Skip to content

Commit

Permalink
tests(erc20): add erc20 query tests (evmos#2023)
Browse files Browse the repository at this point in the history
  • Loading branch information
MalteHerrmann authored Nov 9, 2023
1 parent 377bfd9 commit 0add6e8
Show file tree
Hide file tree
Showing 5 changed files with 702 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- (utils) [#2010](https://github.com/evmos/evmos/pull/2010) Add utils function to create ibc denom trace.
- (erc20) [#2012](https://github.com/evmos/evmos/pull/2012) Adjust ERC20 extension approvals to handle multiple denominations.
- (osmosis-outpost) [#2017](https://github.com/evmos/evmos/pull/2017) Refactor types, errors and precompile struct.
- (erc20) [#2023](https://github.com/evmos/evmos/pull/2023) Add tests for ERC20 precompile queries.
- (osmosis-outpost) [#2025](https://github.com/evmos/evmos/pull/2025) Use a struct to wrap parsed parameters from Solidity.

### Bug Fixes
Expand Down
71 changes: 43 additions & 28 deletions precompiles/erc20/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
"github.com/evmos/evmos/v15/precompiles/authorization"
auth "github.com/evmos/evmos/v15/precompiles/authorization"
transferkeeper "github.com/evmos/evmos/v15/x/ibc/transfer/keeper"

"github.com/ethereum/go-ethereum/accounts/abi"
Expand All @@ -43,7 +43,7 @@ const (
)

// Name returns the name of the token. If the token metadata is registered in the
// bank module, it returns its name. Otherwise it returns the base denomination of
// bank module, it returns its name. Otherwise, it returns the base denomination of
// the token capitalized (eg. uatom -> Atom).
func (p Precompile) Name(
ctx sdk.Context,
Expand All @@ -57,20 +57,12 @@ func (p Precompile) Name(
return method.Outputs.Pack(metadata.Name)
}

// Infer the denomination name from the coin denomination base denom
denomTrace, err := GetDenomTrace(p.transferKeeper, ctx, p.tokenPair.Denom)
baseDenom, err := p.getBaseDenomFromIBCVoucher(ctx, p.tokenPair.Denom)
if err != nil {
// FIXME: return 'not supported' (same error as when you call the method on an ERC20.sol)
return nil, err
}

// safety check
if len(denomTrace.BaseDenom) < 3 {
// FIXME: return not supported (same error as when you call the method on an ERC20.sol)
return nil, nil
}

name := strings.ToUpper(string(denomTrace.BaseDenom[1])) + denomTrace.BaseDenom[2:]
name := strings.ToUpper(string(baseDenom[1])) + baseDenom[2:]
return method.Outputs.Pack(name)
}

Expand All @@ -89,19 +81,12 @@ func (p Precompile) Symbol(
return method.Outputs.Pack(metadata.Symbol)
}

denomTrace, err := GetDenomTrace(p.transferKeeper, ctx, p.tokenPair.Denom)
baseDenom, err := p.getBaseDenomFromIBCVoucher(ctx, p.tokenPair.Denom)
if err != nil {
// FIXME: return not supported (same error as when you call the method on an ERC20.sol)
return nil, err
}

// safety check
if len(denomTrace.BaseDenom) < 3 {
// FIXME: return not supported (same error as when you call the method on an ERC20.sol)
return nil, nil
}

symbol := strings.ToUpper(denomTrace.BaseDenom[1:])
symbol := strings.ToUpper(baseDenom[1:])
return method.Outputs.Pack(symbol)
}

Expand Down Expand Up @@ -131,22 +116,34 @@ func (p Precompile) Decimals(
return method.Outputs.Pack(uint8(18))
}
// FIXME: return not supported (same error as when you call the method on an ERC20.sol)
return nil, nil
return nil, fmt.Errorf(
"invalid base denomination; should be either micro ('u[...]') or atto ('a[...]'); got: %q",
denomTrace.BaseDenom,
)
}

var decimals uint32
for i := len(metadata.DenomUnits); i >= 0; i-- {
var (
decimals uint32
displayFound bool
)
for i := len(metadata.DenomUnits) - 1; i >= 0; i-- {
if metadata.DenomUnits[i].Denom == metadata.Display {
decimals = metadata.DenomUnits[i].Exponent
displayFound = true
break
}
}

if !displayFound {
// FIXME: return not supported (same error as when you call the method on an ERC20.sol)
return nil, fmt.Errorf("display denomination not found for denom: %q", p.tokenPair.Denom)
}

if decimals > math.MaxUint8 {
return nil, errors.New("uint8 overflow: invalid decimals")
return nil, fmt.Errorf("uint8 overflow: invalid decimals: %d", decimals)
}

return method.Outputs.Pack(uint8(decimals)) //#nosec G701
return method.Outputs.Pack(uint8(decimals)) //#nosec G701 // we are checking for overflow above
}

// TotalSupply returns the amount of tokens in existence. It fetches the supply
Expand Down Expand Up @@ -208,7 +205,7 @@ func (p Precompile) Allowance(
}

// GetDenomTrace returns the denomination trace from the corresponding IBC denomination. If the
// denomination is is not an IBC voucher or the trace is not found, it returns an error.
// denomination is not an IBC voucher or the trace is not found, it returns an error.
func GetDenomTrace(
transferKeeper transferkeeper.Keeper,
ctx sdk.Context,
Expand Down Expand Up @@ -239,7 +236,7 @@ func GetAuthzExpirationAndAllowance(
grantee, granter common.Address,
denom string,
) (authz.Authorization, *time.Time, *big.Int, error) {
authorization, expiration, err := authorization.CheckAuthzExists(ctx, authzKeeper, grantee, granter, SendMsgURL)
authorization, expiration, err := auth.CheckAuthzExists(ctx, authzKeeper, grantee, granter, SendMsgURL)
// TODO: return error if doesn't exist?
if err != nil {
return nil, nil, common.Big0, err
Expand All @@ -254,3 +251,21 @@ func GetAuthzExpirationAndAllowance(
allowance := sendAuth.SpendLimit.AmountOfNoDenomValidation(denom)
return authorization, expiration, allowance.BigInt(), nil
}

// getBaseDenomFromIBCVoucher returns the base denomination from the given IBC voucher denomination.
func (p Precompile) getBaseDenomFromIBCVoucher(ctx sdk.Context, denom string) (string, error) {
// Infer the denomination name from the coin denomination base denom
denomTrace, err := GetDenomTrace(p.transferKeeper, ctx, denom)
if err != nil {
// FIXME: return 'not supported' (same error as when you call the method on an ERC20.sol)
return "", err
}

// safety check
if len(denomTrace.BaseDenom) < 3 {
// FIXME: return not supported (same error as when you call the method on an ERC20.sol)
return "", fmt.Errorf("invalid base denomination; should be at least length 3; got: %q", denomTrace.BaseDenom)
}

return denomTrace.BaseDenom, nil
}
Loading

0 comments on commit 0add6e8

Please sign in to comment.