From 411f09631fce0031e37b2d67b9079556e9d7dcae Mon Sep 17 00:00:00 2001 From: Dmitry S <11892559+swift1337@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:21:04 +0100 Subject: [PATCH 1/3] Fix TON call data parsing --- pkg/contracts/ton/gateway_test.go | 86 ++++++++++++++++--- .../ton/testdata/07-deposit-and-call-abi.json | 8 ++ pkg/contracts/ton/tlb.go | 15 ++-- 3 files changed, 88 insertions(+), 21 deletions(-) create mode 100644 pkg/contracts/ton/testdata/07-deposit-and-call-abi.json diff --git a/pkg/contracts/ton/gateway_test.go b/pkg/contracts/ton/gateway_test.go index 6698147e7c..ed7e8cf844 100644 --- a/pkg/contracts/ton/gateway_test.go +++ b/pkg/contracts/ton/gateway_test.go @@ -160,7 +160,42 @@ func TestParsing(t *testing.T) { assert.Equal(t, longCallData, depositAndCall2.CallData) }) + }) + + t.Run("Deposit and call ABI", func(t *testing.T) { + // ARRANGE + // Given a tx + tx, fx := getFixtureTX(t, "07-deposit-and-call-abi") + + // Given a gateway contract + gw := NewGateway(ton.MustParseAccountID(fx.Account)) + + // ACT + parsedTX, err := gw.ParseTransaction(tx) + + // ASSERT + require.NoError(t, err) + + // Check tx props + assert.Equal(t, int(OpDepositAndCall), int(parsedTX.Operation)) + + // Check deposit and call + depositAndCall, err := parsedTX.DepositAndCall() + assert.NoError(t, err) + const ( + expectedSender = "0:74a36900b786949a60c95ee20a56e583f908f2e957f3ffcb1e9770cc9edd408d" + zevmRecipient = "0x13ad4f89050E83e8F485BB8349b40d3b89833790" + expectedDeposit = 94_800_000 // 0.1 TON - tx fee + + // cast abi-encode "fn(string)" "ZETA ON TON YEAH" + callData = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000105a455441204f4e20544f4e205945414800000000000000000000000000000000" + ) + + assert.Equal(t, expectedSender, depositAndCall.Sender.ToRaw()) + assert.Equal(t, expectedDeposit, int(depositAndCall.Amount.Uint64())) + assert.Equal(t, zevmRecipient, depositAndCall.Recipient.Hex()) + assert.Equal(t, callData, "0x"+hex.EncodeToString(depositAndCall.CallData)) }) t.Run("Withdrawal", func(t *testing.T) { @@ -363,23 +398,50 @@ func TestFixtures(t *testing.T) { } func TestSnakeData(t *testing.T) { - for _, tt := range []string{ - "Hello world", - "123", - strings.Repeat(`ZetaChain `, 300), - string(readFixtureFile(t, "testdata/long-call-data.txt")), + h2b := func(raw string) []byte { + b, err := hex.DecodeString(strings.TrimPrefix(raw, "0x")) + require.NoError(t, err) + + return b + } + + for _, tt := range []struct { + name string + data []byte + }{ + {name: "simple", data: []byte("123")}, + {name: "hello world", data: []byte("Hello world")}, + {name: "zeta repeated 10 times", data: []byte(strings.Trim(strings.Repeat("ZetaChain ", 10), " "))}, + {name: "zeta repeated 50 times", data: []byte(strings.Trim(strings.Repeat("ZetaChain ", 50), " "))}, + {name: "long call data text", data: readFixtureFile(t, "testdata/long-call-data.txt")}, + { + // cast abi-encode "fn(string)" "ping-pong" + name: "abi call data 1", + data: h2b("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000970696e672d706f6e670000000000000000000000000000000000000000000000"), + }, + { + // cast abi-encode "swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline)" 123 456 "[0x0E0E08C73CD5019d6CAc98311Fa18edf98b70428,0x0E0E08C73CD5019d6CAc98311Fa18edf98b70428]" 0x0E0E08C73CD5019d6CAc98311Fa18edf98b70428 999 + name: "abi call data 2", + data: h2b("0x000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000e0e08c73cd5019d6cac98311fa18edf98b7042800000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000000020000000000000000000000000e0e08c73cd5019d6cac98311fa18edf98b704280000000000000000000000000e0e08c73cd5019d6cac98311fa18edf98b70428"), + }, } { - a := []byte(tt) + t.Run(tt.name, func(t *testing.T) { + a := tt.data - cell, err := MarshalSnakeCell(a) - require.NoError(t, err) + cell, err := MarshalSnakeCell(a) + require.NoError(t, err) - b, err := UnmarshalSnakeCell(cell) - require.NoError(t, err) + b, err := UnmarshalSnakeCell(cell) + require.NoError(t, err) - t.Logf(string(b)) + if len(a) != len(b) { + t.Logf("Lengths are not equal. Want %d, got %d.\nA:\n```%s```\n\nB:\n```%s```", len(a), len(b), a, b) + t.Logf("Last 8 bytes: A: %v; B: %v", a[len(a)-8:], b[len(b)-8:]) + t.FailNow() + } - assert.Equal(t, a, b, tt) + require.Equal(t, a, b) + }) } } diff --git a/pkg/contracts/ton/testdata/07-deposit-and-call-abi.json b/pkg/contracts/ton/testdata/07-deposit-and-call-abi.json new file mode 100644 index 0000000000..8035f2d65d --- /dev/null +++ b/pkg/contracts/ton/testdata/07-deposit-and-call-abi.json @@ -0,0 +1,8 @@ +{ + "account": "0:7a4d41496726aadb227cf4d313c95912f1fe6cc742c18ebde306ff59881d8816", + "boc": "b5ee9c7201020b010002610003b577a4d41496726aadb227cf4d313c95912f1fe6cc742c18ebde306ff59881d881600001d6a51f8d1c369b56b434771bae9ffdb2fb89e92636ae70d553bd402ae6c4fd1d295190dab9600001d6a488dee4167d3098c0003467eeedc80102030201e004050082729b5c859fe411dadead92b195050b191945d0caf6b345a83dfd6d47d0914492da083ff08d3226242e92e2b7ed236ab69f78e2cdf3795d1545c57f8c766a2d82480217046389017d784018670b8411090a01f16800e946d2016f0d2934c192bdc414adcb07f211e5d2afe7ff963d2ee1993dba811b001e93505259c9aab6c89f3d34c4f25644bc7f9b31d0b063af78c1bfd6620762059017d78400060f33b400003ad4a3f1a384cfa6131800000033000000000000000009d6a7c4828741f47a42ddc1a4da069dc4c19bc840060101df0700c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000105a455441204f4e20544f4e205945414800000000000000000000000000000000015de003d26a0a4b393556d913e7a6989e4ac8978ff3663a160c75ef1837facc40ec40b000003ad4a3f1a388cfa61318c0080010405a6888034f5880009e44824c0f42400000000000000000da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006fc9838d604c1c6b00000000000002000000000003ef0faad6f5e8c20c1fa610ba5f37243e73c948cb3a884e95dbbb64fc5498411c40900d8c", + "description": "Deposit 0.1 TON and provide abi-encoded payload https://testnet.tonviewer.com/transaction/7e6c401f5ec817df8bd9f4d101f72ccd0c196d19d63c0ff9dbb8f807510be932", + "hash": "7e6c401f5ec817df8bd9f4d101f72ccd0c196d19d63c0ff9dbb8f807510be932", + "logicalTime": 32342479000003, + "test": true + } \ No newline at end of file diff --git a/pkg/contracts/ton/tlb.go b/pkg/contracts/ton/tlb.go index 0ee3aea98a..ce1938d6db 100644 --- a/pkg/contracts/ton/tlb.go +++ b/pkg/contracts/ton/tlb.go @@ -1,8 +1,6 @@ package ton import ( - "bytes" - "cosmossdk.io/math" eth "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" @@ -34,22 +32,21 @@ func UnmarshalSnakeCell(cell *boc.Cell) ([]byte, error) { return nil, err } - cd := boc.BitString(sd) + bitString := boc.BitString(sd) + n := bitString.BitsAvailableForRead() / 8 - // TLB operates with bits, so we (might) need to trim some "leftovers" (null chars) - return bytes.Trim(cd.Buffer(), "\x00"), nil + return bitString.ReadBytes(n) } // MarshalSnakeCell encodes []byte to TLB using snake-cell encoding func MarshalSnakeCell(data []byte) (*boc.Cell, error) { - b := boc.NewCell() + bs := boc.NewBitString(len(data) * 8) - wrapped := tlb.Bytes(data) - if err := wrapped.MarshalTLB(b, &tlb.Encoder{}); err != nil { + if err := bs.WriteBytes(data); err != nil { return nil, err } - return b, nil + return MarshalTLB(tlb.SnakeData(bs)) } // UnmarshalEVMAddress decodes eth.Address from BOC From e96abde9b211a77fab52e48bfd91b5686b9ba0c2 Mon Sep 17 00:00:00 2001 From: Dmitry S <11892559+swift1337@users.noreply.github.com> Date: Fri, 14 Mar 2025 17:50:47 +0100 Subject: [PATCH 2/3] Update changelog --- changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog.md b/changelog.md index d6f908b8da..078fa40614 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,10 @@ # CHANGELOG +## v29.0.4 + +### Fixes +* [3711](https://github.com/zeta-chain/node/pull/3711) - fix TON call_data parsing + ## v29.0.3 ### Fixes From da26c3fcd33dd80e4c07c17d8a89404d1a9fd8cd Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Fri, 14 Mar 2025 11:29:04 -0700 Subject: [PATCH 3/3] empty commit