Skip to content

feat: no state overrides support for both evm and native states #504

@yihuang

Description

@yihuang

Context

State overrides are a feature that allows user to simulate some states when executing a message call in RPC, for example, to override native token balances or ERC20 token balances for an account.

In cosmos EVM, we'll need to extend that to native states for precompiles, for example, for erc20 precompiles, we need to override the states in bank module instead of contract storage.

Support Native State

There's an existing feature request #336 and draft pull request to bring geth state overrides to cosmos evm. This new proposal extend that to cover native states as well, which is necessary to support precompiles.

For cosmos-sdk storage system (including evm module), all state diff overrides can be expressed in a generic way as:

message StateEntry {
  bytes key = 1;
  bytes value = 2;
  bool delete = 3;
}

message StoreStateDiff {
  string name = 1;
  repeated StateEntry entries = 2 [(gogoproto.nullable) = false];
}

message EthCallRequest {
  ...
  // state_overrides represents the state overrides before executing the call
  repeated StoreStateDiff state_overrides = 5 [(gogoproto.nullable) = false];
}

Which can be applied to sdk context like this:

func (diff StoreStateDiff) Apply(ctx sdk.Context, keys map[string]*storetypes.KVStoreKey) {
	storeKey, ok := keys[diff.Name]
	if !ok {
		return
	}
	store := ctx.KVStore(storeKey)
	for _, entry := range diff.Entries {
		if entry.Delete {
			store.Delete(entry.Key)
		} else {
			store.Set(entry.Key, entry.Value)
		}
	}
}

In json-rpc we translate both evm state overrides and native state overrides args into above state diffs, and pass to EthCall /EstimateGas/TraceCall grpc queries.

At grpc query handler, we'll apply the state diffs to the sdk ctx before executing the message:

func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.MsgEthereumTxResponse, error) {
	ctx := sdk.UnwrapSDKContext(c)
	req.ApplyStateOverrides(ctx, k.KVStoreKeys())
}

Most of EVM overrides args can be handled as above approach, with the exception of replacing entire contract state and precompile movement, that will need some special care.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions