forked from evmos/evmos
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
imp(erc20): minor alignments between ERC20 extension and contracts (e…
…vmos#2067) * adjust approval behavior when approving 0 * add error vars for erc20 extension * add helper to align errors with ERC20 errors * add changelog entry * add missing license * check error * move error to errors file * further error refactors
- Loading branch information
1 parent
35fe239
commit ac21bae
Showing
9 changed files
with
142 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright Tharsis Labs Ltd.(Evmos) | ||
// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) | ||
|
||
package erc20 | ||
|
||
import ( | ||
"errors" | ||
"strings" | ||
|
||
"github.com/cosmos/cosmos-sdk/x/authz" | ||
"github.com/ethereum/go-ethereum/accounts/abi" | ||
"github.com/ethereum/go-ethereum/crypto" | ||
evmtypes "github.com/evmos/evmos/v15/x/evm/types" | ||
) | ||
|
||
// Errors that have formatted information are defined here as a string. | ||
const ( | ||
ErrIntegerOverflow = "amount %s causes integer overflow" | ||
ErrNoAllowanceForToken = "allowance for token %s does not exist" | ||
ErrSubtractMoreThanAllowance = "subtracted value cannot be greater than existing allowance for denom %s: %s > %s" | ||
) | ||
|
||
var ( | ||
// errorSignature are the prefix bytes for the hex-encoded reason string. See UnpackRevert in ABI implementation in Geth. | ||
errorSignature = crypto.Keccak256([]byte("Error(string)")) | ||
|
||
// Precompile errors | ||
ErrDecreaseNonPositiveValue = errors.New("cannot decrease allowance with non-positive values") | ||
ErrDenomTraceNotFound = errors.New("denom trace not found") | ||
ErrIncreaseNonPositiveValue = errors.New("cannot increase allowance with non-positive values") | ||
ErrNegativeAmount = errors.New("cannot approve negative values") | ||
ErrNoIBCVoucherDenom = errors.New("denom is not an IBC voucher") | ||
|
||
// ErrInsufficientAllowance is returned by ERC20 smart contracts in case | ||
// no authorization is found or the granted amount is not sufficient. | ||
ErrInsufficientAllowance = errors.New("ERC20: insufficient allowance") | ||
// ErrTransferAmountExceedsBalance is returned by ERC20 smart contracts in | ||
// case a transfer is attempted, that sends more than the sender's balance. | ||
ErrTransferAmountExceedsBalance = errors.New("ERC20: transfer amount exceeds balance") | ||
) | ||
|
||
// BuildExecRevertedErr returns a mocked error that should align with the | ||
// behavior of the original ERC20 Solidity implementation. | ||
// | ||
// FIXME: This is not yet producing the correct reason bytes. Will fix on a follow up PR. | ||
func BuildExecRevertedErr(reason string) (error, error) { | ||
// This is reverse-engineering the ABI encoding of the revert reason. | ||
typ, err := abi.NewType("string", "", nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
packedReason, err := (abi.Arguments{{Type: typ}}).Pack(reason) | ||
if err != nil { | ||
return nil, errors.New("failed to pack revert reason") | ||
} | ||
|
||
var reasonBytes []byte | ||
reasonBytes = append(reasonBytes, errorSignature...) | ||
reasonBytes = append(reasonBytes, packedReason...) | ||
|
||
return evmtypes.NewExecErrorWithReason(reasonBytes), nil | ||
} | ||
|
||
// convertErrToERC20Error is a helper function which maps errors raised by the Cosmos SDK stack | ||
// to the corresponding errors which are raised by an ERC20 contract. | ||
// | ||
// TODO: Create the full RevertError types instead of just the standard error type. | ||
// | ||
// TODO: Return ERC-6093 compliant errors. | ||
func convertErrToERC20Error(err error) error { | ||
switch { | ||
case strings.Contains(err.Error(), "spendable balance"): | ||
return ErrTransferAmountExceedsBalance | ||
case strings.Contains(err.Error(), "requested amount is more than spend limit"): | ||
return ErrInsufficientAllowance | ||
case strings.Contains(err.Error(), authz.ErrNoAuthorizationFound.Error()): | ||
return ErrInsufficientAllowance | ||
default: | ||
return err | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package erc20_test | ||
|
||
import ( | ||
"github.com/evmos/evmos/v15/precompiles/erc20" | ||
evmtypes "github.com/evmos/evmos/v15/x/evm/types" | ||
) | ||
|
||
// TODO: This is not yet producing the correct reason bytes so we skip this test for now, | ||
// until that's correctly implemented. | ||
func (s *PrecompileTestSuite) TestBuildExecRevertedError() { | ||
s.T().Skip("skipping until correctly implemented") | ||
|
||
reason := "ERC20: transfer amount exceeds balance" | ||
revErr, err := erc20.BuildExecRevertedErr(reason) | ||
s.Require().NoError(err, "should not error when building revert error") | ||
|
||
revertErr, ok := revErr.(*evmtypes.RevertError) | ||
s.Require().True(ok, "error should be a revert error") | ||
|
||
// Here we expect the correct revert reason that's returned by an ERC20 Solidity contract. | ||
s.Require().Equal( | ||
"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63650000000000000000000000000000000000000000000000000000", | ||
revertErr.ErrorData(), | ||
"error data should be the revert reason") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.