From 94163a1173eb30e9b4b44154878a384214d1bc84 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Thu, 29 Aug 2024 11:35:12 -0500 Subject: [PATCH] initiate impl of Solana restricted address --- cmd/zetaclientd/init.go | 4 +- cmd/zetae2e/local/local.go | 2 + e2e/e2etests/e2etests.go | 23 ++++++- e2e/e2etests/helpers.go | 29 +++++++++ ...est_bitcoin_withdraw_restricted_address.go | 4 +- .../test_erc20_deposit_restricted_address.go | 4 +- .../test_eth_withdraw_restricted_address.go | 4 +- .../test_solana_deposit_restricted_address.go | 21 +++++++ ...test_solana_withdraw_restricted_address.go | 36 +++++++++++ .../test_zeta_deposit_restricted_address.go | 4 +- e2e/runner/poste2e_checker.go | 61 +++++++++++++++++++ e2e/runner/setup_zeta.go | 4 +- e2e/runner/solana.go | 8 ++- e2e/runner/trackers.go | 18 ------ testutil/sample/zetaclient.go | 19 ++++++ zetaclient/chains/solana/observer/outbound.go | 7 +++ zetaclient/chains/solana/signer/signer.go | 18 +++++- zetaclient/chains/solana/signer/withdraw.go | 7 ++- zetaclient/testutils/testdata.go | 19 ++---- 19 files changed, 243 insertions(+), 49 deletions(-) create mode 100644 e2e/e2etests/test_solana_deposit_restricted_address.go create mode 100644 e2e/e2etests/test_solana_withdraw_restricted_address.go create mode 100644 e2e/runner/poste2e_checker.go delete mode 100644 e2e/runner/trackers.go diff --git a/cmd/zetaclientd/init.go b/cmd/zetaclientd/init.go index 2d3e67d698..9dd20090ac 100644 --- a/cmd/zetaclientd/init.go +++ b/cmd/zetaclientd/init.go @@ -4,8 +4,8 @@ import ( "github.com/rs/zerolog" "github.com/spf13/cobra" + "github.com/zeta-chain/zetacore/testutil/sample" "github.com/zeta-chain/zetacore/zetaclient/config" - "github.com/zeta-chain/zetacore/zetaclient/testutils" ) var InitCmd = &cobra.Command{ @@ -110,7 +110,7 @@ func Initialize(_ *cobra.Command, _ []string) error { configData.HsmMode = initArgs.HsmMode configData.HsmHotKey = initArgs.HsmHotKey configData.RelayerKeyPath = initArgs.RelayerKeyPath - configData.ComplianceConfig = testutils.ComplianceConfigTest() + configData.ComplianceConfig = sample.ComplianceConfig() // Save config file return config.Save(&configData, rootArgs.zetaCoreHome) diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index dd00666e25..074ed31197 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -360,6 +360,8 @@ func localE2ETest(cmd *cobra.Command, _ []string) { e2etests.TestSolanaWithdrawName, e2etests.TestSolanaDepositAndCallName, e2etests.TestSolanaDepositAndCallRefundName, + e2etests.TestSolanaDepositRestrictedName, + e2etests.TestSolanaWithdrawRestrictedName, } eg.Go(solanaTestRoutine(conf, deployerRunner, verbose, solanaTests...)) } diff --git a/e2e/e2etests/e2etests.go b/e2e/e2etests/e2etests.go index 5b810276db..dc3b6682c9 100644 --- a/e2e/e2etests/e2etests.go +++ b/e2e/e2etests/e2etests.go @@ -2,6 +2,7 @@ package e2etests import ( "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/testutil/sample" ) // List of all e2e test names to be used in zetae2e @@ -58,6 +59,8 @@ const ( TestSolanaWithdrawName = "solana_withdraw" TestSolanaDepositAndCallName = "solana_deposit_and_call" TestSolanaDepositAndCallRefundName = "solana_deposit_and_call_refund" + TestSolanaDepositRestrictedName = "solana_deposit_restricted" + TestSolanaWithdrawRestrictedName = "solana_withdraw_restricted" /* Bitcoin tests @@ -372,7 +375,7 @@ var AllE2ETests = []runner.E2ETest{ TestSolanaDepositName, "deposit SOL into ZEVM", []runner.ArgDefinition{ - {Description: "amount in lamport", DefaultValue: "1200000"}, + {Description: "amount in lamport", DefaultValue: "12000000"}, }, TestSolanaDeposit, ), @@ -400,6 +403,24 @@ var AllE2ETests = []runner.E2ETest{ }, TestSolanaDepositAndCallRefund, ), + runner.NewE2ETest( + TestSolanaDepositRestrictedName, + "deposit SOL into ZEVM restricted address", + []runner.ArgDefinition{ + {Description: "receiver", DefaultValue: sample.RestrictedEVMAddressTest}, + {Description: "amount in lamport", DefaultValue: "1200000"}, + }, + TestSolanaDepositRestricted, + ), + runner.NewE2ETest( + TestSolanaWithdrawRestrictedName, + "withdraw SOL from ZEVM to restricted address", + []runner.ArgDefinition{ + {Description: "receiver", DefaultValue: sample.RestrictedSolAddressTest}, + {Description: "amount in lamport", DefaultValue: "1000000"}, + }, + TestSolanaWithdrawRestricted, + ), /* Bitcoin tests */ diff --git a/e2e/e2etests/helpers.go b/e2e/e2etests/helpers.go index 8146ff52b8..3635e27c17 100644 --- a/e2e/e2etests/helpers.go +++ b/e2e/e2etests/helpers.go @@ -8,11 +8,14 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" "github.com/zeta-chain/zetacore/pkg/chains" + solanacontracts "github.com/zeta-chain/zetacore/pkg/contracts/solana" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -93,6 +96,32 @@ func verifyTransferAmountFromCCTX(r *runner.E2ERunner, cctx *crosschaintypes.Cro } } +// verifySolanaWithdrawalAmountFromCCTX verifies the withdrawn amount on Solana for given CCTX +func verifySolanaWithdrawalAmountFromCCTX(r *runner.E2ERunner, cctx *crosschaintypes.CrossChainTx, amount uint64) { + txHash := cctx.GetCurrentOutboundParam().Hash + r.Logger.Info("outbound hash %s", txHash) + + // convert txHash to signature + sig, err := solana.SignatureFromBase58(txHash) + require.NoError(r, err) + + // query transaction by signature + txResult, err := r.SolanaClient.GetTransaction(r.Ctx, sig, &rpc.GetTransactionOpts{}) + require.NoError(r, err) + + // unmarshal transaction + tx, err := txResult.Transaction.GetTransaction() + require.NoError(r, err) + + // 1st instruction is the withdraw + instruction := tx.Message.Instructions[0] + instWithdrae, err := solanacontracts.ParseInstructionWithdraw(instruction) + require.NoError(r, err) + + // verify the amount + require.Equal(r, amount, instWithdrae.TokenAmount(), "withdraw amount is not correct") +} + // Parse helpers ==========================================> func parseFloat(t require.TestingT, s string) float64 { diff --git a/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go b/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go index 96cdc9ed0a..774c2a7044 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go +++ b/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go @@ -7,7 +7,7 @@ import ( "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/pkg/chains" - "github.com/zeta-chain/zetacore/zetaclient/testutils" + "github.com/zeta-chain/zetacore/testutil/sample" ) func TestBitcoinWithdrawRestricted(r *runner.E2ERunner, args []string) { @@ -24,7 +24,7 @@ func TestBitcoinWithdrawRestricted(r *runner.E2ERunner, args []string) { func withdrawBitcoinRestricted(r *runner.E2ERunner, amount *big.Int) { // use restricted BTC P2WPKH address addressRestricted, err := chains.DecodeBtcAddress( - testutils.RestrictedBtcAddressTest, + sample.RestrictedBtcAddressTest, chains.BitcoinRegtest.ChainId, ) require.NoError(r, err) diff --git a/e2e/e2etests/test_erc20_deposit_restricted_address.go b/e2e/e2etests/test_erc20_deposit_restricted_address.go index ea5dd81252..55f2f809db 100644 --- a/e2e/e2etests/test_erc20_deposit_restricted_address.go +++ b/e2e/e2etests/test_erc20_deposit_restricted_address.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" - "github.com/zeta-chain/zetacore/zetaclient/testutils" + "github.com/zeta-chain/zetacore/testutil/sample" ) func TestERC20DepositRestricted(r *runner.E2ERunner, args []string) { @@ -15,5 +15,5 @@ func TestERC20DepositRestricted(r *runner.E2ERunner, args []string) { amount := parseBigInt(r, args[0]) // deposit ERC20 to restricted address - r.DepositERC20WithAmountAndMessage(ethcommon.HexToAddress(testutils.RestrictedEVMAddressTest), amount, []byte{}) + r.DepositERC20WithAmountAndMessage(ethcommon.HexToAddress(sample.RestrictedEVMAddressTest), amount, []byte{}) } diff --git a/e2e/e2etests/test_eth_withdraw_restricted_address.go b/e2e/e2etests/test_eth_withdraw_restricted_address.go index 89a0ebdee4..b3a3c8a8da 100644 --- a/e2e/e2etests/test_eth_withdraw_restricted_address.go +++ b/e2e/e2etests/test_eth_withdraw_restricted_address.go @@ -8,8 +8,8 @@ import ( "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" + "github.com/zeta-chain/zetacore/testutil/sample" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - "github.com/zeta-chain/zetacore/zetaclient/testutils" ) // TestEtherWithdrawRestricted tests the withdrawal to a restricted receiver address @@ -31,7 +31,7 @@ func TestEtherWithdrawRestricted(r *runner.E2ERunner, args []string) { r.Logger.EVMReceipt(*receipt, "approve") // withdraw - restrictedAddress := ethcommon.HexToAddress(testutils.RestrictedEVMAddressTest) + restrictedAddress := ethcommon.HexToAddress(sample.RestrictedEVMAddressTest) tx, err = r.ETHZRC20.Withdraw(r.ZEVMAuth, restrictedAddress.Bytes(), withdrawalAmount) require.NoError(r, err) diff --git a/e2e/e2etests/test_solana_deposit_restricted_address.go b/e2e/e2etests/test_solana_deposit_restricted_address.go new file mode 100644 index 0000000000..ffa693b183 --- /dev/null +++ b/e2e/e2etests/test_solana_deposit_restricted_address.go @@ -0,0 +1,21 @@ +package e2etests + +import ( + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/zetacore/e2e/runner" +) + +func TestSolanaDepositRestricted(r *runner.E2ERunner, args []string) { + require.Len(r, args, 2) + + // parse restricted address + receiverRestricted := ethcommon.HexToAddress(args[0]) + + // parse deposit amount (in lamports) + depositAmount := parseBigInt(r, args[1]) + + // execute the deposit transaction + r.SOLDepositAndCall(nil, receiverRestricted, depositAmount, nil) +} diff --git a/e2e/e2etests/test_solana_withdraw_restricted_address.go b/e2e/e2etests/test_solana_withdraw_restricted_address.go new file mode 100644 index 0000000000..cafeca743c --- /dev/null +++ b/e2e/e2etests/test_solana_withdraw_restricted_address.go @@ -0,0 +1,36 @@ +package e2etests + +import ( + "fmt" + "math/big" + + "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/pkg/chains" +) + +func TestSolanaWithdrawRestricted(r *runner.E2ERunner, args []string) { + require.Len(r, args, 2) + + // parse restricted address + receiverRestricted, err := chains.DecodeSolanaWalletAddress(args[0]) + require.NoError(r, err, fmt.Sprintf("unable to decode solana wallet address: %s", args[0])) + + // parse withdraw amount (in lamports), approve amount is 1 SOL + approvedAmount := new(big.Int).SetUint64(solana.LAMPORTS_PER_SOL) + withdrawAmount := parseBigInt(r, args[1]) + require.Equal( + r, + -1, + withdrawAmount.Cmp(approvedAmount), + "Withdrawal amount must be less than the approved amount (1e9).", + ) + + // withdraw + cctx := r.WithdrawSOLZRC20(receiverRestricted, withdrawAmount, approvedAmount) + + // the cctx should be cancelled with zero value + verifySolanaWithdrawalAmountFromCCTX(r, cctx, 0) +} diff --git a/e2e/e2etests/test_zeta_deposit_restricted_address.go b/e2e/e2etests/test_zeta_deposit_restricted_address.go index d760ccafbd..cd3985a4b7 100644 --- a/e2e/e2etests/test_zeta_deposit_restricted_address.go +++ b/e2e/e2etests/test_zeta_deposit_restricted_address.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" - "github.com/zeta-chain/zetacore/zetaclient/testutils" + "github.com/zeta-chain/zetacore/testutil/sample" ) func TestZetaDepositRestricted(r *runner.E2ERunner, args []string) { @@ -15,5 +15,5 @@ func TestZetaDepositRestricted(r *runner.E2ERunner, args []string) { amount := parseBigInt(r, args[0]) // Deposit amount to restricted address - r.DepositZetaWithAmount(ethcommon.HexToAddress(testutils.RestrictedEVMAddressTest), amount) + r.DepositZetaWithAmount(ethcommon.HexToAddress(sample.RestrictedEVMAddressTest), amount) } diff --git a/e2e/runner/poste2e_checker.go b/e2e/runner/poste2e_checker.go new file mode 100644 index 0000000000..7c330f0328 --- /dev/null +++ b/e2e/runner/poste2e_checker.go @@ -0,0 +1,61 @@ +package runner + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/protocol-contracts/v2/pkg/zrc20.sol" + + "github.com/zeta-chain/zetacore/testutil/sample" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +// EnsureNoTrackers ensures that there are no trackers left on zetacore +func (r *E2ERunner) EnsureNoTrackers() { + // get all trackers + res, err := r.CctxClient.OutTxTrackerAll( + r.Ctx, + &crosschaintypes.QueryAllOutboundTrackerRequest{}, + ) + require.NoError(r, err) + require.Empty(r, res.OutboundTracker, "there should be no trackers at the end of the test") +} + +// EnsureZeroBalanceOnRestrictedAddress ensures that the balance of the restricted address is zero +func (r *E2ERunner) EnsureZeroBalanceOnRestrictedAddress() { + restrictedAddress := ethcommon.HexToAddress(sample.RestrictedEVMAddressTest) + + // ensure ZETA balance is zero + balance, err := r.WZeta.BalanceOf(&bind.CallOpts{}, restrictedAddress) + require.NoError(r, err) + require.Zero(r, balance.Cmp(big.NewInt(0)), "the wZETA balance of the restricted address should be zero") + + // ensure ZRC20 ETH balance is zero + ensureZRC20ZeroBalance(r, r.ETHZRC20, restrictedAddress) + + // ensure ZRC20 ERC20 balance is zero + ensureZRC20ZeroBalance(r, r.ERC20ZRC20, restrictedAddress) + + // ensure ZRC20 BTC balance is zero + ensureZRC20ZeroBalance(r, r.BTCZRC20, restrictedAddress) + + // ensure ZRC20 SOL balance is zero + ensureZRC20ZeroBalance(r, r.SOLZRC20, restrictedAddress) +} + +// ensureZRC20ZeroBalance ensures that the balance of the ZRC20 token is zero on given address +func ensureZRC20ZeroBalance(r *E2ERunner, zrc20 *zrc20.ZRC20, address ethcommon.Address) { + balance, err := zrc20.BalanceOf(&bind.CallOpts{}, address) + require.NoError(r, err) + + zrc20Name, err := zrc20.Name(&bind.CallOpts{}) + require.NoError(r, err) + require.Zero( + r, + balance.Cmp(big.NewInt(0)), + fmt.Sprintf("the balance of address %s should be zero on ZRC20: %s", address, zrc20Name), + ) +} diff --git a/e2e/runner/setup_zeta.go b/e2e/runner/setup_zeta.go index 4f72f72108..4b731b2301 100644 --- a/e2e/runner/setup_zeta.go +++ b/e2e/runner/setup_zeta.go @@ -67,7 +67,7 @@ func (r *E2ERunner) SetTSSAddresses() error { // SetZEVMSystemContracts set system contracts for the ZEVM func (r *E2ERunner) SetZEVMSystemContracts() { - r.Logger.Print("⚙️ deploying system contracts and ZRC20s on ZEVM") + r.Logger.Print("⚙️ deploying system contracts on ZEVM") startTime := time.Now() defer func() { r.Logger.Info("System contract deployments took %s\n", time.Since(startTime)) @@ -168,7 +168,7 @@ func (r *E2ERunner) SetZEVMSystemContracts() { // SetZEVMZRC20s set ZRC20 for the ZEVM func (r *E2ERunner) SetZEVMZRC20s() { - r.Logger.Print("⚙️ deploying system contracts and ZRC20s on ZEVM") + r.Logger.Print("⚙️ deploying ZRC20s on ZEVM") startTime := time.Now() defer func() { r.Logger.Info("System contract deployments took %s\n", time.Since(startTime)) diff --git a/e2e/runner/solana.go b/e2e/runner/solana.go index 30e089406e..9d7f256c50 100644 --- a/e2e/runner/solana.go +++ b/e2e/runner/solana.go @@ -145,7 +145,11 @@ func (r *E2ERunner) SOLDepositAndCall( } // WithdrawSOLZRC20 withdraws an amount of ZRC20 SOL tokens -func (r *E2ERunner) WithdrawSOLZRC20(to solana.PublicKey, amount *big.Int, approveAmount *big.Int) { +func (r *E2ERunner) WithdrawSOLZRC20( + to solana.PublicKey, + amount *big.Int, + approveAmount *big.Int, +) *crosschaintypes.CrossChainTx { // approve tx, err := r.SOLZRC20.Approve(r.ZEVMAuth, r.SOLZRC20Addr, approveAmount) require.NoError(r, err) @@ -165,4 +169,6 @@ func (r *E2ERunner) WithdrawSOLZRC20(to solana.PublicKey, amount *big.Int, appro // wait for the cctx to be mined cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) + + return cctx } diff --git a/e2e/runner/trackers.go b/e2e/runner/trackers.go deleted file mode 100644 index 2ff27180ed..0000000000 --- a/e2e/runner/trackers.go +++ /dev/null @@ -1,18 +0,0 @@ -package runner - -import ( - "github.com/stretchr/testify/require" - - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -// EnsureNoTrackers ensures that there are no trackers left on zetacore -func (r *E2ERunner) EnsureNoTrackers() { - // get all trackers - res, err := r.CctxClient.OutTxTrackerAll( - r.Ctx, - &crosschaintypes.QueryAllOutboundTrackerRequest{}, - ) - require.NoError(r, err) - require.Empty(r, res.OutboundTracker, "there should be no trackers at the end of the test") -} diff --git a/testutil/sample/zetaclient.go b/testutil/sample/zetaclient.go index 36f9c7292c..e210c37e1b 100644 --- a/testutil/sample/zetaclient.go +++ b/testutil/sample/zetaclient.go @@ -2,9 +2,17 @@ package sample import ( "github.com/zeta-chain/zetacore/pkg/coin" + "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/types" ) +const ( + // These are sample restricted addresses for e2e tests. + RestrictedEVMAddressTest = "0x8a81Ba8eCF2c418CAe624be726F505332DF119C6" + RestrictedBtcAddressTest = "bcrt1qzp4gt6fc7zkds09kfzaf9ln9c5rvrzxmy6qmpp" + RestrictedSolAddressTest = "9fA4vYZfCa9k9UHjnvYCk4YoipsooapGciKMgaTBw9UH" +) + // InboundEvent returns a sample InboundEvent. func InboundEvent(chainID int64, sender string, receiver string, amount uint64, memo []byte) *types.InboundEvent { r := newRandFromSeed(chainID) @@ -23,3 +31,14 @@ func InboundEvent(chainID int64, sender string, receiver string, amount uint64, Asset: StringRandom(r, 32), } } + +// ComplianceConfig returns a sample compliance config +func ComplianceConfig() config.ComplianceConfig { + return config.ComplianceConfig{ + RestrictedAddresses: []string{ + RestrictedEVMAddressTest, + RestrictedBtcAddressTest, + RestrictedSolAddressTest, + }, + } +} diff --git a/zetaclient/chains/solana/observer/outbound.go b/zetaclient/chains/solana/observer/outbound.go index 396e49df1c..eb14f1f320 100644 --- a/zetaclient/chains/solana/observer/outbound.go +++ b/zetaclient/chains/solana/observer/outbound.go @@ -16,6 +16,7 @@ import ( contracts "github.com/zeta-chain/zetacore/pkg/contracts/solana" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" + "github.com/zeta-chain/zetacore/zetaclient/compliance" zctx "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/logs" clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" @@ -159,6 +160,12 @@ func (ob *Observer) VoteOutboundIfConfirmed(ctx context.Context, cctx *crosschai // status was already verified as successful in CheckFinalizedTx outboundStatus := chains.ReceiveStatus_success + // compliance check, special handling the cancelled cctx + if compliance.IsCctxRestricted(cctx) { + // use cctx's amount to bypass the amount check in zetacore + outboundAmount = cctx.GetCurrentOutboundParam().Amount.BigInt() + } + // post vote to zetacore ob.PostVoteOutbound(ctx, cctx.Index, txSig.String(), txResult, outboundAmount, outboundStatus, nonce, coinType) return false, nil diff --git a/zetaclient/chains/solana/signer/signer.go b/zetaclient/chains/solana/signer/signer.go index 2b766a49f5..16b6ce8c1c 100644 --- a/zetaclient/chains/solana/signer/signer.go +++ b/zetaclient/chains/solana/signer/signer.go @@ -16,6 +16,7 @@ import ( observertypes "github.com/zeta-chain/zetacore/x/observer/types" "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" + "github.com/zeta-chain/zetacore/zetaclient/compliance" "github.com/zeta-chain/zetacore/zetaclient/keys" "github.com/zeta-chain/zetacore/zetaclient/metrics" "github.com/zeta-chain/zetacore/zetaclient/outboundprocessor" @@ -126,8 +127,23 @@ func (signer *Signer) TryProcessOutbound( return } + // compliance check + cancelTx := compliance.IsCctxRestricted(cctx) + if cancelTx { + compliance.PrintComplianceLog( + logger, + signer.Logger().Compliance, + true, + chainID, + cctx.Index, + cctx.InboundParams.Sender, + params.Receiver, + "SOL", + ) + } + // sign gateway withdraw message by TSS - msg, err := signer.SignMsgWithdraw(ctx, params, height) + msg, err := signer.SignMsgWithdraw(ctx, params, height, cancelTx) if err != nil { logger.Error().Err(err).Msgf("TryProcessOutbound: SignMsgWithdraw error for chain %d nonce %d", chainID, nonce) return diff --git a/zetaclient/chains/solana/signer/withdraw.go b/zetaclient/chains/solana/signer/withdraw.go index 8b91dc8f23..3800fb13f0 100644 --- a/zetaclient/chains/solana/signer/withdraw.go +++ b/zetaclient/chains/solana/signer/withdraw.go @@ -18,6 +18,7 @@ func (signer *Signer) SignMsgWithdraw( ctx context.Context, params *types.OutboundParams, height uint64, + cancelTx bool, ) (*contracts.MsgWithdraw, error) { chain := signer.Chain() // #nosec G115 always positive @@ -25,6 +26,11 @@ func (signer *Signer) SignMsgWithdraw( nonce := params.TssNonce amount := params.Amount.Uint64() + // zero out the amount if cancelTx is set. It's legal to withdraw 0 lamports thru the gateway. + if cancelTx { + amount = 0 + } + // check receiver address to, err := chains.DecodeSolanaWalletAddress(params.Receiver) if err != nil { @@ -116,7 +122,6 @@ func attachWithdrawAccounts( accountSlice = append(accountSlice, solana.Meta(signer).WRITE().SIGNER()) accountSlice = append(accountSlice, solana.Meta(pda).WRITE()) accountSlice = append(accountSlice, solana.Meta(to).WRITE()) - accountSlice = append(accountSlice, solana.Meta(gatewayID)) inst.ProgID = gatewayID inst.AccountValues = accountSlice diff --git a/zetaclient/testutils/testdata.go b/zetaclient/testutils/testdata.go index 146a73e243..a405a8d378 100644 --- a/zetaclient/testutils/testdata.go +++ b/zetaclient/testutils/testdata.go @@ -15,17 +15,14 @@ import ( "github.com/zeta-chain/zetacore/pkg/coin" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - "github.com/zeta-chain/zetacore/zetaclient/config" testcctx "github.com/zeta-chain/zetacore/zetaclient/testdata/cctx" ) const ( - TestDataPathEVM = "testdata/evm" - TestDataPathBTC = "testdata/btc" - TestDataPathSolana = "testdata/solana" - TestDataPathCctx = "testdata/cctx" - RestrictedEVMAddressTest = "0x8a81Ba8eCF2c418CAe624be726F505332DF119C6" - RestrictedBtcAddressTest = "bcrt1qzp4gt6fc7zkds09kfzaf9ln9c5rvrzxmy6qmpp" + TestDataPathEVM = "testdata/evm" + TestDataPathBTC = "testdata/btc" + TestDataPathSolana = "testdata/solana" + TestDataPathCctx = "testdata/cctx" ) // cloneCctx returns a deep copy of the cctx @@ -50,14 +47,6 @@ func LoadObjectFromJSONFile(t *testing.T, obj interface{}, filename string) { require.NoError(t, err) } -// ComplianceConfigTest returns a test compliance config -// TODO(revamp): move to sample package -func ComplianceConfigTest() config.ComplianceConfig { - return config.ComplianceConfig{ - RestrictedAddresses: []string{RestrictedEVMAddressTest, RestrictedBtcAddressTest}, - } -} - // LoadCctxByInbound loads archived cctx by inbound func LoadCctxByInbound( t *testing.T,