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

chore(e2e): tolerate multiple runs of precompiled tests #3256

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 18 additions & 6 deletions cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
}))
}

e2eStartHeight, err := deployerRunner.Clients.Zetacore.GetBlockHeight(ctx)
noError(err)

// setting up the networks
if !skipSetup {
logger.Print("⚙️ setting up networks")
Expand Down Expand Up @@ -258,8 +261,6 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
deployerRunner.UpdateChainParamsV2Contracts()
deployerRunner.ERC20CustodyAddr = deployerRunner.ERC20CustodyV2Addr

deployerRunner.MintERC20OnEvm(1e10)

logger.Print("✅ setup completed in %s", time.Since(startTime))
}

Expand All @@ -284,6 +285,9 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
os.Exit(0)
}

// always mint ERC20 before every test execution
deployerRunner.MintERC20OnEvm(1e10)

// run the v2 migration
if testV2Migration {
deployerRunner.RunV2Migration()
Expand Down Expand Up @@ -368,15 +372,23 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
precompiledContractTests = []string{
e2etests.TestPrecompilesPrototypeName,
e2etests.TestPrecompilesPrototypeThroughContractName,
e2etests.TestPrecompilesStakingName,
// Disabled until further notice, check https://github.com/zeta-chain/node/issues/3005.
// e2etests.TestPrecompilesStakingThroughContractName,
e2etests.TestPrecompilesBankName,
e2etests.TestPrecompilesBankFailName,
e2etests.TestPrecompilesBankThroughContractName,
e2etests.TestPrecompilesDistributeName,
e2etests.TestPrecompilesDistributeNonZRC20Name,
e2etests.TestPrecompilesDistributeThroughContractName,
}
if e2eStartHeight < 100 {
// these tests require a clean system
// since unstaking has an unbonding period
precompiledContractTests = append(precompiledContractTests,
e2etests.TestPrecompilesStakingName,
e2etests.TestPrecompilesDistributeName,
e2etests.TestPrecompilesDistributeNonZRC20Name,
e2etests.TestPrecompilesDistributeThroughContractName,
)
} else {
logger.Print("⚠️ partial precompiled run (unclean state)")
}
}

Expand Down
10 changes: 10 additions & 0 deletions e2e/e2etests/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,13 @@ func parseBitcoinWithdrawArgs(r *runner.E2ERunner, args []string, defaultReceive

return receiver, amount
}

// bigAdd is shorthand for new(big.Int).Add(x, y)
func bigAdd(x *big.Int, y *big.Int) *big.Int {
return new(big.Int).Add(x, y)
}

// bigSub is shorthand for new(big.Int).Sub(x, y)
func bigSub(x *big.Int, y *big.Int) *big.Int {
return new(big.Int).Sub(x, y)
}
79 changes: 59 additions & 20 deletions e2e/e2etests/test_precompiles_bank.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ func TestPrecompilesBank(r *runner.E2ERunner, args []string) {
utils.RequireTxSuccessful(r, receipt, "Resetting balance failed")
}()

// Ensure starting allowance is zero; this is needed when running the tests multiple times
tx, err := r.ERC20ZRC20.Approve(r.ZEVMAuth, bankAddress, big.NewInt(0))
require.NoError(r, err)
receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
utils.RequireTxSuccessful(r, receipt, "Resetting allowance failed")

// Get ERC20ZRC20.
txHash := r.DepositERC20WithAmountAndMessage(r.EVMAddress(), totalAmount, []byte{})
utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout)
Expand All @@ -54,15 +60,18 @@ func TestPrecompilesBank(r *runner.E2ERunner, args []string) {
bankContract, err := bank.NewIBank(bank.ContractAddress, r.ZEVMClient)
require.NoError(r, err, "Failed to create bank contract caller")

// Cosmos coin balance should be 0 at this point.
cosmosBalance, err := bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.ERC20ZRC20Addr, spender)
// get starting balances
startSpenderCosmosBalance, err := bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.ERC20ZRC20Addr, spender)
require.NoError(r, err, "Call bank.BalanceOf()")
require.Equal(r, uint64(0), cosmosBalance.Uint64(), "spender cosmos coin balance should be 0")
startSpenderZRC20Balance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, spender)
require.NoError(r, err, "Call bank.BalanceOf()")
startBankZRC20Balance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, bankAddress)
require.NoError(r, err, "Call ERC20ZRC20.BalanceOf")

