Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DeployInstance script #2

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
GC_RPC=
POLYGON_RPC=
HOLESKY_RPC=
SCROLL_RPC=
INFURA_KEY=
export PRIVATE_KEY=
ETHERSCAN_KEY=
Expand Down
9 changes: 7 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ optimizer_runs = 1_000_000
bytecode_hash = "none"
gas_reports = []
auto_detect_solc = false
solc = "0.8.19"
solc = "0.8.21"
remappings = [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
Expand Down Expand Up @@ -54,19 +54,24 @@ wrap_comments = true
arbitrum = "https://arbitrum-mainnet.infura.io/v3/${INFURA_KEY}"
gnosis = "${GC_RPC}"
goerli = "https://goerli.infura.io/v3/${INFURA_KEY}"
holesky = "${HOLESKY_RPC}"
local = "http://localhost:8545"
mainnet = "https://mainnet.infura.io/v3/${INFURA_KEY}"
optimism = "https://optimism-mainnet.infura.io/v3/${INFURA_KEY}"
polygon = "${POLYGON_RPC}"
scroll = "${SCROLL_RPC}"
sepolia = "https://sepolia.infura.io/v3/${INFURA_KEY}"


[etherscan]
arbitrum = { key = "${ARBISCAN_KEY}", url = "https://api.arbiscan.io/api" }
goerli = { key = "${ETHERSCAN_KEY}", url = "https://api-goerli.etherscan.io/api" }
gnosis = { key = "${GNOSISSCAN_KEY}", url = "https://api.gnosisscan.io/api" }
holesky = { key = "${ETHERSCAN_KEY}", url = "https://api-holesky.etherscan.io/api" }
mainnet = { key = "${ETHERSCAN_KEY}", url = "https://api.etherscan.io/api" }
optimism = { key = "${OPTIMISM_KEY}", url = "https://api-optimistic.etherscan.io/api" }
sepolia = { key = "${ETHERSCAN_KEY}", url = "https://api-sepolia.etherscan.io/api" }
polygon = { key = "${POLYGONSCAN_KEY}", url = "https://api.polygonscan.com/api" }
scroll = { key = "${SCROLLSCAN_KEY}", uril = "https://api.scrollscan.com/api" }
sepolia = { key = "${ETHERSCAN_KEY}", url = "https://api-sepolia.etherscan.io/api" }

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
2 changes: 1 addition & 1 deletion lib/hats-module
117 changes: 87 additions & 30 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,37 @@ pragma solidity ^0.8.19;

import { Script, console2 } from "forge-std/Script.sol";
import { Module } from "../src/Module.sol";
import { HatsModuleFactory } from "hats-module/HatsModuleFactory.sol";

contract Deploy is Script {
Module public implementation;
bytes32 public SALT = bytes32(abi.encode("change this to the value of your choice"));

// default values
abstract contract Deployer is Script {
bool internal _verbose = true;
string internal _version = "0.0.1"; // increment this with each new deployment

/// @dev Override default values, if desired
function prepare(bool verbose, string memory version) public {
_verbose = verbose;
_version = version;
}

/// @dev Set up the deployer via their private key from the environment
function deployer() public returns (address) {
uint256 privKey = vm.envUint("PRIVATE_KEY");
return vm.rememberKey(privKey);
}

function _log(string memory prefix) internal view {
function _log(string memory prefix, address deployed) internal view {
if (_verbose) {
console2.log(string.concat(prefix, "Module:"), address(implementation));
console2.log(string.concat(prefix, "Module:"), deployed);
}
}
}

contract DeployImplementation is Deployer {
bytes32 public SALT = bytes32(abi.encode("change this to the value of your choice"));
Module public implementation;

// default values

string internal _version = "0.1.0"; // increment this with each new deployment

/// @dev Override default values, if desired
function prepare(bool verbose, string memory version) public {
_verbose = verbose;
_version = version;
}

/// @dev Deploy the contract to a deterministic address via forge's create2 deployer factory.
function run() public virtual {
Expand All @@ -46,13 +51,29 @@ contract Deploy is Script {

vm.stopBroadcast();

_log("");
_log("", address(implementation));
}

/* FORGE CLI COMMANDS

## A. Simulate the implementation deployment locally
forge script script/Deploy.s.sol:DeployImplementation -f mainnet

## B. Deploy implementation to real network and verify on etherscan
forge script script/Deploy.s.sol:DeployImplementation -f mainnet --broadcast --verify

## C. Fix verification issues (replace values in curly braces with the actual values)
forge verify-contract --chain-id 1 --num-of-optimizations 1000000 --watch --constructor-args $(cast abi-encode \
"constructor({args})" "{arg1}" "{arg2}" "{argN}" ) \
--compiler-version v0.8.19 {deploymentAddress} \
src/{Counter}.sol:{Counter} --etherscan-api-key $ETHERSCAN_KEY

*/
}

/// @dev Deploy pre-compiled ir-optimized bytecode to a non-deterministic address
contract DeployPrecompiled is Deploy {
/// @dev Update SALT and default values in Deploy contract
contract DeployImplementationPrecompiled is DeployImplementation {
/// @dev Update SALT and default values in DeployImplementation contract

function run() public override {
vm.startBroadcast(deployer());
Expand All @@ -64,24 +85,12 @@ contract DeployPrecompiled is Deploy {

vm.stopBroadcast();

_log("Precompiled ");
_log("Precompiled ", address(implementation));
}
}

/* FORGE CLI COMMANDS

## A. Simulate the deployment locally
forge script script/Deploy.s.sol -f mainnet

## B. Deploy to real network and verify on etherscan
forge script script/Deploy.s.sol -f mainnet --broadcast --verify

## C. Fix verification issues (replace values in curly braces with the actual values)
forge verify-contract --chain-id 1 --num-of-optimizations 1000000 --watch --constructor-args $(cast abi-encode \
"constructor({args})" "{arg1}" "{arg2}" "{argN}" ) \
--compiler-version v0.8.19 {deploymentAddress} \
src/{Counter}.sol:{Counter} --etherscan-api-key $ETHERSCAN_KEY

## D. To verify ir-optimized contracts on etherscan...
1. Run (C) with the following additional flag: `--show-standard-json-input > etherscan.json`
2. Patch `etherscan.json`: `"optimizer":{"enabled":true,"runs":100}` =>
Expand All @@ -91,3 +100,51 @@ forge verify-contract --chain-id 1 --num-of-optimizations 1000000 --watch --cons
See this github issue for more: https://github.com/foundry-rs/foundry/issues/3507#issuecomment-1465382107

*/

/// @dev Deploy an instance of the implementation
contract DeployInstance is Deployer {
HatsModuleFactory public factory = HatsModuleFactory(0xfE661c01891172046feE16D3a57c3Cf456729efA);
bytes32 public SALT = bytes32(abi.encode("change this to the value of your choice"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in use here

address public implementation;
address public instance;
uint256 public hatId;

// default immutable args

// default init args

/// @dev Override default values, if desired
function prepare(bool verbose, address _implementation, uint256 _hatId) public virtual {
_verbose = verbose;
implementation = _implementation;
hatId = _hatId;
}

/// @dev Deploy the contract to a deterministic address via forge's create2 deployer factory.
function run() public virtual returns (address) {
vm.startBroadcast(deployer());

instance = factory.createHatsModule(
implementation,
hatId,
abi.encodePacked( /* insert other immutable args here */ ),
abi.encode( /* insert init args here */ )
);

vm.stopBroadcast();

_log("", instance);

return instance;
}

/* FORGE CLI COMMANDS

## E. Simulate the instance deployment locally
forge script script/Deploy.s.sol:DeployImplementation -f mainnet

## F. Deploy instance to real network and verify on etherscan
forge script script/Deploy.s.sol:DeployImplementation -f mainnet --broadcast --verify

*/
}
37 changes: 18 additions & 19 deletions test/Module.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@ pragma solidity ^0.8.19;

import { Test, console2 } from "forge-std/Test.sol";
import { Module } from "../src/Module.sol";
import { Deploy, DeployPrecompiled } from "../script/Deploy.s.sol";
import {
HatsModuleFactory, IHats, deployModuleInstance, deployModuleFactory
} from "hats-module/utils/DeployFunctions.sol";
import { DeployImplementation, DeployImplementationPrecompiled, DeployInstance } from "../script/Deploy.s.sol";
// import {
// HatsModuleFactory, IHats, deployModuleInstance, deployModuleFactory
// } from "hats-module/utils/DeployFunctions.sol";
import { IHats } from "hats-protocol/Interfaces/IHats.sol";

contract ModuleTest is Deploy, Test {
contract ModuleTest is DeployImplementation, Test {
/// @dev Inherit from DeployPrecompiled instead of Deploy if working with pre-compiled contracts

/// @dev variables inhereted from Deploy script
/// @dev variables inhereted from DeployImplementation script
// Module public implementation;
// bytes32 public SALT;

uint256 public fork;
uint256 public BLOCK_NUMBER = 17_671_864; // deployment block for Hats.sol
uint256 public BLOCK_NUMBER = 18_265_600; // after HatsModuleFactory deployment block
IHats public HATS = IHats(0x3bc1A0Ad72417f2d411118085256fC53CBdDd137); // v1.hatsprotocol.eth
HatsModuleFactory public factory;
DeployInstance public deployInstance;
Module public instance;
bytes public otherImmutableArgs;
bytes public initArgs;
uint256 public hatId;

string public MODULE_VERSION;
Expand All @@ -34,9 +32,6 @@ contract ModuleTest is Deploy, Test {
// deploy implementation via the script
prepare(false, MODULE_VERSION);
run();

// deploy the hats module factory
factory = deployModuleFactory(HATS, SALT, "test factory");
}
}

Expand All @@ -46,14 +41,18 @@ contract WithInstanceTest is ModuleTest {

// set up the hats

// set up the other immutable args
otherImmutableArgs = abi.encodePacked();
// set up the other immutable args (if necessary)

// set up the init args (if necessary)

// deploy the DeployInstance script
deployInstance = new DeployInstance();

// set up the init args
initArgs = abi.encode();
// prepare the script with the necessary args
deployInstance.prepare(false, address(implementation), hatId);

// deploy an instance of the module
instance = Module(deployModuleInstance(factory, address(implementation), hatId, otherImmutableArgs, initArgs));
// run the script to deploy an instance of the module
instance = Module(deployInstance.run());
}
}

Expand Down