-
Notifications
You must be signed in to change notification settings - Fork 27
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
chore: [v0.8-develop] alpha.0 deploy prep #111
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
|
||
# Factory owner capable only of managing stake | ||
OWNER= | ||
# EP 0.7 address | ||
ENTRYPOINT= | ||
|
||
# Create2 expected addresses of the contracts. | ||
# When running for the first time, the error message will contain the expected addresses. | ||
ACCOUNT_IMPL= | ||
FACTORY= | ||
SINGLE_SIGNER_VALIDATION= | ||
|
||
# Optional, defaults to bytes32(0) | ||
ACCOUNT_IMPL_SALT= | ||
FACTORY_SALT= | ||
SINGLE_SIGNER_VALIDATION_SALT= | ||
|
||
# Optional, defaults to 0.1 ether and 1 day, respectively | ||
STAKE_AMOUNT= | ||
UNSTAKE_DELAY= |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,6 @@ node_modules/ | |
# Coverage | ||
report/ | ||
lcov.info | ||
|
||
# env vars | ||
.env |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.25; | ||
|
||
import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol"; | ||
import {Script} from "forge-std/Script.sol"; | ||
import {console2} from "forge-std/Test.sol"; | ||
|
||
import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; | ||
|
||
import {AccountFactory} from "../src/account/AccountFactory.sol"; | ||
import {UpgradeableModularAccount} from "../src/account/UpgradeableModularAccount.sol"; | ||
import {SingleSignerValidation} from "../src/modules/validation/SingleSignerValidation.sol"; | ||
|
||
contract DeployScript is Script { | ||
IEntryPoint public entryPoint = IEntryPoint(payable(vm.envAddress("ENTRYPOINT"))); | ||
|
||
address public owner = vm.envAddress("OWNER"); | ||
|
||
address public accountImpl = vm.envOr("ACCOUNT_IMPL", address(0)); | ||
address public factory = vm.envOr("FACTORY", address(0)); | ||
address public singleSignerValidation = vm.envOr("SINGLE_SIGNER_VALIDATION", address(0)); | ||
|
||
bytes32 public accountImplSalt = bytes32(vm.envOr("ACCOUNT_IMPL_SALT", uint256(0))); | ||
bytes32 public factorySalt = bytes32(vm.envOr("FACTORY_SALT", uint256(0))); | ||
bytes32 public singleSignerValidationSalt = bytes32(vm.envOr("SINGLE_SIGNER_VALIDATION_SALT", uint256(0))); | ||
|
||
uint256 public requiredStakeAmount = vm.envOr("STAKE_AMOUNT", uint256(0.1 ether)); | ||
uint256 public requiredUnstakeDelay = vm.envOr("UNSTAKE_DELAY", uint256(1 days)); | ||
|
||
function run() public { | ||
console2.log("******** Deploying ERC-6900 Reference Implementation ********"); | ||
console2.log("Chain: ", block.chainid); | ||
console2.log("EP: ", address(entryPoint)); | ||
console2.log("Factory owner: ", owner); | ||
|
||
_deployAccountImpl(accountImplSalt, accountImpl); | ||
_deploySingleSignerValidation(singleSignerValidationSalt, singleSignerValidation); | ||
_deployAccountFactory(factorySalt, factory); | ||
_addStakeForFactory(uint32(requiredUnstakeDelay), requiredStakeAmount); | ||
} | ||
|
||
function _deployAccountImpl(bytes32 salt, address expected) internal { | ||
console2.log(string.concat("Deploying AccountImpl with salt: ", vm.toString(salt))); | ||
|
||
address addr = Create2.computeAddress( | ||
salt, keccak256(abi.encodePacked(type(UpgradeableModularAccount).creationCode, abi.encode(entryPoint))) | ||
); | ||
if (addr != expected) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if this is necessary in RI. It is gonna make test deployment annoying as you will need to compute all the addresses first and put them in env (account impl, validation, etc.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's just to prevent accidental drift between when it's calculated vs deployed, which can happen if using the wrong build profile, for example. For the first time pass, we can just run the script, and the error in |
||
console2.log("Expected address mismatch"); | ||
console2.log("Expected: ", expected); | ||
console2.log("Actual: ", addr); | ||
revert(); | ||
} | ||
|
||
if (addr.code.length == 0) { | ||
console2.log("No code found at expected address, deploying..."); | ||
UpgradeableModularAccount deployed = new UpgradeableModularAccount{salt: salt}(entryPoint); | ||
|
||
if (address(deployed) != expected) { | ||
console2.log("Deployed address mismatch"); | ||
console2.log("Expected: ", expected); | ||
console2.log("Deployed: ", address(deployed)); | ||
revert(); | ||
} | ||
|
||
console2.log("Deployed AccountImpl at: ", address(deployed)); | ||
} else { | ||
console2.log("Code found at expected address, skipping deployment"); | ||
} | ||
} | ||
|
||
function _deploySingleSignerValidation(bytes32 salt, address expected) internal { | ||
console2.log(string.concat("Deploying SingleSignerValidation with salt: ", vm.toString(salt))); | ||
|
||
address addr = | ||
Create2.computeAddress(salt, keccak256(abi.encodePacked(type(SingleSignerValidation).creationCode))); | ||
if (addr != expected) { | ||
console2.log("Expected address mismatch"); | ||
console2.log("Expected: ", expected); | ||
console2.log("Actual: ", addr); | ||
revert(); | ||
} | ||
|
||
if (addr.code.length == 0) { | ||
console2.log("No code found at expected address, deploying..."); | ||
SingleSignerValidation deployed = new SingleSignerValidation{salt: salt}(); | ||
|
||
if (address(deployed) != expected) { | ||
console2.log("Deployed address mismatch"); | ||
console2.log("Expected: ", expected); | ||
console2.log("Deployed: ", address(deployed)); | ||
revert(); | ||
} | ||
|
||
console2.log("Deployed SingleSignerValidation at: ", address(deployed)); | ||
} else { | ||
console2.log("Code found at expected address, skipping deployment"); | ||
} | ||
} | ||
|
||
function _deployAccountFactory(bytes32 salt, address expected) internal { | ||
console2.log(string.concat("Deploying AccountFactory with salt: ", vm.toString(salt))); | ||
|
||
address addr = Create2.computeAddress( | ||
salt, | ||
keccak256( | ||
abi.encodePacked( | ||
type(AccountFactory).creationCode, | ||
abi.encode(entryPoint, accountImpl, singleSignerValidation, owner) | ||
) | ||
) | ||
); | ||
if (addr != expected) { | ||
console2.log("Expected address mismatch"); | ||
console2.log("Expected: ", expected); | ||
console2.log("Actual: ", addr); | ||
revert(); | ||
} | ||
|
||
if (addr.code.length == 0) { | ||
console2.log("No code found at expected address, deploying..."); | ||
AccountFactory deployed = new AccountFactory{salt: salt}( | ||
entryPoint, UpgradeableModularAccount(payable(accountImpl)), singleSignerValidation, owner | ||
); | ||
|
||
if (address(deployed) != expected) { | ||
console2.log("Deployed address mismatch"); | ||
console2.log("Expected: ", expected); | ||
console2.log("Deployed: ", address(deployed)); | ||
revert(); | ||
} | ||
|
||
console2.log("Deployed AccountFactory at: ", address(deployed)); | ||
} else { | ||
console2.log("Code found at expected address, skipping deployment"); | ||
} | ||
} | ||
|
||
function _addStakeForFactory(uint32 unstakeDelay, uint256 stakeAmount) internal { | ||
console2.log("Adding stake to factory"); | ||
|
||
uint256 currentStake = entryPoint.getDepositInfo(address(factory)).stake; | ||
console2.log("Current stake: ", currentStake); | ||
uint256 stakeToAdd = stakeAmount - currentStake; | ||
|
||
if (stakeToAdd > 0) { | ||
console2.log("Adding stake: ", stakeToAdd); | ||
entryPoint.addStake{value: stakeToAdd}(unstakeDelay); | ||
console2.log("Staked factory: ", address(factory)); | ||
console2.log("Total stake amount: ", entryPoint.getDepositInfo(address(factory)).stake); | ||
console2.log("Unstake delay: ", entryPoint.getDepositInfo(address(factory)).unstakeDelaySec); | ||
} else { | ||
console2.log("No stake to add"); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.25; | ||
|
||
import {Test} from "forge-std/Test.sol"; | ||
|
||
import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol"; | ||
import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; | ||
|
||
import {DeployScript} from "../../script/Deploy.s.sol"; | ||
|
||
import {AccountFactory} from "../../src/account/AccountFactory.sol"; | ||
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; | ||
import {SingleSignerValidation} from "../../src/modules/validation/SingleSignerValidation.sol"; | ||
|
||
contract DeployTest is Test { | ||
DeployScript internal _deployScript; | ||
|
||
EntryPoint internal _entryPoint; | ||
|
||
address internal _owner; | ||
|
||
address internal _accountImpl; | ||
address internal _singleSignerValidation; | ||
address internal _factory; | ||
|
||
function setUp() public { | ||
_entryPoint = new EntryPoint(); | ||
_owner = makeAddr("OWNER"); | ||
|
||
vm.setEnv("ENTRYPOINT", vm.toString(address(_entryPoint))); | ||
vm.setEnv("OWNER", vm.toString(_owner)); | ||
|
||
// Create1 derivation of the 2nd address deployed | ||
address deployScriptAddr = address(0x2e234DAe75C793f67A35089C9d99245E1C58470b); | ||
|
||
_accountImpl = Create2.computeAddress( | ||
bytes32(0), | ||
keccak256( | ||
abi.encodePacked(type(UpgradeableModularAccount).creationCode, abi.encode(address(_entryPoint))) | ||
), | ||
deployScriptAddr | ||
); | ||
|
||
_singleSignerValidation = Create2.computeAddress( | ||
bytes32(0), keccak256(abi.encodePacked(type(SingleSignerValidation).creationCode)), deployScriptAddr | ||
); | ||
|
||
_factory = Create2.computeAddress( | ||
bytes32(0), | ||
keccak256( | ||
abi.encodePacked( | ||
type(AccountFactory).creationCode, | ||
abi.encode(address(_entryPoint), _accountImpl, _singleSignerValidation, _owner) | ||
) | ||
), | ||
deployScriptAddr | ||
); | ||
|
||
vm.setEnv("ACCOUNT_IMPL", vm.toString(address(_accountImpl))); | ||
vm.setEnv("FACTORY", vm.toString(address(_factory))); | ||
vm.setEnv("SINGLE_SIGNER_VALIDATION", vm.toString(address(_singleSignerValidation))); | ||
|
||
vm.setEnv("ACCOUNT_IMPL_SALT", vm.toString(uint256(0))); | ||
vm.setEnv("FACTORY_SALT", vm.toString(uint256(0))); | ||
vm.setEnv("SINGLE_SIGNER_VALIDATION_SALT", vm.toString(uint256(0))); | ||
|
||
_deployScript = new DeployScript(); | ||
|
||
vm.deal(address(_deployScript), 0.1 ether); | ||
} | ||
|
||
function test_deployScript_run() public { | ||
_deployScript.run(); | ||
|
||
assertTrue(_accountImpl.code.length > 0); | ||
assertTrue(_factory.code.length > 0); | ||
assertTrue(_singleSignerValidation.code.length > 0); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we update readme for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add .env.example too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added both a
.env.example
with comments, and a section in the README for running the script.