github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/eth/contract_test.go (about) 1 //go:build unittest 2 3 package eth 4 5 import ( 6 "fmt" 7 "math/big" 8 "strings" 9 "testing" 10 11 "github.com/trezor/blockbook/bchain" 12 "github.com/trezor/blockbook/tests/dbtestdata" 13 ) 14 15 func Test_contractGetTransfersFromLog(t *testing.T) { 16 tests := []struct { 17 name string 18 args []*bchain.RpcLog 19 want bchain.TokenTransfers 20 wantErr bool 21 }{ 22 { 23 name: "ERC20 transfer 1", 24 args: []*bchain.RpcLog{ 25 { 26 Address: "0x76a45e8976499ab9ae223cc584019341d5a84e96", 27 Topics: []string{ 28 "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", 29 "0x0000000000000000000000002aacf811ac1a60081ea39f7783c0d26c500871a8", 30 "0x000000000000000000000000e9a5216ff992cfa01594d43501a56e12769eb9d2", 31 }, 32 Data: "0x0000000000000000000000000000000000000000000000000000000000000123", 33 }, 34 }, 35 want: bchain.TokenTransfers{ 36 { 37 Contract: "0x76a45e8976499ab9ae223cc584019341d5a84e96", 38 From: "0x2aacf811ac1a60081ea39f7783c0d26c500871a8", 39 To: "0xe9a5216ff992cfa01594d43501a56e12769eb9d2", 40 Value: *big.NewInt(0x123), 41 }, 42 }, 43 }, 44 { 45 name: "ERC20 transfer 2", 46 args: []*bchain.RpcLog{ 47 { // Transfer 48 Address: "0x0d0f936ee4c93e25944694d6c121de94d9760f11", 49 Topics: []string{ 50 "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", 51 "0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed", 52 "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d", 53 }, 54 Data: "0x0000000000000000000000000000000000000000000000006a8313d60b1f606b", 55 }, 56 { // Transfer 57 Address: "0xc778417e063141139fce010982780140aa0cd5ab", 58 Topics: []string{ 59 "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", 60 "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d", 61 "0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed", 62 }, 63 Data: "0x000000000000000000000000000000000000000000000000000308fd0e798ac0", 64 }, 65 { // not Transfer 66 Address: "0x479cc461fecd078f766ecc58533d6f69580cf3ac", 67 Topics: []string{ 68 "0x0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb3", 69 "0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed", 70 "0x0000000000000000000000000000000000000000000000000000000000000000", 71 "0x5af266c0a89a07c1917deaa024414577e6c3c31c8907d079e13eb448c082594f", 72 }, 73 Data: "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d0000000000000", 74 }, 75 { // not Transfer 76 Address: "0x0d0f936ee4c93e25944694d6c121de94d9760f11", 77 Topics: []string{ 78 "0x0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb3", 79 "0x0000000000000000000000007b62eb7fe80350dc7ec945c0b73242cb9877fb1b", 80 "0xb0b69dad58df6032c3b266e19b1045b19c87acd2c06fb0c598090f44b8e263aa", 81 }, 82 Data: "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d000000000000000000000000c778417e063141139fce010982780140aa0cd5ab0000000000000000000000000d0f936ee4c93e25944694d6c121de94d9760f1100000000000000000000000000000000000000000000000000031855667df7a80000000000000000000000000000000000000000000000006a8313d60b1f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 83 }, 84 }, 85 want: bchain.TokenTransfers{ 86 { 87 Contract: "0x0d0f936ee4c93e25944694d6c121de94d9760f11", 88 From: "0x6f44cceb49b4a5812d54b6f494fc2febf25511ed", 89 To: "0x4bda106325c335df99eab7fe363cac8a0ba2a24d", 90 Value: *big.NewInt(0x6a8313d60b1f606b), 91 }, 92 { 93 Contract: "0xc778417e063141139fce010982780140aa0cd5ab", 94 From: "0x4bda106325c335df99eab7fe363cac8a0ba2a24d", 95 To: "0x6f44cceb49b4a5812d54b6f494fc2febf25511ed", 96 Value: *big.NewInt(0x308fd0e798ac0), 97 }, 98 }, 99 }, 100 { 101 name: "ERC721 transfer 1", 102 args: []*bchain.RpcLog{ 103 { // Approval 104 Address: "0x5689b918D34C038901870105A6C7fc24744D31eB", 105 Topics: []string{ 106 "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", 107 "0x0000000000000000000000000a206d4d5ff79cb5069def7fe3598421cff09391", 108 "0x0000000000000000000000000000000000000000000000000000000000000000", 109 "0x0000000000000000000000000000000000000000000000000000000000001396", 110 }, 111 Data: "0x", 112 }, 113 { // Transfer 114 Address: "0x5689b918D34C038901870105A6C7fc24744D31eB", 115 Topics: []string{ 116 "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", 117 "0x0000000000000000000000000a206d4d5ff79cb5069def7fe3598421cff09391", 118 "0x0000000000000000000000006a016d7eec560549ffa0fbdb7f15c2b27302087f", 119 "0x0000000000000000000000000000000000000000000000000000000000001396", 120 }, 121 Data: "0x", 122 }, 123 { // OrdersMatched 124 Address: "0x7Be8076f4EA4A4AD08075C2508e481d6C946D12b", 125 Topics: []string{ 126 "0xc4109843e0b7d514e4c093114b863f8e7d8d9a458c372cd51bfe526b588006c9", 127 "0x0000000000000000000000000a206d4d5ff79cb5069def7fe3598421cff09391", 128 "0x0000000000000000000000006a016d7eec560549ffa0fbdb7f15c2b27302087f", 129 "0x0000000000000000000000000000000000000000000000000000000000000000", 130 }, 131 Data: "0x000000000000000000000000000000000000000000000000000000000000000069d3f0cc25f121f2aa96215f51ec4b4f1966f2d2ffbd3d8d8a45ad27b1c90323000000000000000000000000000000000000000000000000008e1bc9bf040000", 132 }, 133 }, 134 want: bchain.TokenTransfers{ 135 { 136 Type: bchain.NonFungibleToken, 137 Contract: "0x5689b918D34C038901870105A6C7fc24744D31eB", 138 From: "0x0a206d4d5ff79cb5069def7fe3598421cff09391", 139 To: "0x6a016d7eec560549ffa0fbdb7f15c2b27302087f", 140 Value: *big.NewInt(0x1396), 141 }, 142 }, 143 }, 144 { 145 name: "ERC1155 TransferSingle", 146 args: []*bchain.RpcLog{ 147 { // Transfer 148 Address: "0x6Fd712E3A5B556654044608F9129040A4839E36c", 149 Topics: []string{ 150 "0x5f9832c7244497a64c11c4a4f7597934bdf02b0361c54ad8e90091c2ce1f9e3c", 151 }, 152 Data: "0x000000000000000000000000a3950b823cb063dd9afc0d27f35008b805b3ed530000000000000000000000004392faf3bb96b5694ecc6ef64726f61cdd4bb0ec000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", 153 }, 154 { // TransferSingle 155 Address: "0x6Fd712E3A5B556654044608F9129040A4839E36c", 156 Topics: []string{ 157 "0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62", 158 "0x0000000000000000000000009248a6048a58db9f0212dc7cd85ee8741128be72", 159 "0x000000000000000000000000a3950b823cb063dd9afc0d27f35008b805b3ed53", 160 "0x0000000000000000000000004392faf3bb96b5694ecc6ef64726f61cdd4bb0ec", 161 }, 162 Data: "0x00000000000000000000000000000000000000000000000000000000000000960000000000000000000000000000000000000000000000000000000000000011", 163 }, 164 { // unknown 165 Address: "0x9248A6048a58db9f0212dC7CD85eE8741128be72", 166 Topics: []string{ 167 "0x0b7bef9468bee71526deef3cbbded0ec1a0aa3d5a3e81eaffb0e758552b33199", 168 }, 169 Data: "0x0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000a3950b823cb063dd9afc0d27f35008b805b3ed530000000000000000000000004392faf3bb96b5694ecc6ef64726f61cdd4bb0ec0000000000000000000000000000000000000000000000000000000000000001", 170 }, 171 }, 172 want: bchain.TokenTransfers{ 173 { 174 Type: bchain.MultiToken, 175 Contract: "0x6Fd712E3A5B556654044608F9129040A4839E36c", 176 From: "0xa3950b823cb063dd9afc0d27f35008b805b3ed53", 177 To: "0x4392faf3bb96b5694ecc6ef64726f61cdd4bb0ec", 178 MultiTokenValues: []bchain.MultiTokenValue{{Id: *big.NewInt(150), Value: *big.NewInt(0x11)}}, 179 }, 180 }, 181 }, 182 { 183 name: "ERC1155 TransferBatch", 184 args: []*bchain.RpcLog{ 185 { // TransferBatch 186 Address: "0x6c42C26a081c2F509F8bb68fb7Ac3062311cCfB7", 187 Topics: []string{ 188 "0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb", 189 "0x0000000000000000000000005dc6288b35e0807a3d6feb89b3a2ff4ab773168e", 190 "0x0000000000000000000000000000000000000000000000000000000000000000", 191 "0x0000000000000000000000005dc6288b35e0807a3d6feb89b3a2ff4ab773168e", 192 }, 193 Data: "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000076a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a", 194 }, 195 }, 196 want: bchain.TokenTransfers{ 197 { 198 Type: bchain.MultiToken, 199 Contract: "0x6c42c26a081c2f509f8bb68fb7ac3062311ccfb7", 200 From: "0x0000000000000000000000000000000000000000", 201 To: "0x5dc6288b35e0807a3d6feb89b3a2ff4ab773168e", 202 MultiTokenValues: []bchain.MultiTokenValue{ 203 {Id: *big.NewInt(1776), Value: *big.NewInt(1)}, 204 {Id: *big.NewInt(1898), Value: *big.NewInt(10)}, 205 }, 206 }, 207 }, 208 }} 209 for _, tt := range tests { 210 t.Run(tt.name, func(t *testing.T) { 211 got, err := contractGetTransfersFromLog(tt.args) 212 if (err != nil) != tt.wantErr { 213 t.Errorf("contractGetTransfersFromLog error = %v, wantErr %v", err, tt.wantErr) 214 return 215 } 216 if len(got) != len(tt.want) { 217 t.Errorf("contractGetTransfersFromLog len not same, %+v, want %+v", got, tt.want) 218 } 219 for i := range got { 220 // the addresses could have different case 221 if strings.ToLower(fmt.Sprint(got[i])) != strings.ToLower(fmt.Sprint(tt.want[i])) { 222 t.Errorf("contractGetTransfersFromLog %d = %+v, want %+v", i, got[i], tt.want[i]) 223 } 224 225 } 226 }) 227 } 228 } 229 230 func Test_contractGetTransfersFromTx(t *testing.T) { 231 p := NewEthereumParser(1, false) 232 b1 := dbtestdata.GetTestEthereumTypeBlock1(p) 233 b2 := dbtestdata.GetTestEthereumTypeBlock2(p) 234 bn, _ := new(big.Int).SetString("21e19e0c9bab2400000", 16) 235 tests := []struct { 236 name string 237 args *bchain.RpcTransaction 238 want bchain.TokenTransfers 239 }{ 240 { 241 name: "no contract transfer", 242 args: (b1.Txs[0].CoinSpecificData.(bchain.EthereumSpecificData)).Tx, 243 want: bchain.TokenTransfers{}, 244 }, 245 { 246 name: "ERC20 transfer", 247 args: (b1.Txs[1].CoinSpecificData.(bchain.EthereumSpecificData)).Tx, 248 want: bchain.TokenTransfers{ 249 { 250 Type: bchain.FungibleToken, 251 Contract: "0x4af4114f73d1c1c903ac9e0361b379d1291808a2", 252 From: "0x20cd153de35d469ba46127a0c8f18626b59a256a", 253 To: "0x555ee11fbddc0e49a9bab358a8941ad95ffdb48f", 254 Value: *bn, 255 }, 256 }, 257 }, 258 { 259 name: "ERC721 transferFrom", 260 args: (b2.Txs[2].CoinSpecificData.(bchain.EthereumSpecificData)).Tx, 261 want: bchain.TokenTransfers{ 262 { 263 Type: bchain.NonFungibleToken, 264 Contract: "0xcda9fc258358ecaa88845f19af595e908bb7efe9", 265 From: "0x837e3f699d85a4b0b99894567e9233dfb1dcb081", 266 To: "0x7b62eb7fe80350dc7ec945c0b73242cb9877fb1b", 267 Value: *big.NewInt(1), 268 }, 269 }, 270 }, 271 } 272 for _, tt := range tests { 273 t.Run(tt.name, func(t *testing.T) { 274 got, err := contractGetTransfersFromTx(tt.args) 275 if err != nil { 276 t.Errorf("contractGetTransfersFromTx error = %v", err) 277 return 278 } 279 if len(got) != len(tt.want) { 280 t.Errorf("contractGetTransfersFromTx len not same, %+v, want %+v", got, tt.want) 281 } 282 for i := range got { 283 // the addresses could have different case 284 if strings.ToLower(fmt.Sprint(got[i])) != strings.ToLower(fmt.Sprint(tt.want[i])) { 285 t.Errorf("contractGetTransfersFromTx %d = %+v, want %+v", i, got[i], tt.want[i]) 286 } 287 288 } 289 }) 290 } 291 }