Skip to content

Commit 0c7c32b

Browse files
committed
tests: enhance error handling with specific solidity error in erc20
1 parent 08191b8 commit 0c7c32b

8 files changed

Lines changed: 250 additions & 163 deletions

File tree

tests/integration/precompiles/erc20/test_approve.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package erc20
22

33
import (
4+
"fmt"
45
"math/big"
56

67
"github.com/ethereum/go-ethereum/accounts/abi"
78
"github.com/ethereum/go-ethereum/common"
89
"github.com/ethereum/go-ethereum/core/vm"
910

11+
cmn "github.com/cosmos/evm/precompiles/common"
1012
"github.com/cosmos/evm/precompiles/erc20"
1113
"github.com/cosmos/evm/precompiles/testutil"
1214
)
@@ -21,12 +23,13 @@ func (s *PrecompileTestSuite) TestApprove() {
2123
malleate func() []interface{}
2224
postCheck func()
2325
expPass bool
26+
wantErr error
2427
errContains string
2528
}{
2629
{
27-
name: "fail - empty args",
28-
malleate: func() []interface{} { return nil },
29-
errContains: "invalid number of arguments",
30+
name: "fail - empty args",
31+
malleate: func() []interface{} { return nil },
32+
wantErr: cmn.NewRevertWithSolidityError(s.precompile.ABI, cmn.SolidityErrInvalidNumberOfArgs, big.NewInt(2), big.NewInt(0)),
3033
},
3134
{
3235
name: "fail - invalid number of arguments",
@@ -35,7 +38,7 @@ func (s *PrecompileTestSuite) TestApprove() {
3538
1, 2, 3,
3639
}
3740
},
38-
errContains: "invalid number of arguments",
41+
wantErr: cmn.NewRevertWithSolidityError(s.precompile.ABI, cmn.SolidityErrInvalidNumberOfArgs, big.NewInt(2), big.NewInt(3)),
3942
},
4043
{
4144
name: "fail - invalid address",
@@ -44,7 +47,7 @@ func (s *PrecompileTestSuite) TestApprove() {
4447
"invalid address", big.NewInt(2),
4548
}
4649
},
47-
errContains: "invalid address",
50+
wantErr: cmn.NewRevertWithSolidityError(s.precompile.ABI, cmn.SolidityErrInvalidAddress, "invalid address"),
4851
},
4952
{
5053
name: "fail - invalid amount",
@@ -53,7 +56,7 @@ func (s *PrecompileTestSuite) TestApprove() {
5356
s.keyring.GetAddr(1), "invalid amount",
5457
}
5558
},
56-
errContains: "invalid amount",
59+
wantErr: cmn.NewRevertWithSolidityError(s.precompile.ABI, cmn.SolidityErrInvalidAmount, "invalid amount"),
5760
},
5861
{
5962
name: "fail - negative amount",
@@ -62,7 +65,7 @@ func (s *PrecompileTestSuite) TestApprove() {
6265
s.keyring.GetAddr(1), big.NewInt(-1),
6366
}
6467
},
65-
errContains: erc20.ErrNegativeAmount.Error(),
68+
wantErr: cmn.NewRevertWithSolidityError(s.precompile.ABI, cmn.SolidityErrInvalidAmount, "cannot approve negative values"),
6669
},
6770
{
6871
name: "fail - approve uint256 overflow",
@@ -71,7 +74,8 @@ func (s *PrecompileTestSuite) TestApprove() {
7174
s.keyring.GetAddr(1), new(big.Int).Add(abi.MaxUint256, common.Big1),
7275
}
7376
},
74-
errContains: "causes integer overflow",
77+
wantErr: cmn.NewRevertWithSolidityError(s.precompile.ABI, cmn.SolidityErrInvalidAmount,
78+
fmt.Sprintf(erc20.ErrIntegerOverflow, new(big.Int).Add(abi.MaxUint256, common.Big1))),
7579
},
7680
{
7781
name: "pass - approve to zero with existing allowance only for other denominations",
@@ -241,7 +245,11 @@ func (s *PrecompileTestSuite) TestApprove() {
241245
s.Require().NotNil(bz, "expected non-nil bytes")
242246
} else {
243247
s.Require().Error(err, "expected error")
244-
s.Require().ErrorContains(err, tc.errContains, "expected different error message")
248+
if tc.wantErr != nil {
249+
testutil.RequireExactError(s.T(), err, tc.wantErr)
250+
} else {
251+
s.Require().ErrorContains(err, tc.errContains, "expected different error message")
252+
}
245253
s.Require().Empty(bz, "expected empty bytes")
246254
}
247255

tests/integration/precompiles/erc20/test_integration.go

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
. "github.com/onsi/gomega"
1717

1818
"github.com/cosmos/evm/contracts"
19+
cmn "github.com/cosmos/evm/precompiles/common"
1920
"github.com/cosmos/evm/precompiles/erc20"
2021
"github.com/cosmos/evm/precompiles/erc20/testdata"
2122
"github.com/cosmos/evm/precompiles/testutil"
@@ -396,7 +397,18 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
396397
// Transfer tokens
397398
txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferAmount)
398399

