contracts/ERC6551Registry.sol 2.0 K raw
1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3
4
import "@openzeppelin/contracts/utils/Create2.sol";
5
6
import "./interfaces/IERC6551Registry.sol";
7
import "./lib/ERC6551BytecodeLib.sol";
8
9
contract ERC6551Registry is IERC6551Registry {
10
    error AccountCreationFailed();
11
12
    function createAccount(
13
        address implementation,
14
        uint256 chainId,
15
        address tokenContract,
16
        uint256 tokenId,
17
        uint256 salt,
18
        bytes calldata initData
19
    ) external returns (address) {
20
        bytes memory code = ERC6551BytecodeLib.getCreationCode(
21
            implementation,
22
            chainId,
23
            tokenContract,
24
            tokenId,
25
            salt
26
        );
27
28
        address _account = Create2.computeAddress(
29
            bytes32(salt),
30
            keccak256(code)
31
        );
32
33
        if (_account.code.length != 0) return _account;
34
35
        emit AccountCreated(
36
            _account,
37
            implementation,
38
            chainId,
39
            tokenContract,
40
            tokenId,
41
            salt
42
        );
43
44
        assembly {
45
            _account := create2(0, add(code, 0x20), mload(code), salt)
46
        }
47
48
        if (_account == address(0)) revert AccountCreationFailed();
49
50
        if (initData.length != 0) {
51
            (bool success, bytes memory result) = _account.call(initData);
52
53
            if (!success) {
54
                assembly {
55
                    revert(add(result, 32), mload(result))
56
                }
57
            }
58
        }
59
60
        return _account;
61
    }
62
63
    function account(
64
        address implementation,
65
        uint256 chainId,
66
        address tokenContract,
67
        uint256 tokenId,
68
        uint256 salt
69
    ) external view returns (address) {
70
        bytes32 bytecodeHash = keccak256(
71
            ERC6551BytecodeLib.getCreationCode(
72
                implementation,
73
                chainId,
74
                tokenContract,
75
                tokenId,
76
                salt
77
            )
78
        );
79
80
        return Create2.computeAddress(bytes32(salt), bytecodeHash);
81
    }
82
}