github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/accounts/abi/bind/base_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package bind_test 19 20 import ( 21 "bytes" 22 "context" 23 "math/big" 24 "strings" 25 "testing" 26 27 "github.com/AigarNetwork/aigar" 28 "github.com/AigarNetwork/aigar/accounts/abi" 29 "github.com/AigarNetwork/aigar/accounts/abi/bind" 30 "github.com/AigarNetwork/aigar/common" 31 "github.com/AigarNetwork/aigar/common/hexutil" 32 "github.com/AigarNetwork/aigar/core/types" 33 "github.com/AigarNetwork/aigar/crypto" 34 "github.com/AigarNetwork/aigar/rlp" 35 ) 36 37 type mockCaller struct { 38 codeAtBlockNumber *big.Int 39 callContractBlockNumber *big.Int 40 } 41 42 func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { 43 mc.codeAtBlockNumber = blockNumber 44 return []byte{1, 2, 3}, nil 45 } 46 47 func (mc *mockCaller) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { 48 mc.callContractBlockNumber = blockNumber 49 return nil, nil 50 } 51 func TestPassingBlockNumber(t *testing.T) { 52 53 mc := &mockCaller{} 54 55 bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{ 56 Methods: map[string]abi.Method{ 57 "something": { 58 Name: "something", 59 Outputs: abi.Arguments{}, 60 }, 61 }, 62 }, mc, nil, nil) 63 var ret string 64 65 blockNumber := big.NewInt(42) 66 67 bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, &ret, "something") 68 69 if mc.callContractBlockNumber != blockNumber { 70 t.Fatalf("CallContract() was not passed the block number") 71 } 72 73 if mc.codeAtBlockNumber != blockNumber { 74 t.Fatalf("CodeAt() was not passed the block number") 75 } 76 77 bc.Call(&bind.CallOpts{}, &ret, "something") 78 79 if mc.callContractBlockNumber != nil { 80 t.Fatalf("CallContract() was passed a block number when it should not have been") 81 } 82 83 if mc.codeAtBlockNumber != nil { 84 t.Fatalf("CodeAt() was passed a block number when it should not have been") 85 } 86 } 87 88 const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158" 89 90 func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) { 91 hash := crypto.Keccak256Hash([]byte("testName")) 92 mockLog := types.Log{ 93 Address: common.HexToAddress("0x0"), 94 Topics: []common.Hash{ 95 common.HexToHash("0x0"), 96 hash, 97 }, 98 Data: hexutil.MustDecode(hexData), 99 BlockNumber: uint64(26), 100 TxHash: common.HexToHash("0x0"), 101 TxIndex: 111, 102 BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), 103 Index: 7, 104 Removed: false, 105 } 106 107 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 108 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 109 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 110 111 receivedMap := make(map[string]interface{}) 112 expectedReceivedMap := map[string]interface{}{ 113 "name": hash, 114 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 115 "amount": big.NewInt(1), 116 "memo": []byte{88}, 117 } 118 if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil { 119 t.Error(err) 120 } 121 122 if len(receivedMap) != 4 { 123 t.Fatal("unpacked map expected to have length 4") 124 } 125 if receivedMap["name"] != expectedReceivedMap["name"] { 126 t.Error("unpacked map does not match expected map") 127 } 128 if receivedMap["sender"] != expectedReceivedMap["sender"] { 129 t.Error("unpacked map does not match expected map") 130 } 131 if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 { 132 t.Error("unpacked map does not match expected map") 133 } 134 if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) { 135 t.Error("unpacked map does not match expected map") 136 } 137 } 138 139 func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) { 140 sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"}) 141 if err != nil { 142 t.Fatal(err) 143 } 144 hash := crypto.Keccak256Hash(sliceBytes) 145 mockLog := types.Log{ 146 Address: common.HexToAddress("0x0"), 147 Topics: []common.Hash{ 148 common.HexToHash("0x0"), 149 hash, 150 }, 151 Data: hexutil.MustDecode(hexData), 152 BlockNumber: uint64(26), 153 TxHash: common.HexToHash("0x0"), 154 TxIndex: 111, 155 BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), 156 Index: 7, 157 Removed: false, 158 } 159 160 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"names","type":"string[]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 161 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 162 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 163 164 receivedMap := make(map[string]interface{}) 165 expectedReceivedMap := map[string]interface{}{ 166 "names": hash, 167 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 168 "amount": big.NewInt(1), 169 "memo": []byte{88}, 170 } 171 if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil { 172 t.Error(err) 173 } 174 175 if len(receivedMap) != 4 { 176 t.Fatal("unpacked map expected to have length 4") 177 } 178 if receivedMap["names"] != expectedReceivedMap["names"] { 179 t.Error("unpacked map does not match expected map") 180 } 181 if receivedMap["sender"] != expectedReceivedMap["sender"] { 182 t.Error("unpacked map does not match expected map") 183 } 184 if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 { 185 t.Error("unpacked map does not match expected map") 186 } 187 if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) { 188 t.Error("unpacked map does not match expected map") 189 } 190 } 191 192 func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) { 193 arrBytes, err := rlp.EncodeToBytes([2]common.Address{common.HexToAddress("0x0"), common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")}) 194 if err != nil { 195 t.Fatal(err) 196 } 197 hash := crypto.Keccak256Hash(arrBytes) 198 mockLog := types.Log{ 199 Address: common.HexToAddress("0x0"), 200 Topics: []common.Hash{ 201 common.HexToHash("0x0"), 202 hash, 203 }, 204 Data: hexutil.MustDecode(hexData), 205 BlockNumber: uint64(26), 206 TxHash: common.HexToHash("0x0"), 207 TxIndex: 111, 208 BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), 209 Index: 7, 210 Removed: false, 211 } 212 213 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"addresses","type":"address[2]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 214 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 215 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 216 217 receivedMap := make(map[string]interface{}) 218 expectedReceivedMap := map[string]interface{}{ 219 "addresses": hash, 220 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 221 "amount": big.NewInt(1), 222 "memo": []byte{88}, 223 } 224 if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil { 225 t.Error(err) 226 } 227 228 if len(receivedMap) != 4 { 229 t.Fatal("unpacked map expected to have length 4") 230 } 231 if receivedMap["addresses"] != expectedReceivedMap["addresses"] { 232 t.Error("unpacked map does not match expected map") 233 } 234 if receivedMap["sender"] != expectedReceivedMap["sender"] { 235 t.Error("unpacked map does not match expected map") 236 } 237 if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 { 238 t.Error("unpacked map does not match expected map") 239 } 240 if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) { 241 t.Error("unpacked map does not match expected map") 242 } 243 } 244 245 func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) { 246 mockAddress := common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2") 247 addrBytes := mockAddress.Bytes() 248 hash := crypto.Keccak256Hash([]byte("mockFunction(address,uint)")) 249 functionSelector := hash[:4] 250 functionTyBytes := append(addrBytes, functionSelector...) 251 var functionTy [24]byte 252 copy(functionTy[:], functionTyBytes[0:24]) 253 mockLog := types.Log{ 254 Address: common.HexToAddress("0x0"), 255 Topics: []common.Hash{ 256 common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"), 257 common.BytesToHash(functionTyBytes), 258 }, 259 Data: hexutil.MustDecode(hexData), 260 BlockNumber: uint64(26), 261 TxHash: common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"), 262 TxIndex: 111, 263 BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), 264 Index: 7, 265 Removed: false, 266 } 267 268 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"function","type":"function"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 269 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 270 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 271 272 receivedMap := make(map[string]interface{}) 273 expectedReceivedMap := map[string]interface{}{ 274 "function": functionTy, 275 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 276 "amount": big.NewInt(1), 277 "memo": []byte{88}, 278 } 279 if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil { 280 t.Error(err) 281 } 282 283 if len(receivedMap) != 4 { 284 t.Fatal("unpacked map expected to have length 4") 285 } 286 if receivedMap["function"] != expectedReceivedMap["function"] { 287 t.Error("unpacked map does not match expected map") 288 } 289 if receivedMap["sender"] != expectedReceivedMap["sender"] { 290 t.Error("unpacked map does not match expected map") 291 } 292 if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 { 293 t.Error("unpacked map does not match expected map") 294 } 295 if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) { 296 t.Error("unpacked map does not match expected map") 297 } 298 } 299 300 func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) { 301 byts := []byte{1, 2, 3, 4, 5} 302 hash := crypto.Keccak256Hash(byts) 303 mockLog := types.Log{ 304 Address: common.HexToAddress("0x0"), 305 Topics: []common.Hash{ 306 common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"), 307 hash, 308 }, 309 Data: hexutil.MustDecode(hexData), 310 BlockNumber: uint64(26), 311 TxHash: common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"), 312 TxIndex: 111, 313 BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), 314 Index: 7, 315 Removed: false, 316 } 317 318 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"content","type":"bytes"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 319 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 320 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 321 322 receivedMap := make(map[string]interface{}) 323 expectedReceivedMap := map[string]interface{}{ 324 "content": hash, 325 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 326 "amount": big.NewInt(1), 327 "memo": []byte{88}, 328 } 329 if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil { 330 t.Error(err) 331 } 332 333 if len(receivedMap) != 4 { 334 t.Fatal("unpacked map expected to have length 4") 335 } 336 if receivedMap["content"] != expectedReceivedMap["content"] { 337 t.Error("unpacked map does not match expected map") 338 } 339 if receivedMap["sender"] != expectedReceivedMap["sender"] { 340 t.Error("unpacked map does not match expected map") 341 } 342 if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 { 343 t.Error("unpacked map does not match expected map") 344 } 345 if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) { 346 t.Error("unpacked map does not match expected map") 347 } 348 }