forked from cerc-io/laconicd-deprecated
evm: store reverted tx as not failed (#228)
* add tx when evm revert * add comment * use cache ctx Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
co-authored by
Federico Kunze Küllmer
parent
20c42dc10d
commit
735f00d4a3
@@ -75,6 +75,10 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
|
||||
attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyRecipient, tx.To().Hex()))
|
||||
}
|
||||
|
||||
if response.Reverted {
|
||||
attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyEthereumTxReverted, "true"))
|
||||
}
|
||||
|
||||
// emit events
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
|
||||
@@ -126,12 +126,16 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
|
||||
return nil, stacktrace.Propagate(err, "failed to return ethereum transaction as core message")
|
||||
}
|
||||
|
||||
// create an ethereum StateTransition instance and run TransitionDb
|
||||
// we use a ctx context to avoid modifying to state in case EVM msg is reverted
|
||||
originalCtx := k.ctx
|
||||
cacheCtx, commit := k.ctx.CacheContext()
|
||||
k.ctx = cacheCtx
|
||||
|
||||
evm := k.NewEVM(msg, ethCfg)
|
||||
|
||||
k.SetTxHashTransient(tx.Hash())
|
||||
k.IncreaseTxIndexTransient()
|
||||
|
||||
// create an ethereum StateTransition instance and run TransitionDb
|
||||
res, err := k.ApplyMessage(evm, msg, ethCfg)
|
||||
if err != nil {
|
||||
return nil, stacktrace.Propagate(err, "failed to apply ethereum core message")
|
||||
@@ -140,14 +144,27 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
|
||||
txHash := tx.Hash()
|
||||
res.Hash = txHash.Hex()
|
||||
|
||||
logs := k.GetTxLogs(txHash)
|
||||
res.Logs = types.NewLogsFromEth(logs)
|
||||
// Set the bloom filter and commit only if transaction is NOT reverted
|
||||
if !res.Reverted {
|
||||
logs := k.GetTxLogs(txHash)
|
||||
res.Logs = types.NewLogsFromEth(logs)
|
||||
// update block bloom filter
|
||||
bloom := k.GetBlockBloomTransient()
|
||||
bloom.Or(bloom, big.NewInt(0).SetBytes(ethtypes.LogsBloom(logs)))
|
||||
k.SetBlockBloomTransient(bloom)
|
||||
|
||||
// update block bloom filter
|
||||
bloom := k.GetBlockBloomTransient()
|
||||
bloom.Or(bloom, big.NewInt(0).SetBytes(ethtypes.LogsBloom(logs)))
|
||||
k.SetBlockBloomTransient(bloom)
|
||||
commit()
|
||||
}
|
||||
|
||||
// refund gas prior to handling the vm error in order to set the updated gas meter
|
||||
k.ctx = originalCtx
|
||||
leftoverGas := msg.Gas() - res.GasUsed
|
||||
leftoverGas, err = k.RefundGas(msg, leftoverGas)
|
||||
if err != nil {
|
||||
return nil, stacktrace.Propagate(err, "failed to refund gas leftover gas to sender %s", msg.From())
|
||||
}
|
||||
// update the gas used after refund
|
||||
res.GasUsed = msg.Gas() - leftoverGas
|
||||
k.resetGasMeterAndConsumeGas(res.GasUsed)
|
||||
return res, nil
|
||||
}
|
||||
@@ -215,26 +232,19 @@ func (k *Keeper) ApplyMessage(evm *vm.EVM, msg core.Message, cfg *params.ChainCo
|
||||
ret, leftoverGas, vmErr = evm.Call(sender, *msg.To(), msg.Data(), leftoverGas, msg.Value())
|
||||
}
|
||||
|
||||
// refund gas prior to handling the vm error in order to set the updated gas meter
|
||||
leftoverGas, err = k.RefundGas(msg, leftoverGas)
|
||||
if err != nil {
|
||||
return nil, stacktrace.Propagate(err, "failed to refund gas leftover gas to sender %s", msg.From())
|
||||
}
|
||||
|
||||
var reverted bool
|
||||
if vmErr != nil {
|
||||
if errors.Is(vmErr, vm.ErrExecutionReverted) {
|
||||
// unpack the return data bytes from the err if the execution has been "reverted" on the VM
|
||||
return nil, stacktrace.Propagate(types.NewExecErrorWithReson(ret), "transaction reverted")
|
||||
if !errors.Is(vmErr, vm.ErrExecutionReverted) {
|
||||
// wrap the VM error
|
||||
return nil, stacktrace.Propagate(sdkerrors.Wrap(types.ErrVMExecution, vmErr.Error()), "vm execution failed")
|
||||
}
|
||||
|
||||
// wrap the VM error
|
||||
return nil, stacktrace.Propagate(sdkerrors.Wrap(types.ErrVMExecution, vmErr.Error()), "vm execution failed")
|
||||
reverted = true
|
||||
}
|
||||
|
||||
gasUsed := msg.Gas() - leftoverGas
|
||||
return &types.MsgEthereumTxResponse{
|
||||
Ret: ret,
|
||||
Reverted: false,
|
||||
Reverted: reverted,
|
||||
GasUsed: gasUsed,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -73,9 +73,9 @@ var (
|
||||
ErrInconsistentGas = sdkerrors.Register(ModuleName, codeErrInconsistentGas, "inconsistent gas")
|
||||
)
|
||||
|
||||
// NewExecErrorWithReson unpacks the revert return bytes and returns a wrapped error
|
||||
// NewExecErrorWithReason unpacks the revert return bytes and returns a wrapped error
|
||||
// with the return reason.
|
||||
func NewExecErrorWithReson(revertReason []byte) error {
|
||||
func NewExecErrorWithReason(revertReason []byte) error {
|
||||
hexValue := hexutil.Encode(revertReason)
|
||||
reason, errUnpack := abi.UnpackRevert(revertReason)
|
||||
if errUnpack == nil {
|
||||
|
||||
@@ -4,11 +4,12 @@ package types
|
||||
const (
|
||||
EventTypeEthereumTx = TypeMsgEthereumTx
|
||||
|
||||
AttributeKeyContractAddress = "contract"
|
||||
AttributeKeyRecipient = "recipient"
|
||||
AttributeKeyTxHash = "txHash"
|
||||
AttributeKeyEthereumTxHash = "ethereumTxHash"
|
||||
AttributeValueCategory = ModuleName
|
||||
AttributeKeyContractAddress = "contract"
|
||||
AttributeKeyRecipient = "recipient"
|
||||
AttributeKeyTxHash = "txHash"
|
||||
AttributeKeyEthereumTxHash = "ethereumTxHash"
|
||||
AttributeKeyEthereumTxReverted = "ethereumTxReverted"
|
||||
AttributeValueCategory = ModuleName
|
||||
|
||||
MetricKeyTransitionDB = "transition_db"
|
||||
MetricKeyStaticCall = "static_call"
|
||||
|
||||
Reference in New Issue
Block a user