@@ -13,6 +13,133 @@ abiparser - application binary interface (abi) parser machinery / helper for Eth
13
13
## Usage
14
14
15
15
16
+ ### Functions Signature Hashes / Selectors & Interface (Type) Ids
17
+
18
+
19
+ You can calculate the function selectors (or "sighash",
20
+ that is, signature hash)
21
+ by hashing the function signature
22
+ e.g. ` supportsInterface(bytes4) ` with the Keccak 256-Bit algorithm
23
+ and than use the first 4 bytes, that is, ` 0x01ffc9a7 ` (out of 32 bytes),
24
+ that is, ` 0x01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2 ` . Example:
25
+
26
+
27
+ ``` ruby
28
+ require ' abiparser'
29
+
30
+ sig = ' supportsInterface(bytes4)'
31
+ pp keccak256( sig )[0 ,4 ].hexdigest
32
+ # => "0x01ffc9a7"
33
+ ```
34
+
35
+ Note: The ` String#hexdigest ` (also known as ` String#bin_to_hex ` ) helper
36
+ converts a binary string (with ` BINARY ` /` ASCII-8BIT ` encoding)
37
+ into a hex(adecimal) string.
38
+
39
+
40
+ You can calcuate interface (type) ids
41
+ by xor-ing (` ^ ` ) together the sighashes.
42
+ If the interface only has one function than
43
+ the interface (type) id equals the function sighash (by definition).
44
+
45
+
46
+ ``` solidity
47
+ interface ERC165 {
48
+ /// @notice Query if a contract implements an interface
49
+ /// @param interfaceID The interface identifier, as specified in ERC-165
50
+ /// @dev Interface identification is specified in ERC-165.
51
+ /// @return `true` if the contract implements `interfaceID` and
52
+ /// `interfaceID` is not 0xffffffff, `false` otherwise
53
+ function supportsInterface(bytes4 interfaceID) external view returns (bool);
54
+ }
55
+ // The interface identifier for this interface is 0x01ffc9a7.
56
+ ```
57
+
58
+ If you check the sighash for ` supportsInterface(bytes4) ` ,
59
+ that is, ` 0x01ffc9a7 ` (see above)
60
+ than - bingo! - the interface id for ERC165 matches up.
61
+
62
+
63
+ Let's try to calculate the ERC20 standard (fungible) token interface
64
+ where the official id is ` 0x36372b07 ` by xor-ing (` ^ ` ) together all function sighashes:
65
+
66
+ ``` ruby
67
+ pp (keccak256(' totalSupply()' )[0 ,4 ] ^
68
+ keccak256(' balanceOf(address)' )[0 ,4 ] ^
69
+ keccak256(' allowance(address,address)' )[0 ,4 ] ^
70
+ keccak256(' transfer(address,uint256)' )[0 ,4 ] ^
71
+ keccak256(' approve(address,uint256)' )[0 ,4 ] ^
72
+ keccak256(' transferFrom(address,address,uint256)' )[0 ,4 ]).hexdigest
73
+ # => "0x36372b07"
74
+
75
+ # or where def sig(bin) = keccak256(bin)[0,4])
76
+
77
+ pp (sig(' totalSupply()' ) ^
78
+ sig(' balanceOf(address)' ) ^
79
+ sig(' allowance(address,address)' ) ^
80
+ sig(' transfer(address,uint256)' ) ^
81
+ sig(' approve(address,uint256)' ) ^
82
+ sig(' transferFrom(address,address,uint256)' )).hexdigest
83
+ # => "0x36372b07"
84
+ ```
85
+
86
+ Voila!
87
+ Or re(use) the builtin pre-defined interfaces. Example:
88
+
89
+ ``` ruby
90
+ pp IERC165 .inteface_id # => "0x01ffc9a7"
91
+ pp IERC20 .interface_id # => "0x36372b07"
92
+ pp IERC721 .interface_id # => "0x80ac58cd"
93
+ pp IERC721Metadata .interface_id # => "0x5b5e139f"
94
+ pp IERC721Enumerable .interface_id # => "0x780e9d63"
95
+ ```
96
+
97
+ Yes, you can. Define your own interface. Let's have a looksie
98
+ at the built-ins. Example:
99
+
100
+ ``` ruby
101
+ IERC165 = ABI ::Interface .new (
102
+ ' supportsInterface(bytes4)'
103
+ )
104
+
105
+ IERC20 = ABI ::Interface .new (
106
+ ' totalSupply()' ,
107
+ ' balanceOf(address)' ,
108
+ ' allowance(address,address)' ,
109
+ ' transfer(address,uint256)' ,
110
+ ' approve(address,uint256)' ,
111
+ ' transferFrom(address,address,uint256)'
112
+ )
113
+
114
+ IERC721 = ABI ::Interface .new (
115
+ ' balanceOf(address)' ,
116
+ ' ownerOf(uint256)' ,
117
+ ' approve(address,uint256)' ,
118
+ ' getApproved(uint256)' ,
119
+ ' setApprovalForAll(address,bool)' ,
120
+ ' isApprovedForAll(address,address)' ,
121
+ ' transferFrom(address,address,uint256)' ,
122
+ ' safeTransferFrom(address,address,uint256)' ,
123
+ ' safeTransferFrom(address,address,uint256,bytes)' )
124
+
125
+ IERC721Metadata = ABI ::Interface .new (
126
+ ' name()' ,
127
+ ' symbol()' ,
128
+ ' tokenURI(uint256)' )
129
+
130
+ IERC721Enumerable = ABI ::Interface .new (
131
+ ' tokenOfOwnerByIndex(address,uint256)' ,
132
+ ' totalSupply()' ,
133
+ ' tokenByIndex(uint256)' )
134
+
135
+ ...
136
+ ```
137
+
138
+
139
+ To be continued...
140
+
141
+
142
+
16
143
17
144
18
145
## License
0 commit comments