Skip to content

Commit

Permalink
♻️ ERC6551 new executable interface ID (#861)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized authored Mar 18, 2024
1 parent 91d5f64 commit 06de56d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 23 deletions.
18 changes: 9 additions & 9 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -265,23 +265,23 @@ ERC4626Test:testWithdrawWithNoUnderlyingAmountReverts() (gas: 13102)
ERC4626Test:testWithdrawWithNotEnoughUnderlyingAmountReverts() (gas: 144074)
ERC4626Test:testWithdrawZero() (gas: 52807)
ERC4626Test:test__codesize() (gas: 39940)
ERC6551Test:testCdFallback() (gas: 894305)
ERC6551Test:testDeployERC6551(uint256) (runs: 257, μ: 171193, ~: 168789)
ERC6551Test:testCdFallback() (gas: 894295)
ERC6551Test:testDeployERC6551(uint256) (runs: 257, μ: 171077, ~: 168788)
ERC6551Test:testDeployERC6551Proxy() (gas: 80351)
ERC6551Test:testExecute() (gas: 507899)
ERC6551Test:testExecuteBatch() (gas: 817000)
ERC6551Test:testExecuteBatch(uint256) (runs: 257, μ: 627737, ~: 586245)
ERC6551Test:testExecute() (gas: 508100)
ERC6551Test:testExecuteBatch() (gas: 817200)
ERC6551Test:testExecuteBatch(uint256) (runs: 257, μ: 622293, ~: 483183)
ERC6551Test:testInitializeERC6551ProxyImplementation() (gas: 189796)
ERC6551Test:testIsValidSignature() (gas: 187642)
ERC6551Test:testIsValidSigner(address) (runs: 257, μ: 167326, ~: 167324)
ERC6551Test:testIsValidSigner(address) (runs: 257, μ: 167327, ~: 167324)
ERC6551Test:testOnERC1155BatchReceived() (gas: 1526537)
ERC6551Test:testOnERC1155Received() (gas: 1523871)
ERC6551Test:testOnERC721Received() (gas: 1501317)
ERC6551Test:testOnERC721ReceivedCycles() (gas: 1713680)
ERC6551Test:testOnERC721ReceivedCyclesWithDifferentChainIds(uint256) (runs: 257, μ: 448971, ~: 454680)
ERC6551Test:testOnERC721ReceivedCyclesWithDifferentChainIds(uint256) (runs: 257, μ: 448372, ~: 454235)
ERC6551Test:testSupportsInterface() (gas: 169367)
ERC6551Test:testUpgrade() (gas: 1165638)
ERC6551Test:test__codesize() (gas: 47524)
ERC6551Test:testUpgrade() (gas: 1164238)
ERC6551Test:test__codesize() (gas: 47510)
ERC6909Test:testApprove() (gas: 36771)
ERC6909Test:testApprove(address,uint256,uint256) (runs: 257, μ: 36483, ~: 37413)
ERC6909Test:testBurn() (gas: 40676)
Expand Down
41 changes: 28 additions & 13 deletions src/accounts/ERC6551.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ import {UUPSUpgradeable} from "../utils/UUPSUpgradeable.sol";
/// the click on "Is this a proxy?" on the clone's page on Etherscan.
///
/// Note:
/// - ERC6551 accounts are not compatible with ERC4337
/// (at least not without crazy hacks)
/// due to storage access limitations during ERC4337 UserOp validation.
/// - This implementation does NOT include ERC4337 functionality.
/// This is intentional, because the canonical ERC4337 entry point may still change and we
/// don't want to encourage upgradeability by default for ERC6551 accounts just to handle this.
/// We may include ERC4337 functionality once ERC4337 has been finalized.
/// Recent updates to the account abstraction validation scope rules
/// [ERC7562](https://eips.ethereum.org/EIPS/eip-7562) has made ERC6551 compatible with ERC4337.
/// For an opinionated implementation, see https://github.com/tokenbound/contracts.
/// If you want to add it yourself, you'll just need to add in the
/// user operation validation functionality (and use ERC6551's execution functionality).
/// - Please refer to the official [ERC6551](https://github.com/erc6551/reference) reference
/// for latest updates on the ERC6551 standard, as well as canonical registry information.
abstract contract ERC6551 is UUPSUpgradeable, Receiver, ERC1271 {
Expand Down Expand Up @@ -172,15 +178,26 @@ abstract contract ERC6551 is UUPSUpgradeable, Receiver, ERC1271 {
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @dev Execute a call from this account.
/// Reverts and bubbles up error if operation fails.
/// Returns the result of the operation.
///
/// Accounts MUST accept the following operation parameter values:
/// - 0 = CALL
/// - 1 = DELEGATECALL
/// - 2 = CREATE
/// - 3 = CREATE2
///
/// Accounts MAY support additional operations or restrict a signer's
/// ability to execute certain operations.
function execute(address target, uint256 value, bytes calldata data, uint8 operation)
public
payable
virtual
onlyValidSigner
onlyValidExecuteOperation(operation)
incrementState
returns (bytes memory result)
{
if (operation != 0) revert OperationNotSupported();
/// @solidity memory-safe-assembly
assembly {
result := mload(0x40)
Expand All @@ -198,15 +215,19 @@ abstract contract ERC6551 is UUPSUpgradeable, Receiver, ERC1271 {
}

/// @dev Execute a sequence of calls from this account.
/// Reverts and bubbles up error if an operation fails.
/// Returns the results of the operations.
///
/// This is a batch variant of `execute` and is not required for `IERC6551Executable`.
function executeBatch(Call[] calldata calls, uint8 operation)
public
payable
virtual
onlyValidSigner
onlyValidExecuteOperation(operation)
incrementState
returns (bytes[] memory results)
{
if (operation != 0) revert OperationNotSupported();
/// @solidity memory-safe-assembly
assembly {
results := mload(0x40)
Expand Down Expand Up @@ -235,12 +256,6 @@ abstract contract ERC6551 is UUPSUpgradeable, Receiver, ERC1271 {
}
}

/// @dev Requires that the execute `operation` is supported.
modifier onlyValidExecuteOperation(uint8 operation) virtual {
if (operation != 0) revert OperationNotSupported();
_;
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC165 */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
Expand All @@ -252,8 +267,8 @@ abstract contract ERC6551 is UUPSUpgradeable, Receiver, ERC1271 {
/// @solidity memory-safe-assembly
assembly {
let s := shr(224, interfaceId)
// ERC165: 0x01ffc9a7, ERC6551: 0x6faff5f1, ERC6551Executable: 0x74420f4c.
result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x6faff5f1)), eq(s, 0x74420f4c))
// ERC165: 0x01ffc9a7, ERC6551: 0x6faff5f1, ERC6551Executable: 0x51945447.
result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x6faff5f1)), eq(s, 0x51945447))
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/ERC6551.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ contract ERC6551Test is SoladyTest {
_TestTemps memory t = _testTemps();
assertTrue(t.account.supportsInterface(0x01ffc9a7));
assertTrue(t.account.supportsInterface(0x6faff5f1));
assertTrue(t.account.supportsInterface(0x74420f4c));
assertTrue(t.account.supportsInterface(0x51945447));
assertFalse(t.account.supportsInterface(0x00000001));
}

Expand Down

0 comments on commit 06de56d

Please sign in to comment.