fix: eth: decode as actor creation iff "to" is the EAM (#11520)

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.
This commit is contained in:
Steven Allen 2023-12-14 10:12:54 -08:00 committed by GitHub
parent d75d7c78de
commit 17f6f4caf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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"
@ -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.
@ -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),
@ -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) {