Skip to content

Commit

Permalink
Include CallContract interface
Browse files Browse the repository at this point in the history
  • Loading branch information
fbac committed Sep 16, 2024
1 parent cf17671 commit 02ddce3
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 142 deletions.
4 changes: 4 additions & 0 deletions cmd/zetae2e/config/localnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ additional_accounts:
bech32_address: "zeta1nry9yeg6njhjrp2ctppa8558vqxal9fxk69zxg"
evm_address: "0x98c852651A9CAF2185585843d3D287600Ddf9526"
private_key: "bf9456c679bb5a952a9a137fcfc920e0413efdb97c36de1e57455763084230cb"
user_bank_precompile:
bech32_address: "zeta1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr84sgapz"
evm_address: "0x0000000000000000000000000000000000000067"
private_key: ""
policy_accounts:
emergency_policy_account:
bech32_address: "zeta16m2cnrdwtgweq4njc6t470vl325gw4kp6s7tap"
Expand Down
5 changes: 1 addition & 4 deletions contrib/localnet/orchestrator/start-zetae2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ fund_eth_from_config '.additional_accounts.user_admin.evm_address' 10000 "admin
fund_eth_from_config '.additional_accounts.user_migration.evm_address' 10000 "migration tester"

# unlock precompile tests accounts
fund_eth_from_config '.additional_accounts.user_precompile.evm_address' 10000 "precompile tester"
fund_eth_from_config '.additional_accounts.user_precompile.evm_address' 10000 "precompiles tester"

# unlock v2 ethers tests accounts
fund_eth_from_config '.additional_accounts.user_v2_ether.evm_address' 10000 "V2 ethers tester"
Expand All @@ -131,9 +131,6 @@ fund_eth_from_config '.additional_accounts.user_v2_ether_revert.evm_address' 100
# unlock v2 erc20 revert tests accounts
fund_eth_from_config '.additional_accounts.user_v2_erc20_revert.evm_address' 10000 "V2 ERC20 revert tester"

# unlock precompile tests accounts
fund_eth_from_config '.additional_accounts.user_precompile.evm_address' 10000 "precompiles tester"

# unlock local solana relayer accounts
if host solana > /dev/null; then
solana_url=$(config_str '.rpcs.solana')
Expand Down
3 changes: 3 additions & 0 deletions contrib/localnet/scripts/start-zetacored.sh
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ then
# v2 erc20 revert tester
address=$(yq -r '.additional_accounts.user_v2_erc20_revert.bech32_address' /root/config.yml)
zetacored add-genesis-account "$address" 100000000000000000000000000azeta
# bank precompile user
address=$(yq -r '.additional_accounts.user_bank_precompile.bech32_address' /root/config.yml)
zetacored add-genesis-account "$address" 100000000000000000000000000azeta

# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node
zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING --gas-prices 20000000000azeta
Expand Down
93 changes: 43 additions & 50 deletions e2e/e2etests/test_precompiles_bank.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,78 +15,71 @@ import (
func TestPrecompilesBank(r *runner.E2ERunner, args []string) {
require.Len(r, args, 0, "No arguments expected")

// Increase the gasLimit. It's required because of the gas consumed by precompiled functions.
previousGasLimit := r.ZEVMAuth.GasLimit
r.ZEVMAuth.GasLimit = 10_000_000
defer func() {
r.ZEVMAuth.GasLimit = previousGasLimit
}()

// Set owner and spender for legibility.
owner, spender := r.EVMAddress(), bank.ContractAddress
fmt.Println("owner ", owner.String())
fmt.Println("spender ", spender.String())
fmt.Println("ERC20ZRC20 ", r.ERC20ZRC20Addr.String())
spender, bankAddr := r.EVMAddress(), bank.ContractAddress

// Fund owner with 200 token.
tx, err := r.ERC20ZRC20.Transfer(r.ZEVMAuth, owner, big.NewInt(200))
require.NoError(r, err, "Error funding owner with ERC20ZRC20")
// Deposit and approve 50 WZETA for the test.
approveAmount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(50))
r.DepositAndApproveWZeta(approveAmount)
fmt.Printf("DEBUG: approveAmount %s\n", approveAmount.String())

receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
fmt.Printf("funding owner tx receipt: %+v\n", receipt)
utils.RequireTxSuccessful(r, receipt, "funding owner tx")
initialBalance, err := r.WZeta.BalanceOf(&bind.CallOpts{Context: r.Ctx}, spender)
fmt.Printf("DEBUG: initialBalance %s\n", initialBalance.String())
require.NoError(r, err, "Error approving allowance for bank contract")
require.EqualValues(r, approveAmount, initialBalance, "spender balance should be 50")

// Create a bank contract caller.
bankContract, err := bank.NewIBank(bank.ContractAddress, r.ZEVMClient)
require.NoError(r, err, "Failed to create bank contract caller")

// Get the initial balance of the owner in ERC20ZRC20 tokens. Should be 200.
ownerERC20InitialBalance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, owner)
require.NoError(r, err, "Error retrieving initial owner balance")
require.EqualValues(r, uint64(0), ownerERC20InitialBalance.Uint64(), "Initial ERC20ZRC20 has to be 200")
fmt.Println("owner balance ERC20: ", ownerERC20InitialBalance)

