Skip to content

Commit

Permalink
fix: eth: decode as actor creation iff "to" is the EAM actor
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 committed Dec 13, 2023
1 parent c912f3b commit a35af09
Showing 1 changed file with 22 additions and 28 deletions.
50 changes: 22 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,23 @@ 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 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 a35af09

Please sign in to comment.