Skip to content
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

Feat/sma 809 potential account factories #73

Merged
merged 48 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
91d778b
rename getCounterfactual + add util Boostrap.sol + stakemanager to st…
livingrockrises May 14, 2024
0c31a97
fix script
livingrockrises May 14, 2024
a7870d2
restructure
livingrockrises May 14, 2024
a8f4816
add meta factory
livingrockrises May 15, 2024
48ce072
preserve old factory
livingrockrises May 15, 2024
27ee508
add tests validate user operation from entry point
Aboudjem May 16, 2024
3d8988a
add accesscontrol+unauthorized access tests
Aboudjem May 16, 2024
c16674a
refactor: add InvalidSignature error to EventsAndErrors.sol
Aboudjem May 16, 2024
72c1f48
add tests cases + fix wrong asserts
Aboudjem May 16, 2024
0219d86
chore: Update deployment account funding amount in test
Aboudjem May 16, 2024
5787c54
Remove unnecessary code in TestERC4337Account_ValidateUserOp.t.sol
Aboudjem May 16, 2024
16395f1
add test for validation of user operation nonce
Aboudjem May 16, 2024
1b86b42
Merge branch 'dev' of https://github.com/bcnmy/erc7579-modular-smart-…
Aboudjem May 16, 2024
fcebab3
Merge branch 'dev' of https://github.com/bcnmy/erc7579-modular-smart-…
Aboudjem May 16, 2024
fa87c90
Merge branch 'dev' of https://github.com/bcnmy/erc7579-modular-smart-…
Aboudjem May 16, 2024
b1232a3
Merge branch 'dev' into feat/SMA-809-potential-account-factory
Aboudjem May 16, 2024
a3144cd
update factory, add more factories and foundry test cases
livingrockrises May 19, 2024
25e167a
Merge branch 'dev' into feat/SMA-809-potential-account-factory
livingrockrises May 19, 2024
92ebf11
refactor meta factory
livingrockrises May 20, 2024
c3c132e
refactor + natspecs + logs
livingrockrises May 21, 2024
796f2f2
update factories + refactor + working foundry tests + update hardhat …
livingrockrises May 21, 2024
e3f8ea8
refactor
livingrockrises May 21, 2024
556e045
Merge branch 'dev' into feat/SMA-809-potential-account-factory
livingrockrises May 21, 2024
693e8df
resolve conflicts with helper contract
livingrockrises May 21, 2024
12067c6
refactor: update imports in TestHelper.t.sol, remove unused and reorder
Aboudjem May 21, 2024
3ee489c
refactor: update Stakeable contract with natspecs
Aboudjem May 21, 2024
52e0a3d
refactor: update IStakeable interface with natspecs
Aboudjem May 21, 2024
b018f8c
refactor: rename to test_DeployAccount_CreateAccount function + natspecs
Aboudjem May 21, 2024
5ffee46
refactor: update TestAccountFactory_Deployments contract with natspecs
Aboudjem May 21, 2024
4ce97ad
typo fix + update Bootstrap functions to comply with styleguide
Aboudjem May 21, 2024
81f9aa5
refactor: Update natspecs and refactor names
Aboudjem May 21, 2024
4cda43a
refactor: Update K1ValidatorFactory to use correct function name for …
Aboudjem May 21, 2024
9ab7b48
refactor: Update ArbitrumSmartAccountUpgradeTest.t.sol to use updated…
Aboudjem May 21, 2024
c93a009
refactor: Update func names, remove unused and reorder
Aboudjem May 21, 2024
b0f5f69
refactor: Update BootstrapUtil.sol to comply with styleguide
Aboudjem May 21, 2024
cbd9e18
lint fix
Aboudjem May 21, 2024
b48cd26
refactor: Update Stakeable contract with constructor parameter name c…
Aboudjem May 21, 2024
9568092
lint fix
Aboudjem May 21, 2024
065887b
refactor: Update K1ValidatorFactory to use correct function name for …
Aboudjem May 21, 2024
af17db6
fix typo FactoryNotWhotelisted to FactoryNotWhitelisted in
Aboudjem May 21, 2024
296c3fd
gas optimization, remove memory var + named returns
Aboudjem May 21, 2024
f2eff9c
refactor: Update DEFAULT_ARBITRUM_RPC_URL in ArbitrumSettings contract
Aboudjem May 22, 2024
3bc5eae
Update Stakeable Natspec
Aboudjem May 22, 2024
aaa2574
refactor: Update IStakeable.sol with improved natspec and consistency
Aboudjem May 22, 2024
bfe499b
Merge pull request #79 from bcnmy/chore/account-factory-refactoring
livingrockrises May 22, 2024
5f2d353
fix whitelist factory test
livingrockrises May 24, 2024
00216fa
refactor + act on PR
livingrockrises May 24, 2024
0efdb79
lint fixes
livingrockrises May 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions contracts/common/Stakeable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// ──────────────────────────────────────────────────────────────────────────────
// _ __ _ __
// / | / /__ | |/ /_ _______
// / |/ / _ \| / / / / ___/
// / /| / __/ / /_/ (__ )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Account compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. For security issues, contact: [email protected]

