Skip to content

Commit e23a856

Browse files
committed
feat: add proper SMA support to factory
1 parent 05fe78f commit e23a856

File tree

5 files changed

+78
-8
lines changed

5 files changed

+78
-8
lines changed

script/Deploy.s.sol

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {Script, console} from "forge-std/Script.sol";
77
import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
88

99
import {AccountFactory} from "../src/account/AccountFactory.sol";
10+
11+
import {SemiModularAccount} from "../src/account/SemiModularAccount.sol";
1012
import {UpgradeableModularAccount} from "../src/account/UpgradeableModularAccount.sol";
1113
import {SingleSignerValidation} from "../src/modules/validation/SingleSignerValidation.sol";
1214

@@ -16,10 +18,12 @@ contract DeployScript is Script {
1618
address public owner = vm.envAddress("OWNER");
1719

1820
address public accountImpl = vm.envOr("ACCOUNT_IMPL", address(0));
21+
address public semiModularAccountImpl = vm.envOr("SMA_IMPL", address(0));
1922
address public factory = vm.envOr("FACTORY", address(0));
2023
address public singleSignerValidation = vm.envOr("SINGLE_SIGNER_VALIDATION", address(0));
2124

2225
bytes32 public accountImplSalt = bytes32(vm.envOr("ACCOUNT_IMPL_SALT", uint256(0)));
26+
bytes32 public semiModularAccountImplSalt = bytes32(vm.envOr("SMA_IMPL_SALT", uint256(0)));
2327
bytes32 public factorySalt = bytes32(vm.envOr("FACTORY_SALT", uint256(0)));
2428
bytes32 public singleSignerValidationSalt = bytes32(vm.envOr("SINGLE_SIGNER_VALIDATION_SALT", uint256(0)));
2529

@@ -34,6 +38,7 @@ contract DeployScript is Script {
3438

3539
vm.startBroadcast();
3640
_deployAccountImpl(accountImplSalt, accountImpl);
41+
_deploySemiModularAccountImpl(semiModularAccountImplSalt, semiModularAccountImpl);
3742
_deploySingleSignerValidation(singleSignerValidationSalt, singleSignerValidation);
3843
_deployAccountFactory(factorySalt, factory);
3944
_addStakeForFactory(uint32(requiredUnstakeDelay), requiredStakeAmount);
@@ -72,6 +77,38 @@ contract DeployScript is Script {
7277
}
7378
}
7479

80+
function _deploySemiModularAccountImpl(bytes32 salt, address expected) internal {
81+
console.log(string.concat("Deploying SemiModularAccountImpl with salt: ", vm.toString(salt)));
82+
83+
address addr = Create2.computeAddress(
84+
salt,
85+
keccak256(abi.encodePacked(type(SemiModularAccount).creationCode, abi.encode(entryPoint))),
86+
CREATE2_FACTORY
87+
);
88+
if (addr != expected) {
89+
console.log("Expected address mismatch");
90+
console.log("Expected: ", expected);
91+
console.log("Actual: ", addr);
92+
revert();
93+
}
94+
95+
if (addr.code.length == 0) {
96+
console.log("No code found at expected address, deploying...");
97+
SemiModularAccount deployed = new SemiModularAccount{salt: salt}(entryPoint);
98+
99+
if (address(deployed) != expected) {
100+
console.log("Deployed address mismatch");
101+
console.log("Expected: ", expected);
102+
console.log("Deployed: ", address(deployed));
103+
revert();
104+
}
105+
106+
console.log("Deployed SemiModularAccount at: ", address(deployed));
107+
} else {
108+
console.log("Code found at expected address, skipping deployment");
109+
}
110+
}
111+
75112
function _deploySingleSignerValidation(bytes32 salt, address expected) internal {
76113
console.log(string.concat("Deploying SingleSignerValidation with salt: ", vm.toString(salt)));
77114

@@ -110,7 +147,7 @@ contract DeployScript is Script {
110147
keccak256(
111148
abi.encodePacked(
112149
type(AccountFactory).creationCode,
113-
abi.encode(entryPoint, accountImpl, singleSignerValidation, owner)
150+
abi.encode(entryPoint, accountImpl, semiModularAccountImpl, singleSignerValidation, owner)
114151
)
115152
),
116153
CREATE2_FACTORY
@@ -124,8 +161,13 @@ contract DeployScript is Script {
124161

125162
if (addr.code.length == 0) {
126163
console.log("No code found at expected address, deploying...");
164+
// Patched
127165
AccountFactory deployed = new AccountFactory{salt: salt}(
128-
entryPoint, UpgradeableModularAccount(payable(accountImpl)), singleSignerValidation, owner
166+
entryPoint,
167+
UpgradeableModularAccount(payable(accountImpl)),
168+
SemiModularAccount(payable(semiModularAccountImpl)),
169+
singleSignerValidation,
170+
owner
129171
);
130172

131173
if (address(deployed) != expected) {

src/account/AccountFactory.sol

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,30 @@ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.s
88
import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
99

1010
import {UpgradeableModularAccount} from "../account/UpgradeableModularAccount.sol";
11+
import {SemiModularAccount} from "../account/SemiModularAccount.sol";
1112
import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
1213

1314
import {LibClone} from "solady/utils/LibClone.sol";
1415

1516
contract AccountFactory is Ownable {
1617
UpgradeableModularAccount public immutable ACCOUNT_IMPL;
18+
SemiModularAccount public immutable SEMI_MODULAR_ACCOUNT_IMPL;
1719
bytes32 private immutable _PROXY_BYTECODE_HASH;
1820
IEntryPoint public immutable ENTRY_POINT;
1921
address public immutable SINGLE_SIGNER_VALIDATION;
2022

2123
constructor(
2224
IEntryPoint _entryPoint,
2325
UpgradeableModularAccount _accountImpl,
26+
SemiModularAccount _semiModularImpl,
2427
address _singleSignerValidation,
2528
address owner
2629
) Ownable(owner) {
2730
ENTRY_POINT = _entryPoint;
2831
_PROXY_BYTECODE_HASH =
2932
keccak256(abi.encodePacked(type(ERC1967Proxy).creationCode, abi.encode(address(_accountImpl), "")));
3033
ACCOUNT_IMPL = _accountImpl;
34+
SEMI_MODULAR_ACCOUNT_IMPL = _semiModularImpl;
3135
SINGLE_SIGNER_VALIDATION = _singleSignerValidation;
3236
}
3337

@@ -62,7 +66,7 @@ contract AccountFactory is Ownable {
6266
return UpgradeableModularAccount(payable(addr));
6367
}
6468

65-
function createAccountWithFallbackValidation(address owner, uint256 salt)
69+
function createSemiModularAccount(address owner, uint256 salt)
6670
external
6771
returns (UpgradeableModularAccount)
6872
{
@@ -76,7 +80,7 @@ contract AccountFactory is Ownable {
7680
// short circuit if exists
7781
if (addr.code.length == 0) {
7882
// not necessary to check return addr since next call will fail if so
79-
LibClone.createDeterministicERC1967(address(ACCOUNT_IMPL), immutables, fullSalt);
83+
LibClone.createDeterministicERC1967(address(SEMI_MODULAR_ACCOUNT_IMPL), immutables, fullSalt);
8084
}
8185

8286
return UpgradeableModularAccount(payable(addr));

test/account/AccountFactory.t.sol

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,23 @@
22
pragma solidity ^0.8.19;
33

44
import {AccountFactory} from "../../src/account/AccountFactory.sol";
5+
6+
import {SemiModularAccount} from "../../src/account/SemiModularAccount.sol";
57
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
68
import {AccountTestBase} from "../utils/AccountTestBase.sol";
79

810
contract AccountFactoryTest is AccountTestBase {
911
AccountFactory internal _factory;
1012
UpgradeableModularAccount internal _account;
13+
SemiModularAccount internal _semiModularAccount;
1114

1215
function setUp() public {
1316
_account = new UpgradeableModularAccount(entryPoint);
14-
_factory = new AccountFactory(entryPoint, _account, address(singleSignerValidation), address(this));
17+
_semiModularAccount = new SemiModularAccount(entryPoint);
18+
19+
_factory = new AccountFactory(
20+
entryPoint, _account, _semiModularAccount, address(singleSignerValidation), address(this)
21+
);
1522
}
1623

1724
function test_createAccount() public {

test/mocks/SingleSignerFactoryFixture.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ contract SingleSignerFactoryFixture is OptimizedTest {
4949
*/
5050
function createAccount(address owner, uint256 salt) public returns (UpgradeableModularAccount) {
5151
if (vm.envBool("SMA_TEST")) {
52-
return createAccountWithFallbackValidation(owner, salt);
52+
return createSemiModularAccount(owner, salt);
5353
}
5454

5555
address addr = Create2.computeAddress(getSalt(owner, salt), _PROXY_BYTECODE_HASH);
@@ -74,7 +74,7 @@ contract SingleSignerFactoryFixture is OptimizedTest {
7474
return UpgradeableModularAccount(payable(addr));
7575
}
7676

77-
function createAccountWithFallbackValidation(address owner, uint256 salt)
77+
function createSemiModularAccount(address owner, uint256 salt)
7878
public
7979
returns (UpgradeableModularAccount)
8080
{

test/script/Deploy.s.t.sol

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
1010
import {DeployScript} from "../../script/Deploy.s.sol";
1111

1212
import {AccountFactory} from "../../src/account/AccountFactory.sol";
13+
14+
import {SemiModularAccount} from "../../src/account/SemiModularAccount.sol";
1315
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
1416
import {SingleSignerValidation} from "../../src/modules/validation/SingleSignerValidation.sol";
1517

@@ -21,6 +23,7 @@ contract DeployTest is Test {
2123
address internal _owner;
2224

2325
address internal _accountImpl;
26+
address internal _smaImpl;
2427
address internal _singleSignerValidation;
2528
address internal _factory;
2629

@@ -42,6 +45,12 @@ contract DeployTest is Test {
4245
CREATE2_FACTORY
4346
);
4447

48+
_smaImpl = Create2.computeAddress(
49+
bytes32(0),
50+
keccak256(abi.encodePacked(type(SemiModularAccount).creationCode, abi.encode(address(_entryPoint)))),
51+
CREATE2_FACTORY
52+
);
53+
4554
_singleSignerValidation = Create2.computeAddress(
4655
bytes32(0), keccak256(abi.encodePacked(type(SingleSignerValidation).creationCode)), CREATE2_FACTORY
4756
);
@@ -51,17 +60,25 @@ contract DeployTest is Test {
5160
keccak256(
5261
abi.encodePacked(
5362
type(AccountFactory).creationCode,
54-
abi.encode(address(_entryPoint), _accountImpl, _singleSignerValidation, _owner)
63+
abi.encode(
64+
address(_entryPoint),
65+
_accountImpl,
66+
_smaImpl,
67+
_singleSignerValidation,
68+
_owner
69+
)
5570
)
5671
),
5772
CREATE2_FACTORY
5873
);
5974

6075
vm.setEnv("ACCOUNT_IMPL", vm.toString(address(_accountImpl)));
76+
vm.setEnv("SMA_IMPL", vm.toString(address(_smaImpl)));
6177
vm.setEnv("FACTORY", vm.toString(address(_factory)));
6278
vm.setEnv("SINGLE_SIGNER_VALIDATION", vm.toString(address(_singleSignerValidation)));
6379

6480
vm.setEnv("ACCOUNT_IMPL_SALT", vm.toString(uint256(0)));
81+
vm.setEnv("SMA_IMPL_SALT", vm.toString(uint256(0)));
6582
vm.setEnv("FACTORY_SALT", vm.toString(uint256(0)));
6683
vm.setEnv("SINGLE_SIGNER_VALIDATION_SALT", vm.toString(uint256(0)));
6784

0 commit comments

Comments
 (0)