From 74da22f26729189bdd2978efefafd6f8371ea3ef Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Thu, 28 Mar 2024 21:43:09 +0100 Subject: [PATCH] Update Precompile Input Method + Evm Balance --- precompiles/addr/addr.go | 5 ++++- precompiles/bank/bank.go | 8 +++++--- precompiles/common/precompiles.go | 13 ++++++++++++- precompiles/distribution/distribution.go | 5 ++++- precompiles/gov/gov.go | 5 ++++- precompiles/ibc/ibc.go | 5 ++++- precompiles/json/json.go | 9 +++++++++ precompiles/oracle/oracle.go | 5 ++++- precompiles/staking/staking.go | 5 ++++- precompiles/wasmd/wasmd.go | 5 ++++- x/evm/state/check.go | 5 +++++ x/evm/state/check_test.go | 9 +++++++-- 12 files changed, 66 insertions(+), 13 deletions(-) diff --git a/precompiles/addr/addr.go b/precompiles/addr/addr.go index ac1c80513b..9d10fb1b70 100644 --- a/precompiles/addr/addr.go +++ b/precompiles/addr/addr.go @@ -70,7 +70,10 @@ func NewPrecompile(evmKeeper pcommon.EVMKeeper) (*Precompile, error) { // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } method, err := p.ABI.MethodById(methodID) if err != nil { diff --git a/precompiles/bank/bank.go b/precompiles/bank/bank.go index d5ff728a94..99da368125 100644 --- a/precompiles/bank/bank.go +++ b/precompiles/bank/bank.go @@ -99,7 +99,10 @@ func NewPrecompile(bankKeeper pcommon.BankKeeper, evmKeeper pcommon.EVMKeeper) ( // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } method, err := p.ABI.MethodById(methodID) if err != nil { @@ -127,7 +130,6 @@ func (p Precompile) Run(evm *vm.EVM, caller common.Address, input []byte, value } return p.send(ctx, method, args, value) case SendNativeMethod: - // TODO: Add validation on caller separate from validation above return p.sendNative(ctx, method, args, caller, value) case BalanceMethod: return p.balance(ctx, method, args, value) @@ -255,7 +257,7 @@ func (p Precompile) symbol(ctx sdk.Context, method *abi.Method, args []interface func (p Precompile) decimals(_ sdk.Context, method *abi.Method, _ []interface{}, value *big.Int) ([]byte, error) { pcommon.AssertNonPayable(value) - // all native tokens are integer-based + // all native tokens are integer-based, returns decimals for microdenom (usei) return method.Outputs.Pack(uint8(0)) } diff --git a/precompiles/common/precompiles.go b/precompiles/common/precompiles.go index 6cdc892166..7579c4073d 100644 --- a/precompiles/common/precompiles.go +++ b/precompiles/common/precompiles.go @@ -36,7 +36,10 @@ func (p Precompile) Prepare(evm *vm.EVM, input []byte) (sdk.Context, *abi.Method if !ok { return sdk.Context{}, nil, nil, errors.New("cannot get context from EVM") } - methodID := input[:4] + methodID, err := ExtractMethodID(input) + if err != nil { + return sdk.Context{}, nil, nil, err + } method, err := p.ABI.MethodById(methodID) if err != nil { return sdk.Context{}, nil, nil, err @@ -102,3 +105,11 @@ func ValidateCaller(ctx sdk.Context, evmKeeper EVMKeeper, caller common.Address, } return fmt.Errorf("calling contract %s with code hash %s is not whitelisted for delegate calls", callingContract.Hex(), codeHash.Hex()) } + +func ExtractMethodID(input []byte) ([]byte, error) { + // Check if the input has at least the length needed for methodID + if len(input) < 4 { + return nil, errors.New("input too short to extract method ID") + } + return input[:4], nil +} diff --git a/precompiles/distribution/distribution.go b/precompiles/distribution/distribution.go index 1465b1e7e4..9335291708 100644 --- a/precompiles/distribution/distribution.go +++ b/precompiles/distribution/distribution.go @@ -76,7 +76,10 @@ func NewPrecompile(distrKeeper pcommon.DistributionKeeper, evmKeeper pcommon.EVM // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } if bytes.Equal(methodID, p.SetWithdrawAddrID) { return 30000 diff --git a/precompiles/gov/gov.go b/precompiles/gov/gov.go index ea372d21fe..b140cf6081 100644 --- a/precompiles/gov/gov.go +++ b/precompiles/gov/gov.go @@ -79,7 +79,10 @@ func NewPrecompile(govKeeper pcommon.GovKeeper, evmKeeper pcommon.EVMKeeper, ban // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } if bytes.Equal(methodID, p.VoteID) { return 30000 diff --git a/precompiles/ibc/ibc.go b/precompiles/ibc/ibc.go index cbef497485..e5f9d37bd4 100644 --- a/precompiles/ibc/ibc.go +++ b/precompiles/ibc/ibc.go @@ -78,7 +78,10 @@ func NewPrecompile(transferKeeper pcommon.TransferKeeper, evmKeeper pcommon.EVMK // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } method, err := p.ABI.MethodById(methodID) if err != nil { diff --git a/precompiles/json/json.go b/precompiles/json/json.go index 1a3d5eb4c5..5a0434751f 100644 --- a/precompiles/json/json.go +++ b/precompiles/json/json.go @@ -4,6 +4,7 @@ import ( "bytes" "embed" gjson "encoding/json" + "errors" "fmt" "math/big" "strings" @@ -73,6 +74,9 @@ func NewPrecompile() (*Precompile, error) { // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { + if len(input) < 4 { + return 0 + } return uint64(GasCostPerByte * (len(input) - 4)) } @@ -101,6 +105,11 @@ func (p Precompile) Run(evm *vm.EVM, _ common.Address, input []byte, value *big. if err != nil { return nil, err } + + if uint_.BitLen() > 256 { + return nil, errors.New("value does not fit in 32 bytes") + } + uint_.FillBytes(byteArr) return byteArr, nil } diff --git a/precompiles/oracle/oracle.go b/precompiles/oracle/oracle.go index fbe18402e4..110809e93c 100644 --- a/precompiles/oracle/oracle.go +++ b/precompiles/oracle/oracle.go @@ -95,7 +95,10 @@ func NewPrecompile(oracleKeeper pcommon.OracleKeeper, evmKeeper pcommon.EVMKeepe // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } method, err := p.ABI.MethodById(methodID) if err != nil { diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 7115fec03b..6b27362c3a 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -84,7 +84,10 @@ func NewPrecompile(stakingKeeper pcommon.StakingKeeper, evmKeeper pcommon.EVMKee // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } if bytes.Equal(methodID, p.DelegateID) { return 50000 diff --git a/precompiles/wasmd/wasmd.go b/precompiles/wasmd/wasmd.go index 72acb075e2..20468e0283 100644 --- a/precompiles/wasmd/wasmd.go +++ b/precompiles/wasmd/wasmd.go @@ -82,7 +82,10 @@ func NewPrecompile(evmKeeper pcommon.EVMKeeper, wasmdKeeper pcommon.WasmdKeeper, // RequiredGas returns the required bare minimum gas to execute the precompile. func (p Precompile) RequiredGas(input []byte) uint64 { - methodID := input[:4] + methodID, err := pcommon.ExtractMethodID(input) + if err != nil { + return 0 + } method, err := p.ABI.MethodById(methodID) if err != nil { diff --git a/x/evm/state/check.go b/x/evm/state/check.go index 7053a4b864..3b3a6b606b 100644 --- a/x/evm/state/check.go +++ b/x/evm/state/check.go @@ -23,6 +23,11 @@ func (s *DBImpl) Exist(addr common.Address) bool { return true } + // check if account has a balance + if s.GetBalance(addr).Cmp(utils.Big0) > 0 { + return true + } + // go-ethereum impl considers just-deleted accounts as "exist" as well return s.HasSelfDestructed(addr) } diff --git a/x/evm/state/check_test.go b/x/evm/state/check_test.go index d0a4bb67c2..be98eb355f 100644 --- a/x/evm/state/check_test.go +++ b/x/evm/state/check_test.go @@ -21,10 +21,15 @@ func TestExist(t *testing.T) { statedb.SetCode(addr2, []byte{3}) require.True(t, statedb.Exist(addr2)) - // destructed + // has balance _, addr3 := testkeeper.MockAddressPair() - statedb.SelfDestruct(addr3) + statedb.AddBalance(addr3, big.NewInt(1000000000000)) require.True(t, statedb.Exist(addr3)) + + // destructed + _, addr4 := testkeeper.MockAddressPair() + statedb.SelfDestruct(addr4) + require.True(t, statedb.Exist(addr4)) } func TestEmpty(t *testing.T) {