import {Ownable} from "solady/src/auth/Ownable.sol";
import {IEntryPoint} from "account-abstraction/contracts/interfaces/IEntryPoint.sol";
import {IStakeable} from "../interfaces/common/IStakeable.sol";

/**
livingrockrises marked this conversation as resolved.
Show resolved Hide resolved
* @title Stakeable Entity
* @author Fil Makarov - <[email protected]>
*/
contract Stakeable is Ownable, IStakeable {
constructor(address _newOwner) {
_setOwner(_newOwner);
}

/**
* @dev Stakes a certain amount of Ether on an EntryPoint.
* @notice The contract should have enough Ether to cover the stake.
* @param epAddress Address of the EntryPoint where the stake is added.
* @param unstakeDelaySec The delay in seconds before the stake can be unlocked.
*/
function addStake(
address epAddress,
uint32 unstakeDelaySec
) external payable override onlyOwner {
require(epAddress != address(0), "Invalid EP address");
IEntryPoint(epAddress).addStake{value: msg.value}(unstakeDelaySec);
}

/**
* @dev Unlocks the stake on an EntryPoint.
* @notice This starts the unstaking delay after which funds can be withdrawn.
* @param epAddress Address of the EntryPoint where the stake is unlocked.
*/
function unlockStake(address epAddress) external override onlyOwner {
require(epAddress != address(0), "Invalid EP address");
IEntryPoint(epAddress).unlockStake();
}

/**
* @dev Withdraws the stake from an EntryPoint to a specified address.
* @notice This can only be done after the unstaking delay has passed since the unlock.
* @param epAddress Address of the EntryPoint where the stake is withdrawn from.
* @param withdrawAddress Address to receive the withdrawn stake.
*/
function withdrawStake(
address epAddress,
address payable withdrawAddress
) external override onlyOwner {
require(epAddress != address(0), "Invalid EP address");
IEntryPoint(epAddress).withdrawStake(withdrawAddress);
}
}
11 changes: 5 additions & 6 deletions contracts/factory/AccountFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ pragma solidity ^0.8.24;
// Learn more at https://biconomy.io. For security issues, contact: [email protected]

import { LibClone } from "solady/src/utils/LibClone.sol";
import { StakeManager } from "account-abstraction/contracts/core/StakeManager.sol";

import { Stakeable } from "../common/Stakeable.sol";
import { INexus } from "../interfaces/INexus.sol";
import { IAccountFactory } from "../interfaces/factory/IAccountFactory.sol";

