-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
♻️ isolate the two factory scenarios
This commit move the multi-step deployment scenario to a specific contract that inherits from the original one (the one-step deployment scenario).
- Loading branch information
Showing
9 changed files
with
117 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-License-Identifier: APACHE-2.0 | ||
pragma solidity >=0.8.19 <0.9.0; | ||
|
||
import { AccountFactoryMultiSteps } from "src/AccountFactoryMultiSteps.sol"; | ||
import { BaseScript } from "../Base.s.sol"; | ||
|
||
/// @title Deploy an AccountFactoryMultiSteps | ||
/// @dev You can pass environment variables to this script to tailor the deployment. | ||
/// Do not deploy this script in production without changing the default values! | ||
contract AccountFactoryMultiStepsDeploy is BaseScript { | ||
// This is currently the universal address of the 4337 entrypoint | ||
address internal constant ENTRYPOINT = 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789; | ||
// This is the first account exposed by Anvil | ||
address internal constant NAME_SERVICE_OWNER = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; | ||
|
||
function run() public broadcast returns (AccountFactoryMultiSteps) { | ||
address entrypoint = vm.envOr("ENTRYPOINT", ENTRYPOINT); | ||
address webAuthnVerifier = vm.envOr("WEBAUTHN_VERIFIER", address(0)); | ||
address nameServiceOwner = vm.envOr("NAME_SERVICE_OWNER", NAME_SERVICE_OWNER); | ||
|
||
return new AccountFactoryMultiSteps(entrypoint, webAuthnVerifier, nameServiceOwner); | ||
} | ||
} | ||
|
||
/* | ||
ℹ️ HOW TO USE THIS SCRIPT USING A LEDGER: | ||
forge script AccountFactoryMultiStepsDeploy --rpc-url <RPC_URL> --ledger --sender <ACCOUNT_ADDRESS> [--broadcast] | ||
ℹ️ HOW TO USE THIS SCRIPT WITH AN ARBITRARY PRIVATE KEY (NOT RECOMMENDED): | ||
PRIVATE_KEY=<PRIVATE_KEY> forge script AccountFactoryMultiStepsDeploy --rpc-url <RPC_URL> [--broadcast] | ||
ℹ️ HOW TO USE THIS SCRIPT ON ANVIL IN DEFAULT MODE: | ||
forge script AccountFactoryMultiStepsDeploy --rpc-url http://127.0.0.1:8545 --broadcast --sender \ | ||
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --mnemonics "test test test test test test test test test test test junk" | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity >=0.8.20 <0.9.0; | ||
|
||
import { AccountFactory, Account, ERC1967Proxy } from "./AccountFactory.sol"; | ||
|
||
/// @title Multi-seps 4337-compliant Account Factory | ||
/// @notice This contract inherits from the AccountFactory contract and adds a multi-steps scenario. | ||
/// @custom:experimental This is an experimental contract. | ||
contract AccountFactoryMultiSteps is AccountFactory { | ||
event AccountCreated(bytes32 loginHash, address account); | ||
|
||
/// @notice Deploy the implementation of the account and store its address in the storage of the factory. This | ||
/// implementation will be used as the implementation reference | ||
/// for all the proxies deployed by this factory. | ||
/// @param entryPoint The unique address of the entrypoint (EIP-4337 related) | ||
/// @param webAuthnVerifier The address of the crypto library that will be used by | ||
/// the account to verify the WebAuthn signature of the signer(s) | ||
/// @param _nameServiceOwner The address used to verify the signature of the name service. | ||
/// This address is stored in the storage of this contract that validate future signatures | ||
/// @dev The account deployed here is expected to be proxied later, its own storage won't be used. | ||
/// All the arguments passed to the constructor function are used to set immutable variables. | ||
/// As a valid signature from the nameServiceOwner is required to set the first signer of the account, | ||
/// there is no need to make the account inoperable. No one will be able to use it. | ||
constructor( | ||
address entryPoint, | ||
address webAuthnVerifier, | ||
address _nameServiceOwner | ||
) | ||
AccountFactory(entryPoint, webAuthnVerifier, _nameServiceOwner) | ||
{ } | ||
|
||
/// @notice This is the multi-steps scenario. This function either deploys an account or returns the address of | ||
/// an existing account based on the parameter given. In any case this function set the first signer. | ||
/// @param loginHash The keccak256 hash of the login of the account | ||
/// @return The address of the account (either deployed or not) | ||
function createAccount(bytes32 loginHash) external returns (address) { | ||
// check if the account is already deployed and return prematurely if it is | ||
address alreadyDeployedAddress = _checkAccountExistence(loginHash); | ||
if (alreadyDeployedAddress != address(0)) { | ||
return alreadyDeployedAddress; | ||
} | ||
|
||
// deploy the proxy for the user. During the deployment call, the | ||
// initialize function in the implementation contract is called | ||
// using the `delegatecall` opcode | ||
Account account = Account( | ||
payable( | ||
new ERC1967Proxy{ salt: loginHash }( | ||
address(accountImplementation), abi.encodeCall(Account.initialize, (loginHash)) | ||
) | ||
) | ||
); | ||
|
||
emit AccountCreated(loginHash, address(account)); | ||
|
||
return address(account); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
AccountFactoryDeterministicDeployment | ||
├── when using the createAccount flow | ||
│ └── it should deploy the account to the same address calculated by getAddress | ||
├── when using the createAccountAndInt flow | ||
├── when using the createAccountAndInit flow | ||
│ └── it should deploy the account to the same address calculated by getAddress | ||
└── when using both flows with the same parameters | ||
└── it should deploy the account to the same address |
8 changes: 4 additions & 4 deletions
8
test/unit/AccountFactory/createAccount.t.sol → ...ountFactoryMultiSteps/createAccount.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.