Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: state overrides are not supported in eth_call #369

Merged
merged 11 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (ante) [#310](https://github.com/crypto-org-chain/ethermint/pull/310) Support blocking list of addresses in mempool.
* (evm) [#328](https://github.com/crypto-org-chain/ethermint/pull/328) Support precompile interface.
* (statedb) [#333](https://github.com/crypto-org-chain/ethermint/pull/333) Support native action in statedb, prepare for precompiles.
* (rpc) [#369](https://github.com/crypto-org-chain/ethermint/pull/369) Support state overrides in eth_call.

### State Machine Breaking

Expand Down
2 changes: 2 additions & 0 deletions proto/ethermint/evm/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ message EthCallRequest {
bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
// chain_id is the eip155 chain id parsed from the requested block header
int64 chain_id = 4;
// state overrides encoded as json
bytes overrides = 5;
}

// EstimateGasResponse defines EstimateGas response
Expand Down
2 changes: 1 addition & 1 deletion rpc/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ type EVMBackend interface {
SendRawTransaction(data hexutil.Bytes) (common.Hash, error)
SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error)
EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rpctypes.BlockNumber) (hexutil.Uint64, error)
DoCall(args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber) (*evmtypes.MsgEthereumTxResponse, error)
DoCall(args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber, overrides *rpctypes.StateOverride) (*evmtypes.MsgEthereumTxResponse, error)
GasPrice() (*hexutil.Big, error)

// Filter API
Expand Down
10 changes: 10 additions & 0 deletions rpc/backend/call_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@
// estimated gas used on the operation or an error if fails.
func (b *Backend) DoCall(
args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber,
overrides *rpctypes.StateOverride,
) (*evmtypes.MsgEthereumTxResponse, error) {
bz, err := json.Marshal(&args)
if err != nil {
Expand All @@ -371,11 +372,20 @@
return nil, errors.New("header not found")
}

var overridesJson []byte

Check warning on line 375 in rpc/backend/call_tx.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

var-naming: var overridesJson should be overridesJSON (revive)
if overrides != nil {
overridesJson, err = json.Marshal(overrides)
if err != nil {
return nil, err
}
}

req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ChainId: b.chainID.Int64(),
Overrides: overridesJson,
}

// From ContextWithHeight: if the provided height is 0,
Expand Down
6 changes: 3 additions & 3 deletions rpc/namespaces/ethereum/eth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ type EthereumAPI interface {
//
// Allows developers to read data from the blockchain which includes executing
// smart contracts. However, no data is published to the Ethereum network.
Call(args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, _ *rpctypes.StateOverride) (hexutil.Bytes, error)
Call(args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash, overrides *rpctypes.StateOverride) (hexutil.Bytes, error)

// Chain Information
//
Expand Down Expand Up @@ -280,15 +280,15 @@ func (e *PublicAPI) GetProof(address common.Address,
// Call performs a raw contract call.
func (e *PublicAPI) Call(args evmtypes.TransactionArgs,
blockNrOrHash rpctypes.BlockNumberOrHash,
_ *rpctypes.StateOverride,
overrides *rpctypes.StateOverride,
) (hexutil.Bytes, error) {
e.logger.Debug("eth_call", "args", args.String(), "block number or hash", blockNrOrHash)

blockNum, err := e.backend.BlockNumberFromTendermint(blockNrOrHash)
if err != nil {
return nil, err
}
data, err := e.backend.DoCall(args, blockNum)
data, err := e.backend.DoCall(args, blockNum, overrides)
if err != nil {
return []byte{}, err
}
Expand Down
37 changes: 37 additions & 0 deletions rpc/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
package types

import (
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/evmos/ethermint/x/evm/statedb"
)

// Copied the Account and StorageResult types since they are registered under an
Expand Down Expand Up @@ -70,6 +72,41 @@
// StateOverride is the collection of overridden accounts.
type StateOverride map[common.Address]OverrideAccount

// Apply overrides the fields of specified accounts into the given state.
func (diff *StateOverride) Apply(db *statedb.StateDB) error {
if diff == nil {
return nil
}
for addr, account := range *diff {
// Override account nonce.
if account.Nonce != nil {
db.SetNonce(addr, uint64(*account.Nonce))
}
// Override account(contract) code.
if account.Code != nil {
db.SetCode(addr, *account.Code)
}
// Override account balance.
if account.Balance != nil {
db.SetBalance(addr, (*big.Int)(*account.Balance))
}
if account.State != nil && account.StateDiff != nil {
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
}
// Replace entire state if caller requires.
if account.State != nil {
db.SetStorage(addr, *account.State)
}
// Apply state diff into specified accounts.
if account.StateDiff != nil {
for key, value := range *account.StateDiff {
db.SetState(addr, key, value)
}
Comment on lines +102 to +104

Check failure

Code scanning / gosec

the value in the range statement should be _ unless copying a map: want: for key := range m Error

the value in the range statement should be _ unless copying a map: want: for key := range m
}
}
Comment on lines +80 to +106

Check failure

Code scanning / gosec

the value in the range statement should be _ unless copying a map: want: for key := range m Error

expected exactly 1 statement (either append, delete, or copying to another map) in a range with a map, got 6
return nil
}

// OverrideAccount indicates the overriding fields of account during the execution of
// a message call.
// Note, state and stateDiff can't be specified at the same time. If state is
Expand Down
40 changes: 28 additions & 12 deletions x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"github.com/ethereum/go-ethereum/core/vm"
ethparams "github.com/ethereum/go-ethereum/params"

rpctypes "github.com/evmos/ethermint/rpc/types"
ethermint "github.com/evmos/ethermint/types"
"github.com/evmos/ethermint/x/evm/statedb"
"github.com/evmos/ethermint/x/evm/types"
Expand Down Expand Up @@ -231,6 +232,13 @@
return nil, status.Error(codes.InvalidArgument, "empty request")
}

var overrides *rpctypes.StateOverride
if len(req.Overrides) > 0 {
if err := json.Unmarshal(req.Overrides, overrides); err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
}

ctx := sdk.UnwrapSDKContext(c)

var args types.TransactionArgs
Expand Down Expand Up @@ -259,7 +267,7 @@
txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))

// pass false to not commit StateDB
res, err := k.ApplyMessageWithConfig(ctx, msg, nil, false, cfg, txConfig)
res, err := k.ApplyMessageWithConfig(ctx, msg, nil, false, cfg, txConfig, overrides)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
Expand Down Expand Up @@ -354,7 +362,7 @@
)

// pass false to not commit StateDB
rsp, err = k.ApplyMessageWithConfig(ctx, msg, nil, false, cfg, txConfig)
rsp, err = k.ApplyMessageWithConfig(ctx, msg, nil, false, cfg, txConfig, nil)
if err != nil {
if errors.Is(err, core.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
Expand Down Expand Up @@ -406,6 +414,13 @@
return nil, status.Errorf(codes.InvalidArgument, "output limit cannot be negative, got %d", req.TraceConfig.Limit)
}

var overrides *rpctypes.StateOverride
if len(req.Overrides) > 0 {

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / dependency-review

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-importer

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-sim-nondeterminism

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-rpc

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-sim-random-genesis-fast

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 418 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)
if err := json.Unmarshal(req.Overrides, overrides); err != nil {

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / dependency-review

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-importer

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-sim-nondeterminism

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-rpc

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-sim-random-genesis-fast

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / test-unit-cover

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides) (typecheck)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)) (typecheck)

Check failure on line 419 in x/evm/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

req.Overrides undefined (type *"github.com/evmos/ethermint/x/evm/types".QueryTraceTxRequest has no field or method Overrides)) (typecheck)
return nil, status.Error(codes.InvalidArgument, err.Error())
}
}

