From 6337d594fa00a09eb29aa13a9f04475cc22e1ec1 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 26 Oct 2022 01:24:41 +0100 Subject: [PATCH] fix: evm: use CREATE not CREATE2 for EVM contract deployment (#9553) Also updates the actors to accommodate this change, and fix a bug in looking up addresses for f4 actors. --- api/eth_transactions.go | 11 ++++------- cli/chain.go | 15 +++++---------- node/impl/full/eth.go | 24 +++++++++--------------- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/api/eth_transactions.go b/api/eth_transactions.go index 9709badfb..8514af9d8 100644 --- a/api/eth_transactions.go +++ b/api/eth_transactions.go @@ -132,18 +132,15 @@ func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) { // this is a contract creation to = builtintypes.EthereumAddressManagerActorAddr - var salt [32]byte - binary.BigEndian.PutUint64(salt[:], uint64(tx.Nonce)) - - params2, err := actors.SerializeParams(&eam.Create2Params{ + params2, err := actors.SerializeParams(&eam.CreateParams{ Initcode: tx.Input, - Salt: salt, + Nonce: uint64(tx.Nonce), }) if err != nil { - return nil, fmt.Errorf("failed to serialize Create2 params: %w", err) + return nil, fmt.Errorf("failed to serialize Create params: %w", err) } params = params2 - method = builtintypes.MethodsEAM.Create2 + method = builtintypes.MethodsEAM.Create } else { addr, err := tx.To.ToFilecoinAddress() if err != nil { diff --git a/cli/chain.go b/cli/chain.go index fdf79d464..394000a35 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/base64" - "encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -1673,14 +1672,9 @@ var ChainExecEVMCmd = &cli.Command{ nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist). } - var salt [32]byte - binary.BigEndian.PutUint64(salt[:], nonce) - - // TODO this probably needs to be Create instead of Create2, but Create - // is not callable by any caller - params, err := actors.SerializeParams(&eam.Create2Params{ + params, err := actors.SerializeParams(&eam.CreateParams{ Initcode: contract, - Salt: salt, + Nonce: nonce, }) if err != nil { return fmt.Errorf("failed to serialize Create2 params: %w", err) @@ -1690,10 +1684,11 @@ var ChainExecEVMCmd = &cli.Command{ To: builtintypes.EthereumAddressManagerActorAddr, From: fromAddr, Value: big.Zero(), - Method: builtintypes.MethodsEAM.Create2, + Method: builtintypes.MethodsEAM.Create, Params: params, } + // TODO: this is very racy. It may assign a _different_ nonce than the expected one. afmt.Println("sending message...") smsg, err := api.MpoolPushMessage(ctx, msg, nil) if err != nil { @@ -1711,7 +1706,7 @@ var ChainExecEVMCmd = &cli.Command{ return xerrors.Errorf("actor execution failed") } - var result eam.Create2Return + var result eam.CreateReturn r := bytes.NewReader(wait.Receipt.Return) if err := result.UnmarshalCBOR(r); err != nil { return xerrors.Errorf("error unmarshaling return value: %w", err) diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 3b77c3690..26a3e58af 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -3,7 +3,6 @@ package full import ( "bytes" "context" - "encoding/binary" "fmt" "strconv" @@ -527,20 +526,15 @@ func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx api.EthCall nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist). } - var salt [32]byte - binary.BigEndian.PutUint64(salt[:], nonce) - - // TODO this probably needs to be Create instead of Create2, but Create - // is not callable externally. - params2, err := actors.SerializeParams(&eam.Create2Params{ + params2, err := actors.SerializeParams(&eam.CreateParams{ Initcode: tx.Data, - Salt: salt, + Nonce: nonce, }) if err != nil { - return nil, fmt.Errorf("failed to serialize Create2 params: %w", err) + return nil, fmt.Errorf("failed to serialize Create params: %w", err) } params = params2 - method = builtintypes.MethodsEAM.Create2 + method = builtintypes.MethodsEAM.Create } else { addr, err := tx.To.ToFilecoinAddress() if err != nil { @@ -683,11 +677,11 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti // lookupEthAddress makes its best effort at finding the Ethereum address for a // Filecoin address. It does the following: // -// 1. If the supplied address is an f410 address, we return its payload as the EthAddress. -// 2. Otherwise (f0, f1, f2, f3), we look up the actor on the state tree. If it has a predictable address, we return it if it's f410 address. -// 3. Otherwise, we fall back to returning a masked ID Ethereum address. If the supplied address is an f0 address, we -// use that ID to form the masked ID address. -// 4. Otherwise, we fetch the actor's ID from the state tree and form the masked ID with it. +// 1. If the supplied address is an f410 address, we return its payload as the EthAddress. +// 2. Otherwise (f0, f1, f2, f3), we look up the actor on the state tree. If it has a predictable address, we return it if it's f410 address. +// 3. Otherwise, we fall back to returning a masked ID Ethereum address. If the supplied address is an f0 address, we +// use that ID to form the masked ID address. +// 4. Otherwise, we fetch the actor's ID from the state tree and form the masked ID with it. func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address) (api.EthAddress, error) { // Attempt to convert directly. if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(addr, false); err != nil {