399-
revertReasonCheck := revertReasonExactCheck(execRevertedCheck, erc20.ErrTransferAmountExceedsBalance.Error())
400+
contractAddr := contractsData.GetContractData(callType).Address
401+
402+
var revertReasonCheck testutil.LogCheckArgs
403+
switch callType {
404+
case erc20V5CallerCall:
405+
// Caller uses OpenZeppelin ERC20, which reverts with Error(string), not IERC20Errors.
406+
revertReasonCheck = failCheck.WithErrContains("ERC20: transfer amount exceeds balance")
407+
default:
408+
revertReasonCheck = failCheck.WithErrExact(cmn.NewRevertWithSolidityError(
409+
is.precompile.ABI, erc20.SolidityErrERC20InsufficientBalance, contractAddr, common.Big0, transferAmount,
410+
))
411+
}
400412

401413
_, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, revertReasonCheck)
402414
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -420,7 +432,9 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
420432
// Transfer tokens
421433
txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferAmt)
422434

423-
insufficientBalanceCheck := revertReasonExactCheck(failCheck, erc20.ErrTransferAmountExceedsBalance.Error())
435+
insufficientBalanceCheck := failCheck.WithErrExact(cmn.NewRevertWithSolidityError(
436+
is.precompile.ABI, erc20.SolidityErrERC20InsufficientBalance, sender.Addr, senderInitialAmt.BigInt(), transferAmt,
437+
))
424438

425439
_, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck)
426440
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -706,10 +720,14 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
706720
owner.Addr, receiver, transferAmount,
707721
)
708722

709-
transferCheck := passCheck.WithExpEvents(
710-
erc20.EventTypeTransfer,
711-
erc20.EventTypeApproval,
712-
)
723+
var transferCheck testutil.LogCheckArgs
724+
switch callType {
725+
case erc20Call:
726+
// ERC20MinterBurnerDecimals (OZ in this build) does not emit Approval on transferFrom spend.
727+
transferCheck = passCheck.WithExpEvents(erc20.EventTypeTransfer)
728+
default:
729+
transferCheck = passCheck.WithExpEvents(erc20.EventTypeTransfer, erc20.EventTypeApproval)
730+
}
713731

714732
_, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, transferCheck)
715733
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -760,7 +778,10 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
760778
owner.Addr, receiver, transferCoins[0].Amount.BigInt(),
761779
)
762780

763-
insufficientAllowanceCheck := revertReasonExactCheck(failCheck, erc20.ErrInsufficientAllowance.Error())
781+
insufficientAllowanceCheck := failCheck.WithErrExact(cmn.NewRevertWithSolidityError(
782+
is.precompile.ABI, erc20.SolidityErrERC20InsufficientAllowance,
783+
owner.Addr, common.Big0, transferCoins[0].Amount.BigInt(),
784+
))
764785

