diff --git a/action/protocol/execution/evm/evm.go b/action/protocol/execution/evm/evm.go index 8b2852cd97..9b0433805b 100644 --- a/action/protocol/execution/evm/evm.go +++ b/action/protocol/execution/evm/evm.go @@ -82,16 +82,21 @@ func MakeTransfer(db vm.StateDB, fromHash, toHash common.Address, amount *big.In type ( // Params is the context and parameters Params struct { - context vm.BlockContext - txCtx vm.TxContext - nonce uint64 - evmNetworkID uint32 - executorRawAddress string - amount *big.Int - contract *common.Address - gas uint64 - data []byte - accessList types.AccessList + context vm.BlockContext + txCtx vm.TxContext + nonce uint64 + evmNetworkID uint32 + amount *big.Int + contract *common.Address + gas uint64 + data []byte + accessList types.AccessList + evmConfig vm.Config + chainConfig *params.ChainConfig + blkCtx protocol.BlockCtx + genesis genesis.Blockchain + featureCtx protocol.FeatureCtx + actionCtx protocol.ActionCtx } ) @@ -102,11 +107,19 @@ func newParams( stateDB *StateDBAdapter, getBlockHash GetBlockHash, ) (*Params, error) { - actionCtx := protocol.MustGetActionCtx(ctx) - blkCtx := protocol.MustGetBlockCtx(ctx) - featureCtx := protocol.MustGetFeatureCtx(ctx) - executorAddr := common.BytesToAddress(actionCtx.Caller.Bytes()) - var contractAddrPointer *common.Address + var ( + actionCtx = protocol.MustGetActionCtx(ctx) + blkCtx = protocol.MustGetBlockCtx(ctx) + featureCtx = protocol.MustGetFeatureCtx(ctx) + g = genesis.MustExtractGenesisContext(ctx) + evmNetworkID = protocol.MustGetBlockchainCtx(ctx).EvmNetworkID + executorAddr = common.BytesToAddress(actionCtx.Caller.Bytes()) + + vmConfig vm.Config + contractAddrPointer *common.Address + getHashFn vm.GetHashFunc + ) + if dest := execution.Contract(); dest != action.EmptyAddress { contract, err := address.FromString(execution.Contract()) if err != nil { @@ -122,7 +135,6 @@ func newParams( gasLimit = _preAleutianActionGasLimit } - var getHashFn vm.GetHashFunc switch { case featureCtx.CorrectGetHashFn: getHashFn = func(n uint64) common.Hash { @@ -162,6 +174,10 @@ func newParams( Difficulty: new(big.Int).SetUint64(uint64(50)), BaseFee: new(big.Int), } + if vmCfg, ok := protocol.GetVMConfigCtx(ctx); ok { + vmConfig = vmCfg + } + chainConfig := getChainConfig(g.Blockchain, blkCtx.BlockHeight, evmNetworkID) return &Params{ context, @@ -170,13 +186,18 @@ func newParams( GasPrice: execution.GasPrice(), }, execution.Nonce(), - protocol.MustGetBlockchainCtx(ctx).EvmNetworkID, - actionCtx.Caller.String(), + evmNetworkID, execution.Amount(), contractAddrPointer, gasLimit, execution.Data(), execution.AccessList(), + vmConfig, + chainConfig, + blkCtx, + g.Blockchain, + featureCtx, + actionCtx, }, nil } @@ -209,10 +230,7 @@ func ExecuteContract( ) ([]byte, *action.Receipt, error) { ctx, span := tracer.NewSpan(ctx, "evm.ExecuteContract") defer span.End() - actionCtx := protocol.MustGetActionCtx(ctx) - blkCtx := protocol.MustGetBlockCtx(ctx) - g := genesis.MustExtractGenesisContext(ctx) - featureCtx := protocol.MustGetFeatureCtx(ctx) + stateDB, err := prepareStateDB(ctx, sm) if err != nil { return nil, nil, err @@ -221,14 +239,14 @@ func ExecuteContract( if err != nil { return nil, nil, err } - retval, depositGas, remainingGas, contractAddress, statusCode, err := executeInEVM(ctx, ps, stateDB, g.Blockchain, blkCtx.GasLimit, blkCtx.BlockHeight) + retval, depositGas, remainingGas, contractAddress, statusCode, err := executeInEVM(ps, stateDB) if err != nil { return nil, nil, err } receipt := &action.Receipt{ GasConsumed: ps.gas - remainingGas, - BlockHeight: blkCtx.BlockHeight, - ActionHash: actionCtx.ActionHash, + BlockHeight: ps.blkCtx.BlockHeight, + ActionHash: ps.actionCtx.ActionHash, ContractAddress: contractAddress, } @@ -237,7 +255,7 @@ func ExecuteContract( depositLog, burnLog *action.TransactionLog consumedGas = depositGas - remainingGas ) - if featureCtx.FixDoubleChargeGas { + if ps.featureCtx.FixDoubleChargeGas { // Refund all deposit and, actual gas fee will be subtracted when depositing gas fee to the rewarding protocol stateDB.AddBalance(ps.txCtx.Origin, big.NewInt(0).Mul(big.NewInt(0).SetUint64(depositGas), ps.txCtx.GasPrice)) } else { @@ -248,7 +266,7 @@ func ExecuteContract( if consumedGas > 0 { burnLog = &action.TransactionLog{ Type: iotextypes.TransactionLogType_GAS_FEE, - Sender: actionCtx.Caller.String(), + Sender: ps.actionCtx.Caller.String(), Recipient: "", // burned Amount: new(big.Int).Mul(new(big.Int).SetUint64(consumedGas), ps.txCtx.GasPrice), } @@ -260,7 +278,7 @@ func ExecuteContract( sharedGas uint64 sharedGasFee, totalGasFee *big.Int ) - if featureCtx.SharedGasWithDapp && sgd != nil { + if ps.featureCtx.SharedGasWithDapp && sgd != nil { receiver, sharedGas, err = processSGD(ctx, sm, execution, consumedGas, sgd) if err != nil { return nil, nil, errors.Wrap(err, "failed to process Sharing of Gas-fee with DApps") @@ -282,12 +300,12 @@ func ExecuteContract( } receipt.AddLogs(stateDB.Logs()...).AddTransactionLogs(depositLog, burnLog) if receipt.Status == uint64(iotextypes.ReceiptStatus_Success) || - featureCtx.AddOutOfGasToTransactionLog && receipt.Status == uint64(iotextypes.ReceiptStatus_ErrCodeStoreOutOfGas) { + ps.featureCtx.AddOutOfGasToTransactionLog && receipt.Status == uint64(iotextypes.ReceiptStatus_ErrCodeStoreOutOfGas) { receipt.AddTransactionLogs(stateDB.TransactionLogs()...) } stateDB.clear() - if featureCtx.SetRevertMessageToReceipt && receipt.Status == uint64(iotextypes.ReceiptStatus_ErrExecutionReverted) && retval != nil && bytes.Equal(retval[:4], _revertSelector) { + if ps.featureCtx.SetRevertMessageToReceipt && receipt.Status == uint64(iotextypes.ReceiptStatus_ErrExecutionReverted) && retval != nil && bytes.Equal(retval[:4], _revertSelector) { // in case of the execution revert error, parse the retVal and add to receipt data := retval[4:] msgLength := byteutil.BytesToUint64BigEndian(data[56:64]) @@ -403,21 +421,22 @@ func getChainConfig(g genesis.Blockchain, height uint64, id uint32) *params.Chai } // Error in executeInEVM is a consensus issue -func executeInEVM(ctx context.Context, evmParams *Params, stateDB *StateDBAdapter, g genesis.Blockchain, gasLimit uint64, blockHeight uint64) ([]byte, uint64, uint64, string, iotextypes.ReceiptStatus, error) { - remainingGas := evmParams.gas +func executeInEVM(evmParams *Params, stateDB *StateDBAdapter) ([]byte, uint64, uint64, string, iotextypes.ReceiptStatus, error) { + var ( + gasLimit = evmParams.blkCtx.GasLimit + blockHeight = evmParams.blkCtx.BlockHeight + g = evmParams.genesis + remainingGas = evmParams.gas + chainConfig = evmParams.chainConfig + ) if err := securityDeposit(evmParams, stateDB, gasLimit); err != nil { log.L().Warn("unexpected error: not enough security deposit", zap.Error(err)) return nil, 0, 0, action.EmptyAddress, iotextypes.ReceiptStatus_Failure, err } var ( - config vm.Config accessList types.AccessList ) - if vmCfg, ok := protocol.GetVMConfigCtx(ctx); ok { - config = vmCfg - } - chainConfig := getChainConfig(g, blockHeight, evmParams.evmNetworkID) - evm := vm.NewEVM(evmParams.context, evmParams.txCtx, stateDB, chainConfig, config) + evm := vm.NewEVM(evmParams.context, evmParams.txCtx, stateDB, chainConfig, evmParams.evmConfig) if g.IsOkhotsk(blockHeight) { accessList = evmParams.accessList } @@ -481,7 +500,7 @@ func executeInEVM(ctx context.Context, evmParams *Params, stateDB *StateDBAdapte // the tx is reverted. After Okhotsk height, it is fixed inside RevertToSnapshot() var ( deltaRefundByDynamicGas = evm.DeltaRefundByDynamicGas - featureCtx = protocol.MustGetFeatureCtx(ctx) + featureCtx = evmParams.featureCtx ) if !featureCtx.CorrectGasRefund && deltaRefundByDynamicGas != 0 { if deltaRefundByDynamicGas > 0 {