// Get the balance of the owner in coins "zevm/0x12345". This calls bank.balanceOf().
// Get the balance of the spender in coins "zevm/WZetaAddr". This calls bank.balanceOf().
// BalanceOf will convert the ZRC20 address to a Cosmos denom formatted as "zevm/0x12345".
retBalanceOf, err := bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.ERC20ZRC20Addr, owner)
retBalanceOf, err := bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.WZetaAddr, spender)
fmt.Printf("DEBUG: initial bank.balanceOf() %s\n", retBalanceOf.String())
require.NoError(r, err, "Error calling bank.balanceOf()")
require.EqualValues(r, uint64(0), retBalanceOf.Uint64(), "Initial cosmos coins balance has to be 0")
fmt.Println("owner balance zevm/coin: ", retBalanceOf)

// Allow the bank contract to spend 100 ERC20ZRC20 tokens.
tx, err = r.ERC20ZRC20.Approve(r.ZEVMAuth, spender, big.NewInt(100))
// Allow the bank contract to spend 25 WZeta tokens.
tx, err := r.WZeta.Approve(r.ZEVMAuth, bankAddr, big.NewInt(25))
require.NoError(r, err, "Error approving allowance for bank contract")
fmt.Printf("approve allowance tx: %+v\n", tx)

receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
utils.RequireTxSuccessful(r, receipt, "approve allowance tx")
fmt.Printf("approve allowance tx receipt: %+v\n", receipt)
receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
require.EqualValues(r, uint64(1), receipt.Status, "approve allowance tx failed")

// Check the allowance of the bank in ERC20ZRC20 tokens. Should be 100.
balance, err := r.ERC20ZRC20.Allowance(&bind.CallOpts{Context: r.Ctx}, owner, spender)
// Check the allowance of the bank in WZeta tokens. Should be 25.
balance, err := r.WZeta.Allowance(&bind.CallOpts{Context: r.Ctx}, spender, bankAddr)
fmt.Printf("DEBUG: bank allowance %s\n", balance.String())
require.NoError(r, err, "Error retrieving bank allowance")
require.EqualValues(r, uint64(100), balance.Uint64(), "Error allowance for bank contract")
fmt.Printf("bank allowance: %v\n", balance)

// Call deposit with 100 coins.
tx, err = bankContract.Deposit(r.ZEVMAuth, r.ERC20ZRC20Addr, big.NewInt(100))
require.NoError(r, err, "Error calling bank.deposit")
utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
fmt.Printf("Deposit tx: %+v\n", tx)

// Check the balance of the owner in coins "zevm/0x12345".
retBalanceOf, err = bankContract.BalanceOf(nil, r.ERC20ZRC20Addr, owner)
require.NoError(r, err, "Error calling balanceOf")
require.EqualValues(r, uint64(100), retBalanceOf.Uint64(), "balanceOf result has to be 100")
fmt.Printf("owner balance zevm/coin (should increase): %+v\n", retBalanceOf)

