Skip to content

Commit

Permalink
fix: eth: decode as actor creation iff "to" is the EAM (#11520)
Browse files Browse the repository at this point in the history
Previously, we weren't checking the "to" address. I've also re-ordered
the operations in this function to make it easier to reason about them.
It'll have a slight runtime cost (we _always_ ABI-encode the parameters,
then throw away the result if it turns out we're actually dealing with
an Ethereum transaction), but it's _much_ simpler.
  • Loading branch information
Stebalien authored and rjan90 committed Dec 15, 2023
1 parent 502a9e8 commit d6a198a
Showing 1 changed file with 24 additions and 28 deletions.
52 changes: 24 additions & 28 deletions node/impl/full/eth_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
Expand Down Expand Up @@ -524,9 +525,6 @@ func ethTxFromNativeMessage(msg *types.Message, st *state.StateTree) (ethtypes.E
}
to = revertedEthAddress
}
toPtr := &to

// Finally, convert the input parameters to "solidity ABI".

// For empty, we use "0" as the codec. Otherwise, we use CBOR for message
// parameters.
Expand All @@ -535,31 +533,11 @@ func ethTxFromNativeMessage(msg *types.Message, st *state.StateTree) (ethtypes.E
codec = uint64(multicodec.Cbor)
}

// We try to decode the input as an EVM method invocation and/or a contract creation. If
// that fails, we encode the "native" parameters as Solidity ABI.
var input []byte
switch msg.Method {
case builtintypes.MethodsEVM.InvokeContract, builtintypes.MethodsEAM.CreateExternal:
inp, err := decodePayload(msg.Params, codec)
if err == nil {
// If this is a valid "create external", unset the "to" address.
if msg.Method == builtintypes.MethodsEAM.CreateExternal {
toPtr = nil
}
input = []byte(inp)
break
}
// Yeah, we're going to ignore errors here because the user can send whatever they
// want and may send garbage.
fallthrough
default:
input = encodeFilecoinParamsAsABI(msg.Method, codec, msg.Params)
}

return ethtypes.EthTx{
To: toPtr,
// We decode as a native call first.
ethTx := ethtypes.EthTx{
To: &to,
From: from,
Input: input,
Input: encodeFilecoinParamsAsABI(msg.Method, codec, msg.Params),
Nonce: ethtypes.EthUint64(msg.Nonce),
ChainID: ethtypes.EthUint64(build.Eip155ChainId),
Value: ethtypes.EthBigInt(msg.Value),
Expand All @@ -568,7 +546,25 @@ func ethTxFromNativeMessage(msg *types.Message, st *state.StateTree) (ethtypes.E
MaxFeePerGas: ethtypes.EthBigInt(msg.GasFeeCap),
MaxPriorityFeePerGas: ethtypes.EthBigInt(msg.GasPremium),
AccessList: []ethtypes.EthHash{},
}, nil
}

// Then we try to see if it's "special". If we fail, we ignore the error and keep treating
// it as a native message. Unfortunately, the user is free to send garbage that may not
// properly decode.
if msg.Method == builtintypes.MethodsEVM.InvokeContract {
// try to decode it as a contract invocation first.
if inp, err := decodePayload(msg.Params, codec); err == nil {
ethTx.Input = []byte(inp)
}
} else if msg.To == builtin.EthereumAddressManagerActorAddr && msg.Method == builtintypes.MethodsEAM.CreateExternal {
// Then, try to decode it as a contract deployment from an EOA.
if inp, err := decodePayload(msg.Params, codec); err == nil {
ethTx.Input = []byte(inp)
ethTx.To = nil
}
}

return ethTx, nil
}

func getSignedMessage(ctx context.Context, cs *store.ChainStore, msgCid cid.Cid) (*types.SignedMessage, error) {
Expand Down

0 comments on commit d6a198a

Please sign in to comment.