mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 15:25:18 +00:00
test(e2e): test more complex cosmos assert conversion (#1616)
* ensure users can mint() or burn() erc20s * refactor test setup * refactor GetErc20Balance for arbitrary erc20 contracts * move GetErc20Balance() to Chain * test complex erc20 operations & convert * undo changes to e2e env
This commit is contained in:
parent
0ec64c9378
commit
c90c7a8647
@ -8,7 +8,9 @@ import (
|
|||||||
sdkerrors "cosmossdk.io/errors"
|
sdkerrors "cosmossdk.io/errors"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
"github.com/ethereum/go-ethereum"
|
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/tests/e2e/testutil"
|
"github.com/kava-labs/kava/tests/e2e/testutil"
|
||||||
"github.com/kava-labs/kava/tests/util"
|
"github.com/kava-labs/kava/tests/util"
|
||||||
evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
|
evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
|
||||||
@ -38,6 +40,50 @@ func setupConvertToCoinTest(
|
|||||||
return denom, initialFunds, user
|
return denom, initialFunds, user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// amount must be less than 1e10
|
||||||
|
func (suite *IntegrationTestSuite) setupAccountWithCosmosCoinERC20Balance(
|
||||||
|
accountName string, amount int64,
|
||||||
|
) (user *testutil.SigningAccount, contractAddress *evmutiltypes.InternalEVMAddress, denom string, sdkBalance sdk.Coins) {
|
||||||
|
if amount > 1e10 {
|
||||||
|
panic("test erc20 amount must be less than 1e10")
|
||||||
|
}
|
||||||
|
|
||||||
|
denom, sdkBalance, user = setupConvertToCoinTest(suite, accountName)
|
||||||
|
convertAmount := sdk.NewInt64Coin(denom, amount)
|
||||||
|
|
||||||
|
fee := sdk.NewCoins(ukava(7500))
|
||||||
|
|
||||||
|
// setup user to have erc20 balance
|
||||||
|
msg := evmutiltypes.NewMsgConvertCosmosCoinToERC20(
|
||||||
|
user.SdkAddress.String(),
|
||||||
|
user.EvmAddress.Hex(),
|
||||||
|
convertAmount,
|
||||||
|
)
|
||||||
|
tx := util.KavaMsgRequest{
|
||||||
|
Msgs: []sdk.Msg{&msg},
|
||||||
|
GasLimit: 2e6,
|
||||||
|
FeeAmount: fee,
|
||||||
|
Data: "converting sdk coin to erc20",
|
||||||
|
}
|
||||||
|
res := user.SignAndBroadcastKavaTx(tx)
|
||||||
|
suite.NoError(res.Err)
|
||||||
|
|
||||||
|
// adjust sdk balance
|
||||||
|
sdkBalance = sdkBalance.Sub(convertAmount)
|
||||||
|
|
||||||
|
// query for the deployed contract
|
||||||
|
deployedContracts, err := suite.Kava.Evmutil.DeployedCosmosCoinContracts(
|
||||||
|
context.Background(),
|
||||||
|
&evmutiltypes.QueryDeployedCosmosCoinContractsRequest{CosmosDenoms: []string{denom}},
|
||||||
|
)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Len(deployedContracts.DeployedCosmosCoinContracts, 1)
|
||||||
|
|
||||||
|
contractAddress = deployedContracts.DeployedCosmosCoinContracts[0].Address
|
||||||
|
|
||||||
|
return user, contractAddress, denom, sdkBalance
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *IntegrationTestSuite) TestConvertCosmosCoinsToFromERC20() {
|
func (suite *IntegrationTestSuite) TestConvertCosmosCoinsToFromERC20() {
|
||||||
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter")
|
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter")
|
||||||
|
|
||||||
@ -73,12 +119,7 @@ func (suite *IntegrationTestSuite) TestConvertCosmosCoinsToFromERC20() {
|
|||||||
contractAddress := deployedContracts.DeployedCosmosCoinContracts[0].Address
|
contractAddress := deployedContracts.DeployedCosmosCoinContracts[0].Address
|
||||||
|
|
||||||
// check erc20 balance
|
// check erc20 balance
|
||||||
bz, err := suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
erc20Balance := suite.Kava.GetErc20Balance(contractAddress.Address, user.EvmAddress)
|
||||||
To: &contractAddress.Address,
|
|
||||||
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
|
|
||||||
}, nil)
|
|
||||||
suite.NoError(err)
|
|
||||||
erc20Balance := new(big.Int).SetBytes(bz)
|
|
||||||
suite.BigIntsEqual(big.NewInt(convertAmount), erc20Balance, "unexpected erc20 balance post-convert")
|
suite.BigIntsEqual(big.NewInt(convertAmount), erc20Balance, "unexpected erc20 balance post-convert")
|
||||||
|
|
||||||
// check cosmos coin is deducted from account
|
// check cosmos coin is deducted from account
|
||||||
@ -110,12 +151,7 @@ func (suite *IntegrationTestSuite) TestConvertCosmosCoinsToFromERC20() {
|
|||||||
suite.NoError(res.Err)
|
suite.NoError(res.Err)
|
||||||
|
|
||||||
// check erc20 balance
|
// check erc20 balance
|
||||||
bz, err = suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
erc20Balance = suite.Kava.GetErc20Balance(contractAddress.Address, user.EvmAddress)
|
||||||
To: &contractAddress.Address,
|
|
||||||
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
|
|
||||||
}, nil)
|
|
||||||
suite.NoError(err)
|
|
||||||
erc20Balance = new(big.Int).SetBytes(bz)
|
|
||||||
suite.BigIntsEqual(big.NewInt(0), erc20Balance, "expected all erc20 to be converted back")
|
suite.BigIntsEqual(big.NewInt(0), erc20Balance, "expected all erc20 to be converted back")
|
||||||
|
|
||||||
// check cosmos coin is added back to account
|
// check cosmos coin is added back to account
|
||||||
@ -176,12 +212,7 @@ func (suite *IntegrationTestSuite) TestEIP712ConvertCosmosCoinsToFromERC20() {
|
|||||||
contractAddress := deployedContracts.DeployedCosmosCoinContracts[0].Address
|
contractAddress := deployedContracts.DeployedCosmosCoinContracts[0].Address
|
||||||
|
|
||||||
// check erc20 balance
|
// check erc20 balance
|
||||||
bz, err := suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
erc20Balance := suite.Kava.GetErc20Balance(contractAddress.Address, user.EvmAddress)
|
||||||
To: &contractAddress.Address,
|
|
||||||
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
|
|
||||||
}, nil)
|
|
||||||
suite.NoError(err)
|
|
||||||
erc20Balance := new(big.Int).SetBytes(bz)
|
|
||||||
suite.BigIntsEqual(big.NewInt(convertAmount), erc20Balance, "unexpected erc20 balance post-convert")
|
suite.BigIntsEqual(big.NewInt(convertAmount), erc20Balance, "unexpected erc20 balance post-convert")
|
||||||
|
|
||||||
// check cosmos coin is deducted from account
|
// check cosmos coin is deducted from account
|
||||||
@ -225,12 +256,7 @@ func (suite *IntegrationTestSuite) TestEIP712ConvertCosmosCoinsToFromERC20() {
|
|||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
// check erc20 balance
|
// check erc20 balance
|
||||||
bz, err = suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
erc20Balance = suite.Kava.GetErc20Balance(contractAddress.Address, user.EvmAddress)
|
||||||
To: &contractAddress.Address,
|
|
||||||
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
|
|
||||||
}, nil)
|
|
||||||
suite.NoError(err)
|
|
||||||
erc20Balance = new(big.Int).SetBytes(bz)
|
|
||||||
suite.BigIntsEqual(big.NewInt(0), erc20Balance, "expected all erc20 to be converted back")
|
suite.BigIntsEqual(big.NewInt(0), erc20Balance, "expected all erc20 to be converted back")
|
||||||
|
|
||||||
// check cosmos coin is added back to account
|
// check cosmos coin is added back to account
|
||||||
@ -242,3 +268,159 @@ func (suite *IntegrationTestSuite) TestEIP712ConvertCosmosCoinsToFromERC20() {
|
|||||||
actualModuleBalance = suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
|
actualModuleBalance = suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
|
||||||
suite.Equal(initialModuleBalance, actualModuleBalance)
|
suite.Equal(initialModuleBalance, actualModuleBalance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *IntegrationTestSuite) TestConvertCosmosCoins_ForbiddenERC20Calls() {
|
||||||
|
user, contractAddress, _, _ := suite.setupAccountWithCosmosCoinERC20Balance("cosmo-coin-converter-unhappy", 1e6)
|
||||||
|
|
||||||
|
suite.Run("users can't mint()", func() {
|
||||||
|
data := util.BuildErc20MintCallData(user.EvmAddress, big.NewInt(1))
|
||||||
|
nonce, err := user.NextNonce()
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
mintTx := util.EvmTxRequest{
|
||||||
|
Tx: ethtypes.NewTx(
|
||||||
|
ðtypes.LegacyTx{
|
||||||
|
Nonce: nonce,
|
||||||
|
GasPrice: minEvmGasPrice,
|
||||||
|
Gas: 1e6,
|
||||||
|
To: &contractAddress.Address,
|
||||||
|
Data: data,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Data: "attempting to mint, should fail",
|
||||||
|
}
|
||||||
|
res := user.SignAndBroadcastEvmTx(mintTx)
|
||||||
|
|
||||||
|
suite.ErrorAs(res.Err, &util.ErrEvmTxFailed)
|
||||||
|
// TODO: when traceTransactions enabled, read actual error log
|
||||||
|
suite.ErrorContains(res.Err, "transaction was committed but failed. likely an execution revert by contract code")
|
||||||
|
})
|
||||||
|
|
||||||
|
suite.Run("users can't burn()", func() {
|
||||||
|
data := util.BuildErc20BurnCallData(user.EvmAddress, big.NewInt(1))
|
||||||
|
nonce, err := user.NextNonce()
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
burnTx := util.EvmTxRequest{
|
||||||
|
Tx: ethtypes.NewTx(
|
||||||
|
ðtypes.LegacyTx{
|
||||||
|
Nonce: nonce,
|
||||||
|
GasPrice: minEvmGasPrice,
|
||||||
|
Gas: 1e6,
|
||||||
|
To: &contractAddress.Address,
|
||||||
|
Data: data,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Data: "attempting to burn, should fail",
|
||||||
|
}
|
||||||
|
res := user.SignAndBroadcastEvmTx(burnTx)
|
||||||
|
|
||||||
|
suite.ErrorAs(res.Err, &util.ErrEvmTxFailed)
|
||||||
|
// TODO: when traceTransactions enabled, read actual error log
|
||||||
|
suite.ErrorContains(res.Err, "transaction was committed but failed. likely an execution revert by contract code")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// - check approval flow of erc20. alice approves bob to move their funds
|
||||||
|
// - check complex conversion flow. bob converts funds they receive on evm back to sdk.Coin
|
||||||
|
func (suite *IntegrationTestSuite) TestConvertCosmosCoins_ERC20Magic() {
|
||||||
|
fee := sdk.NewCoins(ukava(7500))
|
||||||
|
initialAliceAmount := int64(2e6)
|
||||||
|
alice, contractAddress, denom, _ := suite.setupAccountWithCosmosCoinERC20Balance(
|
||||||
|
"cosmo-coin-converter-complex-alice", initialAliceAmount,
|
||||||
|
)
|
||||||
|
|
||||||
|
gasMoney := sdk.NewCoins(ukava(1e6))
|
||||||
|
bob := suite.Kava.NewFundedAccount("cosmo-coin-converter-complex-bob", gasMoney)
|
||||||
|
amount := big.NewInt(1e6)
|
||||||
|
|
||||||
|
// bob can't move alice's funds
|
||||||
|
nonce, err := bob.NextNonce()
|
||||||
|
suite.NoError(err)
|
||||||
|
transferFromTxData := ðtypes.LegacyTx{
|
||||||
|
Nonce: nonce,
|
||||||
|
GasPrice: minEvmGasPrice,
|
||||||
|
Gas: 1e6,
|
||||||
|
To: &contractAddress.Address,
|
||||||
|
Value: &big.Int{},
|
||||||
|
Data: util.BuildErc20TransferFromCallData(alice.EvmAddress, bob.EvmAddress, amount),
|
||||||
|
}
|
||||||
|
transferTx := util.EvmTxRequest{
|
||||||
|
Tx: ethtypes.NewTx(transferFromTxData),
|
||||||
|
Data: "bob can't move alice's funds, should fail",
|
||||||
|
}
|
||||||
|
res := bob.SignAndBroadcastEvmTx(transferTx)
|
||||||
|
suite.ErrorAs(res.Err, &util.ErrEvmTxFailed)
|
||||||
|
suite.ErrorContains(res.Err, "transaction was committed but failed. likely an execution revert by contract code")
|
||||||
|
|
||||||
|
// approve bob to move alice's funds
|
||||||
|
nonce, err = alice.NextNonce()
|
||||||
|
suite.NoError(err)
|
||||||
|
approveTx := util.EvmTxRequest{
|
||||||
|
Tx: ethtypes.NewTx(ðtypes.LegacyTx{
|
||||||
|
Nonce: nonce,
|
||||||
|
GasPrice: minEvmGasPrice,
|
||||||
|
Gas: 1e6,
|
||||||
|
To: &contractAddress.Address,
|
||||||
|
Value: &big.Int{},
|
||||||
|
Data: util.BuildErc20ApproveCallData(bob.EvmAddress, amount),
|
||||||
|
}),
|
||||||
|
Data: "alice approves bob to spend amount",
|
||||||
|
}
|
||||||
|
res = alice.SignAndBroadcastEvmTx(approveTx)
|
||||||
|
suite.NoError(res.Err)
|
||||||
|
|
||||||
|
// bob can't move more than alice allowed
|
||||||
|
transferFromTxData.Data = util.BuildErc20TransferFromCallData(
|
||||||
|
alice.EvmAddress, bob.EvmAddress, new(big.Int).Add(amount, big.NewInt(1)),
|
||||||
|
)
|
||||||
|
transferFromTxData.Nonce, err = bob.NextNonce()
|
||||||
|
suite.NoError(err)
|
||||||
|
transferTooMuchTx := util.EvmTxRequest{
|
||||||
|
Tx: ethtypes.NewTx(transferFromTxData),
|
||||||
|
Data: "transferring more than approved, should fail",
|
||||||
|
}
|
||||||
|
res = bob.SignAndBroadcastEvmTx(transferTooMuchTx)
|
||||||
|
suite.ErrorAs(res.Err, &util.ErrEvmTxFailed)
|
||||||
|
suite.ErrorContains(res.Err, "transaction was committed but failed. likely an execution revert by contract code")
|
||||||
|
|
||||||
|
// bob can move allowed amount
|
||||||
|
transferFromTxData.Data = util.BuildErc20TransferFromCallData(alice.EvmAddress, bob.EvmAddress, amount)
|
||||||
|
transferFromTxData.Nonce, err = bob.NextNonce()
|
||||||
|
suite.NoError(err)
|
||||||
|
transferJustRightTx := util.EvmTxRequest{
|
||||||
|
Tx: ethtypes.NewTx(transferFromTxData),
|
||||||
|
Data: "bob transfers alice's funds, allowed because he's approved",
|
||||||
|
}
|
||||||
|
res = bob.SignAndBroadcastEvmTx(transferJustRightTx)
|
||||||
|
suite.NoError(res.Err)
|
||||||
|
|
||||||
|
// alice should have amount deducted
|
||||||
|
erc20Balance := suite.Kava.GetErc20Balance(contractAddress.Address, alice.EvmAddress)
|
||||||
|
suite.BigIntsEqual(big.NewInt(initialAliceAmount-amount.Int64()), erc20Balance, "alice has unexpected erc20 balance")
|
||||||
|
// bob should have amount added
|
||||||
|
erc20Balance = suite.Kava.GetErc20Balance(contractAddress.Address, bob.EvmAddress)
|
||||||
|
suite.BigIntsEqual(amount, erc20Balance, "bob has unexpected erc20 balance")
|
||||||
|
|
||||||
|
// convert bob's new funds back to an sdk.Coin
|
||||||
|
convertMsg := evmutiltypes.NewMsgConvertCosmosCoinFromERC20(
|
||||||
|
bob.EvmAddress.Hex(),
|
||||||
|
bob.SdkAddress.String(),
|
||||||
|
sdk.NewInt64Coin(denom, amount.Int64()),
|
||||||
|
)
|
||||||
|
convertTx := util.KavaMsgRequest{
|
||||||
|
Msgs: []sdk.Msg{&convertMsg},
|
||||||
|
GasLimit: 2e6,
|
||||||
|
FeeAmount: fee,
|
||||||
|
Data: "bob converts his new erc20 to an sdk.Coin",
|
||||||
|
}
|
||||||
|
convertRes := bob.SignAndBroadcastKavaTx(convertTx)
|
||||||
|
suite.NoError(convertRes.Err)
|
||||||
|
|
||||||
|
// bob should have no more erc20 balance
|
||||||
|
erc20Balance = suite.Kava.GetErc20Balance(contractAddress.Address, bob.EvmAddress)
|
||||||
|
suite.BigIntsEqual(big.NewInt(0), erc20Balance, "expected no erc20 balance for bob")
|
||||||
|
// bob should have sdk balance
|
||||||
|
balance := suite.Kava.QuerySdkForBalances(bob.SdkAddress).AmountOf(denom)
|
||||||
|
suite.Equal(sdk.NewIntFromBigInt(amount), balance)
|
||||||
|
}
|
||||||
|
@ -50,14 +50,14 @@ func (suite *IntegrationTestSuite) TestEthCallToErc20() {
|
|||||||
amount := big.NewInt(1e6)
|
amount := big.NewInt(1e6)
|
||||||
|
|
||||||
// make unauthenticated eth_call query to check balance
|
// make unauthenticated eth_call query to check balance
|
||||||
beforeBalance := suite.GetErc20Balance(randoReceiver)
|
beforeBalance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, randoReceiver)
|
||||||
|
|
||||||
// make authenticate eth_call to transfer tokens
|
// make authenticate eth_call to transfer tokens
|
||||||
res := suite.FundKavaErc20Balance(randoReceiver, amount)
|
res := suite.FundKavaErc20Balance(randoReceiver, amount)
|
||||||
suite.NoError(res.Err)
|
suite.NoError(res.Err)
|
||||||
|
|
||||||
// make another unauthenticated eth_call query to check new balance
|
// make another unauthenticated eth_call query to check new balance
|
||||||
afterBalance := suite.GetErc20Balance(randoReceiver)
|
afterBalance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, randoReceiver)
|
||||||
|
|
||||||
suite.BigIntsEqual(big.NewInt(0), beforeBalance, "expected before balance to be zero")
|
suite.BigIntsEqual(big.NewInt(0), beforeBalance, "expected before balance to be zero")
|
||||||
suite.BigIntsEqual(amount, afterBalance, "unexpected post-transfer balance")
|
suite.BigIntsEqual(amount, afterBalance, "unexpected post-transfer balance")
|
||||||
@ -161,7 +161,7 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
|
|||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
// check that depositor no longer has erc20 balance
|
// check that depositor no longer has erc20 balance
|
||||||
balance := suite.GetErc20Balance(depositor.EvmAddress)
|
balance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, depositor.EvmAddress)
|
||||||
suite.BigIntsEqual(big.NewInt(0), balance, "expected no erc20 balance")
|
suite.BigIntsEqual(big.NewInt(0), balance, "expected no erc20 balance")
|
||||||
|
|
||||||
// check that account has an earn deposit position
|
// check that account has an earn deposit position
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package testutil
|
package testutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@ -215,3 +216,8 @@ func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccou
|
|||||||
|
|
||||||
return acc
|
return acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNonce fetches the next nonce / sequence number for the account.
|
||||||
|
func (a *SigningAccount) NextNonce() (uint64, error) {
|
||||||
|
return a.evmSigner.EvmClient.PendingNonceAt(context.Background(), a.EvmAddress)
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package testutil
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
@ -123,3 +125,13 @@ func (chain *Chain) GetModuleBalances(moduleName string) sdk.Coins {
|
|||||||
addr := authtypes.NewModuleAddress(moduleName)
|
addr := authtypes.NewModuleAddress(moduleName)
|
||||||
return chain.QuerySdkForBalances(addr)
|
return chain.QuerySdkForBalances(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (chain *Chain) GetErc20Balance(contract, address common.Address) *big.Int {
|
||||||
|
resData, err := chain.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
||||||
|
To: &contract,
|
||||||
|
Data: util.BuildErc20BalanceOfCallData(address),
|
||||||
|
}, nil)
|
||||||
|
require.NoError(chain.t, err)
|
||||||
|
|
||||||
|
return new(big.Int).SetBytes(resData)
|
||||||
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ func (suite *E2eTestSuite) InitKavaEvmData() {
|
|||||||
whale := suite.Kava.GetAccount(FundedAccountName)
|
whale := suite.Kava.GetAccount(FundedAccountName)
|
||||||
|
|
||||||
// ensure funded account has nonzero erc20 balance
|
// ensure funded account has nonzero erc20 balance
|
||||||
balance := suite.GetErc20Balance(whale.EvmAddress)
|
balance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, whale.EvmAddress)
|
||||||
if balance.Cmp(big.NewInt(0)) != 1 {
|
if balance.Cmp(big.NewInt(0)) != 1 {
|
||||||
panic(fmt.Sprintf("expected funded account (%s) to have erc20 balance", whale.EvmAddress.Hex()))
|
panic(fmt.Sprintf("expected funded account (%s) to have erc20 balance", whale.EvmAddress.Hex()))
|
||||||
}
|
}
|
||||||
@ -38,7 +37,7 @@ func (suite *E2eTestSuite) FundKavaErc20Balance(toAddress common.Address, amount
|
|||||||
// funded account should have erc20 balance
|
// funded account should have erc20 balance
|
||||||
whale := suite.Kava.GetAccount(FundedAccountName)
|
whale := suite.Kava.GetAccount(FundedAccountName)
|
||||||
|
|
||||||
data := util.BuildErc20TransferCallData(whale.EvmAddress, toAddress, amount)
|
data := util.BuildErc20TransferCallData(toAddress, amount)
|
||||||
nonce, err := suite.Kava.EvmClient.PendingNonceAt(context.Background(), whale.EvmAddress)
|
nonce, err := suite.Kava.EvmClient.PendingNonceAt(context.Background(), whale.EvmAddress)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
@ -49,13 +48,3 @@ func (suite *E2eTestSuite) FundKavaErc20Balance(toAddress common.Address, amount
|
|||||||
|
|
||||||
return whale.SignAndBroadcastEvmTx(req)
|
return whale.SignAndBroadcastEvmTx(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *E2eTestSuite) GetErc20Balance(address common.Address) *big.Int {
|
|
||||||
resData, err := suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
|
||||||
To: &suite.DeployedErc20Address,
|
|
||||||
Data: util.BuildErc20BalanceOfCallData(address),
|
|
||||||
}, nil)
|
|
||||||
suite.NoError(err)
|
|
||||||
|
|
||||||
return new(big.Int).SetBytes(resData)
|
|
||||||
}
|
|
||||||
|
@ -15,7 +15,20 @@ func EvmContractMethodId(signature string) []byte {
|
|||||||
return hash.Sum(nil)[:4]
|
return hash.Sum(nil)[:4]
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildErc20TransferCallData(from common.Address, to common.Address, amount *big.Int) []byte {
|
func BuildErc20ApproveCallData(spender common.Address, amount *big.Int) []byte {
|
||||||
|
methodId := EvmContractMethodId("approve(address,uint256)")
|
||||||
|
paddedAddress := common.LeftPadBytes(spender.Bytes(), 32)
|
||||||
|
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
data = append(data, methodId...)
|
||||||
|
data = append(data, paddedAddress...)
|
||||||
|
data = append(data, paddedAmount...)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildErc20TransferCallData(to common.Address, amount *big.Int) []byte {
|
||||||
methodId := EvmContractMethodId("transfer(address,uint256)")
|
methodId := EvmContractMethodId("transfer(address,uint256)")
|
||||||
paddedAddress := common.LeftPadBytes(to.Bytes(), 32)
|
paddedAddress := common.LeftPadBytes(to.Bytes(), 32)
|
||||||
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
|
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
|
||||||
@ -28,6 +41,47 @@ func BuildErc20TransferCallData(from common.Address, to common.Address, amount *
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildErc20TransferFromCallData(from common.Address, to common.Address, amount *big.Int) []byte {
|
||||||
|
methodId := EvmContractMethodId("transferFrom(address,address,uint256)")
|
||||||
|
paddedFrom := common.LeftPadBytes(from.Bytes(), 32)
|
||||||
|
paddedTo := common.LeftPadBytes(to.Bytes(), 32)
|
||||||
|
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
data = append(data, methodId...)
|
||||||
|
data = append(data, paddedFrom...)
|
||||||
|
data = append(data, paddedTo...)
|
||||||
|
data = append(data, paddedAmount...)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildErc20MintCallData(to common.Address, amount *big.Int) []byte {
|
||||||
|
methodId := EvmContractMethodId("mint(address,uint256)")
|
||||||
|
paddedAddress := common.LeftPadBytes(to.Bytes(), 32)
|
||||||
|
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
data = append(data, methodId...)
|
||||||
|
data = append(data, paddedAddress...)
|
||||||
|
data = append(data, paddedAmount...)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildErc20BurnCallData(from common.Address, amount *big.Int) []byte {
|
||||||
|
methodId := EvmContractMethodId("burn(address,uint256)")
|
||||||
|
paddedAddress := common.LeftPadBytes(from.Bytes(), 32)
|
||||||
|
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
data = append(data, methodId...)
|
||||||
|
data = append(data, paddedAddress...)
|
||||||
|
data = append(data, paddedAmount...)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
func BuildErc20BalanceOfCallData(address common.Address) []byte {
|
func BuildErc20BalanceOfCallData(address common.Address) []byte {
|
||||||
methodId := EvmContractMethodId("balanceOf(address)")
|
methodId := EvmContractMethodId("balanceOf(address)")
|
||||||
paddedAddress := common.LeftPadBytes(address.Bytes(), 32)
|
paddedAddress := common.LeftPadBytes(address.Bytes(), 32)
|
||||||
|
Loading…
Reference in New Issue
Block a user