// get the context of block beginning
contextHeight := req.BlockNumber
if contextHeight < 1 {
Expand Down Expand Up @@ -436,7 +451,7 @@
}
txConfig.TxHash = ethTx.Hash()
txConfig.TxIndex = uint(i)
rsp, err := k.ApplyMessageWithConfig(ctx, msg, types.NewNoOpTracer(), true, cfg, txConfig)
rsp, err := k.ApplyMessageWithConfig(ctx, msg, types.NewNoOpTracer(), true, cfg, txConfig, nil)
if err != nil {
continue
}
Expand All @@ -455,7 +470,7 @@
_ = json.Unmarshal([]byte(req.TraceConfig.TracerJsonConfig), &tracerConfig)
}

result, _, err := k.traceTx(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false, tracerConfig)
result, _, err := k.traceTx(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false, tracerConfig, overrides)
if err != nil {
// error will be returned with detail status from traceTx
return nil, err
Expand Down Expand Up @@ -513,7 +528,7 @@
ethTx := tx.AsTransaction()
txConfig.TxHash = ethTx.Hash()
txConfig.TxIndex = uint(i)
traceResult, logIndex, err := k.traceTx(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true, nil)
traceResult, logIndex, err := k.traceTx(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true, nil, nil)
if err != nil {
result.Error = err.Error()
} else {
Expand Down Expand Up @@ -543,13 +558,14 @@
traceConfig *types.TraceConfig,
commitMessage bool,
tracerJSONConfig json.RawMessage,
overrides *rpctypes.StateOverride,
) (*interface{}, uint, error) {
// Assemble the structured logger or the JavaScript tracer
var (
tracer tracers.Tracer
overrides *ethparams.ChainConfig
err error
timeout = defaultTraceTimeout
tracer tracers.Tracer
overrideCfg *ethparams.ChainConfig
err error
timeout = defaultTraceTimeout
)
msg, err := tx.AsMessage(signer, cfg.BaseFee)
if err != nil {
Expand All @@ -561,7 +577,7 @@
}

if traceConfig.Overrides != nil {
overrides = traceConfig.Overrides.EthereumConfig(cfg.ChainConfig.ChainID)
overrideCfg = traceConfig.Overrides.EthereumConfig(cfg.ChainConfig.ChainID)
}

logConfig := logger.Config{
Expand All @@ -571,7 +587,7 @@
EnableReturnData: traceConfig.EnableReturnData,
Debug: traceConfig.Debug,
Limit: int(traceConfig.Limit),
Overrides: overrides,
Overrides: overrideCfg,
}

tracer = logger.NewStructLogger(&logConfig)
Expand Down Expand Up @@ -606,7 +622,7 @@
}
}()

