Skip to content

Commit

Permalink
feat: initial implementation of factory deploy script
Browse files Browse the repository at this point in the history
  • Loading branch information
Zer0dot committed Dec 9, 2024
1 parent 9996f22 commit db63642
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 16 deletions.
134 changes: 134 additions & 0 deletions script/DeployFactory.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

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

import {ModularAccount} from "../src/account/ModularAccount.sol";
import {SemiModularAccountBytecode} from "../src/account/SemiModularAccountBytecode.sol";
import {Artifacts} from "./Artifacts.sol";
import {ScriptBase} from "./ScriptBase.sol";
import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";

// Deploys the Account Factory. This requires the following env vars to be set:
// - ENTRY_POINT
// - MODULAR_ACCOUNT_IMPL
// - SEMI_MODULAR_ACCOUNT_BYTECODE_IMPL
// - SINGLE_SIGNER_VALIDATION_MODULE
// - WEBAUTHN_VALIDATION_MODULE
// - FACTORY_OWNER
contract DeployFactoryScript is ScriptBase, Artifacts {
// State vars for expected addresses and salts.

address public expectedFactoryAddr;
uint256 public factorySalt;

// State vars for factory dependencies

IEntryPoint public entryPoint;
ModularAccount public modularAccountImpl;
SemiModularAccountBytecode public semiModularAccountBytecodeImpl;
address public singleSignerValidationModule;
address public webAuthnValidationModule;
address public factoryOwner;

function setUp() public {
// Load the required addresses for the factory deployment from env vars.
entryPoint = _getEntryPoint();
modularAccountImpl = _getModularAccountImpl();
semiModularAccountBytecodeImpl = _getSemiModularAccountBytecodeImpl();
singleSignerValidationModule = _getSingleSignerValidationModule();
webAuthnValidationModule = _getWebAuthnValidationModule();
factoryOwner = _getFactoryOwner();

// Load the expected address and salt from env vars.
expectedFactoryAddr = vm.envOr("FACTORY", address(0));
factorySalt = vm.envOr("FACTORY_SALT", uint256(0));
}

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

vm.startBroadcast();

_safeDeploy(
"Account Factory",
expectedFactoryAddr,
factorySalt,
_getAccountFactoryInitcode(
entryPoint,
modularAccountImpl,
semiModularAccountBytecodeImpl,
singleSignerValidationModule,
webAuthnValidationModule,
factoryOwner
),
_deployFactory
);

vm.stopBroadcast();

console.log("******** Factory Deployed *********");
}

// Wrapper function to be called within _safeDeploy using the context in this contract.
function _deployFactory(bytes32 salt) internal returns (address) {
_ensureNonzeroFactoryArgs();
return _deployAccountFactory(
salt,
entryPoint,
modularAccountImpl,
semiModularAccountBytecodeImpl,
singleSignerValidationModule,
webAuthnValidationModule,
factoryOwner
);
}

