contracts/ERC6551Account.sol 2.7 K raw
1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3
4
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
5
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
6
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
7
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
8
9
import "./interfaces/IERC6551Account.sol";
10
import "./interfaces/IERC6551Executable.sol";
11
12
contract ERC6551Account is
13
    IERC165,
14
    IERC1271,
15
    IERC6551Account,
16
    IERC6551Executable
17
{
18
    uint256 public state;
19
20
    receive() external payable {}
21
22
    function execute(
23
        address to,
24
        uint256 value,
25
        bytes calldata data,
26
        uint256 operation
27
    ) public payable virtual returns (bytes memory result) {
28
        require(_isValidSigner(msg.sender), "Invalid signer");
29
        require(operation == 0, "Only call operations are supported");
30
31
        ++state;
32
33
        bool success;
34
        (success, result) = to.call{value: value}(data);
35
36
        if (!success) {
37
            assembly {
38
                revert(add(result, 32), mload(result))
39
            }
40
        }
41
    }
42
43
    function isValidSigner(
44
        address signer,
45
        bytes calldata
46
    ) public view virtual returns (bytes4) {
47
        if (_isValidSigner(signer)) {
48
            return IERC6551Account.isValidSigner.selector;
49
        }
50
51
        return bytes4(0);
52
    }
53
54
    function isValidSignature(
55
        bytes32 hash,
56
        bytes memory signature
57
    ) public view virtual returns (bytes4 magicValue) {
58
        bool isValid = SignatureChecker.isValidSignatureNow(
59
            owner(),
60
            hash,
61
            signature
62
        );
63
64
        if (isValid) {
65
            return IERC1271.isValidSignature.selector;
66
        }
67
68
        return "";
69
    }
70
71
    function supportsInterface(
72
        bytes4 interfaceId
73
    ) public pure virtual returns (bool) {
74
        return (interfaceId == type(IERC165).interfaceId ||
75
            interfaceId == type(IERC6551Account).interfaceId ||
76
            interfaceId == type(IERC6551Executable).interfaceId);
77
    }
78
79
    function token() public view virtual returns (uint256, address, uint256) {
80
        bytes memory footer = new bytes(0x60);
81
82
        assembly {
83
            extcodecopy(address(), add(footer, 0x20), 0x4d, 0x60)
84
        }
85
86
        return abi.decode(footer, (uint256, address, uint256));
87
    }
88
89
    function owner() public view virtual returns (address) {
90
        (uint256 chainId, address tokenContract, uint256 tokenId) = token();
91
        if (chainId != block.chainid) return address(0);
92
93
        return IERC721(tokenContract).ownerOf(tokenId);
94
    }
95
96
    function _isValidSigner(
97
        address signer
98
    ) internal view virtual returns (bool) {
99
        return signer == owner();
100
    }
101
}