diff --git a/changelog.md b/changelog.md index f7ab3ed979..e37ffefd0c 100644 --- a/changelog.md +++ b/changelog.md @@ -42,6 +42,7 @@ ### Tests * [3692](https://github.com/zeta-chain/node/pull/3692) - e2e staking test for `MsgUndelegate` tx, to test observer staking hooks +* [3831](https://github.com/zeta-chain/node/pull/3831) - e2e tests for sui fungible token withdraw and call ### Refactor diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index 2f6fe4cce0..f6cfd737c6 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -521,11 +521,12 @@ func localE2ETest(cmd *cobra.Command, _ []string) { e2etests.TestSuiTokenDepositAndCallName, e2etests.TestSuiTokenDepositAndCallRevertName, e2etests.TestSuiWithdrawName, - e2etests.TestSuiWithdrawRevertWithCallName, - e2etests.TestSuiTokenWithdrawName, - // https://github.com/zeta-chain/node/issues/3742 e2etests.TestSuiWithdrawAndCallName, + e2etests.TestSuiWithdrawRevertWithCallName, e2etests.TestSuiWithdrawAndCallRevertWithCallName, + e2etests.TestSuiTokenWithdrawName, + e2etests.TestSuiTokenWithdrawAndCallName, + e2etests.TestSuiTokenWithdrawAndCallRevertWithCallName, e2etests.TestSuiDepositRestrictedName, e2etests.TestSuiWithdrawRestrictedName, } diff --git a/e2e/config/config.go b/e2e/config/config.go index 5662fedd20..e071d4f867 100644 --- a/e2e/config/config.go +++ b/e2e/config/config.go @@ -151,7 +151,6 @@ type SuiExample struct { GlobalConfigID DoubleQuotedString `yaml:"global_config_id"` PartnerID DoubleQuotedString `yaml:"partner_id"` ClockID DoubleQuotedString `yaml:"clock_id"` - PoolID DoubleQuotedString `yaml:"pool_id"` } // Sui contains the addresses of predeployed contracts on the Sui chain diff --git a/e2e/contracts/sui/connected.mv b/e2e/contracts/sui/connected.mv index 9923fca1ff..82a298c9a2 100644 Binary files a/e2e/contracts/sui/connected.mv and b/e2e/contracts/sui/connected.mv differ diff --git a/e2e/contracts/sui/example/Makefile b/e2e/contracts/sui/example/Makefile index 6fb133a100..b6e66b5e24 100644 --- a/e2e/contracts/sui/example/Makefile +++ b/e2e/contracts/sui/example/Makefile @@ -10,8 +10,8 @@ clean: # Build the package and generate bytecode build: sui move build - cp build/example/bytecode_modules/token.mv . - cp build/example/bytecode_modules/connected.mv . + cp build/example/bytecode_modules/token.mv ../token.mv + cp build/example/bytecode_modules/connected.mv ../connected.mv # Help target help: diff --git a/e2e/contracts/sui/example/Move.lock b/e2e/contracts/sui/example/Move.lock index 8593c3c4da..066d6a7621 100644 --- a/e2e/contracts/sui/example/Move.lock +++ b/e2e/contracts/sui/example/Move.lock @@ -2,11 +2,10 @@ [move] version = 3 -manifest_digest = "795BC4DE1AC42C1015B85547951A89D7F9AD63EA50982960E095E815C560BFCC" -deps_digest = "397E6A9F7A624706DBDFEE056CE88391A15876868FD18A88504DA74EB458D697" +manifest_digest = "9AE1AA02EF00BB882BBF7AA642D0DDF8A788CB1C25ACA9667399B8001C02CF81" +deps_digest = "F9B494B64F0615AED0E98FC12A85B85ECD2BC5185C22D30E7F67786BB52E507C" dependencies = [ { id = "Bridge", name = "Bridge" }, - { id = "DeepBook", name = "DeepBook" }, { id = "MoveStdlib", name = "MoveStdlib" }, { id = "Sui", name = "Sui" }, { id = "SuiSystem", name = "SuiSystem" }, @@ -14,7 +13,7 @@ dependencies = [ [[move.package]] id = "Bridge" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "9c04e1840eb5", subdir = "crates/sui-framework/packages/bridge" } +source = { git = "https://github.com/MystenLabs/sui.git", rev = "fbb68879cbd1", subdir = "crates/sui-framework/packages/bridge" } dependencies = [ { id = "MoveStdlib", name = "MoveStdlib" }, @@ -22,22 +21,13 @@ dependencies = [ { id = "SuiSystem", name = "SuiSystem" }, ] -[[move.package]] -id = "DeepBook" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "9c04e1840eb5", subdir = "crates/sui-framework/packages/deepbook" } - -dependencies = [ - { id = "MoveStdlib", name = "MoveStdlib" }, - { id = "Sui", name = "Sui" }, -] - [[move.package]] id = "MoveStdlib" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "9c04e1840eb5", subdir = "crates/sui-framework/packages/move-stdlib" } +source = { git = "https://github.com/MystenLabs/sui.git", rev = "fbb68879cbd1", subdir = "crates/sui-framework/packages/move-stdlib" } [[move.package]] id = "Sui" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "9c04e1840eb5", subdir = "crates/sui-framework/packages/sui-framework" } +source = { git = "https://github.com/MystenLabs/sui.git", rev = "fbb68879cbd1", subdir = "crates/sui-framework/packages/sui-framework" } dependencies = [ { id = "MoveStdlib", name = "MoveStdlib" }, @@ -45,7 +35,7 @@ dependencies = [ [[move.package]] id = "SuiSystem" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "9c04e1840eb5", subdir = "crates/sui-framework/packages/sui-system" } +source = { git = "https://github.com/MystenLabs/sui.git", rev = "fbb68879cbd1", subdir = "crates/sui-framework/packages/sui-system" } dependencies = [ { id = "MoveStdlib", name = "MoveStdlib" }, @@ -53,6 +43,6 @@ dependencies = [ ] [move.toolchain-version] -compiler-version = "1.45.0" +compiler-version = "1.47.0" edition = "2024.beta" flavor = "sui" diff --git a/e2e/contracts/sui/example/connected.mv b/e2e/contracts/sui/example/connected.mv deleted file mode 100644 index 9923fca1ff..0000000000 Binary files a/e2e/contracts/sui/example/connected.mv and /dev/null differ diff --git a/e2e/contracts/sui/example/sources/example.move b/e2e/contracts/sui/example/sources/example.move index 6faee61aaf..6967e75360 100644 --- a/e2e/contracts/sui/example/sources/example.move +++ b/e2e/contracts/sui/example/sources/example.move @@ -43,10 +43,13 @@ fun init(ctx: &mut TxContext) { transfer::share_object(clock); } -public entry fun on_call( +public entry fun on_call( in_coins: Coin, cetus_config: &mut GlobalConfig, - _pool: &mut Pool, + // Note: this pool type is hardcoded as and therefore causes type mismatch error in the + // fungible token withdrawAndCall test, where the SOURCE_COIN type is FAKE_USDC instead of TOKEN. + // Disabling the pool object for now is the easiest solution to allow the E2E tests to go through. + // _pool: &mut Pool, _cetus_partner: &mut Partner, _clock: &Clock, data: vector, diff --git a/e2e/contracts/sui/example/token.mv b/e2e/contracts/sui/example/token.mv deleted file mode 100644 index de33978021..0000000000 Binary files a/e2e/contracts/sui/example/token.mv and /dev/null differ diff --git a/e2e/e2etests/e2etests.go b/e2e/e2etests/e2etests.go index d782554527..d71c24e7f0 100644 --- a/e2e/e2etests/e2etests.go +++ b/e2e/e2etests/e2etests.go @@ -95,19 +95,21 @@ const ( /* Sui tests */ - TestSuiDepositName = "sui_deposit" - TestSuiDepositAndCallName = "sui_deposit_and_call" - TestSuiDepositAndCallRevertName = "sui_deposit_and_call_revert" - TestSuiTokenDepositName = "sui_token_deposit" // #nosec G101: Potential hardcoded credentials (gosec), not a credential - TestSuiTokenDepositAndCallName = "sui_token_deposit_and_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential - TestSuiTokenDepositAndCallRevertName = "sui_token_deposit_and_call_revert" // #nosec G101: Potential hardcoded credentials (gosec), not a credential - TestSuiWithdrawName = "sui_withdraw" - TestSuiTokenWithdrawName = "sui_token_withdraw" // #nosec G101: Potential hardcoded credentials (gosec), not a credential - TestSuiWithdrawAndCallName = "sui_withdraw_and_call" - TestSuiWithdrawRevertWithCallName = "sui_withdraw_revert_with_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential - TestSuiWithdrawAndCallRevertWithCallName = "sui_withdraw_and_call_revert_with_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential - TestSuiDepositRestrictedName = "sui_deposit_restricted" - TestSuiWithdrawRestrictedName = "sui_withdraw_restricted" + TestSuiDepositName = "sui_deposit" + TestSuiDepositAndCallName = "sui_deposit_and_call" + TestSuiDepositAndCallRevertName = "sui_deposit_and_call_revert" + TestSuiTokenDepositName = "sui_token_deposit" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiTokenDepositAndCallName = "sui_token_deposit_and_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiTokenDepositAndCallRevertName = "sui_token_deposit_and_call_revert" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiWithdrawName = "sui_withdraw" + TestSuiTokenWithdrawName = "sui_token_withdraw" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiTokenWithdrawAndCallName = "sui_token_withdraw_and_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiTokenWithdrawAndCallRevertWithCallName = "sui_token_withdraw_and_call_revert_with_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiWithdrawAndCallName = "sui_withdraw_and_call" + TestSuiWithdrawRevertWithCallName = "sui_withdraw_revert_with_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiWithdrawAndCallRevertWithCallName = "sui_withdraw_and_call_revert_with_call" // #nosec G101: Potential hardcoded credentials (gosec), not a credential + TestSuiDepositRestrictedName = "sui_deposit_restricted" + TestSuiWithdrawRestrictedName = "sui_withdraw_restricted" /* Bitcoin tests @@ -902,6 +904,24 @@ var AllE2ETests = []runner.E2ETest{ TestSuiTokenWithdraw, runner.WithMinimumVersion("v29.0.0"), ), + runner.NewE2ETest( + TestSuiTokenWithdrawAndCallName, + "withdraw fungible token from ZEVM and call a contract", + []runner.ArgDefinition{ + {Description: "amount in base unit", DefaultValue: "100000"}, + }, + TestSuiTokenWithdrawAndCall, + runner.WithMinimumVersion("v30.0.0"), + ), + runner.NewE2ETest( + TestSuiTokenWithdrawAndCallRevertWithCallName, + "withdraw fungible token from ZEVM and call a contract that reverts with a onRevert call", + []runner.ArgDefinition{ + {Description: "amount in base unit", DefaultValue: "1000000"}, + }, + TestSuiTokenWithdrawAndCallRevertWithCall, + runner.WithMinimumVersion("v30.0.0"), + ), runner.NewE2ETest( TestSuiDepositRestrictedName, "deposit SUI into ZEVM restricted address", diff --git a/e2e/e2etests/test_sui_token_withdraw_and_call.go b/e2e/e2etests/test_sui_token_withdraw_and_call.go new file mode 100644 index 0000000000..4af1225a20 --- /dev/null +++ b/e2e/e2etests/test_sui_token_withdraw_and_call.go @@ -0,0 +1,62 @@ +package e2etests + +import ( + "math/big" + + "github.com/stretchr/testify/require" + "github.com/zeta-chain/protocol-contracts/pkg/gatewayzevm.sol" + + "github.com/zeta-chain/node/e2e/runner" + "github.com/zeta-chain/node/e2e/utils" + crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" +) + +func TestSuiTokenWithdrawAndCall(r *runner.E2ERunner, args []string) { + require.Len(r, args, 1) + + // ARRANGE + // Given target package ID (example package) and a token amount + targetPackageID := r.SuiExample.PackageID.String() + amount := utils.ParseBigInt(r, args[0]) + + // use the deployer address as on_call payload message + signer, err := r.Account.SuiSigner() + require.NoError(r, err, "get deployer signer") + suiAddress := signer.Address() + + // Given initial balance and called_count + balanceBefore := r.SuiGetFungibleTokenBalance(suiAddress) + calledCountBefore := r.SuiGetConnectedCalledCount() + + // create the on_call payload + payloadOnCall, err := r.SuiCreateExampleWACPayload(suiAddress) + require.NoError(r, err) + + // ACT + // approve both SUI gas budget token and fungible token ZRC20 + r.ApproveSUIZRC20(r.GatewayZEVMAddr) + r.ApproveFungibleTokenZRC20(r.GatewayZEVMAddr) + + // perform the fungible token withdraw and call + tx := r.SuiWithdrawAndCallFungibleToken( + targetPackageID, + amount, + payloadOnCall, + gatewayzevm.RevertOptions{OnRevertGasLimit: big.NewInt(0)}, + ) + r.Logger.EVMTransaction(*tx, "withdraw_and_call") + + // ASSERT + // wait for the cctx to be mined + cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "withdraw") + require.EqualValues(r, crosschaintypes.CctxStatus_OutboundMined, cctx.CctxStatus.Status) + + // check the balance after the withdraw + balanceAfter := r.SuiGetFungibleTokenBalance(signer.Address()) + require.EqualValues(r, balanceBefore+amount.Uint64(), balanceAfter) + + // verify the called_count increased by 1 + calledCountAfter := r.SuiGetConnectedCalledCount() + require.Equal(r, calledCountBefore+1, calledCountAfter) +} diff --git a/e2e/e2etests/test_sui_token_withdraw_and_call_revert_with_call.go b/e2e/e2etests/test_sui_token_withdraw_and_call_revert_with_call.go new file mode 100644 index 0000000000..82fdb0ae6d --- /dev/null +++ b/e2e/e2etests/test_sui_token_withdraw_and_call_revert_with_call.go @@ -0,0 +1,82 @@ +package e2etests + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/protocol-contracts/pkg/gatewayzevm.sol" + + "github.com/zeta-chain/node/e2e/runner" + "github.com/zeta-chain/node/e2e/utils" + "github.com/zeta-chain/node/testutil/sample" + crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" +) + +// TestSuiTokenWithdrawAndCallRevertWithCall executes withdrawAndCall on zevm gateway with fungible token. +// The outbound is rejected by the connected module due to invalid payload (invalid address), +// and 'onRevert' is called instead to handle the revert. +func TestSuiTokenWithdrawAndCallRevertWithCall(r *runner.E2ERunner, args []string) { + require.Len(r, args, 1) + + // ARRANGE + // Given target package ID (example package) and a token amount + targetPackageID := r.SuiExample.PackageID.String() + amount := utils.ParseBigInt(r, args[0]) + + // create the payload for 'on_call' with invalid address + // taking the first 10 letters to form an invalid address + invalidAddress := sample.SuiAddress(r)[:10] + payloadOnCall, err := r.SuiCreateExampleWACPayload(invalidAddress) + require.NoError(r, err) + + // given ZEVM revert address (the dApp) + dAppAddress := r.TestDAppV2ZEVMAddr + dAppBalanceBefore, err := r.SuiTokenZRC20.BalanceOf(&bind.CallOpts{}, dAppAddress) + require.NoError(r, err) + + // given random payload for 'onRevert' + payloadOnRevert := randomPayload(r) + r.AssertTestDAppEVMCalled(false, payloadOnRevert, amount) + + // ACT + // approve both SUI gas budget token and fungible token ZRC20 + r.ApproveSUIZRC20(r.GatewayZEVMAddr) + r.ApproveFungibleTokenZRC20(r.GatewayZEVMAddr) + + // perform the withdraw and call with revert options + tx := r.SuiWithdrawAndCallFungibleToken( + targetPackageID, + amount, + payloadOnCall, + gatewayzevm.RevertOptions{ + CallOnRevert: true, + RevertAddress: dAppAddress, + RevertMessage: []byte(payloadOnRevert), + OnRevertGasLimit: big.NewInt(0), + }, + ) + r.Logger.EVMTransaction(*tx, "withdraw_and_call") + + // ASSERT + // wait for the cctx to be reverted + cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "withdraw") + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_Reverted) + + // should have called 'onRevert' + r.AssertTestDAppZEVMCalled(true, payloadOnRevert, big.NewInt(0)) + + // sender and message should match + sender, err := r.TestDAppV2ZEVM.SenderWithMessage( + &bind.CallOpts{}, + []byte(payloadOnRevert), + ) + require.NoError(r, err) + require.Equal(r, r.ZEVMAuth.From, sender) + + // the dApp address should get reverted amount + dAppBalanceAfter, err := r.SuiTokenZRC20.BalanceOf(&bind.CallOpts{}, dAppAddress) + require.NoError(r, err) + require.Equal(r, amount.Int64(), dAppBalanceAfter.Int64()-dAppBalanceBefore.Int64()) +} diff --git a/e2e/e2etests/test_sui_withdraw_and_call.go b/e2e/e2etests/test_sui_withdraw_and_call.go index 95fbc94f5e..484806dd12 100644 --- a/e2e/e2etests/test_sui_withdraw_and_call.go +++ b/e2e/e2etests/test_sui_withdraw_and_call.go @@ -1,7 +1,6 @@ package e2etests import ( - "encoding/hex" "math/big" "github.com/stretchr/testify/require" @@ -9,7 +8,6 @@ import ( "github.com/zeta-chain/node/e2e/runner" "github.com/zeta-chain/node/e2e/utils" - "github.com/zeta-chain/node/pkg/contracts/sui" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" ) @@ -21,29 +19,18 @@ func TestSuiWithdrawAndCall(r *runner.E2ERunner, args []string) { targetPackageID := r.SuiExample.PackageID.String() amount := utils.ParseBigInt(r, args[0]) - // Given example contract on_call function arguments - argumentTypes := []string{ - r.SuiExample.TokenType.String(), - } - objects := []string{ - r.SuiExample.GlobalConfigID.String(), - r.SuiExample.PoolID.String(), - r.SuiExample.PartnerID.String(), - r.SuiExample.ClockID.String(), - } + // use the deployer address as on_call payload message + signer, err := r.Account.SuiSigner() + require.NoError(r, err, "get deployer signer") + suiAddress := signer.Address() - // define a deterministic address and use it for on_call payload message - // the example contract will just forward the withdrawn SUI token to this address - suiAddress := "0x34a30aaee833d649d7313ddfe4ff5b6a9bac48803236b919369e6636fe93392e" - message, err := hex.DecodeString(suiAddress[2:]) // remove 0x prefix - require.NoError(r, err) + // Given initial balance and called_count balanceBefore := r.SuiGetSUIBalance(suiAddress) - - // query the called_count before withdraw and call calledCountBefore := r.SuiGetConnectedCalledCount() - // create the payload - payload := sui.NewCallPayload(argumentTypes, objects, message) + // create the on_call payload + payloadOnCall, err := r.SuiCreateExampleWACPayload(suiAddress) + require.NoError(r, err) // ACT // approve SUI ZRC20 token @@ -53,7 +40,7 @@ func TestSuiWithdrawAndCall(r *runner.E2ERunner, args []string) { tx := r.SuiWithdrawAndCallSUI( targetPackageID, amount, - payload, + payloadOnCall, gatewayzevm.RevertOptions{OnRevertGasLimit: big.NewInt(0)}, ) r.Logger.EVMTransaction(*tx, "withdraw_and_call") diff --git a/e2e/e2etests/test_sui_withdraw_and_call_revert_with_call.go b/e2e/e2etests/test_sui_withdraw_and_call_revert_with_call.go index 87d00f15e3..ee0bd41e19 100644 --- a/e2e/e2etests/test_sui_withdraw_and_call_revert_with_call.go +++ b/e2e/e2etests/test_sui_withdraw_and_call_revert_with_call.go @@ -1,7 +1,6 @@ package e2etests import ( - "encoding/hex" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -10,11 +9,11 @@ import ( "github.com/zeta-chain/node/e2e/runner" "github.com/zeta-chain/node/e2e/utils" - "github.com/zeta-chain/node/pkg/contracts/sui" + "github.com/zeta-chain/node/testutil/sample" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" ) -// TestSuiWithdrawAndCallRevertWithCall executes withdraw and call on zevm gateway. +// TestSuiWithdrawAndCallRevertWithCall executes withdrawAndCall on zevm gateway with SUI token. // The outbound is rejected by the connected module due to invalid payload (invalid address), // and 'onRevert' is called instead to handle the revert. func TestSuiWithdrawAndCallRevertWithCall(r *runner.E2ERunner, args []string) { @@ -25,20 +24,10 @@ func TestSuiWithdrawAndCallRevertWithCall(r *runner.E2ERunner, args []string) { targetPackageID := r.SuiExample.PackageID.String() amount := utils.ParseBigInt(r, args[0]) - // Given example contract on_call function arguments - argumentTypes := []string{ - r.SuiExample.TokenType.String(), - } - objects := []string{ - r.SuiExample.GlobalConfigID.String(), - r.SuiExample.PoolID.String(), - r.SuiExample.PartnerID.String(), - r.SuiExample.ClockID.String(), - } - - // define an invalid address to cause 'on_call' failure - invalidAddress := "8f569597ebca884b784d32678a6f" - message, err := hex.DecodeString(invalidAddress) + // create the payload for 'on_call' with invalid address + // taking the first 10 letters to form an invalid address + invalidAddress := sample.SuiAddress(r)[:10] + payloadOnCall, err := r.SuiCreateExampleWACPayload(invalidAddress) require.NoError(r, err) // given ZEVM revert address (the dApp) @@ -50,9 +39,6 @@ func TestSuiWithdrawAndCallRevertWithCall(r *runner.E2ERunner, args []string) { payloadOnRevert := randomPayload(r) r.AssertTestDAppEVMCalled(false, payloadOnRevert, amount) - // create the payload for 'on_call' - payloadOnCall := sui.NewCallPayload(argumentTypes, objects, message) - // ACT // approve SUI ZRC20 token r.ApproveSUIZRC20(r.GatewayZEVMAddr) diff --git a/e2e/runner/setup_sui.go b/e2e/runner/setup_sui.go index ab3fd614e1..a86055d2c7 100644 --- a/e2e/runner/setup_sui.go +++ b/e2e/runner/setup_sui.go @@ -147,10 +147,9 @@ func (r *E2ERunner) suiDeployExample() { filterGlobalConfigType = "connected::GlobalConfig" filterPartnerType = "connected::Partner" filterClockType = "connected::Clock" - filterPoolType = "connected::Pool" ) - objectTypeFilters := []string{filterGlobalConfigType, filterPartnerType, filterClockType, filterPoolType} + objectTypeFilters := []string{filterGlobalConfigType, filterPartnerType, filterClockType} packageID, objectIDs := r.suiDeployPackage( []string{suicontract.ExampleFungibleTokenBytecodeBase64(), suicontract.ExampleConnectedBytecodeBase64()}, objectTypeFilters, @@ -166,16 +165,12 @@ func (r *E2ERunner) suiDeployExample() { clockID, ok := objectIDs[filterClockType] require.True(r, ok, "clock object not found") - poolID, ok := objectIDs[filterPoolType] - require.True(r, ok, "pool object not found") - r.SuiExample = config.SuiExample{ PackageID: config.DoubleQuotedString(packageID), TokenType: config.DoubleQuotedString(packageID + "::token::TOKEN"), GlobalConfigID: config.DoubleQuotedString(globalConfigID), PartnerID: config.DoubleQuotedString(partnerID), ClockID: config.DoubleQuotedString(clockID), - PoolID: config.DoubleQuotedString(poolID), } } diff --git a/e2e/runner/sui.go b/e2e/runner/sui.go index ffcf04d635..d17298dded 100644 --- a/e2e/runner/sui.go +++ b/e2e/runner/sui.go @@ -117,6 +117,36 @@ func (r *E2ERunner) SuiWithdrawFungibleToken( return tx } +// SuiWithdrawAndCallFungibleToken calls WithdrawAndCall of Gateway with Sui fungible token ZRC20 on ZEVM +func (r *E2ERunner) SuiWithdrawAndCallFungibleToken( + receiver string, + amount *big.Int, + payload sui.CallPayload, + revertOptions gatewayzevm.RevertOptions, +) *ethtypes.Transaction { + receiverBytes, err := hex.DecodeString(receiver[2:]) + require.NoError(r, err, "receiver: "+receiver[2:]) + + payloadBytes, err := payload.PackABI() + require.NoError(r, err) + + tx, err := r.GatewayZEVM.WithdrawAndCall0( + r.ZEVMAuth, + receiverBytes, + amount, + r.SuiTokenZRC20Addr, + payloadBytes, + gatewayzevm.CallOptions{ + IsArbitraryCall: false, + GasLimit: big.NewInt(20000), + }, + revertOptions, + ) + require.NoError(r, err) + + return tx +} + // SuiDepositSUI calls Deposit on Sui func (r *E2ERunner) SuiDepositSUI( receiver ethcommon.Address, @@ -208,6 +238,26 @@ func (r *E2ERunner) SuiMintUSDC( return r.suiExecuteTx(signer, tx) } +// SuiCreateExampleWACPayload creates a payload for on_call function in Sui the example package +// The example on_call function will just forward the withdrawn token to given 'suiAddress' +func (r *E2ERunner) SuiCreateExampleWACPayload(suiAddress string) (sui.CallPayload, error) { + // only the CCTX's coinType is needed, no additional arguments + argumentTypes := []string{} + objects := []string{ + r.SuiExample.GlobalConfigID.String(), + r.SuiExample.PartnerID.String(), + r.SuiExample.ClockID.String(), + } + + // create the payload message from the sui address + message, err := hex.DecodeString(suiAddress[2:]) // remove 0x prefix + if err != nil { + return sui.CallPayload{}, err + } + + return sui.NewCallPayload(argumentTypes, objects, message), nil +} + // SuiGetConnectedCalledCount reads the called_count from the GlobalConfig object in connected module func (r *E2ERunner) SuiGetConnectedCalledCount() uint64 { // Get object data