// Approve allowance of 500 ERC20ZRC20 tokens for the bank contract. Should pass.
tx, err := r.ERC20ZRC20.Approve(r.ZEVMAuth, bankAddress, depositAmount)
tx, err = r.ERC20ZRC20.Approve(r.ZEVMAuth, bankAddress, depositAmount)
require.NoError(r, err)
receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
utils.RequireTxSuccessful(r, receipt, "Approve ETHZRC20 bank allowance tx failed")

// Deposit 501 ERC20ZRC20 tokens to the bank contract.
Expand Down Expand Up @@ -99,17 +108,27 @@ func TestPrecompilesBank(r *runner.E2ERunner, args []string) {
require.Equal(r, depositAmount, eventDeposit.Amount, "Deposit event amount should be 500")

// Spender: cosmos coin balance should be 500 at this point.
cosmosBalance, err = bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.ERC20ZRC20Addr, spender)
spenderCosmosBalance, err := bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.ERC20ZRC20Addr, spender)
require.NoError(r, err, "Call bank.BalanceOf()")
require.Equal(r, uint64(500), cosmosBalance.Uint64(), "spender cosmos coin balance should be 500")
require.Equal(
r,
startSpenderCosmosBalance.Int64()+500,
spenderCosmosBalance.Int64(),
"spender cosmos coin balance should be +500",
)

// Bank: ERC20ZRC20 balance should be 500 tokens locked.
bankZRC20Balance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, bankAddress)
require.NoError(r, err, "Call ERC20ZRC20.BalanceOf")
require.Equal(r, uint64(500), bankZRC20Balance.Uint64(), "bank ERC20ZRC20 balance should be 500")
require.Equal(
r,
startBankZRC20Balance.Int64()+500,
bankZRC20Balance.Int64(),
"bank ERC20ZRC20 balance should be +500",
)

// Try to withdraw 501 ERC20ZRC20 tokens. Should fail.
tx, err = bankContract.Withdraw(r.ZEVMAuth, r.ERC20ZRC20Addr, big.NewInt(501))
// Try to withdraw one more than current balance. Should fail.
tx, err = bankContract.Withdraw(r.ZEVMAuth, r.ERC20ZRC20Addr, new(big.Int).Add(spenderCosmosBalance, big.NewInt(1)))
require.NoError(r, err, "Error calling bank.withdraw()")
receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
utils.RequiredTxFailed(r, receipt, "Withdrawing more than cosmos coin balance amount should fail")
Expand All @@ -118,7 +137,12 @@ func TestPrecompilesBank(r *runner.E2ERunner, args []string) {
// No tokens should be unlocked with a failed withdraw.
bankZRC20Balance, err = r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, bankAddress)
require.NoError(r, err, "Call ERC20ZRC20.BalanceOf")
require.Equal(r, uint64(500), bankZRC20Balance.Uint64(), "bank ERC20ZRC20 balance should be 500")
require.Equal(
r,
startBankZRC20Balance.Int64()+500,
bankZRC20Balance.Int64(),
"bank ERC20ZRC20 balance should be +500",
)

// Try to withdraw 500 ERC20ZRC20 tokens. Should pass.
tx, err = bankContract.Withdraw(r.ZEVMAuth, r.ERC20ZRC20Addr, depositAmount)
Expand All @@ -133,20 +157,35 @@ func TestPrecompilesBank(r *runner.E2ERunner, args []string) {
require.Equal(r, r.ERC20ZRC20Addr, eventWithdraw.Zrc20Token, "Withdraw event token should be ERC20ZRC20Addr")
require.Equal(r, depositAmount, eventWithdraw.Amount, "Withdraw event amount should be 500")

// Spender: cosmos coin balance should be 0 at this point.
cosmosBalance, err = bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.ERC20ZRC20Addr, spender)
// Spender: cosmos coin balance should be +0 at this point.
spenderCosmosBalance, err = bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.ERC20ZRC20Addr, spender)
require.NoError(r, err, "Call bank.BalanceOf()")
require.Equal(r, uint64(0), cosmosBalance.Uint64(), "spender cosmos coin balance should be 0")
require.Equal(
r,
startSpenderCosmosBalance.Int64(),
spenderCosmosBalance.Int64(),
"spender cosmos coin balance should match starting balance",
)

