Skip to content

Commit

Permalink
feat: module deploy script
Browse files Browse the repository at this point in the history
  • Loading branch information
adamegyed authored and Zer0dot committed Dec 11, 2024
1 parent 0258dfa commit 3393d4a
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 34 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"fmt:check": "forge fmt --check && FOUNDRY_PROFILE=gas forge fmt --check",
"gas": "FOUNDRY_PROFILE=gas forge test -vv",
"gas:check": "FOUNDRY_PROFILE=gas FORGE_SNAPSHOT_CHECK=true forge test -vv",
"initcodehashes": "FOUNDRY_PROFILE=optimized-build forge script GetInitcodeHashScript",
"lcov": "forge coverage --no-match-coverage '(test)' --nmt '(testFuzz|invariant)' --report lcov",
"lint": "pnpm lint:src && pnpm lint:test && pnpm lint:gas && pnpm lint:script",
"lint:src": "solhint --max-warnings 0 -c ./config/solhint-src.json './src/**/*.sol'",
Expand Down
57 changes: 34 additions & 23 deletions script/Artifacts.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,33 @@ abstract contract Artifacts {
address singleSignerValidationModule,
address webAuthnValidationModule,
address owner
) internal returns (AccountFactory) {
return new AccountFactory{salt: salt}(
entryPoint, accountImpl, semiModularImpl, singleSignerValidationModule, webAuthnValidationModule, owner
) internal returns (address) {
return address(
new AccountFactory{salt: salt}(
entryPoint,
accountImpl,
semiModularImpl,
singleSignerValidationModule,
webAuthnValidationModule,
owner
)
);
}

function _getAllowlistModuleInitcode() internal pure returns (bytes memory) {
return type(AllowlistModule).creationCode;
}

function _deployAllowlistModule(bytes32 salt) internal returns (AllowlistModule) {
return new AllowlistModule{salt: salt}();
function _deployAllowlistModule(bytes32 salt) internal returns (address) {
return address(new AllowlistModule{salt: salt}());
}

function _getExecutionInstallDelegateInitcode() internal pure returns (bytes memory) {
return type(ExecutionInstallDelegate).creationCode;
}

function _deployExecutionInstallDelegate(bytes32 salt) internal returns (ExecutionInstallDelegate) {
return new ExecutionInstallDelegate{salt: salt}();
function _deployExecutionInstallDelegate(bytes32 salt) internal returns (address) {
return address(new ExecutionInstallDelegate{salt: salt}());
}

function _getModularAccountInitcode(IEntryPoint entryPoint, ExecutionInstallDelegate executionInstallDelegate)
Expand All @@ -93,24 +100,24 @@ abstract contract Artifacts {
bytes32 salt,
IEntryPoint entryPoint,
ExecutionInstallDelegate executionInstallDelegate
) internal returns (ModularAccount) {
return new ModularAccount{salt: salt}(entryPoint, executionInstallDelegate);
) internal returns (address) {
return address(new ModularAccount{salt: salt}(entryPoint, executionInstallDelegate));
}

function _getNativeTokenLimitModuleInitcode() internal pure returns (bytes memory) {
return type(NativeTokenLimitModule).creationCode;
}

function _deployNativeTokenLimitModule(bytes32 salt) internal returns (NativeTokenLimitModule) {
return new NativeTokenLimitModule{salt: salt}();
function _deployNativeTokenLimitModule(bytes32 salt) internal returns (address) {
return address(new NativeTokenLimitModule{salt: salt}());
}

function _getPaymasterGuardModuleInitcode() internal pure returns (bytes memory) {
return type(PaymasterGuardModule).creationCode;
}

function _deployPaymasterGuardModule(bytes32 salt) internal returns (PaymasterGuardModule) {
return new PaymasterGuardModule{salt: salt}();
function _deployPaymasterGuardModule(bytes32 salt) internal returns (address) {
return address(new PaymasterGuardModule{salt: salt}());
}

function _getSemiModularAccount7702Initcode(
Expand All @@ -126,8 +133,8 @@ abstract contract Artifacts {
bytes32 salt,
IEntryPoint entryPoint,
ExecutionInstallDelegate executionInstallDelegate
) internal returns (SemiModularAccount7702) {
return new SemiModularAccount7702{salt: salt}(entryPoint, executionInstallDelegate);
) internal returns (address) {
return address(new SemiModularAccount7702{salt: salt}(entryPoint, executionInstallDelegate));
}

function _getSemiModularAccountBytecodeInitcode(
Expand All @@ -143,8 +150,8 @@ abstract contract Artifacts {
bytes32 salt,
IEntryPoint entryPoint,
ExecutionInstallDelegate executionInstallDelegate
) internal returns (SemiModularAccountBytecode) {
return new SemiModularAccountBytecode{salt: salt}(entryPoint, executionInstallDelegate);
) internal returns (address) {
return address(new SemiModularAccountBytecode{salt: salt}(entryPoint, executionInstallDelegate));
}

function _getSemiModularAccountStorageOnlyInitcode(
Expand All @@ -160,27 +167,31 @@ abstract contract Artifacts {
bytes32 salt,
IEntryPoint entryPoint,
ExecutionInstallDelegate executionInstallDelegate
) internal returns (SemiModularAccountStorageOnly) {
return new SemiModularAccountStorageOnly{salt: salt}(entryPoint, executionInstallDelegate);
) internal returns (address) {
return address(new SemiModularAccountStorageOnly{salt: salt}(entryPoint, executionInstallDelegate));
}

function _getSingleSignerValidationModuleInitcode() internal pure returns (bytes memory) {
return type(SingleSignerValidationModule).creationCode;
}

function _deploySingleSignerValidationModule(bytes32 salt) internal returns (SingleSignerValidationModule) {
return new SingleSignerValidationModule{salt: salt}();
function _deploySingleSignerValidationModule(bytes32 salt) internal returns (address) {
return address(new SingleSignerValidationModule{salt: salt}());
}

function _getTimeRangeModuleInitcode() internal pure returns (bytes memory) {
return type(TimeRangeModule).creationCode;
}

function _deployTimeRangeModule(bytes32 salt) internal returns (TimeRangeModule) {
return new TimeRangeModule{salt: salt}();
function _deployTimeRangeModule(bytes32 salt) internal returns (address) {
return address(new TimeRangeModule{salt: salt}());
}

function _getWebAuthnValidationModuleInitcode() internal pure returns (bytes memory) {
return type(WebAuthnValidationModule).creationCode;
}

function _deployWebAuthnValidationModule(bytes32 salt) internal returns (address) {
return address(new WebAuthnValidationModule{salt: salt}());
}
}
124 changes: 124 additions & 0 deletions script/DeployModules.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {console} from "forge-std/console.sol";

import {AllowlistModule} from "../src/modules/permissions/AllowlistModule.sol";
import {NativeTokenLimitModule} from "../src/modules/permissions/NativeTokenLimitModule.sol";
import {PaymasterGuardModule} from "../src/modules/permissions/PaymasterGuardModule.sol";

import {TimeRangeModule} from "../src/modules/permissions/TimeRangeModule.sol";
import {SingleSignerValidationModule} from "../src/modules/validation/SingleSignerValidationModule.sol";
import {WebAuthnValidationModule} from "../src/modules/validation/WebAuthnValidationModule.sol";

import {Artifacts} from "./Artifacts.sol";
import {ScriptBase} from "./ScriptBase.sol";

// Deploys all standalone modules.
// - AllowlistModule
// - NativeTokenLimitModule
// - PaymasterGuardModule
// - SingleSignerValidationModule
// - TimeRangeModule
// - WebAuthnValidationModule
contract DeployModulesScript is ScriptBase, Artifacts {
// State vars for expected addresses and salts.

address public expectedAllowlistModuleAddr;
uint256 public allowlistModuleSalt;

address public expectedNativeTokenLimitModuleAddr;
uint256 public nativeTokenLimitModuleSalt;

address public expectedPaymasterGuardModuleAddr;
uint256 public paymasterGuardModuleSalt;

address public expectedSingleSignerValidationModuleAddr;
uint256 public singleSignerValidationModuleSalt;

address public expectedTimeRangeModuleAddr;
uint256 public timeRangeModuleSalt;

address public expectedWebAuthnValidationModuleAddr;
uint256 public webAuthnValidationModuleSalt;

function setUp() public {
// Load the expected addresses and salts from env vars.

expectedAllowlistModuleAddr = vm.envOr("ALLOWLIST_MODULE", address(0));
allowlistModuleSalt = vm.envOr("ALLOWLIST_MODULE_SALT", uint256(0));

expectedNativeTokenLimitModuleAddr = vm.envOr("NATIVE_TOKEN_LIMIT_MODULE", address(0));
nativeTokenLimitModuleSalt = vm.envOr("NATIVE_TOKEN_LIMIT_MODULE_SALT", uint256(0));

expectedPaymasterGuardModuleAddr = vm.envOr("PAYMASTER_GUARD_MODULE", address(0));
paymasterGuardModuleSalt = vm.envOr("PAYMASTER_GUARD_MODULE_SALT", uint256(0));

expectedSingleSignerValidationModuleAddr = vm.envOr("SINGLE_SIGNER_VALIDATION_MODULE", address(0));
singleSignerValidationModuleSalt = vm.envOr("SINGLE_SIGNER_VALIDATION_MODULE_SALT", uint256(0));

expectedTimeRangeModuleAddr = vm.envOr("TIME_RANGE_MODULE", address(0));
timeRangeModuleSalt = vm.envOr("TIME_RANGE_MODULE_SALT", uint256(0));

expectedWebAuthnValidationModuleAddr = vm.envOr("WEBAUTHN_VALIDATION_MODULE", address(0));
webAuthnValidationModuleSalt = vm.envOr("WEBAUTHN_VALIDATION_MODULE_SALT", uint256(0));
}

function run() public onlyProfile("optimized-build"){
console.log("******** Deploying Modules *********");

vm.startBroadcast();

_safeDeploy(
"Allowlist Module",
expectedAllowlistModuleAddr,
allowlistModuleSalt,
_getAllowlistModuleInitcode(),
_deployAllowlistModule
);

_safeDeploy(
"Native Token Limit Module",
expectedNativeTokenLimitModuleAddr,
nativeTokenLimitModuleSalt,
_getNativeTokenLimitModuleInitcode(),
_deployNativeTokenLimitModule
);

_safeDeploy(
"Paymaster Guard Module",
expectedPaymasterGuardModuleAddr,
paymasterGuardModuleSalt,
_getPaymasterGuardModuleInitcode(),
_deployPaymasterGuardModule
);

_safeDeploy(
"Single Signer Validation Module",
expectedSingleSignerValidationModuleAddr,
singleSignerValidationModuleSalt,
_getSingleSignerValidationModuleInitcode(),
_deploySingleSignerValidationModule
);

_safeDeploy(
"Time Range Module",
expectedTimeRangeModuleAddr,
timeRangeModuleSalt,
_getTimeRangeModuleInitcode(),
_deployTimeRangeModule
);

_safeDeploy(
"WebAuthn Validation Module",
expectedWebAuthnValidationModuleAddr,
webAuthnValidationModuleSalt,
_getWebAuthnValidationModuleInitcode(),
_deployWebAuthnValidationModule
);

vm.stopBroadcast();

console.log("******** Modules Deployed *********");
}
}
12 changes: 3 additions & 9 deletions script/GetInitcodeHash.s.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";

import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";
Expand All @@ -10,6 +9,7 @@ import {ModularAccount} from "../src/account/ModularAccount.sol";
import {SemiModularAccountBytecode} from "../src/account/SemiModularAccountBytecode.sol";
import {ExecutionInstallDelegate} from "../src/helpers/ExecutionInstallDelegate.sol";

import {ScriptBase} from "./ScriptBase.sol";
import {Artifacts} from "./Artifacts.sol";

// Logs all initcode hashes from deployment artifacts.
Expand All @@ -31,14 +31,8 @@ import {Artifacts} from "./Artifacts.sol";
// WebAuthnValidationModule, and owner address:
// - AccountFactory

contract GetInitcodeHashScript is Script, Artifacts {
function run() public view {
// Assert that the correct profile is being used.
string memory profile = vm.envOr(string("FOUNDRY_PROFILE"), string(""));

if (keccak256(bytes(profile)) != keccak256("optimized-build")) {
revert("This script should be run with the `optimized-build` profile.");
}
contract GetInitcodeHashScript is ScriptBase, Artifacts {
function run() public view onlyProfile("optimized-build") {

console.log("******** Calculating Initcode Hashes *********");

Expand Down
14 changes: 12 additions & 2 deletions script/DeployScriptBase.sol → script/ScriptBase.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {ScriptBase} from "forge-std/Base.sol";
import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";

import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";

contract DeployScriptBase is ScriptBase {
abstract contract ScriptBase is Script {
modifier onlyProfile(string memory expectedProfile) {
// Assert that the correct profile is being used.
string memory actualProfile = vm.envOr(string("FOUNDRY_PROFILE"), string(""));

if (keccak256(bytes(actualProfile)) != keccak256(bytes(expectedProfile))) {
revert(string.concat("This script should be run with the `", expectedProfile, "` profile."));
}
_;
}

function _safeDeploy(
string memory contractName,
address expectedAddress,
Expand Down
Loading

0 comments on commit 3393d4a

Please sign in to comment.