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.
This commit is contained in:
Steven Allen 2022-10-26 01:24:41 +01:00 committed by vyzo
parent dc5fc9ded4
commit 6337d594fa
3 changed files with 18 additions and 32 deletions

View File

@ -132,18 +132,15 @@ func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) {
// this is a contract creation // this is a contract creation
to = builtintypes.EthereumAddressManagerActorAddr to = builtintypes.EthereumAddressManagerActorAddr
var salt [32]byte params2, err := actors.SerializeParams(&eam.CreateParams{
binary.BigEndian.PutUint64(salt[:], uint64(tx.Nonce))
params2, err := actors.SerializeParams(&eam.Create2Params{
Initcode: tx.Input, Initcode: tx.Input,
Salt: salt, Nonce: uint64(tx.Nonce),
}) })
if err != nil { 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 params = params2
method = builtintypes.MethodsEAM.Create2 method = builtintypes.MethodsEAM.Create
} else { } else {
addr, err := tx.To.ToFilecoinAddress() addr, err := tx.To.ToFilecoinAddress()
if err != nil { if err != nil {

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -1673,14 +1672,9 @@ var ChainExecEVMCmd = &cli.Command{
nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist). nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist).
} }
var salt [32]byte params, err := actors.SerializeParams(&eam.CreateParams{
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{
Initcode: contract, Initcode: contract,
Salt: salt, Nonce: nonce,
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to serialize Create2 params: %w", err) return fmt.Errorf("failed to serialize Create2 params: %w", err)
@ -1690,10 +1684,11 @@ var ChainExecEVMCmd = &cli.Command{
To: builtintypes.EthereumAddressManagerActorAddr, To: builtintypes.EthereumAddressManagerActorAddr,
From: fromAddr, From: fromAddr,
Value: big.Zero(), Value: big.Zero(),
Method: builtintypes.MethodsEAM.Create2, Method: builtintypes.MethodsEAM.Create,
Params: params, Params: params,
} }
// TODO: this is very racy. It may assign a _different_ nonce than the expected one.
afmt.Println("sending message...") afmt.Println("sending message...")
smsg, err := api.MpoolPushMessage(ctx, msg, nil) smsg, err := api.MpoolPushMessage(ctx, msg, nil)
if err != nil { if err != nil {
@ -1711,7 +1706,7 @@ var ChainExecEVMCmd = &cli.Command{
return xerrors.Errorf("actor execution failed") return xerrors.Errorf("actor execution failed")
} }
var result eam.Create2Return var result eam.CreateReturn
r := bytes.NewReader(wait.Receipt.Return) r := bytes.NewReader(wait.Receipt.Return)
if err := result.UnmarshalCBOR(r); err != nil { if err := result.UnmarshalCBOR(r); err != nil {
return xerrors.Errorf("error unmarshaling return value: %w", err) return xerrors.Errorf("error unmarshaling return value: %w", err)

View File

@ -3,7 +3,6 @@ package full
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/binary"
"fmt" "fmt"
"strconv" "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). nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist).
} }
var salt [32]byte params2, err := actors.SerializeParams(&eam.CreateParams{
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{
Initcode: tx.Data, Initcode: tx.Data,
Salt: salt, Nonce: nonce,
}) })
if err != nil { 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 params = params2
method = builtintypes.MethodsEAM.Create2 method = builtintypes.MethodsEAM.Create
} else { } else {
addr, err := tx.To.ToFilecoinAddress() addr, err := tx.To.ToFilecoinAddress()
if err != nil { 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 // lookupEthAddress makes its best effort at finding the Ethereum address for a
// Filecoin address. It does the following: // Filecoin address. It does the following:
// //
// 1. If the supplied address is an f410 address, we return its payload as the EthAddress. // 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. // 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 // 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. // 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. // 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) { func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address) (api.EthAddress, error) {
// Attempt to convert directly. // Attempt to convert directly.
if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(addr, false); err != nil { if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(addr, false); err != nil {