Skip to content

Commit

Permalink
feat: add factory stake script
Browse files Browse the repository at this point in the history
  • Loading branch information
adamegyed committed Dec 16, 2024
1 parent 5344175 commit 62c24e9
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 13 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ ACCOUNT_FACTORY_SALT=

# Factory staking setup

# Needs a new factory address variable, to address a foundry test suite issue with setEnv
ACCOUNT_FACTORY_TO_STAKE=

# 0.1 ether required by bundlers
REQUIRED_STAKE_AMOUNT_WEI=100000000000000000
# 1 day required by bundlers
Expand Down
83 changes: 83 additions & 0 deletions script/StakeFactory.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";
import {IStakeManager} from "@eth-infinitism/account-abstraction/interfaces/IStakeManager.sol";
import {console} from "forge-std/console.sol";

import {AccountFactory} from "../src/factory/AccountFactory.sol";

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

contract StakeFactoryScript is ScriptBase {
AccountFactory internal _accountFactory;

IEntryPoint internal _entryPoint;

function setUp() public {
_entryPoint = _getEntryPoint();

// Has to use a different env var name to avoid conflicts with the one in DeployFactoryScript, because
// vm.setEnv in tests doesn't isolate and it would result in a race condition.
_accountFactory = AccountFactory(vm.envOr("ACCOUNT_FACTORY_TO_STAKE", address(0)));
}

function run() public {
console.log("******** Staking Account Factory *********");

if (address(_accountFactory) == address(0)) {
console.log("Account Factory not found or invalid");
revert();
}

console.log("Using AccountFactory at address: ", address(_accountFactory));

(uint256 stakeAmountWei, uint256 unstakeDelay) = _getStakeParams();

uint256 stakeNeeded = _checkCurrentStake(stakeAmountWei);

vm.startBroadcast();

_accountFactory.addStake{value: stakeNeeded}(uint32(unstakeDelay));

vm.stopBroadcast();

console.log("******** Done Staking Account Factory *********");
}

function _getStakeParams() internal view returns (uint256 stakeAmountWei, uint256 unstakeDelaySec) {
stakeAmountWei = vm.envOr("REQUIRED_STAKE_AMOUNT_WEI", uint256(0));

if (stakeAmountWei == 0) {
console.log("Env Variable 'REQUIRED_STAKE_AMOUNT_WEI' not found or invalid.");
revert();
}

console.log("Using user-defined stake amount: ", stakeAmountWei);

unstakeDelaySec = vm.envOr("UNSTAKE_DELAY_SEC", uint256(0));

if (unstakeDelaySec == 0) {
console.log("Env Variable 'UNSTAKE_DELAY_SEC' not found or invalid.");
revert();
}

console.log("Using user-defined unstake delay: ", unstakeDelaySec);
}

function _checkCurrentStake(uint256 requiredStakeAmountWei) internal view returns (uint256 stakeNeeded) {
IStakeManager.DepositInfo memory factoryDepositInfo = _entryPoint.getDepositInfo(address(_accountFactory));

uint256 currentStake = factoryDepositInfo.stake;

if (currentStake > requiredStakeAmountWei) {
console.log("Factory already has enough stake: ", currentStake);
stakeNeeded = 0;
} else {
stakeNeeded = requiredStakeAmountWei - currentStake;
console.log("Adding stake to factory: ", stakeNeeded);
}

return stakeNeeded;
}
}
9 changes: 4 additions & 5 deletions test/script/DeployAccounts.s.t.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

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

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

import {DeployAccountsScript} from "../../script/DeployAccounts.s.sol";
import {ModularAccount} from "../../src/account/ModularAccount.sol";

import {SemiModularAccount7702} from "../../src/account/SemiModularAccount7702.sol";
import {SemiModularAccountBytecode} from "../../src/account/SemiModularAccountBytecode.sol";