res, err := k.ApplyMessageWithConfig(ctx, msg, tracer, commitMessage, cfg, txConfig)
res, err := k.ApplyMessageWithConfig(ctx, msg, tracer, commitMessage, cfg, txConfig, overrides)
if err != nil {
return nil, 0, status.Error(codes.Internal, err.Error())
}
Expand Down
12 changes: 10 additions & 2 deletions x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"

rpctypes "github.com/evmos/ethermint/rpc/types"
ethermint "github.com/evmos/ethermint/types"
"github.com/evmos/ethermint/x/evm/statedb"
"github.com/evmos/ethermint/x/evm/types"
Expand Down Expand Up @@ -194,7 +195,7 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, msgEth *types.MsgEthereumTx)
}

// pass true to commit the StateDB
res, err := k.ApplyMessageWithConfig(tmpCtx, msg, nil, true, cfg, txConfig)
res, err := k.ApplyMessageWithConfig(tmpCtx, msg, nil, true, cfg, txConfig, nil)
if err != nil {
return nil, errorsmod.Wrap(err, "failed to apply ethereum core message")
}
Expand Down Expand Up @@ -286,7 +287,7 @@ func (k *Keeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLo
}

txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))
return k.ApplyMessageWithConfig(ctx, msg, tracer, commit, cfg, txConfig)
return k.ApplyMessageWithConfig(ctx, msg, tracer, commit, cfg, txConfig, nil)
}

// ApplyMessageWithConfig computes the new state by applying the given message against the existing state.
Expand Down Expand Up @@ -333,6 +334,7 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context,
commit bool,
cfg *statedb.EVMConfig,
txConfig statedb.TxConfig,
overrides *rpctypes.StateOverride,
) (*types.MsgEthereumTxResponse, error) {
var (
ret []byte // return bytes from evm execution
Expand All @@ -347,6 +349,12 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context,
}

stateDB := statedb.NewWithParams(ctx, k, txConfig, cfg.Params)
if overrides != nil {
if err := overrides.Apply(stateDB); err != nil {
return nil, errorsmod.Wrap(err, "failed to apply state override")
}
}

evm := k.NewEVM(ctx, msg, cfg, tracer, stateDB, k.customContracts)
leftoverGas := msg.Gas()
// Allow the tracer captures the tx level events, mainly the gas consumption.
Expand Down
2 changes: 1 addition & 1 deletion x/evm/keeper/state_transition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() {
txConfig = suite.app.EvmKeeper.TxConfig(suite.ctx, common.Hash{})

tc.malleate()
res, err := suite.app.EvmKeeper.ApplyMessageWithConfig(suite.ctx, msg, nil, true, config, txConfig)
res, err := suite.app.EvmKeeper.ApplyMessageWithConfig(suite.ctx, msg, nil, true, config, txConfig, nil)

if tc.expErr {
suite.Require().Error(err)
Expand Down
1 change: 1 addition & 0 deletions x/evm/statedb/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Keeper interface {

AddBalance(ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) error
SubBalance(ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) error
SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int) error
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) *big.Int

// Read methods
Expand Down
20 changes: 18 additions & 2 deletions x/evm/statedb/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,14 @@
}
}

func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) {
if err := s.ExecuteNativeAction(common.Address{}, nil, func(ctx sdk.Context) error {
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
return s.keeper.SetBalance(ctx, addr, amount)
}); err != nil {
s.err = err
}
}

// SetNonce sets the nonce of account.
func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := s.getOrNewStateObject(addr)
Expand All @@ -404,9 +412,17 @@
// SetState sets the contract state.
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetState(key, value)
stateObject.SetState(key, value)
}

// SetStorage replaces the entire storage for the specified account with given
// storage. This function should only be used for debugging and the mutations
// must be discarded afterwards.
func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
stateObject := s.getOrNewStateObject(addr)
for k, v := range storage {
stateObject.SetState(k, v)
}

Check failure

Code scanning / gosec

the value in the range statement should be _ unless copying a map: want: for key := range m Error

the value in the range statement should be _ unless copying a map: want: for key := range m
}

// Suicide marks the given account as suicided.
Expand Down
Loading
Loading