Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- ERC6551Registry
- Optimization enabled
- true
- Compiler version
- v0.8.17+commit.8df45f5f
- Optimization runs
- 200
- EVM Version
- london
- Verified at
- 2024-06-06T15:22:42.861740Z
src/ERC6551Registry.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; interface IERC6551Registry { /** * @dev The registry MUST emit the ERC6551AccountCreated event upon successful account creation. */ event ERC6551AccountCreated( address account, address indexed implementation, bytes32 salt, uint256 chainId, address indexed tokenContract, uint256 indexed tokenId ); /** * @dev The registry MUST revert with AccountCreationFailed error if the create2 operation fails. */ error AccountCreationFailed(); /** * @dev Creates a token bound account for a non-fungible token. * * If account has already been created, returns the account address without calling create2. * * Emits ERC6551AccountCreated event. * * @return account The address of the token bound account */ function createAccount( address implementation, bytes32 salt, uint256 chainId, address tokenContract, uint256 tokenId ) external returns (address account); /** * @dev Returns the computed token bound account address for a non-fungible token. * * @return account The address of the token bound account */ function account( address implementation, bytes32 salt, uint256 chainId, address tokenContract, uint256 tokenId ) external view returns (address account); } contract ERC6551Registry is IERC6551Registry { function createAccount( address implementation, bytes32 salt, uint256 chainId, address tokenContract, uint256 tokenId ) external returns (address) { assembly { // Memory Layout: // ---- // 0x00 0xff (1 byte) // 0x01 registry (address) (20 bytes) // 0x15 salt (bytes32) (32 bytes) // 0x35 Bytecode Hash (bytes32) (32 bytes) // ---- // 0x55 ERC-1167 Constructor + Header (20 bytes) // 0x69 implementation (address) (20 bytes) // 0x5D ERC-1167 Footer (15 bytes) // 0x8C salt (uint256) (32 bytes) // 0xAC chainId (uint256) (32 bytes) // 0xCC tokenContract (address) (32 bytes) // 0xEC tokenId (uint256) (32 bytes) // Silence unused variable warnings pop(chainId) // Copy bytecode + constant data to memory calldatacopy(0x8c, 0x24, 0x80) // salt, chainId, tokenContract, tokenId mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer mstore(0x5d, implementation) // implementation mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header // Copy create2 computation data to memory mstore8(0x00, 0xff) // 0xFF mstore(0x35, keccak256(0x55, 0xb7)) // keccak256(bytecode) mstore(0x01, shl(96, address())) // registry address mstore(0x15, salt) // salt // Compute account address let computed := keccak256(0x00, 0x55) // If the account has not yet been deployed if iszero(extcodesize(computed)) { // Deploy account contract let deployed := create2(0, 0x55, 0xb7, salt) // Revert if the deployment fails if iszero(deployed) { mstore(0x00, 0x20188a59) // `AccountCreationFailed()` revert(0x1c, 0x04) } // Store account address in memory before salt and chainId mstore(0x6c, deployed) // Emit the ERC6551AccountCreated event log4( 0x6c, 0x60, // `ERC6551AccountCreated(address,address,bytes32,uint256,address,uint256)` 0x79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf88722, implementation, tokenContract, tokenId ) // Return the account address return(0x6c, 0x20) } // Otherwise, return the computed account address mstore(0x00, shr(96, shl(96, computed))) return(0x00, 0x20) } } function account( address implementation, bytes32 salt, uint256 chainId, address tokenContract, uint256 tokenId ) external view returns (address) { assembly { // Silence unused variable warnings pop(chainId) pop(tokenContract) pop(tokenId) // Copy bytecode + constant data to memory calldatacopy(0x8c, 0x24, 0x80) // salt, chainId, tokenContract, tokenId mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer mstore(0x5d, implementation) // implementation mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header // Copy create2 computation data to memory mstore8(0x00, 0xff) // 0xFF mstore(0x35, keccak256(0x55, 0xb7)) // keccak256(bytecode) mstore(0x01, shl(96, address())) // registry address mstore(0x15, salt) // salt // Store computed account address in memory mstore(0x00, shr(96, shl(96, keccak256(0x00, 0x55)))) // Return computed account address return(0x00, 0x20) } } }
Compiler Settings
{"viaIR":false,"remappings":["ds-test/=lib/forge-std/lib/ds-test/src/","forge-std/=lib/forge-std/src/","@openzeppelin/=lib/openzeppelin-contracts/","@account-abstraction/=lib/account-abstraction/","erc6551/=lib/erc6551/src/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","multicall-authenticated/=lib/multicall-authenticated/src/","account-abstraction/=lib/account-abstraction/contracts/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"london"}
Contract ABI
[{"type":"error","name":"AccountCreationFailed","inputs":[]},{"type":"event","name":"ERC6551AccountCreated","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false},{"type":"address","name":"implementation","internalType":"address","indexed":true},{"type":"bytes32","name":"salt","internalType":"bytes32","indexed":false},{"type":"uint256","name":"chainId","internalType":"uint256","indexed":false},{"type":"address","name":"tokenContract","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"account","inputs":[{"type":"address","name":"implementation","internalType":"address"},{"type":"bytes32","name":"salt","internalType":"bytes32"},{"type":"uint256","name":"chainId","internalType":"uint256"},{"type":"address","name":"tokenContract","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"createAccount","inputs":[{"type":"address","name":"implementation","internalType":"address"},{"type":"bytes32","name":"salt","internalType":"bytes32"},{"type":"uint256","name":"chainId","internalType":"uint256"},{"type":"address","name":"tokenContract","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b5061023b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063246a00211461003b5780638a54c52f1461006a575b600080fd5b61004e6100493660046101b7565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b61004e6100783660046101b7565b6100e1565b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b60015284601552605560002060601b60601c60005260206000f35b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b600152846015526055600020803b61018b578560b760556000f580610157576320188a596000526004601cfd5b80606c52508284887f79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf887226060606ca46020606cf35b8060601b60601c60005260206000f35b80356001600160a01b03811681146101b257600080fd5b919050565b600080600080600060a086880312156101cf57600080fd5b6101d88661019b565b945060208601359350604086013592506101f46060870161019b565b94979396509194608001359291505056fea2646970667358221220ea2fe53af507453c64dd7c1db05549fa47a298dfb825d6d11e1689856135f16764736f6c63430008110033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063246a00211461003b5780638a54c52f1461006a575b600080fd5b61004e6100493660046101b7565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b61004e6100783660046101b7565b6100e1565b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b60015284601552605560002060601b60601c60005260206000f35b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b600152846015526055600020803b61018b578560b760556000f580610157576320188a596000526004601cfd5b80606c52508284887f79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf887226060606ca46020606cf35b8060601b60601c60005260206000f35b80356001600160a01b03811681146101b257600080fd5b919050565b600080600080600060a086880312156101cf57600080fd5b6101d88661019b565b945060208601359350604086013592506101f46060870161019b565b94979396509194608001359291505056fea2646970667358221220ea2fe53af507453c64dd7c1db05549fa47a298dfb825d6d11e1689856135f16764736f6c63430008110033