diff --git a/app/submodule/eth/eth_api.go b/app/submodule/eth/eth_api.go index 6541bef5cf..be2f11c5ac 100644 --- a/app/submodule/eth/eth_api.go +++ b/app/submodule/eth/eth_api.go @@ -11,6 +11,7 @@ import ( actorstypes "github.com/filecoin-project/go-state-types/actors" "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/go-state-types/builtin/v10/evm" init10 "github.com/filecoin-project/go-state-types/builtin/v10/init" "github.com/filecoin-project/specs-actors/actors/builtin" @@ -181,7 +182,7 @@ func (a *ethAPI) EthGetCode(ctx context.Context, ethAddr types.EthAddress) (type From: from, To: to, Value: big.Zero(), - Method: abi.MethodNum(3), // GetBytecode + Method: builtintypes.MethodsEVM.GetBytecode, Params: nil, GasLimit: constants.BlockGasLimit, GasFeeCap: big.Zero(), @@ -268,7 +269,7 @@ func (a *ethAPI) EthGetStorageAt(ctx context.Context, ethAddr types.EthAddress, From: from, To: to, Value: big.Zero(), - Method: abi.MethodNum(4), // GetStorageAt + Method: builtintypes.MethodsEVM.GetStorageAt, Params: params, GasLimit: constants.BlockGasLimit, GasFeeCap: big.Zero(), @@ -420,8 +421,7 @@ func (a *ethAPI) applyEvmMsg(ctx context.Context, tx types.EthCall) (*types.Invo if tx.To == nil { to = builtintypes.InitActorAddr constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{ - Creator: tx.Data, - Initcode: []byte{}, + Initcode: tx.Data, }) if err != nil { return nil, fmt.Errorf("failed to serialize constructor params: %w", err) @@ -445,14 +445,18 @@ func (a *ethAPI) applyEvmMsg(ctx context.Context, tx types.EthCall) (*types.Invo return nil, fmt.Errorf("cannot get Filecoin address: %w", err) } to = addr - params = tx.Data + var buf bytes.Buffer + if err := cbg.WriteByteArray(&buf, tx.Data); err != nil { + return nil, fmt.Errorf("failed to encode tx input into a cbor byte-string %v", err) + } + params = buf.Bytes() } msg := &types.Message{ From: from, To: to, Value: big.Int(tx.Value), - Method: abi.MethodNum(2), + Method: builtintypes.MethodsEVM.InvokeContract, Params: params, GasLimit: constants.BlockGasLimit, GasFeeCap: big.Zero(), @@ -510,7 +514,7 @@ func (a *ethAPI) EthCall(ctx context.Context, tx types.EthCall, blkParam string) return nil, err } if len(invokeResult.MsgRct.Return) > 0 { - return types.EthBytes(invokeResult.MsgRct.Return), nil + return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return))) } return types.EthBytes{}, nil } @@ -618,9 +622,31 @@ func (a *ethAPI) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup * } toAddr := &toEthAddr - _, err = types.CheckContractCreation(msgLookup) - if err == nil { - toAddr = nil + input := msg.Params + // Check to see if we need to decode as contract deployment. + if toFilAddr == builtintypes.EthereumAddressManagerActorAddr { + switch msg.Method { + case builtintypes.MethodsEAM.Create: + toAddr = nil + var params eam.CreateParams + err = params.UnmarshalCBOR(bytes.NewReader(msg.Params)) + input = params.Initcode + case builtintypes.MethodsEAM.Create2: + toAddr = nil + var params eam.Create2Params + err = params.UnmarshalCBOR(bytes.NewReader(msg.Params)) + input = params.Initcode + } + if err != nil { + return types.EthTx{}, err + } + } + // Otherwise, try to decode as a cbor byte array. + // TODO: Actually check if this is an ethereum call. This code will work for demo purposes, but is not correct. + if toAddr != nil { + if decodedParams, err := cbg.ReadByteArray(bytes.NewReader(msg.Params), uint64(len(msg.Params))); err == nil { + input = decodedParams + } } tx := types.EthTx{ @@ -638,7 +664,7 @@ func (a *ethAPI) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup * V: types.EthBytes{}, R: types.EthBytes{}, S: types.EthBytes{}, - Input: msg.Params, + Input: input, } return tx, nil } diff --git a/venus-shared/types/eth.go b/venus-shared/types/eth.go index 3560338d95..55c7a73568 100644 --- a/venus-shared/types/eth.go +++ b/venus-shared/types/eth.go @@ -11,7 +11,7 @@ import ( "strings" builtintypes "github.com/filecoin-project/go-state-types/builtin" - init8 "github.com/filecoin-project/go-state-types/builtin/v8/init" + "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/ipfs/go-cid" "github.com/multiformats/go-multihash" "github.com/multiformats/go-varint" @@ -212,10 +212,14 @@ func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxRec Logs: []string{}, } - contractAddr, err := CheckContractCreation(lookup) - if err == nil { - receipt.To = nil - receipt.ContractAddress = contractAddr + if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() { + // Create and Create2 return the same things. + var ret eam.CreateReturn + if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil { + return EthTxReceipt{}, fmt.Errorf("failed to parse contract creation result: %w", err) + } + addr := EthAddress(ret.EthAddress) + receipt.ContractAddress = &addr } if lookup.Receipt.ExitCode.IsSuccess() { @@ -235,21 +239,6 @@ func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxRec return receipt, nil } -func CheckContractCreation(lookup *MsgLookup) (*EthAddress, error) { - if lookup.Receipt.ExitCode.IsError() { - return nil, fmt.Errorf("message execution was not successful") - } - var result init8.ExecReturn - ret := bytes.NewReader(lookup.Receipt.Return) - if err := result.UnmarshalCBOR(ret); err == nil { - contractAddr, err := EthAddressFromFilecoinIDAddress(result.IDAddress) - if err == nil { - return &contractAddr, nil - } - } - return nil, fmt.Errorf("not a contract creation tx") -} - const ( ETH_ADDRESS_LENGTH = 20 // nolint ETH_HASH_LENGTH = 32 // nolint