Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ton): TON observer 💎 #2896

Merged
merged 42 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9495518
Use chainParams from base observer
swift1337 Sep 17, 2024
2824c27
Improve base observer Start() semantics
swift1337 Sep 17, 2024
3e3e386
Add pkg/ticker options
swift1337 Sep 17, 2024
555d560
Add TON to pkg/chains & protos
swift1337 Sep 17, 2024
28b1298
Add liteapi wrapper client; locate first tx
swift1337 Sep 18, 2024
7cd1c06
Add TON tx scraper
swift1337 Sep 18, 2024
e0d806f
Add client.GetTransactionsUntil
swift1337 Sep 20, 2024
98a8813
Gateway WIP
swift1337 Sep 23, 2024
861cb4a
Implement Gateway inbound tx parsing
swift1337 Sep 23, 2024
a19a61b
Add Gateway tx filtration
swift1337 Sep 24, 2024
5f14515
Add GetBlockHeader cache; Add masterchain seqno. Implement watchInbound
swift1337 Sep 24, 2024
bfa9af8
Improve ton contracts pkg
swift1337 Sep 27, 2024
feda30f
Add IsTONChain()
swift1337 Sep 27, 2024
2be832f
Refactor Gateway package
swift1337 Sep 27, 2024
0688c47
Implement samples for TON
swift1337 Sep 27, 2024
1fd2cfe
Add liteClient mocks
swift1337 Sep 27, 2024
6619394
Add unit tests for inbound TON observer
swift1337 Sep 29, 2024
ccc1a9d
Localnet: add TON ZRC20
swift1337 Sep 30, 2024
9669adc
Wire the TON observer into the orchestrator
swift1337 Sep 30, 2024
2c1f47c
Add TON chain params of the fly!
swift1337 Oct 1, 2024
b19333f
TON deposits E2E wip
swift1337 Oct 2, 2024
a2acaf6
Fix bugs during cctx;
swift1337 Oct 2, 2024
2642694
TON Deposits E2E 🫡✅
swift1337 Oct 2, 2024
0a3fbad
TON Deposit And Call E2E
swift1337 Oct 3, 2024
ed1f322
Merge branch 'develop' into feat/ton-observer
swift1337 Oct 3, 2024
6eda977
Merge fixes
swift1337 Oct 3, 2024
7b2f232
Update changelog
swift1337 Oct 3, 2024
142778b
gosec
swift1337 Oct 3, 2024
3f8f989
Improve testing
swift1337 Oct 3, 2024
f5a4701
Simplify ticker.Stop(). Leverage ctx.cancel()
swift1337 Oct 3, 2024
2de851d
Simplify E2E
swift1337 Oct 4, 2024
d25a79a
Simplify liteapi semantics
swift1337 Oct 4, 2024
b313ded
Fix comments
swift1337 Oct 4, 2024
e0218c8
Update zetaclient/chains/base/observer.go
swift1337 Oct 4, 2024
cfd4728
Add gw explanatory comments; address PR comments
swift1337 Oct 7, 2024
dd04380
Merge branch 'feat/ton-observer' of github.com:zeta-chain/node into f…
swift1337 Oct 7, 2024
e16eefc
Merge branch 'develop' into feat/ton-observer
swift1337 Oct 7, 2024
c43ae26
Apply fixes for AI suggestions
swift1337 Oct 7, 2024
2bbc791
Merge branch 'develop' into feat/ton-observer
swift1337 Oct 9, 2024
126f966
Fix upgrade tests
swift1337 Oct 9, 2024
1daa056
Merge branch 'feat/ton-observer' of github.com:zeta-chain/node into f…
swift1337 Oct 9, 2024
906e8e9
Merge branch 'develop' into feat/ton-observer
swift1337 Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* [2911](https://github.com/zeta-chain/node/pull/2911) - add chain static information for btc testnet4
* [2904](https://github.com/zeta-chain/node/pull/2904) - integrate authenticated calls smart contract functionality into protocol
* [2919](https://github.com/zeta-chain/node/pull/2919) - add inbound sender to revert context
* [2896](https://github.com/zeta-chain/node/pull/2896) - add TON inbound observation

### Refactor

Expand Down
1 change: 1 addition & 0 deletions cmd/zetae2e/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func ExportContractsFromRunner(r *runner.E2ERunner, conf config.Config) config.C
conf.Contracts.ZEVM.ERC20ZRC20Addr = config.DoubleQuotedString(r.ERC20ZRC20Addr.Hex())
conf.Contracts.ZEVM.BTCZRC20Addr = config.DoubleQuotedString(r.BTCZRC20Addr.Hex())
conf.Contracts.ZEVM.SOLZRC20Addr = config.DoubleQuotedString(r.SOLZRC20Addr.Hex())
conf.Contracts.ZEVM.TONZRC20Addr = config.DoubleQuotedString(r.TONZRC20Addr.Hex())
conf.Contracts.ZEVM.UniswapFactoryAddr = config.DoubleQuotedString(r.UniswapV2FactoryAddr.Hex())
conf.Contracts.ZEVM.UniswapRouterAddr = config.DoubleQuotedString(r.UniswapV2RouterAddr.Hex())
conf.Contracts.ZEVM.ConnectorZEVMAddr = config.DoubleQuotedString(r.ConnectorZEVMAddr.Hex())
Expand Down
11 changes: 11 additions & 0 deletions cmd/zetae2e/config/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ func setContractsFromConfig(r *runner.E2ERunner, conf config.Config) error {
}
}

if c := conf.Contracts.ZEVM.TONZRC20Addr; c != "" {
r.TONZRC20Addr, err = c.AsEVMAddress()
if err != nil {
return fmt.Errorf("invalid TONZRC20Addr: %w", err)
}
r.TONZRC20, err = zrc20.NewZRC20(r.TONZRC20Addr, r.ZEVMClient)
if err != nil {
return err
}
}

if c := conf.Contracts.ZEVM.UniswapFactoryAddr; c != "" {
r.UniswapV2FactoryAddr, err = c.AsEVMAddress()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) {

tonTests := []string{
e2etests.TestTONDepositName,
e2etests.TestTONDepositAndCallName,
}

eg.Go(tonTestRoutine(conf, deployerRunner, verbose, tonTests...))
Expand Down
1 change: 1 addition & 0 deletions cmd/zetae2e/local/ton.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func tonTestRoutine(
deployerRunner,
conf.DefaultAccount,
runner.NewLogger(verbose, color.FgCyan, "ton"),
runner.WithZetaTxServer(deployerRunner.ZetaTxServer),
)
if err != nil {
return errors.Wrap(err, "unable to init ton test runner")
Expand Down
4 changes: 4 additions & 0 deletions docs/openapi/openapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56998,7 +56998,9 @@ definitions:
- bitcoin
- op_stack
- solana_consensus
- catchain_consensus
default: ethereum
description: '- catchain_consensus: ton'
title: |-
Consensus represents the consensus algorithm used by the chain
this can represent the consensus of a L1
Expand All @@ -57014,6 +57016,7 @@ definitions:
- optimism
- base
- solana
- ton
default: eth
title: |-
Network represents the network of the chain
Expand Down Expand Up @@ -57048,6 +57051,7 @@ definitions:
- no_vm
- evm
- svm
- tvm
default: no_vm
title: |-
Vm represents the virtual machine type of the chain to support smart
Expand Down
1 change: 1 addition & 0 deletions e2e/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ type ZEVM struct {
ERC20ZRC20Addr DoubleQuotedString `yaml:"erc20_zrc20"`
BTCZRC20Addr DoubleQuotedString `yaml:"btc_zrc20"`
SOLZRC20Addr DoubleQuotedString `yaml:"sol_zrc20"`
TONZRC20Addr DoubleQuotedString `yaml:"ton_zrc20"`
UniswapFactoryAddr DoubleQuotedString `yaml:"uniswap_factory"`
UniswapRouterAddr DoubleQuotedString `yaml:"uniswap_router"`
ConnectorZEVMAddr DoubleQuotedString `yaml:"connector_zevm"`
Expand Down
13 changes: 11 additions & 2 deletions e2e/e2etests/e2etests.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ const (
/**
* TON tests
*/
TestTONDepositName = "ton_deposit"
TestTONDepositName = "ton_deposit"
TestTONDepositAndCallName = "ton_deposit_and_call"

/*
Bitcoin tests
Expand Down Expand Up @@ -444,10 +445,18 @@ var AllE2ETests = []runner.E2ETest{
TestTONDepositName,
"deposit TON into ZEVM",
[]runner.ArgDefinition{
{Description: "amount in nano tons", DefaultValue: "900000000"}, // 0.9 TON
{Description: "amount in nano tons", DefaultValue: "1000000000"}, // 1.0 TON
},
TestTONDeposit,
),
runner.NewE2ETest(
TestTONDepositAndCallName,
"deposit TON into ZEVM and call a contract",
[]runner.ArgDefinition{
{Description: "amount in nano tons", DefaultValue: "1000000000"}, // 1.0 TON
},
TestTONDepositAndCall,
),
/*
Bitcoin tests
*/
Expand Down
5 changes: 5 additions & 0 deletions e2e/e2etests/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"math/big"
"strconv"

"cosmossdk.io/math"
"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
Expand Down Expand Up @@ -144,6 +145,10 @@ func parseBigInt(t require.TestingT, s string) *big.Int {
return v
}

func parseUint(t require.TestingT, s string) math.Uint {
return math.NewUintFromBigInt(parseBigInt(t, s))
}

// bigIntFromFloat64 takes float64 (e.g. 0.001) that represents btc amount
// and converts it to big.Int for downstream usage.
func btcAmountFromFloat64(t require.TestingT, amount float64) *big.Int {
Expand Down
80 changes: 61 additions & 19 deletions e2e/e2etests/test_ton_deposit.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,84 @@
package e2etests

import (
"time"

"cosmossdk.io/math"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/stretchr/testify/require"

"github.com/zeta-chain/node/e2e/runner"
"github.com/zeta-chain/node/e2e/runner/ton"
"github.com/zeta-chain/node/pkg/chains"
toncontracts "github.com/zeta-chain/node/pkg/contracts/ton"
"github.com/zeta-chain/node/testutil/sample"
crosschainTypes "github.com/zeta-chain/node/x/crosschain/types"
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
)

// TestTONDeposit (!) This boilerplate is a demonstration of E2E capabilities for TON integration
// Actual Deposit test is not implemented yet.
func TestTONDeposit(r *runner.E2ERunner, _ []string) {
ctx, deployer := r.Ctx, r.TONDeployer
// we need to use this send mode due to how wallet V5 works
//
// https://github.com/tonkeeper/w5/blob/main/contracts/wallet_v5.fc#L82
// https://docs.ton.org/develop/smart-contracts/guidelines/message-modes-cookbook
const tonDepositSendCode = toncontracts.SendFlagSeparateFees + toncontracts.SendFlagIgnoreErrors

func TestTONDeposit(r *runner.E2ERunner, args []string) {
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
require.Len(r, args, 1)

// Given deployer
deployerBalance, err := deployer.GetBalance(ctx)
require.NoError(r, err, "failed to get deployer balance")
require.NotZero(r, deployerBalance, "deployer balance is zero")
ctx, deployer, chain := r.Ctx, r.TONDeployer, chains.TONLocalnet

// Given amount
amount := parseUint(r, args[0])

// https://github.com/zeta-chain/protocol-contracts-ton/blob/main/contracts/gateway.fc#L28
// (will be optimized & dynamic in the future)
depositFee := math.NewUint(10_000_000)

// Given TON Gateway
gw := toncontracts.NewGateway(r.TONGateway)

// Given sample wallet with a balance of 50 TON
sender, err := deployer.CreateWallet(ctx, ton.TONCoins(50))
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(r, err)

// That was funded (again) but the faucet
_, err = deployer.Fund(ctx, sender.GetAddress(), ton.TONCoins(30))
// Given sample EVM address
recipient := sample.EthAddress()

// ACT
r.Logger.Info(
"Sending deposit of %s TON from %s to zEVM %s",
amount.String(),
sender.GetAddress().ToRaw(),
recipient.Hex(),
)

err = gw.SendDeposit(ctx, sender, amount, recipient, tonDepositSendCode)

// ASSERT
require.NoError(r, err)

// Check sender balance
sb, err := sender.GetBalance(ctx)
// Wait for CCTX mining
filter := func(cctx *crosschainTypes.CrossChainTx) bool {
return cctx.InboundParams.SenderChainId == chain.ChainId &&
cctx.InboundParams.Sender == sender.GetAddress().ToRaw()
}

cctxs := r.WaitForSpecificCCTX(filter, time.Minute)
require.Len(r, cctxs, 1)

cctx := r.WaitForMinedCCTXFromIndex(cctxs[0].Index)

// Check CCTX
expectedDeposit := amount.Sub(depositFee)

require.Equal(r, sender.GetAddress().ToRaw(), cctx.InboundParams.Sender)
require.Equal(r, expectedDeposit.Uint64(), cctx.InboundParams.Amount.Uint64())

// Check sender's balance
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
balance, err := r.TONZRC20.BalanceOf(&bind.CallOpts{}, recipient)
require.NoError(r, err)

senderBalance := math.NewUint(sb)
r.Logger.Info("Recipient's zEVM TON balance after deposit: %d", balance.Uint64())

// note that it's not exactly 80 TON, but 79.99... due to gas fees
// We'll tackle gas math later.
r.Logger.Print(
"Balance of sender (%s): %s",
sender.GetAddress().ToHuman(false, true),
ton.FormatCoins(senderBalance),
)
require.Equal(r, expectedDeposit.Uint64(), balance.Uint64())
}
84 changes: 84 additions & 0 deletions e2e/e2etests/test_ton_deposit_and_call.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package e2etests

import (
"time"

"cosmossdk.io/math"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/stretchr/testify/require"

"github.com/zeta-chain/node/e2e/runner"
"github.com/zeta-chain/node/e2e/runner/ton"
"github.com/zeta-chain/node/e2e/utils"
"github.com/zeta-chain/node/pkg/chains"
toncontracts "github.com/zeta-chain/node/pkg/contracts/ton"
testcontract "github.com/zeta-chain/node/testutil/contracts"
crosschainTypes "github.com/zeta-chain/node/x/crosschain/types"
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
)

func TestTONDepositAndCall(r *runner.E2ERunner, args []string) {
require.Len(r, args, 1)

// Given deployer
ctx, deployer, chain := r.Ctx, r.TONDeployer, chains.TONLocalnet

// Given amount
amount := parseUint(r, args[0])

// https://github.com/zeta-chain/protocol-contracts-ton/blob/main/contracts/gateway.fc#L28
// (will be optimized & dynamic in the future)
depositFee := math.NewUint(10_000_000)

// Given TON Gateway
gw := toncontracts.NewGateway(r.TONGateway)

// Given sample wallet with a balance of 50 TON
sender, err := deployer.CreateWallet(ctx, ton.TONCoins(50))
require.NoError(r, err)

// Given sample zEVM contract
contractAddr, _, contract, err := testcontract.DeployExample(r.ZEVMAuth, r.ZEVMClient)
require.NoError(r, err)
r.Logger.Info("Example zevm contract deployed at: %s", contractAddr.String())

// Given call data
callData := []byte("hello from TON!")

// ACT
r.Logger.Info(
"Sending deposit of %s TON from %s to zEVM %s and calling contract with %q",
amount.String(),
sender.GetAddress().ToRaw(),
contractAddr.Hex(),
string(callData),
)

err = gw.SendDepositAndCall(ctx, sender, amount, contractAddr, callData, tonDepositSendCode)

// ASSERT
require.NoError(r, err)

// Wait for CCTX mining
filter := func(cctx *crosschainTypes.CrossChainTx) bool {
return cctx.InboundParams.SenderChainId == chain.ChainId &&
cctx.InboundParams.Sender == sender.GetAddress().ToRaw()
}

cctxs := r.WaitForSpecificCCTX(filter, time.Minute)
require.Len(r, cctxs, 1)

r.WaitForMinedCCTXFromIndex(cctxs[0].Index)

expectedDeposit := amount.Sub(depositFee)

// check if example contract has been called, bar value should be set to amount
utils.MustHaveCalledExampleContract(r, contract, expectedDeposit.BigInt())

// Check sender's balance
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
balance, err := r.TONZRC20.BalanceOf(&bind.CallOpts{}, contractAddr)
require.NoError(r, err)

r.Logger.Info("Contract's zEVM TON balance after deposit: %d", balance.Uint64())

require.Equal(r, expectedDeposit.Uint64(), balance.Uint64())
}
8 changes: 8 additions & 0 deletions e2e/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ type E2ERunner struct {
BTCZRC20 *zrc20.ZRC20
SOLZRC20Addr ethcommon.Address
SOLZRC20 *zrc20.ZRC20
TONZRC20Addr ethcommon.Address
TONZRC20 *zrc20.ZRC20
UniswapV2FactoryAddr ethcommon.Address
UniswapV2Factory *uniswapv2factory.UniswapV2Factory
UniswapV2RouterAddr ethcommon.Address
Expand Down Expand Up @@ -230,6 +232,7 @@ func (r *E2ERunner) CopyAddressesFrom(other *E2ERunner) (err error) {
r.ETHZRC20Addr = other.ETHZRC20Addr
r.BTCZRC20Addr = other.BTCZRC20Addr
r.SOLZRC20Addr = other.SOLZRC20Addr
r.TONZRC20Addr = other.TONZRC20Addr
r.UniswapV2FactoryAddr = other.UniswapV2FactoryAddr
r.UniswapV2RouterAddr = other.UniswapV2RouterAddr
r.ConnectorZEVMAddr = other.ConnectorZEVMAddr
Expand Down Expand Up @@ -275,6 +278,10 @@ func (r *E2ERunner) CopyAddressesFrom(other *E2ERunner) (err error) {
if err != nil {
return err
}
r.TONZRC20, err = zrc20.NewZRC20(r.TONZRC20Addr, r.ZEVMClient)
if err != nil {
return err
}
r.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(r.UniswapV2FactoryAddr, r.ZEVMClient)
if err != nil {
return err
Expand Down Expand Up @@ -359,6 +366,7 @@ func (r *E2ERunner) PrintContractAddresses() {
r.Logger.Print("ERC20ZRC20: %s", r.ERC20ZRC20Addr.Hex())
r.Logger.Print("BTCZRC20: %s", r.BTCZRC20Addr.Hex())
r.Logger.Print("SOLZRC20: %s", r.SOLZRC20Addr.Hex())
r.Logger.Print("TONZRC20: %s", r.TONZRC20Addr.Hex())
r.Logger.Print("UniswapFactory: %s", r.UniswapV2FactoryAddr.Hex())
r.Logger.Print("UniswapRouter: %s", r.UniswapV2RouterAddr.Hex())
r.Logger.Print("ConnectorZEVM: %s", r.ConnectorZEVMAddr.Hex())
Expand Down
Loading
Loading