function _ensureNonzeroFactoryArgs() internal view {
bool shouldRevert;
if (address(modularAccountImpl) == address(0)) {
console.log("Env Variable 'MODULAR_ACCOUNT_IMPL' not found or invalid during factory deployment");
shouldRevert = true;
} else {
console.log("Using user-defined ModularAccount at: %x", address(modularAccountImpl));
}

if (address(semiModularAccountBytecodeImpl) == address(0)) {
console.log(
"Env Variable 'SEMI_MODULAR_ACCOUNT_BYTECODE_IMPL' not found or invalid during factory deployment"
);
shouldRevert = true;
} else {
console.log(
"Using user-defined SemiModularAccountBytecode at: %x", address(semiModularAccountBytecodeImpl)
);
}

if (singleSignerValidationModule == address(0)) {
console.log(
"Env Variable 'SINGLE_SIGNER_VALIDATION_MODULE' not found or invalid during factory deployment"
);
shouldRevert = true;
} else {
console.log("Using user-defined SingleSignerValidationModule at: %x", singleSignerValidationModule);
}

if (webAuthnValidationModule == address(0)) {
console.log("Env Variable 'WEBAUTHN_VALIDATION_MODULE' not found or invalid during factory deployment");
shouldRevert = true;
} else {
console.log("Using user-defined WebAuthnValidationModule at: %x", webAuthnValidationModule);
}

if (factoryOwner == address(0)) {
console.log("Env Variable 'FACTORY_OWNER' not found or invalid during factory deployment");
shouldRevert = true;
} else {
console.log("Using user-defined factory owner at: %x", factoryOwner);
}

if (shouldRevert) {
revert("Missing or invalid env variables during factory deployment");
}
}
}
23 changes: 7 additions & 16 deletions script/GetInitcodeHash.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,8 @@ contract GetInitcodeHashScript is ScriptBase, Artifacts {
console.log("- WebAuthnValidationModule: %x", uint256(keccak256(_getWebAuthnValidationModuleInitcode())));

console.log("Artifact initcode hashes with dependencies on EntryPoint and ExecutionInstallDelegate:");
IEntryPoint entryPoint = IEntryPoint(payable(vm.envOr("ENTRYPOINT", address(0))));
if (address(entryPoint) == address(0)) {
console.log(
"Env Variable 'ENTRYPOINT' not found or invalid, defaulting to v0.7 EntryPoint at "
"0x0000000071727De22E5E9d8BAf0edAc6f37da032"
);
entryPoint = IEntryPoint(0x0000000071727De22E5E9d8BAf0edAc6f37da032);
} else {
console.log("Using user-defined EntryPoint at: %x", address(entryPoint));
}
IEntryPoint entryPoint = _getEntryPoint(); //IEntryPoint(payable(vm.envOr("ENTRYPOINT", address(0))));

ExecutionInstallDelegate executionInstallDelegate =
ExecutionInstallDelegate(vm.envOr("EXECUTION_INSTALL_DELEGATE", address(0)));

Expand Down Expand Up @@ -93,12 +85,11 @@ contract GetInitcodeHashScript is ScriptBase, Artifacts {
"WebAuthnValidationModule, and owner address:"
);

ModularAccount modularAccountImpl = ModularAccount(payable(vm.envOr("MODULAR_ACCOUNT_IMPL", address(0))));
SemiModularAccountBytecode semiModularImpl =
SemiModularAccountBytecode(payable(vm.envOr("SEMI_MODULAR_ACCOUNT_BYTECODE_IMPL", address(0))));
address singleSignerValidationModule = vm.envOr("SINGLE_SIGNER_VALIDATION_MODULE", address(0));
address webAuthnValidationModule = vm.envOr("WEBAUTHN_VALIDATION_MODULE", address(0));
address factoryOwner = vm.envOr("FACTORY_OWNER", address(0));
ModularAccount modularAccountImpl = _getModularAccountImpl();
SemiModularAccountBytecode semiModularImpl = _getSemiModularAccountBytecodeImpl();
address singleSignerValidationModule = _getSingleSignerValidationModule();
address webAuthnValidationModule = _getWebAuthnValidationModule();
address factoryOwner = _getFactoryOwner();

if (address(modularAccountImpl) == address(0)) {
console.log(
Expand Down
38 changes: 38 additions & 0 deletions script/ScriptBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ pragma solidity ^0.8.26;
import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";

import {ModularAccount} from "../src/account/ModularAccount.sol";
import {SemiModularAccountBytecode} from "../src/account/SemiModularAccountBytecode.sol";
import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";
import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";

abstract contract ScriptBase is Script {
Expand All @@ -17,6 +20,41 @@ abstract contract ScriptBase is Script {
_;
}

function _getEntryPoint() internal view returns (IEntryPoint) {
IEntryPoint entryPoint = IEntryPoint(payable(vm.envOr("ENTRYPOINT", address(0))));
if (address(entryPoint) == address(0)) {
console.log(
"Env Variable 'ENTRYPOINT' not found or invalid, defaulting to v0.7 EntryPoint at "
"0x0000000071727De22E5E9d8BAf0edAc6f37da032"
);
entryPoint = IEntryPoint(0x0000000071727De22E5E9d8BAf0edAc6f37da032);
} else {
console.log("Using user-defined EntryPoint at: %x", address(entryPoint));
}

return entryPoint;
}

function _getModularAccountImpl() internal view returns (ModularAccount) {
return ModularAccount(payable(vm.envOr("MODULAR_ACCOUNT_IMPL", address(0))));
}

function _getSemiModularAccountBytecodeImpl() internal view returns (SemiModularAccountBytecode) {
return SemiModularAccountBytecode(payable(vm.envOr("SEMI_MODULAR_ACCOUNT_BYTECODE_IMPL", address(0))));
}

function _getSingleSignerValidationModule() internal view returns (address) {
return vm.envOr("SINGLE_SIGNER_VALIDATION_MODULE", address(0));
}

function _getWebAuthnValidationModule() internal view returns (address) {
return vm.envOr("WEBAUTHN_VALIDATION_MODULE", address(0));
}

function _getFactoryOwner() internal view returns (address) {
return vm.envOr("FACTORY_OWNER", address(0));
}

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

0 comments on commit db63642

Please sign in to comment.