github.com/core-coin/go-core/v2@v2.1.9/accounts/abi/bind/base_test.go (about) 1 // Copyright 2019 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package bind_test 18 19 import ( 20 "context" 21 "fmt" 22 "math/big" 23 "reflect" 24 "strings" 25 "testing" 26 27 core "github.com/core-coin/go-core/v2" 28 "github.com/core-coin/go-core/v2/accounts/abi" 29 "github.com/core-coin/go-core/v2/accounts/abi/bind" 30 "github.com/core-coin/go-core/v2/common" 31 "github.com/core-coin/go-core/v2/common/hexutil" 32 "github.com/core-coin/go-core/v2/core/types" 33 "github.com/core-coin/go-core/v2/crypto" 34 "github.com/core-coin/go-core/v2/rlp" 35 ) 36 37 type mockCaller struct { 38 codeAtBlockNumber *big.Int 39 callContractBlockNumber *big.Int 40 pendingCodeAtCalled bool 41 pendingCallContractCalled bool 42 } 43 44 func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { 45 mc.codeAtBlockNumber = blockNumber 46 return []byte{1, 2, 3}, nil 47 } 48 49 func (mc *mockCaller) CallContract(ctx context.Context, call core.CallMsg, blockNumber *big.Int) ([]byte, error) { 50 mc.callContractBlockNumber = blockNumber 51 return nil, nil 52 } 53 54 func (mc *mockCaller) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { 55 mc.pendingCodeAtCalled = true 56 return nil, nil 57 } 58 59 func (mc *mockCaller) PendingCallContract(ctx context.Context, call core.CallMsg) ([]byte, error) { 60 mc.pendingCallContractCalled = true 61 return nil, nil 62 } 63 64 var ( 65 mockAddr, _ = common.HexToAddress("cb27de521e43741cf785cbad450d5649187b9612018f") 66 addr2, _ = common.HexToAddress("cb540000000000000000000000000000000000000000") 67 ) 68 69 func TestPassingBlockNumber(t *testing.T) { 70 71 mc := &mockCaller{} 72 73 bc := bind.NewBoundContract(addr2, abi.ABI{ 74 Methods: map[string]abi.Method{ 75 "something": { 76 Name: "something", 77 Outputs: abi.Arguments{}, 78 }, 79 }, 80 }, mc, nil, nil) 81 82 blockNumber := big.NewInt(42) 83 84 bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, nil, "something") 85 86 if mc.callContractBlockNumber != blockNumber { 87 t.Fatalf("CallContract() was not passed the block number") 88 } 89 90 if mc.codeAtBlockNumber != blockNumber { 91 t.Fatalf("CodeAt() was not passed the block number") 92 } 93 94 bc.Call(&bind.CallOpts{}, nil, "something") 95 96 if mc.callContractBlockNumber != nil { 97 t.Fatalf("CallContract() was passed a block number when it should not have been") 98 } 99 100 if mc.codeAtBlockNumber != nil { 101 t.Fatalf("CodeAt() was passed a block number when it should not have been") 102 } 103 104 bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, nil, "something") 105 106 if !mc.pendingCallContractCalled { 107 t.Fatalf("CallContract() was not passed the block number") 108 } 109 110 if !mc.pendingCodeAtCalled { 111 t.Fatalf("CodeAt() was not passed the block number") 112 } 113 } 114 115 const hexData = "0x00000000000000000000cb27de521e43741cf785cbad450d5649187b9612018f00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158" 116 117 func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) { 118 hash := crypto.SHA3Hash([]byte("testName")) 119 topics := []common.Hash{ 120 common.HexToHash("0x0"), 121 hash, 122 } 123 mockLog := newMockLog(topics, common.HexToHash("0x0")) 124 125 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"}]` 126 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 127 bc := bind.NewBoundContract(addr2, parsedAbi, nil, nil, nil) 128 129 expectedReceivedMap := map[string]interface{}{ 130 "name": hash, 131 "sender": mockAddr, 132 "amount": big.NewInt(1), 133 "memo": []byte{88}, 134 } 135 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 136 } 137 138 func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) { 139 sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"}) 140 if err != nil { 141 t.Fatal(err) 142 } 143 hash := crypto.SHA3Hash(sliceBytes) 144 topics := []common.Hash{ 145 common.HexToHash("0x0"), 146 hash, 147 } 148 mockLog := newMockLog(topics, common.HexToHash("0x0")) 149 150 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"}]` 151 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 152 bc := bind.NewBoundContract(addr2, parsedAbi, nil, nil, nil) 153 154 expectedReceivedMap := map[string]interface{}{ 155 "names": hash, 156 "sender": mockAddr, 157 "amount": big.NewInt(1), 158 "memo": []byte{88}, 159 } 160 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 161 } 162 163 func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) { 164 arrBytes, err := rlp.EncodeToBytes([2]common.Address{addr2}) 165 if err != nil { 166 t.Fatal(err) 167 } 168 hash := crypto.SHA3Hash(arrBytes) 169 topics := []common.Hash{ 170 common.HexToHash("0x0"), 171 hash, 172 } 173 mockLog := newMockLog(topics, common.HexToHash("0x0")) 174 175 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"}]` 176 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 177 bc := bind.NewBoundContract(addr2, parsedAbi, nil, nil, nil) 178 179 expectedReceivedMap := map[string]interface{}{ 180 "addresses": hash, 181 "sender": mockAddr, 182 "amount": big.NewInt(1), 183 "memo": []byte{88}, 184 } 185 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 186 } 187 188 func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) { 189 bytess1 := []byte{203, 39, 222, 82, 30, 67, 116, 28, 247, 133, 203, 173, 69, 13, 86, 73, 24, 123, 150, 18, 1, 143, 212, 250, 35, 31} 190 bytess2 := []byte{222, 82, 30, 67, 116, 28, 247, 133, 203, 173, 69, 13, 86, 73, 24, 123, 150, 18, 1, 143, 212, 250, 35, 31, 0, 0} 191 fmt.Println(common.Bytes2Hex(bytess1)) 192 fmt.Println(common.Bytes2Hex(bytess2)) 193 addrBytes := mockAddr.Bytes() 194 hash := crypto.SHA3Hash([]byte("mockFunction(address,uint)")) 195 functionSelector := hash[:4] 196 functionTyBytes := append(addrBytes, functionSelector...) 197 var functionTy [26]byte 198 copy(functionTy[:], functionTyBytes[0:26]) 199 topics := []common.Hash{ 200 common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"), 201 common.BytesToHash(functionTyBytes), 202 } 203 mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42")) 204 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"}]` 205 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 206 bc := bind.NewBoundContract(addr2, parsedAbi, nil, nil, nil) 207 208 expectedReceivedMap := map[string]interface{}{ 209 "function": functionTy, 210 "sender": mockAddr, 211 "amount": big.NewInt(1), 212 "memo": []byte{88}, 213 } 214 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 215 } 216 217 func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) { 218 bytes := []byte{1, 2, 3, 4, 5} 219 hash := crypto.SHA3Hash(bytes) 220 topics := []common.Hash{ 221 common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"), 222 hash, 223 } 224 mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42")) 225 226 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"}]` 227 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 228 bc := bind.NewBoundContract(addr2, parsedAbi, nil, nil, nil) 229 230 expectedReceivedMap := map[string]interface{}{ 231 "content": hash, 232 "sender": mockAddr, 233 "amount": big.NewInt(1), 234 "memo": []byte{88}, 235 } 236 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 237 } 238 239 func unpackAndCheck(t *testing.T, bc *bind.BoundContract, expected map[string]interface{}, mockLog types.Log) { 240 received := make(map[string]interface{}) 241 if err := bc.UnpackLogIntoMap(received, "received", mockLog); err != nil { 242 t.Error(err) 243 } 244 245 if len(received) != len(expected) { 246 t.Fatalf("unpacked map length %v not equal expected length of %v", len(received), len(expected)) 247 } 248 for name, elem := range expected { 249 if !reflect.DeepEqual(elem, received[name]) { 250 t.Errorf("field %v does not match expected, want %v, got %v", name, elem, received[name]) 251 } 252 } 253 } 254 255 func newMockLog(topics []common.Hash, txHash common.Hash) types.Log { 256 return types.Log{ 257 Address: addr2, 258 Topics: topics, 259 Data: hexutil.MustDecode(hexData), 260 BlockNumber: uint64(26), 261 TxHash: txHash, 262 TxIndex: 111, 263 BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), 264 Index: 7, 265 Removed: false, 266 } 267 }