Skip to content

Commit

Permalink
tests(erc20): Add ERC20 metadata query integration tests (#2086)
Browse files Browse the repository at this point in the history
* add metadata query integration tests

* add changelog entry
  • Loading branch information
MalteHerrmann committed Nov 28, 2023
1 parent f909c22 commit 97307ca
Show file tree
Hide file tree
Showing 5 changed files with 529 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- (werc20) [#2074](https://github.com/evmos/evmos/pull/2074) Add `werc20` EVM Extension acceptance tests with `WEVMOS` contract.
- (erc20) [#2075](https://github.com/evmos/evmos/pull/2075) Align allowance adjustment errors with ERC20 contracts.
- (erc20) [#2080](https://github.com/evmos/evmos/pull/2080) Add ERC20 integration test setup.
- (erc20) [#2086](https://github.com/evmos/evmos/pull/2086) Add ERC20 metadata query integration tests.

### Bug Fixes

Expand Down
160 changes: 159 additions & 1 deletion precompiles/erc20/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/evmos/evmos/v15/contracts"
"github.com/evmos/evmos/v15/precompiles/erc20"
"github.com/evmos/evmos/v15/precompiles/erc20/testdata"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/evmos/evmos/v15/testutil/integration/evmos/keyring"
"github.com/evmos/evmos/v15/testutil/integration/evmos/network"
"github.com/evmos/evmos/v15/testutil/integration/evmos/utils"
erc20types "github.com/evmos/evmos/v15/x/erc20/types"
evmtypes "github.com/evmos/evmos/v15/x/evm/types"

//nolint:revive // dot imports are fine for Ginkgo
Expand Down Expand Up @@ -181,7 +183,163 @@ var _ = Describe("ERC20 Extension -", func() {

Context("basic functionality -", func() {})

Context("metadata query -", func() {})
Context("metadata query -", func() {
Context("for a token without registered metadata", func() {
BeforeEach(func() {
// Deploy ERC20NoMetadata contract for this test
erc20NoMetadataAddr, err := is.factory.DeployContract(
is.keyring.GetPrivKey(0),
evmtypes.EvmTxArgs{},
factory.ContractDeploymentData{
Contract: testdata.ERC20NoMetadataContract,
},
)
Expect(err).ToNot(HaveOccurred(), "failed to deploy contract")

// NOTE: update the address but leave the ABI as it is, so that the ABI includes
// the metadata methods but the contract doesn't have them.
contractsData.contractData[erc20Call] = ContractData{
Address: erc20NoMetadataAddr,
ABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
}
})

DescribeTable("querying the name should return an error", func(callType CallType) {
txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod)

_, _, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, execRevertedCheck)
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
},
Entry(" - direct call", directCall),
Entry(" - through contract", contractCall),
Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors
)

DescribeTable("querying the symbol should return an error", func(callType CallType) {
txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod)

_, _, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, execRevertedCheck)
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
},
Entry(" - direct call", directCall),
Entry(" - through contract", contractCall),
Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors
)

DescribeTable("querying the decimals should return an error", func(callType CallType) {
txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod)

_, _, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, execRevertedCheck)
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
},
Entry(" - direct call", directCall),
Entry(" - through contract", contractCall),
Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors
)
})

Context("for a token with available metadata", func() {
const (
denom = "axmpl"
expSymbol = "Xmpl"
expDecimals = uint8(18)
)

var (
erc20Addr common.Address
expName string
)

BeforeEach(func() {
erc20Addr = contractsData.GetContractData(erc20V5Call).Address
expName = erc20types.CreateDenom(erc20Addr.String())

// Register ERC20 token pair for this test
tokenPair, err := utils.RegisterERC20(is.factory, is.network, utils.ERC20RegistrationData{
Address: erc20Addr,
Denom: denom,
ProposerPriv: is.keyring.GetPrivKey(0),
})
Expect(err).ToNot(HaveOccurred(), "failed to register ERC20 token")

// overwrite the other precompile with this one, so that the test utils like is.getTxAndCallArgs still work.
is.precompile, err = setupERC20PrecompileForTokenPair(*is.network, tokenPair)
Expect(err).ToNot(HaveOccurred(), "failed to set up erc20 precompile")

// update this in the global contractsData
contractsData.contractData[directCall] = ContractData{
Address: is.precompile.Address(),
ABI: is.precompile.ABI,
}

// Deploy contract calling the ERC20 precompile
callerAddr, err := is.factory.DeployContract(
is.keyring.GetPrivKey(0),
evmtypes.EvmTxArgs{},
factory.ContractDeploymentData{
Contract: testdata.ERC20AllowanceCallerContract,
ConstructorArgs: []interface{}{
is.precompile.Address(),
},
},
)
Expect(err).ToNot(HaveOccurred(), "failed to deploy contract")

contractsData.contractData[contractCall] = ContractData{
Address: callerAddr,
ABI: testdata.ERC20AllowanceCallerContract.ABI,
}
})

DescribeTable("querying the name should return the name", func(callType CallType) {
txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod)

_, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, passCheck)
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")

var name string
err = is.precompile.UnpackIntoInterface(&name, erc20.NameMethod, ethRes.Ret)
Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
Expect(name).To(Equal(expName), "expected different name")
},
Entry(" - direct call", directCall),
Entry(" - through contract", contractCall),
Entry(" - through erc20 v5 contract", erc20V5Call),
)

DescribeTable("querying the symbol should return the symbol", func(callType CallType) {
txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod)

_, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, passCheck)
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")

var symbol string
err = is.precompile.UnpackIntoInterface(&symbol, erc20.SymbolMethod, ethRes.Ret)
Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
Expect(symbol).To(Equal(expSymbol), "expected different symbol")
},
Entry(" - direct call", directCall),
Entry(" - through contract", contractCall),
Entry(" - through erc20 v5 contract", erc20V5Call),
)

DescribeTable("querying the decimals should return the decimals", func(callType CallType) {
txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod)

_, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, passCheck)
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")

var decimals uint8
err = is.precompile.UnpackIntoInterface(&decimals, erc20.DecimalsMethod, ethRes.Ret)
Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
Expect(decimals).To(Equal(expDecimals), "expected different decimals")
},
Entry(" - direct call", directCall),
Entry(" - through contract", contractCall),
Entry(" - through erc20 v5 contract", erc20V5Call),
)
})
})