// Check the balance of the owner in r.ERC20ZRC20Addr, should be 100 less.
ownerERC20FinalBalance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{Context: r.Ctx}, owner)
require.EqualValues(r, uint64(25), balance.Uint64(), "Error allowance for bank contract")

// Call deposit with 25 coins.
tx, err = bankContract.Deposit(r.ZEVMAuth, r.WZetaAddr, big.NewInt(25))
fmt.Printf("DEBUG: bank.deposit() tx hash %s\n", tx.Hash().String())
require.NoError(r, err, "Error calling bank.deposit()")

r.Logger.Info("Waiting for 5 blocks")
r.WaitForBlocks(5)
fmt.Printf("DEBUG: bank.deposit() tx %+v\n", tx)

// Check the balance of the spender in coins "zevm/WZetaAddr".
retBalanceOf, err = bankContract.BalanceOf(&bind.CallOpts{Context: r.Ctx}, r.WZetaAddr, spender)
fmt.Printf("DEBUG: final bank.balanceOf() tx %s\n", retBalanceOf.String())
require.NoError(r, err, "Error calling bank.balanceOf()")
require.EqualValues(r, uint64(25), retBalanceOf.Uint64(), "balanceOf result has to be 25")

// Check the balance of the spender in r.WZeta, should be 100 less.
finalBalance, err := r.WZeta.BalanceOf(&bind.CallOpts{Context: r.Ctx}, spender)
fmt.Printf("DEBUG: final WZeta balance %s\n", finalBalance.String())
require.NoError(r, err, "Error retrieving final owner balance")
fmt.Printf("owner final ERC20 balance (should decrease): %+v\n", retBalanceOf)
require.EqualValues(
r,
ownerERC20InitialBalance.Uint64()-100, // expected
ownerERC20FinalBalance.Uint64(), // actual
"Final balance should be initial - 100",
initialBalance.Uint64()-25, // expected
finalBalance.Uint64(), // actual
"Final balance should be initial - 25",
)
}
16 changes: 14 additions & 2 deletions precompiles/bank/bank.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package bank

import (
"fmt"

"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -103,6 +105,7 @@ func (c *Contract) RequiredGas(input []byte) uint64 {
// Run is the entrypoint of the precompiled contract, it switches over the input method,
// and execute them accordingly.
func (c *Contract) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) ([]byte, error) {
fmt.Println("DEBUG: bank.Run()")
method, err := ABI.MethodById(contract.Input[:4])
if err != nil {
return nil, err
Expand All @@ -117,31 +120,40 @@ func (c *Contract) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) ([]byt

switch method.Name {
case DepositMethodName:
fmt.Println("DEBUG: bank.Run(): DepositMethodName")
if readOnly {
return nil, nil
return nil, ptypes.ErrUnexpected{
Got: "method not allowed in read-only mode " + method.Name,
}
}

var res []byte
execErr := stateDB.ExecuteNativeAction(contract.Address(), nil, func(ctx sdk.Context) error {
fmt.Println("DEBUG: bank.Run(): DepositMethodName: ExecuteNativeAction c.deposit()")
res, err = c.deposit(ctx, method, contract.CallerAddress, args)
return err
})
if execErr != nil {
fmt.Printf("DEBUG: bank.Run(): execErr %s", execErr.Error())
return nil, err
}
return res, nil

case WithdrawMethodName:
if readOnly {
return nil, nil
return nil, ptypes.ErrUnexpected{
Got: "method not allowed in read-only mode " + method.Name,
}
}

return nil, nil
// TODO

case BalanceOfMethodName:
fmt.Println("DEBUG: bank.Run(): BalanceOfMethodName")
var res []byte
execErr := stateDB.ExecuteNativeAction(contract.Address(), nil, func(ctx sdk.Context) error {
fmt.Println("DEBUG: bank.Run(): DepositMethodName: ExecuteNativeAction c.balanceOf()")
res, err = c.balanceOf(ctx, method, args)
return err
})
Expand Down
57 changes: 0 additions & 57 deletions precompiles/bank/call_contract.go

This file was deleted.

Loading

0 comments on commit 02ddce3

Please sign in to comment.