diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index 9c0e3f9979e..f4250839843 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -23,7 +23,10 @@ import ( "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build/buildconstants" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/must" ) @@ -247,6 +250,64 @@ type EthCall struct { Data EthBytes `json:"data"` } +func (c *EthCall) ToFilecoinMessage() (*types.Message, error) { + var from address.Address + if c.From == nil || *c.From == (EthAddress{}) { + // Send from the filecoin "system" address. + var err error + from, err = (EthAddress{}).ToFilecoinAddress() + if err != nil { + return nil, fmt.Errorf("failed to construct the ethereum system address: %w", err) + } + } else { + // The from address must be translatable to an f4 address. + var err error + from, err = c.From.ToFilecoinAddress() + if err != nil { + return nil, fmt.Errorf("failed to translate sender address (%s): %w", c.From.String(), err) + } + if p := from.Protocol(); p != address.Delegated { + return nil, fmt.Errorf("expected a class 4 address, got: %d: %w", p, err) + } + } + + var params []byte + if len(c.Data) > 0 { + initcode := abi.CborBytes(c.Data) + params2, err := actors.SerializeParams(&initcode) + if err != nil { + return nil, fmt.Errorf("failed to serialize params: %w", err) + } + params = params2 + } + + var to address.Address + var method abi.MethodNum + if c.To == nil { + // this is a contract creation + to = builtintypes.EthereumAddressManagerActorAddr + method = builtintypes.MethodsEAM.CreateExternal + } else { + addr, err := c.To.ToFilecoinAddress() + if err != nil { + return nil, xerrors.Errorf("cannot get Filecoin address: %w", err) + } + to = addr + method = builtintypes.MethodsEVM.InvokeContract + } + + return &types.Message{ + From: from, + To: to, + Value: big.Int(c.Value), + Method: method, + Params: params, + GasLimit: build.BlockGasLimit, + GasFeeCap: big.Zero(), + GasPremium: big.Zero(), + }, nil +} + func (c *EthCall) UnmarshalJSON(b []byte) error { type EthCallRaw EthCall // Avoid a recursive call. type EthCallDecode struct { diff --git a/node/impl/eth/gas.go b/node/impl/eth/gas.go index db0c848f8b9..135edf7fa7b 100644 --- a/node/impl/eth/gas.go +++ b/node/impl/eth/gas.go @@ -186,7 +186,7 @@ func (e *ethGas) EthEstimateGas(ctx context.Context, p jsonrpc.RawParams) (ethty return ethtypes.EthUint64(0), xerrors.Errorf("decoding params: %w", err) } - msg, err := ethCallToFilecoinMessage(ctx, params.Tx) + msg, err := params.Tx.ToFilecoinMessage() if err != nil { return ethtypes.EthUint64(0), err } @@ -237,7 +237,7 @@ func (e *ethGas) EthEstimateGas(ctx context.Context, p jsonrpc.RawParams) (ethty } func (e *ethGas) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) { - msg, err := ethCallToFilecoinMessage(ctx, tx) + msg, err := tx.ToFilecoinMessage() if err != nil { return nil, xerrors.Errorf("failed to convert ethcall to filecoin message: %w", err) } diff --git a/node/impl/eth/utils.go b/node/impl/eth/utils.go index 165e0aef8b9..21b64b218cb 100644 --- a/node/impl/eth/utils.go +++ b/node/impl/eth/utils.go @@ -21,7 +21,6 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build/buildconstants" - "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/state" @@ -99,64 +98,6 @@ func getTipsetByEthBlockNumberOrHash(ctx context.Context, cp ChainStore, blkPara return nil, xerrors.New("invalid block param") } -func ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.EthCall) (*types.Message, error) { - var from address.Address - if tx.From == nil || *tx.From == (ethtypes.EthAddress{}) { - // Send from the filecoin "system" address. - var err error - from, err = (ethtypes.EthAddress{}).ToFilecoinAddress() - if err != nil { - return nil, xerrors.Errorf("failed to construct the ethereum system address: %w", err) - } - } else { - // The from address must be translatable to an f4 address. - var err error - from, err = tx.From.ToFilecoinAddress() - if err != nil { - return nil, xerrors.Errorf("failed to translate sender address (%s): %w", tx.From.String(), err) - } - if p := from.Protocol(); p != address.Delegated { - return nil, xerrors.Errorf("expected a class 4 address, got: %d: %w", p, err) - } - } - - var params []byte - if len(tx.Data) > 0 { - initcode := abi.CborBytes(tx.Data) - params2, err := actors.SerializeParams(&initcode) - if err != nil { - return nil, xerrors.Errorf("failed to serialize params: %w", err) - } - params = params2 - } - - var to address.Address - var method abi.MethodNum - if tx.To == nil { - // this is a contract creation - to = builtintypes.EthereumAddressManagerActorAddr - method = builtintypes.MethodsEAM.CreateExternal - } else { - addr, err := tx.To.ToFilecoinAddress() - if err != nil { - return nil, xerrors.Errorf("cannot get Filecoin address: %w", err) - } - to = addr - method = builtintypes.MethodsEVM.InvokeContract - } - - return &types.Message{ - From: from, - To: to, - Value: big.Int(tx.Value), - Method: method, - Params: params, - GasLimit: buildconstants.BlockGasLimit, - GasFeeCap: big.Zero(), - GasPremium: big.Zero(), - }, nil -} - func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool, cp ChainStore, sp StateManager) (ethtypes.EthBlock, error) { parentKeyCid, err := ts.Parents().Cid() if err != nil {