Context("allowance adjustments -", func() {})
})
Expand Down
5 changes: 5 additions & 0 deletions precompiles/erc20/testdata/ERC20NoMetadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"abi": "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
"bin": "608060405234801561000f575f80fd5b50610ef58061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610086575f3560e01c806370a082311161005957806370a0823114610138578063a457c2d714610168578063a9059cbb14610198578063dd62ed3e146101c857610086565b8063095ea7b31461008a57806318160ddd146100ba57806323b872dd146100d85780633950935114610108575b5f80fd5b6100a4600480360381019061009f9190610941565b6101f8565b6040516100b19190610999565b60405180910390f35b6100c261021a565b6040516100cf91906109c1565b60405180910390f35b6100f260048036038101906100ed91906109da565b610223565b6040516100ff9190610999565b60405180910390f35b610122600480360381019061011d9190610941565b610251565b60405161012f9190610999565b60405180910390f35b610152600480360381019061014d9190610a2a565b610287565b60405161015f91906109c1565b60405180910390f35b610182600480360381019061017d9190610941565b6102cc565b60405161018f9190610999565b60405180910390f35b6101b260048036038101906101ad9190610941565b610341565b6040516101bf9190610999565b60405180910390f35b6101e260048036038101906101dd9190610a55565b610363565b6040516101ef91906109c1565b60405180910390f35b5f806102026103e5565b905061020f8185856103ec565b600191505092915050565b5f600254905090565b5f8061022d6103e5565b905061023a8582856105af565b61024585858561063a565b60019150509392505050565b5f8061025b6103e5565b905061027c81858561026d8589610363565b6102779190610ac0565b6103ec565b600191505092915050565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f806102d66103e5565b90505f6102e38286610363565b905083811015610328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031f90610b73565b60405180910390fd5b61033582868684036103ec565b60019250505092915050565b5f8061034b6103e5565b905061035881858561063a565b600191505092915050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361045a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045190610c01565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036104c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104bf90610c8f565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516105a291906109c1565b60405180910390a3505050565b5f6105ba8484610363565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146106345781811015610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90610cf7565b60405180910390fd5b61063384848484036103ec565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161069f90610d85565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610716576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161070d90610e13565b60405180910390fd5b6107218383836108a6565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156107a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079b90610ea1565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550815f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161088d91906109c1565b60405180910390a36108a08484846108ab565b50505050565b505050565b505050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6108dd826108b4565b9050919050565b6108ed816108d3565b81146108f7575f80fd5b50565b5f81359050610908816108e4565b92915050565b5f819050919050565b6109208161090e565b811461092a575f80fd5b50565b5f8135905061093b81610917565b92915050565b5f8060408385031215610957576109566108b0565b5b5f610964858286016108fa565b92505060206109758582860161092d565b9150509250929050565b5f8115159050919050565b6109938161097f565b82525050565b5f6020820190506109ac5f83018461098a565b92915050565b6109bb8161090e565b82525050565b5f6020820190506109d45f8301846109b2565b92915050565b5f805f606084860312156109f1576109f06108b0565b5b5f6109fe868287016108fa565b9350506020610a0f868287016108fa565b9250506040610a208682870161092d565b9150509250925092565b5f60208284031215610a3f57610a3e6108b0565b5b5f610a4c848285016108fa565b91505092915050565b5f8060408385031215610a6b57610a6a6108b0565b5b5f610a78858286016108fa565b9250506020610a89858286016108fa565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610aca8261090e565b9150610ad58361090e565b9250828201905080821115610aed57610aec610a93565b5b92915050565b5f82825260208201905092915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f775f8201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b5f610b5d602583610af3565b9150610b6882610b03565b604082019050919050565b5f6020820190508181035f830152610b8a81610b51565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f206164645f8201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b5f610beb602483610af3565b9150610bf682610b91565b604082019050919050565b5f6020820190508181035f830152610c1881610bdf565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f2061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f610c79602283610af3565b9150610c8482610c1f565b604082019050919050565b5f6020820190508181035f830152610ca681610c6d565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000005f82015250565b5f610ce1601d83610af3565b9150610cec82610cad565b602082019050919050565b5f6020820190508181035f830152610d0e81610cd5565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f610d6f602583610af3565b9150610d7a82610d15565b604082019050919050565b5f6020820190508181035f830152610d9c81610d63565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f20616464725f8201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b5f610dfd602383610af3565b9150610e0882610da3565b604082019050919050565b5f6020820190508181035f830152610e2a81610df1565b9050919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320625f8201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b5f610e8b602683610af3565b9150610e9682610e31565b604082019050919050565b5f6020820190508181035f830152610eb881610e7f565b905091905056fea2646970667358221220d423aba14b83b76e2100eddaab80ec25e68f9885be44dc7127bac142c612b6e364736f6c63430008140033",
"contractName": "ERC20NoMetadata"
}

0 comments on commit 97307ca

Please sign in to comment.