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