contract DeployAccountsTest is Test {
import {OptimizedTest} from "../utils/OptimizedTest.sol";

contract DeployAccountsTest is OptimizedTest {
DeployAccountsScript internal _deployAccountsScript;

address public entryPoint;
Expand All @@ -25,7 +24,7 @@ contract DeployAccountsTest is Test {

bytes32 zeroSalt = bytes32(0);

entryPoint = makeAddr("Entrypoint");
entryPoint = address(_deployEntryPoint070());

executionInstallDelegate = makeAddr("ExecutionInstallDelegate");

Expand Down
8 changes: 4 additions & 4 deletions test/script/DeployFactory.s.t.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

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

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

import {DeployFactoryScript} from "../../script/DeployFactory.s.sol";
import {AccountFactory} from "../../src/factory/AccountFactory.sol";

contract DeployFactoryTest is Test {
import {OptimizedTest} from "../utils/OptimizedTest.sol";

contract DeployFactoryTest is OptimizedTest {
DeployFactoryScript internal _deployFactoryScript;

address public entryPoint;
Expand All @@ -25,7 +25,7 @@ contract DeployFactoryTest is Test {

bytes32 zeroSalt = bytes32(0);

entryPoint = makeAddr("Entrypoint");
entryPoint = address(_deployEntryPoint070());
modularAccountImpl = makeAddr("Modular Account Impl");
semiModularAccountBytecodeImpl = makeAddr("Semi Modular Account Bytecode Impl");
singleSignerValidationModule = makeAddr("Single Signer Validation Module");
Expand Down
8 changes: 4 additions & 4 deletions test/script/DeploySmaStorage.s.t.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

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

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

import {DeploySmaStorageScript} from "../../script/DeploySmaStorage.s.sol";
import {SemiModularAccountStorageOnly} from "../../src/account/SemiModularAccountStorageOnly.sol";

contract DeploySmaStorageTest is Test {
import {OptimizedTest} from "../utils/OptimizedTest.sol";

contract DeploySmaStorageTest is OptimizedTest {
DeploySmaStorageScript internal _deploySmaStorageScript;

address public entryPoint;
Expand All @@ -20,7 +20,7 @@ contract DeploySmaStorageTest is Test {

bytes32 zeroSalt = bytes32(0);

entryPoint = makeAddr("Entrypoint");
entryPoint = address(_deployEntryPoint070());

executionInstallDelegate = makeAddr("ExecutionInstallDelegate");

Expand Down
85 changes: 85 additions & 0 deletions test/script/StakeFactory.s.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol";
import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";

import {StakeFactoryScript} from "../../script/StakeFactory.s.sol";
import {AccountFactory} from "../../src/factory/AccountFactory.sol";
import {ExecutionInstallDelegate} from "../../src/helpers/ExecutionInstallDelegate.sol";
import {WebAuthnValidationModule} from "../../src/modules/validation/WebAuthnValidationModule.sol";

import {OptimizedTest} from "../utils/OptimizedTest.sol";

contract StakeFactoryTest is OptimizedTest {
StakeFactoryScript internal _stakeFactoryScript;

EntryPoint internal _entryPoint;

AccountFactory internal _accountFactory;

uint256 internal constant _REQUIRED_STAKE_AMOUNT_WEI = 100_000_000_000_000_000;
uint32 internal constant _UNSTAKE_DELAY_SEC = 86_400;

function setUp() public {
_stakeFactoryScript = new StakeFactoryScript();

_entryPoint = _deployEntryPoint070();

ExecutionInstallDelegate executionInstallDelegate = _deployExecutionInstallDelegate();

_accountFactory = new AccountFactory(
_entryPoint,
_deployModularAccount(_entryPoint, executionInstallDelegate),
_deploySemiModularAccountBytecode(_entryPoint, executionInstallDelegate),
address(_deploySingleSignerValidationModule()),
address(new WebAuthnValidationModule()),
DEFAULT_SENDER
);

vm.setEnv("REQUIRED_STAKE_AMOUNT_WEI", vm.toString(_REQUIRED_STAKE_AMOUNT_WEI));
vm.setEnv("UNSTAKE_DELAY_SEC", vm.toString(_UNSTAKE_DELAY_SEC));
vm.setEnv("ACCOUNT_FACTORY_TO_STAKE", vm.toString(address(_accountFactory)));
}

function test_stakeFactoryScript_fromZero() public {
IEntryPoint.DepositInfo memory factoryDepositInfo = _entryPoint.getDepositInfo(address(_accountFactory));

assertFalse(factoryDepositInfo.staked, "Factory should not be staked");
assertEq(factoryDepositInfo.stake, 0, "Factory Stake should be 0");
assertEq(factoryDepositInfo.unstakeDelaySec, 0, "Factory Unstake Delay should be 0");

_stakeFactoryScript.setUp();

_stakeFactoryScript.run();

factoryDepositInfo = _entryPoint.getDepositInfo(address(_accountFactory));

assertTrue(factoryDepositInfo.staked, "Factory should be staked");
assertEq(factoryDepositInfo.stake, _REQUIRED_STAKE_AMOUNT_WEI, "Factory Stake should be 1000");
assertEq(factoryDepositInfo.unstakeDelaySec, _UNSTAKE_DELAY_SEC, "Factory Unstake Delay should be 86_400");
}

function test_stakeFactoryScript_fromNonZero() public {
vm.prank(DEFAULT_SENDER);
_accountFactory.addStake{value: _REQUIRED_STAKE_AMOUNT_WEI / 2}(uint32(_UNSTAKE_DELAY_SEC / 2));

IEntryPoint.DepositInfo memory factoryDepositInfo = _entryPoint.getDepositInfo(address(_accountFactory));

assertTrue(factoryDepositInfo.staked, "Factory should be staked");
assertEq(factoryDepositInfo.stake, _REQUIRED_STAKE_AMOUNT_WEI / 2, "Factory Stake should be 500");
assertEq(
factoryDepositInfo.unstakeDelaySec, _UNSTAKE_DELAY_SEC / 2, "Factory Unstake Delay should be 43_200"
);

_stakeFactoryScript.setUp();

_stakeFactoryScript.run();

factoryDepositInfo = _entryPoint.getDepositInfo(address(_accountFactory));

assertTrue(factoryDepositInfo.staked, "Factory should be staked");
assertEq(factoryDepositInfo.stake, _REQUIRED_STAKE_AMOUNT_WEI, "Factory Stake should be 1000");
assertEq(factoryDepositInfo.unstakeDelaySec, _UNSTAKE_DELAY_SEC, "Factory Unstake Delay should be 86_400");
}
}

0 comments on commit 62c24e9

Please sign in to comment.