Expand All @@ -28,14 +27,14 @@ import { IAccountFactory } from "../interfaces/factory/IAccountFactory.sol";
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
contract AccountFactory is IAccountFactory, StakeManager {
contract AccountFactory is IAccountFactory, Stakeable {
/// @notice Stores the implementation contract address used to create new Nexus instances.
/// @dev This address is set once upon deployment and cannot be changed afterwards.
address public immutable ACCOUNT_IMPLEMENTATION;

/// @notice Constructor to set the smart account implementation address.
/// @param implementation The address of the Nexus implementation to be used for all deployments.
constructor(address implementation) {
constructor(address implementation, address owner) Stakeable(owner) {
ACCOUNT_IMPLEMENTATION = implementation;
}

Expand Down Expand Up @@ -71,8 +70,8 @@ contract AccountFactory is IAccountFactory, StakeManager {
/// @param moduleInstallData The initialization data for the module.
/// @param index The index or type of the module, used for generating the deployment address.
/// @return expectedAddress The expected address at which the Nexus contract will be deployed if the provided parameters are used.
/// @dev This function allows for address prediction without deploying the Nexus.
function getCounterFactualAddress(
/// @dev This function allows for address calculation without deploying the Nexus.
function computeAccountAddress(
address validationModule,
bytes calldata moduleInstallData,
uint256 index
Expand Down
92 changes: 92 additions & 0 deletions contracts/factory/AccountFactoryOld.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// ──────────────────────────────────────────────────────────────────────────────
// _ __ _ __
// / | / /__ | |/ /_ _______
// / |/ / _ \| / / / / ___/
// / /| / __/ / /_/ (__ )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Account compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. For security issues, contact: [email protected]

import { LibClone } from "solady/src/utils/LibClone.sol";
import { Stakeable } from "../common/Stakeable.sol";
import { INexus } from "../interfaces/INexus.sol";
import { IAccountFactoryOld } from "../interfaces/factory/IAccountFactoryOld.sol";

/// @title Nexus - AccountFactory
/// @notice Manages the creation of Modular Smart Accounts compliant with ERC-7579 and ERC-4337 using a factory pattern.
/// @dev Utilizes the `StakeManager` for staking requirements and `LibClone` for creating deterministic proxy accounts.
/// This contract serves as a factory to generate new Nexus instances with specific modules and initialization data.
/// It combines functionality from Biconomy's implementation and external libraries to manage account deployments and initializations.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
contract AccountFactory is IAccountFactoryOld, Stakeable {
/// @notice Stores the implementation contract address used to create new Nexus instances.
/// @dev This address is set once upon deployment and cannot be changed afterwards.
address public immutable ACCOUNT_IMPLEMENTATION;

/// @notice Constructor to set the smart account implementation address.
/// @param implementation The address of the Nexus implementation to be used for all deployments.
constructor(address implementation, address owner) Stakeable(owner) {
ACCOUNT_IMPLEMENTATION = implementation;
}

/// @notice Creates a new Nexus with a specific validator and initialization data.
/// @param validationModule The address of the validation module to configure the new Nexus.
/// @param moduleInstallData Initialization data for configuring the validation module.
/// @param index An identifier used to generate a unique deployment address.
/// @return The address of the newly created Nexus.
/// @dev Deploys a new Nexus using a deterministic address based on the input parameters.
function createAccount(address validationModule, bytes calldata moduleInstallData, uint256 index) external payable returns (address payable) {
(index);
bytes32 salt;

assembly {
let ptr := mload(0x40)
let calldataLength := sub(calldatasize(), 0x04)
mstore(0x40, add(ptr, calldataLength))
calldatacopy(ptr, 0x04, calldataLength)
salt := keccak256(ptr, calldataLength)
}

(bool alreadyDeployed, address account) = LibClone.createDeterministicERC1967(msg.value, ACCOUNT_IMPLEMENTATION, salt);

if (!alreadyDeployed) {
INexus(account).initialize(validationModule, moduleInstallData);
emit AccountCreatedOld(account, validationModule, moduleInstallData);
}
return payable(account);
}

/// @notice Computes the expected address of a Nexus contract using the factory's deterministic deployment algorithm.
/// @param validationModule The address of the module to be used in the Nexus.
/// @param moduleInstallData The initialization data for the module.
/// @param index The index or type of the module, used for generating the deployment address.
/// @return expectedAddress The expected address at which the Nexus contract will be deployed if the provided parameters are used.
/// @dev This function allows for address calculation without deploying the Nexus.
function computeAccountAddress(
address validationModule,
bytes calldata moduleInstallData,
uint256 index
) external view returns (address payable expectedAddress) {
(validationModule, moduleInstallData, index);
bytes32 salt;

assembly {
let ptr := mload(0x40)
let calldataLength := sub(calldatasize(), 0x04)
mstore(0x40, add(ptr, calldataLength))
calldatacopy(ptr, 0x04, calldataLength)
salt := keccak256(ptr, calldataLength)
}

expectedAddress = payable(LibClone.predictDeterministicAddressERC1967(ACCOUNT_IMPLEMENTATION, salt, address(this)));
}
}
49 changes: 49 additions & 0 deletions contracts/factory/BiconomyMetaFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// ──────────────────────────────────────────────────────────────────────────────
// _ __ _ __
// / | / /__ | |/ /_ _______
// / |/ / _ \| / / / / ___/
// / /| / __/ / /_/ (__ )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Account compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. For security issues, contact: [email protected]

import { IAccountFactory } from "../interfaces/factory/IAccountFactory.sol";
import { Stakeable } from "../common/Stakeable.sol";

// can stake
// can whitelist factories
// deployAccount with chosen factory and required data for that facotry
contract BiconomyMetaFactory is Stakeable {

error FactoryNotWhotelisted();

mapping(address => bool) public factoryWhitelist;

constructor(address owner) Stakeable(owner) {
}

// could be IAccountFactory
// whitelist / blacklist a factory
livingrockrises marked this conversation as resolved.
Show resolved Hide resolved
function whitelistFactory(address factory, bool whitelisted) external payable onlyOwner {
factoryWhitelist[factory] = whitelisted;
}

// Note: deploy using only one of the whitelisted factories
livingrockrises marked this conversation as resolved.
Show resolved Hide resolved
// these factories could possibly enshrine specific module/s
function deployWithFactory(IAccountFactory factory, bytes calldata initData, bytes32 salt)
external
payable
returns (address)
{
if (!factoryWhitelist[address(factory)]) {
revert FactoryNotWhotelisted();
}
// emit AccountDeployedWithFactory(factory, initData, salt);
return factory.createAccount(initData, salt);
}
}
31 changes: 31 additions & 0 deletions contracts/interfaces/common/IStakeable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// ──────────────────────────────────────────────────────────────────────────────
// _ __ _ __
// / | / /__ | |/ /_ _______
// / |/ / _ \| / / / / ___/
// / /| / __/ / /_/ (__ )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Account compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. For security issues, contact: [email protected]

/**
livingrockrises marked this conversation as resolved.
Show resolved Hide resolved
* @title Stakeable Entity
* @author Fil Makarov - <[email protected]>
*/
interface IStakeable {
function addStake(
address epAddress,
uint32 unstakeDelaySec
) external payable;

function unlockStake(address epAddress) external;

function withdrawStake(
address epAddress,
address payable withdrawAddress
) external;
}
40 changes: 40 additions & 0 deletions contracts/interfaces/factory/IAccountFactoryOld.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// ──────────────────────────────────────────────────────────────────────────────
// _ __ _ __
// / | / /__ | |/ /_ _______
// / |/ / _ \| / / / / ___/
// / /| / __/ / /_/ (__ )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Account compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. For security issues, contact: [email protected]

/// @title Nexus - IAccountFactory Interface
/// @notice Interface for creating Smart Accounts within the Nexus suite, compliant with ERC-4337 and ERC-7579.
/// @dev This interface defines the creation method for Smart Accounts, specifying the necessary parameters for account setup and configuration.
/// It includes an event that logs the creation of new accounts, detailing the associated modules and their installation data.
/// This contract supports dynamic account creation using modular designs for varied validation strategies and operational scopes.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IAccountFactoryOld {
/// @notice Emitted when a new Smart Account is created, capturing the account details and associated module configurations.
event AccountCreatedOld(address indexed account, address indexed validationModule, bytes moduleInstallData);

/// @notice Creates a new Smart Account with a specified validation module and initialization data.
/// @dev Deploys a new Smart Account deterministically using EIP-1167 minimal proxy pattern and initializes it with the provided module and data.
/// @param validationModule The address of the module used for validation in the new Smart Account.
/// @param moduleInstallData Initialization data for configuring the module on the new Smart Account.
/// @param index An additional parameter that can be used to influence the creation process, often used as a nonce.
/// @return account The address of the newly created payable Smart Account.
function createAccount(
address validationModule,
bytes calldata moduleInstallData,
uint256 index
) external payable returns (address payable account);
}
Loading
Loading