// Spender: ERC20ZRC20 balance should be 1000 at this point.
zrc20Balance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, spender)
require.NoError(r, err, "Call bank.BalanceOf()")
require.Equal(r, uint64(1000), zrc20Balance.Uint64(), "spender ERC20ZRC20 balance should be 1000")
// Spender: ERC20ZRC20 balance should be +0 at this point.
spenderZRC20Balance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, spender)
require.NoError(r, err, "Call ERC20ZRC20.BalanceOf")
require.Equal(
r,
startSpenderZRC20Balance.Int64(),
spenderZRC20Balance.Int64(),
"spender ERC20ZRC20 balance should match starting balance",
)

// Bank: ERC20ZRC20 balance should be 0 tokens locked.
// Bank: ERC20ZRC20 balance should be +0 tokens locked.
bankZRC20Balance, err = r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, bankAddress)
require.NoError(r, err, "Call ERC20ZRC20.BalanceOf")
require.Equal(r, uint64(0), bankZRC20Balance.Uint64(), "bank ERC20ZRC20 balance should be 0")
require.Equal(
r,
startBankZRC20Balance.Int64(),
bankZRC20Balance.Int64(),
"bank ERC20ZRC20 balance should match starting balance",
)
}

func TestPrecompilesBankNonZRC20(r *runner.E2ERunner, args []string) {
Expand Down
59 changes: 35 additions & 24 deletions e2e/e2etests/test_precompiles_bank_through_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestPrecompilesBankThroughContract(r *runner.E2ERunner, args []string) {
r.ZEVMAuth.GasLimit = previousGasLimit

// Reset the allowance to 0; this is needed when running upgrade tests where this test runs twice.
approveAllowance(r, bank.ContractAddress, big.NewInt(0))
approveAllowance(r, bank.ContractAddress, zero)

// Reset balance to 0; this is needed when running upgrade tests where this test runs twice.
tx, err = r.ERC20ZRC20.Transfer(
Expand All @@ -60,19 +60,22 @@ func TestPrecompilesBankThroughContract(r *runner.E2ERunner, args []string) {
utils.RequireTxSuccessful(r, receipt, "Resetting balance failed")
}()

// Check initial balances.
balanceShouldBe(r, zero, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, oneThousand, checkZRC20Balance(r, spender))
balanceShouldBe(r, zero, checkZRC20Balance(r, bankAddress))
// always ensure allowance is set to zero before test starts
approveAllowance(r, bank.ContractAddress, zero)

// get starting balances
startSpenderCosmosBalance := checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender)
startSpenderZRC20Balance := checkZRC20Balance(r, spender)
startBankZRC20Balance := checkZRC20Balance(r, bankAddress)

// Deposit without previous alllowance should fail.
receipt = depositThroughTestBank(r, testBank, zrc20Address, oneThousand)
utils.RequiredTxFailed(r, receipt, "Deposit ERC20ZRC20 without allowance should fail")

// Check balances, should be the same.
balanceShouldBe(r, zero, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, oneThousand, checkZRC20Balance(r, spender))
balanceShouldBe(r, zero, checkZRC20Balance(r, bankAddress))
balanceShouldBe(r, startSpenderCosmosBalance, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, startSpenderZRC20Balance, checkZRC20Balance(r, spender))
balanceShouldBe(r, startBankZRC20Balance, checkZRC20Balance(r, bankAddress))

// Allow 500 ZRC20 to bank precompile.
approveAllowance(r, bankAddress, fiveHundred)
Expand All @@ -83,9 +86,9 @@ func TestPrecompilesBankThroughContract(r *runner.E2ERunner, args []string) {
utils.RequiredTxFailed(r, receipt, "Depositting an amount higher than allowed should fail")

// Balances shouldn't change.
balanceShouldBe(r, zero, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, oneThousand, checkZRC20Balance(r, spender))
balanceShouldBe(r, zero, checkZRC20Balance(r, bankAddress))
balanceShouldBe(r, startSpenderCosmosBalance, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, startSpenderZRC20Balance, checkZRC20Balance(r, spender))
balanceShouldBe(r, startBankZRC20Balance, checkZRC20Balance(r, bankAddress))

// Allow 1000 ZRC20 to bank precompile.
approveAllowance(r, bankAddress, oneThousand)
Expand All @@ -96,18 +99,22 @@ func TestPrecompilesBankThroughContract(r *runner.E2ERunner, args []string) {
utils.RequiredTxFailed(r, receipt, "Depositting an amount higher than balance should fail")

// Balances shouldn't change.
balanceShouldBe(r, zero, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, oneThousand, checkZRC20Balance(r, spender))
balanceShouldBe(r, zero, checkZRC20Balance(r, bankAddress))
balanceShouldBe(r, startSpenderCosmosBalance, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, startSpenderZRC20Balance, checkZRC20Balance(r, spender))
balanceShouldBe(r, startBankZRC20Balance, checkZRC20Balance(r, bankAddress))

// Deposit 500 ERC20ZRC20 tokens to the bank contract, it's within allowance and balance. Should pass.
receipt = depositThroughTestBank(r, testBank, zrc20Address, fiveHundred)
utils.RequireTxSuccessful(r, receipt, "Depositting a correct amount should pass")

// Balances should be transferred. Bank now locks 500 ZRC20 tokens.
balanceShouldBe(r, fiveHundred, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, fiveHundred, checkZRC20Balance(r, spender))
balanceShouldBe(r, fiveHundred, checkZRC20Balance(r, bankAddress))
balanceShouldBe(
r,
bigAdd(startSpenderCosmosBalance, fiveHundred),
checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender),
)
balanceShouldBe(r, bigSub(startSpenderZRC20Balance, fiveHundred), checkZRC20Balance(r, spender))
balanceShouldBe(r, bigAdd(startBankZRC20Balance, fiveHundred), checkZRC20Balance(r, bankAddress))

// Check the deposit event.
eventDeposit, err := bankPrecompileCaller.ParseDeposit(*receipt.Logs[0])
Expand All @@ -117,22 +124,26 @@ func TestPrecompilesBankThroughContract(r *runner.E2ERunner, args []string) {
require.Equal(r, fiveHundred, eventDeposit.Amount, "Deposit event amount should be 500")

// Should faild to withdraw more than cosmos balance.
receipt = withdrawThroughTestBank(r, testBank, zrc20Address, fiveHundredOne)
receipt = withdrawThroughTestBank(r, testBank, zrc20Address, bigAdd(startSpenderCosmosBalance, fiveHundredOne))
utils.RequiredTxFailed(r, receipt, "Withdrawing an amount higher than balance should fail")

// Balances shouldn't change.
balanceShouldBe(r, fiveHundred, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, fiveHundred, checkZRC20Balance(r, spender))
balanceShouldBe(r, fiveHundred, checkZRC20Balance(r, bankAddress))
balanceShouldBe(
r,
bigAdd(startSpenderCosmosBalance, fiveHundred),
checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender),
)
balanceShouldBe(r, bigSub(startSpenderZRC20Balance, fiveHundred), checkZRC20Balance(r, spender))
balanceShouldBe(r, bigAdd(startBankZRC20Balance, fiveHundred), checkZRC20Balance(r, bankAddress))

// Try to withdraw 500 ERC20ZRC20 tokens. Should pass.
receipt = withdrawThroughTestBank(r, testBank, zrc20Address, fiveHundred)
utils.RequireTxSuccessful(r, receipt, "Withdraw correct amount should pass")

// Balances should be reverted to initial state.
balanceShouldBe(r, zero, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, oneThousand, checkZRC20Balance(r, spender))
balanceShouldBe(r, zero, checkZRC20Balance(r, bankAddress))
balanceShouldBe(r, startSpenderCosmosBalance, checkCosmosBalanceThroughBank(r, testBank, zrc20Address, spender))
balanceShouldBe(r, startSpenderZRC20Balance, checkZRC20Balance(r, spender))
balanceShouldBe(r, startBankZRC20Balance, checkZRC20Balance(r, bankAddress))

// Check the withdraw event.
eventWithdraw, err := bankPrecompileCaller.ParseWithdraw(*receipt.Logs[0])
Expand Down
Loading