765786
_, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, insufficientAllowanceCheck)
766787
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -810,10 +831,12 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
810831
owner.Addr, receiver, transferCoins[0].Amount.BigInt(),
811832
)
812833

813-
transferCheck := passCheck.WithExpEvents(
814-
erc20.EventTypeTransfer,
815-
erc20.EventTypeApproval,
816-
)
834+
var transferCheck testutil.LogCheckArgs
835+
if callType == erc20Call {
836+
transferCheck = passCheck.WithExpEvents(erc20.EventTypeTransfer)
837+
} else {
838+
transferCheck = passCheck.WithExpEvents(erc20.EventTypeTransfer, erc20.EventTypeApproval)
839+
}
817840

818841
_, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, transferArgs, transferCheck)
819842
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -867,7 +890,10 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
867890
owner.Addr, receiver, transferAmount,
868891
)
869892

870-
insufficientAllowanceCheck := revertReasonExactCheck(failCheck, erc20.ErrInsufficientAllowance.Error())
893+
insufficientAllowanceCheck := failCheck.WithErrExact(cmn.NewRevertWithSolidityError(
894+
is.precompile.ABI, erc20.SolidityErrERC20InsufficientAllowance,
895+
spender.Addr, approveAmount, transferAmount,
896+
))
871897

872898
_, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, insufficientAllowanceCheck)
873899
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -899,7 +925,10 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
899925
from.Addr, receiver, transferAmount,
900926
)
901927

902-
insufficientAllowanceCheck := revertReasonExactCheck(failCheck, erc20.ErrInsufficientAllowance.Error())
928+
insufficientAllowanceCheck := failCheck.WithErrExact(cmn.NewRevertWithSolidityError(
929+
is.precompile.ABI, erc20.SolidityErrERC20InsufficientAllowance,
930+
sender.Addr, common.Big0, transferAmount,
931+
))
903932

904933
_, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientAllowanceCheck)
905934
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -937,7 +966,9 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
937966
// Transfer tokens
938967
txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferFromMethod, from.Addr, receiver, transferAmt)
939968

940-
insufficientBalanceCheck := revertReasonExactCheck(failCheck, erc20.ErrTransferAmountExceedsBalance.Error())
969+
insufficientBalanceCheck := failCheck.WithErrExact(cmn.NewRevertWithSolidityError(
970+
is.precompile.ABI, erc20.SolidityErrERC20InsufficientBalance, from.Addr, senderInitialAmt.BigInt(), transferAmt,
971+
))
941972

942973
_, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck)
943974
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
@@ -1103,7 +1134,18 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options
11031134
from.Addr, receiver, transferAmount,
11041135
)
11051136

1106-
revertReasonCheck := revertReasonExactCheck(execRevertedCheck, erc20.ErrInsufficientAllowance.Error())
1137+
spenderPrecompileAddr := contractsData.GetContractData(callType).Address
1138+
1139+
var revertReasonCheck testutil.LogCheckArgs
1140+
switch callType {
1141+
case erc20V5CallerCall:
1142+
revertReasonCheck = failCheck.WithErrContains("ERC20: insufficient allowance")
1143+
default:
1144+
revertReasonCheck = failCheck.WithErrExact(cmn.NewRevertWithSolidityError(
1145+
is.precompile.ABI, erc20.SolidityErrERC20InsufficientAllowance,
1146+
spenderPrecompileAddr, approveAmount, transferAmount,
1147+
))
1148+
}
11071149

11081150
_, ethRes, err := is.factory.CallContractAndCheckLogs(from.Priv, txArgs, transferArgs, revertReasonCheck)
11091151
Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")

0 commit comments

Comments
 (0)