Skip to content

Commit

Permalink
improve error codes
Browse files Browse the repository at this point in the history
  • Loading branch information
Stebalien committed Feb 14, 2024
1 parent b160fb5 commit b5c0de2
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 17 deletions.
12 changes: 12 additions & 0 deletions chain/actors/builtin/evm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
actorstypes "github.com/filecoin-project/go-state-types/actors"
builtin12 "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/manifest"

"github.com/filecoin-project/lotus/chain/actors"
Expand All @@ -16,6 +17,17 @@ import (

var Methods = builtin12.MethodsEVM

const (
ErrReverted exitcode.ExitCode = iota + 33
ErrInvalidInstruction
ErrUndefinedInstruction
ErrStackUnderflow
ErrStackOverflow
ErrIllegalMemoryAccess
ErrBadJumpdest
ErrSelfdestructFailed
)

func Load(store adt.Store, act *types.Actor) (State, error) {
if name, av, ok := actors.GetActorMetaByCode(act.Code); ok {
if name != manifest.EvmKey {
Expand Down
76 changes: 59 additions & 17 deletions node/impl/full/eth_trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package full

import (
"bytes"
"fmt"

"github.com/multiformats/go-multicodec"
cbg "github.com/whyrusleeping/cbor-gen"
Expand All @@ -10,12 +11,13 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/builtin/v12/eam"
"github.com/filecoin-project/go-state-types/builtin/v12/evm"
init_ "github.com/filecoin-project/go-state-types/builtin/v12/init"
eam12 "github.com/filecoin-project/go-state-types/builtin/v12/eam"
evm12 "github.com/filecoin-project/go-state-types/builtin/v12/evm"
init12 "github.com/filecoin-project/go-state-types/builtin/v12/init"
"github.com/filecoin-project/go-state-types/exitcode"

builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/evm"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
Expand Down Expand Up @@ -109,15 +111,55 @@ func traceToAddress(act *types.ActorTrace) ethtypes.EthAddress {
return ethtypes.EthAddressFromActorID(act.Id)
}

// traceIsEVMOrEAM returns true if the trace is a call to an EVM or EAM actor.
func traceIsEVMOrEAM(et *types.ExecutionTrace) bool {
if et.InvokedActor == nil {
return false
}
return builtinactors.IsEvmActor(et.InvokedActor.State.Code) ||
et.InvokedActor.Id != abi.ActorID(builtin.EthereumAddressManagerActorID)
}

func traceErrMsg(et *types.ExecutionTrace) string {
switch et.MsgRct.ExitCode {
case 0: // success
code := et.MsgRct.ExitCode

if code.IsSuccess() {
return ""
case 33: // reverted
return "Reverted"
default:
return et.MsgRct.ExitCode.Error()
}

// EVM tools often expect this literal string.
if code == exitcode.SysErrOutOfGas {
return "out of gas"
}

// indicate when we have a "system" error.
if code < exitcode.FirstActorErrorCode {
return fmt.Sprintf("vm error: %s", code)
}

// handle special exit codes from the EVM/EAM.
if traceIsEVMOrEAM(et) {
switch code {
case evm.ErrReverted:
return "Reverted" // capitalized for compatibility
case evm.ErrInvalidInstruction:
return "invalid instruction"
case evm.ErrUndefinedInstruction:
return "undefined instruction"
case evm.ErrStackUnderflow:
return "stack underflow"
case evm.ErrStackOverflow:
return "stack overflow"
case evm.ErrIllegalMemoryAccess:
return "illegal memory access"
case evm.ErrBadJumpdest:
return "invalid jump destination"
case evm.ErrSelfdestructFailed:
return "self destruct failed"
}
}
// everything else...
return fmt.Sprintf("actor error: %s", code.Error())
}

// buildTraces recursively builds the traces for a given ExecutionTrace by walking the subcalls
Expand Down Expand Up @@ -338,7 +380,7 @@ func traceNativeCreate(env *environment, addr []int, et *types.ExecutionTrace) (
output = []byte{0xFE}

// Extract the address of the created actor from the return value.
initReturn, err := decodeReturn[init_.ExecReturn](&et.MsgRct)
initReturn, err := decodeReturn[init12.ExecReturn](&et.MsgRct)
if err != nil {
return nil, nil, xerrors.Errorf("failed to decode init params after a successful Init.Exec call: %w", err)
}
Expand Down Expand Up @@ -372,23 +414,23 @@ func traceNativeCreate(env *environment, addr []int, et *types.ExecutionTrace) (
}

// Assert that these are all identical so we can simplify the below code and decode once.
var _ *eam.Return = (*eam.Return)((*eam.CreateReturn)(nil))
var _ *eam.Return = (*eam.Return)((*eam.Create2Return)(nil))
var _ *eam.Return = (*eam.Return)((*eam.CreateExternalReturn)(nil))
var _ *eam12.Return = (*eam12.Return)((*eam12.CreateReturn)(nil))
var _ *eam12.Return = (*eam12.Return)((*eam12.Create2Return)(nil))
var _ *eam12.Return = (*eam12.Return)((*eam12.CreateExternalReturn)(nil))

// Decode the parameters and return value of an EVM smart contract creation through the EAM. This
// should only be called with an ExecutionTrace for a Create, Create2, or CreateExternal method
// invocation on the EAM.
func decodeCreateViaEAM(et *types.ExecutionTrace) (initcode []byte, addr *ethtypes.EthAddress, err error) {
switch et.Msg.Method {
case builtin.MethodsEAM.Create:
params, err := decodeParams[eam.CreateParams](&et.Msg)
params, err := decodeParams[eam12.CreateParams](&et.Msg)
if err != nil {
return nil, nil, err
}
initcode = params.Initcode
case builtin.MethodsEAM.Create2:
params, err := decodeParams[eam.Create2Params](&et.Msg)
params, err := decodeParams[eam12.Create2Params](&et.Msg)
if err != nil {
return nil, nil, err
}
Expand All @@ -402,7 +444,7 @@ func decodeCreateViaEAM(et *types.ExecutionTrace) (initcode []byte, addr *ethtyp
default:
return nil, nil, xerrors.Errorf("unexpected CREATE method %d", et.Msg.Method)
}
ret, err := decodeReturn[eam.CreateReturn](&et.MsgRct)
ret, err := decodeReturn[eam12.CreateReturn](&et.MsgRct)
if err != nil {
return nil, (*ethtypes.EthAddress)(&ret.EthAddress), err
}
Expand Down Expand Up @@ -529,7 +571,7 @@ func traceEVMPrivate(env *environment, addr []int, et *types.ExecutionTrace) (*e
return nil, nil, xerrors.Errorf("delegate-call not from & to self: %s != %s", env.caller, to)
}

dp, err := decodeParams[evm.DelegateCallParams](&et.Msg)
dp, err := decodeParams[evm12.DelegateCallParams](&et.Msg)
if err != nil {
return nil, nil, xerrors.Errorf("failed to decode delegate-call params: %w", err)
}
Expand Down

0 comments on commit b5c0de2

Please sign in to comment.