diff --git a/CHANGELOG.md b/CHANGELOG.md index d578b2b1aec..3b3583336b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Lotus changelog # UNRELEASED -Add `EthGetBlockReceipts` RPC method to retrieve transaction receipts for a specified block. This method allows users to obtain the receipts of all transactions included in a given Ethereum block. ([filecoin-project/lotus#12478](https://github.com/filecoin-project/lotus/pull/12478)) +Add `EthGetBlockReceipts` RPC method to retrieve transaction receipts for a specified block. This method allows users to obtain Ethereum format receipts of all transactions included in a given tipset as specified by its Ethereum block equivalent. ([filecoin-project/lotus#12478](https://github.com/filecoin-project/lotus/pull/12478)) ## ☢️ Upgrade Warnings ☢️ diff --git a/chain/events/filter/event.go b/chain/events/filter/event.go index 8888daff486..fa17d235ea9 100644 --- a/chain/events/filter/event.go +++ b/chain/events/filter/event.go @@ -16,7 +16,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" cstore "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -309,9 +308,10 @@ type EventFilterManager struct { AddressResolver func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool) MaxFilterResults int EventIndex *EventIndex - mu sync.Mutex // guards mutations to filters - filters map[types.FilterID]EventFilter - currentHeight abi.ChainEpoch + + mu sync.Mutex // guards mutations to filters + filters map[types.FilterID]EventFilter + currentHeight abi.ChainEpoch } func (m *EventFilterManager) Apply(ctx context.Context, from, to *types.TipSet) error { @@ -438,43 +438,37 @@ func (m *EventFilterManager) loadExecutedMessages(ctx context.Context, msgTs, rc return nil, xerrors.Errorf("read messages: %w", err) } - store := m.ChainStore.ActorStore(ctx) + st := m.ChainStore.ActorStore(ctx) - arr, err := blockadt.AsArray(store, rctTs.Blocks()[0].ParentMessageReceipts) + arr, err := blockadt.AsArray(st, rctTs.Blocks()[0].ParentMessageReceipts) if err != nil { return nil, xerrors.Errorf("load receipts amt: %w", err) } - receipts := make([]types.MessageReceipt, arr.Length()) - for i := 0; i < len(receipts); i++ { - found, err := arr.Get(uint64(i), &receipts[i]) - if err != nil { - return nil, xerrors.Errorf("load receipt: %w", err) - } - if !found { - return nil, xerrors.Errorf("receipt %d not found", i) - } - } - - return LoadExecutedMessages(ctx, store, msgs, receipts) -} - -func LoadExecutedMessages(ctx context.Context, store adt.Store, msgs []types.ChainMsg, receipts []types.MessageReceipt) ([]executedMessage, error) { - if len(msgs) != len(receipts) { - return nil, xerrors.Errorf("mismatching message and receipt counts (%d msgs, %d rcts)", len(msgs), len(receipts)) + if uint64(len(msgs)) != arr.Length() { + return nil, xerrors.Errorf("mismatching message and receipt counts (%d msgs, %d rcts)", len(msgs), arr.Length()) } ems := make([]executedMessage, len(msgs)) for i := 0; i < len(msgs); i++ { ems[i].msg = msgs[i] - ems[i].rct = &receipts[i] - if receipts[i].EventsRoot == nil { + var rct types.MessageReceipt + found, err := arr.Get(uint64(i), &rct) + if err != nil { + return nil, xerrors.Errorf("load receipt: %w", err) + } + if !found { + return nil, xerrors.Errorf("receipt %d not found", i) + } + ems[i].rct = &rct + + if rct.EventsRoot == nil { continue } - evtArr, err := amt4.LoadAMT(ctx, store, *receipts[i].EventsRoot, amt4.UseTreeBitWidth(types.EventAMTBitwidth)) + evtArr, err := amt4.LoadAMT(ctx, st, *rct.EventsRoot, amt4.UseTreeBitWidth(types.EventAMTBitwidth)) if err != nil { return nil, xerrors.Errorf("load events amt: %w", err) } @@ -488,13 +482,16 @@ func LoadExecutedMessages(ctx context.Context, store adt.Store, msgs []types.Cha if err := evt.UnmarshalCBOR(bytes.NewReader(deferred.Raw)); err != nil { return err } + cpy := evt - ems[i].evs[int(u)] = &cpy + ems[i].evs[int(u)] = &cpy //nolint:scopelint return nil }) + if err != nil { return nil, xerrors.Errorf("read events: %w", err) } + } return ems, nil diff --git a/gateway/proxy_eth.go b/gateway/proxy_eth.go index cd9d6ad1bd4..e24f7a98378 100644 --- a/gateway/proxy_eth.go +++ b/gateway/proxy_eth.go @@ -683,6 +683,26 @@ func (gw *Node) EthTraceFilter(ctx context.Context, filter ethtypes.EthTraceFilt return gw.target.EthTraceFilter(ctx, filter) } +func (gw *Node) EthGetBlockReceipts(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash) ([]*api.EthTxReceipt, error) { + return gw.EthGetBlockReceiptsLimited(ctx, blkParam, api.LookbackNoLimit) +} + +func (gw *Node) EthGetBlockReceiptsLimited(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*api.EthTxReceipt, error) { + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return nil, err + } + + if limit == api.LookbackNoLimit { + limit = gw.maxMessageLookbackEpochs + } + + if gw.maxMessageLookbackEpochs != api.LookbackNoLimit && limit > gw.maxMessageLookbackEpochs { + limit = gw.maxMessageLookbackEpochs + } + + return gw.target.EthGetBlockReceiptsLimited(ctx, blkParam, limit) +} + func (gw *Node) addUserFilterLimited( ctx context.Context, callName string, @@ -762,22 +782,3 @@ func newStatefulCallTracker() *statefulCallTracker { userSubscriptions: make(map[ethtypes.EthSubscriptionID]cleanup), } } -func (gw *Node) EthGetBlockReceipts(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash) ([]*api.EthTxReceipt, error) { - return gw.EthGetBlockReceiptsLimited(ctx, blkParam, api.LookbackNoLimit) -} - -func (gw *Node) EthGetBlockReceiptsLimited(ctx context.Context, blkParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*api.EthTxReceipt, error) { - if err := gw.limit(ctx, stateRateLimitTokens); err != nil { - return nil, err - } - - if limit == api.LookbackNoLimit { - limit = gw.maxMessageLookbackEpochs - } - - if gw.maxMessageLookbackEpochs != api.LookbackNoLimit && limit > gw.maxMessageLookbackEpochs { - limit = gw.maxMessageLookbackEpochs - } - - return gw.target.EthGetBlockReceiptsLimited(ctx, blkParam, limit) -} diff --git a/itests/eth_deploy_test.go b/itests/eth_deploy_test.go index c1fb34805c4..6f5e67af3cf 100644 --- a/itests/eth_deploy_test.go +++ b/itests/eth_deploy_test.go @@ -144,6 +144,24 @@ func TestDeployment(t *testing.T) { receipts, err := client.EthGetBlockReceipts(ctx, ethtypes.EthBlockNumberOrHash{BlockHash: &receipt.BlockHash}) require.NoError(t, err) require.NotNil(t, receipts) + require.Greater(t, len(receipts), 0) + var matchingReceipt *api.EthTxReceipt + for _, r := range receipts { + if r.TransactionHash == receipt.TransactionHash { + require.Nil(t, matchingReceipt, "Multiple matching receipts found") + matchingReceipt = r + } + } + require.NotNil(t, matchingReceipt, "No matching receipt found") + + require.NotNil(t, receipt.ContractAddress) + require.NotNil(t, matchingReceipt.ContractAddress) + require.Equal(t, *receipt.ContractAddress, *matchingReceipt.ContractAddress) + originalReceiptContractAddress := receipt.ContractAddress + receipt.ContractAddress = nil + matchingReceipt.ContractAddress = nil + require.Equal(t, receipt, matchingReceipt) + receipt.ContractAddress = originalReceiptContractAddress // logs must be an empty array, not a nil value, to avoid tooling compatibility issues require.Empty(t, receipt.Logs) diff --git a/itests/eth_filter_test.go b/itests/eth_filter_test.go index cc1a0c18543..16991069c9c 100644 --- a/itests/eth_filter_test.go +++ b/itests/eth_filter_test.go @@ -517,7 +517,6 @@ func TestEthGetLogsBasic(t *testing.T) { require.NotNil(rct) require.Len(rct.Logs, 1) - var rctLogs []*ethtypes.EthLog for _, rctLog := range rct.Logs { addr := &rctLog diff --git a/itests/fevm_test.go b/itests/fevm_test.go index 7ad9e1585d6..78bac325d20 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -1148,17 +1148,19 @@ func TestEthGetBlockReceipts(t *testing.T) { require.Len(t, blockReceipts, 3) // Ensure there are three receipts expectedLogCounts := []int{4, 3, 3} + for i, receipt := range blockReceipts { require.Equal(t, &contractAddr, receipt.To) require.Equal(t, ethtypes.EthUint64(1), receipt.Status) require.NotEmpty(t, receipt.BlockHash, "Block hash should not be empty") require.Equal(t, expectedLogCounts[i], len(receipt.Logs), fmt.Sprintf("Transaction %d should have %d event logs", i+1, expectedLogCounts[i])) - } + if i > 0 { + require.Equal(t, blockReceipts[i-1].BlockHash, receipt.BlockHash, "All receipts should have the same block hash") + } - // Verify that all receipts have the same block hash - firstBlockHash := blockReceipts[0].BlockHash - for _, receipt := range blockReceipts { - require.Equal(t, firstBlockHash, receipt.BlockHash, "All receipts should have the same block hash") + txReceipt, err := client.EthGetTransactionReceipt(ctx, receipt.TransactionHash) + require.NoError(t, err) + require.Equal(t, txReceipt, receipt) } } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 8228997c8cb..2eec8b8746e 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -3,8 +3,6 @@ package full import ( "bytes" "context" - "crypto/sha256" - "encoding/binary" "errors" "fmt" "os" @@ -135,7 +133,6 @@ var ( // "Latest executed epoch" refers to the tipset that this node currently // accepts as the best parent tipset, based on the blocks it is accumulating // within the HEAD tipset. - type EthModule struct { Chain *store.ChainStore Mpool *messagepool.MessagePool @@ -530,11 +527,20 @@ func (a *EthModule) EthGetTransactionReceiptLimited(ctx context.Context, txHash return nil, xerrors.Errorf("failed to convert %s into an Eth Txn: %w", txHash, err) } - receipt, err := newEthTxReceipt(ctx, tx, &api.MsgLookup{ - Receipt: msgLookup.Receipt, - TipSet: msgLookup.TipSet, - Height: msgLookup.Height, - }, a.ChainAPI, a.StateAPI, a.EthEventHandler) + ts, err := a.Chain.GetTipSetFromKey(ctx, msgLookup.TipSet) + if err != nil { + return nil, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", msgLookup.TipSet, err) + } + + // The tx is located in the parent tipset + parentTs, err := a.Chain.LoadTipSet(ctx, ts.Parents()) + if err != nil { + return nil, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", ts.Parents(), err) + } + + baseFee := parentTs.Blocks()[0].ParentBaseFee + + receipt, err := newEthTxReceipt(ctx, tx, baseFee, msgLookup.Receipt, a.EthEventHandler) if err != nil { return nil, xerrors.Errorf("failed to create Eth receipt: %w", err) } @@ -550,6 +556,63 @@ func (a *EthAPI) EthGetTransactionByBlockNumberAndIndex(context.Context, ethtype return ethtypes.EthTx{}, ErrUnsupported } +func (a *EthModule) EthGetBlockReceipts(ctx context.Context, blockParam ethtypes.EthBlockNumberOrHash) ([]*api.EthTxReceipt, error) { + return a.EthGetBlockReceiptsLimited(ctx, blockParam, api.LookbackNoLimit) +} + +func (a *EthModule) EthGetBlockReceiptsLimited(ctx context.Context, blockParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*api.EthTxReceipt, error) { + ts, err := getTipsetByEthBlockNumberOrHash(ctx, a.Chain, blockParam) + if err != nil { + return nil, xerrors.Errorf("failed to get tipset: %w", err) + } + + tsCid, err := ts.Key().Cid() + if err != nil { + return nil, xerrors.Errorf("failed to get tipset key cid: %w", err) + } + + blkHash, err := ethtypes.EthHashFromCid(tsCid) + if err != nil { + return nil, xerrors.Errorf("failed to parse eth hash from cid: %w", err) + } + + // Execute the tipset to get the receipts, messages, and events + st, msgs, receipts, err := executeTipset(ctx, ts, a.Chain, a.StateAPI) + if err != nil { + return nil, xerrors.Errorf("failed to execute tipset: %w", err) + } + + // Load the state tree + stateTree, err := a.StateManager.StateTree(st) + if err != nil { + return nil, xerrors.Errorf("failed to load state tree: %w", err) + } + + baseFee := ts.Blocks()[0].ParentBaseFee + + ethReceipts := make([]*api.EthTxReceipt, 0, len(msgs)) + for i, msg := range msgs { + msg := msg + + tx, err := newEthTx(ctx, a.Chain, stateTree, ts.Height(), tsCid, msg.Cid(), i) + if err != nil { + return nil, xerrors.Errorf("failed to create EthTx: %w", err) + } + + receipt, err := newEthTxReceipt(ctx, tx, baseFee, receipts[i], a.EthEventHandler) + if err != nil { + return nil, xerrors.Errorf("failed to create Eth receipt: %w", err) + } + + // Set the correct Ethereum block hash + receipt.BlockHash = blkHash + + ethReceipts = append(ethReceipts, &receipt) + } + + return ethReceipts, nil +} + // EthGetCode returns string value of the compiled bytecode func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) { to, err := ethAddr.ToFilecoinAddress() @@ -1643,7 +1706,7 @@ func (e *EthEventHandler) ethGetEventsForFilter(ctx context.Context, filterSpec } // Create a temporary filter - f, err := e.EventFilterManager.Install(ctx, pf.minHeight, pf.maxHeight, pf.tipsetCid, pf.addresses, pf.keys, true) + f, err := e.EventFilterManager.Install(ctx, pf.minHeight, pf.maxHeight, pf.tipsetCid, pf.addresses, pf.keys, false) if err != nil { return nil, xerrors.Errorf("failed to install event filter: %w", err) } @@ -2144,116 +2207,3 @@ func (g gasRewardSorter) Swap(i, j int) { func (g gasRewardSorter) Less(i, j int) bool { return g[i].premium.Int.Cmp(g[j].premium.Int) == -1 } - -func (a *EthModule) EthGetBlockReceipts(ctx context.Context, blockParam ethtypes.EthBlockNumberOrHash) ([]*api.EthTxReceipt, error) { - return a.EthGetBlockReceiptsLimited(ctx, blockParam, api.LookbackNoLimit) -} - -func (a *EthModule) EthGetBlockReceiptsLimited(ctx context.Context, blockParam ethtypes.EthBlockNumberOrHash, limit abi.ChainEpoch) ([]*api.EthTxReceipt, error) { - ts, err := getTipsetByEthBlockNumberOrHash(ctx, a.Chain, blockParam) - if err != nil { - return nil, xerrors.Errorf("failed to get tipset: %w", err) - } - - // Calculate the correct Ethereum block hash - ethBlockHash, err := ethBlockHashFromTipSet(ts) - if err != nil { - return nil, xerrors.Errorf("failed to calculate Ethereum block hash: %w", err) - } - - // Execute the tipset to get the receipts, messages, and events - st, msgs, receipts, err := executeTipset(ctx, ts, a.Chain, a.StateAPI) - if err != nil { - return nil, xerrors.Errorf("failed to execute tipset: %w", err) - } - - // Load the state tree - stateTree, err := a.StateManager.StateTree(st) - if err != nil { - return nil, xerrors.Errorf("failed to load state tree: %w", err) - } - - // Get the parent tipset CID - parentTsCid, err := ts.Parents().Cid() - if err != nil { - return nil, xerrors.Errorf("failed to get parent tipset cid: %w", err) - } - - // Use the LoadExecutedMessages function - execStore := a.Chain.ActorStore(ctx) - executedMsgs, err := filter.LoadExecutedMessages(ctx, execStore, msgs, receipts) - if err != nil { - return nil, xerrors.Errorf("failed to load executed messages: %w", err) - } - - // Convert executed messages to events - events := make([]*filter.CollectedEvent, 0, len(executedMsgs)) - for _, em := range executedMsgs { - for _, ev := range em.Events() { - addr, err := address.NewIDAddress(uint64(ev.Emitter)) - if err != nil { - return nil, xerrors.Errorf("failed to create ID address: %w", err) - } - events = append(events, &filter.CollectedEvent{ - Entries: ev.Entries, - EmitterAddr: addr, - Height: ts.Height(), - TipSetKey: ts.Key(), - MsgCid: em.Message().Cid(), - }) - } - } - - // Convert raw events to Ethereum logs - logs, err := ethFilterLogsFromEvents(ctx, events, a.StateAPI) - if err != nil { - return nil, xerrors.Errorf("failed to convert events to logs: %w", err) - } - - ethReceipts := make([]*api.EthTxReceipt, 0, len(msgs)) - for i, msg := range msgs { - tx, err := newEthTx(ctx, a.Chain, stateTree, ts.Height(), parentTsCid, msg.Cid(), i) - if err != nil { - return nil, xerrors.Errorf("failed to create Eth transaction: %w", err) - } - - receipt, err := newEthTxReceipt(ctx, tx, &api.MsgLookup{ - Receipt: receipts[i], - TipSet: ts.Key(), - Height: ts.Height(), - }, a.ChainAPI, a.StateAPI, a.EthEventHandler) - if err != nil { - return nil, xerrors.Errorf("failed to create Eth receipt: %w", err) - } - - // Set the correct Ethereum block hash - receipt.BlockHash = ethBlockHash - - // Filter logs by transaction hash - receipt.Logs = filterLogsByTxHash(logs, receipt.TransactionHash) - - ethReceipts = append(ethReceipts, &receipt) - } - - return ethReceipts, nil -} - -// Helper function to filter logs by transaction hash -func filterLogsByTxHash(logs []ethtypes.EthLog, txHash ethtypes.EthHash) []ethtypes.EthLog { - var filteredLogs []ethtypes.EthLog - for _, log := range logs { - if log.TransactionHash == txHash { - filteredLogs = append(filteredLogs, log) - } - } - return filteredLogs -} - -func ethBlockHashFromTipSet(ts *types.TipSet) (ethtypes.EthHash, error) { - tsKey := ts.Key() - heightBytes := make([]byte, 8) - binary.BigEndian.PutUint64(heightBytes, uint64(ts.Height())) - - hash := sha256.Sum256(append(tsKey.Bytes(), heightBytes...)) - return ethtypes.EthHash(hash), nil -} diff --git a/node/impl/full/eth_utils.go b/node/impl/full/eth_utils.go index 957b1bea012..6001eeeff75 100644 --- a/node/impl/full/eth_utils.go +++ b/node/impl/full/eth_utils.go @@ -295,7 +295,7 @@ func executeTipset(ctx context.Context, ts *types.TipSet, cs *store.ChainStore, stRoot, rcptRoot, err := sa.StateManager.TipSetState(ctx, ts) if err != nil { - return cid.Undef, nil, nil, xerrors.Errorf("failed to compute state: %w", err) + return cid.Undef, nil, nil, xerrors.Errorf("failed to compute tipset state: %w", err) } rcpts, err := cs.ReadReceipts(ctx, rcptRoot) @@ -651,7 +651,7 @@ func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, tx return newEthTx(ctx, cs, st, parentTs.Height(), parentTsCid, msgLookup.Message, txIdx) } -func newEthTx(ctx context.Context, cs *store.ChainStore, st *state.StateTree, blockHeight abi.ChainEpoch, parentTsCid cid.Cid, msgCid cid.Cid, txIdx int) (ethtypes.EthTx, error) { +func newEthTx(ctx context.Context, cs *store.ChainStore, st *state.StateTree, blockHeight abi.ChainEpoch, msgTsCid cid.Cid, msgCid cid.Cid, txIdx int) (ethtypes.EthTx, error) { smsg, err := getSignedMessage(ctx, cs, msgCid) if err != nil { return ethtypes.EthTx{}, xerrors.Errorf("failed to get signed msg: %w", err) @@ -667,7 +667,7 @@ func newEthTx(ctx context.Context, cs *store.ChainStore, st *state.StateTree, bl ti = ethtypes.EthUint64(txIdx) ) - blkHash, err := ethtypes.EthHashFromCid(parentTsCid) + blkHash, err := ethtypes.EthHashFromCid(msgTsCid) if err != nil { return ethtypes.EthTx{}, err } @@ -679,7 +679,7 @@ func newEthTx(ctx context.Context, cs *store.ChainStore, st *state.StateTree, bl return tx, nil } -func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLookup, ca ChainAPI, sa StateAPI, ev *EthEventHandler) (api.EthTxReceipt, error) { +func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, baseFee big.Int, msgReceipt types.MessageReceipt, ev *EthEventHandler) (api.EthTxReceipt, error) { var ( transactionIndex ethtypes.EthUint64 blockHash ethtypes.EthHash @@ -696,7 +696,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook blockNumber = *tx.BlockNumber } - receipt := api.EthTxReceipt{ + txReceipt := api.EthTxReceipt{ TransactionHash: tx.Hash, From: tx.From, To: tx.To, @@ -708,30 +708,16 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook LogsBloom: ethtypes.NewEmptyEthBloom(), } - if lookup.Receipt.ExitCode.IsSuccess() { - receipt.Status = 1 + if msgReceipt.ExitCode.IsSuccess() { + txReceipt.Status = 1 } else { - receipt.Status = 0 + txReceipt.Status = 0 } - receipt.GasUsed = ethtypes.EthUint64(lookup.Receipt.GasUsed) + txReceipt.GasUsed = ethtypes.EthUint64(msgReceipt.GasUsed) // TODO: handle CumulativeGasUsed - receipt.CumulativeGasUsed = ethtypes.EmptyEthInt - - // TODO: avoid loading the tipset twice (once here, once when we convert the message to a txn) - ts, err := ca.Chain.GetTipSetFromKey(ctx, lookup.TipSet) - if err != nil { - return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", lookup.TipSet, err) - } - - // The tx is located in the parent tipset - parentTs, err := ca.Chain.LoadTipSet(ctx, ts.Parents()) - if err != nil { - return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", ts.Parents(), err) - } - - baseFee := parentTs.Blocks()[0].ParentBaseFee + txReceipt.CumulativeGasUsed = ethtypes.EmptyEthInt gasFeeCap, err := tx.GasFeeCap() if err != nil { @@ -742,44 +728,44 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook return api.EthTxReceipt{}, xerrors.Errorf("failed to get gas premium: %w", err) } - gasOutputs := vm.ComputeGasOutputs(lookup.Receipt.GasUsed, int64(tx.Gas), baseFee, big.Int(gasFeeCap), + gasOutputs := vm.ComputeGasOutputs(msgReceipt.GasUsed, int64(tx.Gas), baseFee, big.Int(gasFeeCap), big.Int(gasPremium), true) totalSpent := big.Sum(gasOutputs.BaseFeeBurn, gasOutputs.MinerTip, gasOutputs.OverEstimationBurn) effectiveGasPrice := big.Zero() - if lookup.Receipt.GasUsed > 0 { - effectiveGasPrice = big.Div(totalSpent, big.NewInt(lookup.Receipt.GasUsed)) + if msgReceipt.GasUsed > 0 { + effectiveGasPrice = big.Div(totalSpent, big.NewInt(msgReceipt.GasUsed)) } - receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice) + txReceipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice) - if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() { + if txReceipt.To == nil && msgReceipt.ExitCode.IsSuccess() { // Create and Create2 return the same things. var ret eam.CreateExternalReturn - if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil { + if err := ret.UnmarshalCBOR(bytes.NewReader(msgReceipt.Return)); err != nil { return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err) } addr := ethtypes.EthAddress(ret.EthAddress) - receipt.ContractAddress = &addr + txReceipt.ContractAddress = &addr } - if rct := lookup.Receipt; rct.EventsRoot != nil { + if rct := msgReceipt; rct.EventsRoot != nil { logs, err := ev.getEthLogsForBlockAndTransaction(ctx, &blockHash, tx.Hash) if err != nil { return api.EthTxReceipt{}, xerrors.Errorf("failed to get eth logs for block and transaction: %w", err) } if len(logs) > 0 { - receipt.Logs = logs + txReceipt.Logs = logs } } - for _, log := range receipt.Logs { + for _, log := range txReceipt.Logs { for _, topic := range log.Topics { - ethtypes.EthBloomSet(receipt.LogsBloom, topic[:]) + ethtypes.EthBloomSet(txReceipt.LogsBloom, topic[:]) } - ethtypes.EthBloomSet(receipt.LogsBloom, log.Address[:]) + ethtypes.EthBloomSet(txReceipt.LogsBloom, log.Address[:]) } - return receipt, nil + return txReceipt, nil } func encodeFilecoinParamsAsABI(method abi.MethodNum, codec uint64, params []byte) []byte {