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  }