diff --git a/ante/cosmos/setup_test.go b/ante/cosmos/setup_test.go
index 47d45b29..8f98f403 100644
--- a/ante/cosmos/setup_test.go
+++ b/ante/cosmos/setup_test.go
@@ -22,7 +22,6 @@ import (
"github.com/evmos/evmos/v19/x/evm/statedb"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
"github.com/evmos/os/ante"
evmante "github.com/evmos/os/ante/evm"
"github.com/evmos/os/crypto/ethsecp256k1"
@@ -33,6 +32,7 @@ import (
chaintestutil "github.com/evmos/os/example_chain/testutil"
"github.com/evmos/os/testutil"
"github.com/evmos/os/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
)
type AnteTestSuite struct {
diff --git a/ante/evm/setup_test.go b/ante/evm/setup_test.go
index c3f493c9..c42d5945 100644
--- a/ante/evm/setup_test.go
+++ b/ante/evm/setup_test.go
@@ -17,13 +17,13 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/core/types"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
evmosante "github.com/evmos/os/ante"
"github.com/evmos/os/encoding"
"github.com/evmos/os/ethereum/eip712"
app "github.com/evmos/os/example_chain"
chainante "github.com/evmos/os/example_chain/ante"
"github.com/evmos/os/testutil"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
)
type AnteTestSuite struct {
diff --git a/ante/interfaces/evm.go b/ante/interfaces/evm.go
index 1887d076..82309d97 100644
--- a/ante/interfaces/evm.go
+++ b/ante/interfaces/evm.go
@@ -15,7 +15,7 @@ import (
"github.com/evmos/evmos/v19/x/evm/statedb"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
)
// EVMKeeper exposes the required EVM keeper interface required for ante handlers
diff --git a/example_chain/app.go b/example_chain/app.go
index b2cd21b3..4213daf1 100644
--- a/example_chain/app.go
+++ b/example_chain/app.go
@@ -97,9 +97,6 @@ import (
"github.com/evmos/evmos/v19/x/evm/core/vm"
evmkeeper "github.com/evmos/evmos/v19/x/evm/keeper"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- "github.com/evmos/evmos/v19/x/feemarket"
- feemarketkeeper "github.com/evmos/evmos/v19/x/feemarket/keeper"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
evmosante "github.com/evmos/os/ante"
evmosevmante "github.com/evmos/os/ante/evm"
evmosencoding "github.com/evmos/os/encoding"
@@ -108,6 +105,9 @@ import (
srvflags "github.com/evmos/os/server/flags"
evmostypes "github.com/evmos/os/types"
evmosutils "github.com/evmos/os/utils"
+ "github.com/evmos/os/x/feemarket"
+ feemarketkeeper "github.com/evmos/os/x/feemarket/keeper"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
"github.com/spf13/cast"
)
diff --git a/example_chain/testutil/contract.go b/example_chain/testutil/contract.go
index 82084c37..3a5f1536 100644
--- a/example_chain/testutil/contract.go
+++ b/example_chain/testutil/contract.go
@@ -19,9 +19,9 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
- evm "github.com/evmos/evmos/v19/x/evm/types"
- app "github.com/evmos/os/example_chain"
+ example_app "github.com/evmos/os/example_chain"
"github.com/evmos/os/testutil/tx"
+ evm "github.com/evmos/os/x/evm/types"
)
// ContractArgs are the params used for calling a smart contract.
@@ -42,7 +42,7 @@ type ContractCallArgs struct {
Contract ContractArgs
// Nonce is the nonce to use for the transaction.
Nonce *big.Int
- // Amount is the aevmos amount to send in the transaction.
+ // Amount is the amount of the native denomination to send in the transaction.
Amount *big.Int
// GasLimit to use for the transaction
GasLimit uint64
@@ -54,7 +54,7 @@ type ContractCallArgs struct {
// compiled contract data and constructor arguments
func DeployContract(
ctx sdk.Context,
- app *app.ExampleChain,
+ app *example_app.ExampleChain,
priv cryptotypes.PrivKey,
queryClientEvm evm.QueryClient,
contract evm.CompiledContract,
@@ -102,14 +102,14 @@ func DeployContract(
// with the provided factoryAddress
func DeployContractWithFactory(
ctx sdk.Context,
- evmosApp *app.ExampleChain,
+ exampleApp *example_app.ExampleChain,
priv cryptotypes.PrivKey,
factoryAddress common.Address,
) (common.Address, abci.ResponseDeliverTx, error) {
- chainID := evmosApp.EVMKeeper.ChainID()
+ chainID := exampleApp.EVMKeeper.ChainID()
from := common.BytesToAddress(priv.PubKey().Address().Bytes())
- factoryNonce := evmosApp.EVMKeeper.GetNonce(ctx, factoryAddress)
- nonce := evmosApp.EVMKeeper.GetNonce(ctx, from)
+ factoryNonce := exampleApp.EVMKeeper.GetNonce(ctx, factoryAddress)
+ nonce := exampleApp.EVMKeeper.GetNonce(ctx, from)
msgEthereumTx := evm.NewTx(&evm.EvmTxArgs{
ChainID: chainID,
@@ -120,12 +120,12 @@ func DeployContractWithFactory(
})
msgEthereumTx.From = from.String()
- res, err := DeliverEthTx(evmosApp, priv, msgEthereumTx)
+ res, err := DeliverEthTx(exampleApp, priv, msgEthereumTx)
if err != nil {
return common.Address{}, abci.ResponseDeliverTx{}, err
}
- if _, err := CheckEthTxResponse(res, evmosApp.AppCodec()); err != nil {
+ if _, err := CheckEthTxResponse(res, exampleApp.AppCodec()); err != nil {
return common.Address{}, abci.ResponseDeliverTx{}, err
}
diff --git a/example_chain/testutil/fund.go b/example_chain/testutil/fund.go
index f184b119..28d036c3 100644
--- a/example_chain/testutil/fund.go
+++ b/example_chain/testutil/fund.go
@@ -22,7 +22,9 @@ func FundAccount(ctx sdk.Context, bankKeeper bankkeeper.Keeper, addr sdk.AccAddr
}
// FundAccountWithBaseDenom is a utility function that uses the FundAccount function
-// to fund an account with the default Evmos denomination.
+// to fund an account with the default denomination.
+//
+// TODO: as per Freddy these methods should be replaced with a bank transfer from a main account, not by minting in the process
func FundAccountWithBaseDenom(ctx sdk.Context, bankKeeper bankkeeper.Keeper, addr sdk.AccAddress, amount int64) error {
coins := sdk.NewCoins(
sdk.NewCoin(testutil.ExampleAttoDenom, math.NewInt(amount)),
diff --git a/ibc/errors.go b/ibc/errors.go
new file mode 100644
index 00000000..fd4d7188
--- /dev/null
+++ b/ibc/errors.go
@@ -0,0 +1,11 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package ibc
+
+import "errors"
+
+var (
+ ErrNoIBCVoucherDenom = errors.New("denom is not an IBC voucher")
+ ErrDenomTraceNotFound = errors.New("denom trace not found")
+ ErrInvalidBaseDenom = errors.New("invalid base denomination")
+)
diff --git a/ibc/module.go b/ibc/module.go
new file mode 100644
index 00000000..a2688f7f
--- /dev/null
+++ b/ibc/module.go
@@ -0,0 +1,129 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ibc
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types"
+ "github.com/cosmos/ibc-go/v7/modules/core/exported"
+)
+
+var _ porttypes.IBCModule = &Module{}
+
+// Module a concrete type for a module boilerplate.
+type Module struct {
+ app porttypes.IBCModule
+}
+
+// NewModule creates a new IBC Module boilerplate given the underlying IBC app
+func NewModule(app porttypes.IBCModule) *Module {
+ return &Module{
+ app: app,
+ }
+}
+
+// OnChanOpenInit implements the Module interface
+// It calls the underlying app's OnChanOpenInit callback.
+func (im Module) OnChanOpenInit(
+ ctx sdk.Context,
+ order channeltypes.Order,
+ connectionHops []string,
+ portID string,
+ channelID string,
+ chanCap *capabilitytypes.Capability,
+ counterparty channeltypes.Counterparty,
+ version string,
+) (string, error) {
+ return im.app.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, version)
+}
+
+// OnChanOpenTry implements the Module interface.
+// It calls the underlying app's OnChanOpenTry callback.
+func (im Module) OnChanOpenTry(
+ ctx sdk.Context,
+ order channeltypes.Order,
+ connectionHops []string,
+ portID,
+ channelID string,
+ chanCap *capabilitytypes.Capability,
+ counterparty channeltypes.Counterparty,
+ counterpartyVersion string,
+) (version string, err error) {
+ return im.app.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, counterpartyVersion)
+}
+
+// OnChanOpenAck implements the Module interface.
+// It calls the underlying app's OnChanOpenAck callback.
+func (im Module) OnChanOpenAck(
+ ctx sdk.Context,
+ portID,
+ channelID,
+ counterpartyChannelID,
+ counterpartyVersion string,
+) error {
+ return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion)
+}
+
+// OnChanOpenConfirm implements the Module interface.
+// It calls the underlying app's OnChanOpenConfirm callback.
+func (im Module) OnChanOpenConfirm(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ return im.app.OnChanOpenConfirm(ctx, portID, channelID)
+}
+
+// OnChanCloseInit implements the Module interface
+// It calls the underlying app's OnChanCloseInit callback.
+func (im Module) OnChanCloseInit(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ return im.app.OnChanCloseInit(ctx, portID, channelID)
+}
+
+// OnChanCloseConfirm implements the Module interface.
+// It calls the underlying app's OnChanCloseConfirm callback.
+func (im Module) OnChanCloseConfirm(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ return im.app.OnChanCloseConfirm(ctx, portID, channelID)
+}
+
+// OnRecvPacket implements the Module interface.
+// It calls the underlying app's OnRecvPacket callback.
+func (im Module) OnRecvPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ relayer sdk.AccAddress,
+) exported.Acknowledgement {
+ return im.app.OnRecvPacket(ctx, packet, relayer)
+}
+
+// OnAcknowledgementPacket implements the Module interface.
+// It calls the underlying app's OnAcknowledgementPacket callback.
+func (im Module) OnAcknowledgementPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ acknowledgement []byte,
+ relayer sdk.AccAddress,
+) error {
+ return im.app.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer)
+}
+
+// OnTimeoutPacket implements the Module interface.
+// It calls the underlying app's OnTimeoutPacket callback.
+func (im Module) OnTimeoutPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ relayer sdk.AccAddress,
+) error {
+ return im.app.OnTimeoutPacket(ctx, packet, relayer)
+}
diff --git a/ibc/module_test.go b/ibc/module_test.go
new file mode 100644
index 00000000..44df31cc
--- /dev/null
+++ b/ibc/module_test.go
@@ -0,0 +1,207 @@
+package ibc
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
+
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types"
+ "github.com/cosmos/ibc-go/v7/modules/core/exported"
+)
+
+var _ porttypes.IBCModule = &MockIBCModule{}
+
+// MockIBCModule defines a mocked object that implements the IBCModule
+// interface. It's used on tests to abstract the complexity of IBC callbacks.
+type MockIBCModule struct {
+ mock.Mock
+}
+
+// OnChanOpenInit implements the Module interface
+// It calls the underlying app's OnChanOpenInit callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnChanOpenInit(
+ ctx sdk.Context,
+ order channeltypes.Order,
+ connectionHops []string,
+ portID string,
+ channelID string,
+ chanCap *capabilitytypes.Capability,
+ counterparty channeltypes.Counterparty,
+ version string,
+) (string, error) {
+ args := m.Called()
+ return version, args.Error(0)
+}
+
+// OnChanOpenTry implements the Module interface.
+// It calls the underlying app's OnChanOpenTry callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnChanOpenTry(
+ ctx sdk.Context,
+ order channeltypes.Order,
+ connectionHops []string,
+ portID,
+ channelID string,
+ chanCap *capabilitytypes.Capability,
+ counterparty channeltypes.Counterparty,
+ counterpartyVersion string,
+) (version string, err error) {
+ args := m.Called()
+ return args.String(0), args.Error(1)
+}
+
+// OnChanOpenAck implements the Module interface.
+// It calls the underlying app's OnChanOpenAck callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnChanOpenAck(
+ ctx sdk.Context,
+ portID,
+ channelID,
+ counterpartyChannelID,
+ counterpartyVersion string,
+) error {
+ args := m.Called()
+ return args.Error(0)
+}
+
+// OnChanOpenConfirm implements the Module interface.
+// It calls the underlying app's OnChanOpenConfirm callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnChanOpenConfirm(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ args := m.Called()
+ return args.Error(0)
+}
+
+// OnChanCloseInit implements the Module interface
+// It calls the underlying app's OnChanCloseInit callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnChanCloseInit(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ args := m.Called()
+ return args.Error(0)
+}
+
+// OnChanCloseConfirm implements the Module interface.
+// It calls the underlying app's OnChanCloseConfirm callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnChanCloseConfirm(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ args := m.Called()
+ return args.Error(0)
+}
+
+// OnRecvPacket implements the Module interface.
+// It calls the underlying app's OnRecvPacket callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnRecvPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ relayer sdk.AccAddress,
+) exported.Acknowledgement {
+ args := m.Called()
+ return args.Get(0).(exported.Acknowledgement)
+}
+
+// OnAcknowledgementPacket implements the Module interface.
+// It calls the underlying app's OnAcknowledgementPacket callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnAcknowledgementPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ acknowledgement []byte,
+ relayer sdk.AccAddress,
+) error {
+ args := m.Called()
+ return args.Error(0)
+}
+
+// OnTimeoutPacket implements the Module interface.
+// It calls the underlying app's OnTimeoutPacket callback.
+//
+// and escaping revive for unused parameters which are okay since they indicate the expected mocked interface
+//
+//nolint:all // escaping govet since we can copy locks here as it is a test
+func (m MockIBCModule) OnTimeoutPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ relayer sdk.AccAddress,
+) error {
+ args := m.Called()
+ return args.Error(0)
+}
+
+func TestModule(t *testing.T) {
+ mockModule := &MockIBCModule{}
+ mockModule.On("OnChanOpenInit").Return(nil)
+ mockModule.On("OnChanOpenTry").Return("", nil)
+ mockModule.On("OnChanOpenAck").Return(nil)
+ mockModule.On("OnChanOpenConfirm").Return(nil)
+ mockModule.On("OnChanCloseInit").Return(nil)
+ mockModule.On("OnChanCloseConfirm").Return(nil)
+ mockModule.On("OnRecvPacket").Return(channeltypes.NewResultAcknowledgement([]byte("ack")))
+ mockModule.On("OnAcknowledgementPacket").Return(nil)
+ mockModule.On("OnTimeoutPacket").Return(nil)
+
+ module := NewModule(mockModule)
+
+ // mock calls for abstraction
+ _, err := module.OnChanOpenInit(sdk.Context{}, channeltypes.ORDERED, nil, transfertypes.PortID, "channel-0", &capabilitytypes.Capability{}, channeltypes.Counterparty{}, "")
+ require.NoError(t, err)
+ _, err = module.OnChanOpenTry(sdk.Context{}, channeltypes.ORDERED, nil, transfertypes.PortID, "channel-0", &capabilitytypes.Capability{}, channeltypes.Counterparty{}, "")
+ require.NoError(t, err)
+ err = module.OnChanOpenAck(sdk.Context{}, transfertypes.PortID, "channel-0", "channel-0", "")
+ require.NoError(t, err)
+ err = module.OnChanOpenConfirm(sdk.Context{}, transfertypes.PortID, "channel-0")
+ require.NoError(t, err)
+ err = module.OnChanCloseInit(sdk.Context{}, transfertypes.PortID, "channel-0")
+ require.NoError(t, err)
+ err = module.OnChanCloseConfirm(sdk.Context{}, transfertypes.PortID, "channel-0")
+ require.NoError(t, err)
+ ack := module.OnRecvPacket(sdk.Context{}, channeltypes.Packet{}, nil)
+ require.NotNil(t, ack)
+ err = module.OnAcknowledgementPacket(sdk.Context{}, channeltypes.Packet{}, nil, nil)
+ require.NoError(t, err)
+ err = module.OnTimeoutPacket(sdk.Context{}, channeltypes.Packet{}, nil)
+ require.NoError(t, err)
+}
diff --git a/ibc/testing/README.md b/ibc/testing/README.md
new file mode 100644
index 00000000..aa0917e9
--- /dev/null
+++ b/ibc/testing/README.md
@@ -0,0 +1,331 @@
+# IBC Testing Package
+
+## Components
+
+The testing package comprises of four parts constructed as a stack:
+
+- coordinator
+- chain
+- path
+- endpoint
+
+A coordinator sits at the highest level and contains all the chains which have been initialized.
+It also stores and updates the current global time. The time is manually incremented by a `TimeIncrement`.
+This allows all the chains to remain in synchrony avoiding the issue of a counterparty being perceived to
+be in the future. The coordinator also contains functions to do basic setup of clients, connections, and channels
+between two chains.
+
+A chain is an SDK application (as represented by an app.go file). Inside the chain is an `TestingApp` which allows
+the chain to simulate block production and transaction processing. The chain contains by default a single tendermint
+validator. A chain is used to process SDK messages.
+
+A path connects two channel endpoints. It contains all the information needed to relay between two endpoints.
+
+An endpoint represents a channel (and its associated client and connections) on some specific chain. It contains
+references to the chain it is on and the counterparty endpoint it is connected to. The endpoint contains functions
+to interact with initialization and updates of its associated clients, connections, and channels. It can send, receive,
+and acknowledge packets.
+
+In general:
+
+- endpoints are used for initialization and execution of IBC logic on one side of an IBC connection
+- paths are used to relay packets
+- chains are used to commit SDK messages
+- coordinator is used to setup a path between two chains
+
+## Integration
+
+To integrate the testing package into your tests, you will need to define:
+
+- a testing application
+- a function to initialize the testing application
+
+### TestingApp
+
+Your project will likely already have an application defined. This application
+will need to be extended to fulfill the `TestingApp` interface.
+
+```go
+type TestingApp interface {
+ abci.Application
+
+ // ibc-go additions
+ GetBaseApp() *baseapp.BaseApp
+ GetStakingKeeper() stakingkeeper.Keeper
+ GetIBCKeeper() *keeper.Keeper
+ GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper
+ GetTxConfig() client.TxConfig
+
+ // Implemented by SimApp
+ AppCodec() codec.Codec
+
+ // Implemented by BaseApp
+ LastCommitID() sdk.CommitID
+ LastBlockHeight() int64
+}
+```
+
+To begin, you will need to extend your application by adding the following functions:
+
+```go
+// TestingApp functions
+// Example using SimApp to implement TestingApp
+
+// GetBaseApp implements the TestingApp interface.
+func (app *SimApp) GetBaseApp() *baseapp.BaseApp {
+ return app.BaseApp
+}
+
+// GetStakingKeeper implements the TestingApp interface.
+func (app *SimApp) GetStakingKeeper() stakingkeeper.Keeper {
+ return app.StakingKeeper
+}
+
+// GetIBCKeeper implements the TestingApp interface.
+func (app *SimApp) GetIBCKeeper() *ibckeeper.Keeper {
+ return app.IBCKeeper
+}
+
+// GetScopedIBCKeeper implements the TestingApp interface.
+func (app *SimApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper {
+ return app.ScopedIBCKeeper
+}
+
+// GetTxConfig implements the TestingApp interface.
+func (app *SimApp) GetTxConfig() client.TxConfig {
+ return MakeTestEncodingConfig().TxConfig
+}
+
+```
+
+Your application may need to define `AppCodec()` if it does not already exist:
+
+```go
+// AppCodec returns SimApp's app codec.
+//
+// NOTE: This is solely to be used for testing purposes as it may be desirable
+// for modules to register their own custom testing types.
+func (app *SimApp) AppCodec() codec.Codec {
+ return app.appCodec
+}
+```
+
+It is assumed your application contains an embedded BaseApp and thus implements the abci.Application interface,
+`LastCommitID()` and `LastBlockHeight()`
+
+### Initialize TestingApp
+
+The testing package requires that you provide a function to initialize your TestingApp.
+This is how ibc-go implements the initialize function with its `SimApp`:
+
+```go
+func SetupTestingApp() (TestingApp, map[string]json.RawMessage) {
+ db := dbm.NewMemDB()
+ encCdc := simapp.MakeTestEncodingConfig()
+ app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{})
+ return app, simapp.NewDefaultGenesisState(encCdc.Marshaler)
+}
+```
+
+This function returns the TestingApp and the default genesis state used to initialize the testing app.
+
+Change the value of `DefaultTestingAppInit` to use your function:
+
+```go
+func init() {
+ ibctesting.DefaultTestingAppInit = MySetupTestingAppFunction
+}
+
+```
+
+## Example
+
+Here is an example of how to setup your testing environment in every package you are testing:
+
+```go
+// KeeperTestSuite is a testing suite to test keeper functions.
+type KeeperTestSuite struct {
+ suite.Suite
+
+ coordinator *ibctesting.Coordinator
+
+ // testing chains used for convenience and readability
+ chainA *ibctesting.TestChain
+ chainB *ibctesting.TestChain
+}
+
+// TestKeeperTestSuite runs all the tests within this package.
+func TestKeeperTestSuite(t *testing.T) {
+ suite.Run(t, new(KeeperTestSuite))
+}
+
+// SetupTest creates a coordinator with 2 test chains.
+func (suite *KeeperTestSuite) SetupTest() {
+ suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) // initializes 2 test chains
+ suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1)) // convenience and readability
+ suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2)) // convenience and readability
+}
+```
+
+To create interaction between chainA and chainB, we need to contruct a `Path` these chains will use.
+A path contains two endpoints, `EndpointA` and `EndpointB` (corresponding to the order of the chains passed
+into the `NewPath` function). A path is a pointer and its values will be filled in as necessary during the
+setup portion of testing.
+
+Endpoint Struct:
+
+```go
+// Endpoint is a which represents a channel endpoint and its associated
+// client and connections. It contains client, connection, and channel
+// configuration parameters. Endpoint functions will utilize the parameters
+// set in the configuration structs when executing IBC messages.
+type Endpoint struct {
+ Chain *TestChain
+ Counterparty *Endpoint
+ ClientID string
+ ConnectionID string
+ ChannelID string
+
+ ClientConfig ClientConfig
+ ConnectionConfig *ConnectionConfig
+ ChannelConfig *ChannelConfig
+}
+```
+
+The fields empty after `NewPath` is called are `ClientID`, `ConnectionID` and
+`ChannelID` as the clients, connections, and channels for these endpoints have not yet been created. The
+`ClientConfig`, `ConnectionConfig` and `ChannelConfig` contain all the necessary information for clients,
+connections, and channels to be initialized. If you would like to use endpoints which are initialized to
+use your Port IDs, you might add a helper function similar to the one found in transfer:
+
+```go
+func NewTransferPath(chainA, chainB *ibctesting.TestChain) *ibctesting.Path {
+ path := ibctesting.NewPath(chainA, chainB)
+ path.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort
+ path.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort
+
+ return path
+}
+
+```
+
+Path configurations should be set to the desired values before calling any `Setup` coordinator functions.
+
+To initialize the clients, connections, and channels for a path we can call the Setup functions of the coordinator:
+
+- Setup() -> setup clients, connections, channels
+- SetupClients() -> setup clients only
+- SetupConnections() -> setup clients and connections only
+
+Here is a basic example of the testing package being used to simulate IBC functionality:
+
+```go
+ path := ibctesting.NewPath(suite.chainA, suite.chainB) // clientID, connectionID, channelID empty
+ suite.coordinator.Setup(path) // clientID, connectionID, channelID filled
+ suite.Require().Equal("07-tendermint-0", path.EndpointA.ClientID)
+ suite.Require().Equal("connection-0", path.EndpointA.ClientID)
+ suite.Require().Equal("channel-0", path.EndpointA.ClientID)
+
+ // create packet 1
+ packet1 := NewPacket() // NewPacket would construct your packet
+
+ // send on endpointA
+ path.EndpointA.SendPacket(packet1)
+
+ // receive on endpointB
+ path.EndpointB.RecvPacket(packet1)
+
+ // acknowledge the receipt of the packet
+ path.EndpointA.AcknowledgePacket(packet1, ack)
+
+ // we can also relay
+ packet2 := NewPacket()
+
+ path.EndpointA.SendPacket(packet2)
+
+ path.Relay(packet2, expectedAck)
+
+ // if needed we can update our clients
+ path.EndpointB.UpdateClient()
+```
+
+### Transfer Testing Example
+
+If ICS 20 had its own simapp, its testing setup might include a `testing/app.go` file with the following contents:
+
+```go
+package transfertesting
+
+import (
+ "encoding/json"
+
+ "github.com/tendermint/tendermint/libs/log"
+ dbm "github.com/tendermint/tm-db"
+
+ "github.com/cosmos/ibc-go/v6/modules/apps/transfer/simapp"
+ ibctesting "github.com/cosmos/ibc-go/v6/testing"
+)
+
+func SetupTransferTestingApp() (ibctesting.TestingApp, map[string]json.RawMessage) {
+ db := dbm.NewMemDB()
+ encCdc := simapp.MakeTestEncodingConfig()
+ app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{})
+ return app, simapp.NewDefaultGenesisState(encCdc.Marshaler)
+}
+
+func init() {
+ ibctesting.DefaultTestingAppInit = SetupTransferTestingApp
+}
+
+func NewTransferPath(chainA, chainB *ibctesting.TestChain) *ibctesting.Path {
+ path := ibctesting.NewPath(chainA, chainB)
+ path.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort
+ path.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort
+
+ return path
+}
+
+func GetTransferSimApp(chain *ibctesting.TestChain) *simapp.SimApp {
+ app, ok := chain.App.(*simapp.SimApp)
+ if !ok {
+ panic("not transfer app")
+ }
+
+ return app
+}
+```
+
+### Middleware Testing
+
+When writing IBC applications acting as middleware, it might be desirable to test integration points.
+This can be done by wiring a middleware stack in the app.go file
+using existing applications as middleware and IBC base applications.
+The mock module may also be leveraged to act as a base application in the instance
+that such an application is not available for testing or causes dependency concerns.
+
+The mock IBC module contains a `MockIBCApp`. This struct contains a function field for every IBC App Module callback.
+Each of these functions can be individually set to mock expected behavior of a base application.
+
+For example, if one wanted to test that the base application cannot affect the outcome of the `OnChanOpenTry` callback,
+the mock module base application callback could be updated as such:
+
+```go
+ mockModule.IBCApp.OnChanOpenTry = func(ctx sdk.Context, portID, channelID, version string) error {
+ return fmt.Errorf("mock base app must not be called for OnChanOpenTry")
+ }
+```
+
+Using a mock module as a base application in a middleware stack may require adding the module to your `SimApp`.
+This is because IBC will route to the top level IBC module of a middleware stack, so a module which never
+sits at the top of middleware stack will need to be accessed via a public field in `SimApp`
+
+This might look like:
+
+```go
+ suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnChanOpenInit = func(ctx sdk.Context, order channeltypes.Order, connectionHops []string,
+ portID, channelID string, chanCap *capabilitytypes.Capability,
+ counterparty channeltypes.Counterparty, version string,
+ ) error {
+ return fmt.Errorf("mock ica auth fails")
+ }
+```
diff --git a/ibc/testing/app.go b/ibc/testing/app.go
new file mode 100644
index 00000000..25822383
--- /dev/null
+++ b/ibc/testing/app.go
@@ -0,0 +1,120 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ibctesting
+
+import (
+ "encoding/json"
+ "testing"
+ "time"
+
+ "cosmossdk.io/math"
+ abci "github.com/cometbft/cometbft/abci/types"
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ tmtypes "github.com/cometbft/cometbft/types"
+
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/stretchr/testify/require"
+
+ ibcgotesting "github.com/cosmos/ibc-go/v7/testing"
+
+ example_app "github.com/evmos/os/example_chain"
+ "github.com/evmos/os/testutil"
+ "github.com/evmos/os/types"
+)
+
+// DefaultTestingAppInit is a test helper function used to initialize an App
+// on the ibc testing pkg
+// need this design to make it compatible with the SetupTestinApp func on ibctesting pkg
+var DefaultTestingAppInit func(chainID string) func() (ibcgotesting.TestingApp, map[string]json.RawMessage) = example_app.SetupTestingApp
+
+// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts
+// that also act as delegators. For simplicity, each validator is bonded with a delegation
+// of one consensus engine unit (10^6) in the default token of the simapp from first genesis
+// account. A Nop logger is set in SimApp.
+func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, chainID string, balances ...banktypes.Balance) ibcgotesting.TestingApp {
+ app, genesisState := DefaultTestingAppInit(chainID)()
+ // set genesis accounts
+ authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
+ genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
+
+ validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
+ delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
+
+ bondAmt := sdk.TokensFromConsensusPower(1, types.PowerReduction)
+
+ for _, val := range valSet.Validators {
+ pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
+ require.NoError(t, err)
+ pkAny, err := codectypes.NewAnyWithValue(pk)
+ require.NoError(t, err)
+ validator := stakingtypes.Validator{
+ OperatorAddress: sdk.ValAddress(val.Address).String(),
+ ConsensusPubkey: pkAny,
+ Jailed: false,
+ Status: stakingtypes.Bonded,
+ Tokens: bondAmt,
+ DelegatorShares: math.LegacyOneDec(),
+ Description: stakingtypes.Description{},
+ UnbondingHeight: int64(0),
+ UnbondingTime: time.Unix(0, 0).UTC(),
+ Commission: stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()),
+ MinSelfDelegation: math.ZeroInt(),
+ }
+ validators = append(validators, validator)
+ delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), math.LegacyOneDec()))
+ }
+
+ // set validators and delegations
+ stakingParams := stakingtypes.DefaultParams()
+ // set bond demon to be aevmos
+ stakingParams.BondDenom = testutil.ExampleAttoDenom
+ stakingGenesis := stakingtypes.NewGenesisState(stakingParams, validators, delegations)
+ genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
+
+ totalSupply := sdk.NewCoins()
+ for _, b := range balances {
+ // add genesis acc tokens and delegated tokens to total supply
+ totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(testutil.ExampleAttoDenom, bondAmt))...)
+ }
+
+ // add bonded amount to bonded pool module account
+ balances = append(balances, banktypes.Balance{
+ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
+ Coins: sdk.Coins{sdk.NewCoin(testutil.ExampleAttoDenom, bondAmt)},
+ })
+
+ // update total supply
+ bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{})
+ genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
+
+ stateBytes, err := json.MarshalIndent(genesisState, "", " ")
+ require.NoError(t, err)
+
+ // init chain will set the validator set and initialize the genesis accounts
+ app.InitChain(
+ abci.RequestInitChain{
+ ChainId: chainID,
+ Validators: []abci.ValidatorUpdate{},
+ ConsensusParams: example_app.DefaultConsensusParams,
+ AppStateBytes: stateBytes,
+ },
+ )
+
+ // commit genesis changes
+ app.Commit()
+ app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{
+ ChainID: chainID,
+ Height: app.LastBlockHeight() + 1,
+ AppHash: app.LastCommitID().Hash,
+ ValidatorsHash: valSet.Hash(),
+ NextValidatorsHash: valSet.Hash(),
+ }})
+
+ return app
+}
diff --git a/ibc/testing/chain.go b/ibc/testing/chain.go
new file mode 100644
index 00000000..e01c76fa
--- /dev/null
+++ b/ibc/testing/chain.go
@@ -0,0 +1,117 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ibctesting
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ tmtypes "github.com/cometbft/cometbft/types"
+
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ ibcgotesting "github.com/cosmos/ibc-go/v7/testing"
+ "github.com/cosmos/ibc-go/v7/testing/mock"
+
+ "github.com/evmos/os/crypto/ethsecp256k1"
+ evmostypes "github.com/evmos/os/types"
+ "github.com/evmos/os/utils"
+)
+
+// ChainIDPrefix defines the default chain ID prefix for Evmos test chains
+var (
+ ChainIDPrefix = utils.MainnetChainID + "-"
+ ChainIDSuffix = ""
+)
+
+func init() {
+ ibcgotesting.ChainIDPrefix = ChainIDPrefix
+ ibcgotesting.ChainIDSuffix = ChainIDSuffix
+}
+
+// NewTestChain initializes a new TestChain instance with a single validator set using a
+// generated private key. It also creates a sender account to be used for delivering transactions.
+//
+// The first block height is committed to state in order to allow for client creations on
+// counterparty chains. The TestChain will return with a block height starting at 2.
+//
+// Time management is handled by the Coordinator in order to ensure synchrony between chains.
+// Each update of any chain increments the block header time for all chains by 5 seconds.
+func NewTestChain(t *testing.T, coord *ibcgotesting.Coordinator, chainID string) *ibcgotesting.TestChain {
+ // generate validator private/public key
+ privVal := mock.NewPV()
+ pubKey, err := privVal.GetPubKey()
+ require.NoError(t, err)
+
+ // create validator set with single validator
+ validator := tmtypes.NewValidator(pubKey, 1)
+ valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
+ signers := make(map[string]tmtypes.PrivValidator)
+ signers[pubKey.Address().String()] = privVal
+
+ // generate genesis account
+ senderPrivKey, err := ethsecp256k1.GenerateKey()
+ if err != nil {
+ panic(err)
+ }
+
+ baseAcc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
+
+ amount := sdk.TokensFromConsensusPower(1, evmostypes.PowerReduction)
+
+ balance := banktypes.Balance{
+ Address: baseAcc.GetAddress().String(),
+ Coins: sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, amount)),
+ }
+
+ app := SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{baseAcc}, chainID, balance)
+
+ // create current header and call begin block
+ header := tmproto.Header{
+ ChainID: chainID,
+ Height: 1,
+ Time: coord.CurrentTime.UTC(),
+ }
+
+ txConfig := app.GetTxConfig()
+
+ // create an account to send transactions from
+ chain := &ibcgotesting.TestChain{
+ T: t,
+ Coordinator: coord,
+ ChainID: chainID,
+ App: app,
+ CurrentHeader: header,
+ QueryServer: app.GetIBCKeeper(),
+ TxConfig: txConfig,
+ Codec: app.AppCodec(),
+ Vals: valSet,
+ Signers: signers,
+ SenderPrivKey: senderPrivKey,
+ SenderAccount: baseAcc,
+ NextVals: valSet,
+ }
+
+ coord.CommitBlock(chain)
+
+ return chain
+}
+
+func NewTransferPath(chainA, chainB *ibcgotesting.TestChain) *Path {
+ path := NewPath(chainA, chainB)
+ path.EndpointA.ChannelConfig.PortID = ibcgotesting.TransferPort
+ path.EndpointB.ChannelConfig.PortID = ibcgotesting.TransferPort
+
+ path.EndpointA.ChannelConfig.Order = channeltypes.UNORDERED
+ path.EndpointB.ChannelConfig.Order = channeltypes.UNORDERED
+ path.EndpointA.ChannelConfig.Version = "ics20-1"
+ path.EndpointB.ChannelConfig.Version = "ics20-1"
+
+ return path
+}
diff --git a/ibc/testing/coordinator.go b/ibc/testing/coordinator.go
new file mode 100644
index 00000000..c5f728d6
--- /dev/null
+++ b/ibc/testing/coordinator.go
@@ -0,0 +1,202 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ibctesting
+
+import (
+ "math/rand"
+ "testing"
+ "time"
+
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ "github.com/cosmos/cosmos-sdk/client"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ example_app "github.com/evmos/os/example_chain"
+ "github.com/stretchr/testify/require"
+)
+
+const DefaultFeeAmt = int64(150_000_000_000_000_000) // 0.15 EVMOS
+
+var globalStartTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC)
+
+// NewCoordinator initializes Coordinator with N EVM TestChain's (Evmos apps) and M Cosmos chains (Simulation Apps)
+func NewCoordinator(t *testing.T, nEVMChains, mCosmosChains int) *ibctesting.Coordinator {
+ chains := make(map[string]*ibctesting.TestChain)
+ coord := &ibctesting.Coordinator{
+ T: t,
+ CurrentTime: globalStartTime,
+ }
+
+ for i := 1; i <= nEVMChains; i++ {
+ chainID := ibctesting.GetChainID(i)
+ // setup EVM chains
+ ibctesting.DefaultTestingAppInit = DefaultTestingAppInit(chainID)
+ chains[chainID] = NewTestChain(t, coord, chainID)
+ }
+
+ // setup Cosmos chains
+ ibctesting.DefaultTestingAppInit = ibctesting.SetupTestingApp
+
+ for j := 1 + nEVMChains; j <= nEVMChains+mCosmosChains; j++ {
+ chainID := ibctesting.GetChainID(j)
+ chains[chainID] = ibctesting.NewTestChain(t, coord, chainID)
+ }
+
+ coord.Chains = chains
+
+ return coord
+}
+
+// SetupPath constructs a TM client, connection, and channel on both chains provided. It will
+// fail if any error occurs. The clientID's, TestConnections, and TestChannels are returned
+// for both chains. The channels created are connected to the ibc-transfer application.
+func SetupPath(coord *ibctesting.Coordinator, path *Path) {
+ SetupConnections(coord, path)
+
+ // channels can also be referenced through the returned connections
+ CreateChannels(coord, path)
+}
+
+// SetupConnections is a helper function to create clients and the appropriate
+// connections on both the source and counterparty chain. It assumes the caller does not
+// anticipate any errors.
+func SetupConnections(coord *ibctesting.Coordinator, path *Path) {
+ SetupClients(coord, path)
+
+ CreateConnections(coord, path)
+}
+
+// CreateChannel constructs and executes channel handshake messages in order to create
+// OPEN channels on chainA and chainB. The function expects the channels to be successfully
+// opened otherwise testing will fail.
+func CreateChannels(coord *ibctesting.Coordinator, path *Path) {
+ err := path.EndpointA.ChanOpenInit()
+ require.NoError(coord.T, err)
+
+ err = path.EndpointB.ChanOpenTry()
+ require.NoError(coord.T, err)
+
+ err = path.EndpointA.ChanOpenAck()
+ require.NoError(coord.T, err)
+
+ err = path.EndpointB.ChanOpenConfirm()
+ require.NoError(coord.T, err)
+
+ // ensure counterparty is up to date
+ err = path.EndpointA.UpdateClient()
+ require.NoError(coord.T, err)
+}
+
+// CreateConnection constructs and executes connection handshake messages in order to create
+// OPEN channels on chainA and chainB. The connection information of for chainA and chainB
+// are returned within a TestConnection struct. The function expects the connections to be
+// successfully opened otherwise testing will fail.
+func CreateConnections(coord *ibctesting.Coordinator, path *Path) {
+ err := path.EndpointA.ConnOpenInit()
+ require.NoError(coord.T, err)
+
+ err = path.EndpointB.ConnOpenTry()
+ require.NoError(coord.T, err)
+
+ err = path.EndpointA.ConnOpenAck()
+ require.NoError(coord.T, err)
+
+ err = path.EndpointB.ConnOpenConfirm()
+ require.NoError(coord.T, err)
+
+ // ensure counterparty is up to date
+ err = path.EndpointA.UpdateClient()
+ require.NoError(coord.T, err)
+}
+
+// SetupClients is a helper function to create clients on both chains. It assumes the
+// caller does not anticipate any errors.
+func SetupClients(coord *ibctesting.Coordinator, path *Path) {
+ err := path.EndpointA.CreateClient()
+ require.NoError(coord.T, err)
+
+ err = path.EndpointB.CreateClient()
+ require.NoError(coord.T, err)
+}
+
+func SendMsgs(chain *ibctesting.TestChain, feeAmt int64, msgs ...sdk.Msg) (*sdk.Result, error) {
+ var bondDenom string
+ // ensure the chain has the latest time
+ chain.Coordinator.UpdateTimeForChain(chain)
+
+ if evmosChain, ok := chain.App.(*example_app.Evmos); ok {
+ bondDenom = evmosChain.StakingKeeper.BondDenom(chain.GetContext())
+ } else {
+ bondDenom = chain.GetSimApp().StakingKeeper.BondDenom(chain.GetContext())
+ }
+
+ fee := sdk.Coins{sdk.NewInt64Coin(bondDenom, feeAmt)}
+ _, r, err := SignAndDeliver(
+ chain.T,
+ chain.TxConfig,
+ chain.App.GetBaseApp(),
+ msgs,
+ fee,
+ chain.ChainID,
+ []uint64{chain.SenderAccount.GetAccountNumber()},
+ []uint64{chain.SenderAccount.GetSequence()},
+ true, chain.SenderPrivKey,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ // NextBlock calls app.Commit()
+ chain.NextBlock()
+
+ // increment sequence for successful transaction execution
+ err = chain.SenderAccount.SetSequence(chain.SenderAccount.GetSequence() + 1)
+ if err != nil {
+ return nil, err
+ }
+
+ chain.Coordinator.IncrementTime()
+
+ return r, nil
+}
+
+// SignAndDeliver signs and delivers a transaction. No simulation occurs as the
+// ibc testing package causes checkState and deliverState to diverge in block time.
+//
+// CONTRACT: BeginBlock must be called before this function.
+// Is a customization of IBC-go function that allows to modify the fee denom and amount
+// IBC-go implementation: https://github.com/cosmos/ibc-go/blob/d34cef7e075dda1a24a0a3e9b6d3eff406cc606c/testing/simapp/test_helpers.go#L332-L364
+func SignAndDeliver(
+ t *testing.T, txCfg client.TxConfig, app *baseapp.BaseApp, msgs []sdk.Msg,
+ fee sdk.Coins,
+ chainID string, accNums, accSeqs []uint64, expPass bool, priv ...cryptotypes.PrivKey,
+) (sdk.GasInfo, *sdk.Result, error) {
+ tx, err := simtestutil.GenSignedMockTx(
+ rand.New(rand.NewSource(time.Now().UnixNano())), //nolint:gosec
+ txCfg,
+ msgs,
+ fee,
+ simtestutil.DefaultGenTxGas,
+ chainID,
+ accNums,
+ accSeqs,
+ priv...,
+ )
+ require.NoError(t, err)
+
+ // Simulate a sending a transaction
+ gInfo, res, err := app.SimDeliver(txCfg.TxEncoder(), tx)
+
+ if expPass {
+ require.NoError(t, err)
+ require.NotNil(t, res)
+ } else {
+ require.Error(t, err)
+ require.Nil(t, res)
+ }
+
+ return gInfo, res, err
+}
diff --git a/ibc/testing/endpoint.go b/ibc/testing/endpoint.go
new file mode 100644
index 00000000..0953ad19
--- /dev/null
+++ b/ibc/testing/endpoint.go
@@ -0,0 +1,611 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package ibctesting
+
+import (
+ "fmt"
+ "time"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/stretchr/testify/require"
+
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types"
+ host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
+ "github.com/cosmos/ibc-go/v7/modules/core/exported"
+ ibclightclient "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+)
+
+// Endpoint is a which represents a channel endpoint and its associated
+// client and connections. It contains client, connection, and channel
+// configuration parameters. Endpoint functions will utilize the parameters
+// set in the configuration structs when executing IBC messages.
+type Endpoint struct {
+ Chain *ibctesting.TestChain
+ Counterparty *Endpoint
+ ClientID string
+ ConnectionID string
+ ChannelID string
+
+ ClientConfig ibctesting.ClientConfig
+ ConnectionConfig *ibctesting.ConnectionConfig
+ ChannelConfig *ibctesting.ChannelConfig
+}
+
+// NewEndpoint constructs a new endpoint without the counterparty.
+// CONTRACT: the counterparty endpoint must be set by the caller.
+func NewEndpoint(
+ chain *ibctesting.TestChain, clientConfig ibctesting.ClientConfig,
+ connectionConfig *ibctesting.ConnectionConfig, channelConfig *ibctesting.ChannelConfig,
+) *Endpoint {
+ return &Endpoint{
+ Chain: chain,
+ ClientConfig: clientConfig,
+ ConnectionConfig: connectionConfig,
+ ChannelConfig: channelConfig,
+ }
+}
+
+// NewDefaultEndpoint constructs a new endpoint using default values.
+// CONTRACT: the counterparty endpoitn must be set by the caller.
+func NewDefaultEndpoint(chain *ibctesting.TestChain) *Endpoint {
+ return &Endpoint{
+ Chain: chain,
+ ClientConfig: ibctesting.NewTendermintConfig(),
+ ConnectionConfig: ibctesting.NewConnectionConfig(),
+ ChannelConfig: ibctesting.NewChannelConfig(),
+ }
+}
+
+// QueryProof queries proof associated with this endpoint using the latest client state
+// height on the counterparty chain.
+func (endpoint *Endpoint) QueryProof(key []byte) ([]byte, clienttypes.Height) {
+ // obtain the counterparty client representing the chain associated with the endpoint
+ clientState := endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID)
+
+ // query proof on the counterparty using the latest height of the IBC client
+ return endpoint.QueryProofAtHeight(key, clientState.GetLatestHeight().GetRevisionHeight())
+}
+
+// QueryProofAtHeight queries proof associated with this endpoint using the proof height
+// provided
+func (endpoint *Endpoint) QueryProofAtHeight(key []byte, height uint64) ([]byte, clienttypes.Height) {
+ // query proof on the counterparty using the latest height of the IBC client
+ return endpoint.Chain.QueryProofAtHeight(key, int64(height))
+}
+
+// CreateClient creates an IBC client on the endpoint. It will update the
+// clientID for the endpoint if the message is successfully executed.
+// NOTE: a solo machine client will be created with an empty diversifier.
+func (endpoint *Endpoint) CreateClient() (err error) {
+ // ensure counterparty has committed state
+ endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain)
+
+ var (
+ clientState exported.ClientState
+ consensusState exported.ConsensusState
+ )
+
+ switch endpoint.ClientConfig.GetClientType() {
+ case exported.Tendermint:
+ tmConfig, ok := endpoint.ClientConfig.(*ibctesting.TendermintConfig)
+ require.True(endpoint.Chain.T, ok)
+
+ height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height)
+ clientState = ibclightclient.NewClientState(
+ endpoint.Counterparty.Chain.ChainID, tmConfig.TrustLevel, tmConfig.TrustingPeriod, tmConfig.UnbondingPeriod, tmConfig.MaxClockDrift,
+ height, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath,
+ )
+ consensusState = endpoint.Counterparty.Chain.LastHeader.ConsensusState()
+ case exported.Solomachine:
+
+ default:
+ err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType())
+ }
+
+ if err != nil {
+ return err
+ }
+
+ require.NotNil(
+ endpoint.Chain.T, endpoint.Chain.SenderAccount,
+ fmt.Sprintf("expected sender account on chain with ID %q not to be nil", endpoint.Chain.ChainID),
+ )
+
+ zeroTimestamp := uint64(time.Time{}.UnixNano())
+ require.NotEqual(
+ endpoint.Chain.T, consensusState.GetTimestamp(), zeroTimestamp,
+ "current timestamp on the last header is the zero time; it might be necessary to commit blocks with the IBC coordinator",
+ )
+
+ msg, err := clienttypes.NewMsgCreateClient(
+ clientState, consensusState, endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ require.NoError(endpoint.Chain.T, err)
+ require.NoError(endpoint.Chain.T, msg.ValidateBasic(), "failed to validate create client msg")
+
+ res, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ if err != nil {
+ return err
+ }
+
+ endpoint.ClientID, err = ibctesting.ParseClientIDFromEvents(res.GetEvents())
+ require.NoError(endpoint.Chain.T, err)
+
+ return nil
+}
+
+// UpdateClient updates the IBC client associated with the endpoint.
+func (endpoint *Endpoint) UpdateClient() (err error) {
+ // ensure counterparty has committed state
+ endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain)
+
+ var header *ibclightclient.Header
+
+ switch endpoint.ClientConfig.GetClientType() {
+ case exported.Tendermint:
+ header, err = endpoint.Chain.ConstructUpdateTMClientHeader(endpoint.Counterparty.Chain, endpoint.ClientID)
+
+ default:
+ err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType())
+ }
+
+ if err != nil {
+ return err
+ }
+
+ msg, err := clienttypes.NewMsgUpdateClient(
+ endpoint.ClientID, header,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ require.NoError(endpoint.Chain.T, err)
+
+ _, err = SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ return err
+}
+
+// ConnOpenInit will construct and execute a MsgConnectionOpenInit on the associated endpoint.
+func (endpoint *Endpoint) ConnOpenInit() error {
+ msg := connectiontypes.NewMsgConnectionOpenInit(
+ endpoint.ClientID,
+ endpoint.Counterparty.ClientID,
+ endpoint.Counterparty.Chain.GetPrefix(), ibctesting.DefaultOpenInitVersion, endpoint.ConnectionConfig.DelayPeriod,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ res, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ if err != nil {
+ return err
+ }
+
+ endpoint.ConnectionID, err = ibctesting.ParseConnectionIDFromEvents(res.GetEvents())
+ require.NoError(endpoint.Chain.T, err)
+
+ return nil
+}
+
+// ConnOpenTry will construct and execute a MsgConnectionOpenTry on the associated endpoint.
+func (endpoint *Endpoint) ConnOpenTry() error {
+ err := endpoint.UpdateClient()
+ require.NoError(endpoint.Chain.T, err)
+
+ counterpartyClient, proofClient, proofConsensus, consensusHeight, proofInit, proofHeight := endpoint.QueryConnectionHandshakeProof()
+
+ msg := connectiontypes.NewMsgConnectionOpenTry(
+ endpoint.ClientID, endpoint.Counterparty.ConnectionID, endpoint.Counterparty.ClientID,
+ counterpartyClient, endpoint.Counterparty.Chain.GetPrefix(), []*connectiontypes.Version{ibctesting.ConnectionVersion}, endpoint.ConnectionConfig.DelayPeriod,
+ proofInit, proofClient, proofConsensus,
+ proofHeight, consensusHeight,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ res, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ if err != nil {
+ return err
+ }
+
+ if endpoint.ConnectionID == "" {
+ endpoint.ConnectionID, err = ibctesting.ParseConnectionIDFromEvents(res.GetEvents())
+ require.NoError(endpoint.Chain.T, err)
+ }
+
+ return nil
+}
+
+// ConnOpenAck will construct and execute a MsgConnectionOpenAck on the associated endpoint.
+func (endpoint *Endpoint) ConnOpenAck() error {
+ err := endpoint.UpdateClient()
+ require.NoError(endpoint.Chain.T, err)
+
+ counterpartyClient, proofClient, proofConsensus, consensusHeight, proofTry, proofHeight := endpoint.QueryConnectionHandshakeProof()
+
+ msg := connectiontypes.NewMsgConnectionOpenAck(
+ endpoint.ConnectionID, endpoint.Counterparty.ConnectionID, counterpartyClient, // testing doesn't use flexible selection
+ proofTry, proofClient, proofConsensus,
+ proofHeight, consensusHeight,
+ ibctesting.ConnectionVersion,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ _, err = SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ return err
+}
+
+// ConnOpenConfirm will construct and execute a MsgConnectionOpenConfirm on the associated endpoint.
+func (endpoint *Endpoint) ConnOpenConfirm() error {
+ err := endpoint.UpdateClient()
+ require.NoError(endpoint.Chain.T, err)
+
+ connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID)
+ proof, height := endpoint.Counterparty.Chain.QueryProof(connectionKey)
+
+ msg := connectiontypes.NewMsgConnectionOpenConfirm(
+ endpoint.ConnectionID,
+ proof, height,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ _, err = SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ return err
+}
+
+// QueryConnectionHandshakeProof returns all the proofs necessary to execute OpenTry or Open Ack of
+// the connection handshakes. It returns the counterparty client state, proof of the counterparty
+// client state, proof of the counterparty consensus state, the consensus state height, proof of
+// the counterparty connection, and the proof height for all the proofs returned.
+func (endpoint *Endpoint) QueryConnectionHandshakeProof() (
+ clientState exported.ClientState, proofClient,
+ proofConsensus []byte, consensusHeight clienttypes.Height,
+ proofConnection []byte, proofHeight clienttypes.Height,
+) {
+ // obtain the client state on the counterparty chain
+ clientState = endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID)
+
+ // query proof for the client state on the counterparty
+ clientKey := host.FullClientStateKey(endpoint.Counterparty.ClientID)
+ proofClient, proofHeight = endpoint.Counterparty.QueryProof(clientKey)
+
+ consensusHeight = clientState.GetLatestHeight().(clienttypes.Height)
+
+ // query proof for the consensus state on the counterparty
+ consensusKey := host.FullConsensusStateKey(endpoint.Counterparty.ClientID, consensusHeight)
+ proofConsensus, _ = endpoint.Counterparty.QueryProofAtHeight(consensusKey, proofHeight.GetRevisionHeight())
+
+ // query proof for the connection on the counterparty
+ connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID)
+ proofConnection, _ = endpoint.Counterparty.QueryProofAtHeight(connectionKey, proofHeight.GetRevisionHeight())
+
+ return
+}
+
+// ChanOpenInit will construct and execute a MsgChannelOpenInit on the associated endpoint.
+func (endpoint *Endpoint) ChanOpenInit() error {
+ msg := channeltypes.NewMsgChannelOpenInit(
+ endpoint.ChannelConfig.PortID,
+ endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID},
+ endpoint.Counterparty.ChannelConfig.PortID,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ res, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ if err != nil {
+ return err
+ }
+
+ endpoint.ChannelID, err = ibctesting.ParseChannelIDFromEvents(res.GetEvents())
+ require.NoError(endpoint.Chain.T, err)
+
+ // update version to selected app version
+ // NOTE: this update must be performed after SendMsgs()
+ endpoint.ChannelConfig.Version = endpoint.GetChannel().Version
+
+ return nil
+}
+
+// ChanOpenTry will construct and execute a MsgChannelOpenTry on the associated endpoint.
+func (endpoint *Endpoint) ChanOpenTry() error {
+ err := endpoint.UpdateClient()
+ require.NoError(endpoint.Chain.T, err)
+
+ channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID)
+ proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey)
+
+ msg := channeltypes.NewMsgChannelOpenTry(
+ endpoint.ChannelConfig.PortID,
+ endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID},
+ endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version,
+ proof, height,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ res, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ if err != nil {
+ return err
+ }
+
+ if endpoint.ChannelID == "" {
+ endpoint.ChannelID, err = ibctesting.ParseChannelIDFromEvents(res.GetEvents())
+ require.NoError(endpoint.Chain.T, err)
+ }
+
+ // update version to selected app version
+ // NOTE: this update must be performed after the endpoint channelID is set
+ endpoint.ChannelConfig.Version = endpoint.GetChannel().Version
+
+ return nil
+}
+
+// ChanOpenAck will construct and execute a MsgChannelOpenAck on the associated endpoint.
+func (endpoint *Endpoint) ChanOpenAck() error {
+ err := endpoint.UpdateClient()
+ require.NoError(endpoint.Chain.T, err)
+
+ channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID)
+ proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey)
+
+ msg := channeltypes.NewMsgChannelOpenAck(
+ endpoint.ChannelConfig.PortID, endpoint.ChannelID,
+ endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, // testing doesn't use flexible selection
+ proof, height,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+
+ if _, err = SendMsgs(endpoint.Chain, DefaultFeeAmt, msg); err != nil {
+ return err
+ }
+
+ endpoint.ChannelConfig.Version = endpoint.GetChannel().Version
+
+ return nil
+}
+
+// ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm on the associated endpoint.
+func (endpoint *Endpoint) ChanOpenConfirm() error {
+ err := endpoint.UpdateClient()
+ require.NoError(endpoint.Chain.T, err)
+
+ channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID)
+ proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey)
+
+ msg := channeltypes.NewMsgChannelOpenConfirm(
+ endpoint.ChannelConfig.PortID, endpoint.ChannelID,
+ proof, height,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ _, err = SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ return err
+}
+
+// ChanCloseInit will construct and execute a MsgChannelCloseInit on the associated endpoint.
+//
+// NOTE: does not work with ibc-transfer module
+func (endpoint *Endpoint) ChanCloseInit() error {
+ msg := channeltypes.NewMsgChannelCloseInit(
+ endpoint.ChannelConfig.PortID, endpoint.ChannelID,
+ endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+ _, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, msg)
+ return err
+}
+
+// SendPacket sends a packet through the channel keeper using the associated endpoint
+// The counterparty client is updated so proofs can be sent to the counterparty chain.
+// The packet sequence generated for the packet to be sent is returned. An error
+// is returned if one occurs.
+func (endpoint *Endpoint) SendPacket(
+ timeoutHeight clienttypes.Height,
+ timeoutTimestamp uint64,
+ data []byte,
+) (uint64, error) {
+ channelCap := endpoint.Chain.GetChannelCapability(endpoint.ChannelConfig.PortID, endpoint.ChannelID)
+
+ // no need to send message, acting as a module
+ sequence, err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SendPacket(endpoint.Chain.GetContext(), channelCap, endpoint.ChannelConfig.PortID, endpoint.ChannelID, timeoutHeight, timeoutTimestamp, data)
+ if err != nil {
+ return 0, err
+ }
+
+ // commit changes since no message was sent
+ endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain)
+
+ err = endpoint.Counterparty.UpdateClient()
+ if err != nil {
+ return 0, err
+ }
+
+ return sequence, nil
+}
+
+// RecvPacket receives a packet on the associated endpoint.
+// The counterparty client is updated.
+func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error {
+ _, err := endpoint.RecvPacketWithResult(packet)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// RecvPacketWithResult receives a packet on the associated endpoint and the result
+// of the transaction is returned. The counterparty client is updated.
+func (endpoint *Endpoint) RecvPacketWithResult(packet channeltypes.Packet) (*sdk.Result, error) {
+ // get proof of packet commitment on source
+ packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
+ proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey)
+
+ recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String())
+
+ // receive on counterparty and update source client
+ res, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, recvMsg)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := endpoint.Counterparty.UpdateClient(); err != nil {
+ return nil, err
+ }
+
+ return res, nil
+}
+
+// WriteAcknowledgement writes an acknowledgement on the channel associated with the endpoint.
+// The counterparty client is updated.
+func (endpoint *Endpoint) WriteAcknowledgement(ack exported.Acknowledgement, packet exported.PacketI) error {
+ channelCap := endpoint.Chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel())
+
+ // no need to send message, acting as a handler
+ err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(endpoint.Chain.GetContext(), channelCap, packet, ack)
+ if err != nil {
+ return err
+ }
+
+ // commit changes since no message was sent
+ endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain)
+
+ return endpoint.Counterparty.UpdateClient()
+}
+
+// AcknowledgePacket sends a MsgAcknowledgement to the channel associated with the endpoint.
+func (endpoint *Endpoint) AcknowledgePacket(packet channeltypes.Packet, ack []byte) error {
+ // get proof of acknowledgement on counterparty
+ packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
+ proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey)
+
+ ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String())
+
+ _, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, ackMsg)
+ return err
+}
+
+// TimeoutPacket sends a MsgTimeout to the channel associated with the endpoint.
+func (endpoint *Endpoint) TimeoutPacket(packet channeltypes.Packet) error {
+ // get proof for timeout based on channel order
+ var packetKey []byte
+
+ switch endpoint.ChannelConfig.Order {
+ case channeltypes.ORDERED:
+ packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
+ case channeltypes.UNORDERED:
+ packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
+ default:
+ return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order)
+ }
+
+ proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey)
+ nextSeqRecv, found := endpoint.Counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID)
+ require.True(endpoint.Chain.T, found)
+
+ timeoutMsg := channeltypes.NewMsgTimeout(
+ packet, nextSeqRecv,
+ proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+
+ _, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, timeoutMsg)
+ return err
+}
+
+// TimeoutOnClose sends a MsgTimeoutOnClose to the channel associated with the endpoint.
+func (endpoint *Endpoint) TimeoutOnClose(packet channeltypes.Packet) error {
+ // get proof for timeout based on channel order
+ var packetKey []byte
+
+ switch endpoint.ChannelConfig.Order {
+ case channeltypes.ORDERED:
+ packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
+ case channeltypes.UNORDERED:
+ packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
+ default:
+ return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order)
+ }
+
+ proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey)
+
+ channelKey := host.ChannelKey(packet.GetDestPort(), packet.GetDestChannel())
+ proofClosed, _ := endpoint.Counterparty.QueryProof(channelKey)
+
+ nextSeqRecv, found := endpoint.Counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID)
+ require.True(endpoint.Chain.T, found)
+
+ timeoutOnCloseMsg := channeltypes.NewMsgTimeoutOnClose(
+ packet, nextSeqRecv,
+ proof, proofClosed, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(),
+ )
+
+ _, err := SendMsgs(endpoint.Chain, DefaultFeeAmt, timeoutOnCloseMsg)
+ return err
+}
+
+// SetChannelClosed sets a channel state to CLOSED.
+func (endpoint *Endpoint) SetChannelClosed() error {
+ channel := endpoint.GetChannel()
+
+ channel.State = channeltypes.CLOSED
+ endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel)
+
+ endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain)
+
+ return endpoint.Counterparty.UpdateClient()
+}
+
+// GetClientState retrieves the Client State for this endpoint. The
+// client state is expected to exist otherwise testing will fail.
+func (endpoint *Endpoint) GetClientState() exported.ClientState {
+ return endpoint.Chain.GetClientState(endpoint.ClientID)
+}
+
+// SetClientState sets the client state for this endpoint.
+func (endpoint *Endpoint) SetClientState(clientState exported.ClientState) {
+ endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientState(endpoint.Chain.GetContext(), endpoint.ClientID, clientState)
+}
+
+// GetConsensusState retrieves the Consensus State for this endpoint at the provided height.
+// The consensus state is expected to exist otherwise testing will fail.
+func (endpoint *Endpoint) GetConsensusState(height exported.Height) exported.ConsensusState {
+ consensusState, found := endpoint.Chain.GetConsensusState(endpoint.ClientID, height)
+ require.True(endpoint.Chain.T, found)
+
+ return consensusState
+}
+
+// SetConsensusState sets the consensus state for this endpoint.
+func (endpoint *Endpoint) SetConsensusState(consensusState exported.ConsensusState, height exported.Height) {
+ endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(endpoint.Chain.GetContext(), endpoint.ClientID, height, consensusState)
+}
+
+// GetConnection retrieves an IBC Connection for the endpoint. The
+// connection is expected to exist otherwise testing will fail.
+func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd {
+ connection, found := endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.GetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID)
+ require.True(endpoint.Chain.T, found)
+
+ return connection
+}
+
+// SetConnection sets the connection for this endpoint.
+func (endpoint *Endpoint) SetConnection(connection connectiontypes.ConnectionEnd) {
+ endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.SetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID, connection)
+}
+
+// GetChannel retrieves an IBC Channel for the endpoint. The channel
+// is expected to exist otherwise testing will fail.
+func (endpoint *Endpoint) GetChannel() channeltypes.Channel {
+ channel, found := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID)
+ require.True(endpoint.Chain.T, found)
+
+ return channel
+}
+
+// SetChannel sets the channel for this endpoint.
+func (endpoint *Endpoint) SetChannel(channel channeltypes.Channel) {
+ endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel)
+}
+
+// QueryClientStateProof performs and abci query for a client stat associated
+// with this endpoint and returns the ClientState along with the proof.
+func (endpoint *Endpoint) QueryClientStateProof() (exported.ClientState, []byte) {
+ // retrieve client state to provide proof for
+ clientState := endpoint.GetClientState()
+
+ clientKey := host.FullClientStateKey(endpoint.ClientID)
+ proofClient, _ := endpoint.QueryProof(clientKey)
+
+ return clientState, proofClient
+}
diff --git a/ibc/testing/path.go b/ibc/testing/path.go
new file mode 100644
index 00000000..29221557
--- /dev/null
+++ b/ibc/testing/path.go
@@ -0,0 +1,88 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package ibctesting
+
+import (
+ "bytes"
+ "fmt"
+
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+)
+
+// Path contains two endpoints representing two chains connected over IBC
+type Path struct {
+ EndpointA *Endpoint
+ EndpointB *Endpoint
+}
+
+// NewPath constructs an endpoint for each chain using the default values
+// for the endpoints. Each endpoint is updated to have a pointer to the
+// counterparty endpoint.
+func NewPath(chainA, chainB *ibctesting.TestChain) *Path {
+ endpointA := NewDefaultEndpoint(chainA)
+ endpointB := NewDefaultEndpoint(chainB)
+
+ endpointA.Counterparty = endpointB
+ endpointB.Counterparty = endpointA
+
+ return &Path{
+ EndpointA: endpointA,
+ EndpointB: endpointB,
+ }
+}
+
+// SetChannelOrdered sets the channel order for both endpoints to ORDERED.
+func (path *Path) SetChannelOrdered() {
+ path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED
+ path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED
+}
+
+// RelayPacket attempts to relay the packet first on EndpointA and then on EndpointB
+// if EndpointA does not contain a packet commitment for that packet. An error is returned
+// if a relay step fails or the packet commitment does not exist on either endpoint.
+func (path *Path) RelayPacket(packet channeltypes.Packet) error {
+ pc := path.EndpointA.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointA.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
+ if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointA.Chain.App.AppCodec(), packet)) {
+
+ // packet found, relay from A to B
+ if err := path.EndpointB.UpdateClient(); err != nil {
+ return err
+ }
+
+ res, err := path.EndpointB.RecvPacketWithResult(packet)
+ if err != nil {
+ return err
+ }
+
+ ack, err := ibctesting.ParseAckFromEvents(res.GetEvents())
+ if err != nil {
+ return err
+ }
+
+ return path.EndpointA.AcknowledgePacket(packet, ack)
+ }
+
+ pc = path.EndpointB.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointB.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
+ if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointB.Chain.App.AppCodec(), packet)) {
+
+ // packet found, relay B to A
+ if err := path.EndpointA.UpdateClient(); err != nil {
+ return err
+ }
+
+ res, err := path.EndpointA.RecvPacketWithResult(packet)
+ if err != nil {
+ return err
+ }
+
+ ack, err := ibctesting.ParseAckFromEvents(res.GetEvents())
+ if err != nil {
+ return err
+ }
+
+ return path.EndpointB.AcknowledgePacket(packet, ack)
+ }
+
+ return fmt.Errorf("packet commitment does not exist on either endpoint for provided packet")
+}
diff --git a/ibc/utils.go b/ibc/utils.go
new file mode 100644
index 00000000..e892f9d8
--- /dev/null
+++ b/ibc/utils.go
@@ -0,0 +1,184 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ibc
+
+import (
+ "strings"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ transferkeeper "github.com/evmos/os/x/ibc/transfer/keeper"
+
+ "github.com/evmos/os/utils"
+)
+
+// GetTransferSenderRecipient returns the sender and recipient sdk.AccAddresses
+// from an ICS20 FungibleTokenPacketData as well as the original sender bech32
+// address from the packet data. This function fails if:
+// - the packet data is not FungibleTokenPacketData
+// - sender address is invalid
+// - recipient address is invalid
+func GetTransferSenderRecipient(data transfertypes.FungibleTokenPacketData) (
+ sender, recipient sdk.AccAddress,
+ senderBech32, recipientBech32 string,
+ err error,
+) {
+ // validate the sender bech32 address from the counterparty chain
+ // and change the bech32 human readable prefix (HRP) of the sender to `evmos`
+ sender, err = utils.GetEvmosAddressFromBech32(data.Sender)
+ if err != nil {
+ return nil, nil, "", "", errorsmod.Wrap(err, "invalid sender")
+ }
+
+ // validate the recipient bech32 address from the counterparty chain
+ // and change the bech32 human readable prefix (HRP) of the recipient to `evmos`
+ recipient, err = utils.GetEvmosAddressFromBech32(data.Receiver)
+ if err != nil {
+ return nil, nil, "", "", errorsmod.Wrap(err, "invalid recipient")
+ }
+
+ return sender, recipient, data.Sender, data.Receiver, nil
+}
+
+// GetTransferAmount returns the amount from an ICS20 FungibleTokenPacketData as a string.
+func GetTransferAmount(packet channeltypes.Packet) (string, error) {
+ // unmarshal packet data to obtain the sender and recipient
+ var data transfertypes.FungibleTokenPacketData
+ if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil {
+ return "", errorsmod.Wrapf(errortypes.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data")
+ }
+
+ if data.Amount == "" {
+ return "", errorsmod.Wrapf(errortypes.ErrInvalidCoins, "empty amount")
+ }
+
+ if _, ok := math.NewIntFromString(data.Amount); !ok {
+ return "", errorsmod.Wrapf(errortypes.ErrInvalidCoins, "invalid amount")
+ }
+
+ return data.Amount, nil
+}
+
+// GetReceivedCoin returns the transferred coin from an ICS20 FungibleTokenPacketData
+// as seen from the destination chain.
+// If the receiving chain is the source chain of the tokens, it removes the prefix
+// path added by source (i.e sender) chain to the denom. Otherwise, it adds the
+// prefix path from the destination chain to the denom.
+func GetReceivedCoin(srcPort, srcChannel, dstPort, dstChannel, rawDenom, rawAmt string) sdk.Coin {
+ // NOTE: Denom and amount are already validated
+ amount, _ := math.NewIntFromString(rawAmt)
+
+ if transfertypes.ReceiverChainIsSource(srcPort, srcChannel, rawDenom) {
+ // remove prefix added by sender chain
+ voucherPrefix := transfertypes.GetDenomPrefix(srcPort, srcChannel)
+ unprefixedDenom := rawDenom[len(voucherPrefix):]
+
+ // coin denomination used in sending from the escrow address
+ // The denomination used to send the coins is either the native denom or the hash of the path
+ // if the denomination is not native.
+ denomTrace := transfertypes.ParseDenomTrace(unprefixedDenom)
+ denom := denomTrace.IBCDenom()
+
+ return sdk.Coin{
+ Denom: denom,
+ Amount: amount,
+ }
+ }
+
+ // since SendPacket did not prefix the denomination, we must prefix denomination here
+ sourcePrefix := transfertypes.GetDenomPrefix(dstPort, dstChannel)
+ // NOTE: sourcePrefix contains the trailing "/"
+ prefixedDenom := sourcePrefix + rawDenom
+
+ // construct the denomination trace from the full raw denomination
+ denomTrace := transfertypes.ParseDenomTrace(prefixedDenom)
+ voucherDenom := denomTrace.IBCDenom()
+
+ return sdk.Coin{
+ Denom: voucherDenom,
+ Amount: amount,
+ }
+}
+
+// GetSentCoin returns the sent coin from an ICS20 FungibleTokenPacketData.
+func GetSentCoin(rawDenom, rawAmt string) sdk.Coin {
+ // NOTE: Denom and amount are already validated
+ amount, _ := math.NewIntFromString(rawAmt)
+ trace := transfertypes.ParseDenomTrace(rawDenom)
+
+ return sdk.Coin{
+ Denom: trace.IBCDenom(),
+ Amount: amount,
+ }
+}
+
+// IsBaseDenomFromSourceChain checks if the given denom has only made a single hop.
+// It returns true if the denomination is single-hop, false otherwise.
+// This function expects to receive a string representing a token like
+// the denom string of the `FungibleTokenPacketData` of a received packet.
+// If the coin denom starts with `factory/` then it is a token factory coin, and we should not convert it
+// NOTE: Check https://docs.osmosis.zone/osmosis-core/modules/tokenfactory/ for more information
+func IsBaseDenomFromSourceChain(rawDenom string) bool {
+ // Parse the raw denomination to get its DenomTrace
+ denomTrace := transfertypes.ParseDenomTrace(rawDenom)
+
+ // Split the denom of the DenomTrace into its components
+ denomComponents := strings.Split(denomTrace.BaseDenom, "/")
+
+ // Each hop in the path is represented by a pair of port and channel ids
+ // If the number of components in the path is equal to or more than 2, it has hopped multiple chains
+ return len(denomTrace.Path) == 0 && len(denomComponents) == 1
+}
+
+// GetDenomTrace returns the denomination trace from the corresponding IBC denomination. If the
+// denomination is not an IBC voucher or the trace is not found, it returns an error.
+func GetDenomTrace(
+ transferKeeper transferkeeper.Keeper,
+ ctx sdk.Context,
+ denom string,
+) (transfertypes.DenomTrace, error) {
+ if !strings.HasPrefix(denom, "ibc/") {
+ return transfertypes.DenomTrace{}, errorsmod.Wrapf(ErrNoIBCVoucherDenom, denom)
+ }
+
+ hash, err := transfertypes.ParseHexHash(denom[4:])
+ if err != nil {
+ return transfertypes.DenomTrace{}, err
+ }
+
+ denomTrace, found := transferKeeper.GetDenomTrace(ctx, hash)
+ if !found {
+ return transfertypes.DenomTrace{}, ErrDenomTraceNotFound
+ }
+
+ return denomTrace, nil
+}
+
+// DeriveDecimalsFromDenom returns the number of decimals of an IBC coin
+// depending on the prefix of the base denomination
+func DeriveDecimalsFromDenom(baseDenom string) (uint8, error) {
+ var decimals uint8
+ if len(baseDenom) == 0 {
+ return decimals, errorsmod.Wrapf(ErrInvalidBaseDenom, "Base denom cannot be an empty string")
+ }
+
+ switch baseDenom[0] {
+ case 'u': // micro (u) -> 6 decimals
+ decimals = 6
+ case 'a': // atto (a) -> 18 decimals
+ decimals = 18
+ default:
+ return decimals, errorsmod.Wrapf(
+ ErrInvalidBaseDenom,
+ "Should be either micro ('u[...]') or atto ('a[...]'); got: %q",
+ baseDenom,
+ )
+ }
+ return decimals, nil
+}
diff --git a/ibc/utils_test.go b/ibc/utils_test.go
new file mode 100644
index 00000000..35c4d95b
--- /dev/null
+++ b/ibc/utils_test.go
@@ -0,0 +1,368 @@
+package ibc
+
+import (
+ "testing"
+
+ "cosmossdk.io/math"
+ "github.com/stretchr/testify/require"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ teststypes "github.com/evmos/os/types/tests"
+)
+
+func init() {
+ cfg := sdk.GetConfig()
+ cfg.SetBech32PrefixForAccount("evmos", "evmospub")
+}
+
+func TestGetTransferSenderRecipient(t *testing.T) {
+ testCases := []struct {
+ name string
+ data transfertypes.FungibleTokenPacketData
+ expSender string
+ expRecipient string
+ expError bool
+ }{
+ {
+ name: "empty FungibleTokenPacketData",
+ data: transfertypes.FungibleTokenPacketData{},
+ expSender: "",
+ expRecipient: "",
+ expError: true,
+ },
+ {
+ name: "invalid sender",
+ data: transfertypes.FungibleTokenPacketData{
+ Sender: "cosmos1",
+ Receiver: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ Amount: "123456",
+ },
+ expSender: "",
+ expRecipient: "",
+ expError: true,
+ },
+ {
+ name: "invalid recipient",
+ data: transfertypes.FungibleTokenPacketData{
+ Sender: "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc",
+ Receiver: "evmos1",
+ Amount: "123456",
+ },
+ expSender: "",
+ expRecipient: "",
+ expError: true,
+ },
+ {
+ name: "valid - cosmos sender, evmos recipient",
+ data: transfertypes.FungibleTokenPacketData{
+ Sender: "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc",
+ Receiver: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ Amount: "123456",
+ },
+ expSender: "evmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueuafmxps",
+ expRecipient: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ expError: false,
+ },
+ {
+ name: "valid - evmos sender, cosmos recipient",
+ data: transfertypes.FungibleTokenPacketData{
+ Sender: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ Receiver: "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc",
+ Amount: "123456",
+ },
+ expSender: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ expRecipient: "evmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueuafmxps",
+ expError: false,
+ },
+ {
+ name: "valid - osmosis sender, evmos recipient",
+ data: transfertypes.FungibleTokenPacketData{
+ Sender: "osmo1qql8ag4cluz6r4dz28p3w00dnc9w8ueuhnecd2",
+ Receiver: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ Amount: "123456",
+ },
+ expSender: "evmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueuafmxps",
+ expRecipient: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ expError: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ sender, recipient, _, _, err := GetTransferSenderRecipient(tc.data)
+ if tc.expError {
+ require.Error(t, err, tc.name)
+ } else {
+ require.NoError(t, err, tc.name)
+ require.Equal(t, tc.expSender, sender.String())
+ require.Equal(t, tc.expRecipient, recipient.String())
+ }
+ }
+}
+
+func TestGetTransferAmount(t *testing.T) {
+ testCases := []struct {
+ name string
+ packet channeltypes.Packet
+ expAmount string
+ expError bool
+ }{
+ {
+ name: "empty packet",
+ packet: channeltypes.Packet{},
+ expAmount: "",
+ expError: true,
+ },
+ {
+ name: "invalid packet data",
+ packet: channeltypes.Packet{Data: ibctesting.MockFailPacketData},
+ expAmount: "",
+ expError: true,
+ },
+ {
+ name: "invalid amount - empty",
+ packet: channeltypes.Packet{
+ Data: transfertypes.ModuleCdc.MustMarshalJSON(
+ &transfertypes.FungibleTokenPacketData{
+ Sender: "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc",
+ Receiver: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ Amount: "",
+ },
+ ),
+ },
+ expAmount: "",
+ expError: true,
+ },
+ {
+ name: "invalid amount - non-int",
+ packet: channeltypes.Packet{
+ Data: transfertypes.ModuleCdc.MustMarshalJSON(
+ &transfertypes.FungibleTokenPacketData{
+ Sender: "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc",
+ Receiver: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ Amount: "test",
+ },
+ ),
+ },
+ expAmount: "test",
+ expError: true,
+ },
+ {
+ name: "valid",
+ packet: channeltypes.Packet{
+ Data: transfertypes.ModuleCdc.MustMarshalJSON(
+ &transfertypes.FungibleTokenPacketData{
+ Sender: "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc",
+ Receiver: "evmos1x2w87cvt5mqjncav4lxy8yfreynn273xn5335v",
+ Amount: "10000",
+ },
+ ),
+ },
+ expAmount: "10000",
+ expError: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ amt, err := GetTransferAmount(tc.packet)
+ if tc.expError {
+ require.Error(t, err, tc.name)
+ } else {
+ require.NoError(t, err, tc.name)
+ require.Equal(t, tc.expAmount, amt)
+ }
+ }
+}
+
+func TestGetReceivedCoin(t *testing.T) {
+ testCases := []struct {
+ name string
+ srcPort string
+ srcChannel string
+ dstPort string
+ dstChannel string
+ rawDenom string
+ rawAmount string
+ expCoin sdk.Coin
+ }{
+ {
+ "transfer unwrapped coin to destination which is not its source",
+ "transfer",
+ "channel-0",
+ "transfer",
+ "channel-0",
+ "uosmo",
+ "10",
+ sdk.Coin{Denom: teststypes.UosmoIbcdenom, Amount: math.NewInt(10)},
+ },
+ {
+ "transfer ibc wrapped coin to destination which is its source",
+ "transfer",
+ "channel-0",
+ "transfer",
+ "channel-0",
+ "transfer/channel-0/aevmos",
+ "10",
+ sdk.Coin{Denom: "aevmos", Amount: math.NewInt(10)},
+ },
+ {
+ "transfer 2x ibc wrapped coin to destination which is its source",
+ "transfer",
+ "channel-0",
+ "transfer",
+ "channel-2",
+ "transfer/channel-0/transfer/channel-1/uatom",
+ "10",
+ sdk.Coin{Denom: teststypes.UatomIbcdenom, Amount: math.NewInt(10)},
+ },
+ {
+ "transfer ibc wrapped coin to destination which is not its source",
+ "transfer",
+ "channel-0",
+ "transfer",
+ "channel-0",
+ "transfer/channel-1/uatom",
+ "10",
+ sdk.Coin{Denom: teststypes.UatomOsmoIbcdenom, Amount: math.NewInt(10)},
+ },
+ }
+
+ for _, tc := range testCases {
+ coin := GetReceivedCoin(tc.srcPort, tc.srcChannel, tc.dstPort, tc.dstChannel, tc.rawDenom, tc.rawAmount)
+ require.Equal(t, tc.expCoin, coin)
+ }
+}
+
+func TestGetSentCoin(t *testing.T) {
+ testCases := []struct {
+ name string
+ rawDenom string
+ rawAmount string
+ expCoin sdk.Coin
+ }{
+ {
+ "get unwrapped aevmos coin",
+ "aevmos",
+ "10",
+ sdk.Coin{Denom: "aevmos", Amount: math.NewInt(10)},
+ },
+ {
+ "get ibc wrapped aevmos coin",
+ "transfer/channel-0/aevmos",
+ "10",
+ sdk.Coin{Denom: teststypes.AevmosIbcdenom, Amount: math.NewInt(10)},
+ },
+ {
+ "get ibc wrapped uosmo coin",
+ "transfer/channel-0/uosmo",
+ "10",
+ sdk.Coin{Denom: teststypes.UosmoIbcdenom, Amount: math.NewInt(10)},
+ },
+ {
+ "get ibc wrapped uatom coin",
+ "transfer/channel-1/uatom",
+ "10",
+ sdk.Coin{Denom: teststypes.UatomIbcdenom, Amount: math.NewInt(10)},
+ },
+ {
+ "get 2x ibc wrapped uatom coin",
+ "transfer/channel-0/transfer/channel-1/uatom",
+ "10",
+ sdk.Coin{Denom: teststypes.UatomOsmoIbcdenom, Amount: math.NewInt(10)},
+ },
+ }
+
+ for _, tc := range testCases {
+ coin := GetSentCoin(tc.rawDenom, tc.rawAmount)
+ require.Equal(t, tc.expCoin, coin)
+ }
+}
+
+func TestDeriveDecimalsFromDenom(t *testing.T) {
+ testCases := []struct {
+ name string
+ baseDenom string
+ expDec uint8
+ expFail bool
+ expErrMsg string
+ }{
+ {
+ name: "fail: empty string",
+ baseDenom: "",
+ expDec: 0,
+ expFail: true,
+ expErrMsg: "Base denom cannot be an empty string",
+ },
+ {
+ name: "fail: invalid prefix",
+ baseDenom: "nevmos",
+ expDec: 0,
+ expFail: true,
+ expErrMsg: "Should be either micro ('u[...]') or atto ('a[...]'); got: \"nevmos\"",
+ },
+ {
+ name: "success: micro 'u' prefix",
+ baseDenom: "uevmos",
+ expDec: 6,
+ expFail: false,
+ expErrMsg: "",
+ },
+ {
+ name: "success: atto 'a' prefix",
+ baseDenom: "aevmos",
+ expDec: 18,
+ expFail: false,
+ expErrMsg: "",
+ },
+ }
+
+ for _, tc := range testCases {
+ dec, err := DeriveDecimalsFromDenom(tc.baseDenom)
+ if tc.expFail {
+ require.Error(t, err, tc.expErrMsg)
+ require.Contains(t, err.Error(), tc.expErrMsg)
+ } else {
+ require.NoError(t, err)
+ }
+ require.Equal(t, tc.expDec, dec)
+ }
+}
+
+func TestIsBaseDenomFromSourceChain(t *testing.T) {
+ tests := []struct {
+ name string
+ denom string
+ expected bool
+ }{
+ {
+ name: "one hop",
+ denom: "transfer/channel-0/uatom",
+ expected: false,
+ },
+ {
+ name: "no hop with factory prefix",
+ denom: "factory/owner/uatom",
+ expected: false,
+ },
+ {
+ name: "multi hop",
+ denom: "transfer/channel-0/transfer/channel-1/uatom",
+ expected: false,
+ },
+ {
+ name: "no hop",
+ denom: "uatom",
+ expected: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := IsBaseDenomFromSourceChain(tt.denom)
+ require.Equal(t, tt.expected, result)
+ })
+ }
+}
diff --git a/precompiles/authorization/AuthorizationI.sol b/precompiles/authorization/AuthorizationI.sol
new file mode 100644
index 00000000..ec9e0772
--- /dev/null
+++ b/precompiles/authorization/AuthorizationI.sol
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+/// @author Evmos Team
+/// @title Authorization Interface
+/// @dev The interface through which solidity contracts will interact with smart contract approvals.
+interface AuthorizationI {
+ /// @dev Approves a list of Cosmos or IBC transactions with a specific amount of tokens.
+ /// @param grantee The contract address which will have an authorization to spend the origin funds.
+ /// @param amount The amount of tokens to be spent.
+ /// @param methods The message type URLs of the methods to approve.
+ /// @return approved Boolean value to indicate if the approval was successful.
+ function approve(
+ address grantee,
+ uint256 amount,
+ string[] calldata methods
+ ) external returns (bool approved);
+
+ /// @dev Revokes a list of Cosmos transactions.
+ /// @param grantee The contract address which will have its allowances revoked.
+ /// @param methods The message type URLs of the methods to revoke.
+ /// @return revoked Boolean value to indicate if the revocation was successful.
+ function revoke(
+ address grantee,
+ string[] calldata methods
+ ) external returns (bool revoked);
+
+ /// @dev Increase the allowance of a given spender by a specific amount of tokens for IBC
+ /// transfer methods or staking.
+ /// @param grantee The contract address which allowance will be increased.
+ /// @param amount The amount of tokens to be spent.
+ /// @param methods The message type URLs of the methods to approve.
+ /// @return approved Boolean value to indicate if the approval was successful.
+ function increaseAllowance(
+ address grantee,
+ uint256 amount,
+ string[] calldata methods
+ ) external returns (bool approved);
+
+ /// @dev Decreases the allowance of a given spender by a specific amount of tokens for IBC
+ /// transfer methods or staking.
+ /// @param grantee The contract address which allowance will be decreased.
+ /// @param amount The amount of tokens to be spent.
+ /// @param methods The message type URLs of the methods to approve.
+ /// @return approved Boolean value to indicate if the approval was successful.
+ function decreaseAllowance(
+ address grantee,
+ uint256 amount,
+ string[] calldata methods
+ ) external returns (bool approved);
+
+ /// @dev Returns the remaining number of tokens that spender will be allowed to spend
+ /// on behalf of the owner through IBC transfer methods or staking. This is zero by default.
+ /// @param grantee The contract address which has the Authorization.
+ /// @param granter The account address that grants an Authorization.
+ /// @param method The message type URL of the methods for which the approval should be queried.
+ /// @return remaining The remaining number of tokens available to be spent.
+ function allowance(
+ address grantee,
+ address granter,
+ string calldata method
+ ) external view returns (uint256 remaining);
+
+ /// @dev This event is emitted when the allowance of a granter is set by a call to the approve method.
+ /// The value field specifies the new allowance and the methods field holds the information for which methods
+ /// the approval was set.
+ /// @param grantee The contract address that received an Authorization from the granter.
+ /// @param granter The account address that granted an Authorization.
+ /// @param methods The message type URLs of the methods for which the approval is set.
+ /// @param value The amount of tokens approved to be spent.
+ event Approval(
+ address indexed grantee,
+ address indexed granter,
+ string[] methods,
+ uint256 value
+ );
+
+ /// @dev This event is emitted when an owner revokes a spender's allowance.
+ /// @param grantee The contract address that has it's Authorization revoked.
+ /// @param granter The account address of the granter.
+ /// @param methods The message type URLs of the methods for which the approval is set.
+ event Revocation(
+ address indexed grantee,
+ address indexed granter,
+ string[] methods
+ );
+
+ /// @dev This event is emitted when the allowance of a granter is changed by a call to the decrease or increase
+ /// allowance method. The values field specifies the new allowances and the methods field holds the
+ /// information for which methods the approval was set.
+ /// @param grantee The contract address for which the allowance changed.
+ /// @param granter The account address of the granter.
+ /// @param methods The message type URLs of the methods for which the approval is set.
+ /// @param values The amounts of tokens approved to be spent.
+ event AllowanceChange(
+ address indexed grantee,
+ address indexed granter,
+ string[] methods,
+ uint256[] values
+ );
+}
diff --git a/precompiles/authorization/IICS20Authorization.sol b/precompiles/authorization/IICS20Authorization.sol
new file mode 100644
index 00000000..7b391486
--- /dev/null
+++ b/precompiles/authorization/IICS20Authorization.sol
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../common/Types.sol";
+
+/// @author Evmos Team
+/// @title Authorization Interface
+/// @dev The interface through which solidity contracts will interact with smart contract approvals.
+interface IICS20Authorization {
+ /// @dev Emitted when an ICS-20 transfer authorization is granted.
+ /// @param grantee The address of the grantee.
+ /// @param granter The address of the granter.
+ /// @param allocations An array of Allocation authorized with this grant.
+ event IBCTransferAuthorization(
+ address indexed grantee,
+ address indexed granter,
+ ICS20Allocation[] allocations
+ );
+
+ /// @dev Approves IBC transfer with a specific amount of tokens.
+ /// @param grantee The address for which the transfer authorization is granted.
+ /// @param allocations An array of Allocation for the authorization.
+ function approve(address grantee, ICS20Allocation[] calldata allocations) external returns (bool approved);
+
+ /// @dev Revokes IBC transfer authorization for a specific grantee.
+ /// @param grantee The address for which the transfer authorization will be revoked.
+ function revoke(address grantee) external returns (bool revoked);
+
+ /// @dev Increase the allowance of a given grantee by a specific amount of tokens for IBC transfer methods.
+ /// @param grantee The address of the contract that is allowed to spend the granter's tokens.
+ /// @param sourcePort The port on which the packet will be sent.
+ /// @param sourceChannel The channel by which the packet will be sent.
+ /// @param denom The denomination of the Coin to be transferred to the receiver.
+ /// @param amount The increase in amount of tokens that can be spent.
+ /// @return approved Is true if the operation ran successfully.
+ function increaseAllowance(
+ address grantee,
+ string calldata sourcePort,
+ string calldata sourceChannel,
+ string calldata denom,
+ uint256 amount
+ ) external returns (bool approved);
+
+ /// @dev Decreases the allowance of a given grantee by a specific amount of tokens for IBC transfer methods.
+ /// @param grantee The address of the contract that is allowed to spend the granter's tokens.
+ /// @param sourcePort The port on which the packet will be sent.
+ /// @param sourceChannel The channel by which the packet will be sent.
+ /// @param denom The denomination of the Coin to be transferred to the receiver.
+ /// @param amount The amount by which the spendable tokens are decreased.
+ /// @return approved Is true if the operation ran successfully.
+ function decreaseAllowance(
+ address grantee,
+ string calldata sourcePort,
+ string calldata sourceChannel,
+ string calldata denom,
+ uint256 amount
+ ) external returns (bool approved);
+
+ /// @dev Returns the remaining number of tokens that a grantee
+ /// will be allowed to spend on behalf of granter through
+ /// IBC transfers. This is an empty array by default.
+ /// @param grantee The address of the contract that is allowed to spend the granter's tokens.
+ /// @param granter The address of the account able to transfer the tokens.
+ /// @return allocations The remaining amounts allowed to be spent for
+ /// corresponding source port and channel.
+ function allowance(
+ address grantee,
+ address granter
+ ) external view returns (ICS20Allocation[] memory allocations);
+}
\ No newline at end of file
diff --git a/precompiles/authorization/errors.go b/precompiles/authorization/errors.go
new file mode 100644
index 00000000..257751b5
--- /dev/null
+++ b/precompiles/authorization/errors.go
@@ -0,0 +1,24 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package authorization
+
+const (
+ // ErrAuthzDoesNotExistOrExpired is raised when the authorization does not exist.
+ ErrAuthzDoesNotExistOrExpired = "authorization to %s for address %s does not exist or is expired"
+ // ErrEmptyMethods is raised when the given methods array is empty.
+ ErrEmptyMethods = "no methods defined; expected at least one message type url"
+ // ErrEmptyStringInMethods is raised when the given methods array contains an empty string.
+ ErrEmptyStringInMethods = "empty string found in methods array; expected no empty strings to be passed; got: %v"
+ // ErrExceededAllowance is raised when the amount exceeds the set allowance.
+ ErrExceededAllowance = "amount %s greater than allowed limit %s"
+ // ErrInvalidGranter is raised when the granter address is not valid.
+ ErrInvalidGranter = "invalid granter address: %v"
+ // ErrInvalidGrantee is raised when the grantee address is not valid.
+ ErrInvalidGrantee = "invalid grantee address: %v"
+ // ErrInvalidMethods is raised when the given methods cannot be unpacked.
+ ErrInvalidMethods = "invalid methods defined; expected an array of strings; got: %v"
+ // ErrInvalidMethod is raised when the given method cannot be unpacked.
+ ErrInvalidMethod = "invalid method defined; expected a string; got: %v"
+ // ErrAuthzNotAccepted is raised when the authorization is not accepted.
+ ErrAuthzNotAccepted = "authorization to %s for address %s is not accepted"
+)
diff --git a/precompiles/authorization/events.go b/precompiles/authorization/events.go
new file mode 100644
index 00000000..6876b942
--- /dev/null
+++ b/precompiles/authorization/events.go
@@ -0,0 +1,127 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package authorization
+
+import (
+ "fmt"
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // EventTypeIBCTransferAuthorization defines the event type for the ICS20 TransferAuthorization transaction.
+ EventTypeIBCTransferAuthorization = "IBCTransferAuthorization" //#nosec G101 -- no hardcoded credentials here
+)
+
+// EventApproval is the event emitted on a successful Approve transaction.
+type EventApproval struct {
+ Grantee common.Address
+ Granter common.Address
+ Value *big.Int
+ Methods []string
+}
+
+// EventAllowanceChange is the event emitted on successful IncreaseAllowance or DecreaseAllowance transactions.
+type EventAllowanceChange struct {
+ Grantee common.Address
+ Granter common.Address
+ Values []*big.Int
+ Methods []string
+}
+
+// EventRevocation is the event emitted on a successful Revoke transaction.
+type EventRevocation struct {
+ Grantee common.Address
+ Granter common.Address
+ TypeUrls []string
+}
+
+// EmitRevocationEvent creates a new approval event emitted on a Revoke transaction.
+func EmitRevocationEvent(args cmn.EmitEventArgs) error {
+ // Prepare the event topics
+ revocationEvent, ok := args.EventData.(EventRevocation)
+ if !ok {
+ return fmt.Errorf("invalid Event type, expecting EventRevocation but received %T", args.EventData)
+ }
+ // Prepare the event topics
+ event := args.ContractEvents[EventTypeRevocation]
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(revocationEvent.Grantee)
+ if err != nil {
+ return err
+ }
+
+ topics[2], err = cmn.MakeTopic(revocationEvent.Granter)
+ if err != nil {
+ return err
+ }
+
+ // Pack the arguments to be used as the Data field
+ arguments := abi.Arguments{event.Inputs[2]}
+ packed, err := arguments.Pack(revocationEvent.TypeUrls)
+ if err != nil {
+ return err
+ }
+
+ args.StateDB.AddLog(ðtypes.Log{
+ Address: args.ContractAddr,
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(args.Ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitIBCTransferAuthorizationEvent creates a new IBC transfer authorization event emitted on a TransferAuthorization transaction.
+func EmitIBCTransferAuthorizationEvent(
+ event abi.Event,
+ ctx sdk.Context,
+ stateDB vm.StateDB,
+ precompileAddr, granteeAddr, granterAddr common.Address,
+ allocations []cmn.ICS20Allocation,
+) error {
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(granteeAddr)
+ if err != nil {
+ return err
+ }
+
+ topics[2], err = cmn.MakeTopic(granterAddr)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data: sourcePort, sourceChannel, denom, amount
+ arguments := abi.Arguments{event.Inputs[2]}
+ packed, err := arguments.Pack(allocations)
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: precompileAddr,
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
diff --git a/precompiles/authorization/types.go b/precompiles/authorization/types.go
new file mode 100644
index 00000000..8890a95e
--- /dev/null
+++ b/precompiles/authorization/types.go
@@ -0,0 +1,202 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package authorization
+
+import (
+ "fmt"
+ "math/big"
+ "slices"
+ "time"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+const (
+ // ApproveMethod defines the ABI method name for the authorization Approve transaction.
+ ApproveMethod = "approve"
+ // RevokeMethod defines the ABI method name for the authorization Revoke transaction.
+ RevokeMethod = "revoke"
+ // DecreaseAllowanceMethod defines the ABI method name for the DecreaseAllowance transaction.
+ DecreaseAllowanceMethod = "decreaseAllowance"
+ // IncreaseAllowanceMethod defines the ABI method name for the IncreaseAllowance transaction.
+ IncreaseAllowanceMethod = "increaseAllowance"
+ // AllowanceMethod defines the ABI method name for the Allowance query.
+ AllowanceMethod = "allowance"
+ // EventTypeApproval defines the event type for the distribution Approve transaction.
+ EventTypeApproval = "Approval"
+ // EventTypeRevocation defines the event type for the distribution Revoke transaction.
+ EventTypeRevocation = "Revocation"
+ // EventTypeAllowanceChange defines the event type for the staking IncreaseAllowance or
+ // DecreaseAllowance transactions.
+ EventTypeAllowanceChange = "AllowanceChange"
+)
+
+// CheckApprovalArgs checks the arguments passed to the approve function as well as
+// the functions to change the allowance. This is refactored into one function as
+// they all take in the same arguments.
+func CheckApprovalArgs(args []interface{}, denom string) (common.Address, *sdk.Coin, []string, error) {
+ if len(args) != 3 {
+ return common.Address{}, nil, nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
+ }
+ // TODO: (optional) new Go 1.20 functionality would allow to check all args and then return a joint list of errors.
+ // This would improve UX as everything wrong with the input would be returned at once.
+
+ grantee, ok := args[0].(common.Address)
+ if !ok || grantee == (common.Address{}) {
+ return common.Address{}, nil, nil, fmt.Errorf(ErrInvalidGranter, args[0])
+ }
+
+ var coin *sdk.Coin
+ amount, ok := args[1].(*big.Int)
+ if ok {
+ if amount.Sign() == -1 {
+ return common.Address{}, nil, nil, fmt.Errorf("amount cannot be negative: %v", args[1])
+ }
+ // If amount is not MaxUint256, create a coin with the given amount
+ if amount.Cmp(abi.MaxUint256) != 0 {
+ coin = &sdk.Coin{
+ Denom: denom,
+ Amount: math.NewIntFromBigInt(amount),
+ }
+ }
+ }
+
+ typeURLs, ok := args[2].([]string)
+ if !ok {
+ return common.Address{}, nil, nil, fmt.Errorf(ErrInvalidMethods, args[2])
+ }
+ if len(typeURLs) == 0 {
+ return common.Address{}, nil, nil, fmt.Errorf(ErrEmptyMethods)
+ }
+ if slices.Contains(typeURLs, "") {
+ return common.Address{}, nil, nil, fmt.Errorf(ErrEmptyStringInMethods, typeURLs)
+ }
+ // TODO: check if the typeURLs are valid? e.g. with a regex pattern?
+
+ return grantee, coin, typeURLs, nil
+}
+
+// CheckRevokeArgs checks the arguments passed to the revoke function.
+func CheckRevokeArgs(args []interface{}) (common.Address, []string, error) {
+ if len(args) != 2 {
+ return common.Address{}, nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ // TODO: (optional) new Go 1.20 functionality would allow to check all args and then return a joint list of errors.
+ // This would improve UX as everything wrong with the input would be returned at once.
+
+ granteeAddr, ok := args[0].(common.Address)
+ if !ok || granteeAddr == (common.Address{}) {
+ return common.Address{}, nil, fmt.Errorf(ErrInvalidGranter, args[0])
+ }
+
+ typeURLs, err := validateMsgTypes(args[1])
+ if err != nil {
+ return common.Address{}, nil, err
+ }
+ // TODO: check if the typeURLs are valid? e.g. with a regex pattern?
+ // Check - ENG-1632 on Linear
+
+ return granteeAddr, typeURLs, nil
+}
+
+// CheckAllowanceArgs checks the arguments for the Allowance function.
+func CheckAllowanceArgs(args []interface{}) (common.Address, common.Address, string, error) {
+ if len(args) != 3 {
+ return common.Address{}, common.Address{}, "", fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
+ }
+
+ granteeAddr, ok := args[0].(common.Address)
+ if !ok || granteeAddr == (common.Address{}) {
+ return common.Address{}, common.Address{}, "", fmt.Errorf(ErrInvalidGrantee, args[0])
+ }
+
+ granterAddr, ok := args[1].(common.Address)
+ if !ok || granterAddr == (common.Address{}) {
+ return common.Address{}, common.Address{}, "", fmt.Errorf(ErrInvalidGranter, args[1])
+ }
+
+ typeURL, ok := args[2].(string)
+ if !ok {
+ return common.Address{}, common.Address{}, "", fmt.Errorf(ErrInvalidMethod, args[2])
+ }
+ if typeURL == "" {
+ return common.Address{}, common.Address{}, "", fmt.Errorf("empty method defined; expected a valid message type url")
+ }
+ // TODO: check if the typeURL is valid? e.g. with a regex pattern?
+
+ return granteeAddr, granterAddr, typeURL, nil
+}
+
+// CheckAuthzExists checks if the authorization exists for the given granter and
+// returns the authorization and its expiration time.
+//
+// NOTE: It's not necessary to check for expiration of the authorization, because that is already handled
+// by the GetAuthorization method. If a grant is expired, it will return nil.
+func CheckAuthzExists(
+ ctx sdk.Context,
+ authzKeeper authzkeeper.Keeper,
+ grantee, granter common.Address,
+ msgURL string,
+) (authz.Authorization, *time.Time, error) {
+ msgAuthz, expiration := authzKeeper.GetAuthorization(ctx, grantee.Bytes(), granter.Bytes(), msgURL)
+ if msgAuthz == nil {
+ return nil, nil, fmt.Errorf(ErrAuthzDoesNotExistOrExpired, msgURL, grantee)
+ }
+ return msgAuthz, expiration, nil
+}
+
+// CheckAuthzAndAllowanceForGranter checks if the authorization exists and is not expired for the
+// given spender and the allowance is not exceeded.
+// If the authorization has a limit, checks that the provided amount does not exceed the current limit.
+// Returns an error if the authorization does not exist
+// is expired or the allowance is exceeded.
+func CheckAuthzAndAllowanceForGranter(
+ ctx sdk.Context,
+ authzKeeper authzkeeper.Keeper,
+ grantee, granter common.Address,
+ amount *sdk.Coin,
+ msgURL string,
+) (*stakingtypes.StakeAuthorization, *time.Time, error) {
+ msgAuthz, expiration := authzKeeper.GetAuthorization(ctx, grantee.Bytes(), granter.Bytes(), msgURL)
+ if msgAuthz == nil {
+ return nil, nil, fmt.Errorf(ErrAuthzDoesNotExistOrExpired, msgURL, grantee)
+ }
+
+ stakeAuthz, ok := msgAuthz.(*stakingtypes.StakeAuthorization)
+ if !ok {
+ return nil, nil, authz.ErrUnknownAuthorizationType
+ }
+
+ if stakeAuthz.MaxTokens != nil && amount.Amount.GT(stakeAuthz.MaxTokens.Amount) {
+ return nil, nil, fmt.Errorf(ErrExceededAllowance, amount.Amount, stakeAuthz.MaxTokens.Amount)
+ }
+
+ return stakeAuthz, expiration, nil
+}
+
+// validateMsgTypes checks if the typeURLs are of the correct type,
+// performs basic validation on the length and checks for any empty strings
+func validateMsgTypes(arg interface{}) ([]string, error) {
+ typeURLs, ok := arg.([]string)
+ if !ok {
+ return nil, fmt.Errorf(ErrInvalidMethods, arg)
+ }
+ if len(typeURLs) == 0 {
+ return nil, fmt.Errorf(ErrEmptyMethods)
+ }
+
+ if slices.Contains(typeURLs, "") {
+ return nil, fmt.Errorf(ErrEmptyStringInMethods, typeURLs)
+ }
+
+ return typeURLs, nil
+}
diff --git a/precompiles/authorization/types_test.go b/precompiles/authorization/types_test.go
new file mode 100644
index 00000000..5401fcb0
--- /dev/null
+++ b/precompiles/authorization/types_test.go
@@ -0,0 +1,116 @@
+package authorization_test
+
+import (
+ "fmt"
+ "testing"
+
+ "cosmossdk.io/math"
+ "github.com/evmos/evmos/v19/utils"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ testutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/stretchr/testify/require"
+)
+
+const validTypeURL = "/cosmos.bank.v1beta1.MsgSend"
+
+func TestCheckApprovalArgs(t *testing.T) {
+ addr := testutiltx.GenerateAddress()
+ testcases := []struct {
+ name string
+ args []interface{}
+ expErr bool
+ ErrContains string
+ }{
+ {
+ name: "invalid number of arguments",
+ args: []interface{}{addr, common.Address{}, math.NewInt(100), "abc"},
+ expErr: true,
+ ErrContains: fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 4),
+ },
+ {
+ name: "invalid methods defined",
+ args: []interface{}{addr, 100, nil},
+ expErr: true,
+ ErrContains: fmt.Sprintf(authorization.ErrInvalidMethods, nil),
+ },
+ {
+ name: "no methods defined",
+ args: []interface{}{addr, 100, []string{}},
+ expErr: true,
+ ErrContains: authorization.ErrEmptyMethods,
+ },
+ {
+ name: "empty string found in methods array",
+ args: []interface{}{addr, 100, []string{"", validTypeURL}},
+ expErr: true,
+ ErrContains: fmt.Sprintf(authorization.ErrEmptyStringInMethods, []string{"", validTypeURL}),
+ },
+ {
+ name: "valid arguments",
+ args: []interface{}{addr, 100, []string{validTypeURL}},
+ expErr: false,
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ _, _, _, err := authorization.CheckApprovalArgs(tc.args, utils.BaseDenom)
+ if tc.expErr {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), tc.ErrContains)
+ } else {
+ require.NoError(t, err)
+ }
+ })
+ }
+}
+
+func TestCheckAllowanceArgs(t *testing.T) {
+ addr := testutiltx.GenerateAddress()
+
+ testcases := []struct {
+ name string
+ args []interface{}
+ expErr bool
+ ErrContains string
+ }{
+ {
+ name: "invalid number of arguments",
+ args: []interface{}{"", "", "", ""},
+ expErr: true,
+ ErrContains: fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 4),
+ },
+ {
+ name: "invalid grantee address",
+ args: []interface{}{common.Address{}, addr, validTypeURL},
+ expErr: true,
+ ErrContains: fmt.Sprintf(authorization.ErrInvalidGrantee, common.Address{}),
+ },
+ {
+ name: "invalid granter address",
+ args: []interface{}{addr, common.Address{}, validTypeURL},
+ expErr: true,
+ ErrContains: fmt.Sprintf(authorization.ErrInvalidGranter, common.Address{}),
+ },
+ {
+ name: "valid arguments",
+ args: []interface{}{addr, addr, validTypeURL},
+ expErr: false,
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ _, _, _, err := authorization.CheckAllowanceArgs(tc.args)
+ if tc.expErr {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), tc.ErrContains)
+ } else {
+ require.NoError(t, err)
+ }
+ })
+ }
+}
diff --git a/precompiles/bank/IBank.sol b/precompiles/bank/IBank.sol
new file mode 100644
index 00000000..626775df
--- /dev/null
+++ b/precompiles/bank/IBank.sol
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.18;
+
+/// @dev The IBank contract's address.
+address constant IBANK_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000804;
+
+/// @dev The IBank contract's instance.
+IBank constant IBANK_CONTRACT = IBank(IBANK_PRECOMPILE_ADDRESS);
+
+/// @dev Balance specifies the ERC20 contract address and the amount of tokens.
+struct Balance {
+ /// contractAddress defines the ERC20 contract address.
+ address contractAddress;
+ /// amount of tokens
+ uint256 amount;
+}
+
+/**
+ * @author Evmos Team
+ * @title Bank Interface
+ * @dev Interface for querying balances and supply from the Bank module.
+ */
+interface IBank {
+ /// @dev Balances defines a method for retrieving all the native token balances
+ /// for a given account.
+ /// @param account the address of the account to query balances for
+ /// @return balances the array of native token balances
+ function balances(address account) external view returns (Balance[] memory balances);
+
+ /// @dev TotalSupply defines a method for retrieving the total supply of all
+ /// native tokens.
+ /// @return totalSupply the supply as an array of native token balances
+ function totalSupply() external view returns (Balance[] memory totalSupply);
+
+
+ /// @dev supplyOf defines a method for retrieving the total supply of a particular native coin.
+ /// @return totalSupply the supply as a uint256
+ function supplyOf(address erc20Address) external view returns (uint256 totalSupply);
+}
diff --git a/precompiles/bank/abi.json b/precompiles/bank/abi.json
new file mode 100644
index 00000000..f64400e2
--- /dev/null
+++ b/precompiles/bank/abi.json
@@ -0,0 +1,86 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "IBank",
+ "sourceName": "solidity/precompiles/bank/IBank.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balances",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "contractAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Balance[]",
+ "name": "balances",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "erc20Address",
+ "type": "address"
+ }
+ ],
+ "name": "supplyOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "totalSupply",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "contractAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Balance[]",
+ "name": "totalSupply",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x",
+ "deployedBytecode": "0x",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/bank/bank.go b/precompiles/bank/bank.go
new file mode 100644
index 00000000..e54f05d3
--- /dev/null
+++ b/precompiles/bank/bank.go
@@ -0,0 +1,146 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package bank
+
+import (
+ "embed"
+ "fmt"
+
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ erc20keeper "github.com/evmos/evmos/v19/x/erc20/keeper"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+const (
+ // GasBalanceOf defines the gas cost for a single ERC-20 balanceOf query
+ GasBalanceOf = 2_851
+
+ // GasTotalSupply defines the gas cost for a single ERC-20 totalSupply query
+ GasTotalSupply = 2_477
+
+ // GasSupplyOf defines the gas cost for a single ERC-20 supplyOf query, taken from totalSupply of ERC20
+ GasSupplyOf = 2_477
+)
+
+var _ vm.PrecompiledContract = &Precompile{}
+
+// Embed abi json file to the executable binary. Needed when importing as dependency.
+//
+//go:embed abi.json
+var f embed.FS
+
+// Precompile defines the bank precompile
+type Precompile struct {
+ cmn.Precompile
+ bankKeeper bankkeeper.Keeper
+ erc20Keeper erc20keeper.Keeper
+}
+
+// NewPrecompile creates a new bank Precompile instance as a
+// PrecompiledContract interface.
+func NewPrecompile(
+ bankKeeper bankkeeper.Keeper,
+ erc20Keeper erc20keeper.Keeper,
+) (*Precompile, error) {
+ newABI, err := cmn.LoadABI(f, "abi.json")
+ if err != nil {
+ return nil, err
+ }
+
+ // NOTE: we set an empty gas configuration to avoid extra gas costs
+ // during the run execution
+ p := &Precompile{
+ Precompile: cmn.Precompile{
+ ABI: newABI,
+ KvGasConfig: storetypes.GasConfig{},
+ TransientKVGasConfig: storetypes.GasConfig{},
+ },
+ bankKeeper: bankKeeper,
+ erc20Keeper: erc20Keeper,
+ }
+
+ // SetAddress defines the address of the bank compile contract.
+ p.SetAddress(common.HexToAddress(evmtypes.BankPrecompileAddress))
+
+ return p, nil
+}
+
+// RequiredGas calculates the precompiled contract's base gas rate.
+func (p Precompile) RequiredGas(input []byte) uint64 {
+ // NOTE: This check avoid panicking when trying to decode the method ID
+ if len(input) < 4 {
+ return 0
+ }
+
+ methodID := input[:4]
+
+ method, err := p.MethodById(methodID)
+ if err != nil {
+ // This should never happen since this method is going to fail during Run
+ return 0
+ }
+
+ // NOTE: Charge the amount of gas required for a single ERC-20
+ // balanceOf or totalSupply query
+ switch method.Name {
+ case BalancesMethod:
+ return GasBalanceOf
+ case TotalSupplyMethod:
+ return GasTotalSupply
+ case SupplyOfMethod:
+ return GasSupplyOf
+ }
+
+ return 0
+}
+
+// Run executes the precompiled contract bank query methods defined in the ABI.
+func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) {
+ ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction)
+ if err != nil {
+ return nil, err
+ }
+
+ // This handles any out of gas errors that may occur during the execution of a precompile query.
+ // It avoids panics and returns the out of gas error so the EVM can continue gracefully.
+ defer cmn.HandleGasError(ctx, contract, initialGas, &err)()
+
+ switch method.Name {
+ // Bank queries
+ case BalancesMethod:
+ bz, err = p.Balances(ctx, contract, method, args)
+ case TotalSupplyMethod:
+ bz, err = p.TotalSupply(ctx, contract, method, args)
+ case SupplyOfMethod:
+ bz, err = p.SupplyOf(ctx, contract, method, args)
+ default:
+ return nil, fmt.Errorf(cmn.ErrUnknownMethod, method.Name)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ cost := ctx.GasMeter().GasConsumed() - initialGas
+
+ if !contract.UseGas(cost) {
+ return nil, vm.ErrOutOfGas
+ }
+
+ if err := p.AddJournalEntries(stateDB, snapshot); err != nil {
+ return nil, err
+ }
+
+ return bz, nil
+}
+
+// IsTransaction checks if the given method name corresponds to a transaction or query.
+// It returns false since all bank methods are queries.
+func (Precompile) IsTransaction(_ string) bool {
+ return false
+}
diff --git a/precompiles/bank/integration_test.go b/precompiles/bank/integration_test.go
new file mode 100644
index 00000000..13fd70ef
--- /dev/null
+++ b/precompiles/bank/integration_test.go
@@ -0,0 +1,425 @@
+package bank_test
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/evmos/evmos/v19/precompiles/bank/testdata"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ integrationutils "github.com/evmos/evmos/v19/testutil/integration/evmos/utils"
+ "github.com/evmos/evmos/v19/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+
+ evmosutiltx "github.com/evmos/evmos/v19/testutil/tx"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/evmos/evmos/v19/precompiles/bank"
+
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+)
+
+var is *IntegrationTestSuite
+
+// IntegrationTestSuite is the implementation of the TestSuite interface for Bank precompile
+// unit testis.
+type IntegrationTestSuite struct {
+ bondDenom, tokenDenom string
+ evmosAddr, xmplAddr common.Address
+
+ // tokenDenom is the specific token denomination used in testing the Bank precompile.
+ // This denomination is used to instantiate the precompile.
+ network *network.UnitTestNetwork
+ factory factory.TxFactory
+ grpcHandler grpc.Handler
+ keyring keyring.Keyring
+
+ precompile *bank.Precompile
+}
+
+func (is *IntegrationTestSuite) SetupTest() {
+ keyring := keyring.New(2)
+ genesis := integrationutils.CreateGenesisWithTokenPairs(keyring)
+ integrationNetwork := network.NewUnitTestNetwork(
+ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ network.WithCustomGenesis(genesis),
+ )
+ grpcHandler := grpc.NewIntegrationHandler(integrationNetwork)
+ txFactory := factory.New(integrationNetwork, grpcHandler)
+
+ ctx := integrationNetwork.GetContext()
+ sk := integrationNetwork.App.StakingKeeper
+ bondDenom := sk.BondDenom(ctx)
+ Expect(bondDenom).ToNot(BeEmpty(), "bond denom cannot be empty")
+
+ is.bondDenom = bondDenom
+ is.tokenDenom = "xmpl"
+ is.factory = txFactory
+ is.grpcHandler = grpcHandler
+ is.keyring = keyring
+ is.network = integrationNetwork
+
+ tokenPairID := is.network.App.Erc20Keeper.GetTokenPairID(is.network.GetContext(), is.bondDenom)
+ tokenPair, found := is.network.App.Erc20Keeper.GetTokenPair(is.network.GetContext(), tokenPairID)
+ Expect(found).To(BeTrue(), "failed to register token erc20 extension")
+ is.evmosAddr = common.HexToAddress(tokenPair.Erc20Address)
+
+ // Mint and register a second coin for testing purposes
+ err := is.network.App.BankKeeper.MintCoins(is.network.GetContext(), inflationtypes.ModuleName, sdk.Coins{{Denom: is.tokenDenom, Amount: sdk.NewInt(1e18)}})
+ Expect(err).ToNot(HaveOccurred(), "failed to mint coin")
+
+ tokenPairID = is.network.App.Erc20Keeper.GetTokenPairID(is.network.GetContext(), is.tokenDenom)
+ tokenPair, found = is.network.App.Erc20Keeper.GetTokenPair(is.network.GetContext(), tokenPairID)
+ Expect(found).To(BeTrue(), "failed to register token erc20 extension")
+ is.xmplAddr = common.HexToAddress(tokenPair.Erc20Address)
+ is.precompile = is.setupBankPrecompile()
+}
+
+func TestIntegrationSuite(t *testing.T) {
+ is = new(IntegrationTestSuite)
+
+ // Run Ginkgo integration tests
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Bank Extension Suite")
+}
+
+var _ = Describe("Bank Extension -", func() {
+ var (
+ bankCallerContractAddr common.Address
+ bankCallerContract evmtypes.CompiledContract
+
+ err error
+ sender keyring.Key
+ amount *big.Int
+
+ // contractData is a helper struct to hold the addresses and ABIs for the
+ // different contract instances that are subject to testing here.
+ contractData ContractData
+ passCheck testutil.LogCheckArgs
+ )
+
+ BeforeEach(func() {
+ is.SetupTest()
+
+ // Default sender, amount
+ sender = is.keyring.GetKey(0)
+ amount = big.NewInt(1e18)
+
+ bankCallerContract, err = testdata.LoadBankCallerContract()
+ Expect(err).ToNot(HaveOccurred(), "failed to load BankCaller contract")
+
+ bankCallerContractAddr, err = is.factory.DeployContract(
+ sender.Priv,
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: bankCallerContract,
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter burner contract")
+
+ contractData = ContractData{
+ ownerPriv: sender.Priv,
+ precompileAddr: is.precompile.Address(),
+ precompileABI: is.precompile.ABI,
+ contractAddr: bankCallerContractAddr,
+ contractABI: bankCallerContract.ABI,
+ }
+
+ passCheck = testutil.LogCheckArgs{}.WithExpPass(true)
+
+ err = is.network.NextBlock()
+ Expect(err).ToNot(HaveOccurred(), "failed to advance block")
+ })
+
+ Context("Direct precompile queries", func() {
+ Context("balances query", func() {
+ It("should return the correct balance", func() {
+ balanceBefore, err := is.grpcHandler.GetBalance(sender.AccAddr, is.tokenDenom)
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+ Expect(balanceBefore.Balance.Amount).To(Equal(sdk.NewInt(0)))
+ Expect(balanceBefore.Balance.Denom).To(Equal(is.tokenDenom))
+
+ is.mintAndSendXMPLCoin(is.keyring.GetAccAddr(0), sdk.NewInt(amount.Int64()))
+
+ queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, sender.Addr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ balanceAfter, err := is.grpcHandler.GetBalance(sender.AccAddr, is.tokenDenom)
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+
+ Expect(sdk.NewInt(balances[1].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount))
+ })
+
+ It("should return a single token balance", func() {
+ queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, sender.Addr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ balanceAfter, err := is.grpcHandler.GetBalance(sender.AccAddr, utils.BaseDenom)
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+
+ Expect(sdk.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount))
+ })
+
+ It("should return no balance for new account", func() {
+ queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, evmosutiltx.GenerateAddress())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ Expect(balances).To(BeEmpty())
+ })
+
+ It("should consume the correct amount of gas", func() {
+ is.mintAndSendXMPLCoin(is.keyring.GetAccAddr(0), sdk.NewInt(amount.Int64()))
+
+ queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, sender.Addr)
+ res, err := is.factory.ExecuteContractCall(sender.Priv, queryArgs, balancesArgs)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ ethRes, err := evmtypes.DecodeTxResponse(res.Data)
+ Expect(err).ToNot(HaveOccurred(), "failed to decode tx response")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ gasUsed := Max(bank.GasBalanceOf, len(balances)*bank.GasBalanceOf)
+ // Here increasing the GasBalanceOf will increase the use of gas so they will never be equal
+ Expect(gasUsed).To(BeNumerically("<=", ethRes.GasUsed))
+ })
+ })
+
+ Context("totalSupply query", func() {
+ It("should return the correct total supply", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.TotalSupplyMethod)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.TotalSupplyMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ evmosTotalSupply, ok := new(big.Int).SetString("11000000000000000000", 10)
+ Expect(ok).To(BeTrue(), "failed to parse evmos total supply")
+ xmplTotalSupply := amount
+
+ Expect(balances[0].Amount).To(Equal(evmosTotalSupply))
+ Expect(balances[1].Amount).To(Equal(xmplTotalSupply))
+ })
+ })
+
+ Context("supplyOf query", func() {
+ It("should return the supply of Evmos", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, is.evmosAddr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ evmosTotalSupply, ok := new(big.Int).SetString("11000000000000000000", 10)
+ Expect(ok).To(BeTrue(), "failed to parse evmos total supply")
+
+ Expect(out[0].(*big.Int)).To(Equal(evmosTotalSupply))
+ })
+
+ It("should return the supply of XMPL", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, is.xmplAddr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ Expect(out[0].(*big.Int)).To(Equal(amount))
+ })
+
+ It("should return a supply of 0 for a non existing token", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, evmosutiltx.GenerateAddress())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ Expect(out[0].(*big.Int).Int64()).To(Equal(big.NewInt(0).Int64()))
+ })
+
+ It("should consume the correct amount of gas", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, is.xmplAddr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ // Here increasing the GasSupplyOf will increase the use of gas so they will never be equal
+ Expect(bank.GasSupplyOf).To(BeNumerically("<=", ethRes.GasUsed))
+ })
+ })
+ })
+
+ Context("Calls from a contract", func() {
+ const (
+ BalancesFunction = "callBalances"
+ TotalSupplyOf = "callTotalSupply"
+ SupplyOfFunction = "callSupplyOf"
+ )
+
+ Context("balances query", func() {
+ It("should return the correct balance", func() {
+ balanceBefore, err := is.grpcHandler.GetBalance(sender.AccAddr, is.tokenDenom)
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+ Expect(balanceBefore.Balance.Amount).To(Equal(sdk.NewInt(0)))
+ Expect(balanceBefore.Balance.Denom).To(Equal(is.tokenDenom))
+
+ is.mintAndSendXMPLCoin(is.keyring.GetAccAddr(0), sdk.NewInt(amount.Int64()))
+
+ queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, sender.Addr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ balanceAfter, err := is.grpcHandler.GetBalance(sender.AccAddr, is.tokenDenom)
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+
+ Expect(sdk.NewInt(balances[1].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount))
+ })
+
+ It("should return a single token balance", func() {
+ queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, sender.Addr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ balanceAfter, err := is.grpcHandler.GetBalance(sender.AccAddr, utils.BaseDenom)
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+
+ Expect(sdk.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount))
+ })
+
+ It("should return no balance for new account", func() {
+ queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, evmosutiltx.GenerateAddress())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ Expect(balances).To(BeEmpty())
+ })
+
+ It("should consume the correct amount of gas", func() {
+ is.mintAndSendXMPLCoin(is.keyring.GetAccAddr(0), sdk.NewInt(amount.Int64()))
+
+ queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, sender.Addr)
+ res, err := is.factory.ExecuteContractCall(sender.Priv, queryArgs, balancesArgs)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ ethRes, err := evmtypes.DecodeTxResponse(res.Data)
+ Expect(err).ToNot(HaveOccurred(), "failed to decode tx response")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ gasUsed := Max(bank.GasBalanceOf, len(balances)*bank.GasBalanceOf)
+ // Here increasing the GasBalanceOf will increase the use of gas so they will never be equal
+ Expect(gasUsed).To(BeNumerically("<=", ethRes.GasUsed))
+ })
+ })
+
+ Context("totalSupply query", func() {
+ It("should return the correct total supply", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, TotalSupplyOf)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balances []bank.Balance
+ err = is.precompile.UnpackIntoInterface(&balances, bank.TotalSupplyMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ evmosTotalSupply, ok := new(big.Int).SetString("11000000000000000000", 10)
+ Expect(ok).To(BeTrue(), "failed to parse evmos total supply")
+ xmplTotalSupply := amount
+
+ Expect(balances[0].Amount).To(Equal(evmosTotalSupply))
+ Expect(balances[1].Amount).To(Equal(xmplTotalSupply))
+ })
+ })
+
+ Context("supplyOf query", func() {
+ It("should return the supply of Evmos", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.evmosAddr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ evmosTotalSupply, ok := new(big.Int).SetString("11000000000000000000", 10)
+ Expect(ok).To(BeTrue(), "failed to parse evmos total supply")
+
+ Expect(out[0].(*big.Int)).To(Equal(evmosTotalSupply))
+ })
+
+ It("should return the supply of XMPL", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.xmplAddr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ Expect(out[0].(*big.Int)).To(Equal(amount))
+ })
+
+ It("should return a supply of 0 for a non existing token", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, evmosutiltx.GenerateAddress())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
+
+ Expect(out[0].(*big.Int).Int64()).To(Equal(big.NewInt(0).Int64()))
+ })
+
+ It("should consume the correct amount of gas", func() {
+ queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.xmplAddr)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ // Here increasing the GasSupplyOf will increase the use of gas so they will never be equal
+ Expect(bank.GasSupplyOf).To(BeNumerically("<=", ethRes.GasUsed))
+ })
+ })
+ })
+})
diff --git a/precompiles/bank/query.go b/precompiles/bank/query.go
new file mode 100644
index 00000000..f34d8fb8
--- /dev/null
+++ b/precompiles/bank/query.go
@@ -0,0 +1,126 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package bank
+
+import (
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // BalancesMethod defines the ABI method name for the bank Balances
+ // query.
+ BalancesMethod = "balances"
+ // TotalSupplyMethod defines the ABI method name for the bank TotalSupply
+ // query.
+ TotalSupplyMethod = "totalSupply"
+ // SupplyOfMethod defines the ABI method name for the bank SupplyOf
+ // query.
+ SupplyOfMethod = "supplyOf"
+)
+
+// Balances returns all the native token balances (address, amount) for a given
+// account. This method charges the account the corresponding value of an ERC-20
+// balanceOf call for each token returned.
+func (p Precompile) Balances(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ account, err := ParseBalancesArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ i := 0
+ balances := make([]Balance, 0)
+
+ p.bankKeeper.IterateAccountBalances(ctx, account, func(coin sdk.Coin) bool {
+ defer func() { i++ }()
+
+ // NOTE: we already charged for a single balanceOf request so we don't
+ // need to charge on the first iteration
+ if i > 0 {
+ ctx.GasMeter().ConsumeGas(GasBalanceOf, "ERC-20 extension balances method")
+ }
+
+ contractAddress, err := p.erc20Keeper.GetCoinAddress(ctx, coin.Denom)
+ if err != nil {
+ return false
+ }
+
+ balances = append(balances, Balance{
+ ContractAddress: contractAddress,
+ Amount: coin.Amount.BigInt(),
+ })
+
+ return false
+ })
+
+ return method.Outputs.Pack(balances)
+}
+
+// TotalSupply returns the total supply of all the native tokens.
+// This method charges the account the corresponding value of a ERC-20 totalSupply
+// call for each token returned.
+func (p Precompile) TotalSupply(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ _ []interface{},
+) ([]byte, error) {
+ i := 0
+ totalSupply := make([]Balance, 0)
+
+ p.bankKeeper.IterateTotalSupply(ctx, func(coin sdk.Coin) bool {
+ defer func() { i++ }()
+
+ // NOTE: we already charged for a single totalSupply request so we don't
+ // need to charge on the first iteration
+ if i > 0 {
+ ctx.GasMeter().ConsumeGas(GasTotalSupply, "ERC-20 extension totalSupply method")
+ }
+
+ contractAddress, err := p.erc20Keeper.GetCoinAddress(ctx, coin.Denom)
+ if err != nil {
+ return false
+ }
+
+ totalSupply = append(totalSupply, Balance{
+ ContractAddress: contractAddress,
+ Amount: coin.Amount.BigInt(),
+ })
+
+ return false
+ })
+
+ return method.Outputs.Pack(totalSupply)
+}
+
+// SupplyOf returns the total native supply of a given registered erc20 token.
+func (p Precompile) SupplyOf(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ erc20ContractAddress, err := ParseSupplyOfArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ tokenPairID := p.erc20Keeper.GetERC20Map(ctx, erc20ContractAddress)
+ tokenPair, found := p.erc20Keeper.GetTokenPair(ctx, tokenPairID)
+ if !found {
+ return method.Outputs.Pack(big.NewInt(0))
+ }
+
+ supply := p.bankKeeper.GetSupply(ctx, tokenPair.Denom)
+
+ return method.Outputs.Pack(supply.Amount.BigInt())
+}
diff --git a/precompiles/bank/query_test.go b/precompiles/bank/query_test.go
new file mode 100644
index 00000000..eac61c98
--- /dev/null
+++ b/precompiles/bank/query_test.go
@@ -0,0 +1,259 @@
+package bank_test
+
+import (
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/evmos/evmos/v19/precompiles/bank"
+ evmosutiltx "github.com/evmos/evmos/v19/testutil/tx"
+)
+
+func (s *PrecompileTestSuite) TestBalances() {
+ method := s.precompile.Methods[bank.BalancesMethod]
+
+ testcases := []struct {
+ name string
+ malleate func() []interface{}
+ expPass bool
+ errContains string
+ expBalances []bank.Balance
+ }{
+ {
+ "fail - invalid number of arguments",
+ func() []interface{} {
+ return []interface{}{
+ "", "",
+ }
+ },
+ false,
+ "invalid number of arguments",
+ nil,
+ },
+ {
+ "fail - invalid account address",
+ func() []interface{} {
+ return []interface{}{
+ "random text",
+ }
+ },
+ false,
+ "invalid type for account",
+ nil,
+ },
+ {
+ "pass - empty balances for new account",
+ func() []interface{} {
+ return []interface{}{
+ evmosutiltx.GenerateAddress(),
+ }
+ },
+ true,
+ "",
+ []bank.Balance{},
+ },
+ {
+ "pass - EVMOS balance present",
+ func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(0),
+ }
+ },
+ true,
+ "",
+ []bank.Balance{{
+ ContractAddress: s.evmosAddr,
+ Amount: big.NewInt(4e18),
+ }},
+ },
+ {
+ "pass - EVMOS and XMPL balances present",
+ func() []interface{} {
+ s.mintAndSendXMPLCoin(s.keyring.GetAccAddr(0), sdk.NewInt(1e18))
+ return []interface{}{
+ s.keyring.GetAddr(0),
+ }
+ },
+ true,
+ "",
+ []bank.Balance{{
+ ContractAddress: s.evmosAddr,
+ Amount: big.NewInt(4e18),
+ }, {
+ ContractAddress: s.xmplAddr,
+ Amount: big.NewInt(1e18),
+ }},
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ bz, err := s.precompile.Balances(
+ s.network.GetContext(),
+ nil,
+ &method,
+ tc.malleate(),
+ )
+
+ if tc.expPass {
+ s.Require().NoError(err)
+ var balances []bank.Balance
+ err = s.precompile.UnpackIntoInterface(&balances, method.Name, bz)
+ s.Require().NoError(err)
+ s.Require().Equal(tc.expBalances, balances)
+ } else {
+ s.Require().Contains(err.Error(), tc.errContains)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestTotalSupply() {
+ method := s.precompile.Methods[bank.TotalSupplyMethod]
+
+ evmosTotalSupply, ok := new(big.Int).SetString("11000000000000000000", 10)
+ s.Require().True(ok)
+
+ testcases := []struct {
+ name string
+ malleate func()
+ expSupply []bank.Balance
+ }{
+ {
+ "pass - EVMOS and XMPL total supply",
+ func() {
+ s.mintAndSendXMPLCoin(s.keyring.GetAccAddr(0), sdk.NewInt(1e18))
+ },
+ []bank.Balance{{
+ ContractAddress: s.evmosAddr,
+ Amount: evmosTotalSupply,
+ }, {
+ ContractAddress: s.xmplAddr,
+ Amount: big.NewInt(1e18),
+ }},
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ bz, err := s.precompile.TotalSupply(
+ s.network.GetContext(),
+ nil,
+ &method,
+ nil,
+ )
+
+ s.Require().NoError(err)
+ var balances []bank.Balance
+ err = s.precompile.UnpackIntoInterface(&balances, method.Name, bz)
+ s.Require().NoError(err)
+ s.Require().Equal(tc.expSupply, balances)
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestSupplyOf() {
+ method := s.precompile.Methods[bank.SupplyOfMethod]
+
+ evmosTotalSupply, ok := new(big.Int).SetString("11000000000000000000", 10)
+ s.Require().True(ok)
+
+ testcases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ expSupply *big.Int
+ }{
+ {
+ "fail - invalid number of arguments",
+ func() []interface{} {
+ return []interface{}{
+ "", "", "",
+ }
+ },
+ true,
+ "invalid number of arguments",
+ nil,
+ },
+ {
+ "fail - invalid hex address",
+ func() []interface{} {
+ return []interface{}{
+ "random text",
+ }
+ },
+ true,
+ "invalid type for erc20Address",
+ nil,
+ },
+ {
+ "pass - erc20 not registered return 0 supply",
+ func() []interface{} {
+ return []interface{}{
+ evmosutiltx.GenerateAddress(),
+ }
+ },
+ false,
+ "",
+ big.NewInt(0),
+ },
+ {
+ "pass - XMPL total supply",
+ func() []interface{} {
+ return []interface{}{
+ s.xmplAddr,
+ }
+ },
+ false,
+ "",
+ big.NewInt(1e18),
+ },
+
+ {
+ "pass - EVMOS total supply",
+ func() []interface{} {
+ return []interface{}{
+ s.evmosAddr,
+ }
+ },
+ false,
+ "",
+ evmosTotalSupply,
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ bz, err := s.precompile.SupplyOf(
+ s.network.GetContext(),
+ nil,
+ &method,
+ tc.malleate(),
+ )
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ out, err := method.Outputs.Unpack(bz)
+ s.Require().NoError(err, "expected no error unpacking")
+ supply, ok := out[0].(*big.Int)
+ s.Require().True(ok, "expected output to be a big.Int")
+ s.Require().NoError(err)
+ s.Require().Equal(supply.Int64(), tc.expSupply.Int64())
+ }
+ })
+ }
+}
diff --git a/precompiles/bank/setup_test.go b/precompiles/bank/setup_test.go
new file mode 100644
index 00000000..6cf47d23
--- /dev/null
+++ b/precompiles/bank/setup_test.go
@@ -0,0 +1,86 @@
+package bank_test
+
+import (
+ "testing"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/bank"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ integrationutils "github.com/evmos/evmos/v19/testutil/integration/evmos/utils"
+ "github.com/stretchr/testify/suite"
+)
+
+var s *PrecompileTestSuite
+
+// PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 precompile
+// unit tests.
+type PrecompileTestSuite struct {
+ suite.Suite
+
+ bondDenom, tokenDenom string
+ evmosAddr, xmplAddr common.Address
+
+ // tokenDenom is the specific token denomination used in testing the ERC20 precompile.
+ // This denomination is used to instantiate the precompile.
+ network *network.UnitTestNetwork
+ factory factory.TxFactory
+ grpcHandler grpc.Handler
+ keyring testkeyring.Keyring
+
+ precompile *bank.Precompile
+}
+
+func TestPrecompileTestSuite(t *testing.T) {
+ s = new(PrecompileTestSuite)
+ suite.Run(t, s)
+}
+
+func (s *PrecompileTestSuite) SetupTest() {
+ keyring := testkeyring.New(2)
+ genesis := integrationutils.CreateGenesisWithTokenPairs(keyring)
+ integrationNetwork := network.NewUnitTestNetwork(
+ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ network.WithCustomGenesis(genesis),
+ )
+ grpcHandler := grpc.NewIntegrationHandler(integrationNetwork)
+ txFactory := factory.New(integrationNetwork, grpcHandler)
+
+ ctx := integrationNetwork.GetContext()
+ sk := integrationNetwork.App.StakingKeeper
+ bondDenom := sk.BondDenom(ctx)
+ s.Require().NotEmpty(bondDenom, "bond denom cannot be empty")
+
+ s.bondDenom = bondDenom
+ s.tokenDenom = "xmpl"
+ s.factory = txFactory
+ s.grpcHandler = grpcHandler
+ s.keyring = keyring
+ s.network = integrationNetwork
+
+ tokenPairID := s.network.App.Erc20Keeper.GetTokenPairID(s.network.GetContext(), s.bondDenom)
+ tokenPair, found := s.network.App.Erc20Keeper.GetTokenPair(s.network.GetContext(), tokenPairID)
+ s.Require().True(found)
+ s.evmosAddr = common.HexToAddress(tokenPair.Erc20Address)
+
+ s.evmosAddr = tokenPair.GetERC20Contract()
+
+ // Mint and register a second coin for testing purposes
+ err := s.network.App.BankKeeper.MintCoins(s.network.GetContext(), inflationtypes.ModuleName, sdk.Coins{{Denom: "xmpl", Amount: math.NewInt(1e18)}})
+ s.Require().NoError(err)
+
+ tokenPairID = s.network.App.Erc20Keeper.GetTokenPairID(s.network.GetContext(), s.tokenDenom)
+ tokenPair, found = s.network.App.Erc20Keeper.GetTokenPair(s.network.GetContext(), tokenPairID)
+ s.Require().True(found)
+ s.xmplAddr = common.HexToAddress(tokenPair.Erc20Address)
+
+ s.xmplAddr = tokenPair.GetERC20Contract()
+
+ s.precompile = s.setupBankPrecompile()
+}
diff --git a/precompiles/bank/testdata/BankCaller.json b/precompiles/bank/testdata/BankCaller.json
new file mode 100644
index 00000000..c5f7ecbd
--- /dev/null
+++ b/precompiles/bank/testdata/BankCaller.json
@@ -0,0 +1,86 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "BankCaller",
+ "sourceName": "solidity/precompiles/bank/testdata/BankCaller.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "callBalances",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "contractAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Balance[]",
+ "name": "balances",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "erc20Address",
+ "type": "address"
+ }
+ ],
+ "name": "callSupplyOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "callTotalSupply",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "contractAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Balance[]",
+ "name": "totalSupply",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b50610706806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806389129c6814610046578063acab2f9414610076578063bba60ca014610094575b600080fd5b610060600480360381019061005b91906102c2565b6100c4565b60405161006d91906103f5565b60405180910390f35b61007e61014e565b60405161008b91906103f5565b60405180910390f35b6100ae60048036038101906100a991906102c2565b6101cb565b6040516100bb9190610426565b60405180910390f35b606061080473ffffffffffffffffffffffffffffffffffffffff166327e235e3836040518263ffffffff1660e01b81526004016101019190610450565b600060405180830381865afa15801561011e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610147919061065a565b9050919050565b606061080473ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561019d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906101c6919061065a565b905090565b600061080473ffffffffffffffffffffffffffffffffffffffff166362400e4c836040518263ffffffff1660e01b81526004016102089190610450565b602060405180830381865afa158015610225573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024991906106a3565b9050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028f82610264565b9050919050565b61029f81610284565b81146102aa57600080fd5b50565b6000813590506102bc81610296565b92915050565b6000602082840312156102d8576102d761025a565b5b60006102e6848285016102ad565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61032481610284565b82525050565b6000819050919050565b61033d8161032a565b82525050565b604082016000820151610359600085018261031b565b50602082015161036c6020850182610334565b50505050565b600061037e8383610343565b60408301905092915050565b6000602082019050919050565b60006103a2826102ef565b6103ac81856102fa565b93506103b78361030b565b8060005b838110156103e85781516103cf8882610372565b97506103da8361038a565b9250506001810190506103bb565b5085935050505092915050565b6000602082019050818103600083015261040f8184610397565b905092915050565b6104208161032a565b82525050565b600060208201905061043b6000830184610417565b92915050565b61044a81610284565b82525050565b60006020820190506104656000830184610441565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6104b982610470565b810181811067ffffffffffffffff821117156104d8576104d7610481565b5b80604052505050565b60006104eb610250565b90506104f782826104b0565b919050565b600067ffffffffffffffff82111561051757610516610481565b5b602082029050602081019050919050565b600080fd5b600080fd5b60008151905061054181610296565b92915050565b6105508161032a565b811461055b57600080fd5b50565b60008151905061056d81610547565b92915050565b6000604082840312156105895761058861052d565b5b61059360406104e1565b905060006105a384828501610532565b60008301525060206105b78482850161055e565b60208301525092915050565b60006105d66105d1846104fc565b6104e1565b905080838252602082019050604084028301858111156105f9576105f8610528565b5b835b81811015610622578061060e8882610573565b8452602084019350506040810190506105fb565b5050509392505050565b600082601f8301126106415761064061046b565b5b81516106518482602086016105c3565b91505092915050565b6000602082840312156106705761066f61025a565b5b600082015167ffffffffffffffff81111561068e5761068d61025f565b5b61069a8482850161062c565b91505092915050565b6000602082840312156106b9576106b861025a565b5b60006106c78482850161055e565b9150509291505056fea264697066735822122069dcf2adfa16b7c11a609b544775058a5caffe57f2d073bb7f7ee7533aea460964736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806389129c6814610046578063acab2f9414610076578063bba60ca014610094575b600080fd5b610060600480360381019061005b91906102c2565b6100c4565b60405161006d91906103f5565b60405180910390f35b61007e61014e565b60405161008b91906103f5565b60405180910390f35b6100ae60048036038101906100a991906102c2565b6101cb565b6040516100bb9190610426565b60405180910390f35b606061080473ffffffffffffffffffffffffffffffffffffffff166327e235e3836040518263ffffffff1660e01b81526004016101019190610450565b600060405180830381865afa15801561011e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610147919061065a565b9050919050565b606061080473ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561019d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906101c6919061065a565b905090565b600061080473ffffffffffffffffffffffffffffffffffffffff166362400e4c836040518263ffffffff1660e01b81526004016102089190610450565b602060405180830381865afa158015610225573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024991906106a3565b9050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028f82610264565b9050919050565b61029f81610284565b81146102aa57600080fd5b50565b6000813590506102bc81610296565b92915050565b6000602082840312156102d8576102d761025a565b5b60006102e6848285016102ad565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61032481610284565b82525050565b6000819050919050565b61033d8161032a565b82525050565b604082016000820151610359600085018261031b565b50602082015161036c6020850182610334565b50505050565b600061037e8383610343565b60408301905092915050565b6000602082019050919050565b60006103a2826102ef565b6103ac81856102fa565b93506103b78361030b565b8060005b838110156103e85781516103cf8882610372565b97506103da8361038a565b9250506001810190506103bb565b5085935050505092915050565b6000602082019050818103600083015261040f8184610397565b905092915050565b6104208161032a565b82525050565b600060208201905061043b6000830184610417565b92915050565b61044a81610284565b82525050565b60006020820190506104656000830184610441565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6104b982610470565b810181811067ffffffffffffffff821117156104d8576104d7610481565b5b80604052505050565b60006104eb610250565b90506104f782826104b0565b919050565b600067ffffffffffffffff82111561051757610516610481565b5b602082029050602081019050919050565b600080fd5b600080fd5b60008151905061054181610296565b92915050565b6105508161032a565b811461055b57600080fd5b50565b60008151905061056d81610547565b92915050565b6000604082840312156105895761058861052d565b5b61059360406104e1565b905060006105a384828501610532565b60008301525060206105b78482850161055e565b60208301525092915050565b60006105d66105d1846104fc565b6104e1565b905080838252602082019050604084028301858111156105f9576105f8610528565b5b835b81811015610622578061060e8882610573565b8452602084019350506040810190506105fb565b5050509392505050565b600082601f8301126106415761064061046b565b5b81516106518482602086016105c3565b91505092915050565b6000602082840312156106705761066f61025a565b5b600082015167ffffffffffffffff81111561068e5761068d61025f565b5b61069a8482850161062c565b91505092915050565b6000602082840312156106b9576106b861025a565b5b60006106c78482850161055e565b9150509291505056fea264697066735822122069dcf2adfa16b7c11a609b544775058a5caffe57f2d073bb7f7ee7533aea460964736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/bank/testdata/BankCaller.sol b/precompiles/bank/testdata/BankCaller.sol
new file mode 100644
index 00000000..7322fe11
--- /dev/null
+++ b/precompiles/bank/testdata/BankCaller.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.18;
+
+import "../IBank.sol";
+
+contract BankCaller {
+
+ function callBalances(address account) external view returns (Balance[] memory balances) {
+ return IBANK_CONTRACT.balances(account);
+ }
+
+ function callTotalSupply() external view returns (Balance[] memory totalSupply) {
+ return IBANK_CONTRACT.totalSupply();
+ }
+
+ function callSupplyOf(address erc20Address) external view returns (uint256) {
+ return IBANK_CONTRACT.supplyOf(erc20Address);
+ }
+}
\ No newline at end of file
diff --git a/precompiles/bank/testdata/bank.go b/precompiles/bank/testdata/bank.go
new file mode 100644
index 00000000..03f89685
--- /dev/null
+++ b/precompiles/bank/testdata/bank.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadBankCallerContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("BankCaller.json")
+}
diff --git a/precompiles/bank/types.go b/precompiles/bank/types.go
new file mode 100644
index 00000000..636b492b
--- /dev/null
+++ b/precompiles/bank/types.go
@@ -0,0 +1,47 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package bank
+
+import (
+ "fmt"
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+// Balance contains the amount for a corresponding ERC-20 contract address
+type Balance struct {
+ ContractAddress common.Address
+ Amount *big.Int
+}
+
+// ParseBalancesArgs parses the call arguments for the bank Balances query.
+func ParseBalancesArgs(args []interface{}) (sdk.AccAddress, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ account, ok := args[0].(common.Address)
+ if !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "account", common.Address{}, args[0])
+ }
+
+ return account.Bytes(), nil
+}
+
+// ParseSupplyOfArgs parses the call arguments for the bank SupplyOf query.
+func ParseSupplyOfArgs(args []interface{}) (common.Address, error) {
+ if len(args) != 1 {
+ return common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ erc20Address, ok := args[0].(common.Address)
+ if !ok {
+ return common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "erc20Address", common.Address{}, args[0])
+ }
+
+ return erc20Address, nil
+}
diff --git a/precompiles/bank/utils_test.go b/precompiles/bank/utils_test.go
new file mode 100644
index 00000000..aa260e4b
--- /dev/null
+++ b/precompiles/bank/utils_test.go
@@ -0,0 +1,108 @@
+package bank_test
+
+import (
+ "cosmossdk.io/math"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/bank"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+)
+
+// setupBankPrecompile is a helper function to set up an instance of the Bank precompile for
+// a given token denomination.
+func (s *PrecompileTestSuite) setupBankPrecompile() *bank.Precompile {
+ precompile, err := bank.NewPrecompile(
+ s.network.App.BankKeeper,
+ s.network.App.Erc20Keeper,
+ )
+
+ s.Require().NoError(err, "failed to create bank precompile")
+
+ return precompile
+}
+
+// setupBankPrecompile is a helper function to set up an instance of the Bank precompile for
+// a given token denomination.
+func (is *IntegrationTestSuite) setupBankPrecompile() *bank.Precompile {
+ precompile, err := bank.NewPrecompile(
+ is.network.App.BankKeeper,
+ is.network.App.Erc20Keeper,
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to create bank precompile")
+ return precompile
+}
+
+// mintAndSendXMPLCoin is a helper function to mint and send a coin to a given address.
+func (s *PrecompileTestSuite) mintAndSendXMPLCoin(addr sdk.AccAddress, amount math.Int) {
+ coins := sdk.NewCoins(sdk.NewCoin(s.tokenDenom, amount))
+ err := s.network.App.BankKeeper.MintCoins(s.network.GetContext(), inflationtypes.ModuleName, coins)
+ s.Require().NoError(err)
+ err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(s.network.GetContext(), inflationtypes.ModuleName, addr, coins)
+ s.Require().NoError(err)
+}
+
+// mintAndSendXMPLCoin is a helper function to mint and send a coin to a given address.
+func (is *IntegrationTestSuite) mintAndSendXMPLCoin(addr sdk.AccAddress, amount math.Int) {
+ coins := sdk.NewCoins(sdk.NewCoin(is.tokenDenom, amount))
+ err := is.network.App.BankKeeper.MintCoins(is.network.GetContext(), inflationtypes.ModuleName, coins)
+ Expect(err).ToNot(HaveOccurred())
+ err = is.network.App.BankKeeper.SendCoinsFromModuleToAccount(is.network.GetContext(), inflationtypes.ModuleName, addr, coins)
+ Expect(err).ToNot(HaveOccurred())
+}
+
+// callType constants to differentiate between direct calls and calls through a contract.
+const (
+ directCall = iota + 1
+ contractCall
+)
+
+// ContractData is a helper struct to hold the addresses and ABIs for the
+// different contract instances that are subject to testing here.
+type ContractData struct {
+ ownerPriv cryptotypes.PrivKey
+
+ contractAddr common.Address
+ contractABI abi.ABI
+ precompileAddr common.Address
+ precompileABI abi.ABI
+}
+
+// getTxAndCallArgs is a helper function to return the correct call arguments for a given call type.
+// In case of a direct call to the precompile, the precompile's ABI is used. Otherwise a caller contract is used.
+func getTxAndCallArgs(
+ callType int,
+ contractData ContractData,
+ methodName string,
+ args ...interface{},
+) (evmtypes.EvmTxArgs, factory.CallArgs) {
+ txArgs := evmtypes.EvmTxArgs{}
+ callArgs := factory.CallArgs{}
+
+ switch callType {
+ case directCall:
+ txArgs.To = &contractData.precompileAddr
+ callArgs.ContractABI = contractData.precompileABI
+ case contractCall:
+ txArgs.To = &contractData.contractAddr
+ callArgs.ContractABI = contractData.contractABI
+ }
+
+ callArgs.MethodName = methodName
+ callArgs.Args = args
+
+ return txArgs, callArgs
+}
+
+func Max(x, y int) int {
+ if x > y {
+ return x
+ }
+ return y
+}
diff --git a/precompiles/bech32/Bech32I.sol b/precompiles/bech32/Bech32I.sol
new file mode 100644
index 00000000..7d1c65a1
--- /dev/null
+++ b/precompiles/bech32/Bech32I.sol
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+/// @dev The Bech32I contract's address.
+address constant Bech32_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000400;
+
+/// @dev The Bech32I contract's instance.
+Bech32I constant BECH32_CONTRACT = Bech32I(Bech32_PRECOMPILE_ADDRESS);
+
+/// @author Evmos Team
+/// @title Bech32 Precompiled Contract
+/// @dev The interface through which solidity contracts can convert addresses from
+/// hex to bech32 and vice versa.
+/// @custom:address 0x0000000000000000000000000000000000000400
+interface Bech32I {
+ /// @dev Defines a method for converting a hex formatted address to bech32.
+ /// @param addr The hex address to be converted.
+ /// @param prefix The human readable prefix (HRP) of the bech32 address.
+ /// @return bech32Address The address in bech32 format.
+ function hexToBech32(
+ address addr,
+ string memory prefix
+ ) external returns (string memory bech32Address);
+
+ /// @dev Defines a method for converting a bech32 formatted address to hex.
+ /// @param bech32Address The bech32 address to be converted.
+ /// @return addr The address in hex format.
+ function bech32ToHex(
+ string memory bech32Address
+ ) external returns (address addr);
+}
diff --git a/precompiles/bech32/abi.json b/precompiles/bech32/abi.json
new file mode 100644
index 00000000..de66134b
--- /dev/null
+++ b/precompiles/bech32/abi.json
@@ -0,0 +1,54 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "Bech32I",
+ "sourceName": "solidity/precompiles/bech32/Bech32I.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "bech32Address",
+ "type": "string"
+ }
+ ],
+ "name": "bech32ToHex",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "addr",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "prefix",
+ "type": "string"
+ }
+ ],
+ "name": "hexToBech32",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "bech32Address",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x",
+ "deployedBytecode": "0x",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/bech32/bech32.go b/precompiles/bech32/bech32.go
new file mode 100644
index 00000000..177858f5
--- /dev/null
+++ b/precompiles/bech32/bech32.go
@@ -0,0 +1,91 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package bech32
+
+import (
+ "embed"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+var _ vm.PrecompiledContract = &Precompile{}
+
+// Embed abi json file to the executable binary. Needed when importing as dependency.
+//
+//go:embed abi.json
+var f embed.FS
+
+// Precompile defines the precompiled contract for Bech32 encoding.
+type Precompile struct {
+ abi.ABI
+ baseGas uint64
+}
+
+// NewPrecompile creates a new bech32 Precompile instance as a
+// PrecompiledContract interface.
+func NewPrecompile(baseGas uint64) (*Precompile, error) {
+ newABI, err := cmn.LoadABI(f, "abi.json")
+ if err != nil {
+ return nil, err
+ }
+
+ if baseGas == 0 {
+ return nil, fmt.Errorf("baseGas cannot be zero")
+ }
+
+ return &Precompile{
+ ABI: newABI,
+ baseGas: baseGas,
+ }, nil
+}
+
+// Address defines the address of the bech32 precompiled contract.
+func (Precompile) Address() common.Address {
+ return common.HexToAddress(evmtypes.Bech32PrecompileAddress)
+}
+
+// RequiredGas calculates the contract gas use.
+func (p Precompile) RequiredGas(_ []byte) uint64 {
+ return p.baseGas
+}
+
+// Run executes the precompiled contract bech32 methods defined in the ABI.
+func (p Precompile) Run(_ *vm.EVM, contract *vm.Contract, _ bool) (bz []byte, err error) {
+ // NOTE: This check avoid panicking when trying to decode the method ID
+ if len(contract.Input) < 4 {
+ return nil, vm.ErrExecutionReverted
+ }
+
+ methodID := contract.Input[:4]
+ // NOTE: this function iterates over the method map and returns
+ // the method with the given ID
+ method, err := p.MethodById(methodID)
+ if err != nil {
+ return nil, err
+ }
+
+ argsBz := contract.Input[4:]
+ args, err := method.Inputs.Unpack(argsBz)
+ if err != nil {
+ return nil, err
+ }
+
+ switch method.Name {
+ case HexToBech32Method:
+ bz, err = p.HexToBech32(method, args)
+ case Bech32ToHexMethod:
+ bz, err = p.Bech32ToHex(method, args)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ return bz, nil
+}
diff --git a/precompiles/bech32/bech32_test.go b/precompiles/bech32/bech32_test.go
new file mode 100644
index 00000000..2c6d3579
--- /dev/null
+++ b/precompiles/bech32/bech32_test.go
@@ -0,0 +1,270 @@
+package bech32_test
+
+import (
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/cmd/config"
+ "github.com/evmos/evmos/v19/precompiles/bech32"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func (s *PrecompileTestSuite) TestNewPrecompile() {
+ testCases := []struct {
+ name string
+ baseGas uint64
+ expPass bool
+ errContains string
+ }{
+ {
+ "fail - new precompile with baseGas == 0",
+ 0,
+ false,
+ "baseGas cannot be zero",
+ },
+ {
+ "success - new precompile with baseGas > 0",
+ 10,
+ true,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ // setup basic test suite
+ s.SetupTest()
+ p, err := bech32.NewPrecompile(tc.baseGas)
+ if tc.expPass {
+ s.Require().NoError(err)
+ s.Require().NotNil(p)
+ s.Require().Equal(tc.baseGas, p.RequiredGas([]byte{}))
+ } else {
+ s.Require().Error(err)
+ s.Require().Nil(p)
+ s.Require().Contains(err.Error(), tc.errContains)
+ }
+ })
+ }
+}
+
+// TestRun tests the precompile's Run method.
+func (s *PrecompileTestSuite) TestRun() {
+ contract := vm.NewPrecompile(
+ vm.AccountRef(s.keyring.GetAddr(0)),
+ s.precompile,
+ big.NewInt(0),
+ uint64(1000000),
+ )
+
+ testCases := []struct {
+ name string
+ malleate func() *vm.Contract
+ postCheck func(data []byte)
+ expPass bool
+ errContains string
+ }{
+ {
+ "fail - invalid method",
+ func() *vm.Contract {
+ contract.Input = []byte("invalid")
+ return contract
+ },
+ func([]byte) {},
+ false,
+ "no method with id",
+ },
+ {
+ "fail - error during unpack",
+ func() *vm.Contract {
+ // only pass the method ID to the input
+ contract.Input = s.precompile.Methods[bech32.HexToBech32Method].ID
+ return contract
+ },
+ func([]byte) {},
+ false,
+ "abi: attempting to unmarshall an empty string while arguments are expected",
+ },
+ {
+ "fail - HexToBech32 method error",
+ func() *vm.Contract {
+ input, err := s.precompile.Pack(
+ bech32.HexToBech32Method,
+ s.keyring.GetAddr(0),
+ "",
+ )
+ s.Require().NoError(err, "failed to pack input")
+
+ // only pass the method ID to the input
+ contract.Input = input
+ return contract
+ },
+ func([]byte) {},
+ false,
+ "invalid bech32 human readable prefix (HRP)",
+ },
+ {
+ "pass - hex to bech32 account (evmos)",
+ func() *vm.Contract {
+ input, err := s.precompile.Pack(
+ bech32.HexToBech32Method,
+ s.keyring.GetAddr(0),
+ config.Bech32Prefix,
+ )
+ s.Require().NoError(err, "failed to pack input")
+ contract.Input = input
+ return contract
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.HexToBech32Method, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(string)
+ s.Require().True(ok)
+ s.Require().Equal(s.keyring.GetAccAddr(0).String(), addr)
+ },
+ true,
+ "",
+ },
+ {
+ "pass - hex to bech32 validator operator (evmosvaloper)",
+ func() *vm.Contract {
+ input, err := s.precompile.Pack(
+ bech32.HexToBech32Method,
+ common.BytesToAddress(s.network.GetValidators()[0].GetOperator().Bytes()),
+ config.Bech32PrefixValAddr,
+ )
+ s.Require().NoError(err, "failed to pack input")
+ contract.Input = input
+ return contract
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.HexToBech32Method, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(string)
+ s.Require().True(ok)
+ s.Require().Equal(s.network.GetValidators()[0].OperatorAddress, addr)
+ },
+ true,
+ "",
+ },
+ {
+ "pass - hex to bech32 consensus address (evmosvalcons)",
+ func() *vm.Contract {
+ input, err := s.precompile.Pack(
+ bech32.HexToBech32Method,
+ s.keyring.GetAddr(0),
+ config.Bech32PrefixConsAddr,
+ )
+ s.Require().NoError(err, "failed to pack input")
+ contract.Input = input
+ return contract
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.HexToBech32Method, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(string)
+ s.Require().True(ok)
+ s.Require().Equal(sdk.ConsAddress(s.keyring.GetAddr(0).Bytes()).String(), addr)
+ },
+ true,
+ "",
+ },
+ {
+ "pass - bech32 to hex account address",
+ func() *vm.Contract {
+ input, err := s.precompile.Pack(
+ bech32.Bech32ToHexMethod,
+ s.keyring.GetAccAddr(0).String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ contract.Input = input
+ return contract
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.Bech32ToHexMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(common.Address)
+ s.Require().True(ok)
+ s.Require().Equal(s.keyring.GetAddr(0), addr)
+ },
+ true,
+ "",
+ },
+ {
+ "pass - bech32 to hex validator address",
+ func() *vm.Contract {
+ input, err := s.precompile.Pack(
+ bech32.Bech32ToHexMethod,
+ s.network.GetValidators()[0].OperatorAddress,
+ )
+ s.Require().NoError(err, "failed to pack input")
+ contract.Input = input
+ return contract
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.Bech32ToHexMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(common.Address)
+ s.Require().True(ok)
+ s.Require().Equal(common.BytesToAddress(s.network.GetValidators()[0].GetOperator().Bytes()), addr)
+ },
+ true,
+ "",
+ },
+ {
+ "pass - bech32 to hex consensus address",
+ func() *vm.Contract {
+ input, err := s.precompile.Pack(
+ bech32.Bech32ToHexMethod,
+ sdk.ConsAddress(s.keyring.GetAddr(0).Bytes()).String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ contract.Input = input
+ return contract
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.Bech32ToHexMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(common.Address)
+ s.Require().True(ok)
+ s.Require().Equal(s.keyring.GetAddr(0), addr)
+ },
+ true,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ // setup basic test suite
+ s.SetupTest()
+
+ // malleate testcase
+ contract := tc.malleate()
+
+ // Run precompiled contract
+
+ // NOTE: we can ignore the EVM and readonly args since it's a stateless
+ // precompiled contract
+ bz, err := s.precompile.Run(nil, contract, true)
+
+ // Check results
+ if tc.expPass {
+ s.Require().NoError(err, "expected no error when running the precompile")
+ s.Require().NotNil(bz, "expected returned bytes not to be nil")
+ tc.postCheck(bz)
+ } else {
+ s.Require().Error(err, "expected error to be returned when running the precompile")
+ s.Require().Nil(bz, "expected returned bytes to be nil")
+ s.Require().ErrorContains(err, tc.errContains)
+ }
+ })
+ }
+}
diff --git a/precompiles/bech32/methods.go b/precompiles/bech32/methods.go
new file mode 100644
index 00000000..809ae58b
--- /dev/null
+++ b/precompiles/bech32/methods.go
@@ -0,0 +1,95 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package bech32
+
+import (
+ "fmt"
+ "strings"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+const (
+ // HexToBech32Method defines the ABI method name to convert a EIP-55
+ // hex formatted address to bech32 address string.
+ HexToBech32Method = "hexToBech32"
+ // Bech32ToHexMethod defines the ABI method name to convert a bech32
+ // formatted address string to an EIP-55 address.
+ Bech32ToHexMethod = "bech32ToHex"
+)
+
+// HexToBech32 converts a hex address to its corresponding Bech32 format. The Human Readable Prefix
+// (HRP) must be provided in the arguments. This function fails if the address is invalid or if the
+// bech32 conversion fails.
+func (p Precompile) HexToBech32(
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ if len(args) != 2 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ address, ok := args[0].(common.Address)
+ if !ok {
+ return nil, fmt.Errorf("invalid hex address")
+ }
+
+ cfg := sdk.GetConfig()
+
+ prefix, _ := args[1].(string)
+ if strings.TrimSpace(prefix) == "" {
+ return nil, fmt.Errorf(
+ "invalid bech32 human readable prefix (HRP). Please provide a either an account, validator or consensus address prefix (eg: %s, %s, %s)",
+ cfg.GetBech32AccountAddrPrefix(), cfg.GetBech32ValidatorAddrPrefix(), cfg.GetBech32ConsensusAddrPrefix(),
+ )
+ }
+
+ // NOTE: safety check, should not happen given that the address is 20 bytes.
+ if err := sdk.VerifyAddressFormat(address.Bytes()); err != nil {
+ return nil, err
+ }
+
+ bech32Str, err := sdk.Bech32ifyAddressBytes(prefix, address.Bytes())
+ if err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(bech32Str)
+}
+
+// Bech32ToHex converts a bech32 address to its corresponding EIP-55 hex format. The Human Readable Prefix
+// (HRP) must be provided in the arguments. This function fails if the address is invalid or if the
+// bech32 conversion fails.
+func (p Precompile) Bech32ToHex(
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ address, ok := args[0].(string)
+ if !ok || address == "" {
+ return nil, fmt.Errorf("invalid bech32 address: %v", args[0])
+ }
+
+ bech32Prefix := strings.SplitN(address, "1", 2)[0]
+ if bech32Prefix == address {
+ return nil, fmt.Errorf("invalid bech32 address: %s", address)
+ }
+
+ addressBz, err := sdk.GetFromBech32(address, bech32Prefix)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := sdk.VerifyAddressFormat(addressBz); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(common.BytesToAddress(addressBz))
+}
diff --git a/precompiles/bech32/methods_test.go b/precompiles/bech32/methods_test.go
new file mode 100644
index 00000000..bd06bb1a
--- /dev/null
+++ b/precompiles/bech32/methods_test.go
@@ -0,0 +1,202 @@
+package bech32_test
+
+import (
+ "fmt"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/cmd/config"
+ "github.com/evmos/evmos/v19/precompiles/bech32"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+func (s *PrecompileTestSuite) TestHexToBech32() {
+ // setup basic test suite
+ s.SetupTest()
+
+ method := s.precompile.Methods[bech32.HexToBech32Method]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte)
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - invalid args length",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid hex address",
+ func() []interface{} {
+ return []interface{}{
+ "",
+ "",
+ }
+ },
+ func([]byte) {},
+ true,
+ "invalid hex address",
+ },
+ {
+ "fail - invalid bech32 HRP",
+ func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(0),
+ "",
+ }
+ },
+ func([]byte) {},
+ true,
+ "invalid bech32 human readable prefix (HRP)",
+ },
+ {
+ "pass - valid hex address and valid bech32 HRP",
+ func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(0),
+ config.Bech32Prefix,
+ }
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.HexToBech32Method, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(string)
+ s.Require().True(ok)
+ s.Require().Equal(s.keyring.GetAccAddr(0).String(), addr)
+ },
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ bz, err := s.precompile.HexToBech32(&method, tc.malleate())
+
+ if tc.expError {
+ s.Require().Error(err)
+ s.Require().ErrorContains(err, tc.errContains, err.Error())
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestBech32ToHex() {
+ // setup basic test suite
+ s.SetupTest()
+
+ method := s.precompile.Methods[bech32.Bech32ToHexMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte)
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - invalid args length",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 0),
+ },
+ {
+ "fail - empty bech32 address",
+ func() []interface{} {
+ return []interface{}{
+ "",
+ }
+ },
+ func([]byte) {},
+ true,
+ "invalid bech32 address",
+ },
+ {
+ "fail - invalid bech32 address",
+ func() []interface{} {
+ return []interface{}{
+ config.Bech32Prefix,
+ }
+ },
+ func([]byte) {},
+ true,
+ fmt.Sprintf("invalid bech32 address: %s", config.Bech32Prefix),
+ },
+ {
+ "fail - decoding bech32 failed",
+ func() []interface{} {
+ return []interface{}{
+ config.Bech32Prefix + "1",
+ }
+ },
+ func([]byte) {},
+ true,
+ "decoding bech32 failed",
+ },
+ {
+ "fail - invalid address format",
+ func() []interface{} {
+ return []interface{}{
+ sdk.AccAddress(make([]byte, 256)).String(),
+ }
+ },
+ func([]byte) {},
+ true,
+ "address max length is 255",
+ },
+ {
+ "success - valid bech32 address",
+ func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAccAddr(0).String(),
+ }
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(bech32.Bech32ToHexMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ addr, ok := args[0].(common.Address)
+ s.Require().True(ok)
+ s.Require().Equal(s.keyring.GetAddr(0), addr)
+ },
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ bz, err := s.precompile.Bech32ToHex(&method, tc.malleate())
+
+ if tc.expError {
+ s.Require().Error(err)
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
diff --git a/precompiles/bech32/setup_test.go b/precompiles/bech32/setup_test.go
new file mode 100644
index 00000000..a01b0c74
--- /dev/null
+++ b/precompiles/bech32/setup_test.go
@@ -0,0 +1,44 @@
+package bech32_test
+
+import (
+ "testing"
+
+ "github.com/evmos/evmos/v19/precompiles/bech32"
+
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ "github.com/stretchr/testify/suite"
+)
+
+var s *PrecompileTestSuite
+
+// PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 precompile
+// unit tests.
+type PrecompileTestSuite struct {
+ suite.Suite
+
+ network *network.UnitTestNetwork
+ keyring testkeyring.Keyring
+
+ precompile *bech32.Precompile
+}
+
+func TestPrecompileTestSuite(t *testing.T) {
+ s = new(PrecompileTestSuite)
+ suite.Run(t, s)
+}
+
+func (s *PrecompileTestSuite) SetupTest() {
+ keyring := testkeyring.New(2)
+ integrationNetwork := network.NewUnitTestNetwork(
+ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+
+ s.keyring = keyring
+ s.network = integrationNetwork
+
+ precompile, err := bech32.NewPrecompile(6000)
+ s.Require().NoError(err, "failed to create bech32 precompile")
+
+ s.precompile = precompile
+}
diff --git a/precompiles/common/Types.sol b/precompiles/common/Types.sol
new file mode 100644
index 00000000..deeb78d0
--- /dev/null
+++ b/precompiles/common/Types.sol
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+
+/// @dev Allocation represents a single allocation for an IBC fungible token transfer.
+struct ICS20Allocation {
+ string sourcePort;
+ string sourceChannel;
+ Coin[] spendLimit;
+ string[] allowList;
+ string[] allowedPacketData;
+}
+
+/// @dev Dec represents a fixed point decimal value. The value is stored as an integer, and the
+/// precision is stored as a uint8. The value is multiplied by 10^precision to get the actual value.
+struct Dec {
+ uint256 value;
+ uint8 precision;
+}
+
+/// @dev Coin is a struct that represents a token with a denomination and an amount.
+struct Coin {
+ string denom;
+ uint256 amount;
+}
+
+/// @dev DecCoin is a struct that represents a token with a denomination, an amount and a precision.
+struct DecCoin {
+ string denom;
+ uint256 amount;
+ uint8 precision;
+}
+
+/// @dev PageResponse is a struct that represents a page response.
+struct PageResponse {
+ bytes nextKey;
+ uint64 total;
+}
+
+/// @dev PageRequest is a struct that represents a page request.
+struct PageRequest {
+ bytes key;
+ uint64 offset;
+ uint64 limit;
+ bool countTotal;
+ bool reverse;
+}
+
+/// @dev Height is a monotonically increasing data type
+/// that can be compared against another Height for the purposes of updating and
+/// freezing clients
+///
+/// Normally the RevisionHeight is incremented at each height while keeping
+/// RevisionNumber the same. However some consensus algorithms may choose to
+/// reset the height in certain conditions e.g. hard forks, state-machine
+/// breaking changes In these cases, the RevisionNumber is incremented so that
+/// height continues to be monotonically increasing even as the RevisionHeight
+/// gets reset
+struct Height {
+ // the revision that the client is currently on
+ uint64 revisionNumber;
+ // the height within the given revision
+ uint64 revisionHeight;
+}
diff --git a/precompiles/common/abi.go b/precompiles/common/abi.go
new file mode 100644
index 00000000..8ad70937
--- /dev/null
+++ b/precompiles/common/abi.go
@@ -0,0 +1,147 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package common
+
+import (
+ "embed"
+ "fmt"
+ "math/big"
+ "reflect"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+)
+
+// MakeTopic converts a filter query argument into a filter topic.
+// NOTE: This was copied from accounts/abi/topics.go
+func MakeTopic(rule interface{}) (common.Hash, error) {
+ var topic common.Hash
+
+ // Try to generate the topic based on simple types
+ switch rule := rule.(type) {
+ case common.Hash:
+ copy(topic[:], rule[:])
+ case common.Address:
+ copy(topic[common.HashLength-common.AddressLength:], rule[:])
+ case *big.Int:
+ blob := rule.Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case bool:
+ if rule {
+ topic[common.HashLength-1] = 1
+ }
+ case int8:
+ copy(topic[:], genIntType(int64(rule), 1))
+ case int16:
+ copy(topic[:], genIntType(int64(rule), 2))
+ case int32:
+ copy(topic[:], genIntType(int64(rule), 4))
+ case int64:
+ copy(topic[:], genIntType(rule, 8))
+ case uint8:
+ blob := new(big.Int).SetUint64(uint64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case uint16:
+ blob := new(big.Int).SetUint64(uint64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case uint32:
+ blob := new(big.Int).SetUint64(uint64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case uint64:
+ blob := new(big.Int).SetUint64(rule).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case string:
+ hash := crypto.Keccak256Hash([]byte(rule))
+ copy(topic[:], hash[:])
+ case []byte:
+ hash := crypto.Keccak256Hash(rule)
+ copy(topic[:], hash[:])
+
+ default:
+ // todo(rjl493456442) according solidity documentation, indexed event
+ // parameters that are not value types i.e. arrays and structs are not
+ // stored directly but instead a keccak256-hash of an encoding is stored.
+ //
+ // We only convert stringS and bytes to hash, still need to deal with
+ // array(both fixed-size and dynamic-size) and struct.
+
+ // Attempt to generate the topic from funky types
+ val := reflect.ValueOf(rule)
+ switch {
+ // static byte array
+ case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8:
+ reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val)
+ default:
+ return topic, fmt.Errorf("unsupported indexed type: %T", rule)
+ }
+ }
+
+ return topic, nil
+}
+
+// UnpackLog unpacks a retrieved log into the provided output structure.
+func UnpackLog(contractABI abi.ABI, out interface{}, event string, log ethtypes.Log) error {
+ if log.Topics[0] != contractABI.Events[event].ID {
+ return fmt.Errorf("event signature mismatch")
+ }
+ if len(log.Data) > 0 {
+ if err := contractABI.UnpackIntoInterface(out, event, log.Data); err != nil {
+ return err
+ }
+ }
+ var indexed abi.Arguments
+ for _, arg := range contractABI.Events[event].Inputs {
+ if arg.Indexed {
+ indexed = append(indexed, arg)
+ }
+ }
+ return abi.ParseTopics(out, indexed, log.Topics[1:])
+}
+
+// NOTE: This was copied from accounts/abi/topics.go
+func genIntType(rule int64, size uint) []byte {
+ var topic [common.HashLength]byte
+ if rule < 0 {
+ // if a rule is negative, we need to put it into two's complement.
+ // extended to common.HashLength bytes.
+ topic = [common.HashLength]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
+ }
+ for i := uint(0); i < size; i++ {
+ topic[common.HashLength-i-1] = byte(rule >> (i * 8))
+ }
+ return topic[:]
+}
+
+// PackNum packs the given number (using the reflect value) and will cast it to appropriate number representation.
+func PackNum(value reflect.Value) []byte {
+ switch kind := value.Kind(); kind {
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return math.U256Bytes(new(big.Int).SetUint64(value.Uint()))
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return math.U256Bytes(big.NewInt(value.Int()))
+ case reflect.Ptr:
+ return math.U256Bytes(new(big.Int).Set(value.Interface().(*big.Int)))
+ default:
+ panic("abi: fatal error")
+ }
+}
+
+// LoadABI read the ABI file described by the path and parse it as JSON.
+func LoadABI(fs embed.FS, path string) (abi.ABI, error) {
+ abiBz, err := fs.ReadFile(path)
+ if err != nil {
+ return abi.ABI{}, fmt.Errorf("error loading the ABI %s", err)
+ }
+
+ contract, err := contractutils.ConvertPrecompileHardhatBytesToCompiledContract(abiBz)
+ if err != nil {
+ return abi.ABI{}, fmt.Errorf(ErrInvalidABI, err)
+ }
+
+ return contract.ABI, nil
+}
diff --git a/precompiles/common/errors.go b/precompiles/common/errors.go
new file mode 100644
index 00000000..7c31bcb5
--- /dev/null
+++ b/precompiles/common/errors.go
@@ -0,0 +1,41 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package common
+
+const (
+ // ErrNotRunInEvm is raised when a function is not called inside the EVM.
+ ErrNotRunInEvm = "not run in EVM"
+ // ErrDelegatorDifferentOrigin is raised when an approval is set but the origin address is not the same as the spender.
+ ErrDelegatorDifferentOrigin = "tx origin address %s does not match the delegator address %s"
+ // ErrSpenderDifferentOrigin is raised when the origin address is not the same as the spender.
+ ErrSpenderDifferentOrigin = "tx origin address %s does not match the spender address %s"
+ // ErrInvalidABI is raised when the ABI cannot be parsed.
+ ErrInvalidABI = "invalid ABI: %w"
+ // ErrInvalidAmount is raised when the amount cannot be cast to a big.Int.
+ ErrInvalidAmount = "invalid amount: %v"
+ // ErrInvalidHexAddress is raised when the hex address is not valid.
+ ErrInvalidHexAddress = "invalid hex address address: %s"
+ // ErrInvalidDelegator is raised when the delegator address is not valid.
+ ErrInvalidDelegator = "invalid delegator address: %s"
+ // ErrInvalidValidator is raised when the validator address is not valid.
+ ErrInvalidValidator = "invalid validator address: %s"
+ // ErrInvalidDenom is raised when the denom is not valid.
+ ErrInvalidDenom = "invalid denom: %s"
+ // ErrInvalidMsgType is raised when the transaction type is not valid for the given precompile.
+ ErrInvalidMsgType = "invalid %s transaction type: %s"
+ // ErrInvalidNumberOfArgs is raised when the number of arguments is not what is expected.
+ ErrInvalidNumberOfArgs = "invalid number of arguments; expected %d; got: %d"
+ // ErrUnknownMethod is raised when the method is not known.
+ ErrUnknownMethod = "unknown method: %s"
+ // ErrIntegerOverflow is raised when an integer overflow occurs.
+ ErrIntegerOverflow = "integer overflow when increasing allowance"
+ // ErrNegativeAmount is raised when an amount is negative.
+ ErrNegativeAmount = "negative amount when decreasing allowance"
+ // ErrInvalidType is raised when the provided type is different than the expected.
+ ErrInvalidType = "invalid type for %s: expected %T, received %T"
+ // ErrInvalidDescription is raised when the input description cannot be cast to stakingtypes.Description{}.
+ ErrInvalidDescription = "invalid description: %v"
+ // ErrInvalidCommission is raised when the input commission cannot be cast to stakingtypes.CommissionRates{}.
+ ErrInvalidCommission = "invalid commission: %v"
+)
diff --git a/precompiles/common/events.go b/precompiles/common/events.go
new file mode 100644
index 00000000..af8b1e42
--- /dev/null
+++ b/precompiles/common/events.go
@@ -0,0 +1,26 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package common
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// EmitEventArgs are the arguments required to emit an authorization event.
+//
+// The event type can be:
+// - ApprovalEvent
+// - GenericApprovalEvent
+// - AllowanceChangeEvent
+// - ...
+type EmitEventArgs struct {
+ Ctx sdk.Context
+ StateDB vm.StateDB
+ ContractAddr common.Address
+ ContractEvents map[string]abi.Event
+ EventData interface{}
+}
diff --git a/precompiles/common/precompile.go b/precompiles/common/precompile.go
new file mode 100644
index 00000000..b18392f7
--- /dev/null
+++ b/precompiles/common/precompile.go
@@ -0,0 +1,258 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package common
+
+import (
+ "fmt"
+ "math/big"
+ "time"
+
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+)
+
+// Precompile is a common struct for all precompiles that holds the common data each
+// precompile needs to run which includes the ABI, Gas config, approval expiration and the authz keeper.
+type Precompile struct {
+ abi.ABI
+ AuthzKeeper authzkeeper.Keeper
+ ApprovalExpiration time.Duration
+ KvGasConfig storetypes.GasConfig
+ TransientKVGasConfig storetypes.GasConfig
+ address common.Address
+ journalEntries []balanceChangeEntry
+}
+
+// Operation is a type that defines if the precompile call
+// produced an addition or subtraction of an account's balance
+type Operation int8
+
+const (
+ Sub Operation = iota
+ Add
+)
+
+type balanceChangeEntry struct {
+ Account common.Address
+ Amount *big.Int
+ Op Operation
+}
+
+func NewBalanceChangeEntry(acc common.Address, amt *big.Int, op Operation) balanceChangeEntry { //nolint:revive
+ return balanceChangeEntry{acc, amt, op}
+}
+
+// snapshot contains all state and events previous to the precompile call
+// This is needed to allow us to revert the changes
+// during the EVM execution
+type snapshot struct {
+ MultiStore sdk.CacheMultiStore
+ Events sdk.Events
+}
+
+// RequiredGas calculates the base minimum required gas for a transaction or a query.
+// It uses the method ID to determine if the input is a transaction or a query and
+// uses the Cosmos SDK gas config flat cost and the flat per byte cost * len(argBz) to calculate the gas.
+func (p Precompile) RequiredGas(input []byte, isTransaction bool) uint64 {
+ argsBz := input[4:]
+
+ if isTransaction {
+ return p.KvGasConfig.WriteCostFlat + (p.KvGasConfig.WriteCostPerByte * uint64(len(argsBz)))
+ }
+
+ return p.KvGasConfig.ReadCostFlat + (p.KvGasConfig.ReadCostPerByte * uint64(len(argsBz)))
+}
+
+// RunSetup runs the initial setup required to run a transaction or a query.
+// It returns the sdk Context, EVM stateDB, ABI method, initial gas and calling arguments.
+func (p Precompile) RunSetup(
+ evm *vm.EVM,
+ contract *vm.Contract,
+ readOnly bool,
+ isTransaction func(name string) bool,
+) (ctx sdk.Context, stateDB *statedb.StateDB, s snapshot, method *abi.Method, gasConfig storetypes.Gas, args []interface{}, err error) { //nolint:revive
+ stateDB, ok := evm.StateDB.(*statedb.StateDB)
+ if !ok {
+ return sdk.Context{}, nil, s, nil, uint64(0), nil, fmt.Errorf(ErrNotRunInEvm)
+ }
+
+ // get the stateDB cache ctx
+ ctx, err = stateDB.GetCacheContext()
+ if err != nil {
+ return sdk.Context{}, nil, s, nil, uint64(0), nil, err
+ }
+
+ // take a snapshot of the current state before any changes
+ // to be able to revert the changes
+ s.MultiStore = stateDB.MultiStoreSnapshot()
+ s.Events = ctx.EventManager().Events()
+
+ // commit the current changes in the cache ctx
+ // to get the updated state for the precompile call
+ if err := stateDB.CommitWithCacheCtx(); err != nil {
+ return sdk.Context{}, nil, s, nil, uint64(0), nil, err
+ }
+
+ // NOTE: This is a special case where the calling transaction does not specify a function name.
+ // In this case we default to a `fallback` or `receive` function on the contract.
+
+ // Simplify the calldata checks
+ isEmptyCallData := len(contract.Input) == 0
+ isShortCallData := len(contract.Input) > 0 && len(contract.Input) < 4
+ isStandardCallData := len(contract.Input) >= 4
+
+ switch {
+ // Case 1: Calldata is empty
+ case isEmptyCallData:
+ method, err = p.emptyCallData(contract)
+
+ // Case 2: calldata is non-empty but less than 4 bytes needed for a method
+ case isShortCallData:
+ method, err = p.methodIDCallData()
+
+ // Case 3: calldata is non-empty and contains the minimum 4 bytes needed for a method
+ case isStandardCallData:
+ method, err = p.standardCallData(contract)
+ }
+
+ if err != nil {
+ return sdk.Context{}, nil, s, nil, uint64(0), nil, err
+ }
+
+ // return error if trying to write to state during a read-only call
+ if readOnly && isTransaction(method.Name) {
+ return sdk.Context{}, nil, s, nil, uint64(0), nil, vm.ErrWriteProtection
+ }
+
+ // if the method type is `function` continue looking for arguments
+ if method.Type == abi.Function {
+ argsBz := contract.Input[4:]
+ args, err = method.Inputs.Unpack(argsBz)
+ if err != nil {
+ return sdk.Context{}, nil, s, nil, uint64(0), nil, err
+ }
+ }
+
+ initialGas := ctx.GasMeter().GasConsumed()
+
+ defer HandleGasError(ctx, contract, initialGas, &err)()
+
+ // set the default SDK gas configuration to track gas usage
+ // we are changing the gas meter type, so it panics gracefully when out of gas
+ ctx = ctx.WithGasMeter(storetypes.NewGasMeter(contract.Gas)).
+ WithKVGasConfig(p.KvGasConfig).
+ WithTransientKVGasConfig(p.TransientKVGasConfig)
+ // we need to consume the gas that was already used by the EVM
+ ctx.GasMeter().ConsumeGas(initialGas, "creating a new gas meter")
+
+ return ctx, stateDB, s, method, initialGas, args, nil
+}
+
+// HandleGasError handles the out of gas panic by resetting the gas meter and returning an error.
+// This is used in order to avoid panics and to allow for the EVM to continue cleanup if the tx or query run out of gas.
+func HandleGasError(ctx sdk.Context, contract *vm.Contract, initialGas storetypes.Gas, err *error) func() {
+ return func() {
+ if r := recover(); r != nil {
+ switch r.(type) {
+ case sdk.ErrorOutOfGas:
+ // update contract gas
+ usedGas := ctx.GasMeter().GasConsumed() - initialGas
+ _ = contract.UseGas(usedGas)
+
+ *err = vm.ErrOutOfGas
+ // FIXME: add InfiniteGasMeter with previous Gas limit.
+ ctx = ctx.WithKVGasConfig(storetypes.GasConfig{}).
+ WithTransientKVGasConfig(storetypes.GasConfig{})
+ default:
+ panic(r)
+ }
+ }
+ }
+}
+
+// AddJournalEntries adds the balanceChange (if corresponds)
+// and precompileCall entries on the stateDB journal
+// This allows to revert the call changes within an evm tx
+func (p Precompile) AddJournalEntries(stateDB *statedb.StateDB, s snapshot) error {
+ for _, entry := range p.journalEntries {
+ switch entry.Op {
+ case Sub:
+ // add the corresponding balance change to the journal
+ stateDB.SubBalance(entry.Account, entry.Amount)
+ case Add:
+ // add the corresponding balance change to the journal
+ stateDB.AddBalance(entry.Account, entry.Amount)
+ }
+ }
+
+ if err := stateDB.AddPrecompileFn(p.Address(), s.MultiStore, s.Events); err != nil {
+ return err
+ }
+ return nil
+}
+
+// SetBalanceChangeEntries sets the balanceChange entries
+// as the journalEntries field of the precompile.
+// These entries will be added to the stateDB's journal
+// when calling the AddJournalEntries function
+func (p *Precompile) SetBalanceChangeEntries(entries ...balanceChangeEntry) {
+ p.journalEntries = entries
+}
+
+func (p Precompile) Address() common.Address {
+ return p.address
+}
+
+func (p *Precompile) SetAddress(addr common.Address) {
+ p.address = addr
+}
+
+// emptyCallData is a helper function that returns the method to be called when the calldata is empty.
+func (p Precompile) emptyCallData(contract *vm.Contract) (method *abi.Method, err error) {
+ switch {
+ // Case 1.1: Send call or transfer tx - 'receive' is called if present and value is transferred
+ case contract.Value().Sign() > 0 && p.HasReceive():
+ return &p.Receive, nil
+ // Case 1.2: Either 'receive' is not present, or no value is transferred - call 'fallback' if present
+ case p.HasFallback():
+ return &p.Fallback, nil
+ // Case 1.3: Neither 'receive' nor 'fallback' are present - return error
+ default:
+ return nil, vm.ErrExecutionReverted
+ }
+}
+
+// methodIDCallData is a helper function that returns the method to be called when the calldata is less than 4 bytes.
+func (p Precompile) methodIDCallData() (method *abi.Method, err error) {
+ // Case 2.2: calldata contains less than 4 bytes needed for a method and 'fallback' is not present - return error
+ if !p.HasFallback() {
+ return nil, vm.ErrExecutionReverted
+ }
+ // Case 2.1: calldata contains less than 4 bytes needed for a method - 'fallback' is called if present
+ return &p.Fallback, nil
+}
+
+// standardCallData is a helper function that returns the method to be called when the calldata is 4 bytes or more.
+func (p Precompile) standardCallData(contract *vm.Contract) (method *abi.Method, err error) {
+ methodID := contract.Input[:4]
+ // NOTE: this function iterates over the method map and returns
+ // the method with the given ID
+ method, err = p.MethodById(methodID)
+
+ // Case 3.1 calldata contains a non-existing method ID, and `fallback` is not present - return error
+ if err != nil && !p.HasFallback() {
+ return nil, err
+ }
+
+ // Case 3.2: calldata contains a non-existing method ID - 'fallback' is called if present
+ if err != nil && p.HasFallback() {
+ return &p.Fallback, nil
+ }
+
+ return method, nil
+}
diff --git a/precompiles/common/types.go b/precompiles/common/types.go
new file mode 100644
index 00000000..c99e2c93
--- /dev/null
+++ b/precompiles/common/types.go
@@ -0,0 +1,107 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package common
+
+import (
+ "math/big"
+ "strings"
+ "time"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ evmosutils "github.com/evmos/evmos/v19/utils"
+)
+
+var (
+ // TrueValue is the byte array representing a true value in solidity.
+ TrueValue = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}
+ // DefaultExpirationDuration is the default duration for an authorization to expire.
+ DefaultExpirationDuration = time.Hour * 24 * 365
+ // DefaultChainID is the standard chain id used for testing purposes
+ DefaultChainID = evmosutils.MainnetChainID + "-1"
+)
+
+// ICS20Allocation defines the spend limit for a particular port and channel.
+// We need this to be able to unpack to big.Int instead of math.Int.
+type ICS20Allocation struct {
+ SourcePort string
+ SourceChannel string
+ SpendLimit []Coin
+ AllowList []string
+ AllowedPacketData []string
+}
+
+// Coin defines a struct that stores all needed information about a coin
+// in types native to the EVM.
+type Coin struct {
+ Denom string
+ Amount *big.Int
+}
+
+// DecCoin defines a struct that stores all needed information about a decimal coin
+// in types native to the EVM.
+type DecCoin struct {
+ Denom string
+ Amount *big.Int
+ Precision uint8
+}
+
+// Dec defines a struct that represents a decimal number of a given precision
+// in types native to the EVM.
+type Dec struct {
+ Value *big.Int
+ Precision uint8
+}
+
+// ToSDKType converts the Coin to the Cosmos SDK representation.
+func (c Coin) ToSDKType() sdk.Coin {
+ return sdk.NewCoin(c.Denom, math.NewIntFromBigInt(c.Amount))
+}
+
+// NewCoinsResponse converts a response to an array of Coin.
+func NewCoinsResponse(amount sdk.Coins) []Coin {
+ // Create a new output for each coin and add it to the output array.
+ outputs := make([]Coin, len(amount))
+ for i, coin := range amount {
+ outputs[i] = Coin{
+ Denom: coin.Denom,
+ Amount: coin.Amount.BigInt(),
+ }
+ }
+ return outputs
+}
+
+// NewDecCoinsResponse converts a response to an array of DecCoin.
+func NewDecCoinsResponse(amount sdk.DecCoins) []DecCoin {
+ // Create a new output for each coin and add it to the output array.
+ outputs := make([]DecCoin, len(amount))
+ for i, coin := range amount {
+ outputs[i] = DecCoin{
+ Denom: coin.Denom,
+ Amount: coin.Amount.TruncateInt().BigInt(),
+ Precision: math.LegacyPrecision,
+ }
+ }
+ return outputs
+}
+
+// HexAddressFromBech32String converts a hex address to a bech32 encoded address.
+func HexAddressFromBech32String(addr string) (res common.Address, err error) {
+ if strings.Contains(addr, sdk.PrefixValidator) {
+ valAddr, err := sdk.ValAddressFromBech32(addr)
+ if err != nil {
+ return res, err
+ }
+ return common.BytesToAddress(valAddr.Bytes()), nil
+ }
+ return common.BytesToAddress(sdk.MustAccAddressFromBech32(addr)), nil
+}
+
+// SafeAdd adds two integers and returns a boolean if an overflow occurs to avoid panic.
+// TODO: Upstream this to the SDK math package.
+func SafeAdd(a, b math.Int) (res *big.Int, overflow bool) {
+ res = a.BigInt().Add(a.BigInt(), b.BigInt())
+ return res, res.BitLen() > math.MaxBitLen
+}
diff --git a/precompiles/common/types_test.go b/precompiles/common/types_test.go
new file mode 100644
index 00000000..bb70f115
--- /dev/null
+++ b/precompiles/common/types_test.go
@@ -0,0 +1,47 @@
+package common_test
+
+import (
+ "testing"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/stretchr/testify/require"
+)
+
+var largeAmt, _ = math.NewIntFromString("1000000000000000000000000000000000000000")
+
+func TestNewCoinsResponse(t *testing.T) {
+ testCases := []struct {
+ amount math.Int
+ }{
+ {amount: math.NewInt(1)},
+ {amount: largeAmt},
+ }
+
+ for _, tc := range testCases {
+ coin := sdk.NewCoin(utils.BaseDenom, tc.amount)
+ coins := sdk.NewCoins(coin)
+ res := common.NewCoinsResponse(coins)
+ require.Equal(t, 1, len(res))
+ require.Equal(t, tc.amount.BigInt(), res[0].Amount)
+ }
+}
+
+func TestNewDecCoinsResponse(t *testing.T) {
+ testCases := []struct {
+ amount math.Int
+ }{
+ {amount: math.NewInt(1)},
+ {amount: largeAmt},
+ }
+
+ for _, tc := range testCases {
+ coin := sdk.NewDecCoin(utils.BaseDenom, tc.amount)
+ coins := sdk.NewDecCoins(coin)
+ res := common.NewDecCoinsResponse(coins)
+ require.Equal(t, 1, len(res))
+ require.Equal(t, tc.amount.BigInt(), res[0].Amount)
+ }
+}
diff --git a/precompiles/distribution/DistributionI.sol b/precompiles/distribution/DistributionI.sol
new file mode 100644
index 00000000..ae58acec
--- /dev/null
+++ b/precompiles/distribution/DistributionI.sol
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../common/Types.sol";
+
+/// @dev The DistributionI contract's address.
+address constant DISTRIBUTION_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000801;
+
+/// @dev Define all the available distribution methods.
+string constant MSG_SET_WITHDRAWER_ADDRESS = "/cosmos.distribution.v1beta1.MsgSetWithdrawAddress";
+string constant MSG_WITHDRAW_DELEGATOR_REWARD = "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward";
+string constant MSG_WITHDRAW_VALIDATOR_COMMISSION = "/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission";
+
+/// @dev The DistributionI contract's instance.
+DistributionI constant DISTRIBUTION_CONTRACT = DistributionI(
+ DISTRIBUTION_PRECOMPILE_ADDRESS
+);
+
+struct ValidatorSlashEvent {
+ uint64 validatorPeriod;
+ Dec fraction;
+}
+
+struct ValidatorDistributionInfo {
+ string operatorAddress;
+ DecCoin[] selfBondRewards;
+ DecCoin[] commission;
+}
+
+struct DelegationDelegatorReward {
+ string validatorAddress;
+ DecCoin[] reward;
+}
+
+/// @author Evmos Team
+/// @title Distribution Precompile Contract
+/// @dev The interface through which solidity contracts will interact with Distribution
+/// @custom:address 0x0000000000000000000000000000000000000801
+interface DistributionI {
+ /// @dev ClaimRewards defines an Event emitted when rewards are claimed
+ /// @param delegatorAddress the address of the delegator
+ /// @param amount the amount being claimed
+ event ClaimRewards(address indexed delegatorAddress, uint256 amount);
+
+ /// @dev SetWithdrawerAddress defines an Event emitted when a new withdrawer address is being set
+ /// @param caller the caller of the transaction
+ /// @param withdrawerAddress the newly set withdrawer address
+ event SetWithdrawerAddress(
+ address indexed caller,
+ string withdrawerAddress
+ );
+
+ /// @dev WithdrawDelegatorRewards defines an Event emitted when rewards from a delegation are withdrawn
+ /// @param delegatorAddress the address of the delegator
+ /// @param validatorAddress the address of the validator
+ /// @param amount the amount being withdrawn from the delegation
+ event WithdrawDelegatorRewards(
+ address indexed delegatorAddress,
+ address indexed validatorAddress,
+ uint256 amount
+ );
+
+ /// @dev WithdrawValidatorCommission defines an Event emitted when validator commissions are being withdrawn
+ /// @param validatorAddress is the address of the validator
+ /// @param commission is the total commission earned by the validator
+ event WithdrawValidatorCommission(
+ string indexed validatorAddress,
+ uint256 commission
+ );
+
+ /// @dev FundCommunityPool defines an Event emitted when an account
+ /// fund the community pool
+ /// @param depositor the address funding the community pool
+ /// @param amount the amount being sent to the community pool
+ event FundCommunityPool(address indexed depositor, uint256 amount);
+
+ /// TRANSACTIONS
+
+ /// @dev Claims all rewards from a select set of validators or all of them for a delegator.
+ /// @param delegatorAddress The address of the delegator
+ /// @param maxRetrieve The maximum number of validators to claim rewards from
+ /// @return success Whether the transaction was successful or not
+ function claimRewards(
+ address delegatorAddress,
+ uint32 maxRetrieve
+ ) external returns (bool success);
+
+ /// @dev Change the address, that can withdraw the rewards of a delegator.
+ /// Note that this address cannot be a module account.
+ /// @param delegatorAddress The address of the delegator
+ /// @param withdrawerAddress The address that will be capable of withdrawing rewards for
+ /// the given delegator address
+ function setWithdrawAddress(
+ address delegatorAddress,
+ string memory withdrawerAddress
+ ) external returns (bool success);
+
+ /// @dev Withdraw the rewards of a delegator from a validator
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @return amount The amount of Coin withdrawn
+ function withdrawDelegatorRewards(
+ address delegatorAddress,
+ string memory validatorAddress
+ ) external returns (Coin[] calldata amount);
+
+ /// @dev Withdraws the rewards commission of a validator.
+ /// @param validatorAddress The address of the validator
+ /// @return amount The amount of Coin withdrawn
+ function withdrawValidatorCommission(
+ string memory validatorAddress
+ ) external returns (Coin[] calldata amount);
+
+ /// @dev fundCommunityPool defines a method to allow an account to directly
+ /// fund the community pool.
+ /// @param depositor The address of the depositor
+ /// @param amount The amount of coin sent to the community pool
+ /// @return success Whether the transaction was successful or not
+ function fundCommunityPool(
+ address depositor,
+ uint256 amount
+ ) external returns (bool success);
+
+ /// QUERIES
+ /// @dev Queries validator commission and self-delegation rewards for validator.
+ /// @param validatorAddress The address of the validator
+ /// @return distributionInfo The validator's distribution info
+ function validatorDistributionInfo(
+ string memory validatorAddress
+ )
+ external
+ view
+ returns (ValidatorDistributionInfo calldata distributionInfo);
+
+ /// @dev Queries the outstanding rewards of a validator address.
+ /// @param validatorAddress The address of the validator
+ /// @return rewards The validator's outstanding rewards
+ function validatorOutstandingRewards(
+ string memory validatorAddress
+ ) external view returns (DecCoin[] calldata rewards);
+
+ /// @dev Queries the accumulated commission for a validator.
+ /// @param validatorAddress The address of the validator
+ /// @return commission The validator's commission
+ function validatorCommission(
+ string memory validatorAddress
+ ) external view returns (DecCoin[] calldata commission);
+
+ /// @dev Queries the slashing events for a validator in a given height interval
+ /// defined by the starting and ending height.
+ /// @param validatorAddress The address of the validator
+ /// @param startingHeight The starting height
+ /// @param endingHeight The ending height
+ /// @param pageRequest Defines a pagination for the request.
+ /// @return slashes The validator's slash events
+ /// @return pageResponse The pagination response for the query
+ function validatorSlashes(
+ string memory validatorAddress,
+ uint64 startingHeight,
+ uint64 endingHeight,
+ PageRequest calldata pageRequest
+ )
+ external
+ view
+ returns (
+ ValidatorSlashEvent[] calldata slashes,
+ PageResponse calldata pageResponse
+ );
+
+ /// @dev Queries the total rewards accrued by a delegation from a specific address to a given validator.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @return rewards The total rewards accrued by a delegation.
+ function delegationRewards(
+ address delegatorAddress,
+ string memory validatorAddress
+ ) external view returns (DecCoin[] calldata rewards);
+
+ /// @dev Queries the total rewards accrued by each validator, that a given
+ /// address has delegated to.
+ /// @param delegatorAddress The address of the delegator
+ /// @return rewards The total rewards accrued by each validator for a delegator.
+ /// @return total The total rewards accrued by a delegator.
+ function delegationTotalRewards(
+ address delegatorAddress
+ )
+ external
+ view
+ returns (
+ DelegationDelegatorReward[] calldata rewards,
+ DecCoin[] calldata total
+ );
+
+ /// @dev Queries all validators, that a given address has delegated to.
+ /// @param delegatorAddress The address of the delegator
+ /// @return validators The addresses of all validators, that were delegated to by the given address.
+ function delegatorValidators(
+ address delegatorAddress
+ ) external view returns (string[] calldata validators);
+
+ /// @dev Queries the address capable of withdrawing rewards for a given delegator.
+ /// @param delegatorAddress The address of the delegator
+ /// @return withdrawAddress The address capable of withdrawing rewards for the delegator.
+ function delegatorWithdrawAddress(
+ address delegatorAddress
+ ) external view returns (string memory withdrawAddress);
+}
diff --git a/precompiles/distribution/abi.json b/precompiles/distribution/abi.json
new file mode 100644
index 00000000..ee69d2c0
--- /dev/null
+++ b/precompiles/distribution/abi.json
@@ -0,0 +1,644 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "DistributionI",
+ "sourceName": "solidity/precompiles/distribution/DistributionI.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "ClaimRewards",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "depositor",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "FundCommunityPool",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "caller",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "withdrawerAddress",
+ "type": "string"
+ }
+ ],
+ "name": "SetWithdrawerAddress",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "WithdrawDelegatorRewards",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "commission",
+ "type": "uint256"
+ }
+ ],
+ "name": "WithdrawValidatorCommission",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint32",
+ "name": "maxRetrieve",
+ "type": "uint32"
+ }
+ ],
+ "name": "claimRewards",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "delegationRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "rewards",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ }
+ ],
+ "name": "delegationTotalRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "reward",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct DelegationDelegatorReward[]",
+ "name": "rewards",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "total",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ }
+ ],
+ "name": "delegatorValidators",
+ "outputs": [
+ {
+ "internalType": "string[]",
+ "name": "validators",
+ "type": "string[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ }
+ ],
+ "name": "delegatorWithdrawAddress",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "withdrawAddress",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "depositor",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "fundCommunityPool",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "withdrawerAddress",
+ "type": "string"
+ }
+ ],
+ "name": "setWithdrawAddress",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "validatorCommission",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "commission",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "validatorDistributionInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "operatorAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "selfBondRewards",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "commission",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct ValidatorDistributionInfo",
+ "name": "distributionInfo",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "validatorOutstandingRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "rewards",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "uint64",
+ "name": "startingHeight",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "endingHeight",
+ "type": "uint64"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "validatorSlashes",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint64",
+ "name": "validatorPeriod",
+ "type": "uint64"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct Dec",
+ "name": "fraction",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct ValidatorSlashEvent[]",
+ "name": "slashes",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "pageResponse",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "withdrawDelegatorRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "amount",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "withdrawValidatorCommission",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "amount",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x",
+ "deployedBytecode": "0x",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/distribution/distribution.go b/precompiles/distribution/distribution.go
new file mode 100644
index 00000000..788c7528
--- /dev/null
+++ b/precompiles/distribution/distribution.go
@@ -0,0 +1,160 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package distribution
+
+import (
+ "embed"
+ "fmt"
+
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ stakingkeeper "github.com/evmos/evmos/v19/x/staking/keeper"
+)
+
+var _ vm.PrecompiledContract = &Precompile{}
+
+// Embed abi json file to the executable binary. Needed when importing as dependency.
+//
+//go:embed abi.json
+var f embed.FS
+
+// Precompile defines the precompiled contract for distribution.
+type Precompile struct {
+ cmn.Precompile
+ distributionKeeper distributionkeeper.Keeper
+ stakingKeeper stakingkeeper.Keeper
+}
+
+// NewPrecompile creates a new distribution Precompile instance as a
+// PrecompiledContract interface.
+func NewPrecompile(
+ distributionKeeper distributionkeeper.Keeper,
+ stakingKeeper stakingkeeper.Keeper,
+ authzKeeper authzkeeper.Keeper,
+) (*Precompile, error) {
+ newAbi, err := cmn.LoadABI(f, "abi.json")
+ if err != nil {
+ return nil, fmt.Errorf("error loading the distribution ABI %s", err)
+ }
+
+ p := &Precompile{
+ Precompile: cmn.Precompile{
+ ABI: newAbi,
+ AuthzKeeper: authzKeeper,
+ KvGasConfig: storetypes.KVGasConfig(),
+ TransientKVGasConfig: storetypes.TransientGasConfig(),
+ ApprovalExpiration: cmn.DefaultExpirationDuration, // should be configurable in the future.
+ },
+ stakingKeeper: stakingKeeper,
+ distributionKeeper: distributionKeeper,
+ }
+
+ // SetAddress defines the address of the distribution compile contract.
+ p.SetAddress(common.HexToAddress(evmtypes.DistributionPrecompileAddress))
+
+ return p, nil
+}
+
+// RequiredGas calculates the precompiled contract's base gas rate.
+func (p Precompile) RequiredGas(input []byte) uint64 {
+ // NOTE: This check avoid panicking when trying to decode the method ID
+ if len(input) < 4 {
+ return 0
+ }
+
+ methodID := input[:4]
+
+ method, err := p.MethodById(methodID)
+ if err != nil {
+ // This should never happen since this method is going to fail during Run
+ return 0
+ }
+
+ return p.Precompile.RequiredGas(input, p.IsTransaction(method.Name))
+}
+
+// Run executes the precompiled contract distribution methods defined in the ABI.
+func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) {
+ ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction)
+ if err != nil {
+ return nil, err
+ }
+
+ // This handles any out of gas errors that may occur during the execution of a precompile tx or query.
+ // It avoids panics and returns the out of gas error so the EVM can continue gracefully.
+ defer cmn.HandleGasError(ctx, contract, initialGas, &err)()
+
+ switch method.Name {
+ // Custom transactions
+ case ClaimRewardsMethod:
+ bz, err = p.ClaimRewards(ctx, evm.Origin, contract, stateDB, method, args)
+ // Distribution transactions
+ case SetWithdrawAddressMethod:
+ bz, err = p.SetWithdrawAddress(ctx, evm.Origin, contract, stateDB, method, args)
+ case WithdrawDelegatorRewardsMethod:
+ bz, err = p.WithdrawDelegatorRewards(ctx, evm.Origin, contract, stateDB, method, args)
+ case WithdrawValidatorCommissionMethod:
+ bz, err = p.WithdrawValidatorCommission(ctx, evm.Origin, contract, stateDB, method, args)
+ case FundCommunityPoolMethod:
+ bz, err = p.FundCommunityPool(ctx, evm.Origin, contract, stateDB, method, args)
+ // Distribution queries
+ case ValidatorDistributionInfoMethod:
+ bz, err = p.ValidatorDistributionInfo(ctx, contract, method, args)
+ case ValidatorOutstandingRewardsMethod:
+ bz, err = p.ValidatorOutstandingRewards(ctx, contract, method, args)
+ case ValidatorCommissionMethod:
+ bz, err = p.ValidatorCommission(ctx, contract, method, args)
+ case ValidatorSlashesMethod:
+ bz, err = p.ValidatorSlashes(ctx, contract, method, args)
+ case DelegationRewardsMethod:
+ bz, err = p.DelegationRewards(ctx, contract, method, args)
+ case DelegationTotalRewardsMethod:
+ bz, err = p.DelegationTotalRewards(ctx, contract, method, args)
+ case DelegatorValidatorsMethod:
+ bz, err = p.DelegatorValidators(ctx, contract, method, args)
+ case DelegatorWithdrawAddressMethod:
+ bz, err = p.DelegatorWithdrawAddress(ctx, contract, method, args)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ cost := ctx.GasMeter().GasConsumed() - initialGas
+
+ if !contract.UseGas(cost) {
+ return nil, vm.ErrOutOfGas
+ }
+
+ if err := p.AddJournalEntries(stateDB, snapshot); err != nil {
+ return nil, err
+ }
+
+ return bz, nil
+}
+
+// IsTransaction checks if the given method name corresponds to a transaction or query.
+//
+// Available distribution transactions are:
+// - ClaimRewards
+// - SetWithdrawAddress
+// - WithdrawDelegatorRewards
+// - WithdrawValidatorCommission
+func (Precompile) IsTransaction(methodName string) bool {
+ switch methodName {
+ case ClaimRewardsMethod,
+ SetWithdrawAddressMethod,
+ WithdrawDelegatorRewardsMethod,
+ WithdrawValidatorCommissionMethod,
+ FundCommunityPoolMethod:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/precompiles/distribution/distribution_test.go b/precompiles/distribution/distribution_test.go
new file mode 100644
index 00000000..67884f14
--- /dev/null
+++ b/precompiles/distribution/distribution_test.go
@@ -0,0 +1,239 @@
+package distribution_test
+
+import (
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (s *PrecompileTestSuite) TestIsTransaction() {
+ testCases := []struct {
+ name string
+ method string
+ isTx bool
+ }{
+ {
+ distribution.SetWithdrawAddressMethod,
+ s.precompile.Methods[distribution.SetWithdrawAddressMethod].Name,
+ true,
+ },
+ {
+ distribution.WithdrawDelegatorRewardsMethod,
+ s.precompile.Methods[distribution.WithdrawDelegatorRewardsMethod].Name,
+ true,
+ },
+ {
+ distribution.WithdrawValidatorCommissionMethod,
+ s.precompile.Methods[distribution.WithdrawValidatorCommissionMethod].Name,
+ true,
+ },
+ {
+ distribution.FundCommunityPoolMethod,
+ s.precompile.Methods[distribution.FundCommunityPoolMethod].Name,
+ true,
+ },
+ {
+ distribution.ValidatorDistributionInfoMethod,
+ s.precompile.Methods[distribution.ValidatorDistributionInfoMethod].Name,
+ false,
+ },
+ {
+ "invalid",
+ "invalid",
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.Require().Equal(s.precompile.IsTransaction(tc.method), tc.isTx)
+ })
+ }
+}
+
+// TestRun tests the precompile's Run method.
+func (s *PrecompileTestSuite) TestRun() {
+ testcases := []struct {
+ name string
+ malleate func() (common.Address, []byte)
+ readOnly bool
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "pass - set withdraw address transaction",
+ malleate: func() (common.Address, []byte) {
+ valAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ val, _ := s.app.StakingKeeper.GetValidator(s.ctx, valAddr)
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18)))
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))
+
+ input, err := s.precompile.Pack(
+ distribution.SetWithdrawAddressMethod,
+ s.address,
+ s.address.String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return s.address, input
+ },
+ readOnly: false,
+ expPass: true,
+ },
+ {
+ name: "pass - withdraw validator commissions transaction",
+ malleate: func() (common.Address, []byte) {
+ hexAddr := common.Bytes2Hex(s.address.Bytes())
+ valAddr, err := sdk.ValAddressFromHex(hexAddr)
+ s.Require().NoError(err)
+ caller := common.BytesToAddress(valAddr)
+
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(utils.BaseDenom, math.LegacyNewDecWithPrec(1000000000000000000, 1))}
+ // set outstanding rewards
+ s.app.DistrKeeper.SetValidatorOutstandingRewards(s.ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})
+ // set commission
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(s.ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})
+
+ input, err := s.precompile.Pack(
+ distribution.WithdrawValidatorCommissionMethod,
+ valAddr.String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return caller, input
+ },
+ readOnly: false,
+ expPass: true,
+ },
+ {
+ name: "pass - withdraw delegator rewards transaction",
+ malleate: func() (common.Address, []byte) {
+ valAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ val, _ := s.app.StakingKeeper.GetValidator(s.ctx, valAddr)
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18)))
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))
+
+ input, err := s.precompile.Pack(
+ distribution.WithdrawDelegatorRewardsMethod,
+ s.address,
+ valAddr.String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+
+ return s.address, input
+ },
+ readOnly: false,
+ expPass: true,
+ },
+ {
+ name: "pass - claim rewards transaction",
+ malleate: func() (common.Address, []byte) {
+ valAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ val, _ := s.app.StakingKeeper.GetValidator(s.ctx, valAddr)
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18)))
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))
+
+ input, err := s.precompile.Pack(
+ distribution.ClaimRewardsMethod,
+ s.address,
+ uint32(2),
+ )
+ s.Require().NoError(err, "failed to pack input")
+
+ return s.address, input
+ },
+ readOnly: false,
+ expPass: true,
+ },
+ {
+ name: "pass - fund community pool transaction",
+ malleate: func() (common.Address, []byte) {
+ input, err := s.precompile.Pack(
+ distribution.FundCommunityPoolMethod,
+ s.address,
+ big.NewInt(1e18),
+ )
+ s.Require().NoError(err, "failed to pack input")
+
+ return s.address, input
+ },
+ readOnly: false,
+ expPass: true,
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ // setup basic test suite
+ s.SetupTest()
+
+ baseFee := s.app.FeeMarketKeeper.GetBaseFee(s.ctx)
+
+ // malleate testcase
+ caller, input := tc.malleate()
+
+ contract := vm.NewPrecompile(vm.AccountRef(caller), s.precompile, big.NewInt(0), uint64(1e6))
+ contract.Input = input
+
+ contractAddr := contract.Address()
+ // Build and sign Ethereum transaction
+ txArgs := evmtypes.EvmTxArgs{
+ ChainID: s.app.EvmKeeper.ChainID(),
+ Nonce: 0,
+ To: &contractAddr,
+ Amount: nil,
+ GasLimit: 100000,
+ GasPrice: app.MainnetMinGasPrices.BigInt(),
+ GasFeeCap: baseFee,
+ GasTipCap: big.NewInt(1),
+ Accesses: ðtypes.AccessList{},
+ }
+ msgEthereumTx := evmtypes.NewTx(&txArgs)
+
+ msgEthereumTx.From = s.address.String()
+ err := msgEthereumTx.Sign(s.ethSigner, s.signer)
+ s.Require().NoError(err, "failed to sign Ethereum message")
+
+ // Instantiate config
+ proposerAddress := s.ctx.BlockHeader().ProposerAddress
+ cfg, err := s.app.EvmKeeper.EVMConfig(s.ctx, proposerAddress, s.app.EvmKeeper.ChainID())
+ s.Require().NoError(err, "failed to instantiate EVM config")
+
+ msg, err := msgEthereumTx.AsMessage(s.ethSigner, baseFee)
+ s.Require().NoError(err, "failed to instantiate Ethereum message")
+
+ // Instantiate EVM
+ evm := s.app.EvmKeeper.NewEVM(
+ s.ctx, msg, cfg, nil, s.stateDB,
+ )
+
+ precompiles, found, err := s.app.EvmKeeper.GetPrecompileInstance(s.ctx, contractAddr)
+ s.Require().NoError(err, "failed to instantiate precompile")
+ s.Require().True(found, "not found precompile")
+ evm.WithPrecompiles(precompiles.Map, precompiles.Addresses)
+ // Run precompiled contract
+ bz, err := s.precompile.Run(evm, contract, tc.readOnly)
+
+ // Check results
+ if tc.expPass {
+ s.Require().NoError(err, "expected no error when running the precompile")
+ s.Require().NotNil(bz, "expected returned bytes not to be nil")
+ } else {
+ s.Require().Error(err, "expected error to be returned when running the precompile")
+ s.Require().Nil(bz, "expected returned bytes to be nil")
+ s.Require().ErrorContains(err, tc.errContains)
+ }
+ })
+ }
+}
diff --git a/precompiles/distribution/errors.go b/precompiles/distribution/errors.go
new file mode 100644
index 00000000..9728a93d
--- /dev/null
+++ b/precompiles/distribution/errors.go
@@ -0,0 +1,14 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package distribution
+
+const (
+ // ErrSetWithdrawAddrAuth is raised when no authorization to set the withdraw address exists.
+ ErrSetWithdrawAddrAuth = "set withdrawer address authorization for address %s does not exist"
+ // ErrWithdrawDelRewardsAuth is raised when no authorization to withdraw delegation rewards exists.
+ ErrWithdrawDelRewardsAuth = "withdraw delegation rewards authorization for address %s does not exist"
+ // ErrWithdrawValCommissionAuth is raised when no authorization to withdraw validator commission exists.
+ ErrWithdrawValCommissionAuth = "withdraw validator commission authorization for address %s does not exist"
+ // ErrDifferentValidator is raised when the origin address is not the same as the validator address.
+ ErrDifferentValidator = "origin address %s is not the same as validator address %s"
+)
diff --git a/precompiles/distribution/events.go b/precompiles/distribution/events.go
new file mode 100644
index 00000000..8b70b544
--- /dev/null
+++ b/precompiles/distribution/events.go
@@ -0,0 +1,190 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package distribution
+
+import (
+ "bytes"
+ "reflect"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // EventTypeSetWithdrawAddress defines the event type for the distribution SetWithdrawAddressMethod transaction.
+ EventTypeSetWithdrawAddress = "SetWithdrawerAddress"
+ // EventTypeWithdrawDelegatorRewards defines the event type for the distribution WithdrawDelegatorRewardsMethod transaction.
+ EventTypeWithdrawDelegatorRewards = "WithdrawDelegatorRewards"
+ // EventTypeWithdrawValidatorCommission defines the event type for the distribution WithdrawValidatorCommissionMethod transaction.
+ EventTypeWithdrawValidatorCommission = "WithdrawValidatorCommission"
+ // EventTypeFundCommunityPool defines the event type for the distribution FundCommunityPoolMethod transaction.
+ EventTypeFundCommunityPool = "FundCommunityPool"
+ // EventTypeClaimRewards defines the event type for the distribution ClaimRewardsMethod transaction.
+ EventTypeClaimRewards = "ClaimRewards"
+)
+
+// EmitClaimRewardsEvent creates a new event emitted on a ClaimRewards transaction.
+func (p Precompile) EmitClaimRewardsEvent(ctx sdk.Context, stateDB vm.StateDB, delegatorAddress common.Address, totalCoins sdk.Coins) error {
+ // Prepare the event topics
+ event := p.Events[EventTypeClaimRewards]
+ topics := make([]common.Hash, 2)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(delegatorAddress)
+ if err != nil {
+ return err
+ }
+
+ totalAmount := totalCoins.AmountOf(p.stakingKeeper.BondDenom(ctx))
+ // Pack the arguments to be used as the Data field
+ arguments := abi.Arguments{event.Inputs[1]}
+ packed, err := arguments.Pack(totalAmount.BigInt())
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitSetWithdrawAddressEvent creates a new event emitted on a SetWithdrawAddressMethod transaction.
+func (p Precompile) EmitSetWithdrawAddressEvent(ctx sdk.Context, stateDB vm.StateDB, caller common.Address, withdrawerAddress string) error {
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeSetWithdrawAddress]
+ topics := make([]common.Hash, 2)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(caller)
+ if err != nil {
+ return err
+ }
+
+ // Pack the arguments to be used as the Data field
+ arguments := abi.Arguments{event.Inputs[1]}
+ packed, err := arguments.Pack(withdrawerAddress)
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitWithdrawDelegatorRewardsEvent creates a new event emitted on a WithdrawDelegatorRewards transaction.
+func (p Precompile) EmitWithdrawDelegatorRewardsEvent(ctx sdk.Context, stateDB vm.StateDB, delegatorAddress common.Address, validatorAddress string, coins sdk.Coins) error {
+ valAddr, err := sdk.ValAddressFromBech32(validatorAddress)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeWithdrawDelegatorRewards]
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ topics[1], err = cmn.MakeTopic(delegatorAddress)
+ if err != nil {
+ return err
+ }
+
+ topics[2], err = cmn.MakeTopic(common.BytesToAddress(valAddr.Bytes()))
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(coins[0].Amount.BigInt())))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitWithdrawValidatorCommissionEvent creates a new event emitted on a WithdrawValidatorCommission transaction.
+func (p Precompile) EmitWithdrawValidatorCommissionEvent(ctx sdk.Context, stateDB vm.StateDB, validatorAddress string, coins sdk.Coins) error {
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeWithdrawValidatorCommission]
+ topics := make([]common.Hash, 2)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(validatorAddress)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(coins[0].Amount.BigInt())))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitFundCommunityPoolEvent creates a new event emitted on a FundCommunityPool transaction.
+func (p Precompile) EmitFundCommunityPoolEvent(ctx sdk.Context, stateDB vm.StateDB, depositor common.Address, coins sdk.Coins) error {
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeFundCommunityPool]
+ topics := make([]common.Hash, 2)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(depositor)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(coins[0].Amount.BigInt())))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
diff --git a/precompiles/distribution/events_test.go b/precompiles/distribution/events_test.go
new file mode 100644
index 00000000..49d9c704
--- /dev/null
+++ b/precompiles/distribution/events_test.go
@@ -0,0 +1,289 @@
+package distribution_test
+
+import (
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/cmd/config"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func (s *PrecompileTestSuite) TestSetWithdrawAddressEvent() {
+ method := s.precompile.Methods[distribution.SetWithdrawAddressMethod]
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func()
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "success - the correct event is emitted",
+ func(string) []interface{} {
+ return []interface{}{
+ s.address,
+ s.address.String(),
+ }
+ },
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[distribution.EventTypeSetWithdrawAddress]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var setWithdrawerAddrEvent distribution.EventSetWithdrawAddress
+ err := cmn.UnpackLog(s.precompile.ABI, &setWithdrawerAddrEvent, distribution.EventTypeSetWithdrawAddress, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, setWithdrawerAddrEvent.Caller)
+ s.Require().Equal(sdk.MustBech32ifyAddressBytes(config.Bech32Prefix, s.address.Bytes()), setWithdrawerAddrEvent.WithdrawerAddress)
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.SetupTest()
+
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+ s.ctx = s.ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
+ initialGas := s.ctx.GasMeter().GasConsumed()
+ s.Require().Zero(initialGas)
+
+ _, err := s.precompile.SetWithdrawAddress(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ if tc.expError {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ }
+}
+
+func (s *PrecompileTestSuite) TestWithdrawDelegatorRewardsEvent() {
+ method := s.precompile.Methods[distribution.WithdrawDelegatorRewardsMethod]
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func()
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "success - the correct event is emitted",
+ func(operatorAddress string) []interface{} {
+ valAddr, err := sdk.ValAddressFromBech32(operatorAddress)
+ s.Require().NoError(err)
+ val, _ := s.app.StakingKeeper.GetValidator(s.ctx, valAddr)
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18)))
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ }
+ },
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[distribution.EventTypeWithdrawDelegatorRewards]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ optAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ optHexAddr := common.BytesToAddress(optAddr)
+
+ // Check the fully unpacked event matches the one emitted
+ var delegatorRewards distribution.EventWithdrawDelegatorRewards
+ err = cmn.UnpackLog(s.precompile.ABI, &delegatorRewards, distribution.EventTypeWithdrawDelegatorRewards, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, delegatorRewards.DelegatorAddress)
+ s.Require().Equal(optHexAddr, delegatorRewards.ValidatorAddress)
+ s.Require().Equal(big.NewInt(1000000000000000000), delegatorRewards.Amount)
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.SetupTest()
+
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+ s.ctx = s.ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
+ initialGas := s.ctx.GasMeter().GasConsumed()
+ s.Require().Zero(initialGas)
+
+ _, err := s.precompile.WithdrawDelegatorRewards(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ if tc.expError {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ }
+}
+
+func (s *PrecompileTestSuite) TestWithdrawValidatorCommissionEvent() {
+ method := s.precompile.Methods[distribution.WithdrawValidatorCommissionMethod]
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func()
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "success - the correct event is emitted",
+ func(operatorAddress string) []interface{} {
+ valAddr, err := sdk.ValAddressFromBech32(operatorAddress)
+ s.Require().NoError(err)
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(utils.BaseDenom, math.LegacyNewDecWithPrec(1000000000000000000, 1))}
+ // set outstanding rewards
+ s.app.DistrKeeper.SetValidatorOutstandingRewards(s.ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})
+ // set commission
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(s.ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})
+ return []interface{}{
+ operatorAddress,
+ }
+ },
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[distribution.EventTypeWithdrawValidatorCommission]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var validatorRewards distribution.EventWithdrawValidatorRewards
+ err := cmn.UnpackLog(s.precompile.ABI, &validatorRewards, distribution.EventTypeWithdrawValidatorCommission, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(crypto.Keccak256Hash([]byte(s.validators[0].OperatorAddress)), validatorRewards.ValidatorAddress)
+ s.Require().Equal(big.NewInt(100000000000000000), validatorRewards.Commission)
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.SetupTest()
+
+ validatorAddress := common.BytesToAddress(s.validators[0].GetOperator().Bytes())
+ contract := vm.NewContract(vm.AccountRef(validatorAddress), s.precompile, big.NewInt(0), tc.gas)
+ s.ctx = s.ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
+ initialGas := s.ctx.GasMeter().GasConsumed()
+ s.Require().Zero(initialGas)
+
+ _, err := s.precompile.WithdrawValidatorCommission(s.ctx, validatorAddress, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ if tc.expError {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ }
+}
+
+//nolint:dupl
+func (s *PrecompileTestSuite) TestClaimRewardsEvent() {
+ testCases := []struct {
+ name string
+ coins sdk.Coins
+ postCheck func()
+ }{
+ {
+ "success",
+ sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18))),
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[distribution.EventTypeClaimRewards]
+ s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var claimRewardsEvent distribution.EventClaimRewards
+ err := cmn.UnpackLog(s.precompile.ABI, &claimRewardsEvent, distribution.EventTypeClaimRewards, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(common.BytesToAddress(s.address.Bytes()), claimRewardsEvent.DelegatorAddress)
+ s.Require().Equal(big.NewInt(1e18), claimRewardsEvent.Amount)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ err := s.precompile.EmitClaimRewardsEvent(s.ctx, s.stateDB, s.address, tc.coins)
+ s.Require().NoError(err)
+ tc.postCheck()
+ })
+ }
+}
+
+//nolint:dupl
+func (s *PrecompileTestSuite) TestFundCommunityPoolEvent() {
+ testCases := []struct {
+ name string
+ coins sdk.Coins
+ postCheck func()
+ }{
+ {
+ "success - the correct event is emitted",
+ sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18))),
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[distribution.EventTypeFundCommunityPool]
+ s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var fundCommunityPoolEvent distribution.EventFundCommunityPool
+ err := cmn.UnpackLog(s.precompile.ABI, &fundCommunityPoolEvent, distribution.EventTypeFundCommunityPool, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(common.BytesToAddress(s.address.Bytes()), fundCommunityPoolEvent.Depositor)
+ s.Require().Equal(big.NewInt(1e18), fundCommunityPoolEvent.Amount)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ err := s.precompile.EmitFundCommunityPoolEvent(s.ctx, s.stateDB, s.address, tc.coins)
+ s.Require().NoError(err)
+ tc.postCheck()
+ })
+ }
+}
diff --git a/precompiles/distribution/integration_test.go b/precompiles/distribution/integration_test.go
new file mode 100644
index 00000000..e4e7d4d4
--- /dev/null
+++ b/precompiles/distribution/integration_test.go
@@ -0,0 +1,2036 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package distribution_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
+ distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/precompiles/testutil/contracts"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ testutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+)
+
+// General variables used for integration tests
+var (
+ // differentAddr is an address generated for testing purposes that e.g. raises the different origin error
+ differentAddr = testutiltx.GenerateAddress()
+ // expRewardAmt is the expected amount of rewards
+ expRewardAmt = big.NewInt(2000000000000000000)
+ // gasPrice is the gas price used for the transactions
+ gasPrice = big.NewInt(1e9)
+ // defaultCallArgs are the default arguments for calling the smart contract
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultCallArgs contracts.CallArgs
+
+ // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated.
+ defaultLogCheck testutil.LogCheckArgs
+ // passCheck defines the arguments to check if the precompile returns no error
+ passCheck testutil.LogCheckArgs
+ // outOfGasCheck defines the arguments to check if the precompile returns out of gas error
+ outOfGasCheck testutil.LogCheckArgs
+)
+
+var _ = Describe("Calling distribution precompile from EOA", func() {
+ BeforeEach(func() {
+ s.SetupTest()
+
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fmt.Println("Fist Before each: ", initialBalance)
+
+ // set the default call arguments
+ defaultCallArgs = contracts.CallArgs{
+ ContractAddr: s.precompile.Address(),
+ ContractABI: s.precompile.ABI,
+ PrivKey: s.privKey,
+ }
+
+ defaultLogCheck = testutil.LogCheckArgs{
+ ABIEvents: s.precompile.Events,
+ }
+ passCheck = defaultLogCheck.WithExpPass(true)
+ outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error())
+
+ initialBalance = s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fmt.Println("Fist Before each: ", initialBalance)
+ })
+
+ // =====================================
+ // TRANSACTIONS
+ // =====================================
+ Describe("Execute SetWithdrawAddress transaction", func() {
+ const method = distribution.SetWithdrawAddressMethod
+ // defaultSetWithdrawArgs are the default arguments to set the withdraw address
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key otherwise is not yet initialized.
+ var defaultSetWithdrawArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ // set the default call arguments
+ defaultSetWithdrawArgs = defaultCallArgs.WithMethodName(method)
+ })
+
+ It("should return error if the provided gasLimit is too low", func() {
+ setWithdrawArgs := defaultSetWithdrawArgs.
+ WithGasLimit(30000).
+ WithArgs(s.address, differentAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, setWithdrawArgs, outOfGasCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring("out of gas"), "expected out of gas error")
+
+ // withdraw address should remain unchanged
+ withdrawAddr := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawAddr.Bytes()).To(Equal(s.address.Bytes()), "expected withdraw address to remain unchanged")
+ })
+
+ It("should return error if the origin is different than the delegator", func() {
+ setWithdrawArgs := defaultSetWithdrawArgs.WithArgs(differentAddr, s.address.String())
+
+ withdrawAddrSetCheck := defaultLogCheck.WithErrContains(cmn.ErrDelegatorDifferentOrigin, s.address.String(), differentAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, setWithdrawArgs, withdrawAddrSetCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(cmn.ErrDelegatorDifferentOrigin, s.address, differentAddr)), "expected different origin error")
+ })
+
+ It("should set withdraw address", func() {
+ // initially, withdraw address should be same as address
+ withdrawAddr := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawAddr.Bytes()).To(Equal(s.address.Bytes()))
+
+ setWithdrawArgs := defaultSetWithdrawArgs.WithArgs(s.address, differentAddr.String())
+
+ withdrawAddrSetCheck := passCheck.
+ WithExpEvents(distribution.EventTypeSetWithdrawAddress)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, setWithdrawArgs, withdrawAddrSetCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ // withdraw should be updated
+ withdrawAddr = s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawAddr.Bytes()).To(Equal(differentAddr.Bytes()), "expected different withdraw address")
+ })
+ })
+
+ Describe("Execute WithdrawDelegatorRewards transaction", func() {
+ // defaultWithdrawRewardsArgs are the default arguments to withdraw rewards
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key otherwise is not yet initialized.
+ var defaultWithdrawRewardsArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ // set the default call arguments
+ defaultWithdrawRewardsArgs = defaultCallArgs.WithMethodName(distribution.WithdrawDelegatorRewardsMethod)
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+ })
+
+ It("should return error if the origin is different than the delegator", func() {
+ withdrawRewardsArgs := defaultWithdrawRewardsArgs.WithArgs(differentAddr, s.validators[0].OperatorAddress)
+
+ withdrawalCheck := defaultLogCheck.WithErrContains(cmn.ErrDelegatorDifferentOrigin, s.address.String(), differentAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawRewardsArgs, withdrawalCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(cmn.ErrDelegatorDifferentOrigin, s.address, differentAddr)), "expected different origin error")
+ })
+
+ It("should withdraw delegation rewards", func() {
+ // get initial balance
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(initialBalance.Amount).To(Equal(initialBalance.Amount))
+
+ withdrawRewardsArgs := defaultWithdrawRewardsArgs.
+ WithArgs(s.address, s.validators[0].OperatorAddress).
+ WithGasPrice(gasPrice)
+
+ withdrawalCheck := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawDelegatorRewards)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawRewardsArgs, withdrawalCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var rewards []cmn.Coin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(1))
+ Expect(rewards[0].Denom).To(Equal(s.bondDenom))
+ Expect(rewards[0].Amount).To(Equal(expRewardAmt))
+
+ // check that the rewards were added to the balance
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fees := gasPrice.Int64() * res.GasUsed
+ expFinal := initialBalance.Amount.Int64() + expRewardAmt.Int64() - fees
+ Expect(finalBalance.Amount.Equal(math.NewInt(expFinal))).To(BeTrue(), "expected final balance to be equal to initial balance + rewards - fees")
+ })
+
+ It("should withdraw delegation rewards to a smart contract", func() {
+ // deploy a smart contract to use as withdrawer
+ distributionCallerContract, err := contracts.LoadDistributionCallerContract()
+ Expect(err).To(BeNil(), "error while loading the smart contract: %v", err)
+
+ contractAddr, err := s.DeployContract(distributionCallerContract)
+ Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err)
+
+ initialWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(initialWithdrawerBalance.Amount).To(Equal(sdk.ZeroInt()))
+
+ // set contract address as withdrawer address
+ err = s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), contractAddr.Bytes())
+ Expect(err).To(BeNil())
+
+ // get tx sender initial balance
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+
+ withdrawRewardsArgs := defaultWithdrawRewardsArgs.
+ WithArgs(s.address, s.validators[0].OperatorAddress).
+ WithGasPrice(gasPrice)
+
+ withdrawalCheck := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawDelegatorRewards)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawRewardsArgs, withdrawalCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var rewards []cmn.Coin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(1))
+ Expect(rewards[0].Denom).To(Equal(s.bondDenom))
+ Expect(rewards[0].Amount).To(Equal(expRewardAmt))
+
+ // check tx sender balance is reduced by fees paid
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fees := sdk.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ expFinal := initialBalance.Amount.Sub(fees)
+ Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to initial balance - fees")
+
+ // check that the rewards were added to the withdrawer balance
+ finalWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(finalWithdrawerBalance.Amount.BigInt()).To(Equal(expRewardAmt))
+ })
+ })
+
+ Describe("Validator Commission: Execute WithdrawValidatorCommission tx", func() {
+ var (
+ // defaultWithdrawCommissionArgs are the default arguments to withdraw commission
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key otherwise is not yet initialized.
+ defaultWithdrawCommissionArgs contracts.CallArgs
+
+ // expCommAmt is the expected commission amount
+ expCommAmt = big.NewInt(1)
+ // commDec is the commission rate
+ commDec = math.LegacyNewDec(1)
+ valAddr sdk.ValAddress
+ stakeAmt math.Int
+ )
+
+ BeforeEach(func() {
+ // set the default call arguments
+ defaultWithdrawCommissionArgs = defaultCallArgs.WithMethodName(
+ distribution.WithdrawValidatorCommissionMethod,
+ )
+
+ // create a validator with s.address and s.privKey because this account is
+ // used for signing txs
+ stakeAmt = math.NewInt(100)
+ testutil.CreateValidator(s.ctx, s.T(), s.privKey.PubKey(), *s.app.StakingKeeper.Keeper, stakeAmt)
+
+ // set some validator commission
+ valAddr = s.address.Bytes()
+ val := s.app.StakingKeeper.Validator(s.ctx, valAddr)
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, commDec)}
+
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(s.ctx, valAddr, distrtypes.ValidatorAccumulatedCommission{Commission: valCommission})
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.DecCoins{sdk.NewDecCoin(s.bondDenom, stakeAmt)})
+ })
+
+ It("should return error if the provided gasLimit is too low", func() {
+ withdrawCommissionArgs := defaultWithdrawCommissionArgs.
+ WithGasLimit(50000).
+ WithArgs(valAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawCommissionArgs, outOfGasCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring("out of gas"), "expected out of gas error")
+ })
+
+ It("should return error if the origin is different than the validator", func() {
+ withdrawCommissionArgs := defaultWithdrawCommissionArgs.WithArgs(s.validators[0].OperatorAddress)
+ validatorHexAddr := common.BytesToAddress(s.validators[0].GetOperator())
+
+ withdrawalCheck := defaultLogCheck.WithErrContains(cmn.ErrDelegatorDifferentOrigin, s.address.String(), validatorHexAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawCommissionArgs, withdrawalCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(cmn.ErrDelegatorDifferentOrigin, s.address, validatorHexAddr)), "expected different origin error")
+ })
+
+ It("should withdraw validator commission", func() {
+ // initial balance should be the initial amount minus the staked amount used to create the validator
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(initialBalance.Amount).To(Equal(math.NewInt(4999999999999999900)))
+
+ withdrawCommissionArgs := defaultWithdrawCommissionArgs.
+ WithArgs(valAddr.String()).
+ WithGasPrice(gasPrice)
+
+ withdrawalCheck := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawValidatorCommission)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawCommissionArgs, withdrawalCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var comm []cmn.Coin
+ err = s.precompile.UnpackIntoInterface(&comm, distribution.WithdrawValidatorCommissionMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(comm)).To(Equal(1))
+ Expect(comm[0].Denom).To(Equal(s.bondDenom))
+ Expect(comm[0].Amount).To(Equal(expCommAmt))
+
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fees := gasPrice.Int64() * res.GasUsed
+ expFinal := initialBalance.Amount.Int64() + expCommAmt.Int64() - fees
+ Expect(finalBalance.Amount.Equal(math.NewInt(expFinal))).To(BeTrue(), "expected final balance to be equal to the final balance after withdrawing commission")
+ })
+
+ It("should withdraw validator commission to a smart contract", func() {
+ // deploy a smart contract to use as withdrawer
+ distributionCallerContract, err := contracts.LoadDistributionCallerContract()
+ Expect(err).To(BeNil(), "error while loading the smart contract: %v", err)
+
+ contractAddr, err := s.DeployContract(distributionCallerContract)
+ Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err)
+
+ initialWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(initialWithdrawerBalance.Amount).To(Equal(sdk.ZeroInt()))
+
+ // set contract address as withdrawer address
+ err = s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), contractAddr.Bytes())
+ Expect(err).To(BeNil())
+
+ // get validator initial balance
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+
+ withdrawCommissionArgs := defaultWithdrawCommissionArgs.
+ WithArgs(valAddr.String()).
+ WithGasPrice(gasPrice)
+
+ withdrawalCheck := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawValidatorCommission)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawCommissionArgs, withdrawalCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var comm []cmn.Coin
+ err = s.precompile.UnpackIntoInterface(&comm, distribution.WithdrawValidatorCommissionMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(comm)).To(Equal(1))
+ Expect(comm[0].Denom).To(Equal(s.bondDenom))
+ Expect(comm[0].Amount).To(Equal(expCommAmt))
+
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fees := sdk.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ expFinal := initialBalance.Amount.Sub(fees)
+ Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to the final balance after withdrawing commission")
+
+ // check that the commission was added to the withdrawer balance
+ finalWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(finalWithdrawerBalance.Amount.BigInt()).To(Equal(expCommAmt))
+ })
+ })
+
+ Describe("Execute ClaimRewards transaction", func() {
+ // defaultWithdrawRewardsArgs are the default arguments to withdraw rewards
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key otherwise is not yet initialized.
+ var defaultClaimRewardsArgs contracts.CallArgs
+ // starting balance minus delegated tokens
+ startingBalance := math.NewInt(5e18)
+ expectedBalance := math.NewInt(8999665039062500000)
+
+ BeforeEach(func() {
+ // set the default call arguments
+ defaultClaimRewardsArgs = defaultCallArgs.WithMethodName(distribution.ClaimRewardsMethod)
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fmt.Println("BeforeEach: ", initialBalance)
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[1], rewards})
+ })
+
+ It("should return err if the origin is different than the delegator", func() {
+ claimRewardsArgs := defaultClaimRewardsArgs.WithArgs(differentAddr, uint32(1))
+
+ claimRewardsCheck := defaultLogCheck.WithErrContains(cmn.ErrDelegatorDifferentOrigin, s.address.String(), differentAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, claimRewardsArgs, claimRewardsCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(cmn.ErrDelegatorDifferentOrigin, s.address, differentAddr)), "expected different origin error")
+ })
+
+ It("should claim all rewards from all validators", func() {
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(initialBalance.Amount).To(Equal(startingBalance))
+
+ claimRewardsArgs := defaultClaimRewardsArgs.WithArgs(s.address, uint32(2))
+ claimRewardsCheck := passCheck.WithExpEvents(distribution.EventTypeClaimRewards)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, claimRewardsArgs, claimRewardsCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ // check that the rewards were added to the balance
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.Equal(expectedBalance)).To(BeTrue(), "expected final balance to be equal to initial balance + rewards - fees")
+ })
+ })
+ // =====================================
+ // QUERIES
+ // =====================================
+ Describe("Execute queries", func() {
+ It("should get validator distribution info - validatorDistributionInfo query", func() {
+ addr := sdk.AccAddress(s.validators[0].GetOperator())
+ // fund validator account to make self-delegation
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, addr, 10)
+ Expect(err).To(BeNil())
+ // make a self delegation
+ _, err = s.app.StakingKeeper.Delegate(s.ctx, addr, math.NewInt(1), stakingtypes.Unspecified, s.validators[0], true)
+ Expect(err).To(BeNil())
+
+ valDistArgs := defaultCallArgs.
+ WithMethodName(distribution.ValidatorDistributionInfoMethod).
+ WithArgs(s.validators[0].OperatorAddress)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, valDistArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var out distribution.ValidatorDistributionInfoOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorDistributionInfoMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+
+ expAddr := sdk.AccAddress(s.validators[0].GetOperator())
+ Expect(expAddr.String()).To(Equal(out.DistributionInfo.OperatorAddress))
+ Expect(0).To(Equal(len(out.DistributionInfo.Commission)))
+ Expect(0).To(Equal(len(out.DistributionInfo.SelfBondRewards)))
+ })
+
+ It("should get validator outstanding rewards - validatorOutstandingRewards query", func() { //nolint:dupl
+ valRewards := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, math.LegacyNewDec(1))}
+ // set outstanding rewards
+ s.app.DistrKeeper.SetValidatorOutstandingRewards(s.ctx, s.validators[0].GetOperator(), distrtypes.ValidatorOutstandingRewards{Rewards: valRewards})
+
+ valOutRewardsArgs := defaultCallArgs.
+ WithMethodName(distribution.ValidatorOutstandingRewardsMethod).
+ WithArgs(s.validators[0].OperatorAddress)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, valOutRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var rewards []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.ValidatorOutstandingRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(1))
+ Expect(uint8(18)).To(Equal(rewards[0].Precision))
+ Expect(s.bondDenom).To(Equal(rewards[0].Denom))
+ Expect(expValAmount).To(Equal(rewards[0].Amount.Int64()))
+ })
+
+ It("should get validator commission - validatorCommission query", func() { //nolint:dupl
+ // set commission
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, math.LegacyNewDec(1))}
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(s.ctx, s.validators[0].GetOperator(), distrtypes.ValidatorAccumulatedCommission{Commission: valCommission})
+
+ valCommArgs := defaultCallArgs.
+ WithMethodName(distribution.ValidatorCommissionMethod).
+ WithArgs(s.validators[0].OperatorAddress)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, valCommArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var commission []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(commission)).To(Equal(1))
+ Expect(uint8(18)).To(Equal(commission[0].Precision))
+ Expect(s.bondDenom).To(Equal(commission[0].Denom))
+ Expect(expValAmount).To(Equal(commission[0].Amount.Int64()))
+ })
+
+ Context("validatorSlashes query query", func() {
+ It("should get validator slashing events (default pagination)", func() {
+ // set slash event
+ slashEvent := distrtypes.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)}
+ s.app.DistrKeeper.SetValidatorSlashEvent(s.ctx, s.validators[0].GetOperator(), 2, 1, slashEvent)
+
+ valSlashArgs := defaultCallArgs.
+ WithMethodName(distribution.ValidatorSlashesMethod).
+ WithArgs(
+ s.validators[0].OperatorAddress,
+ uint64(1), uint64(5),
+ query.PageRequest{},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, valSlashArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var out distribution.ValidatorSlashesOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(out.Slashes)).To(Equal(1))
+ Expect(slashEvent.Fraction.BigInt()).To(Equal(out.Slashes[0].Fraction.Value))
+ Expect(slashEvent.ValidatorPeriod).To(Equal(out.Slashes[0].ValidatorPeriod))
+ Expect(uint64(1)).To(Equal(out.PageResponse.Total))
+ Expect(out.PageResponse.NextKey).To(BeEmpty())
+ })
+
+ It("should get validator slashing events - query w/pagination limit = 1)", func() {
+ // set 2 slashing events for validator[0]
+ slashEvent := s.setupValidatorSlashes(s.validators[0].GetOperator(), 2)
+
+ valSlashArgs := defaultCallArgs.
+ WithMethodName(distribution.ValidatorSlashesMethod).
+ WithArgs(
+ s.validators[0].OperatorAddress,
+ uint64(1), uint64(5),
+ query.PageRequest{
+ Limit: 1,
+ CountTotal: true,
+ },
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, valSlashArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var out distribution.ValidatorSlashesOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(out.Slashes)).To(Equal(1))
+ Expect(slashEvent.Fraction.BigInt()).To(Equal(out.Slashes[0].Fraction.Value))
+ Expect(slashEvent.ValidatorPeriod).To(Equal(out.Slashes[0].ValidatorPeriod))
+ // total slashes count is 2
+ Expect(uint64(2)).To(Equal(out.PageResponse.Total))
+ Expect(out.PageResponse.NextKey).NotTo(BeEmpty())
+ })
+ })
+
+ It("should get delegation rewards - delegationRewards query", func() {
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+
+ delRewardsArgs := defaultCallArgs.
+ WithMethodName(distribution.DelegationRewardsMethod).
+ WithArgs(s.address, s.validators[0].OperatorAddress)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var rewards []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(1))
+ Expect(rewards[0].Denom).To(Equal(s.bondDenom))
+ Expect(rewards[0].Amount.Int64()).To(Equal(expDelegationRewards))
+ })
+
+ It("should get delegators's total rewards - delegationTotalRewards query", func() {
+ // set rewards
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+
+ delTotalRewardsArgs := defaultCallArgs.
+ WithMethodName(distribution.DelegationTotalRewardsMethod).
+ WithArgs(s.address)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delTotalRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var (
+ out distribution.DelegationTotalRewardsOutput
+ i int
+ )
+ err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(2).To(Equal(len(out.Rewards)))
+
+ // the response order may change
+ if out.Rewards[0].ValidatorAddress == s.validators[0].OperatorAddress {
+ Expect(s.validators[0].OperatorAddress).To(Equal(out.Rewards[0].ValidatorAddress))
+ Expect(s.validators[1].OperatorAddress).To(Equal(out.Rewards[1].ValidatorAddress))
+ Expect(0).To(Equal(len(out.Rewards[1].Reward)))
+ } else {
+ i = 1
+ Expect(s.validators[0].OperatorAddress).To(Equal(out.Rewards[1].ValidatorAddress))
+ Expect(s.validators[1].OperatorAddress).To(Equal(out.Rewards[0].ValidatorAddress))
+ Expect(0).To(Equal(len(out.Rewards[0].Reward)))
+ }
+
+ // only validator[i] has rewards
+ Expect(1).To(Equal(len(out.Rewards[i].Reward)))
+ Expect(s.bondDenom).To(Equal(out.Rewards[i].Reward[0].Denom))
+ Expect(uint8(math.LegacyPrecision)).To(Equal(out.Rewards[i].Reward[0].Precision))
+ Expect(expDelegationRewards).To(Equal(out.Rewards[i].Reward[0].Amount.Int64()))
+
+ Expect(1).To(Equal(len(out.Total)))
+ Expect(expDelegationRewards).To(Equal(out.Total[0].Amount.Int64()))
+ })
+
+ It("should get all validators a delegators has delegated to - delegatorValidators query", func() {
+ delValArgs := defaultCallArgs.
+ WithMethodName(distribution.DelegatorValidatorsMethod).
+ WithArgs(s.address)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delValArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var validators []string
+ err = s.precompile.UnpackIntoInterface(&validators, distribution.DelegatorValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(2).To(Equal(len(validators)))
+
+ // the response order may change
+ if validators[0] == s.validators[0].OperatorAddress {
+ Expect(s.validators[0].OperatorAddress).To(Equal(validators[0]))
+ Expect(s.validators[1].OperatorAddress).To(Equal(validators[1]))
+ } else {
+ Expect(s.validators[1].OperatorAddress).To(Equal(validators[0]))
+ Expect(s.validators[0].OperatorAddress).To(Equal(validators[1]))
+ }
+ })
+
+ It("should get withdraw address - delegatorWithdrawAddress query", func() {
+ // set the withdraw address
+ err := s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), differentAddr.Bytes())
+ Expect(err).To(BeNil())
+
+ delWithdrawAddrArgs := defaultCallArgs.
+ WithMethodName(distribution.DelegatorWithdrawAddressMethod).
+ WithArgs(s.address)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delWithdrawAddrArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ // get the bech32 encoding
+ expAddr := sdk.AccAddress(differentAddr.Bytes())
+ Expect(withdrawAddr[0]).To(Equal(expAddr.String()))
+ })
+ })
+})
+
+var _ = Describe("Calling distribution precompile from another contract", func() {
+ // testCase is a struct used for cases of contracts calls that have some operation
+ // performed before and/or after the precompile call
+ type testCase struct {
+ withdrawer *common.Address
+ before bool
+ after bool
+ }
+
+ var (
+ // initBalanceAmt is the initial balance for testing
+ initBalanceAmt = math.NewInt(5000000000000000000)
+
+ // contractAddr is the address of the smart contract that will be deployed
+ contractAddr common.Address
+
+ // execRevertedCheck defines the default log checking arguments which includes the
+ // standard revert message.
+ execRevertedCheck testutil.LogCheckArgs
+ )
+
+ BeforeEach(func() {
+ s.SetupTest()
+
+ distributionCallerContract, err := contracts.LoadDistributionCallerContract()
+ Expect(err).To(BeNil(), "error while loading the smart contract: %v", err)
+
+ contractAddr, err = s.DeployContract(distributionCallerContract)
+ Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err)
+
+ // NextBlock the smart contract
+ s.NextBlock()
+
+ // check contract was correctly deployed
+ cAcc := s.app.EvmKeeper.GetAccount(s.ctx, contractAddr)
+ Expect(cAcc).ToNot(BeNil(), "contract account should exist")
+ Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract")
+
+ // populate default call args
+ defaultCallArgs = contracts.CallArgs{
+ ContractAddr: contractAddr,
+ ContractABI: distributionCallerContract.ABI,
+ PrivKey: s.privKey,
+ }
+
+ // default log check arguments
+ defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.Events}
+ execRevertedCheck = defaultLogCheck.WithErrContains("execution reverted")
+ passCheck = defaultLogCheck.WithExpPass(true)
+ })
+
+ // =====================================
+ // TRANSACTIONS
+ // =====================================
+ Context("setWithdrawAddress", func() {
+ var (
+ // defaultSetWithdrawAddrArgs are the default arguments for the set withdraw address call
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultSetWithdrawAddrArgs contracts.CallArgs
+ // newWithdrawer is the address to set the withdraw address to
+ newWithdrawer = differentAddr
+ )
+
+ BeforeEach(func() {
+ // withdraw address should be same as address
+ withdrawer := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawer.Bytes()).To(Equal(s.address.Bytes()))
+
+ // populate default arguments
+ defaultSetWithdrawAddrArgs = defaultCallArgs.WithMethodName(
+ "testSetWithdrawAddress",
+ )
+ })
+
+ It("should set withdraw address successfully", func() {
+ setWithdrawAddrArgs := defaultSetWithdrawAddrArgs.WithArgs(
+ s.address, newWithdrawer.String(),
+ )
+
+ setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, setWithdrawAddrArgs, setWithdrawCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ withdrawer := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawer.Bytes()).To(Equal(newWithdrawer.Bytes()))
+ })
+ })
+
+ Context("setWithdrawerAddress with contract as delegator", func() {
+ var (
+ // defaultSetWithdrawAddrArgs are the default arguments for the set withdraw address call
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultSetWithdrawAddrArgs contracts.CallArgs
+ // newWithdrawer is the address to set the withdraw address to
+ newWithdrawer = differentAddr
+ )
+
+ BeforeEach(func() {
+ // withdraw address should be same as address
+ withdrawer := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawer.Bytes()).To(Equal(s.address.Bytes()))
+
+ // populate default arguments
+ defaultSetWithdrawAddrArgs = defaultCallArgs.WithMethodName(
+ "testSetWithdrawAddressFromContract",
+ )
+ })
+
+ It("should set withdraw address successfully without origin check", func() {
+ setWithdrawAddrArgs := defaultSetWithdrawAddrArgs.WithArgs(newWithdrawer.String())
+
+ setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, setWithdrawAddrArgs, setWithdrawCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ withdrawer := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, contractAddr.Bytes())
+ Expect(withdrawer.Bytes()).To(Equal(newWithdrawer.Bytes()))
+ })
+ })
+
+ Context("withdrawDelegatorRewards", func() {
+ var (
+ // defaultWithdrawDelRewardsArgs are the default arguments for the withdraw delegator rewards call
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultWithdrawDelRewardsArgs contracts.CallArgs
+ // initialBalance is the initial balance of the delegator
+ initialBalance sdk.Coin
+ )
+
+ BeforeEach(func() {
+ // set some rewards for s.address & another address
+ s.prepareStakingRewards([]stakingRewards{
+ {s.address.Bytes(), s.validators[0], rewards},
+ {differentAddr.Bytes(), s.validators[0], rewards},
+ }...)
+
+ initialBalance = s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+
+ // populate default arguments
+ defaultWithdrawDelRewardsArgs = defaultCallArgs.WithMethodName(
+ "testWithdrawDelegatorRewards",
+ )
+ })
+
+ It("should not withdraw rewards when sending from a different address", func() {
+ withdrawDelRewardsArgs := defaultWithdrawDelRewardsArgs.WithArgs(
+ differentAddr, s.validators[0].OperatorAddress,
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawDelRewardsArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // balance should be equal as initial balance or less (because of fees)
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.Uint64() <= initialBalance.Amount.Uint64()).To(BeTrue())
+
+ // differentAddr balance should remain unchanged
+ differentAddrFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, differentAddr.Bytes(), s.bondDenom)
+ Expect(differentAddrFinalBalance.Amount).To(Equal(math.ZeroInt()))
+ })
+
+ It("should withdraw rewards successfully", func() {
+ withdrawDelRewardsArgs := defaultWithdrawDelRewardsArgs.WithArgs(
+ s.address, s.validators[0].OperatorAddress,
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawDelegatorRewards)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawDelRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // balance should remain unchanged
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.GT(initialBalance.Amount)).To(BeTrue(), "expected final balance to be greater than initial balance after withdrawing rewards")
+ })
+
+ DescribeTable("should withdraw rewards successfully to the new withdrawer address", func(tc testCase) {
+ initialBalance := s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ // Set new withdrawer address
+ err := s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), tc.withdrawer.Bytes())
+ Expect(err).To(BeNil())
+
+ withdrawDelRewardsArgs := defaultWithdrawDelRewardsArgs.WithArgs(
+ s.address, s.validators[0].OperatorAddress,
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawDelegatorRewards)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawDelRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // should increase balance by rewards
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.GT(initialBalance.Amount)).To(BeTrue(), "expected final balance to be greater than initial balance after withdrawing rewards")
+ },
+ Entry("withdrawer addr is existing acc", testCase{
+ withdrawer: &differentAddr,
+ }),
+ Entry("withdrawer addr is non-existing acc", testCase{
+ withdrawer: func() *common.Address {
+ addr := testutiltx.GenerateAddress()
+ return &addr
+ }(),
+ }),
+ )
+
+ // Specific BeforeEach for table-driven tests
+ Context("Table-driven tests for Withdraw Delegator Rewards", func() {
+ var (
+ args contracts.CallArgs
+ contractInitialBalance = math.NewInt(100)
+ )
+ BeforeEach(func() {
+ args = defaultWithdrawDelRewardsArgs.
+ WithMethodName("testWithdrawDelegatorRewardsWithTransfer").
+ WithGasPrice(gasPrice)
+
+ // send some funds to the contract
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, contractAddr.Bytes(), contractInitialBalance.Int64())
+ Expect(err).To(BeNil())
+ })
+
+ DescribeTable("withdraw delegation rewards with internal transfers to delegator - should withdraw rewards successfully to the withdrawer address",
+ func(tc testCase) {
+ withdrawerInitialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ if tc.withdrawer != nil {
+ // Set new withdrawer address
+ err := s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), tc.withdrawer.Bytes())
+ Expect(err).To(BeNil())
+ withdrawerInitialBalance = s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ }
+
+ delInitialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+
+ // get the pending rewards to claim
+ qr := distrkeeper.Querier{Keeper: s.app.DistrKeeper}
+ qRes, err := qr.DelegationRewards(s.ctx, &distrtypes.QueryDelegationRewardsRequest{DelegatorAddress: sdk.AccAddress(s.address.Bytes()).String(), ValidatorAddress: s.validators[0].OperatorAddress})
+ Expect(err).To(BeNil())
+ expRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt()
+
+ withdrawDelRewardsArgs := args.WithArgs(
+ s.address, s.validators[0].OperatorAddress, tc.before, tc.after,
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawDelegatorRewards)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawDelRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+
+ // check balances
+ contractTransferredAmt := math.ZeroInt()
+ for _, transferred := range []bool{tc.before, tc.after} {
+ if transferred {
+ contractTransferredAmt = contractTransferredAmt.AddRaw(15)
+ }
+ }
+ // contract balance be updated according to the transferred amount
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Sub(contractTransferredAmt)))
+
+ expDelFinalBalance := delInitialBalance.Amount.Sub(fees).Add(contractTransferredAmt).Add(expRewards)
+ if tc.withdrawer != nil {
+ expDelFinalBalance = delInitialBalance.Amount.Sub(fees).Add(contractTransferredAmt)
+ expWithdrawerFinalBalance := withdrawerInitialBalance.Amount.Add(expRewards)
+ // withdrawer balance should have the rewards
+ withdrawerFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ Expect(withdrawerFinalBalance.Amount).To(Equal(expWithdrawerFinalBalance), "expected final balance to be greater than initial balance after withdrawing rewards")
+ }
+
+ // delegator balance should have the transferred amt - fees + rewards (when is the withdrawer)
+ delFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(delFinalBalance.Amount).To(Equal(expDelFinalBalance), "expected final balance to be greater than initial balance after withdrawing rewards")
+ },
+
+ Entry("delegator == withdrawer - with internal transfers before and after precompile call", testCase{
+ before: true,
+ after: true,
+ }),
+
+ Entry("delegator == withdrawer - with internal transfers before precompile call", testCase{
+ before: true,
+ after: false,
+ }),
+
+ Entry("delegator == withdrawer - with internal transfers after precompile call", testCase{
+ before: false,
+ after: true,
+ }),
+ Entry("delegator != withdrawer - with internal transfers before and after precompile call", testCase{
+ withdrawer: &differentAddr,
+ before: true,
+ after: true,
+ }),
+
+ Entry("delegator != withdrawer - with internal transfers before precompile call", testCase{
+ withdrawer: &differentAddr,
+ before: true,
+ after: false,
+ }),
+
+ Entry("delegator != withdrawer - with internal transfers after precompile call", testCase{
+ withdrawer: &differentAddr,
+ before: false,
+ after: true,
+ }),
+ )
+
+ DescribeTable("should revert withdraw rewards successfully and update correspondingly the withdrawer and contract's balances", func(tc testCase) {
+ // get the pending rewards to claim
+ qr := distrkeeper.Querier{Keeper: s.app.DistrKeeper}
+ qRes, err := qr.DelegationRewards(s.ctx, &distrtypes.QueryDelegationRewardsRequest{DelegatorAddress: sdk.AccAddress(s.address.Bytes()).String(), ValidatorAddress: s.validators[0].OperatorAddress})
+ Expect(err).To(BeNil())
+ initRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt()
+
+ delInitBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ withdrawerInitBalance := s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ // Set new withdrawer address
+ err = s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), tc.withdrawer.Bytes())
+ Expect(err).To(BeNil())
+
+ // update args to call the corresponding contract method
+ callArgs := args.
+ WithMethodName("revertWithdrawRewardsAndTransfer").
+ WithArgs(
+ s.address, *tc.withdrawer, s.validators[0].OperatorAddress, true,
+ )
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, callArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+
+ // check balances
+ contractTransferredAmt := math.NewInt(15)
+ // contract balance be updated according to the transferred amount
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Sub(contractTransferredAmt)))
+
+ // delegator balance should be initial_balance - fees
+ delFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(delFinalBalance.Amount).To(Equal(delInitBalance.Amount.Sub(fees)))
+
+ // withdrawer balance should increase by the transferred amount only
+ // the rewards withdrawal should revert
+ withdrawerFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ Expect(withdrawerFinalBalance.Amount).To(Equal(withdrawerInitBalance.Amount.Add(contractTransferredAmt)), "expected final balance to be greater than initial balance after withdrawing rewards")
+
+ // rewards to claim should remain unchanged
+ qRes, err = qr.DelegationRewards(s.ctx, &distrtypes.QueryDelegationRewardsRequest{DelegatorAddress: sdk.AccAddress(s.address.Bytes()).String(), ValidatorAddress: s.validators[0].OperatorAddress})
+ Expect(err).To(BeNil())
+ finalRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt()
+ Expect(finalRewards).To(Equal(initRewards))
+ },
+ Entry("withdrawer addr is existing acc", testCase{
+ withdrawer: &differentAddr,
+ }),
+ Entry("withdrawer addr is non-existing acc", testCase{
+ withdrawer: func() *common.Address {
+ addr := testutiltx.GenerateAddress()
+ return &addr
+ }(),
+ }),
+ )
+ })
+ })
+
+ Context("withdrawDelegatorRewards with contract as delegator", func() {
+ var (
+ // defaultWithdrawDelRewardsArgs are the default arguments for the withdraw delegator rewards call
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultWithdrawDelRewardsArgs contracts.CallArgs
+ // initialBalance is the initial balance of the delegator
+ initialBalance sdk.Coin
+ )
+
+ BeforeEach(func() {
+ // set some rewards for s.address & another address
+ s.prepareStakingRewards([]stakingRewards{
+ {
+ Delegator: contractAddr.Bytes(),
+ Validator: s.validators[0],
+ RewardAmt: rewards,
+ },
+ }...)
+
+ initialBalance = s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+
+ // populate default arguments
+ defaultWithdrawDelRewardsArgs = defaultCallArgs.WithMethodName(
+ "testWithdrawDelegatorRewardsFromContract",
+ )
+ })
+
+ It("should withdraw rewards successfully without origin check", func() {
+ withdrawDelRewardsArgs := defaultWithdrawDelRewardsArgs.WithArgs(s.validators[0].OperatorAddress)
+
+ logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorRewards)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawDelRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // balance should increase
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.GT(initialBalance.Amount)).To(BeTrue(), "expected final balance to be greater than initial balance after withdrawing rewards")
+ })
+
+ It("should withdraw rewards successfully without origin check to a withdrawer address", func() {
+ withdrawerAddr, _ := testutiltx.NewAccAddressAndKey()
+
+ initialWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, withdrawerAddr.Bytes(), s.bondDenom)
+ Expect(initialWithdrawerBalance.Amount).To(Equal(sdk.ZeroInt()))
+
+ err := s.app.DistrKeeper.SetWithdrawAddr(s.ctx, contractAddr.Bytes(), withdrawerAddr.Bytes())
+ Expect(err).To(BeNil())
+
+ withdrawDelRewardsArgs := defaultWithdrawDelRewardsArgs.WithArgs(s.validators[0].OperatorAddress)
+
+ logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorRewards)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawDelRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // withdrawer balance should increase with the rewards amt
+ finalWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, withdrawerAddr.Bytes(), s.bondDenom)
+ Expect(finalWithdrawerBalance.Amount.Equal(rewards)).To(BeTrue(), "expected final balance to be greater than initial balance after withdrawing rewards")
+
+ // delegator balance (contract) should remain unchanged
+ finalDelegatorBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(finalDelegatorBalance.Amount.Equal(initialBalance.Amount)).To(BeTrue(), "expected delegator final balance remain unchanged after withdrawing rewards to withdrawer")
+ })
+
+ Context("Withdraw Delegator Rewards with another smart contract (different than the contract calling the precompile) as delegator", func() {
+ var (
+ delContractAddr common.Address
+ args contracts.CallArgs
+ contractInitialBalance = math.NewInt(100)
+ )
+ BeforeEach(func() {
+ args = defaultWithdrawDelRewardsArgs.
+ WithMethodName("testWithdrawDelegatorRewardsWithTransfer").
+ WithGasPrice(gasPrice)
+
+ // deploy a contract to use as delegator contract
+ delegatorContract, err := contracts.LoadInterchainSenderContract()
+ Expect(err).To(BeNil())
+
+ delContractAddr, err = s.DeployContract(delegatorContract)
+ Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err)
+
+ // send some funds to the contract
+ err = evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, contractAddr.Bytes(), contractInitialBalance.Int64())
+ Expect(err).To(BeNil())
+
+ // set some rewards for the delegator contract
+ s.prepareStakingRewards([]stakingRewards{
+ {
+ Delegator: delContractAddr.Bytes(),
+ Validator: s.validators[0],
+ RewardAmt: rewards,
+ },
+ }...)
+ })
+
+ It("should NOT allow to withdraw rewards", func() {
+ txSenderInitialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ delInitialBalance := s.app.BankKeeper.GetBalance(s.ctx, delContractAddr.Bytes(), s.bondDenom)
+
+ // get the pending rewards to claim
+ qr := distrkeeper.Querier{Keeper: s.app.DistrKeeper}
+ qRes, err := qr.DelegationRewards(s.ctx, &distrtypes.QueryDelegationRewardsRequest{DelegatorAddress: sdk.AccAddress(delContractAddr.Bytes()).String(), ValidatorAddress: s.validators[0].OperatorAddress})
+ Expect(err).To(BeNil())
+ expRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt()
+
+ withdrawDelRewardsArgs := args.WithArgs(
+ delContractAddr, s.validators[0].OperatorAddress, true, true,
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawDelRewardsArgs, execRevertedCheck)
+ Expect(err).NotTo(BeNil(), "error while calling the smart contract: %v", err)
+
+ // check balances
+ // tx signer final balance should be the initial balance - fees
+ txSignerFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(txSignerFinalBalance.Amount.LT(txSenderInitialBalance.Amount)).To(BeTrue())
+
+ // contract balance be updated according to the transferred amount
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance))
+
+ // delegator balance should have the transferred amt + rewards (when is the withdrawer)
+ delFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, delContractAddr.Bytes(), s.bondDenom)
+ Expect(delFinalBalance.Amount).To(Equal(delInitialBalance.Amount))
+
+ // delegation rewards should remain unchanged
+ qRes, err = qr.DelegationRewards(s.ctx, &distrtypes.QueryDelegationRewardsRequest{DelegatorAddress: sdk.AccAddress(delContractAddr.Bytes()).String(), ValidatorAddress: s.validators[0].OperatorAddress})
+ Expect(err).To(BeNil())
+ Expect(qRes.Rewards.AmountOf(s.bondDenom).TruncateInt()).To(Equal(expRewards))
+ })
+ })
+ })
+
+ Context("withdrawValidatorCommission", func() {
+ var (
+ // defaultWithdrawValCommArgs are the default arguments for the withdraw validator commission call
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultWithdrawValCommArgs contracts.CallArgs
+ // commDec is the commission rate of the validator
+ commDec = math.LegacyNewDec(1)
+ // valAddr is the address of the validator
+ valAddr sdk.ValAddress
+ // initialBalance is the initial balance of the delegator
+ initialBalance sdk.Coin
+ )
+
+ BeforeEach(func() {
+ // create a validator with s.address because is the address
+ // used for signing txs
+ valAddr = s.address.Bytes()
+ stakeAmt := math.NewInt(100)
+ testutil.CreateValidator(s.ctx, s.T(), s.privKey.PubKey(), *s.app.StakingKeeper.Keeper, stakeAmt)
+
+ // set some commissions to validators
+ var valAddresses []sdk.ValAddress
+ valAddresses = append(
+ valAddresses,
+ valAddr,
+ s.validators[0].GetOperator(),
+ s.validators[1].GetOperator(),
+ )
+
+ for _, addr := range valAddresses {
+ val := s.app.StakingKeeper.Validator(s.ctx, addr)
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, commDec)}
+
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(
+ s.ctx, addr,
+ distrtypes.ValidatorAccumulatedCommission{Commission: valCommission},
+ )
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.DecCoins{sdk.NewDecCoin(s.bondDenom, stakeAmt)})
+ }
+
+ initialBalance = s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+
+ // populate default arguments
+ defaultWithdrawValCommArgs = defaultCallArgs.WithMethodName(
+ "testWithdrawValidatorCommission",
+ )
+ })
+
+ It("should not withdraw commission from validator when sending from a different address", func() {
+ withdrawValCommArgs := defaultWithdrawValCommArgs.WithArgs(
+ s.validators[0].OperatorAddress,
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawValCommArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // balance should be equal as initial balance or less (because of fees)
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.Uint64() <= initialBalance.Amount.Uint64()).To(BeTrue())
+
+ // validator's balance should remain unchanged
+ valFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, sdk.AccAddress(s.validators[0].GetOperator()), s.bondDenom)
+ Expect(valFinalBalance.Amount).To(Equal(math.ZeroInt()))
+ })
+
+ It("should withdraw commission successfully", func() {
+ withdrawValCommArgs := defaultWithdrawValCommArgs.
+ WithArgs(valAddr.String()).
+ WithGasPrice(gasPrice)
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawValidatorCommission)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawValCommArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fees := gasPrice.Int64() * res.GasUsed
+ expFinal := initialBalance.Amount.Int64() + expValAmount - fees
+ Expect(finalBalance.Amount).To(Equal(math.NewInt(expFinal)), "expected final balance to be equal to initial balance + validator commission - fees")
+ })
+
+ It("should withdraw commission successfully to withdrawer address (contract)", func() {
+ initialWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(initialWithdrawerBalance.Amount).To(Equal(sdk.ZeroInt()))
+
+ err := s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), contractAddr.Bytes())
+ Expect(err).To(BeNil())
+
+ withdrawValCommArgs := defaultWithdrawValCommArgs.
+ WithArgs(valAddr.String()).
+ WithGasPrice(gasPrice)
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawValidatorCommission)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawValCommArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ finalWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(finalWithdrawerBalance.Amount).To(Equal(math.NewInt(expValAmount)), "expected final balance to be equal to initial balance + validator commission")
+
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ fees := gasPrice.Int64() * res.GasUsed
+ expFinal := initialBalance.Amount.Int64() - fees
+ Expect(finalBalance.Amount).To(Equal(math.NewInt(expFinal)), "expected final balance to be equal to initial balance - fees")
+ })
+
+ // Specific BeforeEach for table-driven tests
+ Context("Table-driven tests for Withdraw Validator Commission", func() {
+ var (
+ args contracts.CallArgs
+ contractInitialBalance = math.NewInt(100)
+ )
+ BeforeEach(func() {
+ args = defaultWithdrawValCommArgs.
+ WithMethodName("testWithdrawValidatorCommissionWithTransfer").
+ WithGasPrice(gasPrice)
+
+ // send some funds to the contract
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, contractAddr.Bytes(), contractInitialBalance.Int64())
+ Expect(err).To(BeNil())
+ })
+
+ DescribeTable("withdraw validator commission with state changes in withdrawer - should withdraw commission successfully to the withdrawer address",
+ func(tc testCase) {
+ withdrawerAddr := s.address
+ withdrawerInitialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ if tc.withdrawer != nil {
+ withdrawerAddr = *tc.withdrawer
+ // Set new withdrawer address
+ err := s.app.DistrKeeper.SetWithdrawAddr(s.ctx, s.address.Bytes(), tc.withdrawer.Bytes())
+ Expect(err).To(BeNil())
+ withdrawerInitialBalance = s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ }
+
+ valInitialBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+
+ // get the pending commission to claim
+ valAccAddr := sdk.ValAddress(s.address.Bytes())
+ qr := distrkeeper.Querier{Keeper: s.app.DistrKeeper}
+ qRes, err := qr.ValidatorCommission(s.ctx, &distrtypes.QueryValidatorCommissionRequest{ValidatorAddress: valAccAddr.String()})
+ Expect(err).To(BeNil())
+ expCommission := qRes.Commission.Commission.AmountOf(s.bondDenom).TruncateInt()
+
+ withdrawValCommissionArgs := args.WithArgs(
+ valAccAddr.String(), withdrawerAddr, tc.before, tc.after,
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeWithdrawValidatorCommission)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, withdrawValCommissionArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+
+ // calculate the transferred amt during the call
+ contractTransferredAmt := math.ZeroInt()
+ for _, transferred := range []bool{tc.before, tc.after} {
+ if transferred {
+ contractTransferredAmt = contractTransferredAmt.AddRaw(15)
+ }
+ }
+
+ // check balances
+ expContractFinalBalance := contractInitialBalance.Sub(contractTransferredAmt)
+ expValFinalBalance := valInitialBalance.Amount.Sub(fees).Add(contractTransferredAmt).Add(expCommission)
+ if tc.withdrawer != nil {
+ expValFinalBalance = valInitialBalance.Amount.Sub(fees)
+ if *tc.withdrawer == contractAddr {
+ // no internal transfers if the contract itself is the withdrawer
+ expContractFinalBalance = contractInitialBalance.Add(expCommission)
+ } else {
+ expWithdrawerFinalBalance := withdrawerInitialBalance.Amount.Add(expCommission).Add(contractTransferredAmt)
+ // withdrawer balance should have the rewards
+ withdrawerFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, tc.withdrawer.Bytes(), s.bondDenom)
+ Expect(withdrawerFinalBalance.Amount).To(Equal(expWithdrawerFinalBalance), "expected final balance to be greater than initial balance after withdrawing rewards")
+ }
+ }
+
+ // contract balance be updated according to the transferred amount
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(expContractFinalBalance))
+
+ // validator balance should have the transferred amt - fees + rewards (when is the withdrawer)
+ valFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(valFinalBalance.Amount).To(Equal(expValFinalBalance), "expected final balance to be greater than initial balance after withdrawing rewards")
+ },
+
+ Entry("validator == withdrawer - with internal transfers before and after precompile call", testCase{
+ before: true,
+ after: true,
+ }),
+
+ Entry("validator == withdrawer - with internal transfers before precompile call", testCase{
+ before: true,
+ after: false,
+ }),
+
+ Entry("validator == withdrawer - with internal transfers after precompile call", testCase{
+ before: false,
+ after: true,
+ }),
+ Entry("validator != withdrawer - with internal transfers before and after precompile call", testCase{
+ withdrawer: &differentAddr,
+ before: true,
+ after: true,
+ }),
+
+ Entry("validator != withdrawer - with internal transfers before precompile call", testCase{
+ withdrawer: &differentAddr,
+ before: true,
+ after: false,
+ }),
+
+ Entry("validator != withdrawer - with internal transfers after precompile call", testCase{
+ withdrawer: &differentAddr,
+ before: false,
+ after: true,
+ }),
+ Entry("contract as withdrawer - with contract state change before and after precompile call", testCase{
+ withdrawer: &contractAddr,
+ before: true,
+ after: true,
+ }),
+
+ Entry("contract as withdrawer - with contract state change before precompile call", testCase{
+ withdrawer: &contractAddr,
+ before: true,
+ after: false,
+ }),
+
+ Entry("contract as withdrawer - with contract state change after precompile call", testCase{
+ withdrawer: &contractAddr,
+ before: false,
+ after: true,
+ }),
+ )
+ })
+ })
+
+ Context("claimRewards", func() {
+ var (
+ // defaultClaimRewardsArgs are the default arguments for the claim rewards call
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultClaimRewardsArgs contracts.CallArgs
+ // initialBalance is the initial balance of the delegator
+ initialBalance sdk.Coin
+ )
+
+ BeforeEach(func() {
+ // set some rewards for s.address & another address
+ s.prepareStakingRewards([]stakingRewards{
+ {s.address.Bytes(), s.validators[0], rewards},
+ {differentAddr.Bytes(), s.validators[0], rewards},
+ }...)
+
+ initialBalance = s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+
+ // populate default arguments
+ defaultClaimRewardsArgs = defaultCallArgs.WithMethodName(
+ "testClaimRewards",
+ )
+ })
+
+ It("should not claim rewards when sending from a different address", func() {
+ claimRewardsArgs := defaultClaimRewardsArgs.WithArgs(
+ differentAddr, uint32(1),
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, claimRewardsArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // balance should be equal as initial balance or less (because of fees)
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.Uint64() <= initialBalance.Amount.Uint64()).To(BeTrue())
+
+ // differentAddr balance should remain unchanged
+ differentAddrFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, differentAddr.Bytes(), s.bondDenom)
+ Expect(differentAddrFinalBalance.Amount).To(Equal(math.ZeroInt()))
+ })
+
+ It("should claim rewards successfully", func() {
+ claimRewardsArgs := defaultClaimRewardsArgs.WithArgs(
+ s.address, uint32(2),
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeClaimRewards)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, claimRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // balance should remain unchanged
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.GT(initialBalance.Amount)).To(BeTrue(), "expected final balance to be greater than initial balance after claiming rewards")
+ })
+
+ Context("Table driven tests", func() {
+ var (
+ args contracts.CallArgs
+ contractInitialBalance = math.NewInt(100)
+ )
+ BeforeEach(func() {
+ args = defaultClaimRewardsArgs.
+ WithMethodName("testClaimRewardsWithTransfer").
+ WithGasPrice(gasPrice)
+
+ // send some funds to the contract
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, contractAddr.Bytes(), contractInitialBalance.Int64())
+ Expect(err).To(BeNil())
+ })
+
+ DescribeTable("claimRewards with transfer to withdrawer", func(tc testCase) {
+ // get the pending rewards to claim
+ qr := distrkeeper.Querier{Keeper: s.app.DistrKeeper}
+ qRes, err := qr.DelegationTotalRewards(s.ctx, &distrtypes.QueryDelegationTotalRewardsRequest{DelegatorAddress: sdk.AccAddress(s.address.Bytes()).String()})
+ Expect(err).To(BeNil())
+ expRewards := qRes.Total.AmountOf(s.bondDenom).TruncateInt()
+
+ claimRewardsArgs := args.WithArgs(
+ s.address, uint32(2), tc.before, tc.after,
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(distribution.EventTypeClaimRewards)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, claimRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+
+ // calculate the transferred amt during the call
+ contractTransferredAmt := math.ZeroInt()
+ for _, transferred := range []bool{tc.before, tc.after} {
+ if transferred {
+ contractTransferredAmt = contractTransferredAmt.AddRaw(15)
+ }
+ }
+
+ // check balances
+ expContractFinalBalance := contractInitialBalance.Sub(contractTransferredAmt)
+ expDelFinalBalance := initialBalance.Amount.Sub(fees).Add(contractTransferredAmt).Add(expRewards)
+
+ // contract balance be updated according to the transferred amount
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(expContractFinalBalance))
+
+ // delegator (and withdrawer) balance should be updated
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(expDelFinalBalance), "expected final balance to be greater than initial balance after claiming rewards")
+ },
+ Entry("claim rewards with transfer to withdrawer before and after precompile call", testCase{
+ before: true,
+ after: true,
+ }),
+ Entry("claim rewards with transfer to withdrawer before precompile call", testCase{
+ before: true,
+ after: false,
+ }),
+ Entry("claim rewards with transfer to withdrawer after precompile call", testCase{
+ before: false,
+ after: true,
+ }),
+ )
+ })
+ })
+
+ Context("claimRewards with contract as delegator", func() {
+ var (
+ // defaultClaimRewardsArgs are the default arguments for the claim rewards call
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultClaimRewardsArgs contracts.CallArgs
+ // expectedBalance is the total after claiming from both validators
+ expectedBalance sdk.Coin
+ )
+
+ BeforeEach(func() {
+ // set some rewards for s.address & another address
+ s.prepareStakingRewards([]stakingRewards{
+ {
+ Delegator: contractAddr.Bytes(),
+ Validator: s.validators[0],
+ RewardAmt: rewards,
+ }, {
+ Delegator: contractAddr.Bytes(),
+ Validator: s.validators[1],
+ RewardAmt: rewards,
+ },
+ }...)
+
+ expectedBalance = sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewInt(2e18)}
+ // populate default arguments
+ defaultClaimRewardsArgs = defaultCallArgs.WithMethodName(
+ "testClaimRewards",
+ )
+ })
+
+ It("should withdraw rewards successfully without origin check", func() {
+ claimRewardsArgs := defaultClaimRewardsArgs.WithArgs(contractAddr, uint32(2))
+
+ logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeClaimRewards)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, claimRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // balance should increase
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.Equal(expectedBalance.Amount)).To(BeTrue(), "expected final balance to be greater than initial balance after withdrawing rewards")
+ })
+
+ It("should withdraw rewards successfully to a different address without origin check", func() {
+ withdrawerAddr, _ := testutiltx.NewAccAddressAndKey()
+ initialWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, withdrawerAddr.Bytes(), s.bondDenom)
+ Expect(initialWithdrawerBalance.Amount).To(Equal(sdk.ZeroInt()))
+
+ initialDelegatorBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+
+ err := s.app.DistrKeeper.SetWithdrawAddr(s.ctx, contractAddr.Bytes(), withdrawerAddr.Bytes())
+ Expect(err).To(BeNil())
+
+ claimRewardsArgs := defaultClaimRewardsArgs.WithArgs(contractAddr, uint32(2))
+
+ logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeClaimRewards)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, claimRewardsArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // withdrawer balance should increase
+ finalWithdrawerBalance := s.app.BankKeeper.GetBalance(s.ctx, withdrawerAddr.Bytes(), s.bondDenom)
+ Expect(finalWithdrawerBalance.Equal(expectedBalance)).To(BeTrue(), "expected final withdrawer balance to be greater than initial balance after withdrawing rewards")
+
+ // delegator (contract) balance should remain unchanged
+ finalDelegatorBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(finalDelegatorBalance.Amount.Equal(initialDelegatorBalance.Amount)).To(BeTrue(), "expected final delegator balance to same as initial balance after withdrawing rewards")
+ })
+ })
+
+ Context("Forbidden operations", func() {
+ It("should revert state: modify withdraw address & then try to withdraw rewards corresponding to another user", func() {
+ // set rewards to another user
+ s.prepareStakingRewards(stakingRewards{differentAddr.Bytes(), s.validators[0], rewards})
+
+ revertArgs := defaultCallArgs.
+ WithMethodName("testRevertState").
+ WithArgs(
+ differentAddr.String(), differentAddr, s.validators[0].OperatorAddress,
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, revertArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // check withdraw address didn't change
+ withdrawer := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawer.Bytes()).To(Equal(s.address.Bytes()))
+
+ // check signer address balance should've decreased (fees paid)
+ finalBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount.Uint64() <= initBalanceAmt.Uint64()).To(BeTrue())
+
+ // check other address' balance remained unchanged
+ finalBalance = s.app.BankKeeper.GetBalance(s.ctx, differentAddr.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(math.ZeroInt()))
+ })
+
+ It("should not allow to call SetWithdrawAddress using delegatecall", func() {
+ setWithdrawAddrArgs := defaultCallArgs.
+ WithMethodName("delegateCallSetWithdrawAddress").
+ WithArgs(s.address, differentAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, setWithdrawAddrArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // check withdraw address didn't change
+ withdrawer := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawer.Bytes()).To(Equal(s.address.Bytes()))
+ })
+
+ It("should not allow to call txs (SetWithdrawAddress) using staticcall", func() {
+ setWithdrawAddrArgs := defaultCallArgs.
+ WithMethodName("staticCallSetWithdrawAddress").
+ WithArgs(s.address, differentAddr.String())
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, setWithdrawAddrArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ // check withdraw address didn't change
+ withdrawer := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ Expect(withdrawer.Bytes()).To(Equal(s.address.Bytes()))
+ })
+ })
+
+ // ===================================
+ // QUERIES
+ // ===================================
+ Context("Distribution precompile queries", func() {
+ Context("get validator distribution info", func() {
+ // defaultValDistArgs are the default arguments for the getValidatorDistributionInfo query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultValDistArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ addr := sdk.AccAddress(s.validators[0].GetOperator())
+ // fund validator account to make self-delegation
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, addr, 10)
+ Expect(err).To(BeNil())
+ // make a self delegation
+ _, err = s.app.StakingKeeper.Delegate(s.ctx, addr, math.NewInt(1), stakingtypes.Unspecified, s.validators[0], true)
+ Expect(err).To(BeNil())
+
+ defaultValDistArgs = defaultCallArgs.
+ WithMethodName("getValidatorDistributionInfo").
+ WithArgs(s.validators[0].OperatorAddress)
+ })
+
+ It("should get validator distribution info", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValDistArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out distribution.ValidatorDistributionInfoOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorDistributionInfoMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+
+ expAddr := sdk.AccAddress(s.validators[0].GetOperator())
+ Expect(expAddr.String()).To(Equal(out.DistributionInfo.OperatorAddress))
+ Expect(0).To(Equal(len(out.DistributionInfo.Commission)))
+ Expect(0).To(Equal(len(out.DistributionInfo.SelfBondRewards)))
+ })
+ })
+
+ Context("get validator outstanding rewards", func() { //nolint:dupl
+ // defaultValOutRewardsArgs are the default arguments for the getValidatorOutstandingRewards query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultValOutRewardsArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultValOutRewardsArgs = defaultCallArgs.
+ WithMethodName("getValidatorOutstandingRewards").
+ WithArgs(s.validators[0].OperatorAddress)
+ })
+
+ It("should not get rewards - validator without outstanding rewards", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValOutRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var rewards []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.ValidatorOutstandingRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(0))
+ })
+
+ It("should get rewards - validator with outstanding rewards", func() {
+ valRewards := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, math.LegacyNewDec(1))}
+ // set outstanding rewards
+ s.app.DistrKeeper.SetValidatorOutstandingRewards(s.ctx, s.validators[0].GetOperator(), distrtypes.ValidatorOutstandingRewards{Rewards: valRewards})
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValOutRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var rewards []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.ValidatorOutstandingRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(1))
+ Expect(uint8(18)).To(Equal(rewards[0].Precision))
+ Expect(s.bondDenom).To(Equal(rewards[0].Denom))
+ Expect(expValAmount).To(Equal(rewards[0].Amount.Int64()))
+ })
+ })
+
+ Context("get validator commission", func() { //nolint:dupl
+ // defaultValCommArgs are the default arguments for the getValidatorCommission query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultValCommArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultValCommArgs = defaultCallArgs.
+ WithMethodName("getValidatorCommission").
+ WithArgs(s.validators[0].OperatorAddress)
+ })
+
+ It("should not get commission - validator without commission", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValCommArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var commission []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(commission)).To(Equal(0))
+ })
+
+ It("should get commission - validator with commission", func() {
+ // set commission
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, math.LegacyNewDec(1))}
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(s.ctx, s.validators[0].GetOperator(), distrtypes.ValidatorAccumulatedCommission{Commission: valCommission})
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValCommArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var commission []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(commission)).To(Equal(1))
+ Expect(uint8(18)).To(Equal(commission[0].Precision))
+ Expect(s.bondDenom).To(Equal(commission[0].Denom))
+ Expect(expValAmount).To(Equal(commission[0].Amount.Int64()))
+ })
+ })
+
+ Context("get validator slashing events", func() {
+ // defaultValSlashArgs are the default arguments for the getValidatorSlashes query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultValSlashArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultValSlashArgs = defaultCallArgs.
+ WithMethodName("getValidatorSlashes").
+ WithArgs(
+ s.validators[0].OperatorAddress,
+ uint64(1), uint64(5),
+ query.PageRequest{},
+ )
+ })
+
+ It("should not get slashing events - validator without slashes", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValSlashArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out distribution.ValidatorSlashesOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(out.Slashes)).To(Equal(0))
+ })
+
+ It("should get slashing events - validator with slashes (default pagination)", func() {
+ // set slash event
+ slashEvent := s.setupValidatorSlashes(s.validators[0].GetOperator(), 1)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValSlashArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out distribution.ValidatorSlashesOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(out.Slashes)).To(Equal(1))
+ Expect(slashEvent.Fraction.BigInt()).To(Equal(out.Slashes[0].Fraction.Value))
+ Expect(slashEvent.ValidatorPeriod).To(Equal(out.Slashes[0].ValidatorPeriod))
+ Expect(uint64(1)).To(Equal(out.PageResponse.Total))
+ Expect(out.PageResponse.NextKey).To(BeEmpty())
+ })
+
+ It("should get slashing events - validator with slashes w/pagination", func() {
+ // set 2 slashing events
+ slashEvent := s.setupValidatorSlashes(s.validators[0].GetOperator(), 2)
+
+ // set pagination
+ defaultValSlashArgs.Args = []interface{}{
+ s.validators[0].OperatorAddress,
+ uint64(1), uint64(5),
+ query.PageRequest{
+ Limit: 1,
+ CountTotal: true,
+ },
+ }
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultValSlashArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out distribution.ValidatorSlashesOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(out.Slashes)).To(Equal(1))
+ Expect(slashEvent.Fraction.BigInt()).To(Equal(out.Slashes[0].Fraction.Value))
+ Expect(slashEvent.ValidatorPeriod).To(Equal(out.Slashes[0].ValidatorPeriod))
+ Expect(uint64(2)).To(Equal(out.PageResponse.Total))
+ Expect(out.PageResponse.NextKey).NotTo(BeEmpty())
+ })
+ })
+
+ Context("get delegation rewards", func() {
+ // defaultDelRewardsArgs are the default arguments for the getDelegationRewards query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultDelRewardsArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultDelRewardsArgs = defaultCallArgs.
+ WithMethodName("getDelegationRewards").
+ WithArgs(s.address, s.validators[0].OperatorAddress)
+ })
+
+ It("should not get rewards - no rewards available", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultDelRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var rewards []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(0))
+ })
+ It("should get rewards", func() {
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultDelRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var rewards []cmn.DecCoin
+ err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(rewards)).To(Equal(1))
+ Expect(len(rewards)).To(Equal(1))
+ Expect(rewards[0].Denom).To(Equal(s.bondDenom))
+ Expect(rewards[0].Amount.Int64()).To(Equal(expDelegationRewards))
+ })
+ })
+
+ Context("get delegator's total rewards", func() {
+ // defaultDelTotalRewardsArgs are the default arguments for the getDelegationTotalRewards query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultDelTotalRewardsArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultDelTotalRewardsArgs = defaultCallArgs.
+ WithMethodName("getDelegationTotalRewards").
+ WithArgs(s.address)
+ })
+
+ It("should not get rewards - no rewards available", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultDelTotalRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out distribution.DelegationTotalRewardsOutput
+ err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(len(out.Rewards)).To(Equal(2))
+ Expect(len(out.Rewards[0].Reward)).To(Equal(0))
+ Expect(len(out.Rewards[1].Reward)).To(Equal(0))
+ })
+ It("should get total rewards", func() {
+ // set rewards
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultDelTotalRewardsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var (
+ out distribution.DelegationTotalRewardsOutput
+ i int
+ )
+ err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+
+ // the response order may change
+ if out.Rewards[0].ValidatorAddress == s.validators[0].OperatorAddress {
+ Expect(s.validators[0].OperatorAddress).To(Equal(out.Rewards[0].ValidatorAddress))
+ Expect(s.validators[1].OperatorAddress).To(Equal(out.Rewards[1].ValidatorAddress))
+ Expect(0).To(Equal(len(out.Rewards[1].Reward)))
+ } else {
+ i = 1
+ Expect(s.validators[0].OperatorAddress).To(Equal(out.Rewards[1].ValidatorAddress))
+ Expect(s.validators[1].OperatorAddress).To(Equal(out.Rewards[0].ValidatorAddress))
+ Expect(0).To(Equal(len(out.Rewards[0].Reward)))
+ }
+
+ // only validator[i] has rewards
+ Expect(1).To(Equal(len(out.Rewards[i].Reward)))
+ Expect(s.bondDenom).To(Equal(out.Rewards[i].Reward[0].Denom))
+ Expect(uint8(math.LegacyPrecision)).To(Equal(out.Rewards[i].Reward[0].Precision))
+ Expect(expDelegationRewards).To(Equal(out.Rewards[i].Reward[0].Amount.Int64()))
+
+ Expect(1).To(Equal(len(out.Total)))
+ Expect(expDelegationRewards).To(Equal(out.Total[0].Amount.Int64()))
+ })
+
+ Context("query call with revert - all changes should revert to corresponding stateDB snapshot", func() {
+ var (
+ reverterContract evmtypes.CompiledContract
+ reverterAddr common.Address
+ testContractInitialBalance = math.NewInt(1000)
+ )
+ BeforeEach(func() {
+ var err error
+ // Deploy Reverter contract
+ reverterContract, err = contracts.LoadReverterContract()
+ Expect(err).To(BeNil(), "error while loading the Reverter contract")
+
+ reverterAddr, err = s.DeployContract(reverterContract)
+ Expect(err).To(BeNil(), "error while deploying the Reverter contract")
+ s.NextBlock()
+
+ // send some funds to the Reverter contracts to transfer to the
+ // delegator during the tx
+ err = evmosutil.FundAccount(s.ctx, s.app.BankKeeper, reverterAddr.Bytes(), sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, testContractInitialBalance)))
+ Expect(err).To(BeNil(), "error while funding the smart contract: %v", err)
+ })
+
+ It("should revert the execution - Reverter contract", func() {
+ args := contracts.CallArgs{
+ ContractAddr: reverterAddr,
+ ContractABI: reverterContract.ABI,
+ PrivKey: s.privKey,
+ MethodName: "run",
+ GasPrice: gasPrice,
+ }
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, args, execRevertedCheck)
+ Expect(err).NotTo(BeNil(), "error while calling the smart contract: %v", err)
+
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, reverterAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(testContractInitialBalance))
+ })
+ })
+ })
+
+ Context("get all delegator validators", func() {
+ // defaultDelValArgs are the default arguments for the getDelegatorValidators query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultDelValArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultDelValArgs = defaultCallArgs.
+ WithMethodName("getDelegatorValidators").
+ WithArgs(s.address)
+ })
+
+ It("should get all validators a delegator has delegated to", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultDelValArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var validators []string
+ err = s.precompile.UnpackIntoInterface(&validators, distribution.DelegatorValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ Expect(2).To(Equal(len(validators)))
+
+ // the response order may change
+ if validators[0] == s.validators[0].OperatorAddress {
+ Expect(s.validators[0].OperatorAddress).To(Equal(validators[0]))
+ Expect(s.validators[1].OperatorAddress).To(Equal(validators[1]))
+ } else {
+ Expect(s.validators[1].OperatorAddress).To(Equal(validators[0]))
+ Expect(s.validators[0].OperatorAddress).To(Equal(validators[1]))
+ }
+ })
+ })
+
+ Context("get withdraw address", func() {
+ // defaultWithdrawAddrArgs are the default arguments for the getDelegatorWithdrawAddress query
+ //
+ // NOTE: this has to be populated in BeforeEach because the test suite setup is not available prior to that.
+ var defaultWithdrawAddrArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultWithdrawAddrArgs = defaultCallArgs.
+ WithMethodName("getDelegatorWithdrawAddress").
+ WithArgs(s.address)
+ })
+
+ It("should get withdraw address", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, defaultWithdrawAddrArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ // get the bech32 encoding
+ expAddr := sdk.AccAddress(s.address.Bytes())
+ Expect(withdrawAddr[0]).To(Equal(expAddr.String()))
+ })
+
+ It("should call GetWithdrawAddress using staticcall", func() {
+ staticCallArgs := defaultCallArgs.
+ WithMethodName("staticCallGetWithdrawAddress").
+ WithArgs(s.address)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, staticCallArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret)
+ Expect(err).To(BeNil())
+ // get the bech32 encoding
+ expAddr := sdk.AccAddress(s.address.Bytes())
+ Expect(withdrawAddr[0]).To(ContainSubstring(expAddr.String()))
+ })
+ })
+ })
+})
diff --git a/precompiles/distribution/query.go b/precompiles/distribution/query.go
new file mode 100644
index 00000000..5299989a
--- /dev/null
+++ b/precompiles/distribution/query.go
@@ -0,0 +1,220 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package distribution
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // ValidatorDistributionInfoMethod defines the ABI method name for the
+ // ValidatorDistributionInfo query.
+ ValidatorDistributionInfoMethod = "validatorDistributionInfo"
+ // ValidatorOutstandingRewardsMethod defines the ABI method name for the
+ // ValidatorOutstandingRewards query.
+ ValidatorOutstandingRewardsMethod = "validatorOutstandingRewards"
+ // ValidatorCommissionMethod defines the ABI method name for the
+ // ValidatorCommission query.
+ ValidatorCommissionMethod = "validatorCommission"
+ // ValidatorSlashesMethod defines the ABI method name for the
+ // ValidatorSlashes query.
+ ValidatorSlashesMethod = "validatorSlashes"
+ // DelegationRewardsMethod defines the ABI method name for the
+ // DelegationRewards query.
+ DelegationRewardsMethod = "delegationRewards"
+ // DelegationTotalRewardsMethod defines the ABI method name for the
+ // DelegationTotalRewards query.
+ DelegationTotalRewardsMethod = "delegationTotalRewards"
+ // DelegatorValidatorsMethod defines the ABI method name for the
+ // DelegatorValidators query.
+ DelegatorValidatorsMethod = "delegatorValidators"
+ // DelegatorWithdrawAddressMethod defines the ABI method name for the
+ // DelegatorWithdrawAddress query.
+ DelegatorWithdrawAddressMethod = "delegatorWithdrawAddress"
+)
+
+// ValidatorDistributionInfo returns the distribution info for a validator.
+func (p Precompile) ValidatorDistributionInfo(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewValidatorDistributionInfoRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+
+ res, err := querier.ValidatorDistributionInfo(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ out := new(ValidatorDistributionInfoOutput).FromResponse(res)
+
+ return method.Outputs.Pack(out.DistributionInfo)
+}
+
+// ValidatorOutstandingRewards returns the outstanding rewards for a validator.
+func (p Precompile) ValidatorOutstandingRewards(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewValidatorOutstandingRewardsRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+
+ res, err := querier.ValidatorOutstandingRewards(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(cmn.NewDecCoinsResponse(res.Rewards.Rewards))
+}
+
+// ValidatorCommission returns the commission for a validator.
+func (p Precompile) ValidatorCommission(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewValidatorCommissionRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+
+ res, err := querier.ValidatorCommission(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(cmn.NewDecCoinsResponse(res.Commission.Commission))
+}
+
+// ValidatorSlashes returns the slashes for a validator.
+func (p Precompile) ValidatorSlashes(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewValidatorSlashesRequest(method, args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+
+ res, err := querier.ValidatorSlashes(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ out := new(ValidatorSlashesOutput).FromResponse(res)
+
+ return out.Pack(method.Outputs)
+}
+
+// DelegationRewards returns the total rewards accrued by a delegation.
+func (p Precompile) DelegationRewards(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDelegationRewardsRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+ res, err := querier.DelegationRewards(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(cmn.NewDecCoinsResponse(res.Rewards))
+}
+
+// DelegationTotalRewards returns the total rewards accrued by a delegation.
+func (p Precompile) DelegationTotalRewards(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDelegationTotalRewardsRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+
+ res, err := querier.DelegationTotalRewards(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ out := new(DelegationTotalRewardsOutput).FromResponse(res)
+
+ return out.Pack(method.Outputs)
+}
+
+// DelegatorValidators returns the validators a delegator is bonded to.
+func (p Precompile) DelegatorValidators(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDelegatorValidatorsRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+
+ res, err := querier.DelegatorValidators(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(res.Validators)
+}
+
+// DelegatorWithdrawAddress returns the withdraw address for a delegator.
+func (p Precompile) DelegatorWithdrawAddress(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDelegatorWithdrawAddressRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ querier := distributionkeeper.Querier{Keeper: p.distributionKeeper}
+
+ res, err := querier.DelegatorWithdrawAddress(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(res.WithdrawAddress)
+}
diff --git a/precompiles/distribution/query_test.go b/precompiles/distribution/query_test.go
new file mode 100644
index 00000000..394c1ac6
--- /dev/null
+++ b/precompiles/distribution/query_test.go
@@ -0,0 +1,845 @@
+package distribution_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ "github.com/cosmos/cosmos-sdk/testutil/mock"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ "github.com/evmos/evmos/v19/testutil"
+ testutiltx "github.com/evmos/evmos/v19/testutil/tx"
+
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+)
+
+var (
+ expDelegationRewards int64 = 2000000000000000000
+ expValAmount int64 = 1
+ rewards, _ = math.NewIntFromString("1000000000000000000")
+)
+
+type distrTestCases struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+}
+
+var baseTestCases = []distrTestCases{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "invalid number of arguments",
+ },
+ {
+ "fail - invalid validator address",
+ func() []interface{} {
+ return []interface{}{
+ "invalid",
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "invalid bech32 string",
+ },
+}
+
+func (s *PrecompileTestSuite) TestValidatorDistributionInfo() {
+ method := s.precompile.Methods[distribution.ValidatorDistributionInfoMethod]
+
+ testCases := []distrTestCases{
+ {
+ "fail - nonexistent validator address",
+ func() []interface{} {
+ pv := mock.NewPV()
+ pk, err := pv.GetPubKey()
+ s.Require().NoError(err)
+ return []interface{}{
+ sdk.ValAddress(pk.Address().Bytes()).String(),
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "validator does not exist",
+ },
+ {
+ "fail - existent validator but without self delegation",
+ func() []interface{} {
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "delegation does not exist",
+ },
+ {
+ "success",
+ func() []interface{} {
+ addr := sdk.AccAddress(s.validators[0].GetOperator())
+ // fund del account to make self-delegation
+ err := testutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, addr, 10)
+ s.Require().NoError(err)
+ // make a self delegation
+ _, err = s.app.StakingKeeper.Delegate(s.ctx, addr, math.NewInt(1), stakingtypes.Unspecified, s.validators[0], true)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var out distribution.ValidatorDistributionInfoOutput
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorDistributionInfoMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ expAddr := sdk.AccAddress(s.validators[0].GetOperator())
+ s.Require().Equal(expAddr.String(), out.DistributionInfo.OperatorAddress)
+ s.Require().Equal(0, len(out.DistributionInfo.Commission))
+ s.Require().Equal(0, len(out.DistributionInfo.SelfBondRewards))
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases...)
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.ValidatorDistributionInfo(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestValidatorOutstandingRewards() { //nolint:dupl
+ method := s.precompile.Methods[distribution.ValidatorOutstandingRewardsMethod]
+
+ testCases := []distrTestCases{
+ {
+ "success - nonexistent validator address",
+ func() []interface{} {
+ pv := mock.NewPV()
+ pk, err := pv.GetPubKey()
+ s.Require().NoError(err)
+ return []interface{}{
+ sdk.ValAddress(pk.Address().Bytes()).String(),
+ }
+ },
+ func(bz []byte) {
+ var out []sdk.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorOutstandingRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(0, len(out))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - existent validator, no outstanding rewards",
+ func() []interface{} {
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var out []sdk.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorOutstandingRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(0, len(out))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - with outstanding rewards",
+ func() []interface{} {
+ valRewards := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, math.LegacyNewDec(1))}
+ // set outstanding rewards
+ s.app.DistrKeeper.SetValidatorOutstandingRewards(s.ctx, s.validators[0].GetOperator(), types.ValidatorOutstandingRewards{Rewards: valRewards})
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var out []cmn.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorOutstandingRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(1, len(out))
+ s.Require().Equal(uint8(18), out[0].Precision)
+ s.Require().Equal(s.bondDenom, out[0].Denom)
+ s.Require().Equal(expValAmount, out[0].Amount.Int64())
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases...)
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.ValidatorOutstandingRewards(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestValidatorCommission() { //nolint:dupl
+ method := s.precompile.Methods[distribution.ValidatorCommissionMethod]
+
+ testCases := []distrTestCases{
+ {
+ "success - nonexistent validator address",
+ func() []interface{} {
+ pv := mock.NewPV()
+ pk, err := pv.GetPubKey()
+ s.Require().NoError(err)
+ return []interface{}{
+ sdk.ValAddress(pk.Address().Bytes()).String(),
+ }
+ },
+ func(bz []byte) {
+ var out []sdk.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorCommissionMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(0, len(out))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - existent validator, no accumulated commission",
+ func() []interface{} {
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var out []sdk.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorCommissionMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(0, len(out))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - with accumulated commission",
+ func() []interface{} {
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, math.LegacyNewDec(1))}
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(s.ctx, s.validators[0].GetOperator(), types.ValidatorAccumulatedCommission{Commission: valCommission})
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var out []cmn.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorCommissionMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(1, len(out))
+ s.Require().Equal(uint8(18), out[0].Precision)
+ s.Require().Equal(s.bondDenom, out[0].Denom)
+ s.Require().Equal(expValAmount, out[0].Amount.Int64())
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases...)
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.ValidatorCommission(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestValidatorSlashes() {
+ method := s.precompile.Methods[distribution.ValidatorSlashesMethod]
+
+ testCases := []distrTestCases{
+ {
+ "fail - invalid validator address",
+ func() []interface{} {
+ return []interface{}{
+ "invalid", uint64(1), uint64(5), query.PageRequest{},
+ }
+ },
+ func([]byte) {
+ },
+ 100000,
+ true,
+ "invalid validator address",
+ },
+ {
+ "fail - invalid starting height type",
+ func() []interface{} {
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ int64(1), uint64(5),
+ query.PageRequest{},
+ }
+ },
+ func([]byte) {
+ },
+ 100000,
+ true,
+ "invalid type for startingHeight: expected uint64, received int64",
+ },
+ {
+ "fail - starting height greater than ending height",
+ func() []interface{} {
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ uint64(6), uint64(5),
+ query.PageRequest{},
+ }
+ },
+ func([]byte) {
+ },
+ 100000,
+ true,
+ "starting height greater than ending height",
+ },
+ {
+ "success - nonexistent validator address",
+ func() []interface{} {
+ pv := mock.NewPV()
+ pk, err := pv.GetPubKey()
+ s.Require().NoError(err)
+ return []interface{}{
+ sdk.ValAddress(pk.Address().Bytes()).String(),
+ uint64(1),
+ uint64(5),
+ query.PageRequest{},
+ }
+ },
+ func(bz []byte) {
+ var out distribution.ValidatorSlashesOutput
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(0, len(out.Slashes))
+ s.Require().Equal(uint64(0), out.PageResponse.Total)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - existent validator, no slashes",
+ func() []interface{} {
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ uint64(1),
+ uint64(5),
+ query.PageRequest{},
+ }
+ },
+ func(bz []byte) {
+ var out distribution.ValidatorSlashesOutput
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(0, len(out.Slashes))
+ s.Require().Equal(uint64(0), out.PageResponse.Total)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - with slashes",
+ func() []interface{} {
+ s.app.DistrKeeper.SetValidatorSlashEvent(s.ctx, s.validators[0].GetOperator(), 2, 1, types.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)})
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ uint64(1), uint64(5),
+ query.PageRequest{},
+ }
+ },
+ func(bz []byte) {
+ var out distribution.ValidatorSlashesOutput
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(1, len(out.Slashes))
+ s.Require().Equal(math.LegacyNewDec(5).BigInt(), out.Slashes[0].Fraction.Value)
+ s.Require().Equal(uint64(1), out.Slashes[0].ValidatorPeriod)
+ s.Require().Equal(uint64(1), out.PageResponse.Total)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - with slashes w/pagination",
+ func() []interface{} {
+ s.app.DistrKeeper.SetValidatorSlashEvent(s.ctx, s.validators[0].GetOperator(), 2, 1, types.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)})
+ return []interface{}{
+ s.validators[0].OperatorAddress,
+ uint64(1),
+ uint64(5),
+ query.PageRequest{Limit: 1, CountTotal: true},
+ }
+ },
+ func(bz []byte) {
+ var out distribution.ValidatorSlashesOutput
+ err := s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(1, len(out.Slashes))
+ s.Require().Equal(math.LegacyNewDec(5).BigInt(), out.Slashes[0].Fraction.Value)
+ s.Require().Equal(uint64(1), out.Slashes[0].ValidatorPeriod)
+ s.Require().Equal(uint64(1), out.PageResponse.Total)
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases[0])
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.ValidatorSlashes(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDelegationRewards() {
+ method := s.precompile.Methods[distribution.DelegationRewardsMethod]
+
+ testCases := []distrTestCases{
+ {
+ "fail - invalid validator address",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ "invalid",
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "invalid bech32 string",
+ },
+ {
+ "fail - nonexistent validator address",
+ func() []interface{} {
+ pv := mock.NewPV()
+ pk, err := pv.GetPubKey()
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ sdk.ValAddress(pk.Address().Bytes()).String(),
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "validator does not exist",
+ },
+ {
+ "fail - existent validator, no delegation",
+ func() []interface{} {
+ newAddr, _ := testutiltx.NewAddrKey()
+ return []interface{}{
+ newAddr,
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "delegation does not exist",
+ },
+ {
+ "success - existent validator & delegation, but no rewards",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var out []cmn.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegationRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(0, len(out))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - with rewards",
+ func() []interface{} {
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+ return []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var out []cmn.DecCoin
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegationRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(1, len(out))
+ s.Require().Equal(uint8(18), out[0].Precision)
+ s.Require().Equal(s.bondDenom, out[0].Denom)
+ s.Require().Equal(expDelegationRewards, out[0].Amount.Int64())
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases[0])
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.DelegationRewards(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDelegationTotalRewards() {
+ method := s.precompile.Methods[distribution.DelegationTotalRewardsMethod]
+
+ testCases := []distrTestCases{
+ {
+ "fail - invalid delegator address",
+ func() []interface{} {
+ return []interface{}{
+ "invalid",
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, "invalid"),
+ },
+ {
+ "success - no delegations",
+ func() []interface{} {
+ newAddr, _ := testutiltx.NewAddrKey()
+ return []interface{}{
+ newAddr,
+ }
+ },
+ func(bz []byte) {
+ var out distribution.DelegationTotalRewardsOutput
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(0, len(out.Rewards))
+ s.Require().Equal(0, len(out.Total))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - existent validator & delegation, but no rewards",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ }
+ },
+ func(bz []byte) {
+ var out distribution.DelegationTotalRewardsOutput
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(2, len(out.Rewards))
+ // the response order may change
+ if out.Rewards[0].ValidatorAddress == s.validators[0].OperatorAddress {
+ s.Require().Equal(s.validators[0].OperatorAddress, out.Rewards[0].ValidatorAddress)
+ s.Require().Equal(s.validators[1].OperatorAddress, out.Rewards[1].ValidatorAddress)
+ } else {
+ s.Require().Equal(s.validators[1].OperatorAddress, out.Rewards[0].ValidatorAddress)
+ s.Require().Equal(s.validators[0].OperatorAddress, out.Rewards[1].ValidatorAddress)
+ }
+ // no rewards
+ s.Require().Equal(0, len(out.Rewards[0].Reward))
+ s.Require().Equal(0, len(out.Rewards[1].Reward))
+ s.Require().Equal(0, len(out.Total))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - with rewards",
+ func() []interface{} {
+ s.prepareStakingRewards(stakingRewards{s.address.Bytes(), s.validators[0], rewards})
+ return []interface{}{
+ s.address,
+ }
+ },
+ func(bz []byte) {
+ var (
+ out distribution.DelegationTotalRewardsOutput
+ i int
+ )
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(2, len(out.Rewards))
+
+ // the response order may change
+ if out.Rewards[0].ValidatorAddress == s.validators[0].OperatorAddress {
+ s.Require().Equal(s.validators[0].OperatorAddress, out.Rewards[0].ValidatorAddress)
+ s.Require().Equal(s.validators[1].OperatorAddress, out.Rewards[1].ValidatorAddress)
+ s.Require().Equal(0, len(out.Rewards[1].Reward))
+ } else {
+ i = 1
+ s.Require().Equal(s.validators[0].OperatorAddress, out.Rewards[1].ValidatorAddress)
+ s.Require().Equal(s.validators[1].OperatorAddress, out.Rewards[0].ValidatorAddress)
+ s.Require().Equal(0, len(out.Rewards[0].Reward))
+ }
+
+ // only validator[i] has rewards
+ s.Require().Equal(1, len(out.Rewards[i].Reward))
+ s.Require().Equal(s.bondDenom, out.Rewards[i].Reward[0].Denom)
+ s.Require().Equal(uint8(math.LegacyPrecision), out.Rewards[i].Reward[0].Precision)
+ s.Require().Equal(expDelegationRewards, out.Rewards[i].Reward[0].Amount.Int64())
+
+ s.Require().Equal(1, len(out.Total))
+ s.Require().Equal(expDelegationRewards, out.Total[0].Amount.Int64())
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases[0])
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.DelegationTotalRewards(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDelegatorValidators() {
+ method := s.precompile.Methods[distribution.DelegatorValidatorsMethod]
+
+ testCases := []distrTestCases{
+ {
+ "fail - invalid delegator address",
+ func() []interface{} {
+ return []interface{}{
+ "invalid",
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, "invalid"),
+ },
+ {
+ "success - no delegations",
+ func() []interface{} {
+ newAddr, _ := testutiltx.NewAddrKey()
+ return []interface{}{
+ newAddr,
+ }
+ },
+ func(bz []byte) {
+ var out []string
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegatorValidatorsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(0, len(out))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - existent delegations",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ }
+ },
+ func(bz []byte) {
+ var out []string
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegatorValidatorsMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(2, len(out))
+ // the order may change
+ if out[0] == s.validators[0].OperatorAddress {
+ s.Require().Equal(s.validators[0].OperatorAddress, out[0])
+ s.Require().Equal(s.validators[1].OperatorAddress, out[1])
+ } else {
+ s.Require().Equal(s.validators[1].OperatorAddress, out[0])
+ s.Require().Equal(s.validators[0].OperatorAddress, out[1])
+ }
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases[0])
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.DelegatorValidators(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDelegatorWithdrawAddress() {
+ method := s.precompile.Methods[distribution.DelegatorWithdrawAddressMethod]
+
+ testCases := []distrTestCases{
+ {
+ "fail - invalid delegator address",
+ func() []interface{} {
+ return []interface{}{
+ "invalid",
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, "invalid"),
+ },
+ {
+ "success - withdraw address same as delegator address",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ }
+ },
+ func(bz []byte) {
+ var out string
+ err := s.precompile.UnpackIntoInterface(&out, distribution.DelegatorWithdrawAddressMethod, bz)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(sdk.AccAddress(s.address.Bytes()).String(), out)
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, baseTestCases[0])
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.DelegatorWithdrawAddress(s.ctx, contract, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
diff --git a/precompiles/distribution/setup_test.go b/precompiles/distribution/setup_test.go
new file mode 100644
index 00000000..2d891d43
--- /dev/null
+++ b/precompiles/distribution/setup_test.go
@@ -0,0 +1,58 @@
+package distribution_test
+
+import (
+ "testing"
+
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ tmtypes "github.com/cometbft/cometbft/types"
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ evmosapp "github.com/evmos/evmos/v19/app"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ "github.com/stretchr/testify/suite"
+)
+
+var s *PrecompileTestSuite
+
+type PrecompileTestSuite struct {
+ suite.Suite
+
+ ctx sdk.Context
+ app *evmosapp.Evmos
+ address common.Address
+ validators []stakingtypes.Validator
+ valSet *tmtypes.ValidatorSet
+ ethSigner ethtypes.Signer
+ privKey cryptotypes.PrivKey
+ signer keyring.Signer
+ bondDenom string
+
+ precompile *distribution.Precompile
+ stateDB *statedb.StateDB
+
+ queryClientEVM evmtypes.QueryClient
+}
+
+func TestPrecompileTestSuite(t *testing.T) {
+ s = new(PrecompileTestSuite)
+ suite.Run(t, s)
+
+ // Run Ginkgo integration tests
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Distribution Precompile Suite")
+}
+
+func (s *PrecompileTestSuite) SetupTest() {
+ s.DoSetupTest()
+}
diff --git a/precompiles/distribution/tx.go b/precompiles/distribution/tx.go
new file mode 100644
index 00000000..d220c50c
--- /dev/null
+++ b/precompiles/distribution/tx.go
@@ -0,0 +1,262 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package distribution
+
+import (
+ "fmt"
+
+ "github.com/evmos/evmos/v19/utils"
+
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // SetWithdrawAddressMethod defines the ABI method name for the distribution
+ // SetWithdrawAddress transaction.
+ SetWithdrawAddressMethod = "setWithdrawAddress"
+ // WithdrawDelegatorRewardsMethod defines the ABI method name for the distribution
+ // WithdrawDelegatorRewards transaction.
+ WithdrawDelegatorRewardsMethod = "withdrawDelegatorRewards"
+ // WithdrawValidatorCommissionMethod defines the ABI method name for the distribution
+ // WithdrawValidatorCommission transaction.
+ WithdrawValidatorCommissionMethod = "withdrawValidatorCommission"
+ // FundCommunityPoolMethod defines the ABI method name for the fundCommunityPool transaction
+ FundCommunityPoolMethod = "fundCommunityPool"
+ // ClaimRewardsMethod defines the ABI method name for the custom ClaimRewards transaction
+ ClaimRewardsMethod = "claimRewards"
+)
+
+// ClaimRewards claims the rewards accumulated by a delegator from multiple or all validators.
+func (p *Precompile) ClaimRewards(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ delegatorAddr, maxRetrieve, err := parseClaimRewardsArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ maxVals := p.stakingKeeper.MaxValidators(ctx)
+ if maxRetrieve > maxVals {
+ return nil, fmt.Errorf("maxRetrieve (%d) parameter exceeds the maximum number of validators (%d)", maxRetrieve, maxVals)
+ }
+
+ // If the contract is the delegator, we don't need an origin check
+ // Otherwise check if the origin matches the delegator address
+ isContractDelegator := contract.CallerAddress == delegatorAddr && origin != delegatorAddr
+ if !isContractDelegator && origin != delegatorAddr {
+ return nil, fmt.Errorf(cmn.ErrDelegatorDifferentOrigin, origin.String(), delegatorAddr.String())
+ }
+
+ validators := p.stakingKeeper.GetDelegatorValidators(ctx, delegatorAddr.Bytes(), maxRetrieve)
+ totalCoins := sdk.Coins{}
+ for _, validator := range validators {
+ // Convert the validator operator address into an ValAddress
+ valAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress)
+ if err != nil {
+ return nil, err
+ }
+
+ // Withdraw the rewards for each validator address
+ coins, err := p.distributionKeeper.WithdrawDelegationRewards(ctx, delegatorAddr.Bytes(), valAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ totalCoins = totalCoins.Add(coins...)
+ }
+
+ // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB.
+ // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state.
+ // this happens when the precompile is called from a smart contract
+ if contract.CallerAddress != origin {
+ // rewards go to the withdrawer address
+ withdrawerHexAddr := p.getWithdrawerHexAddr(ctx, delegatorAddr)
+ p.SetBalanceChangeEntries(cmn.NewBalanceChangeEntry(withdrawerHexAddr, totalCoins.AmountOf(utils.BaseDenom).BigInt(), cmn.Add))
+ }
+
+ if err := p.EmitClaimRewardsEvent(ctx, stateDB, delegatorAddr, totalCoins); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// SetWithdrawAddress sets the withdrawal address for a delegator (or validator self-delegation).
+func (p Precompile) SetWithdrawAddress(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, delegatorHexAddr, err := NewMsgSetWithdrawAddress(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // If the contract is the delegator, we don't need an origin check
+ // Otherwise check if the origin matches the delegator address
+ isContractDelegator := contract.CallerAddress == delegatorHexAddr && origin != delegatorHexAddr
+ if !isContractDelegator && origin != delegatorHexAddr {
+ return nil, fmt.Errorf(cmn.ErrDelegatorDifferentOrigin, origin.String(), delegatorHexAddr.String())
+ }
+
+ msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper)
+ if _, err = msgSrv.SetWithdrawAddress(sdk.WrapSDKContext(ctx), msg); err != nil {
+ return nil, err
+ }
+
+ if err = p.EmitSetWithdrawAddressEvent(ctx, stateDB, delegatorHexAddr, msg.WithdrawAddress); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// WithdrawDelegatorRewards withdraws the rewards of a delegator from a single validator.
+func (p *Precompile) WithdrawDelegatorRewards(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, delegatorHexAddr, err := NewMsgWithdrawDelegatorReward(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // If the contract is the delegator, we don't need an origin check
+ // Otherwise check if the origin matches the delegator address
+ isContractDelegator := contract.CallerAddress == delegatorHexAddr && origin != delegatorHexAddr
+ if !isContractDelegator && origin != delegatorHexAddr {
+ return nil, fmt.Errorf(cmn.ErrDelegatorDifferentOrigin, origin.String(), delegatorHexAddr.String())
+ }
+
+ msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper)
+ res, err := msgSrv.WithdrawDelegatorReward(sdk.WrapSDKContext(ctx), msg)
+ if err != nil {
+ return nil, err
+ }
+
+ // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB
+ // when calling the precompile from a smart contract
+ // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state.
+ if contract.CallerAddress != origin {
+ // rewards go to the withdrawer address
+ withdrawerHexAddr := p.getWithdrawerHexAddr(ctx, delegatorHexAddr)
+ p.SetBalanceChangeEntries(cmn.NewBalanceChangeEntry(withdrawerHexAddr, res.Amount[0].Amount.BigInt(), cmn.Add))
+ }
+
+ if err = p.EmitWithdrawDelegatorRewardsEvent(ctx, stateDB, delegatorHexAddr, msg.ValidatorAddress, res.Amount); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(cmn.NewCoinsResponse(res.Amount))
+}
+
+// WithdrawValidatorCommission withdraws the rewards of a validator.
+func (p *Precompile) WithdrawValidatorCommission(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, validatorHexAddr, err := NewMsgWithdrawValidatorCommission(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // If the contract is the validator, we don't need an origin check
+ // Otherwise check if the origin matches the validator address
+ isContractValidator := contract.CallerAddress == validatorHexAddr && origin != validatorHexAddr
+ if !isContractValidator && origin != validatorHexAddr {
+ return nil, fmt.Errorf(cmn.ErrDelegatorDifferentOrigin, origin.String(), validatorHexAddr.String())
+ }
+
+ msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper)
+ res, err := msgSrv.WithdrawValidatorCommission(sdk.WrapSDKContext(ctx), msg)
+ if err != nil {
+ return nil, err
+ }
+
+ // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB
+ // when calling the precompile from a smart contract
+ // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state.
+ if contract.CallerAddress != origin {
+ // commissions go to the withdrawer address
+ withdrawerHexAddr := p.getWithdrawerHexAddr(ctx, validatorHexAddr)
+ p.SetBalanceChangeEntries(cmn.NewBalanceChangeEntry(withdrawerHexAddr, res.Amount[0].Amount.BigInt(), cmn.Add))
+ }
+
+ if err = p.EmitWithdrawValidatorCommissionEvent(ctx, stateDB, msg.ValidatorAddress, res.Amount); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(cmn.NewCoinsResponse(res.Amount))
+}
+
+// FundCommunityPool directly fund the community pool
+func (p *Precompile) FundCommunityPool(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, depositorHexAddr, err := NewMsgFundCommunityPool(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // If the contract is the depositor, we don't need an origin check
+ // Otherwise check if the origin matches the depositor address
+ isContractDepositor := contract.CallerAddress == depositorHexAddr && origin != depositorHexAddr
+ if !isContractDepositor && origin != depositorHexAddr {
+ return nil, fmt.Errorf(cmn.ErrSpenderDifferentOrigin, origin.String(), depositorHexAddr.String())
+ }
+
+ msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper)
+ _, err = msgSrv.FundCommunityPool(sdk.WrapSDKContext(ctx), msg)
+ if err != nil {
+ return nil, err
+ }
+
+ // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB
+ // when calling the precompile from a smart contract
+ // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state.
+ if contract.CallerAddress != origin {
+ p.SetBalanceChangeEntries(cmn.NewBalanceChangeEntry(depositorHexAddr, msg.Amount.AmountOf(utils.BaseDenom).BigInt(), cmn.Sub))
+ }
+
+ if err = p.EmitFundCommunityPoolEvent(ctx, stateDB, depositorHexAddr, msg.Amount); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// getWithdrawerHexAddr is a helper function to get the hex address
+// of the withdrawer for the specified account address
+func (p Precompile) getWithdrawerHexAddr(ctx sdk.Context, delegatorAddr common.Address) common.Address {
+ withdrawerAccAddr := p.distributionKeeper.GetDelegatorWithdrawAddr(ctx, delegatorAddr.Bytes())
+ return common.BytesToAddress(withdrawerAccAddr)
+}
diff --git a/precompiles/distribution/tx_test.go b/precompiles/distribution/tx_test.go
new file mode 100644
index 00000000..f6e1afc7
--- /dev/null
+++ b/precompiles/distribution/tx_test.go
@@ -0,0 +1,525 @@
+package distribution_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/utils"
+)
+
+func (s *PrecompileTestSuite) TestSetWithdrawAddress() {
+ method := s.precompile.Methods[distribution.SetWithdrawAddressMethod]
+ newWithdrawerAddr := utiltx.GenerateAddress()
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func()
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func() {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func() []interface{} {
+ return []interface{}{
+ "",
+ s.address.String(),
+ }
+ },
+ func() {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, ""),
+ },
+ {
+ "fail - invalid withdrawer address",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ nil,
+ }
+ },
+ func() {},
+ 200000,
+ true,
+ "invalid withdraw address: empty address string is not allowed: invalid address",
+ },
+ {
+ "success - using the same address withdrawer address",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ s.address.String(),
+ }
+ },
+ func() {
+ withdrawerAddr := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ s.Require().Equal(withdrawerAddr.Bytes(), s.address.Bytes())
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - using a different withdrawer address",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ newWithdrawerAddr.String(),
+ }
+ },
+ func() {
+ withdrawerAddr := s.app.DistrKeeper.GetDelegatorWithdrawAddr(s.ctx, s.address.Bytes())
+ s.Require().Equal(withdrawerAddr.Bytes(), newWithdrawerAddr.Bytes())
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ _, err := s.precompile.SetWithdrawAddress(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestWithdrawDelegatorRewards() {
+ method := s.precompile.Methods[distribution.WithdrawDelegatorRewardsMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func(data []byte)
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ "",
+ operatorAddress,
+ }
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, ""),
+ },
+ {
+ "fail - invalid validator address",
+ func(string) []interface{} {
+ return []interface{}{
+ s.address,
+ nil,
+ }
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ "invalid validator address",
+ },
+ {
+ "success - withdraw rewards from a single validator without commission",
+ func(operatorAddress string) []interface{} {
+ valAddr, err := sdk.ValAddressFromBech32(operatorAddress)
+ s.Require().NoError(err)
+ val, _ := s.app.StakingKeeper.GetValidator(s.ctx, valAddr)
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18)))
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ }
+ },
+ func(data []byte) {
+ var coins []cmn.Coin
+ err := s.precompile.UnpackIntoInterface(&coins, distribution.WithdrawDelegatorRewardsMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(coins[0].Denom, utils.BaseDenom)
+ s.Require().Equal(coins[0].Amount, big.NewInt(1000000000000000000))
+ // Check bank balance after the withdrawal of rewards
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(6000000000000000000))
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ // sanity check to make sure the starting balance is always 5 EVMOS
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(5000000000000000000))
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ bz, err := s.precompile.WithdrawDelegatorRewards(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestWithdrawValidatorCommission() {
+ method := s.precompile.Methods[distribution.WithdrawDelegatorRewardsMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func(data []byte)
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 0),
+ },
+ {
+ "fail - invalid validator address",
+ func(string) []interface{} {
+ return []interface{}{
+ nil,
+ }
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ "invalid validator address",
+ },
+ {
+ "success - withdraw all commission from a single validator",
+ func(operatorAddress string) []interface{} {
+ valAddr, err := sdk.ValAddressFromBech32(operatorAddress)
+ s.Require().NoError(err)
+ valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(utils.BaseDenom, math.LegacyNewDecWithPrec(1000000000000000000, 1))}
+ // set outstanding rewards
+ s.app.DistrKeeper.SetValidatorOutstandingRewards(s.ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})
+ // set commission
+ s.app.DistrKeeper.SetValidatorAccumulatedCommission(s.ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})
+ return []interface{}{
+ operatorAddress,
+ }
+ },
+ func(data []byte) {
+ var coins []cmn.Coin
+ err := s.precompile.UnpackIntoInterface(&coins, distribution.WithdrawValidatorCommissionMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(coins[0].Denom, utils.BaseDenom)
+ s.Require().Equal(coins[0].Amount, big.NewInt(100000000000000000))
+ // Check bank balance after the withdrawal of commission
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.validators[0].GetOperator().Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(100000000000000000))
+ s.Require().Equal(balance.Denom, utils.BaseDenom)
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ // Sanity check to make sure the starting balance is always 0
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.validators[0].GetOperator().Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(0))
+ s.Require().Equal(balance.Denom, utils.BaseDenom)
+
+ validatorAddress := common.BytesToAddress(s.validators[0].GetOperator().Bytes())
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, validatorAddress, s.precompile, tc.gas)
+
+ bz, err := s.precompile.WithdrawValidatorCommission(s.ctx, validatorAddress, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestClaimRewards() {
+ method := s.precompile.Methods[distribution.ClaimRewardsMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte)
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func() []interface{} {
+ return []interface{}{
+ nil,
+ 10,
+ }
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ "invalid delegator address",
+ },
+ {
+ "fail - invalid type for maxRetrieve: expected uint32",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(100000000000000000),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ "invalid type for maxRetrieve: expected uint32",
+ },
+ {
+ "pass - withdraw from validators with maxRetrieve higher than number of validators",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ uint32(10),
+ }
+ },
+ func([]byte) {
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(7e18))
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "fail - too many retrieved results",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ uint32(32_000_000),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ "maxRetrieve (32000000) parameter exceeds the maximum number of validators (100)",
+ },
+ {
+ "success - withdraw from all validators - 2",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ uint32(2),
+ }
+ },
+ func([]byte) {
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(7e18))
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - withdraw from only 1 validator",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ uint32(1),
+ }
+ },
+ func([]byte) {
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(6e18))
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ // Sanity check to make sure the starting balance is always 5 EVMOS
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(5e18))
+
+ // Distribute rewards to the 2 validators, 1 EVMOS each
+ for _, val := range s.validators {
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e18)))
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))
+ }
+
+ bz, err := s.precompile.ClaimRewards(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestFundCommunityPool() {
+ method := s.precompile.Methods[distribution.FundCommunityPoolMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte)
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid depositor address",
+ func() []interface{} {
+ return []interface{}{
+ nil,
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ true,
+ "invalid hex address address",
+ },
+ {
+ "success - fund the community pool 1 EVMOS",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte) {
+ coins := s.app.DistrKeeper.GetFeePoolCommunityCoins(s.ctx)
+ expectedAmount := new(big.Int).Mul(big.NewInt(1e18), new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(sdk.Precision)), nil))
+ s.Require().Equal(expectedAmount, coins.AmountOf(utils.BaseDenom).BigInt())
+ userBalance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(big.NewInt(4e18), userBalance.Amount.BigInt())
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ // Sanity check to make sure the starting balance is always 5 EVMOS
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount.BigInt(), big.NewInt(5e18))
+
+ bz, err := s.precompile.FundCommunityPool(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
diff --git a/precompiles/distribution/types.go b/precompiles/distribution/types.go
new file mode 100644
index 00000000..6e8fd16f
--- /dev/null
+++ b/precompiles/distribution/types.go
@@ -0,0 +1,427 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package distribution
+
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/evmos/evmos/v19/utils"
+
+ "cosmossdk.io/math"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/cmd/config"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+// EventSetWithdrawAddress defines the event data for the SetWithdrawAddress transaction.
+type EventSetWithdrawAddress struct {
+ Caller common.Address
+ WithdrawerAddress string
+}
+
+// EventWithdrawDelegatorRewards defines the event data for the WithdrawDelegatorRewards transaction.
+type EventWithdrawDelegatorRewards struct {
+ DelegatorAddress common.Address
+ ValidatorAddress common.Address
+ Amount *big.Int
+}
+
+// EventWithdrawValidatorRewards defines the event data for the WithdrawValidatorRewards transaction.
+type EventWithdrawValidatorRewards struct {
+ ValidatorAddress common.Hash
+ Commission *big.Int
+}
+
+// EventClaimRewards defines the event data for the ClaimRewards transaction.
+type EventClaimRewards struct {
+ DelegatorAddress common.Address
+ Amount *big.Int
+}
+
+// EventFundCommunityPool defines the event data for the FundCommunityPool transaction.
+type EventFundCommunityPool struct {
+ Depositor common.Address
+ Amount *big.Int
+}
+
+// parseClaimRewardsArgs parses the arguments for the ClaimRewards method.
+func parseClaimRewardsArgs(args []interface{}) (common.Address, uint32, error) {
+ if len(args) != 2 {
+ return common.Address{}, 0, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ delegatorAddress, ok := args[0].(common.Address)
+ if !ok || delegatorAddress == (common.Address{}) {
+ return common.Address{}, 0, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ maxRetrieve, ok := args[1].(uint32)
+ if !ok {
+ return common.Address{}, 0, fmt.Errorf(cmn.ErrInvalidType, "maxRetrieve", uint32(0), args[1])
+ }
+
+ return delegatorAddress, maxRetrieve, nil
+}
+
+// NewMsgSetWithdrawAddress creates a new MsgSetWithdrawAddress instance.
+func NewMsgSetWithdrawAddress(args []interface{}) (*distributiontypes.MsgSetWithdrawAddress, common.Address, error) {
+ if len(args) != 2 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ delegatorAddress, ok := args[0].(common.Address)
+ if !ok || delegatorAddress == (common.Address{}) {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ withdrawerAddress, _ := args[1].(string)
+
+ // If the withdrawer address is a hex address, convert it to a bech32 address.
+ if common.IsHexAddress(withdrawerAddress) {
+ var err error
+ withdrawerAddress, err = sdk.Bech32ifyAddressBytes(config.Bech32Prefix, common.HexToAddress(withdrawerAddress).Bytes())
+ if err != nil {
+ return nil, common.Address{}, err
+ }
+ }
+
+ msg := &distributiontypes.MsgSetWithdrawAddress{
+ DelegatorAddress: sdk.AccAddress(delegatorAddress.Bytes()).String(),
+ WithdrawAddress: withdrawerAddress,
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, delegatorAddress, nil
+}
+
+// NewMsgWithdrawDelegatorReward creates a new MsgWithdrawDelegatorReward instance.
+func NewMsgWithdrawDelegatorReward(args []interface{}) (*distributiontypes.MsgWithdrawDelegatorReward, common.Address, error) {
+ if len(args) != 2 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ delegatorAddress, ok := args[0].(common.Address)
+ if !ok || delegatorAddress == (common.Address{}) {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorAddress, _ := args[1].(string)
+
+ msg := &distributiontypes.MsgWithdrawDelegatorReward{
+ DelegatorAddress: sdk.AccAddress(delegatorAddress.Bytes()).String(),
+ ValidatorAddress: validatorAddress,
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, delegatorAddress, nil
+}
+
+// NewMsgWithdrawValidatorCommission creates a new MsgWithdrawValidatorCommission message.
+func NewMsgWithdrawValidatorCommission(args []interface{}) (*distributiontypes.MsgWithdrawValidatorCommission, common.Address, error) {
+ if len(args) != 1 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ validatorAddress, _ := args[0].(string)
+
+ msg := &distributiontypes.MsgWithdrawValidatorCommission{
+ ValidatorAddress: validatorAddress,
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ validatorHexAddr, err := cmn.HexAddressFromBech32String(msg.ValidatorAddress)
+ if err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, validatorHexAddr, nil
+}
+
+// NewMsgFundCommunityPool creates a new NewMsgFundCommunityPool message.
+func NewMsgFundCommunityPool(args []interface{}) (*distributiontypes.MsgFundCommunityPool, common.Address, error) {
+ if len(args) != 2 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ depositorAddress, ok := args[0].(common.Address)
+ if !ok || depositorAddress == (common.Address{}) {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidHexAddress, args[0])
+ }
+
+ amount, ok := args[1].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidAmount, args[1])
+ }
+
+ msg := &distributiontypes.MsgFundCommunityPool{
+ Depositor: sdk.AccAddress(depositorAddress.Bytes()).String(),
+ Amount: sdk.Coins{sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewIntFromBigInt(amount)}},
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, depositorAddress, nil
+}
+
+// NewValidatorDistributionInfoRequest creates a new QueryValidatorDistributionInfoRequest instance and does sanity
+// checks on the provided arguments.
+func NewValidatorDistributionInfoRequest(args []interface{}) (*distributiontypes.QueryValidatorDistributionInfoRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ validatorAddress, _ := args[0].(string)
+
+ return &distributiontypes.QueryValidatorDistributionInfoRequest{
+ ValidatorAddress: validatorAddress,
+ }, nil
+}
+
+// NewValidatorOutstandingRewardsRequest creates a new QueryValidatorOutstandingRewardsRequest instance and does sanity
+// checks on the provided arguments.
+func NewValidatorOutstandingRewardsRequest(args []interface{}) (*distributiontypes.QueryValidatorOutstandingRewardsRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ validatorAddress, _ := args[0].(string)
+
+ return &distributiontypes.QueryValidatorOutstandingRewardsRequest{
+ ValidatorAddress: validatorAddress,
+ }, nil
+}
+
+// NewValidatorCommissionRequest creates a new QueryValidatorCommissionRequest instance and does sanity
+// checks on the provided arguments.
+func NewValidatorCommissionRequest(args []interface{}) (*distributiontypes.QueryValidatorCommissionRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ validatorAddress, _ := args[0].(string)
+
+ return &distributiontypes.QueryValidatorCommissionRequest{
+ ValidatorAddress: validatorAddress,
+ }, nil
+}
+
+// NewValidatorSlashesRequest creates a new QueryValidatorSlashesRequest instance and does sanity
+// checks on the provided arguments.
+func NewValidatorSlashesRequest(method *abi.Method, args []interface{}) (*distributiontypes.QueryValidatorSlashesRequest, error) {
+ if len(args) != 4 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 4, len(args))
+ }
+
+ if _, ok := args[1].(uint64); !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "startingHeight", uint64(0), args[1])
+ }
+ if _, ok := args[2].(uint64); !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "endingHeight", uint64(0), args[2])
+ }
+
+ var input ValidatorSlashesInput
+ if err := method.Inputs.Copy(&input, args); err != nil {
+ return nil, fmt.Errorf("error while unpacking args to ValidatorSlashesInput struct: %s", err)
+ }
+
+ return &distributiontypes.QueryValidatorSlashesRequest{
+ ValidatorAddress: input.ValidatorAddress,
+ StartingHeight: input.StartingHeight,
+ EndingHeight: input.EndingHeight,
+ Pagination: &input.PageRequest,
+ }, nil
+}
+
+// NewDelegationRewardsRequest creates a new QueryDelegationRewardsRequest instance and does sanity
+// checks on the provided arguments.
+func NewDelegationRewardsRequest(args []interface{}) (*distributiontypes.QueryDelegationRewardsRequest, error) {
+ if len(args) != 2 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ delegatorAddress, ok := args[0].(common.Address)
+ if !ok || delegatorAddress == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorAddress, _ := args[1].(string)
+
+ return &distributiontypes.QueryDelegationRewardsRequest{
+ DelegatorAddress: sdk.AccAddress(delegatorAddress.Bytes()).String(),
+ ValidatorAddress: validatorAddress,
+ }, nil
+}
+
+// NewDelegationTotalRewardsRequest creates a new QueryDelegationTotalRewardsRequest instance and does sanity
+// checks on the provided arguments.
+func NewDelegationTotalRewardsRequest(args []interface{}) (*distributiontypes.QueryDelegationTotalRewardsRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ delegatorAddress, ok := args[0].(common.Address)
+ if !ok || delegatorAddress == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ return &distributiontypes.QueryDelegationTotalRewardsRequest{
+ DelegatorAddress: sdk.AccAddress(delegatorAddress.Bytes()).String(),
+ }, nil
+}
+
+// NewDelegatorValidatorsRequest creates a new QueryDelegatorValidatorsRequest instance and does sanity
+// checks on the provided arguments.
+func NewDelegatorValidatorsRequest(args []interface{}) (*distributiontypes.QueryDelegatorValidatorsRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ delegatorAddress, ok := args[0].(common.Address)
+ if !ok || delegatorAddress == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ return &distributiontypes.QueryDelegatorValidatorsRequest{
+ DelegatorAddress: sdk.AccAddress(delegatorAddress.Bytes()).String(),
+ }, nil
+}
+
+// NewDelegatorWithdrawAddressRequest creates a new QueryDelegatorWithdrawAddressRequest instance and does sanity
+// checks on the provided arguments.
+func NewDelegatorWithdrawAddressRequest(args []interface{}) (*distributiontypes.QueryDelegatorWithdrawAddressRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ delegatorAddress, ok := args[0].(common.Address)
+ if !ok || delegatorAddress == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ return &distributiontypes.QueryDelegatorWithdrawAddressRequest{
+ DelegatorAddress: sdk.AccAddress(delegatorAddress.Bytes()).String(),
+ }, nil
+}
+
+// ValidatorDistributionInfo is a struct to represent the key information from
+// a ValidatorDistributionInfoResponse.
+type ValidatorDistributionInfo struct {
+ OperatorAddress string `abi:"operatorAddress"`
+ SelfBondRewards []cmn.DecCoin `abi:"selfBondRewards"`
+ Commission []cmn.DecCoin `abi:"commission"`
+}
+
+// ValidatorDistributionInfoOutput is a wrapper for ValidatorDistributionInfo to return in the response.
+type ValidatorDistributionInfoOutput struct {
+ DistributionInfo ValidatorDistributionInfo `abi:"distributionInfo"`
+}
+
+// FromResponse converts a response to a ValidatorDistributionInfo.
+func (o *ValidatorDistributionInfoOutput) FromResponse(res *distributiontypes.QueryValidatorDistributionInfoResponse) ValidatorDistributionInfoOutput {
+ return ValidatorDistributionInfoOutput{
+ DistributionInfo: ValidatorDistributionInfo{
+ OperatorAddress: res.OperatorAddress,
+ SelfBondRewards: cmn.NewDecCoinsResponse(res.SelfBondRewards),
+ Commission: cmn.NewDecCoinsResponse(res.Commission),
+ },
+ }
+}
+
+// ValidatorSlashEvent is a struct to represent the key information from
+// a ValidatorSlashEvent response.
+type ValidatorSlashEvent struct {
+ ValidatorPeriod uint64 `abi:"validatorPeriod"`
+ Fraction cmn.Dec `abi:"fraction"`
+}
+
+// ValidatorSlashesInput is a struct to represent the key information
+// to perform a ValidatorSlashes query.
+type ValidatorSlashesInput struct {
+ ValidatorAddress string
+ StartingHeight uint64
+ EndingHeight uint64
+ PageRequest query.PageRequest
+}
+
+// ValidatorSlashesOutput is a struct to represent the key information from
+// a ValidatorSlashes response.
+type ValidatorSlashesOutput struct {
+ Slashes []ValidatorSlashEvent
+ PageResponse query.PageResponse
+}
+
+// FromResponse populates the ValidatorSlashesOutput from a QueryValidatorSlashesResponse.
+func (vs *ValidatorSlashesOutput) FromResponse(res *distributiontypes.QueryValidatorSlashesResponse) *ValidatorSlashesOutput {
+ vs.Slashes = make([]ValidatorSlashEvent, len(res.Slashes))
+ for i, s := range res.Slashes {
+ vs.Slashes[i] = ValidatorSlashEvent{
+ ValidatorPeriod: s.ValidatorPeriod,
+ Fraction: cmn.Dec{
+ Value: s.Fraction.BigInt(),
+ Precision: math.LegacyPrecision,
+ },
+ }
+ }
+
+ if res.Pagination != nil {
+ vs.PageResponse.Total = res.Pagination.Total
+ vs.PageResponse.NextKey = res.Pagination.NextKey
+ }
+
+ return vs
+}
+
+// Pack packs a given slice of abi arguments into a byte array.
+func (vs *ValidatorSlashesOutput) Pack(args abi.Arguments) ([]byte, error) {
+ return args.Pack(vs.Slashes, vs.PageResponse)
+}
+
+// DelegationDelegatorReward is a struct to represent the key information from
+// a query for the rewards of a delegation to a given validator.
+type DelegationDelegatorReward struct {
+ ValidatorAddress string
+ Reward []cmn.DecCoin
+}
+
+// DelegationTotalRewardsOutput is a struct to represent the key information from
+// a DelegationTotalRewards response.
+type DelegationTotalRewardsOutput struct {
+ Rewards []DelegationDelegatorReward
+ Total []cmn.DecCoin
+}
+
+// FromResponse populates the DelegationTotalRewardsOutput from a QueryDelegationTotalRewardsResponse.
+func (dtr *DelegationTotalRewardsOutput) FromResponse(res *distributiontypes.QueryDelegationTotalRewardsResponse) *DelegationTotalRewardsOutput {
+ dtr.Rewards = make([]DelegationDelegatorReward, len(res.Rewards))
+ for i, r := range res.Rewards {
+ dtr.Rewards[i] = DelegationDelegatorReward{
+ ValidatorAddress: r.ValidatorAddress,
+ Reward: cmn.NewDecCoinsResponse(r.Reward),
+ }
+ }
+ dtr.Total = cmn.NewDecCoinsResponse(res.Total)
+ return dtr
+}
+
+// Pack packs a given slice of abi arguments into a byte array.
+func (dtr *DelegationTotalRewardsOutput) Pack(args abi.Arguments) ([]byte, error) {
+ return args.Pack(dtr.Rewards, dtr.Total)
+}
diff --git a/precompiles/distribution/utils_test.go b/precompiles/distribution/utils_test.go
new file mode 100644
index 00000000..b1159781
--- /dev/null
+++ b/precompiles/distribution/utils_test.go
@@ -0,0 +1,271 @@
+package distribution_test
+
+import (
+ "encoding/json"
+ "time"
+
+ "cosmossdk.io/math"
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/cometbft/cometbft/crypto/tmhash"
+ tmtypes "github.com/cometbft/cometbft/types"
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
+ "github.com/cosmos/cosmos-sdk/testutil/mock"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ sdkstaking "github.com/cosmos/cosmos-sdk/x/staking"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ evmosapp "github.com/evmos/evmos/v19/app"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ evmosutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ evmostypes "github.com/evmos/evmos/v19/types"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+)
+
+// SetupWithGenesisValSet initializes a new EvmosApp with a validator set and genesis accounts
+// that also act as delegators. For simplicity, each validator is bonded with a delegation
+// of one consensus engine unit (10^6) in the default token of the simapp from first genesis
+// account. A Nop logger is set in SimApp.
+func (s *PrecompileTestSuite) SetupWithGenesisValSet(valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) {
+ appI, genesisState := evmosapp.SetupTestingApp(cmn.DefaultChainID)()
+ app, ok := appI.(*evmosapp.Evmos)
+ s.Require().True(ok)
+
+ // set genesis accounts
+ authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
+ genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
+
+ validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
+ delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
+
+ bondAmt := sdk.TokensFromConsensusPower(1, evmostypes.PowerReduction)
+
+ for _, val := range valSet.Validators {
+ pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
+ s.Require().NoError(err)
+ pkAny, err := codectypes.NewAnyWithValue(pk)
+ s.Require().NoError(err)
+ validator := stakingtypes.Validator{
+ OperatorAddress: sdk.ValAddress(val.Address).String(),
+ ConsensusPubkey: pkAny,
+ Jailed: false,
+ Status: stakingtypes.Bonded,
+ Tokens: bondAmt,
+ DelegatorShares: math.LegacyOneDec(),
+ Description: stakingtypes.Description{},
+ UnbondingHeight: int64(0),
+ UnbondingTime: time.Unix(0, 0).UTC(),
+ Commission: stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()),
+ MinSelfDelegation: math.ZeroInt(),
+ }
+ validators = append(validators, validator)
+ delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), math.LegacyOneDec()))
+ }
+ s.validators = validators
+
+ // set validators and delegations
+ stakingParams := stakingtypes.DefaultParams()
+ // set bond demon to be aevmos
+ stakingParams.BondDenom = utils.BaseDenom
+ stakingGenesis := stakingtypes.NewGenesisState(stakingParams, validators, delegations)
+ genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
+
+ totalBondAmt := bondAmt.Add(bondAmt)
+ totalSupply := sdk.NewCoins()
+ for _, b := range balances {
+ // add genesis acc tokens and delegated tokens to total supply
+ totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(utils.BaseDenom, totalBondAmt))...)
+ }
+
+ // add bonded amount to bonded pool module account
+ balances = append(balances, banktypes.Balance{
+ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
+ Coins: sdk.Coins{sdk.NewCoin(utils.BaseDenom, totalBondAmt)},
+ })
+
+ // update total supply
+ bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{})
+ genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
+
+ stateBytes, err := json.MarshalIndent(genesisState, "", " ")
+ s.Require().NoError(err)
+
+ // init chain will set the validator set and initialize the genesis accounts
+ app.InitChain(
+ abci.RequestInitChain{
+ ChainId: cmn.DefaultChainID,
+ Validators: []abci.ValidatorUpdate{},
+ ConsensusParams: evmosapp.DefaultConsensusParams,
+ AppStateBytes: stateBytes,
+ },
+ )
+ app.Commit()
+
+ // instantiate new header
+ header := evmosutil.NewHeader(
+ 2,
+ time.Now().UTC(),
+ cmn.DefaultChainID,
+ sdk.ConsAddress(validators[0].GetOperator()),
+ tmhash.Sum([]byte("app")),
+ tmhash.Sum([]byte("validators")),
+ )
+
+ app.BeginBlock(abci.RequestBeginBlock{
+ Header: header,
+ })
+
+ // create Context
+ s.ctx = app.BaseApp.NewContext(false, header)
+ s.app = app
+}
+
+func (s *PrecompileTestSuite) DoSetupTest() {
+ // generate validator private/public key
+ privVal := mock.NewPV()
+ pubKey, err := privVal.GetPubKey()
+ s.Require().NoError(err)
+
+ privVal2 := mock.NewPV()
+ pubKey2, err := privVal2.GetPubKey()
+ s.Require().NoError(err)
+
+ // create validator set with two validators
+ validator := tmtypes.NewValidator(pubKey, 1)
+ validator2 := tmtypes.NewValidator(pubKey2, 2)
+ s.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator, validator2})
+ signers := make(map[string]tmtypes.PrivValidator)
+ signers[pubKey.Address().String()] = privVal
+ signers[pubKey2.Address().String()] = privVal2
+
+ // generate genesis account
+ addr, priv := evmosutiltx.NewAddrKey()
+ s.privKey = priv
+ s.address = addr
+ s.signer = evmosutiltx.NewSigner(priv)
+
+ baseAcc := authtypes.NewBaseAccount(priv.PubKey().Address().Bytes(), priv.PubKey(), 0, 0)
+
+ amount := sdk.TokensFromConsensusPower(5, evmostypes.PowerReduction)
+
+ balance := banktypes.Balance{
+ Address: baseAcc.GetAddress().String(),
+ Coins: sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, amount)),
+ }
+
+ s.SetupWithGenesisValSet(s.valSet, []authtypes.GenesisAccount{baseAcc}, balance)
+
+ // Create StateDB
+ s.stateDB = statedb.New(s.ctx, s.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.ctx.HeaderHash().Bytes())))
+
+ // bond denom
+ stakingParams := s.app.StakingKeeper.GetParams(s.ctx)
+ stakingParams.BondDenom = utils.BaseDenom
+ s.bondDenom = stakingParams.BondDenom
+ err = s.app.StakingKeeper.SetParams(s.ctx, stakingParams)
+ s.Require().NoError(err)
+
+ s.ethSigner = ethtypes.LatestSignerForChainID(s.app.EvmKeeper.ChainID())
+
+ precompile, err := distribution.NewPrecompile(s.app.DistrKeeper, s.app.StakingKeeper, s.app.AuthzKeeper)
+ s.Require().NoError(err)
+ s.precompile = precompile
+
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(5_000_000_000_000_000_000)))
+ inflCoins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(2_000_000_000_000_000_000)))
+ distrCoins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(3_000_000_000_000_000_000)))
+ err = s.app.BankKeeper.MintCoins(s.ctx, inflationtypes.ModuleName, coins)
+ s.Require().NoError(err)
+ err = s.app.BankKeeper.SendCoinsFromModuleToModule(s.ctx, inflationtypes.ModuleName, authtypes.FeeCollectorName, inflCoins)
+ s.Require().NoError(err)
+ err = s.app.BankKeeper.SendCoinsFromModuleToModule(s.ctx, inflationtypes.ModuleName, distrtypes.ModuleName, distrCoins)
+ s.Require().NoError(err)
+
+ queryHelperEvm := baseapp.NewQueryServerTestHelper(s.ctx, s.app.InterfaceRegistry())
+ evmtypes.RegisterQueryServer(queryHelperEvm, s.app.EvmKeeper)
+ s.queryClientEVM = evmtypes.NewQueryClient(queryHelperEvm)
+}
+
+// DeployContract deploys a contract that calls the distribution precompile's methods for testing purposes.
+func (s *PrecompileTestSuite) DeployContract(contract evmtypes.CompiledContract) (addr common.Address, err error) {
+ addr, err = evmosutil.DeployContract(
+ s.ctx,
+ s.app,
+ s.privKey,
+ s.queryClientEVM,
+ contract,
+ )
+ return
+}
+
+type stakingRewards struct {
+ Delegator sdk.AccAddress
+ Validator stakingtypes.Validator
+ RewardAmt math.Int
+}
+
+// prepareStakingRewards prepares the test suite for testing delegation rewards.
+//
+// Specified rewards amount are allocated to the specified validator using the distribution keeper,
+// such that the given amount of tokens is outstanding as a staking reward for the account.
+//
+// The setup is done in the following way:
+// - Fund the account with the given address with the given rewards amount.
+// - Delegate the rewards amount to the validator specified
+// - Allocate rewards to the validator.
+func (s *PrecompileTestSuite) prepareStakingRewards(stkRs ...stakingRewards) {
+ for _, r := range stkRs {
+ // fund account to make delegation
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, r.Delegator, r.RewardAmt.Int64())
+ s.Require().NoError(err)
+ // set distribution module account balance which pays out the rewards
+ distrAcc := s.app.DistrKeeper.GetDistributionAccount(s.ctx)
+ err = evmosutil.FundModuleAccount(s.ctx, s.app.BankKeeper, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(s.bondDenom, r.RewardAmt)))
+ s.Require().NoError(err)
+
+ // make a delegation
+ _, err = s.app.StakingKeeper.Delegate(s.ctx, r.Delegator, r.RewardAmt, stakingtypes.Unspecified, r.Validator, true)
+ s.Require().NoError(err)
+
+ // end block to bond validator and increase block height
+ sdkstaking.EndBlocker(s.ctx, s.app.StakingKeeper.Keeper)
+ // allocate rewards to validator (of these 50% will be paid out to the delegator)
+ allocatedRewards := sdk.NewDecCoins(sdk.NewDecCoin(s.bondDenom, r.RewardAmt.Mul(math.NewInt(2))))
+ s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, r.Validator, allocatedRewards)
+ }
+ s.NextBlock()
+}
+
+// NextBlock commits the current block and sets up the next block.
+func (s *PrecompileTestSuite) NextBlock() {
+ var err error
+ s.ctx, err = evmosutil.CommitAndCreateNewCtx(s.ctx, s.app, time.Second, s.valSet)
+ s.Require().NoError(err)
+}
+
+// setupValidatorSlashes sets slashes events for the provided validator
+// returns the slash event set
+func (s *PrecompileTestSuite) setupValidatorSlashes(valAddr sdk.ValAddress, slashesCount uint64) distrtypes.ValidatorSlashEvent {
+ const (
+ initialHeight uint64 = 2
+ initialPeriod uint64 = 1
+ )
+
+ slashEvent := distrtypes.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)}
+
+ for i := uint64(0); i < slashesCount; i++ {
+ s.app.DistrKeeper.SetValidatorSlashEvent(s.ctx, valAddr, initialHeight+i, initialPeriod+i, slashEvent)
+ }
+
+ return slashEvent
+}
diff --git a/precompiles/erc20/IERC20.sol b/precompiles/erc20/IERC20.sol
new file mode 100644
index 00000000..66c4e4d8
--- /dev/null
+++ b/precompiles/erc20/IERC20.sol
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
+
+pragma solidity ^0.8.0;
+
+/**
+ * @dev Interface of the ERC20 standard as defined in the EIP.
+ */
+interface IERC20 {
+ /**
+ * @dev Emitted when `value` tokens are moved from one account (`from`) to
+ * another (`to`).
+ *
+ * Note that `value` may be zero.
+ */
+ event Transfer(address indexed from, address indexed to, uint256 value);
+
+ /**
+ * @dev Emitted when the allowance of a `spender` for an `owner` is set by
+ * a call to {approve}. `value` is the new allowance.
+ */
+ event Approval(address indexed owner, address indexed spender, uint256 value);
+
+ /**
+ * @dev Returns the amount of tokens in existence.
+ */
+ function totalSupply() external view returns (uint256);
+
+ /**
+ * @dev Returns the amount of tokens owned by `account`.
+ */
+ function balanceOf(address account) external view returns (uint256);
+
+ /**
+ * @dev Moves `amount` tokens from the caller's account to `to`.
+ *
+ * Returns a boolean value indicating whether the operation succeeded.
+ *
+ * Emits a {Transfer} event.
+ */
+ function transfer(address to, uint256 amount) external returns (bool);
+
+ /**
+ * @dev Returns the remaining number of tokens that `spender` will be
+ * allowed to spend on behalf of `owner` through {transferFrom}. This is
+ * zero by default.
+ *
+ * This value changes when {approve} or {transferFrom} are called.
+ */
+ function allowance(address owner, address spender) external view returns (uint256);
+
+ /**
+ * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
+ *
+ * Returns a boolean value indicating whether the operation succeeded.
+ *
+ * IMPORTANT: Beware that changing an allowance with this method brings the risk
+ * that someone may use both the old and the new allowance by unfortunate
+ * transaction ordering. One possible solution to mitigate this race
+ * condition is to first reduce the spender's allowance to 0 and set the
+ * desired value afterwards:
+ * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+ *
+ * Emits an {Approval} event.
+ */
+ function approve(address spender, uint256 amount) external returns (bool);
+
+ /**
+ * @dev Moves `amount` tokens from `from` to `to` using the
+ * allowance mechanism. `amount` is then deducted from the caller's
+ * allowance.
+ *
+ * Returns a boolean value indicating whether the operation succeeded.
+ *
+ * Emits a {Transfer} event.
+ */
+ function transferFrom(address from, address to, uint256 amount) external returns (bool);
+}
diff --git a/precompiles/erc20/IERC20Metadata.sol b/precompiles/erc20/IERC20Metadata.sol
new file mode 100644
index 00000000..982bc39e
--- /dev/null
+++ b/precompiles/erc20/IERC20Metadata.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
+
+pragma solidity ^0.8.0;
+
+import "./IERC20.sol";
+
+/**
+ * @dev Interface for the optional metadata functions from the ERC20 standard.
+ *
+ * _Available since v4.1._
+ */
+interface IERC20Metadata is IERC20 {
+ /**
+ * @dev Returns the name of the token.
+ */
+ function name() external view returns (string memory);
+
+ /**
+ * @dev Returns the symbol of the token.
+ */
+ function symbol() external view returns (string memory);
+
+ /**
+ * @dev Returns the decimals places of the token.
+ */
+ function decimals() external view returns (uint8);
+}
diff --git a/precompiles/erc20/IERC20MetadataAllowance.sol b/precompiles/erc20/IERC20MetadataAllowance.sol
new file mode 100644
index 00000000..4eb31bf7
--- /dev/null
+++ b/precompiles/erc20/IERC20MetadataAllowance.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.18;
+
+import "./IERC20Metadata.sol";
+
+/**
+ * @author Evmos Team
+ * @title ERC20 Metadata Allowance Interface
+ * @dev Interface for the optional metadata and allowance functions from the ERC20 standard.
+ */
+interface IERC20MetadataAllowance is IERC20Metadata {
+ /** @dev Atomically increases the allowance granted to spender by the caller.
+ * This is an alternative to approve that can be used as a mitigation for problems described in
+ * IERC20.approve.
+ * @param spender The address which will spend the funds.
+ * @param addedValue The amount of tokens added to the spender allowance.
+ * @return approved Boolean value to indicate if the approval was successful.
+ */
+ function increaseAllowance(
+ address spender,
+ uint256 addedValue
+ ) external returns (bool approved);
+
+ /** @dev Atomically decreases the allowance granted to spender by the caller.
+ * This is an alternative to approve that can be used as a mitigation for problems described in
+ * IERC20.approve.
+ * @param spender The address which will spend the funds.
+ * @param subtractedValue The amount to be subtracted from the spender allowance.
+ * @return approved Boolean value to indicate if the approval was successful.
+ */
+ function decreaseAllowance(
+ address spender,
+ uint256 subtractedValue
+ ) external returns (bool approved);
+}
diff --git a/precompiles/erc20/abi.json b/precompiles/erc20/abi.json
new file mode 100644
index 00000000..46fbced2
--- /dev/null
+++ b/precompiles/erc20/abi.json
@@ -0,0 +1,281 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "IERC20MetadataAllowance",
+ "sourceName": "solidity/precompiles/erc20/IERC20MetadataAllowance.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "decimals",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "subtractedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "decreaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "addedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "increaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x",
+ "deployedBytecode": "0x",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/erc20/approve.go b/precompiles/erc20/approve.go
new file mode 100644
index 00000000..d74b2336
--- /dev/null
+++ b/precompiles/erc20/approve.go
@@ -0,0 +1,333 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "math/big"
+ "time"
+
+ sdkerrors "cosmossdk.io/errors"
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// Approve sets the given amount as the allowance of the spender address over
+// the caller’s tokens. It returns a boolean value indicating whether the
+// operation succeeded and emits the Approval event on success.
+//
+// The Approve method handles 4 cases:
+// 1. no authorization, amount negative -> return error
+// 2. no authorization, amount positive -> create a new authorization
+// 3. authorization exists, amount 0 or negative -> delete authorization
+// 4. authorization exists, amount positive -> update authorization
+// 5. no authorizaiton, amount 0 -> no-op but still emit Approval event
+func (p Precompile) Approve(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ spender, amount, err := ParseApproveArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ grantee := spender
+ granter := contract.CallerAddress
+
+ // NOTE: We do not support approvals if the grantee is the granter.
+ // This is different from the ERC20 standard but there is no reason to
+ // do so, since in that case the grantee can just transfer the tokens
+ // without authorization.
+ if bytes.Equal(grantee.Bytes(), granter.Bytes()) {
+ return nil, ErrSpenderIsOwner
+ }
+
+ // TODO: owner should be the owner of the contract
+ authorization, expiration, _ := auth.CheckAuthzExists(ctx, p.AuthzKeeper, grantee, granter, SendMsgURL) //#nosec:G703 -- we are handling the error case (authorization == nil) in the switch statement below
+
+ switch {
+ case authorization == nil && amount != nil && amount.Sign() < 0:
+ // case 1: no authorization, amount 0 or negative -> error
+ err = ErrNegativeAmount
+ case authorization == nil && amount != nil && amount.Sign() > 0:
+ // case 2: no authorization, amount positive -> create a new authorization
+ err = p.createAuthorization(ctx, grantee, granter, amount)
+ case authorization != nil && amount != nil && amount.Sign() <= 0:
+ // case 3: authorization exists, amount 0 or negative -> remove from spend limit and delete authorization if no spend limit left
+ err = p.removeSpendLimitOrDeleteAuthorization(ctx, grantee, granter, authorization, expiration)
+ case authorization != nil && amount != nil && amount.Sign() > 0:
+ // case 4: authorization exists, amount positive -> update authorization
+ sendAuthz, ok := authorization.(*banktypes.SendAuthorization)
+ if !ok {
+ return nil, authz.ErrUnknownAuthorizationType
+ }
+
+ err = p.updateAuthorization(ctx, grantee, granter, amount, sendAuthz, expiration)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: check owner?
+ if err := p.EmitApprovalEvent(ctx, stateDB, p.Address(), spender, amount); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// IncreaseAllowance increases the allowance of the spender address over
+// the caller’s tokens by the given added value. It returns a boolean value
+// indicating whether the operation succeeded and emits the Approval event on
+// success.
+//
+// The IncreaseAllowance method handles 3 cases:
+// 1. addedValue 0 or negative -> return error
+// 2. no authorization, addedValue positive -> create a new authorization
+// 3. authorization exists, addedValue positive -> update authorization
+func (p Precompile) IncreaseAllowance(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ spender, addedValue, err := ParseApproveArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ grantee := spender
+ granter := contract.CallerAddress
+
+ if bytes.Equal(grantee.Bytes(), granter.Bytes()) {
+ return nil, ErrSpenderIsOwner
+ }
+
+ // TODO: owner should be the owner of the contract
+ authorization, expiration, _ := auth.CheckAuthzExists(ctx, p.AuthzKeeper, grantee, granter, SendMsgURL) //#nosec:G703 -- we are handling the error case (authorization == nil) in the switch statement below
+
+ var amount *big.Int
+ switch {
+ case addedValue != nil && addedValue.Sign() <= 0:
+ // case 1: addedValue 0 or negative -> error
+ // TODO: (@fedekunze) check if this is correct by comparing behavior with
+ // regular ERC20
+ err = ErrIncreaseNonPositiveValue
+ case authorization == nil && addedValue != nil && addedValue.Sign() > 0:
+ // case 2: no authorization, amount positive -> create a new authorization
+ amount = addedValue
+ err = p.createAuthorization(ctx, grantee, granter, addedValue)
+ case authorization != nil && addedValue != nil && addedValue.Sign() > 0:
+ // case 3: authorization exists, amount positive -> update authorization
+ amount, err = p.increaseAllowance(ctx, grantee, granter, addedValue, authorization, expiration)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: check owner?
+ if err := p.EmitApprovalEvent(ctx, stateDB, p.Address(), spender, amount); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// DecreaseAllowance decreases the allowance of the spender address over
+// the caller’s tokens by the given subtracted value. It returns a boolean value
+// indicating whether the operation succeeded and emits the Approval event on
+// success.
+//
+// The DecreaseAllowance method handles 4 cases:
+// 1. subtractedValue 0 or negative -> return error
+// 2. no authorization -> return error
+// 3. authorization exists, subtractedValue positive and subtractedValue less than allowance -> update authorization
+// 4. authorization exists, subtractedValue positive and subtractedValue equal to allowance -> delete authorization
+// 5. authorization exists, subtractedValue positive but no allowance for given denomination -> return error
+// 6. authorization exists, subtractedValue positive and subtractedValue higher than allowance -> return error
+func (p Precompile) DecreaseAllowance(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ spender, subtractedValue, err := ParseApproveArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ grantee := spender
+ granter := contract.CallerAddress
+
+ if bytes.Equal(grantee.Bytes(), granter.Bytes()) {
+ return nil, ErrSpenderIsOwner
+ }
+ // TODO: owner should be the owner of the contract
+
+ authorization, expiration, allowance, err := GetAuthzExpirationAndAllowance(p.AuthzKeeper, ctx, grantee, granter, p.tokenPair.Denom)
+
+ // TODO: (@fedekunze) check if this is correct by comparing behavior with
+ // regular ERC-20
+ var amount *big.Int
+ switch {
+ case subtractedValue != nil && subtractedValue.Sign() <= 0:
+ // case 1. subtractedValue 0 or negative -> return error
+ err = ErrDecreaseNonPositiveValue
+ case err != nil:
+ // case 2. no authorization -> return error
+ err = sdkerrors.Wrap(err, fmt.Sprintf(ErrNoAllowanceForToken, p.tokenPair.Denom))
+ case subtractedValue != nil && subtractedValue.Cmp(allowance) < 0:
+ // case 3. subtractedValue positive and subtractedValue less than allowance -> update authorization
+ amount, err = p.decreaseAllowance(ctx, grantee, granter, subtractedValue, authorization, expiration)
+ case subtractedValue != nil && subtractedValue.Cmp(allowance) == 0:
+ // case 4. subtractedValue positive and subtractedValue equal to allowance -> remove spend limit for token and delete authorization if no other denoms are approved for
+ err = p.removeSpendLimitOrDeleteAuthorization(ctx, grantee, granter, authorization, expiration)
+ amount = common.Big0
+ case subtractedValue != nil && allowance.Sign() == 0:
+ // case 5. subtractedValue positive but no allowance for given denomination -> return error
+ err = fmt.Errorf(ErrNoAllowanceForToken, p.tokenPair.Denom)
+ case subtractedValue != nil && subtractedValue.Cmp(allowance) > 0:
+ // case 6. subtractedValue positive and subtractedValue higher than allowance -> return error
+ err = ConvertErrToERC20Error(fmt.Errorf(ErrSubtractMoreThanAllowance, p.tokenPair.Denom, subtractedValue, allowance))
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: check owner?
+ if err := p.EmitApprovalEvent(ctx, stateDB, p.Address(), spender, amount); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+func (p Precompile) createAuthorization(ctx sdk.Context, grantee, granter common.Address, amount *big.Int) error {
+ if amount.BitLen() > sdkmath.MaxBitLen {
+ return fmt.Errorf(ErrIntegerOverflow, amount)
+ }
+
+ coins := sdk.Coins{{Denom: p.tokenPair.Denom, Amount: sdkmath.NewIntFromBigInt(amount)}}
+ expiration := ctx.BlockTime().Add(p.ApprovalExpiration)
+
+ // NOTE: we leave the allowed arg empty as all recipients are allowed (per ERC20 standard)
+ authorization := banktypes.NewSendAuthorization(coins, []sdk.AccAddress{})
+ if err := authorization.ValidateBasic(); err != nil {
+ return err
+ }
+
+ return p.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), authorization, &expiration)
+}
+
+func (p Precompile) updateAuthorization(ctx sdk.Context, grantee, granter common.Address, amount *big.Int, authorization *banktypes.SendAuthorization, expiration *time.Time) error {
+ authorization.SpendLimit = updateOrAddCoin(authorization.SpendLimit, sdk.Coin{Denom: p.tokenPair.Denom, Amount: sdkmath.NewIntFromBigInt(amount)})
+ if err := authorization.ValidateBasic(); err != nil {
+ return err
+ }
+
+ return p.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), authorization, expiration)
+}
+
+// removeSpendLimitOrDeleteAuthorization removes the spend limit for the given
+// token and updates the grant or deletes the authorization if no spend limit in another
+// denomination is set.
+func (p Precompile) removeSpendLimitOrDeleteAuthorization(ctx sdk.Context, grantee, granter common.Address, authorization authz.Authorization, expiration *time.Time) error {
+ sendAuthz, ok := authorization.(*banktypes.SendAuthorization)
+ if !ok {
+ return authz.ErrUnknownAuthorizationType
+ }
+
+ found, denomCoins := sendAuthz.SpendLimit.Find(p.tokenPair.Denom)
+ if !found {
+ return fmt.Errorf(ErrNoAllowanceForToken, p.tokenPair.Denom)
+ }
+
+ newSpendLimit, hasNeg := sendAuthz.SpendLimit.SafeSub(denomCoins)
+ // NOTE: safety check only, this should never happen since we only subtract what was found in the slice.
+ if hasNeg {
+ return ConvertErrToERC20Error(fmt.Errorf(ErrSubtractMoreThanAllowance,
+ p.tokenPair.Denom, denomCoins, sendAuthz.SpendLimit,
+ ))
+ }
+
+ if newSpendLimit.IsZero() {
+ return p.AuthzKeeper.DeleteGrant(ctx, grantee.Bytes(), granter.Bytes(), SendMsgURL)
+ }
+
+ sendAuthz.SpendLimit = newSpendLimit
+ return p.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), sendAuthz, expiration)
+}
+
+func (p Precompile) increaseAllowance(
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ addedValue *big.Int,
+ authorization authz.Authorization,
+ expiration *time.Time,
+) (amount *big.Int, err error) {
+ sendAuthz, ok := authorization.(*banktypes.SendAuthorization)
+ if !ok {
+ return nil, authz.ErrUnknownAuthorizationType
+ }
+
+ allowance := sendAuthz.SpendLimit.AmountOfNoDenomValidation(p.tokenPair.Denom)
+ sdkAddedValue := sdkmath.NewIntFromBigInt(addedValue)
+ amount, overflow := cmn.SafeAdd(allowance, sdkAddedValue)
+ if overflow {
+ return nil, ConvertErrToERC20Error(errors.New(cmn.ErrIntegerOverflow))
+ }
+
+ if err := p.updateAuthorization(ctx, grantee, granter, amount, sendAuthz, expiration); err != nil {
+ return nil, err
+ }
+
+ return amount, nil
+}
+
+func (p Precompile) decreaseAllowance(
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ subtractedValue *big.Int,
+ authorization authz.Authorization,
+ expiration *time.Time,
+) (amount *big.Int, err error) {
+ sendAuthz, ok := authorization.(*banktypes.SendAuthorization)
+ if !ok {
+ return nil, authz.ErrUnknownAuthorizationType
+ }
+
+ found, allowance := sendAuthz.SpendLimit.Find(p.tokenPair.Denom)
+ if !found {
+ return nil, fmt.Errorf(ErrNoAllowanceForToken, p.tokenPair.Denom)
+ }
+
+ amount = new(big.Int).Sub(allowance.Amount.BigInt(), subtractedValue)
+ // NOTE: Safety check only since this is checked in the DecreaseAllowance method already.
+ if amount.Sign() < 0 {
+ return nil, ConvertErrToERC20Error(fmt.Errorf(ErrSubtractMoreThanAllowance, p.tokenPair.Denom, subtractedValue, allowance.Amount))
+ }
+
+ if err := p.updateAuthorization(ctx, grantee, granter, amount, sendAuthz, expiration); err != nil {
+ return nil, err
+ }
+
+ return amount, nil
+}
diff --git a/precompiles/erc20/approve_test.go b/precompiles/erc20/approve_test.go
new file mode 100644
index 00000000..b75593f7
--- /dev/null
+++ b/precompiles/erc20/approve_test.go
@@ -0,0 +1,764 @@
+package erc20_test
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+//nolint:dupl // tests are not duplicate between the functions
+func (s *PrecompileTestSuite) TestApprove() {
+ method := s.precompile.Methods[authorization.ApproveMethod]
+ amount := int64(100)
+
+ testcases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func()
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "fail - empty args",
+ malleate: func() []interface{} { return nil },
+ errContains: "invalid number of arguments",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ malleate: func() []interface{} {
+ return []interface{}{
+ 1, 2, 3,
+ }
+ },
+ errContains: "invalid number of arguments",
+ },
+ {
+ name: "fail - invalid address",
+ malleate: func() []interface{} {
+ return []interface{}{
+ "invalid address", big.NewInt(2),
+ }
+ },
+ errContains: "invalid address",
+ },
+ {
+ name: "fail - invalid amount",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), "invalid amount",
+ }
+ },
+ errContains: "invalid amount",
+ },
+ {
+ name: "fail - negative amount",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(-1),
+ }
+ },
+ errContains: erc20.ErrNegativeAmount.Error(),
+ },
+ {
+ name: "fail - approve uint256 overflow",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), new(big.Int).Add(abi.MaxUint256, common.Big1),
+ }
+ },
+ errContains: "causes integer overflow",
+ },
+ {
+ name: "fail - approve to zero with existing authorization only for other denominations",
+ malleate: func() []interface{} {
+ // NOTE: We are setting up a grant with a spend limit for a different denomination
+ // and then trying to approve an amount of zero for the token denomination
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.bondDenom, 1),
+ ),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), common.Big0,
+ }
+ },
+ errContains: fmt.Sprintf(erc20.ErrNoAllowanceForToken, s.tokenDenom),
+ postCheck: func() {
+ // NOTE: Here we check that the authorization was not adjusted
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.bondDenom, 1),
+ ),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - approve without existing authorization",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(amount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, amount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - approve with existing authorization",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, 1)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(amount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, amount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - approve with existing authorization in different denomination",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, 1)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(amount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ // Check that the approval is extended with the new denomination instead of overwritten
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, 1), sdk.NewInt64Coin(s.tokenDenom, amount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - delete existing authorization",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, 1)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), common.Big0,
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ grants, err := s.grpcHandler.GetGrantsByGrantee(s.keyring.GetAccAddr(1).String())
+ s.Require().NoError(err, "expected no error querying the grants")
+ s.Require().Len(grants, 0, "expected grant to be deleted")
+ },
+ },
+ {
+ name: "pass - delete denomination from spend limit but leave other denoms",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.tokenDenom, 1),
+ sdk.NewInt64Coin(s.bondDenom, 1),
+ ),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), common.Big0,
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ // Check that the approval does not have a spend limit for the deleted denomination
+ // but still contains the other denom
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, 1)),
+ []string{},
+ )
+ },
+ },
+ }
+
+ for _, tc := range testcases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ ctx := s.network.GetContext()
+
+ var contract *vm.Contract
+ contract, ctx = testutil.NewPrecompileContract(
+ s.T(),
+ ctx,
+ s.keyring.GetAddr(0),
+ s.precompile,
+ 200_000,
+ )
+
+ var args []interface{}
+ if tc.malleate != nil {
+ args = tc.malleate()
+ }
+
+ bz, err := s.precompile.Approve(
+ ctx,
+ contract,
+ s.network.GetStateDB(),
+ &method,
+ args,
+ )
+
+ if tc.expPass {
+ s.Require().NoError(err, "expected no error")
+ s.Require().NotNil(bz, "expected non-nil bytes")
+ } else {
+ s.Require().Error(err, "expected error")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ s.Require().Empty(bz, "expected empty bytes")
+ }
+
+ if tc.postCheck != nil {
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+//nolint:dupl // tests are not duplicate between the functions
+func (s *PrecompileTestSuite) TestIncreaseAllowance() {
+ method := s.precompile.Methods[authorization.IncreaseAllowanceMethod]
+ amount := int64(100)
+ increaseAmount := int64(200)
+
+ testcases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func()
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "fail - empty args",
+ malleate: func() []interface{} { return nil },
+ errContains: "invalid number of arguments",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ malleate: func() []interface{} {
+ return []interface{}{
+ 1, 2, 3,
+ }
+ },
+ errContains: "invalid number of arguments",
+ },
+ {
+ name: "fail - invalid address",
+ malleate: func() []interface{} {
+ return []interface{}{
+ "invalid address", big.NewInt(2),
+ }
+ },
+ errContains: "invalid address",
+ },
+ {
+ name: "fail - invalid amount",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), "invalid amount",
+ }
+ },
+ errContains: "invalid amount",
+ },
+ {
+ name: "fail - negative amount",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(-1),
+ }
+ },
+ errContains: erc20.ErrIncreaseNonPositiveValue.Error(),
+ },
+ {
+ name: "pass - increase allowance without existing authorization",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(increaseAmount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, increaseAmount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - increase allowance with existing authorization",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, amount)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(increaseAmount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, amount+increaseAmount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "fail - uint256 overflow when increasing allowance",
+ malleate: func() []interface{} {
+ // NOTE: We are setting up a grant with a spend limit of the maximum uint256 value
+ // and then trying to approve an amount that would overflow the uint256 value
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.bondDenom, 1),
+ sdk.NewCoin(s.tokenDenom, math.NewIntFromBigInt(abi.MaxUint256)),
+ ),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(amount),
+ }
+ },
+ errContains: erc20.ConvertErrToERC20Error(errors.New(cmn.ErrIntegerOverflow)).Error(),
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ // NOTE: The amounts should not have been adjusted after failing the overflow check.
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.bondDenom, 1),
+ sdk.NewCoin(s.tokenDenom, math.NewIntFromBigInt(abi.MaxUint256)),
+ ),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - increase allowance with existing authorization in different denomination",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(increaseAmount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ // NOTE: The approval in the precompile denomination is added to the existing
+ // approval for the different denomination.
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount), sdk.NewInt64Coin(s.tokenDenom, increaseAmount)),
+ []string{},
+ )
+ },
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ ctx := s.network.GetContext()
+
+ var contract *vm.Contract
+ contract, ctx = testutil.NewPrecompileContract(
+ s.T(),
+ ctx,
+ s.keyring.GetAddr(0),
+ s.precompile,
+ 200_000,
+ )
+
+ var args []interface{}
+ if tc.malleate != nil {
+ args = tc.malleate()
+ }
+
+ bz, err := s.precompile.IncreaseAllowance(
+ ctx,
+ contract,
+ s.network.GetStateDB(),
+ &method,
+ args,
+ )
+
+ if tc.expPass {
+ s.Require().NoError(err, "expected no error")
+ s.Require().NotNil(bz, "expected non-nil bytes")
+ } else {
+ s.Require().Error(err, "expected error")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ s.Require().Empty(bz, "expected empty bytes")
+ }
+
+ if tc.postCheck != nil {
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+//nolint:dupl // tests are not duplicate between the functions
+func (s *PrecompileTestSuite) TestDecreaseAllowance() {
+ method := s.precompile.Methods[authorization.DecreaseAllowanceMethod]
+ amount := int64(100)
+ decreaseAmount := int64(50)
+
+ testcases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func()
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "fail - empty args",
+ malleate: func() []interface{} { return nil },
+ errContains: "invalid number of arguments",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ malleate: func() []interface{} {
+ return []interface{}{
+ 1, 2, 3,
+ }
+ },
+ errContains: "invalid number of arguments",
+ },
+ {
+ name: "fail - invalid address",
+ malleate: func() []interface{} {
+ return []interface{}{
+ "invalid address", big.NewInt(2),
+ }
+ },
+ errContains: "invalid address",
+ },
+ {
+ name: "fail - invalid amount",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), "invalid amount",
+ }
+ },
+ errContains: "invalid amount",
+ },
+ {
+ name: "fail - negative amount",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(-1),
+ }
+ },
+ errContains: erc20.ErrDecreaseNonPositiveValue.Error(),
+ },
+ {
+ name: "fail - decrease allowance without existing authorization",
+ malleate: func() []interface{} {
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(decreaseAmount),
+ }
+ },
+ errContains: "does not exist or is expired",
+ },
+ {
+ name: "fail - decrease allowance with existing authorization only for other denominations",
+ malleate: func() []interface{} {
+ // NOTE: We are setting up a grant with a spend limit for a different denomination
+ // and then trying to decrease the allowance for the token denomination
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.bondDenom, 1),
+ ),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(decreaseAmount),
+ }
+ },
+ errContains: fmt.Sprintf("allowance for token %s does not exist", s.tokenDenom),
+ postCheck: func() {
+ // NOTE: Here we check that the authorization was not adjusted
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.bondDenom, 1),
+ ),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - decrease allowance with existing authorization",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, amount)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(decreaseAmount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, decreaseAmount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - decrease to zero and delete existing authorization",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, amount)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(amount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ // Check that the authorization was deleted
+ grants, err := s.grpcHandler.GetGrantsByGrantee(s.keyring.GetAccAddr(1).String())
+ s.Require().NoError(err, "expected no error querying the grants")
+ s.Require().Len(grants, 0, "expected grant to be deleted")
+ },
+ },
+ {
+ name: "pass - decrease allowance with existing authorization in different denomination",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount), sdk.NewInt64Coin(s.tokenDenom, amount)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(decreaseAmount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ // NOTE: Here we check that the authorization for the other denom was not deleted and the spend limit
+ // for token denom was adjusted as expected
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount), sdk.NewInt64Coin(s.tokenDenom, amount-decreaseAmount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "pass - decrease allowance to zero for denom with existing authorization in other denominations",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(
+ sdk.NewInt64Coin(s.bondDenom, amount),
+ sdk.NewInt64Coin(s.tokenDenom, amount),
+ ),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(amount),
+ }
+ },
+ expPass: true,
+ postCheck: func() {
+ // NOTE: Here we check that the authorization for the other denom was not deleted
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "fail - decrease allowance with existing authorization but decreased amount too high",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.tokenDenom, amount)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(amount + 1),
+ }
+ },
+ errContains: erc20.ConvertErrToERC20Error(errors.New("subtracted value cannot be greater than existing allowance")).Error(),
+ },
+ {
+ name: "fail - decrease allowance with existing authorization in different denomination",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(decreaseAmount),
+ }
+ },
+ errContains: fmt.Sprintf(erc20.ErrNoAllowanceForToken, s.tokenDenom),
+ postCheck: func() {
+ // NOTE: Here we check that the authorization for the other denom was not deleted
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount)),
+ []string{},
+ )
+ },
+ },
+ {
+ name: "fail - decrease allowance with existing authorization in different denomination but decreased amount too high",
+ malleate: func() []interface{} {
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetPrivKey(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount), sdk.NewInt64Coin(s.tokenDenom, 1)),
+ )
+
+ return []interface{}{
+ s.keyring.GetAddr(1), big.NewInt(decreaseAmount),
+ }
+ },
+ errContains: erc20.ConvertErrToERC20Error(errors.New("subtracted value cannot be greater than existing allowance")).Error(),
+ postCheck: func() {
+ // NOTE: Here we check that the authorization was not adjusted
+ s.requireSendAuthz(
+ s.keyring.GetAccAddr(1),
+ s.keyring.GetAccAddr(0),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, amount), sdk.NewInt64Coin(s.tokenDenom, 1)),
+ []string{},
+ )
+ },
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ ctx := s.network.GetContext()
+
+ var contract *vm.Contract
+ contract, ctx = testutil.NewPrecompileContract(
+ s.T(),
+ ctx,
+ s.keyring.GetAddr(0),
+ s.precompile,
+ 200_000,
+ )
+
+ var args []interface{}
+ if tc.malleate != nil {
+ args = tc.malleate()
+ }
+
+ bz, err := s.precompile.DecreaseAllowance(
+ ctx,
+ contract,
+ s.network.GetStateDB(),
+ &method,
+ args,
+ )
+
+ if tc.expPass {
+ s.Require().NoError(err, "expected no error")
+ s.Require().NotNil(bz, "expected non-nil bytes")
+ } else {
+ s.Require().Error(err, "expected error")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ s.Require().Empty(bz, "expected empty bytes")
+ }
+
+ if tc.postCheck != nil {
+ tc.postCheck()
+ }
+ })
+ }
+}
diff --git a/precompiles/erc20/erc20.go b/precompiles/erc20/erc20.go
new file mode 100644
index 00000000..b378097a
--- /dev/null
+++ b/precompiles/erc20/erc20.go
@@ -0,0 +1,210 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20
+
+import (
+ "embed"
+ "fmt"
+
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+ erc20types "github.com/evmos/evmos/v19/x/erc20/types"
+ transferkeeper "github.com/evmos/evmos/v19/x/ibc/transfer/keeper"
+)
+
+const (
+ // abiPath defines the path to the ERC-20 precompile ABI JSON file.
+ abiPath = "abi.json"
+
+ GasTransfer = 3_000_000
+ GasApprove = 30_956
+ GasIncreaseAllowance = 34_605
+ GasDecreaseAllowance = 34_519
+ GasName = 3_421
+ GasSymbol = 3_464
+ GasDecimals = 427
+ GasTotalSupply = 2_477
+ GasBalanceOf = 2_851
+ GasAllowance = 3_246
+)
+
+// Embed abi json file to the executable binary. Needed when importing as dependency.
+//
+//go:embed abi.json
+var f embed.FS
+
+var _ vm.PrecompiledContract = &Precompile{}
+
+// Precompile defines the precompiled contract for ERC-20.
+type Precompile struct {
+ cmn.Precompile
+ tokenPair erc20types.TokenPair
+ bankKeeper bankkeeper.Keeper
+ transferKeeper transferkeeper.Keeper
+}
+
+// NewPrecompile creates a new ERC-20 Precompile instance as a
+// PrecompiledContract interface.
+func NewPrecompile(
+ tokenPair erc20types.TokenPair,
+ bankKeeper bankkeeper.Keeper,
+ authzKeeper authzkeeper.Keeper,
+ transferKeeper transferkeeper.Keeper,
+) (*Precompile, error) {
+ newABI, err := cmn.LoadABI(f, abiPath)
+ if err != nil {
+ return nil, err
+ }
+
+ p := &Precompile{
+ Precompile: cmn.Precompile{
+ ABI: newABI,
+ AuthzKeeper: authzKeeper,
+ ApprovalExpiration: cmn.DefaultExpirationDuration,
+ KvGasConfig: storetypes.GasConfig{},
+ TransientKVGasConfig: storetypes.GasConfig{},
+ },
+ tokenPair: tokenPair,
+ bankKeeper: bankKeeper,
+ transferKeeper: transferKeeper,
+ }
+ // Address defines the address of the ERC-20 precompile contract.
+ p.SetAddress(p.tokenPair.GetERC20Contract())
+ return p, nil
+}
+
+// RequiredGas calculates the contract gas used for the
+func (p Precompile) RequiredGas(input []byte) uint64 {
+ // NOTE: This check avoid panicking when trying to decode the method ID
+ if len(input) < 4 {
+ return 0
+ }
+
+ methodID := input[:4]
+ method, err := p.MethodById(methodID)
+ if err != nil {
+ return 0
+ }
+
+ // TODO: these values were obtained from Remix using the ERC20.sol from OpenZeppelin.
+ // We should execute the transactions using the ERC20MinterBurnerDecimals.sol from Evmos testnet
+ // to ensure parity in the values.
+ switch method.Name {
+ // ERC-20 transactions
+ case TransferMethod:
+ return GasTransfer
+ case TransferFromMethod:
+ return GasTransfer
+ case auth.ApproveMethod:
+ return GasApprove
+ case auth.IncreaseAllowanceMethod:
+ return GasIncreaseAllowance
+ case auth.DecreaseAllowanceMethod:
+ return GasDecreaseAllowance
+ // ERC-20 queries
+ case NameMethod:
+ return GasName
+ case SymbolMethod:
+ return GasSymbol
+ case DecimalsMethod:
+ return GasDecimals
+ case TotalSupplyMethod:
+ return GasTotalSupply
+ case BalanceOfMethod:
+ return GasBalanceOf
+ case auth.AllowanceMethod:
+ return GasAllowance
+ default:
+ return 0
+ }
+}
+
+// Run executes the precompiled contract ERC-20 methods defined in the ABI.
+func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) {
+ ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction)
+ if err != nil {
+ return nil, err
+ }
+
+ // This handles any out of gas errors that may occur during the execution of a precompile tx or query.
+ // It avoids panics and returns the out of gas error so the EVM can continue gracefully.
+ defer cmn.HandleGasError(ctx, contract, initialGas, &err)()
+
+ bz, err = p.HandleMethod(ctx, contract, stateDB, method, args)
+ if err != nil {
+ return nil, err
+ }
+
+ cost := ctx.GasMeter().GasConsumed() - initialGas
+
+ if !contract.UseGas(cost) {
+ return nil, vm.ErrOutOfGas
+ }
+ if err := p.AddJournalEntries(stateDB, snapshot); err != nil {
+ return nil, err
+ }
+ return bz, nil
+}
+
+// IsTransaction checks if the given method name corresponds to a transaction or query.
+func (Precompile) IsTransaction(methodName string) bool {
+ switch methodName {
+ case TransferMethod,
+ TransferFromMethod,
+ auth.ApproveMethod,
+ auth.IncreaseAllowanceMethod,
+ auth.DecreaseAllowanceMethod:
+ return true
+ default:
+ return false
+ }
+}
+
+// HandleMethod handles the execution of each of the ERC-20 methods.
+func (p *Precompile) HandleMethod(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) (bz []byte, err error) {
+ switch method.Name {
+ // ERC-20 transactions
+ case TransferMethod:
+ bz, err = p.Transfer(ctx, contract, stateDB, method, args)
+ case TransferFromMethod:
+ bz, err = p.TransferFrom(ctx, contract, stateDB, method, args)
+ case auth.ApproveMethod:
+ bz, err = p.Approve(ctx, contract, stateDB, method, args)
+ case auth.IncreaseAllowanceMethod:
+ bz, err = p.IncreaseAllowance(ctx, contract, stateDB, method, args)
+ case auth.DecreaseAllowanceMethod:
+ bz, err = p.DecreaseAllowance(ctx, contract, stateDB, method, args)
+ // ERC-20 queries
+ case NameMethod:
+ bz, err = p.Name(ctx, contract, stateDB, method, args)
+ case SymbolMethod:
+ bz, err = p.Symbol(ctx, contract, stateDB, method, args)
+ case DecimalsMethod:
+ bz, err = p.Decimals(ctx, contract, stateDB, method, args)
+ case TotalSupplyMethod:
+ bz, err = p.TotalSupply(ctx, contract, stateDB, method, args)
+ case BalanceOfMethod:
+ bz, err = p.BalanceOf(ctx, contract, stateDB, method, args)
+ case auth.AllowanceMethod:
+ bz, err = p.Allowance(ctx, contract, stateDB, method, args)
+ default:
+ return nil, fmt.Errorf(cmn.ErrUnknownMethod, method.Name)
+ }
+
+ return bz, err
+}
diff --git a/precompiles/erc20/erc20_test.go b/precompiles/erc20/erc20_test.go
new file mode 100644
index 00000000..54396dbe
--- /dev/null
+++ b/precompiles/erc20/erc20_test.go
@@ -0,0 +1,163 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20_test
+
+import (
+ "math/big"
+
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+)
+
+func (s *PrecompileTestSuite) TestIsTransaction() {
+ s.SetupTest()
+
+ // Queries
+ s.Require().False(s.precompile.IsTransaction(erc20.BalanceOfMethod))
+ s.Require().False(s.precompile.IsTransaction(erc20.DecimalsMethod))
+ s.Require().False(s.precompile.IsTransaction(erc20.NameMethod))
+ s.Require().False(s.precompile.IsTransaction(erc20.SymbolMethod))
+ s.Require().False(s.precompile.IsTransaction(erc20.TotalSupplyMethod))
+
+ // Transactions
+ s.Require().True(s.precompile.IsTransaction(auth.ApproveMethod))
+ s.Require().True(s.precompile.IsTransaction(auth.IncreaseAllowanceMethod))
+ s.Require().True(s.precompile.IsTransaction(auth.DecreaseAllowanceMethod))
+ s.Require().True(s.precompile.IsTransaction(erc20.TransferMethod))
+ s.Require().True(s.precompile.IsTransaction(erc20.TransferFromMethod))
+}
+
+func (s *PrecompileTestSuite) TestRequiredGas() {
+ s.SetupTest()
+
+ testcases := []struct {
+ name string
+ malleate func() []byte
+ expGas uint64
+ }{
+ {
+ name: erc20.BalanceOfMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(erc20.BalanceOfMethod, s.keyring.GetAddr(0))
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasBalanceOf,
+ },
+ {
+ name: erc20.DecimalsMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(erc20.DecimalsMethod)
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasDecimals,
+ },
+ {
+ name: erc20.NameMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(erc20.NameMethod)
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasName,
+ },
+ {
+ name: erc20.SymbolMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(erc20.SymbolMethod)
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasSymbol,
+ },
+ {
+ name: erc20.TotalSupplyMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(erc20.TotalSupplyMethod)
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasTotalSupply,
+ },
+ {
+ name: auth.ApproveMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(auth.ApproveMethod, s.keyring.GetAddr(0), big.NewInt(1))
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasApprove,
+ },
+ {
+ name: auth.IncreaseAllowanceMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(auth.IncreaseAllowanceMethod, s.keyring.GetAddr(0), big.NewInt(1))
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasIncreaseAllowance,
+ },
+ {
+ name: auth.DecreaseAllowanceMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(auth.DecreaseAllowanceMethod, s.keyring.GetAddr(0), big.NewInt(1))
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasDecreaseAllowance,
+ },
+ {
+ name: erc20.TransferMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(erc20.TransferMethod, s.keyring.GetAddr(0), big.NewInt(1))
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasTransfer,
+ },
+ {
+ name: erc20.TransferFromMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(erc20.TransferFromMethod, s.keyring.GetAddr(0), s.keyring.GetAddr(0), big.NewInt(1))
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasTransfer,
+ },
+ {
+ name: auth.AllowanceMethod,
+ malleate: func() []byte {
+ bz, err := s.precompile.ABI.Pack(auth.AllowanceMethod, s.keyring.GetAddr(0), s.keyring.GetAddr(0))
+ s.Require().NoError(err, "expected no error packing ABI")
+ return bz
+ },
+ expGas: erc20.GasAllowance,
+ },
+ {
+ name: "invalid method",
+ malleate: func() []byte {
+ return []byte("invalid method")
+ },
+ expGas: 0,
+ },
+ {
+ name: "input bytes too short",
+ malleate: func() []byte {
+ return []byte{0x00, 0x00, 0x00}
+ },
+ expGas: 0,
+ },
+ }
+
+ for _, tc := range testcases {
+ s.Run(tc.name, func() {
+ tc := tc
+
+ input := tc.malleate()
+
+ s.Require().Equal(tc.expGas, s.precompile.RequiredGas(input))
+ })
+ }
+}
diff --git a/precompiles/erc20/errors.go b/precompiles/erc20/errors.go
new file mode 100644
index 00000000..66fb7ffb
--- /dev/null
+++ b/precompiles/erc20/errors.go
@@ -0,0 +1,97 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/ibc"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// Errors that have formatted information are defined here as a string.
+const (
+ ErrIntegerOverflow = "amount %s causes integer overflow"
+ ErrInvalidOwner = "invalid from address: %s"
+ ErrInvalidReceiver = "invalid to address: %s"
+ ErrNoAllowanceForToken = "allowance for token %s does not exist"
+ ErrSubtractMoreThanAllowance = "subtracted value cannot be greater than existing allowance for denom %s: %s > %s"
+)
+
+var (
+ // errorSignature are the prefix bytes for the hex-encoded reason string. See UnpackRevert in ABI implementation in Geth.
+ errorSignature = crypto.Keccak256([]byte("Error(string)"))
+
+ // Precompile errors
+ ErrDecreaseNonPositiveValue = errors.New("cannot decrease allowance with non-positive values")
+ ErrIncreaseNonPositiveValue = errors.New("cannot increase allowance with non-positive values")
+ ErrNegativeAmount = errors.New("cannot approve negative values")
+ ErrSpenderIsOwner = errors.New("spender cannot be the owner")
+
+ // ERC20 errors
+ ErrDecreasedAllowanceBelowZero = errors.New("ERC20: decreased allowance below zero")
+ ErrInsufficientAllowance = errors.New("ERC20: insufficient allowance")
+ ErrTransferAmountExceedsBalance = errors.New("ERC20: transfer amount exceeds balance")
+)
+
+// BuildExecRevertedErr returns a mocked error that should align with the
+// behavior of the original ERC20 Solidity implementation.
+//
+// FIXME: This is not yet producing the correct reason bytes. Will fix on a follow up PR.
+func BuildExecRevertedErr(reason string) (error, error) {
+ // This is reverse-engineering the ABI encoding of the revert reason.
+ typ, err := abi.NewType("string", "", nil)
+ if err != nil {
+ return nil, err
+ }
+
+ packedReason, err := (abi.Arguments{{Type: typ}}).Pack(reason)
+ if err != nil {
+ return nil, errors.New("failed to pack revert reason")
+ }
+
+ var reasonBytes []byte
+ reasonBytes = append(reasonBytes, errorSignature...)
+ reasonBytes = append(reasonBytes, packedReason...)
+
+ return evmtypes.NewExecErrorWithReason(reasonBytes), nil
+}
+
+// ConvertErrToERC20Error is a helper function which maps errors raised by the Cosmos SDK stack
+// to the corresponding errors which are raised by an ERC20 contract.
+//
+// TODO: Create the full RevertError types instead of just the standard error type.
+//
+// TODO: Return ERC-6093 compliant errors.
+func ConvertErrToERC20Error(err error) error {
+ switch {
+ case strings.Contains(err.Error(), "spendable balance"):
+ return ErrTransferAmountExceedsBalance
+ case strings.Contains(err.Error(), "requested amount is more than spend limit"):
+ return ErrInsufficientAllowance
+ case strings.Contains(err.Error(), authz.ErrNoAuthorizationFound.Error()):
+ return ErrInsufficientAllowance
+ case strings.Contains(err.Error(), "subtracted value cannot be greater than existing allowance"):
+ return ErrDecreasedAllowanceBelowZero
+ case strings.Contains(err.Error(), cmn.ErrIntegerOverflow):
+ return vm.ErrExecutionReverted
+ case errors.Is(err, ibc.ErrNoIBCVoucherDenom) ||
+ errors.Is(err, ibc.ErrDenomTraceNotFound) ||
+ strings.Contains(err.Error(), "invalid base denomination") ||
+ strings.Contains(err.Error(), "display denomination not found") ||
+ strings.Contains(err.Error(), "invalid decimals"):
+ // NOTE: These are the cases when trying to query metadata of a contract, which has no metadata available.
+ // The ERC20 contract raises an "execution reverted" error, without any further information here, which we
+ // reproduce (even though it's less verbose than the actual error).
+ return vm.ErrExecutionReverted
+ default:
+ return err
+ }
+}
diff --git a/precompiles/erc20/errors_test.go b/precompiles/erc20/errors_test.go
new file mode 100644
index 00000000..14218e46
--- /dev/null
+++ b/precompiles/erc20/errors_test.go
@@ -0,0 +1,25 @@
+package erc20_test
+
+import (
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// TODO: This is not yet producing the correct reason bytes so we skip this test for now,
+// until that's correctly implemented.
+func (s *PrecompileTestSuite) TestBuildExecRevertedError() {
+ s.T().Skip("skipping until correctly implemented")
+
+ reason := "ERC20: transfer amount exceeds balance"
+ revErr, err := erc20.BuildExecRevertedErr(reason)
+ s.Require().NoError(err, "should not error when building revert error")
+
+ revertErr, ok := revErr.(*evmtypes.RevertError)
+ s.Require().True(ok, "error should be a revert error")
+
+ // Here we expect the correct revert reason that's returned by an ERC20 Solidity contract.
+ s.Require().Equal(
+ "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63650000000000000000000000000000000000000000000000000000",
+ revertErr.ErrorData(),
+ "error data should be the revert reason")
+}
diff --git a/precompiles/erc20/events.go b/precompiles/erc20/events.go
new file mode 100644
index 00000000..0be677ad
--- /dev/null
+++ b/precompiles/erc20/events.go
@@ -0,0 +1,96 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20
+
+import (
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+const (
+ // EventTypeTransfer defines the event type for the ERC-20 Transfer and TransferFrom transactions.
+ EventTypeTransfer = "Transfer"
+)
+
+// EmitTransferEvent creates a new Transfer event emitted on transfer and transferFrom transactions.
+func (p Precompile) EmitTransferEvent(ctx sdk.Context, stateDB vm.StateDB, from, to common.Address, value *big.Int) error {
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeTransfer]
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(from)
+ if err != nil {
+ return err
+ }
+
+ topics[2], err = cmn.MakeTopic(to)
+ if err != nil {
+ return err
+ }
+
+ arguments := abi.Arguments{event.Inputs[2]}
+ packed, err := arguments.Pack(value)
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitApprovalEvent creates a new approval event emitted on Approve, IncreaseAllowance
+// and DecreaseAllowance transactions.
+func (p Precompile) EmitApprovalEvent(ctx sdk.Context, stateDB vm.StateDB, owner, spender common.Address, value *big.Int) error {
+ // Prepare the event topics
+ event := p.ABI.Events[auth.EventTypeApproval]
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(owner)
+ if err != nil {
+ return err
+ }
+
+ topics[2], err = cmn.MakeTopic(spender)
+ if err != nil {
+ return err
+ }
+
+ arguments := abi.Arguments{event.Inputs[2]}
+ packed, err := arguments.Pack(value)
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
diff --git a/precompiles/erc20/events_test.go b/precompiles/erc20/events_test.go
new file mode 100644
index 00000000..8a6fe6b7
--- /dev/null
+++ b/precompiles/erc20/events_test.go
@@ -0,0 +1,107 @@
+package erc20_test
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ erc20precompile "github.com/evmos/evmos/v19/precompiles/erc20"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+)
+
+//nolint:dupl // this is not a duplicate of the approval events test
+func (s *PrecompileTestSuite) TestEmitTransferEvent() {
+ testcases := []struct {
+ name string
+ from common.Address
+ to common.Address
+ amount *big.Int
+ }{
+ {
+ name: "pass",
+ from: utiltx.GenerateAddress(),
+ to: utiltx.GenerateAddress(),
+ amount: big.NewInt(100),
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ stateDB := s.network.GetStateDB()
+
+ err := s.precompile.EmitTransferEvent(
+ s.network.GetContext(), stateDB, tc.from, tc.to, tc.amount,
+ )
+ s.Require().NoError(err, "expected transfer event to be emitted successfully")
+
+ log := stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[erc20precompile.EventTypeTransfer]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.network.GetContext().BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var transferEvent erc20precompile.EventTransfer
+ err = cmn.UnpackLog(s.precompile.ABI, &transferEvent, erc20precompile.EventTypeTransfer, *log)
+ s.Require().NoError(err, "unable to unpack log into transfer event")
+
+ s.Require().Equal(tc.from, transferEvent.From, "expected different from address")
+ s.Require().Equal(tc.to, transferEvent.To, "expected different to address")
+ s.Require().Equal(tc.amount, transferEvent.Value, "expected different amount")
+ })
+ }
+}
+
+//nolint:dupl // this is not a duplicate of the transfer events test
+func (s *PrecompileTestSuite) TestEmitApprovalEvent() {
+ testcases := []struct {
+ name string
+ owner common.Address
+ spender common.Address
+ amount *big.Int
+ }{
+ {
+ name: "pass",
+ owner: utiltx.GenerateAddress(),
+ spender: utiltx.GenerateAddress(),
+ amount: big.NewInt(100),
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ stateDB := s.network.GetStateDB()
+
+ err := s.precompile.EmitApprovalEvent(
+ s.network.GetContext(), stateDB, tc.owner, tc.spender, tc.amount,
+ )
+ s.Require().NoError(err, "expected approval event to be emitted successfully")
+
+ log := stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[authorization.EventTypeApproval]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.network.GetContext().BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var approvalEvent erc20precompile.EventApproval
+ err = cmn.UnpackLog(s.precompile.ABI, &approvalEvent, authorization.EventTypeApproval, *log)
+ s.Require().NoError(err, "unable to unpack log into approval event")
+
+ s.Require().Equal(tc.owner, approvalEvent.Owner, "expected different owner address")
+ s.Require().Equal(tc.spender, approvalEvent.Spender, "expected different spender address")
+ s.Require().Equal(tc.amount, approvalEvent.Value, "expected different amount")
+ })
+ }
+}
diff --git a/precompiles/erc20/integration_test.go b/precompiles/erc20/integration_test.go
new file mode 100644
index 00000000..a382027c
--- /dev/null
+++ b/precompiles/erc20/integration_test.go
@@ -0,0 +1,2512 @@
+package erc20_test
+
+import (
+ "fmt"
+ "math/big"
+ "strings"
+ "testing"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/contracts"
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/precompiles/erc20/testdata"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ contractutils "github.com/evmos/evmos/v19/precompiles/testutil/contracts"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/utils"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ erc20types "github.com/evmos/evmos/v19/x/erc20/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+)
+
+var is *IntegrationTestSuite
+
+type IntegrationTestSuite struct {
+ // NOTE: we have to use the Unit testing network because we access a keeper in a setup function.
+ // Might adjust this on a follow-up PR.
+ network *network.UnitTestNetwork
+ handler grpc.Handler
+ keyring keyring.Keyring
+ factory factory.TxFactory
+
+ bondDenom string
+ tokenDenom string
+
+ precompile *erc20.Precompile
+}
+
+func (is *IntegrationTestSuite) SetupTest() {
+ keys := keyring.New(2)
+ nw := network.NewUnitTestNetwork(
+ network.WithPreFundedAccounts(keys.GetAllAccAddrs()...),
+ )
+ gh := grpc.NewIntegrationHandler(nw)
+ tf := factory.New(nw, gh)
+
+ // Set up min deposit in Evmos
+ params, err := gh.GetGovParams("deposit")
+ Expect(err).ToNot(HaveOccurred(), "failed to get gov params")
+ Expect(params).ToNot(BeNil(), "returned gov params are nil")
+
+ updatedParams := params.Params
+ updatedParams.MinDeposit = sdk.NewCoins(sdk.NewCoin(nw.GetDenom(), math.NewInt(1e18)))
+ err = nw.UpdateGovParams(*updatedParams)
+ Expect(err).ToNot(HaveOccurred(), "failed to update the min deposit")
+
+ is.network = nw
+ is.factory = tf
+ is.handler = gh
+ is.keyring = keys
+
+ is.bondDenom = nw.GetDenom()
+ is.tokenDenom = "xmpl"
+
+ is.precompile = is.setupERC20Precompile(is.tokenDenom)
+}
+
+func TestIntegrationSuite(t *testing.T) {
+ is = new(IntegrationTestSuite)
+
+ // Run Ginkgo integration tests
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "ERC20 Extension Suite")
+}
+
+var (
+ defaultCallArgs contractutils.CallArgs
+ wevmosAddress common.Address
+ revertContractAddr common.Address
+ gasLimit uint64
+ gasPrice *big.Int
+)
+
+var _ = Describe("ERC20 Extension -", func() {
+ var (
+ // contractsData holds the addresses and ABIs for the different
+ // contract instances that are subject to testing here.
+ contractsData ContractsData
+
+ allowanceCallerContract evmtypes.CompiledContract
+ revertCallerContract evmtypes.CompiledContract
+ erc20MinterV5Contract evmtypes.CompiledContract
+
+ execRevertedCheck testutil.LogCheckArgs
+ failCheck testutil.LogCheckArgs
+ passCheck testutil.LogCheckArgs
+ )
+
+ BeforeEach(func() {
+ is.SetupTest()
+
+ var err error
+ allowanceCallerContract, err = testdata.LoadERC20AllowanceCaller()
+ Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 allowance caller contract")
+
+ erc20MinterV5Contract, err = testdata.LoadERC20MinterV5Contract()
+ Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 minter contract")
+
+ revertCallerContract, err = testdata.LoadERC20TestCaller()
+ Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 allowance caller contract")
+
+ sender := is.keyring.GetKey(0)
+ contractAddr, err := is.factory.DeployContract(
+ sender.Priv,
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: allowanceCallerContract,
+ // NOTE: we're passing the precompile address to the constructor because that initiates the contract
+ // to make calls to the correct ERC20 precompile.
+ ConstructorArgs: []interface{}{is.precompile.Address()},
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy contract")
+
+ erc20MinterBurnerAddr, err := is.factory.DeployContract(
+ sender.Priv,
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: contracts.ERC20MinterBurnerDecimalsContract,
+ ConstructorArgs: []interface{}{
+ "Xmpl", "Xmpl", uint8(6),
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter burner contract")
+
+ ERC20MinterV5Addr, err := is.factory.DeployContract(
+ sender.Priv,
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: erc20MinterV5Contract,
+ ConstructorArgs: []interface{}{
+ "Xmpl", "Xmpl",
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter contract")
+
+ erc20MinterV5CallerAddr, err := is.factory.DeployContract(
+ sender.Priv,
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: allowanceCallerContract,
+ ConstructorArgs: []interface{}{
+ ERC20MinterV5Addr,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter caller contract")
+
+ // Store the data of the deployed contracts
+ contractsData = ContractsData{
+ ownerPriv: sender.Priv,
+ contractData: map[CallType]ContractData{
+ directCall: {
+ Address: is.precompile.Address(),
+ ABI: is.precompile.ABI,
+ },
+ contractCall: {
+ Address: contractAddr,
+ ABI: allowanceCallerContract.ABI,
+ },
+ erc20Call: {
+ Address: erc20MinterBurnerAddr,
+ ABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ },
+ erc20V5Call: {
+ Address: ERC20MinterV5Addr,
+ ABI: erc20MinterV5Contract.ABI,
+ },
+ erc20V5CallerCall: {
+ Address: erc20MinterV5CallerAddr,
+ ABI: allowanceCallerContract.ABI,
+ },
+ },
+ }
+
+ failCheck = testutil.LogCheckArgs{ABIEvents: is.precompile.Events}
+ execRevertedCheck = failCheck.WithErrContains("execution reverted")
+ passCheck = failCheck.WithExpPass(true)
+
+ erc20Params := is.network.App.Erc20Keeper.GetParams(is.network.GetContext())
+ Expect(len(erc20Params.NativePrecompiles)).To(Equal(1))
+
+ wevmosAddress = common.HexToAddress(erc20Params.NativePrecompiles[0])
+ revertContractAddr, err = is.factory.DeployContract(
+ sender.Priv,
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: revertCallerContract,
+ // NOTE: we're passing the precompile address to the constructor because that initiates the contract
+ // to make calls to the correct ERC20 precompile.
+ ConstructorArgs: []interface{}{common.HexToAddress(erc20Params.NativePrecompiles[0])},
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy reverter contract")
+
+ gasLimit = uint64(4991202)
+ gasPrice = big.NewInt(765625001)
+ defaultCallArgs = contractutils.CallArgs{
+ ContractAddr: revertContractAddr,
+ ContractABI: revertCallerContract.ABI,
+ PrivKey: sender.Priv,
+ GasLimit: gasLimit,
+ GasPrice: gasPrice,
+ }
+
+ err = is.network.NextBlock()
+ Expect(err).ToNot(HaveOccurred(), "failed to advance block")
+ })
+
+ Context("basic functionality -", func() {
+ When("sending tokens to contract", func() {
+ It("it should return error", func() {
+ sender := is.keyring.GetKey(0)
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+
+ // Fund account with some tokens
+ is.fundWithTokens(directCall, contractsData, sender.Addr, fundCoins)
+
+ // Taking custom args from the table entry
+ txArgs := evmtypes.EvmTxArgs{}
+ txArgs.Amount = big.NewInt(int64(1000))
+ precompileAddress := is.precompile.Address()
+ txArgs.To = &precompileAddress
+
+ _, err := is.factory.ExecuteEthTx(sender.Priv, txArgs)
+ Expect(err.Error()).To(ContainSubstring(vm.ErrExecutionReverted.Error()), "precompile should not accept transfers")
+ },
+ )
+ })
+ When("transferring tokens", func() {
+ DescribeTable("it should transfer tokens to a non-existing address", func(callType CallType, expGasUsedLowerBound int64, expGasUsedUpperBound int64) {
+ sender := is.keyring.GetKey(0)
+ receiver := utiltx.GenerateAddress()
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferCoins[0].Amount.BigInt())
+
+ transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer)
+
+ res, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, transferCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, erc20.TransferMethod)
+ is.ExpectBalancesForContract(
+ callType, contractsData,
+ []ExpectedBalance{
+ {address: sender.AccAddr, expCoins: fundCoins.Sub(transferCoins...)},
+ {address: receiver.Bytes(), expCoins: transferCoins},
+ },
+ )
+
+ Expect(res.GasUsed > expGasUsedLowerBound).To(BeTrue(), "expected different gas used")
+ Expect(res.GasUsed < expGasUsedUpperBound).To(BeTrue(), "expected different gas used")
+ },
+ // FIXME: The gas used on the precompile is much higher than on the EVM
+ Entry(" - direct call", directCall, int64(3_021_000), int64(3_022_000)),
+ Entry(" - through erc20 contract", erc20Call, int64(54_000), int64(54_500)),
+ Entry(" - through erc20 v5 contract", erc20V5Call, int64(52_000), int64(52_200)),
+ )
+
+ DescribeTable("it should transfer tokens to an existing address", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetKey(1)
+ fundCoinsSender := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ fundCoinsReceiver := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 500)}
+ transferCoin := sdk.NewInt64Coin(is.tokenDenom, 100)
+
+ // Fund accounts with some tokens
+ is.fundWithTokens(callType, contractsData, sender.Addr, fundCoinsSender)
+ is.fundWithTokens(callType, contractsData, receiver.Addr, fundCoinsReceiver)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver.Addr, transferCoin.Amount.BigInt())
+
+ transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, transferCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, erc20.TransferMethod)
+ is.ExpectBalancesForContract(
+ callType, contractsData,
+ []ExpectedBalance{
+ {address: sender.AccAddr, expCoins: fundCoinsSender.Sub(transferCoin)},
+ {address: receiver.AccAddr, expCoins: fundCoinsReceiver.Add(transferCoin)},
+ },
+ )
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the contract call here because transferring using a caller contract
+ // is only supported through transferFrom method.
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("it should return an error trying to call from a smart contract", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetAddr(1)
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoin := sdk.NewInt64Coin(is.tokenDenom, 100)
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferCoin.Amount.BigInt())
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ // NOTE: we are not passing the direct call here because this test is specific to the contract calls
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should return an error if the sender does not have enough tokens", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetAddr(1)
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)}
+ transferCoin := sdk.NewInt64Coin(is.tokenDenom, 300)
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferCoin.Amount.BigInt())
+
+ insufficientBalanceCheck := failCheck.WithErrContains(
+ erc20.ErrTransferAmountExceedsBalance.Error(),
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the contract call here because this test is for direct calls only
+
+ Entry(" - through erc20 contract", erc20Call),
+ // // TODO: The ERC20 V5 contract is raising the ERC-6093 standardized error which we are not as of yet
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+ When("calling reverter contract", func() {
+ Context("in a direct call to the WEVMOS contract", func() {
+ It("should transfer tokens", func() {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetAddr(1)
+ amountToSend := big.NewInt(100)
+ denomInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ senderInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+
+ cArgs := defaultCallArgs.
+ WithPrivKey(sender.Priv).
+ WithMethodName("transferWithRevert").
+ WithArgs(
+ receiver,
+ amountToSend,
+ false,
+ false,
+ ).
+ WithAmount(amountToSend)
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer,
+ )
+ res, _, err := contractutils.CallContractAndCheckLogs(is.network.GetContext(), is.network.App, cArgs, transferCheck)
+ Expect(err).To(BeNil())
+ denomFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(amountToSend.Int64()))))
+
+ contractBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), revertContractAddr.Bytes(), is.bondDenom)
+ Expect(contractBalance.Amount).To(Equal(math.ZeroInt()))
+
+ senderFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+ denomSpent := math.NewInt((res.GasUsed*gasPrice.Int64() + amountToSend.Int64()))
+ Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent)))
+ },
+ )
+ DescribeTable("it should revert token transfer from the WEVMOS contract", func(before bool, after bool) {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetAddr(1)
+ amountToSend := big.NewInt(100)
+ denomInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ senderInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+
+ cArgs := defaultCallArgs.
+ WithPrivKey(sender.Priv).
+ WithMethodName("transferWithRevert").
+ WithArgs(
+ receiver,
+ amountToSend,
+ before,
+ after,
+ ).
+ WithAmount(amountToSend)
+
+ res, _, err := contractutils.CallContractAndCheckLogs(is.network.GetContext(), is.network.App, cArgs, execRevertedCheck)
+ Expect(err).NotTo(BeNil())
+ // contract balance should remain unchanged
+ denomFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount))
+
+ contractBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), revertContractAddr.Bytes(), is.bondDenom)
+ Expect(contractBalance.Amount).To(Equal(math.ZeroInt()))
+
+ senderFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+ Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(math.NewInt((res.GasUsed * gasPrice.Int64())))))
+ },
+ Entry("revert before", true, false),
+ Entry("revert after", false, true),
+ )
+ It("it should send token transfer and send from WEVMOS contract", func() {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetAddr(1)
+ totalToSend := int64(350)
+ denomInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ senderInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+
+ cArgs := defaultCallArgs.
+ WithPrivKey(sender.Priv).
+ WithMethodName("testTransferAndSend").
+ WithArgs(
+ receiver,
+ big.NewInt(100),
+ big.NewInt(100),
+ big.NewInt(150),
+ false,
+ false,
+ ).
+ WithAmount(big.NewInt(totalToSend))
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer,
+ )
+ res, _, err := contractutils.CallContractAndCheckLogs(is.network.GetContext(), is.network.App, cArgs, transferCheck)
+ Expect(err).To(BeNil())
+ // contract balance should remain unchanged
+ denomFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(totalToSend))))
+
+ contractBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), revertContractAddr.Bytes(), is.bondDenom)
+ Expect(contractBalance.Amount).To(Equal(math.ZeroInt()))
+
+ senderFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+ denomSpent := math.NewInt((res.GasUsed*gasPrice.Int64() + totalToSend))
+ Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent)))
+ },
+ )
+ DescribeTable("it should revert token transfer and send from WEVMOS contract", func(before bool, after bool) {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetAddr(1)
+ denomInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ senderInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+
+ cArgs := defaultCallArgs.
+ WithPrivKey(sender.Priv).
+ WithMethodName("testTransferAndSend").
+ WithArgs(
+ receiver,
+ big.NewInt(100),
+ big.NewInt(100),
+ big.NewInt(100),
+ before,
+ after,
+ ).
+ WithAmount(big.NewInt(300))
+
+ res, _, err := contractutils.CallContractAndCheckLogs(is.network.GetContext(), is.network.App, cArgs, execRevertedCheck)
+ Expect(err).NotTo(BeNil())
+ // contract balance should remain unchanged
+ denomFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount))
+
+ contractBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), revertContractAddr.Bytes(), is.bondDenom)
+ Expect(contractBalance.Amount).To(Equal(math.ZeroInt()))
+
+ senderFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+ Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(math.NewInt((res.GasUsed * gasPrice.Int64())))))
+ },
+ Entry("revert before", true, false),
+ Entry("revert after", false, true),
+ )
+ It("revert when transfer with try", func() {
+ sender := is.keyring.GetKey(0)
+ receiver := is.keyring.GetAddr(1)
+ amountToSend := big.NewInt(100)
+ denomInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ senderInitialBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+
+ cArgs := defaultCallArgs.
+ WithPrivKey(sender.Priv).
+ WithMethodName("transfersWithTry").
+ WithArgs(
+ receiver,
+ amountToSend,
+ amountToSend,
+ ).
+ WithAmount(big.NewInt(200))
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer,
+ )
+ res, _, err := contractutils.CallContractAndCheckLogs(is.network.GetContext(), is.network.App, cArgs, transferCheck)
+ Expect(err).To(BeNil())
+ denomFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), receiver.Bytes(), is.bondDenom)
+ Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(amountToSend.Int64()))))
+
+ contractBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), revertContractAddr.Bytes(), is.bondDenom)
+ Expect(contractBalance.Amount.Int64()).To(Equal(amountToSend.Int64()))
+
+ senderFinalBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), sender.AccAddr, is.bondDenom)
+ denomSpent := math.NewInt((res.GasUsed*gasPrice.Int64() + amountToSend.Int64() + amountToSend.Int64()))
+ Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent)))
+ })
+ })
+ })
+
+ When("transferring tokens from another account", func() {
+ Context("in a direct call to the token contract", func() {
+ DescribeTable("it should transfer tokens from another account with a sufficient approval set", func(callType CallType) {
+ owner := is.keyring.GetKey(0)
+ spender := is.keyring.GetKey(1)
+ receiver := utiltx.GenerateAddress()
+
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins)
+
+ // Set allowance
+ is.setupSendAuthzForContract(callType, contractsData, spender.Addr, owner.Priv, transferCoins)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ erc20.TransferFromMethod,
+ owner.Addr, receiver, transferCoins[0].Amount.BigInt(),
+ )
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer,
+ auth.EventTypeApproval,
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, transferCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod)
+ is.ExpectBalancesForContract(
+ callType, contractsData,
+ []ExpectedBalance{
+ {address: owner.AccAddr, expCoins: fundCoins.Sub(transferCoins...)},
+ {address: receiver.Bytes(), expCoins: transferCoins},
+ },
+ )
+
+ // Check that the allowance was removed since we authorized only the transferred amount
+ is.ExpectNoSendAuthzForContract(
+ callType, contractsData,
+ spender.Addr, owner.Addr,
+ )
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the contract call here because this test is for direct calls only
+
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ When("the spender is the same as the sender", func() {
+ It("should transfer funds without the need for an approval when calling the EVM extension", func() {
+ owner := is.keyring.GetKey(0)
+ spender := owner
+ receiver := utiltx.GenerateAddress()
+
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Fund account with some tokens
+ is.fundWithTokens(directCall, contractsData, owner.Addr, fundCoins)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ directCall, contractsData,
+ erc20.TransferFromMethod,
+ owner.Addr, receiver, transferCoins[0].Amount.BigInt(),
+ )
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer, auth.EventTypeApproval,
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, transferCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, erc20.TransferMethod)
+ is.ExpectBalancesForContract(
+ directCall, contractsData,
+ []ExpectedBalance{
+ {address: owner.AccAddr, expCoins: fundCoins.Sub(transferCoins...)},
+ {address: receiver.Bytes(), expCoins: transferCoins},
+ },
+ )
+ })
+
+ DescribeTable("it should transfer funds from the own account in case sufficient approval is set", func(callType CallType) {
+ owner := is.keyring.GetKey(0)
+ receiver := utiltx.GenerateAddress()
+
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins)
+
+ // NOTE: Here we set up the allowance using the contract calls instead of the helper utils,
+ // because the `MsgGrant` used there doesn't allow the sender to be the same as the spender,
+ // but the ERC20 contracts do.
+ txArgs, approveArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ auth.ApproveMethod,
+ owner.Addr, transferCoins[0].Amount.BigInt(),
+ )
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, _, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ owner.Addr, owner.Addr, transferCoins,
+ )
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ erc20.TransferFromMethod,
+ owner.Addr, receiver, transferCoins[0].Amount.BigInt(),
+ )
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer,
+ auth.EventTypeApproval,
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, transferArgs, transferCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod)
+ is.ExpectBalancesForContract(
+ callType, contractsData,
+ []ExpectedBalance{
+ {address: owner.AccAddr, expCoins: fundCoins.Sub(transferCoins...)},
+ {address: receiver.Bytes(), expCoins: transferCoins},
+ },
+ )
+
+ // Check that the allowance was removed since we authorized only the transferred amount
+ // FIXME: This is not working for the case where we transfer from the own account
+ // because the allowance is not removed on the SDK side.
+ is.ExpectNoSendAuthzForContract(
+ callType, contractsData,
+ owner.Addr, owner.Addr,
+ )
+ },
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+
+ DescribeTable("it should return an error when the spender does not have enough allowance", func(callType CallType) {
+ owner := is.keyring.GetKey(0)
+ spender := is.keyring.GetKey(1)
+ receiver := utiltx.GenerateAddress()
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+ transferCoin := sdk.NewInt64Coin(is.tokenDenom, 200)
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins)
+ // Set allowance
+ is.setupSendAuthzForContract(
+ callType, contractsData,
+ spender.Addr, owner.Priv, authzCoins,
+ )
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ erc20.TransferFromMethod,
+ owner.Addr, receiver, transferCoin.Amount.BigInt(),
+ )
+
+ insufficientAllowanceCheck := failCheck.WithErrContains(erc20.ErrInsufficientAllowance.Error())
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, insufficientAllowanceCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the contract call here because this test case only covers direct calls
+
+ Entry(" - through erc20 contract", erc20Call),
+
+ // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("it should return an error if there is no allowance set", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ from := is.keyring.GetKey(1)
+ receiver := utiltx.GenerateAddress()
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoin := sdk.NewInt64Coin(is.tokenDenom, 100)
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, from.Addr, fundCoins)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ erc20.TransferFromMethod,
+ from.Addr, receiver, transferCoin.Amount.BigInt(),
+ )
+
+ insufficientAllowanceCheck := failCheck.WithErrContains(
+ erc20.ErrInsufficientAllowance.Error(),
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientAllowanceCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the contract call here because this test case only covers direct calls
+
+ Entry(" - through erc20 contract", erc20Call),
+
+ // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("it should return an error if the sender does not have enough tokens", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ from := is.keyring.GetKey(1)
+ receiver := utiltx.GenerateAddress()
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)}
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, from.Addr, fundCoins)
+
+ // Set allowance
+ is.setupSendAuthzForContract(
+ callType, contractsData,
+ sender.Addr, from.Priv, transferCoins,
+ )
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferFromMethod, from.Addr, receiver, transferCoins[0].Amount.BigInt())
+
+ insufficientBalanceCheck := failCheck.WithErrContains(
+ erc20.ErrTransferAmountExceedsBalance.Error(),
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the contract call here because this test case only covers direct calls
+
+ Entry(" - through erc20 contract", erc20Call),
+
+ // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+
+ Context("in a call from another smart contract to the token contract", func() {
+ DescribeTable("it should transfer tokens with a sufficient approval set", func(callType CallType) {
+ owner := is.keyring.GetKey(0)
+ receiver := utiltx.GenerateAddress()
+ fundCoin := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // NOTE: the spender will be the contract address
+ spender := contractsData.GetContractData(callType).Address
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, owner.Addr, fundCoin)
+
+ // Set allowance
+ is.setupSendAuthzForContract(
+ callType, contractsData,
+ spender, owner.Priv, transferCoins,
+ )
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ erc20.TransferFromMethod,
+ owner.Addr, receiver, transferCoins[0].Amount.BigInt(),
+ )
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer,
+ auth.EventTypeApproval,
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, transferArgs, transferCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod)
+ is.ExpectBalancesForContract(
+ callType, contractsData,
+ []ExpectedBalance{
+ {address: owner.AccAddr, expCoins: fundCoin.Sub(transferCoins...)},
+ {address: receiver.Bytes(), expCoins: transferCoins},
+ },
+ )
+
+ // Check that the allowance was removed since we authorized only the transferred amount
+ is.ExpectNoSendAuthzForContract(
+ callType, contractsData,
+ spender, owner.Addr,
+ )
+ },
+ // Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ // NOTE: we are not passing the erc20 contract call here because this is supposed to
+ // test external contract calls
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should transfer funds with a sufficient allowance and triggered from another account", func(callType CallType) {
+ msgSender := is.keyring.GetKey(0)
+ owner := is.keyring.GetKey(1)
+ receiver := utiltx.GenerateAddress()
+
+ // NOTE: the spender will be the contract address
+ spender := contractsData.GetContractData(callType).Address
+
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)}
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins)
+
+ // Set allowance
+ is.setupSendAuthzForContract(
+ callType, contractsData,
+ spender, owner.Priv, transferCoins,
+ )
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ erc20.TransferFromMethod,
+ owner.Addr, receiver, transferCoins[0].Amount.BigInt(),
+ )
+
+ transferCheck := passCheck.WithExpEvents(
+ erc20.EventTypeTransfer,
+ auth.EventTypeApproval,
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(msgSender.Priv, txArgs, transferArgs, transferCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod)
+ is.ExpectBalancesForContract(
+ callType, contractsData,
+ []ExpectedBalance{
+ {address: owner.AccAddr, expCoins: fundCoins.Sub(transferCoins...)},
+ {address: receiver.Bytes(), expCoins: transferCoins},
+ },
+ )
+
+ // Check that the allowance was removed since we authorized only the transferred amount
+ is.ExpectNoSendAuthzForContract(
+ callType, contractsData,
+ spender, owner.Addr,
+ )
+ },
+ // NOTE: we are not passing the direct call here because this test is specific to the contract calls
+
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should return an error when the spender does not have enough allowance", func(callType CallType) {
+ from := is.keyring.GetKey(0)
+ receiver := utiltx.GenerateAddress()
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 400)}
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+ transferCoin := sdk.NewInt64Coin(is.tokenDenom, 300)
+
+ // NOTE: the spender will be the contract address
+ spender := contractsData.GetContractData(callType).Address
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, from.Addr, fundCoins)
+
+ // Set allowance
+ is.setupSendAuthzForContract(callType, contractsData, spender, from.Priv, authzCoins)
+
+ // Transfer tokens
+ txArgs, transferArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ erc20.TransferFromMethod,
+ from.Addr, receiver, transferCoin.Amount.BigInt(),
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(from.Priv, txArgs, transferArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ // NOTE: we are not passing the direct call here because this test is for contract calls only
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+ })
+ })
+
+ When("querying balance", func() {
+ DescribeTable("it should return an existing balance", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ expBalance := big.NewInt(100)
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, expBalance.Int64())}
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins)
+
+ // Query the balance
+ txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, sender.Addr)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balance *big.Int
+ err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(balance).To(Equal(expBalance), "expected different balance")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should return zero if balance only exists for other tokens", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ address := utiltx.GenerateAddress()
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetDenom(), 100)}
+
+ // Fund account with some tokens
+ err := is.network.FundAccount(sender.AccAddr, fundCoins)
+ Expect(err).ToNot(HaveOccurred(), "failed to fund account")
+
+ // Query the balance
+ txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, address)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balance *big.Int
+ err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(balance.Int64()).To(BeZero(), "expected zero balance")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contracts
+ // only support the actual token denomination and don't know of other balances.
+ )
+
+ DescribeTable("it should return zero if the account does not exist", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ address := utiltx.GenerateAddress()
+
+ // Query the balance
+ txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, address)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var balance *big.Int
+ err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(balance.Int64()).To(BeZero(), "expected zero balance")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+ })
+
+ When("querying allowance", func() {
+ DescribeTable("it should return an existing allowance", func(callType CallType) {
+ grantee := utiltx.GenerateAddress()
+ granter := is.keyring.GetKey(0)
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ is.setupSendAuthzForContract(callType, contractsData, grantee, granter.Priv, authzCoins)
+
+ txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, auth.AllowanceMethod, granter.Addr, grantee)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, allowanceArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var allowance *big.Int
+ err = is.precompile.UnpackIntoInterface(&allowance, auth.AllowanceMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(allowance).To(Equal(authzCoins[0].Amount.BigInt()), "expected different allowance")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ When("querying the allowance for the own address", func() {
+ // NOTE: We differ in behavior from the ERC20 calls here, because the full logic for approving,
+ // querying allowance and reducing allowance on a transferFrom transaction is not possible without
+ // changes to the Cosmos SDK.
+ //
+ // For reference see this comment: https://github.com/evmos/evmos/pull/2088#discussion_r1407646217
+ It("should return the maxUint256 value when calling the EVM extension", func() {
+ grantee := is.keyring.GetAddr(0)
+ granter := is.keyring.GetKey(0)
+
+ txArgs, allowanceArgs := is.getTxAndCallArgs(directCall, contractsData, auth.AllowanceMethod, grantee, grantee)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, allowanceArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var allowance *big.Int
+ err = is.precompile.UnpackIntoInterface(&allowance, auth.AllowanceMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(allowance).To(Equal(abi.MaxUint256), "expected different allowance")
+ })
+
+ // NOTE: Since it's possible to set an allowance for the own address with the Solidity ERC20 contracts,
+ // we describe this case here for completion purposes, to describe the difference in behavior.
+ DescribeTable("should return the actual allowance value when calling the ERC20 contract", func(callType CallType) {
+ granter := is.keyring.GetKey(0)
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ is.setupSendAuthzForContract(callType, contractsData, granter.Addr, granter.Priv, authzCoins)
+
+ txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, auth.AllowanceMethod, granter.Addr, granter.Addr)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, allowanceArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var allowance *big.Int
+ err = is.precompile.UnpackIntoInterface(&allowance, auth.AllowanceMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(allowance).To(Equal(authzCoins.AmountOf(is.tokenDenom).BigInt()), "expected different allowance")
+ },
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+
+ DescribeTable("it should return zero if no allowance exists", func(callType CallType) {
+ grantee := is.keyring.GetAddr(1)
+ granter := is.keyring.GetKey(0)
+
+ txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, auth.AllowanceMethod, granter.Addr, grantee)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, allowanceArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var allowance *big.Int
+ err = is.precompile.UnpackIntoInterface(&allowance, auth.AllowanceMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(allowance.Int64()).To(BeZero(), "expected zero allowance")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should return zero if an allowance exists for other tokens", func(callType CallType) {
+ grantee := is.keyring.GetKey(1)
+ granter := is.keyring.GetKey(0)
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetDenom(), 100)}
+
+ is.setupSendAuthz(grantee.AccAddr, granter.Priv, authzCoins)
+
+ txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, auth.AllowanceMethod, granter.Addr, grantee.Addr)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, allowanceArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var allowance *big.Int
+ err = is.precompile.UnpackIntoInterface(&allowance, auth.AllowanceMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(allowance.Int64()).To(BeZero(), "expected zero allowance")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("it should return zero if the account does not exist", func(callType CallType) {
+ grantee := utiltx.GenerateAddress()
+ granter := is.keyring.GetKey(0)
+
+ txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, auth.AllowanceMethod, granter.Addr, grantee)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, allowanceArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var allowance *big.Int
+ err = is.precompile.UnpackIntoInterface(&allowance, auth.AllowanceMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(allowance.Int64()).To(BeZero(), "expected zero allowance")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+ })
+
+ When("querying total supply", func() {
+ DescribeTable("it should return the total supply", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ expSupply := big.NewInt(100)
+ fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, expSupply.Int64())}
+
+ // Fund account with some tokens
+ is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins)
+
+ // Query the balance
+ txArgs, supplyArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TotalSupplyMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var supply *big.Int
+ err = is.precompile.UnpackIntoInterface(&supply, erc20.TotalSupplyMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(supply).To(Equal(expSupply), "expected different supply")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should return zero if no tokens exist", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ txArgs, supplyArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TotalSupplyMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, supplyArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var supply *big.Int
+ err = is.precompile.UnpackIntoInterface(&supply, erc20.TotalSupplyMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(supply.Int64()).To(BeZero(), "expected zero supply")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+ })
+
+ When("approving an allowance", func() {
+ Context("in a call to the token contract", func() {
+ DescribeTable("it should approve an allowance", func(callType CallType) {
+ grantee := is.keyring.GetKey(0)
+ granter := is.keyring.GetKey(1)
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)}
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, transferCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ grantee.Addr, granter.Addr, transferCoins,
+ )
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("it should add a new spend limit to an existing allowance with a different token", func(callType CallType) {
+ grantee := is.keyring.GetKey(1)
+ granter := is.keyring.GetKey(0)
+ bondCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetDenom(), 200)}
+ tokenCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // set up a previous authorization
+ is.setupSendAuthz(grantee.AccAddr, granter.Priv, bondCoins)
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, tokenCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ // Check allowance contains both spend limits
+ is.expectSendAuthz(grantee.AccAddr, granter.AccAddr, bondCoins.Add(tokenCoins...))
+ },
+ Entry(" - direct call", directCall),
+
+ // NOTE 2: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("it should set the new spend limit for an existing allowance with the same token", func(callType CallType) {
+ grantee := is.keyring.GetKey(1)
+ granter := is.keyring.GetKey(0)
+ bondCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetDenom(), 200)}
+ tokenCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+ doubleTokenCoin := sdk.NewInt64Coin(is.tokenDenom, 200)
+
+ // set up a previous authorization
+ is.setupSendAuthz(grantee.AccAddr, granter.Priv, bondCoins.Add(doubleTokenCoin))
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, tokenCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ // Check allowance contains both spend limits
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, bondCoins.Add(tokenCoins...))
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("it should remove the token from the spend limit of an existing authorization when approving zero", func(callType CallType) {
+ grantee := is.keyring.GetKey(1)
+ granter := is.keyring.GetKey(0)
+ bondCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetDenom(), 200)}
+ tokenCoin := sdk.NewInt64Coin(is.tokenDenom, 100)
+
+ // set up a previous authorization
+ is.setupSendAuthz(grantee.AccAddr, granter.Priv, bondCoins.Add(tokenCoin))
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, common.Big0)
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ // Check allowance contains only the spend limit in network denomination
+ is.expectSendAuthz(grantee.AccAddr, granter.AccAddr, bondCoins)
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("it should delete the authorization when approving zero with no other spend limits", func(callType CallType) {
+ grantee := is.keyring.GetKey(1)
+ granter := is.keyring.GetKey(0)
+ tokenCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // set up a previous authorization
+ is.setupSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Priv, tokenCoins)
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, common.Big0)
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ // Check allowance was deleted
+ is.expectNoSendAuthz(grantee.AccAddr, granter.AccAddr)
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("it should no-op if approving 0 and no allowance exists", func(callType CallType) {
+ grantee := is.keyring.GetKey(1)
+ granter := is.keyring.GetKey(0)
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, common.Big0)
+
+ // We are expecting an approval to be made, but no authorization stored since it's 0
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ // Check still no authorization exists
+ is.ExpectNoSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr)
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ When("the grantee is the same as the granter", func() {
+ // NOTE: We differ in behavior from the ERC20 calls here, because the full logic for approving,
+ // querying allowance and reducing allowance on a transferFrom transaction is not possible without
+ // changes to the Cosmos SDK.
+ //
+ // For reference see this comment: https://github.com/evmos/evmos/pull/2088#discussion_r1407646217
+ It("should return an error when calling the EVM extension", func() {
+ grantee := is.keyring.GetKey(0)
+ granter := is.keyring.GetKey(0)
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(
+ directCall, contractsData,
+ auth.ApproveMethod,
+ grantee.Addr, authzCoins[0].Amount.BigInt(),
+ )
+
+ spenderIsOwnerCheck := failCheck.WithErrContains(erc20.ErrSpenderIsOwner.Error())
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, spenderIsOwnerCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ is.ExpectNoSendAuthzForContract(
+ directCall, contractsData,
+ grantee.Addr, granter.Addr,
+ )
+ })
+
+ DescribeTable("it should create an allowance", func(callType CallType) {
+ grantee := is.keyring.GetKey(0)
+ granter := is.keyring.GetKey(0)
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ auth.ApproveMethod,
+ grantee.Addr, authzCoins[0].Amount.BigInt(),
+ )
+
+ approvalCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approvalCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ grantee.Addr, granter.Addr, authzCoins,
+ )
+ },
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+
+ DescribeTable("it should return an error if approving 0 and allowance only exists for other tokens", func(callType CallType) {
+ grantee := is.keyring.GetKey(1)
+ granter := is.keyring.GetKey(0)
+ bondCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetDenom(), 200)}
+
+ // set up a previous authorization
+ is.setupSendAuthz(grantee.AccAddr, granter.Priv, bondCoins)
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, common.Big0)
+
+ notFoundCheck := failCheck.WithErrContains(
+ fmt.Sprintf(erc20.ErrNoAllowanceForToken, is.tokenDenom),
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, notFoundCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+ })
+
+ // NOTE: We have to split the tests for contract calls into a separate context because
+ // when approving through a smart contract, the approval is created between the contract address and the
+ // grantee, instead of the sender address and the grantee.
+ Context("in a contract call", func() {
+ DescribeTable("it should approve an allowance", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ grantee := is.keyring.GetKey(1)
+ granter := contractsData.GetContractData(callType).Address // the granter will be the contract address
+ transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)}
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, transferCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ // Check allowance
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ grantee.Addr, granter, transferCoins,
+ )
+ },
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should set the new spend limit for an existing allowance with the same token", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ grantee := is.keyring.GetKey(1)
+ granter := contractsData.GetContractData(callType).Address // the granter will be the contract address
+ initialAmount := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+ newAmount := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)}
+
+ // Set up a first approval
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, initialAmount[0].Amount.BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+
+ // Set up a second approval which should overwrite the initial one
+ txArgs, approveArgs = is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, newAmount[0].Amount.BigInt())
+ approveCheck = passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err = is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+
+ // Check allowance has been updated
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ grantee.Addr, granter, newAmount,
+ )
+ },
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should delete the authorization when approving zero with no other spend limits", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ grantee := is.keyring.GetKey(1)
+ granter := contractsData.GetContractData(callType).Address // the granter will be the contract address
+ tokenCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // set up a previous authorization
+ //
+ // TODO: refactor using helper
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, tokenCoins[0].Amount.BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+
+ // Approve allowance
+ txArgs, approveArgs = is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, common.Big0)
+ _, ethRes, err = is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+
+ // Check allowance was deleted from the keeper / is returning 0 for smart contracts
+ is.ExpectNoSendAuthzForContract(callType, contractsData, grantee.Addr, granter)
+ },
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ DescribeTable("it should no-op if approving 0 and no allowance exists", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ grantee := is.keyring.GetKey(1)
+ granter := contractsData.GetContractData(callType).Address // the granter will be the contract address
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, auth.ApproveMethod, grantee.Addr, common.Big0)
+
+ // We are expecting an approval event to be emitted, but no authorization to be stored
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ // Check still no authorization exists
+ is.ExpectNoSendAuthzForContract(callType, contractsData, grantee.Addr, granter)
+ },
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+
+ When("the grantee is the same as the granter", func() {
+ // NOTE: We differ in behavior from the ERC20 calls here, because the full logic for approving,
+ // querying allowance and reducing allowance on a transferFrom transaction is not possible without
+ // changes to the Cosmos SDK.
+ //
+ // For reference see this comment: https://github.com/evmos/evmos/pull/2088#discussion_r1407646217
+ It("should return an error when calling the EVM extension", func() {
+ callType := contractCall
+ sender := is.keyring.GetKey(0)
+ granter := contractsData.GetContractData(callType).Address // the granter will be the contract address
+ grantee := granter
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ auth.ApproveMethod,
+ grantee, authzCoins[0].Amount.BigInt(),
+ )
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ is.ExpectNoSendAuthzForContract(
+ callType, contractsData,
+ grantee, granter,
+ )
+ })
+
+ DescribeTable("it should create an allowance when calling an ERC20 Solidity contract", func(callType CallType) {
+ sender := is.keyring.GetKey(0)
+ granter := contractsData.GetContractData(callType).Address // the granter will be the contract address
+ grantee := granter
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // Approve allowance
+ txArgs, approveArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ auth.ApproveMethod,
+ grantee, authzCoins[0].Amount.BigInt(),
+ )
+
+ approvalCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approvalCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ grantee, granter, authzCoins,
+ )
+ },
+ Entry(" - through erc20 v5 caller contract", erc20V5CallerCall),
+ )
+ })
+ })
+ })
+ })
+
+ Context("metadata query -", func() {
+ Context("for a token without registered metadata", func() {
+ BeforeEach(func() {
+ // Deploy ERC20NoMetadata contract for this test
+ erc20NoMetadataContract, err := testdata.LoadERC20NoMetadataContract()
+ Expect(err).ToNot(HaveOccurred(), "failed to load contract")
+
+ erc20NoMetadataAddr, err := is.factory.DeployContract(
+ is.keyring.GetPrivKey(0),
+ evmtypes.EvmTxArgs{},
+ factory.ContractDeploymentData{
+ Contract: erc20NoMetadataContract,
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy contract")
+
+ // NOTE: update the address but leave the ABI as it is, so that the ABI includes
+ // the metadata methods but the contract doesn't have them.
+ contractsData.contractData[erc20Call] = ContractData{
+ Address: erc20NoMetadataAddr,
+ ABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ }
+ })
+
+ DescribeTable("querying the name should return an error", func(callType CallType) {
+ txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors
+ )
+
+ DescribeTable("querying the symbol should return an error", func(callType CallType) {
+ txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors
+ )
+
+ DescribeTable("querying the decimals should return an error", func(callType CallType) {
+ txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors
+ )
+ })
+
+ Context("for a token with available metadata", func() {
+ const (
+ denom = "axmpl"
+ expSymbol = "Xmpl"
+ expDecimals = uint8(18)
+ )
+
+ var (
+ erc20Addr common.Address
+ expName string
+ )
+
+ BeforeEach(func() {
+ erc20Addr = contractsData.GetContractData(erc20V5Call).Address
+ expName = erc20types.CreateDenom(erc20Addr.String())
+
+ // Register ERC20 token pair for this test
+ tokenPair, err := utils.RegisterERC20(is.factory, is.network, utils.ERC20RegistrationData{
+ Address: erc20Addr,
+ Denom: denom,
+ ProposerPriv: is.keyring.GetPrivKey(0),
+ })
+ Expect(err).ToNot(HaveOccurred(), "failed to register ERC20 token")
+
+ // overwrite the other precompile with this one, so that the test utils like is.getTxAndCallArgs still work.
+ is.precompile, err = setupERC20PrecompileForTokenPair(*is.network, tokenPair)
+ Expect(err).ToNot(HaveOccurred(), "failed to set up erc20 precompile")
+
+ // update this in the global contractsData
+ contractsData.contractData[directCall] = ContractData{
+ Address: is.precompile.Address(),
+ ABI: is.precompile.ABI,
+ }
+
+ // Deploy contract calling the ERC20 precompile
+ callerAddr, err := is.factory.DeployContract(
+ is.keyring.GetPrivKey(0),
+ evmtypes.EvmTxArgs{},
+ factory.ContractDeploymentData{
+ Contract: allowanceCallerContract,
+ ConstructorArgs: []interface{}{
+ is.precompile.Address(),
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy contract")
+
+ contractsData.contractData[contractCall] = ContractData{
+ Address: callerAddr,
+ ABI: allowanceCallerContract.ABI,
+ }
+ })
+
+ DescribeTable("querying the name should return the name", func(callType CallType) {
+ txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var name string
+ err = is.precompile.UnpackIntoInterface(&name, erc20.NameMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(name).To(Equal(expName), "expected different name")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("querying the symbol should return the symbol", func(callType CallType) {
+ txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var symbol string
+ err = is.precompile.UnpackIntoInterface(&symbol, erc20.SymbolMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(symbol).To(Equal(expSymbol), "expected different symbol")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("querying the decimals should return the decimals", func(callType CallType) {
+ txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ var decimals uint8
+ err = is.precompile.UnpackIntoInterface(&decimals, erc20.DecimalsMethod, ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack result")
+ Expect(decimals).To(Equal(expDecimals), "expected different decimals")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through contract", contractCall),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+ })
+
+ Context("allowance adjustments -", func() {
+ var (
+ grantee keyring.Key
+ granter keyring.Key
+ )
+
+ BeforeEach(func() {
+ // Deploying the contract which has the increase / decrease allowance methods
+ contractAddr, err := is.factory.DeployContract(
+ is.keyring.GetPrivKey(0),
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: allowanceCallerContract,
+ ConstructorArgs: []interface{}{is.precompile.Address()},
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy contract")
+
+ contractsData.contractData[erc20CallerCall] = ContractData{
+ Address: contractAddr,
+ ABI: allowanceCallerContract.ABI,
+ }
+
+ grantee = is.keyring.GetKey(0)
+ granter = is.keyring.GetKey(1)
+ })
+
+ When("the grantee is the same as the granter", func() {
+ // NOTE: We differ in behavior from the ERC20 calls here, because the full logic for approving,
+ // querying allowance and reducing allowance on a transferFrom transaction is not possible without
+ // changes to the Cosmos SDK.
+ //
+ // For reference see this comment: https://github.com/evmos/evmos/pull/2088#discussion_r1407646217
+ Context("increasing allowance", func() {
+ It("should return an error when calling the EVM extension", func() {
+ granter := is.keyring.GetKey(0)
+ grantee := granter
+
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(
+ directCall, contractsData,
+ auth.IncreaseAllowanceMethod,
+ grantee.Addr, authzCoins[0].Amount.BigInt(),
+ )
+
+ spenderIsOwnerCheck := failCheck.WithErrContains(erc20.ErrSpenderIsOwner.Error())
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, spenderIsOwnerCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ is.ExpectNoSendAuthzForContract(
+ directCall, contractsData,
+ grantee.Addr, granter.Addr,
+ )
+ })
+
+ DescribeTable("it should create an allowance if none existed before", func(callType CallType) {
+ granter := is.keyring.GetKey(0)
+ grantee := granter
+
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ auth.IncreaseAllowanceMethod,
+ grantee.Addr, authzCoins[0].Amount.BigInt(),
+ )
+
+ approvalCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, approvalCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.IncreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ grantee.Addr, granter.Addr, authzCoins,
+ )
+ },
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+
+ Context("decreasing allowance", func() {
+ It("should return an error when calling the EVM extension", func() {
+ granter := is.keyring.GetKey(0)
+ grantee := granter
+
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(
+ directCall, contractsData,
+ auth.DecreaseAllowanceMethod,
+ grantee.Addr, authzCoins[0].Amount.BigInt(),
+ )
+
+ spenderIsOwnerCheck := failCheck.WithErrContains(erc20.ErrSpenderIsOwner.Error())
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, spenderIsOwnerCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ is.ExpectNoSendAuthzForContract(
+ directCall, contractsData,
+ grantee.Addr, granter.Addr,
+ )
+ })
+
+ DescribeTable("it should decrease an existing allowance", func(callType CallType) {
+ granter := is.keyring.GetKey(0)
+ grantee := granter
+
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)}
+ decreaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ is.setupSendAuthzForContract(
+ callType, contractsData,
+ grantee.Addr, granter.Priv, authzCoins,
+ )
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(
+ callType, contractsData,
+ auth.DecreaseAllowanceMethod,
+ grantee.Addr, decreaseCoins[0].Amount.BigInt(),
+ )
+
+ approvalCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, approvalCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.IncreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(
+ callType, contractsData,
+ grantee.Addr, granter.Addr, decreaseCoins,
+ )
+ },
+ Entry(" - through erc20 contract", erc20Call),
+ Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+ })
+
+ When("no allowance exists", func() {
+ DescribeTable("decreasing the allowance should return an error", func(callType CallType) {
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, authzCoins[0].Amount.BigInt())
+
+ notFoundCheck := execRevertedCheck
+ if callType == directCall {
+ notFoundCheck = failCheck.WithErrContains(
+ fmt.Sprintf(auth.ErrAuthzDoesNotExistOrExpired, erc20.SendMsgURL, grantee.Addr.String()),
+ )
+ }
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, notFoundCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ // NOTE: The ERC20 V5 contract does not contain these methods
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ Entry(" - contract call", contractCall),
+ Entry(" - through erc20 caller contract", erc20CallerCall),
+ )
+
+ // NOTE: We have to split between direct and contract calls here because the ERC20 behavior
+ // for approvals is different, so we expect different authorizations here
+ Context("in direct calls", func() {
+ DescribeTable("increasing the allowance should create a new authorization", func(callType CallType) {
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, authzCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.ApproveMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins)
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ // NOTE: The ERC20 V5 contract does not contain these methods
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+
+ Context("in contract calls", func() {
+ DescribeTable("increasing the allowance should create a new authorization", func(callType CallType) {
+ contractAddr := contractsData.GetContractData(callType).Address
+ authzCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, authzCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.IncreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, contractAddr, authzCoins)
+ },
+ Entry(" - contract call", contractCall),
+ Entry(" - through erc20 caller contract", erc20CallerCall),
+ )
+ })
+ })
+
+ When("an allowance exists for other tokens", func() {
+ var bondCoins sdk.Coins
+
+ BeforeEach(func() {
+ bondCoins = sdk.Coins{sdk.NewInt64Coin(is.network.GetDenom(), 200)}
+ is.setupSendAuthz(grantee.AccAddr, granter.Priv, bondCoins)
+ })
+
+ DescribeTable("increasing the allowance should add the token to the spend limit", func(callType CallType) {
+ increaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, increaseCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.IncreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, bondCoins.Add(increaseCoins...))
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("decreasing the allowance should return an error", func(callType CallType) {
+ decreaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, decreaseCoins[0].Amount.BigInt())
+
+ notFoundCheck := execRevertedCheck
+ if callType == directCall {
+ notFoundCheck = failCheck.WithErrContains(
+ fmt.Sprintf(erc20.ErrNoAllowanceForToken, is.tokenDenom),
+ )
+ }
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, notFoundCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+ })
+
+ When("an allowance exists for the same token", func() {
+ var authzCoins sdk.Coins
+
+ BeforeEach(func() {
+ authzCoins = sdk.NewCoins(
+ sdk.NewInt64Coin(is.network.GetDenom(), 100),
+ sdk.NewInt64Coin(is.tokenDenom, 200),
+ )
+
+ is.setupSendAuthz(grantee.AccAddr, granter.Priv, authzCoins)
+ })
+
+ DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) {
+ increaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, increaseCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.IncreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins.Add(increaseCoins...))
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) {
+ decreaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, decreaseCoins[0].Amount.BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.DecreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins.Sub(decreaseCoins...))
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) {
+ maxUint256Coins := sdk.Coins{sdk.NewCoin(is.tokenDenom, math.NewIntFromBigInt(abi.MaxUint256))}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, maxUint256Coins[0].Amount.BigInt())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("decreasing the allowance to zero should remove the token from the spend limit", func(callType CallType) {
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, authzCoins.AmountOf(is.tokenDenom).BigInt())
+
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.DecreaseAllowanceMethod)
+
+ // Check that only the spend limit in the network denomination remains
+ bondDenom := is.network.GetDenom()
+ expCoins := sdk.Coins{sdk.NewCoin(bondDenom, authzCoins.AmountOf(bondDenom))}
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, expCoins)
+ },
+ Entry(" - direct call", directCall),
+ // NOTE: we are not passing the erc20 contract call here because the ERC20 contract
+ // only supports the actual token denomination and doesn't know of other allowances.
+ )
+
+ DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) {
+ decreaseCoins := sdk.Coins{sdk.NewCoin(is.tokenDenom, authzCoins.AmountOf(is.tokenDenom).AddRaw(100))}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, decreaseCoins[0].Amount.BigInt())
+ belowZeroCheck := failCheck.WithErrContains(erc20.ErrDecreasedAllowanceBelowZero.Error())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, belowZeroCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ // Check that the allowance was not changed
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins)
+ },
+ Entry(" - direct call", directCall),
+ )
+ })
+
+ When("an allowance exists for only the same token", func() {
+ // NOTE: we have to split between direct and contract calls here because the ERC20 contract
+ // handles the allowance differently by creating an approval between the contract and the grantee, instead
+ // of the message sender and the grantee, so we expect different authorizations.
+ Context("in direct calls", func() {
+ var authzCoins sdk.Coins
+
+ BeforeEach(func() {
+ authzCoins = sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ // NOTE: We set up the standard authorization here for the authz keeper and then also
+ // set up the authorization for the ERC20 contract, so that we can test both.
+ is.setupSendAuthzForContract(directCall, contractsData, grantee.Addr, granter.Priv, authzCoins)
+ is.setupSendAuthzForContract(erc20Call, contractsData, grantee.Addr, granter.Priv, authzCoins)
+ })
+
+ DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) {
+ increaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, increaseCoins[0].Amount.BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.DecreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins.Add(increaseCoins...))
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ // NOTE: The ERC20 V5 contract does not contain these methods
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) {
+ decreaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 50)}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, decreaseCoins[0].Amount.BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.DecreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins.Sub(decreaseCoins...))
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ // NOTE: The ERC20 V5 contract does not contain these methods
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("decreasing the allowance to zero should delete the authorization", func(callType CallType) {
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, authzCoins.AmountOf(is.tokenDenom).BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.DecreaseAllowanceMethod)
+ is.ExpectNoSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr)
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ // NOTE: The ERC20 V5 contract does not contain these methods
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) {
+ decreaseAmount := authzCoins.AmountOf(is.tokenDenom).AddRaw(100)
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, decreaseAmount.BigInt())
+
+ belowZeroCheck := failCheck.WithErrContains(erc20.ErrDecreasedAllowanceBelowZero.Error())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, decreaseArgs, belowZeroCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ // Check that the allowance was not changed
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins)
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ // NOTE: The ERC20 V5 contract does not contain these methods
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+
+ DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) {
+ maxUint256Coins := sdk.Coins{sdk.NewCoin(is.tokenDenom, math.NewIntFromBigInt(abi.MaxUint256))}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, maxUint256Coins[0].Amount.BigInt())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, increaseArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ // Check that the allowance was not changed
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granter.Addr, authzCoins)
+ },
+ Entry(" - direct call", directCall),
+ Entry(" - through erc20 contract", erc20Call),
+ // NOTE: The ERC20 V5 contract does not contain these methods
+ // Entry(" - through erc20 v5 contract", erc20V5Call),
+ )
+ })
+
+ Context("in contract calls", func() {
+ var (
+ authzCoins sdk.Coins
+ grantee keyring.Key
+ )
+
+ BeforeEach(func() {
+ authzCoins = sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ grantee = is.keyring.GetKey(1)
+ callerContractAddr := contractsData.GetContractData(contractCall).Address
+ erc20CallerContractAddr := contractsData.GetContractData(erc20CallerCall).Address
+
+ // NOTE: Here we create an authorization between the contract and the grantee for both contracts.
+ // This is different from the direct calls, where the authorization is created between the
+ // message sender and the grantee.
+ txArgs, approveArgs := is.getTxAndCallArgs(contractCall, contractsData, auth.ApproveMethod, grantee.Addr, authzCoins[0].Amount.BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, _, err := is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ is.ExpectSendAuthzForContract(contractCall, contractsData, grantee.Addr, callerContractAddr, authzCoins)
+
+ // Create the authorization for the ERC20 caller contract
+ txArgs, approveArgs = is.getTxAndCallArgs(erc20CallerCall, contractsData, auth.ApproveMethod, grantee.Addr, authzCoins[0].Amount.BigInt())
+ _, _, err = is.factory.CallContractAndCheckLogs(granter.Priv, txArgs, approveArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ is.ExpectSendAuthzForContract(erc20CallerCall, contractsData, grantee.Addr, erc20CallerContractAddr, authzCoins)
+ })
+
+ DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) {
+ senderPriv := is.keyring.GetPrivKey(0)
+ granterAddr := contractsData.GetContractData(callType).Address
+ increaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, increaseCoins[0].Amount.BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, increaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.IncreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granterAddr, authzCoins.Add(increaseCoins...))
+ },
+ Entry(" - contract call", contractCall),
+ Entry(" - through erc20 caller contract", erc20CallerCall),
+ )
+
+ DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) {
+ senderPriv := is.keyring.GetPrivKey(0)
+ granterAddr := contractsData.GetContractData(callType).Address
+ maxUint256Coins := sdk.Coins{sdk.NewCoin(is.tokenDenom, math.NewIntFromBigInt(abi.MaxUint256))}
+
+ txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.IncreaseAllowanceMethod, grantee.Addr, maxUint256Coins[0].Amount.BigInt())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, increaseArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ // Check that the allowance was not changed
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granterAddr, authzCoins)
+ },
+ Entry(" - contract call", contractCall),
+ Entry(" - through erc20 caller contract", erc20CallerCall),
+ )
+
+ DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) {
+ senderPriv := is.keyring.GetPrivKey(0)
+ granterAddr := contractsData.GetContractData(callType).Address
+ decreaseCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 50)}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, decreaseCoins[0].Amount.BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.DecreaseAllowanceMethod)
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granterAddr, authzCoins.Sub(decreaseCoins...))
+ },
+ Entry(" - contract call", contractCall),
+ Entry(" - through erc20 caller contract", erc20CallerCall),
+ )
+
+ DescribeTable("decreasing the allowance to zero should delete the authorization", func(callType CallType) {
+ senderPriv := is.keyring.GetPrivKey(0)
+ granterAddr := contractsData.GetContractData(callType).Address
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, authzCoins.AmountOf(is.tokenDenom).BigInt())
+ approveCheck := passCheck.WithExpEvents(auth.EventTypeApproval)
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+
+ is.ExpectTrueToBeReturned(ethRes, auth.DecreaseAllowanceMethod)
+ is.ExpectNoSendAuthzForContract(callType, contractsData, grantee.Addr, granterAddr)
+ },
+ Entry(" - contract call", contractCall),
+ Entry(" - through erc20 caller contract", erc20CallerCall),
+ )
+
+ DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) {
+ senderPriv := is.keyring.GetPrivKey(0)
+ granterAddr := contractsData.GetContractData(callType).Address
+ decreaseCoins := sdk.Coins{sdk.NewCoin(is.tokenDenom, authzCoins.AmountOf(is.tokenDenom).AddRaw(100))}
+
+ txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, auth.DecreaseAllowanceMethod, grantee.Addr, decreaseCoins[0].Amount.BigInt())
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, execRevertedCheck)
+ Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract")
+ Expect(ethRes).To(BeNil(), "expected empty result")
+
+ // Check that the allowance was not changed
+ is.ExpectSendAuthzForContract(callType, contractsData, grantee.Addr, granterAddr, authzCoins)
+ },
+ Entry(" - contract call", contractCall),
+ Entry(" - through erc20 caller contract", erc20CallerCall),
+ )
+ })
+ })
+ })
+})
+
+var _ = Describe("ERC20 Extension migration Flows -", func() {
+ When("migrating an existing ERC20 token", func() {
+ var (
+ contractData ContractsData
+ erc20MinterV5Contract evmtypes.CompiledContract
+
+ tokenDenom = "xmpl"
+ tokenName = "Xmpl"
+ tokenSymbol = strings.ToUpper(tokenDenom)
+
+ supply = sdk.NewInt64Coin(tokenDenom, 1000000000000000000)
+ )
+
+ BeforeEach(func() {
+ is.SetupTest()
+
+ var err error
+ erc20MinterV5Contract, err = testdata.LoadERC20MinterV5Contract()
+ Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 minter contract")
+
+ contractOwner := is.keyring.GetKey(0)
+
+ // Deploy an ERC20 contract
+ erc20Addr, err := is.factory.DeployContract(
+ contractOwner.Priv,
+ evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values
+ factory.ContractDeploymentData{
+ Contract: erc20MinterV5Contract,
+ ConstructorArgs: []interface{}{
+ tokenName, tokenSymbol,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy contract")
+
+ // NOTE: We need to overwrite the information in the contractData here for this specific
+ // deployed contract.
+ contractData = ContractsData{
+ ownerPriv: contractOwner.Priv,
+ contractData: map[CallType]ContractData{
+ erc20V5Call: {
+ Address: erc20Addr,
+ ABI: erc20MinterV5Contract.ABI,
+ },
+ },
+ }
+
+ err = is.network.NextBlock()
+ Expect(err).ToNot(HaveOccurred(), "failed to commit block")
+
+ // Register the deployed erc20 contract as a token pair
+ _, err = utils.RegisterERC20(is.factory, is.network, utils.ERC20RegistrationData{
+ Address: erc20Addr,
+ Denom: tokenDenom,
+ ProposerPriv: contractOwner.Priv,
+ })
+ Expect(err).ToNot(HaveOccurred(), "failed to register ERC20 token")
+
+ err = is.network.NextBlock()
+ Expect(err).ToNot(HaveOccurred(), "failed to commit block")
+
+ // Mint the supply of tokens
+ err = is.MintERC20(erc20V5Call, contractData, contractOwner.Addr, supply.Amount.BigInt())
+ Expect(err).ToNot(HaveOccurred(), "failed to mint tokens")
+
+ err = is.network.NextBlock()
+ Expect(err).ToNot(HaveOccurred(), "failed to commit block")
+
+ // Check that the supply was minted
+ is.ExpectBalancesForERC20(erc20V5Call, contractData, []ExpectedBalance{{
+ address: contractOwner.AccAddr,
+ expCoins: sdk.Coins{supply},
+ }})
+ })
+
+ It("should migrate the full token balance to the bank module", func() {
+ // TODO: implement test on follow-up PR
+ Skip("will be addressed on follow-up PR")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+ })
+
+ When("migrating an extended ERC20 token (e.g. ERC20Votes)", func() {
+ It("should migrate the full token balance to the bank module", func() {
+ // TODO: make sure that extended tokens are compatible with the ERC20 extensions
+ Skip("not included in first tranche")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+ })
+
+ When("running the migration logic for a set of existing ERC20 tokens", func() {
+ BeforeEach(func() {
+ // TODO: Add some ERC20 tokens and then run migration logic
+ // TODO: check here that the balance cannot be queried from the bank keeper before migrating the token
+ })
+
+ It("should add and enable the corresponding EVM extensions", func() {
+ Skip("will be addressed in follow-up PR")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+
+ It("should be possible to query the balances through the bank module", func() {
+ Skip("will be addressed in follow-up PR")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+
+ It("should return all tokens when querying all balances for an account", func() {
+ Skip("will be addressed in follow-up PR")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+ })
+
+ When("registering a native IBC coin", func() {
+ BeforeEach(func() {
+ // TODO: Add some IBC coins, register the token pair and then run migration logic
+ })
+
+ It("should add the corresponding EVM extensions", func() {
+ Skip("will be addressed in follow-up PR")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+
+ It("should be possible to query the balances using an EVM transaction", func() {
+ Skip("will be addressed in follow-up PR")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+ })
+
+ When("using Evmos (not wEvmos) in smart contracts", func() {
+ It("should be using straight Evmos for sending funds in smart contracts", func() {
+ Skip("will be addressed in follow-up PR")
+
+ Expect(true).To(BeFalse(), "not implemented")
+ })
+ })
+})
diff --git a/precompiles/erc20/query.go b/precompiles/erc20/query.go
new file mode 100644
index 00000000..b3055fca
--- /dev/null
+++ b/precompiles/erc20/query.go
@@ -0,0 +1,249 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "math/big"
+ "strings"
+ "time"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/evmos/evmos/v19/ibc"
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // NameMethod defines the ABI method name for the ERC-20 Name
+ // query.
+ NameMethod = "name"
+ // SymbolMethod defines the ABI method name for the ERC-20 Symbol
+ // query.
+ SymbolMethod = "symbol"
+ // DecimalsMethod defines the ABI method name for the ERC-20 Decimals
+ // query.
+ DecimalsMethod = "decimals"
+ // TotalSupplyMethod defines the ABI method name for the ERC-20 TotalSupply
+ // query.
+ TotalSupplyMethod = "totalSupply"
+ // BalanceOfMethod defines the ABI method name for the ERC-20 BalanceOf
+ // query.
+ BalanceOfMethod = "balanceOf"
+)
+
+// Name returns the name of the token. If the token metadata is registered in the
+// bank module, it returns its name. Otherwise, it returns the base denomination of
+// the token capitalized (e.g. uatom -> Atom).
+func (p Precompile) Name(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ _ vm.StateDB,
+ method *abi.Method,
+ _ []interface{},
+) ([]byte, error) {
+ metadata, found := p.bankKeeper.GetDenomMetaData(ctx, p.tokenPair.Denom)
+ if found {
+ return method.Outputs.Pack(metadata.Name)
+ }
+
+ baseDenom, err := p.getBaseDenomFromIBCVoucher(ctx, p.tokenPair.Denom)
+ if err != nil {
+ return nil, ConvertErrToERC20Error(err)
+ }
+
+ name := strings.ToUpper(string(baseDenom[1])) + baseDenom[2:]
+ return method.Outputs.Pack(name)
+}
+
+// Symbol returns the symbol of the token. If the token metadata is registered in the
+// bank module, it returns its symbol. Otherwise, it returns the base denomination of
+// the token in uppercase (e.g. uatom -> ATOM).
+func (p Precompile) Symbol(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ _ vm.StateDB,
+ method *abi.Method,
+ _ []interface{},
+) ([]byte, error) {
+ metadata, found := p.bankKeeper.GetDenomMetaData(ctx, p.tokenPair.Denom)
+ if found {
+ return method.Outputs.Pack(metadata.Symbol)
+ }
+
+ baseDenom, err := p.getBaseDenomFromIBCVoucher(ctx, p.tokenPair.Denom)
+ if err != nil {
+ return nil, ConvertErrToERC20Error(err)
+ }
+
+ symbol := strings.ToUpper(baseDenom[1:])
+ return method.Outputs.Pack(symbol)
+}
+
+// Decimals returns the decimals places of the token. If the token metadata is registered in the
+// bank module, it returns the display denomination exponent. Otherwise, it infers the decimal
+// value from the first character of the base denomination (e.g. uatom -> 6).
+func (p Precompile) Decimals(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ _ vm.StateDB,
+ method *abi.Method,
+ _ []interface{},
+) ([]byte, error) {
+ metadata, found := p.bankKeeper.GetDenomMetaData(ctx, p.tokenPair.Denom)
+ if !found {
+ denomTrace, err := ibc.GetDenomTrace(p.transferKeeper, ctx, p.tokenPair.Denom)
+ if err != nil {
+ return nil, ConvertErrToERC20Error(err)
+ }
+
+ // we assume the decimal from the first character of the denomination
+ decimals, err := ibc.DeriveDecimalsFromDenom(denomTrace.BaseDenom)
+ if err != nil {
+ return nil, ConvertErrToERC20Error(err)
+ }
+ return method.Outputs.Pack(decimals)
+ }
+
+ var (
+ decimals uint32
+ displayFound bool
+ )
+ for i := len(metadata.DenomUnits) - 1; i >= 0; i-- {
+ if metadata.DenomUnits[i].Denom == metadata.Display {
+ decimals = metadata.DenomUnits[i].Exponent
+ displayFound = true
+ break
+ }
+ }
+
+ if !displayFound {
+ return nil, ConvertErrToERC20Error(fmt.Errorf(
+ "display denomination not found for denom: %q",
+ p.tokenPair.Denom,
+ ))
+ }
+
+ if decimals > math.MaxUint8 {
+ return nil, ConvertErrToERC20Error(fmt.Errorf(
+ "uint8 overflow: invalid decimals: %d",
+ decimals,
+ ))
+ }
+
+ return method.Outputs.Pack(uint8(decimals)) //#nosec G701 // we are checking for overflow above
+}
+
+// TotalSupply returns the amount of tokens in existence. It fetches the supply
+// of the coin from the bank keeper and returns zero if not found.
+func (p Precompile) TotalSupply(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ _ vm.StateDB,
+ method *abi.Method,
+ _ []interface{},
+) ([]byte, error) {
+ supply := p.bankKeeper.GetSupply(ctx, p.tokenPair.Denom)
+
+ return method.Outputs.Pack(supply.Amount.BigInt())
+}
+
+// BalanceOf returns the amount of tokens owned by account. It fetches the balance
+// of the coin from the bank keeper and returns zero if not found.
+func (p Precompile) BalanceOf(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ _ vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ account, err := ParseBalanceOfArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ balance := p.bankKeeper.GetBalance(ctx, account.Bytes(), p.tokenPair.Denom)
+
+ return method.Outputs.Pack(balance.Amount.BigInt())
+}
+
+// Allowance returns the remaining allowance of a spender to the contract by
+// checking the existence of a bank SendAuthorization.
+func (p Precompile) Allowance(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ _ vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ owner, spender, err := ParseAllowanceArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // NOTE: In case the allowance is queried by the owner, we return the max uint256 value, which
+ // resembles an infinite allowance.
+ if bytes.Equal(owner.Bytes(), spender.Bytes()) {
+ return method.Outputs.Pack(abi.MaxUint256)
+ }
+
+ _, _, allowance, err := GetAuthzExpirationAndAllowance(p.AuthzKeeper, ctx, spender, owner, p.tokenPair.Denom)
+ if err != nil {
+ // NOTE: We are not returning the error here, because we want to align the behavior with
+ // standard ERC20 smart contracts, which return zero if an allowance is not found.
+ allowance = common.Big0
+ }
+
+ return method.Outputs.Pack(allowance)
+}
+
+// GetAuthzExpirationAndAllowance returns the authorization, its expiration as well as the amount of denom
+// that the grantee is allowed to spend on behalf of the granter.
+func GetAuthzExpirationAndAllowance(
+ authzKeeper authzkeeper.Keeper,
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ denom string,
+) (authz.Authorization, *time.Time, *big.Int, error) {
+ authorization, expiration, err := auth.CheckAuthzExists(ctx, authzKeeper, grantee, granter, SendMsgURL)
+ if err != nil {
+ return nil, nil, common.Big0, err
+ }
+
+ sendAuth, ok := authorization.(*banktypes.SendAuthorization)
+ if !ok {
+ return nil, nil, common.Big0, fmt.Errorf(
+ "expected authorization to be a %T", banktypes.SendAuthorization{},
+ )
+ }
+
+ allowance := sendAuth.SpendLimit.AmountOfNoDenomValidation(denom)
+ return authorization, expiration, allowance.BigInt(), nil
+}
+
+// getBaseDenomFromIBCVoucher returns the base denomination from the given IBC voucher denomination.
+func (p Precompile) getBaseDenomFromIBCVoucher(ctx sdk.Context, denom string) (string, error) {
+ // Infer the denomination name from the coin denomination base denom
+ denomTrace, err := ibc.GetDenomTrace(p.transferKeeper, ctx, denom)
+ if err != nil {
+ // FIXME: return 'not supported' (same error as when you call the method on an ERC20.sol)
+ return "", err
+ }
+
+ // safety check
+ if len(denomTrace.BaseDenom) < 3 {
+ // FIXME: return not supported (same error as when you call the method on an ERC20.sol)
+ return "", fmt.Errorf("invalid base denomination; should be at least length 3; got: %q", denomTrace.BaseDenom)
+ }
+
+ return denomTrace.BaseDenom, nil
+}
diff --git a/precompiles/erc20/query_test.go b/precompiles/erc20/query_test.go
new file mode 100644
index 00000000..264fd694
--- /dev/null
+++ b/precompiles/erc20/query_test.go
@@ -0,0 +1,595 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20_test
+
+import (
+ "math"
+ "math/big"
+
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/app"
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/testutil"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+)
+
+// Define useful variables for tests here.
+var (
+ // tooShortTrace is a denomination trace with a name that will raise the "denom too short" error
+ tooShortTrace = types.DenomTrace{Path: "channel-0", BaseDenom: "ab"}
+ // validTraceDenom is a denomination trace with a valid IBC voucher name
+ validTraceDenom = types.DenomTrace{Path: "channel-0", BaseDenom: "uosmo"}
+ // validAttoTraceDenom is a denomination trace with a valid IBC voucher name and 18 decimals
+ validAttoTraceDenom = types.DenomTrace{Path: "channel-0", BaseDenom: "aevmos"}
+ // validTraceDenomNoMicroAtto is a denomination trace with a valid IBC voucher name but no micro or atto prefix
+ validTraceDenomNoMicroAtto = types.DenomTrace{Path: "channel-0", BaseDenom: "mevmos"}
+
+ // --------------------
+ // Variables for coin with valid metadata
+ //
+
+ // validMetadataDenom is the base denomination of the coin with valid metadata
+ validMetadataDenom = "uatom"
+ // validMetadataDisplay is the denomination displayed of the coin with valid metadata
+ validMetadataDisplay = "atom"
+ // validMetadataName is the name of the coin with valid metadata
+ validMetadataName = "Atom"
+ // validMetadataSymbol is the symbol of the coin with valid metadata
+ validMetadataSymbol = "ATOM"
+
+ // validMetadata is the metadata of the coin with valid metadata
+ validMetadata = banktypes.Metadata{
+ Description: "description",
+ Base: validMetadataDenom,
+ // NOTE: Denom units MUST be increasing
+ DenomUnits: []*banktypes.DenomUnit{
+ {
+ Denom: validMetadataDenom,
+ Exponent: 0,
+ },
+ {
+ Denom: validMetadataDisplay,
+ Exponent: uint32(6),
+ },
+ },
+ Name: validMetadataName,
+ Symbol: validMetadataSymbol,
+ Display: validMetadataDisplay,
+ }
+
+ // overflowMetadata contains a metadata with an exponent that overflows uint8
+ overflowMetadata = banktypes.Metadata{
+ Description: "description",
+ Base: validMetadataDenom,
+ // NOTE: Denom units MUST be increasing
+ DenomUnits: []*banktypes.DenomUnit{
+ {
+ Denom: validMetadataDenom,
+ Exponent: 0,
+ },
+ {
+ Denom: validMetadataDisplay,
+ Exponent: uint32(math.MaxUint8 + 1),
+ },
+ },
+ Name: validMetadataName,
+ Symbol: validMetadataSymbol,
+ Display: validMetadataDisplay,
+ }
+
+ // noDisplayMetadata contains a metadata where the denom units do not contain with no display denom
+ noDisplayMetadata = banktypes.Metadata{
+ Description: "description",
+ Base: validMetadataDenom,
+ // NOTE: Denom units MUST be increasing
+ DenomUnits: []*banktypes.DenomUnit{
+ {
+ Denom: validMetadataDenom,
+ Exponent: 0,
+ },
+ },
+ Name: validMetadataName,
+ Symbol: validMetadataSymbol,
+ Display: "",
+ }
+)
+
+// TestNameSymbolDecimals tests the Name and Symbol methods of the ERC20 precompile.
+//
+// NOTE: we test both methods in the same test because they need the same testcases and
+// the same setup.
+func (s *PrecompileTestSuite) TestNameSymbol() {
+ nameMethod := s.precompile.Methods[erc20.NameMethod]
+ symbolMethod := s.precompile.Methods[erc20.SymbolMethod]
+
+ testcases := []struct {
+ name string
+ denom string
+ malleate func(sdk.Context, *app.Evmos)
+ expPass bool
+ errContains string
+ expName string
+ expSymbol string
+ }{
+ {
+ name: "fail - empty denom",
+ denom: "",
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "fail - invalid denom trace",
+ denom: tooShortTrace.IBCDenom()[:len(tooShortTrace.IBCDenom())-1],
+ errContains: "odd length hex string",
+ },
+ {
+ name: "fail - denom not found",
+ denom: types.DenomTrace{Path: "channel-0", BaseDenom: "notfound"}.IBCDenom(),
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "fail - invalid denom (too short < 3 chars)",
+ denom: tooShortTrace.IBCDenom(),
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ app.TransferKeeper.SetDenomTrace(ctx, tooShortTrace)
+ },
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "fail - denom without metadata and not an IBC voucher",
+ denom: "noIBCvoucher",
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "pass - valid ibc denom without metadata and neither atto nor micro prefix",
+ denom: validTraceDenomNoMicroAtto.IBCDenom(),
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ app.TransferKeeper.SetDenomTrace(ctx, validTraceDenomNoMicroAtto)
+ },
+ expPass: true,
+ expName: "Evmos",
+ expSymbol: "EVMOS",
+ },
+ {
+ name: "pass - valid denom with metadata",
+ denom: validMetadataDenom,
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ // NOTE: we mint some coins to the inflation module address to be able to set denom metadata
+ err := app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)})
+ s.Require().NoError(err)
+
+ // NOTE: we set the denom metadata for the coin
+ app.BankKeeper.SetDenomMetaData(ctx, validMetadata)
+ },
+ expPass: true,
+ expName: "Atom",
+ expSymbol: "ATOM",
+ },
+ {
+ name: "pass - valid ibc denom without metadata",
+ denom: validTraceDenom.IBCDenom(),
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ app.TransferKeeper.SetDenomTrace(ctx, validTraceDenom)
+ },
+ expPass: true,
+ expName: "Osmo",
+ expSymbol: "OSMO",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ if tc.malleate != nil {
+ tc.malleate(s.network.GetContext(), s.network.App)
+ }
+
+ precompile := s.setupERC20Precompile(tc.denom)
+
+ s.Run("name", func() {
+ bz, err := precompile.Name(
+ s.network.GetContext(),
+ nil,
+ nil,
+ &nameMethod,
+ []interface{}{},
+ )
+
+ // NOTE: all output and error checking happens in here
+ s.requireOut(bz, err, nameMethod, tc.expPass, tc.errContains, tc.expName)
+ })
+
+ s.Run("symbol", func() {
+ bz, err := precompile.Symbol(
+ s.network.GetContext(),
+ nil,
+ nil,
+ &symbolMethod,
+ []interface{}{},
+ )
+
+ // NOTE: all output and error checking happens in here
+ s.requireOut(bz, err, symbolMethod, tc.expPass, tc.errContains, tc.expSymbol)
+ })
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDecimals() {
+ DecimalsMethod := s.precompile.Methods[erc20.DecimalsMethod]
+
+ testcases := []struct {
+ name string
+ denom string
+ malleate func(sdk.Context, *app.Evmos)
+ expPass bool
+ errContains string
+ expDecimals uint8
+ }{
+ {
+ name: "fail - empty denom",
+ denom: "",
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "fail - invalid denom trace",
+ denom: tooShortTrace.IBCDenom()[:len(tooShortTrace.IBCDenom())-1],
+ errContains: "odd length hex string",
+ },
+ {
+ name: "fail - denom not found",
+ denom: types.DenomTrace{Path: "channel-0", BaseDenom: "notfound"}.IBCDenom(),
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "fail - denom without metadata and not an IBC voucher",
+ denom: "noIBCvoucher",
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "fail - valid ibc denom without metadata and neither atto nor micro prefix",
+ denom: validTraceDenomNoMicroAtto.IBCDenom(),
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ app.TransferKeeper.SetDenomTrace(ctx, validTraceDenomNoMicroAtto)
+ },
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "pass - invalid denom (too short < 3 chars)",
+ denom: tooShortTrace.IBCDenom(),
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ app.TransferKeeper.SetDenomTrace(ctx, tooShortTrace)
+ },
+ expPass: true, // TODO: do we want to check in decimals query for the above error?
+ expDecimals: 18, // expect 18 decimals here because of "a" prefix
+ },
+ {
+ name: "pass - valid denom with metadata",
+ denom: validMetadataDenom,
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ // NOTE: we mint some coins to the inflation module address to be able to set denom metadata
+ err := app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)})
+ s.Require().NoError(err)
+
+ // NOTE: we set the denom metadata for the coin
+ app.BankKeeper.SetDenomMetaData(ctx, validMetadata)
+ },
+ expPass: true,
+ expDecimals: 6,
+ },
+ {
+ name: "pass - valid ibc denom without metadata",
+ denom: validTraceDenom.IBCDenom(),
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ app.TransferKeeper.SetDenomTrace(ctx, validTraceDenom)
+ },
+ expPass: true,
+ expDecimals: 6,
+ },
+ {
+ name: "pass - valid ibc denom without metadata and 18 decimals",
+ denom: validAttoTraceDenom.IBCDenom(),
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ app.TransferKeeper.SetDenomTrace(ctx, validAttoTraceDenom)
+ },
+ expPass: true,
+ expDecimals: 18,
+ },
+ {
+ name: "pass - valid denom with metadata but decimals overflow",
+ denom: validMetadataDenom,
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ // NOTE: we mint some coins to the inflation module address to be able to set denom metadata
+ err := app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)})
+ s.Require().NoError(err)
+
+ // NOTE: we set the denom metadata for the coin
+ app.BankKeeper.SetDenomMetaData(s.network.GetContext(), overflowMetadata)
+ },
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ {
+ name: "pass - valid ibc denom with metadata but no display denom",
+ denom: validMetadataDenom,
+ malleate: func(ctx sdk.Context, app *app.Evmos) {
+ // NOTE: we mint some coins to the inflation module address to be able to set denom metadata
+ err := app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)})
+ s.Require().NoError(err)
+
+ // NOTE: we set the denom metadata for the coin
+ app.BankKeeper.SetDenomMetaData(ctx, noDisplayMetadata)
+ },
+ errContains: vm.ErrExecutionReverted.Error(),
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ if tc.malleate != nil {
+ tc.malleate(s.network.GetContext(), s.network.App)
+ }
+
+ precompile := s.setupERC20Precompile(tc.denom)
+
+ bz, err := precompile.Decimals(
+ s.network.GetContext(),
+ nil,
+ nil,
+ &DecimalsMethod,
+ []interface{}{},
+ )
+
+ // NOTE: all output and error checking happens in here
+ s.requireOut(bz, err, DecimalsMethod, tc.expPass, tc.errContains, tc.expDecimals)
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestTotalSupply() {
+ method := s.precompile.Methods[erc20.TotalSupplyMethod]
+
+ testcases := []struct {
+ name string
+ malleate func(sdk.Context, *app.Evmos, *big.Int)
+ expPass bool
+ errContains string
+ expTotal *big.Int
+ }{
+ {
+ name: "pass - no coins",
+ expPass: true,
+ expTotal: common.Big0,
+ },
+ {
+ name: "pass - some coins",
+ malleate: func(ctx sdk.Context, app *app.Evmos, amount *big.Int) {
+ // NOTE: we mint some coins to the inflation module address to be able to set denom metadata
+ err := app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewCoin(validMetadata.Base, sdkmath.NewIntFromBigInt(amount))})
+ s.Require().NoError(err)
+ },
+ expPass: true,
+ expTotal: big.NewInt(100),
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ if tc.malleate != nil {
+ tc.malleate(s.network.GetContext(), s.network.App, tc.expTotal)
+ }
+
+ precompile := s.setupERC20Precompile(validMetadataDenom)
+
+ bz, err := precompile.TotalSupply(
+ s.network.GetContext(),
+ nil,
+ nil,
+ &method,
+ []interface{}{},
+ )
+
+ // NOTE: all output and error checking happens in here
+ s.requireOut(bz, err, method, tc.expPass, tc.errContains, tc.expTotal)
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestBalanceOf() {
+ method := s.precompile.Methods[erc20.BalanceOfMethod]
+
+ testcases := []struct {
+ name string
+ malleate func(sdk.Context, *app.Evmos, *big.Int) []interface{}
+ expPass bool
+ errContains string
+ expBalance *big.Int
+ }{
+ {
+ name: "fail - invalid number of arguments",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ return []interface{}{}
+ },
+ errContains: "invalid number of arguments; expected 1; got: 0",
+ },
+ {
+ name: "fail - invalid address",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ return []interface{}{"invalid address"}
+ },
+ errContains: "invalid account address: invalid address",
+ },
+ {
+ name: "pass - no coins in token denomination of precompile token pair",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ // NOTE: we fund the account with some coins in a different denomination from what was used in the precompile.
+ err := testutil.FundAccount(
+ s.network.GetContext(), s.network.App.BankKeeper, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, 100)),
+ )
+ s.Require().NoError(err, "expected no error funding account")
+
+ return []interface{}{s.keyring.GetAddr(0)}
+ },
+ expPass: true,
+ expBalance: common.Big0,
+ },
+ {
+ name: "pass - some coins",
+ malleate: func(ctx sdk.Context, app *app.Evmos, amount *big.Int) []interface{} {
+ // NOTE: we fund the account with some coins of the token denomination that was used for the precompile
+ err := testutil.FundAccount(
+ ctx, app.BankKeeper, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewCoin(s.tokenDenom, sdkmath.NewIntFromBigInt(amount))),
+ )
+ s.Require().NoError(err, "expected no error funding account")
+
+ return []interface{}{s.keyring.GetAddr(0)}
+ },
+ expPass: true,
+ expBalance: big.NewInt(100),
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var balanceOfArgs []interface{}
+ if tc.malleate != nil {
+ balanceOfArgs = tc.malleate(s.network.GetContext(), s.network.App, tc.expBalance)
+ }
+
+ precompile := s.setupERC20Precompile(s.tokenDenom)
+
+ bz, err := precompile.BalanceOf(
+ s.network.GetContext(),
+ nil,
+ nil,
+ &method,
+ balanceOfArgs,
+ )
+
+ // NOTE: all output and error checking happens in here
+ s.requireOut(bz, err, method, tc.expPass, tc.errContains, tc.expBalance)
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestAllowance() {
+ method := s.precompile.Methods[auth.AllowanceMethod]
+
+ testcases := []struct {
+ name string
+ malleate func(sdk.Context, *app.Evmos, *big.Int) []interface{}
+ expPass bool
+ errContains string
+ expAllow *big.Int
+ }{
+ {
+ name: "fail - invalid number of arguments",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ return []interface{}{1}
+ },
+ errContains: "invalid number of arguments; expected 2; got: 1",
+ },
+ {
+ name: "fail - invalid owner address",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ return []interface{}{"invalid address", s.keyring.GetAddr(1)}
+ },
+ errContains: "invalid owner address: invalid address",
+ },
+ {
+ name: "fail - invalid spender address",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ return []interface{}{s.keyring.GetAddr(0), "invalid address"}
+ },
+ errContains: "invalid spender address: invalid address",
+ },
+ {
+ name: "pass - no allowance exists should return 0",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ return []interface{}{s.keyring.GetAddr(0), s.keyring.GetAddr(1)}
+ },
+ expPass: true,
+ expAllow: common.Big0,
+ },
+ {
+ name: "pass - allowance exists but not for precompile token pair denom",
+ malleate: func(_ sdk.Context, _ *app.Evmos, _ *big.Int) []interface{} {
+ granterIdx := 0
+ granteeIdx := 1
+
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(granteeIdx),
+ s.keyring.GetPrivKey(granterIdx),
+ sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, 100)),
+ )
+
+ return []interface{}{s.keyring.GetAddr(granterIdx), s.keyring.GetAddr(granteeIdx)}
+ },
+ expPass: true,
+ expAllow: common.Big0,
+ },
+ {
+ name: "pass - allowance exists for precompile token pair denom",
+ malleate: func(_ sdk.Context, _ *app.Evmos, amount *big.Int) []interface{} {
+ granterIdx := 0
+ granteeIdx := 1
+
+ s.setupSendAuthz(
+ s.keyring.GetAccAddr(granteeIdx),
+ s.keyring.GetPrivKey(granterIdx),
+ sdk.NewCoins(sdk.NewCoin(s.tokenDenom, sdkmath.NewIntFromBigInt(amount))),
+ )
+
+ return []interface{}{s.keyring.GetAddr(granterIdx), s.keyring.GetAddr(granteeIdx)}
+ },
+ expPass: true,
+ expAllow: big.NewInt(100),
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var allowanceArgs []interface{}
+ if tc.malleate != nil {
+ allowanceArgs = tc.malleate(s.network.GetContext(), s.network.App, tc.expAllow)
+ }
+
+ precompile := s.setupERC20Precompile(s.tokenDenom)
+
+ bz, err := precompile.Allowance(
+ s.network.GetContext(),
+ nil,
+ nil,
+ &method,
+ allowanceArgs,
+ )
+
+ // NOTE: all output and error checking happens in here
+ s.requireOut(bz, err, method, tc.expPass, tc.errContains, tc.expAllow)
+ })
+ }
+}
diff --git a/precompiles/erc20/setup_test.go b/precompiles/erc20/setup_test.go
new file mode 100644
index 00000000..aa992431
--- /dev/null
+++ b/precompiles/erc20/setup_test.go
@@ -0,0 +1,62 @@
+package erc20_test
+
+import (
+ "testing"
+
+ erc20precompile "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ "github.com/stretchr/testify/suite"
+)
+
+var s *PrecompileTestSuite
+
+// PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 precompile
+// unit tests.
+type PrecompileTestSuite struct {
+ suite.Suite
+
+ bondDenom string
+ // tokenDenom is the specific token denomination used in testing the ERC20 precompile.
+ // This denomination is used to instantiate the precompile.
+ tokenDenom string
+ network *network.UnitTestNetwork
+ factory factory.TxFactory
+ grpcHandler grpc.Handler
+ keyring testkeyring.Keyring
+
+ precompile *erc20precompile.Precompile
+}
+
+func TestPrecompileTestSuite(t *testing.T) {
+ s = new(PrecompileTestSuite)
+ suite.Run(t, s)
+}
+
+func (s *PrecompileTestSuite) SetupTest() {
+ keyring := testkeyring.New(2)
+ integrationNetwork := network.NewUnitTestNetwork(
+ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ grpcHandler := grpc.NewIntegrationHandler(integrationNetwork)
+ txFactory := factory.New(integrationNetwork, grpcHandler)
+
+ ctx := integrationNetwork.GetContext()
+ sk := integrationNetwork.App.StakingKeeper
+ bondDenom := sk.BondDenom(ctx)
+ s.Require().NotEmpty(bondDenom, "bond denom cannot be empty")
+
+ s.bondDenom = bondDenom
+ s.factory = txFactory
+ s.grpcHandler = grpcHandler
+ s.keyring = keyring
+ s.network = integrationNetwork
+
+ // Instantiate the precompile with an exemplary token denomination.
+ //
+ // NOTE: This has to be done AFTER assigning the suite fields.
+ s.tokenDenom = "xmpl"
+ s.precompile = s.setupERC20Precompile(s.tokenDenom)
+}
diff --git a/precompiles/erc20/testdata/ERC20AllowanceCaller.json b/precompiles/erc20/testdata/ERC20AllowanceCaller.json
new file mode 100644
index 00000000..ea8b233e
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20AllowanceCaller.json
@@ -0,0 +1,255 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "ERC20AllowanceCaller",
+ "sourceName": "solidity/precompiles/erc20/testdata/ERC20AllowanceCaller.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "tokenAddress",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "decimals",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "subtractedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "decreaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "addedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "increaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "token",
+ "outputs": [
+ {
+ "internalType": "contract IERC20MetadataAllowance",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x60806040523480156200001157600080fd5b50604051620011a3380380620011a38339818101604052810190620000379190620000e8565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200011a565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000b08262000083565b9050919050565b620000c281620000a3565b8114620000ce57600080fd5b50565b600081519050620000e281620000b7565b92915050565b6000602082840312156200010157620001006200007e565b5b60006200011184828501620000d1565b91505092915050565b611079806200012a6000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c806370a082311161007157806370a08231146101a357806395d89b41146101d3578063a457c2d7146101f1578063a9059cbb14610221578063dd62ed3e14610251578063fc0c546a14610281576100b4565b806306fdde03146100b9578063095ea7b3146100d757806318160ddd1461010757806323b872dd14610125578063313ce567146101555780633950935114610173575b600080fd5b6100c161029f565b6040516100ce9190610a52565b60405180910390f35b6100f160048036038101906100ec9190610b1c565b61033a565b6040516100fe9190610b77565b60405180910390f35b61010f6103e3565b60405161011c9190610ba1565b60405180910390f35b61013f600480360381019061013a9190610bbc565b61047a565b60405161014c9190610b77565b60405180910390f35b61015d610526565b60405161016a9190610c2b565b60405180910390f35b61018d60048036038101906101889190610b1c565b6105bd565b60405161019a9190610b77565b60405180910390f35b6101bd60048036038101906101b89190610c46565b610666565b6040516101ca9190610ba1565b60405180910390f35b6101db61070a565b6040516101e89190610a52565b60405180910390f35b61020b60048036038101906102069190610b1c565b6107a5565b6040516102189190610b77565b60405180910390f35b61023b60048036038101906102369190610b1c565b61084e565b6040516102489190610b77565b60405180910390f35b61026b60048036038101906102669190610c73565b6108f7565b6040516102789190610ba1565b60405180910390f35b61028961099e565b6040516102969190610d12565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801561030c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906103359190610e53565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b384846040518363ffffffff1660e01b8152600401610398929190610eab565b6020604051808303816000875af11580156103b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103db9190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104759190610f42565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd8585856040518463ffffffff1660e01b81526004016104da93929190610f6f565b6020604051808303816000875af11580156104f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051d9190610f00565b90509392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190610fd2565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633950935184846040518363ffffffff1660e01b815260040161061b929190610eab565b6020604051808303816000875af115801561063a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065e9190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b81526004016106c29190610fff565b602060405180830381865afa1580156106df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107039190610f42565b9050919050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610777573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107a09190610e53565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a457c2d784846040518363ffffffff1660e01b8152600401610803929190610eab565b6020604051808303816000875af1158015610822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108469190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b81526004016108ac929190610eab565b6020604051808303816000875af11580156108cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ef9190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e84846040518363ffffffff1660e01b815260040161095592919061101a565b602060405180830381865afa158015610972573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109969190610f42565b905092915050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081519050919050565b600082825260208201905092915050565b60005b838110156109fc5780820151818401526020810190506109e1565b60008484015250505050565b6000601f19601f8301169050919050565b6000610a24826109c2565b610a2e81856109cd565b9350610a3e8185602086016109de565b610a4781610a08565b840191505092915050565b60006020820190508181036000830152610a6c8184610a19565b905092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610ab382610a88565b9050919050565b610ac381610aa8565b8114610ace57600080fd5b50565b600081359050610ae081610aba565b92915050565b6000819050919050565b610af981610ae6565b8114610b0457600080fd5b50565b600081359050610b1681610af0565b92915050565b60008060408385031215610b3357610b32610a7e565b5b6000610b4185828601610ad1565b9250506020610b5285828601610b07565b9150509250929050565b60008115159050919050565b610b7181610b5c565b82525050565b6000602082019050610b8c6000830184610b68565b92915050565b610b9b81610ae6565b82525050565b6000602082019050610bb66000830184610b92565b92915050565b600080600060608486031215610bd557610bd4610a7e565b5b6000610be386828701610ad1565b9350506020610bf486828701610ad1565b9250506040610c0586828701610b07565b9150509250925092565b600060ff82169050919050565b610c2581610c0f565b82525050565b6000602082019050610c406000830184610c1c565b92915050565b600060208284031215610c5c57610c5b610a7e565b5b6000610c6a84828501610ad1565b91505092915050565b60008060408385031215610c8a57610c89610a7e565b5b6000610c9885828601610ad1565b9250506020610ca985828601610ad1565b9150509250929050565b6000819050919050565b6000610cd8610cd3610cce84610a88565b610cb3565b610a88565b9050919050565b6000610cea82610cbd565b9050919050565b6000610cfc82610cdf565b9050919050565b610d0c81610cf1565b82525050565b6000602082019050610d276000830184610d03565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610d6f82610a08565b810181811067ffffffffffffffff82111715610d8e57610d8d610d37565b5b80604052505050565b6000610da1610a74565b9050610dad8282610d66565b919050565b600067ffffffffffffffff821115610dcd57610dcc610d37565b5b610dd682610a08565b9050602081019050919050565b6000610df6610df184610db2565b610d97565b905082815260208101848484011115610e1257610e11610d32565b5b610e1d8482856109de565b509392505050565b600082601f830112610e3a57610e39610d2d565b5b8151610e4a848260208601610de3565b91505092915050565b600060208284031215610e6957610e68610a7e565b5b600082015167ffffffffffffffff811115610e8757610e86610a83565b5b610e9384828501610e25565b91505092915050565b610ea581610aa8565b82525050565b6000604082019050610ec06000830185610e9c565b610ecd6020830184610b92565b9392505050565b610edd81610b5c565b8114610ee857600080fd5b50565b600081519050610efa81610ed4565b92915050565b600060208284031215610f1657610f15610a7e565b5b6000610f2484828501610eeb565b91505092915050565b600081519050610f3c81610af0565b92915050565b600060208284031215610f5857610f57610a7e565b5b6000610f6684828501610f2d565b91505092915050565b6000606082019050610f846000830186610e9c565b610f916020830185610e9c565b610f9e6040830184610b92565b949350505050565b610faf81610c0f565b8114610fba57600080fd5b50565b600081519050610fcc81610fa6565b92915050565b600060208284031215610fe857610fe7610a7e565b5b6000610ff684828501610fbd565b91505092915050565b60006020820190506110146000830184610e9c565b92915050565b600060408201905061102f6000830185610e9c565b61103c6020830184610e9c565b939250505056fea2646970667358221220637880a86b5674a1029aca57cde1625d2301a03c9bb21329d064a801f8d8916664736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c806370a082311161007157806370a08231146101a357806395d89b41146101d3578063a457c2d7146101f1578063a9059cbb14610221578063dd62ed3e14610251578063fc0c546a14610281576100b4565b806306fdde03146100b9578063095ea7b3146100d757806318160ddd1461010757806323b872dd14610125578063313ce567146101555780633950935114610173575b600080fd5b6100c161029f565b6040516100ce9190610a52565b60405180910390f35b6100f160048036038101906100ec9190610b1c565b61033a565b6040516100fe9190610b77565b60405180910390f35b61010f6103e3565b60405161011c9190610ba1565b60405180910390f35b61013f600480360381019061013a9190610bbc565b61047a565b60405161014c9190610b77565b60405180910390f35b61015d610526565b60405161016a9190610c2b565b60405180910390f35b61018d60048036038101906101889190610b1c565b6105bd565b60405161019a9190610b77565b60405180910390f35b6101bd60048036038101906101b89190610c46565b610666565b6040516101ca9190610ba1565b60405180910390f35b6101db61070a565b6040516101e89190610a52565b60405180910390f35b61020b60048036038101906102069190610b1c565b6107a5565b6040516102189190610b77565b60405180910390f35b61023b60048036038101906102369190610b1c565b61084e565b6040516102489190610b77565b60405180910390f35b61026b60048036038101906102669190610c73565b6108f7565b6040516102789190610ba1565b60405180910390f35b61028961099e565b6040516102969190610d12565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801561030c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906103359190610e53565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b384846040518363ffffffff1660e01b8152600401610398929190610eab565b6020604051808303816000875af11580156103b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103db9190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104759190610f42565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd8585856040518463ffffffff1660e01b81526004016104da93929190610f6f565b6020604051808303816000875af11580156104f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051d9190610f00565b90509392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190610fd2565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633950935184846040518363ffffffff1660e01b815260040161061b929190610eab565b6020604051808303816000875af115801561063a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065e9190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b81526004016106c29190610fff565b602060405180830381865afa1580156106df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107039190610f42565b9050919050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610777573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107a09190610e53565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a457c2d784846040518363ffffffff1660e01b8152600401610803929190610eab565b6020604051808303816000875af1158015610822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108469190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b81526004016108ac929190610eab565b6020604051808303816000875af11580156108cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ef9190610f00565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e84846040518363ffffffff1660e01b815260040161095592919061101a565b602060405180830381865afa158015610972573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109969190610f42565b905092915050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081519050919050565b600082825260208201905092915050565b60005b838110156109fc5780820151818401526020810190506109e1565b60008484015250505050565b6000601f19601f8301169050919050565b6000610a24826109c2565b610a2e81856109cd565b9350610a3e8185602086016109de565b610a4781610a08565b840191505092915050565b60006020820190508181036000830152610a6c8184610a19565b905092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610ab382610a88565b9050919050565b610ac381610aa8565b8114610ace57600080fd5b50565b600081359050610ae081610aba565b92915050565b6000819050919050565b610af981610ae6565b8114610b0457600080fd5b50565b600081359050610b1681610af0565b92915050565b60008060408385031215610b3357610b32610a7e565b5b6000610b4185828601610ad1565b9250506020610b5285828601610b07565b9150509250929050565b60008115159050919050565b610b7181610b5c565b82525050565b6000602082019050610b8c6000830184610b68565b92915050565b610b9b81610ae6565b82525050565b6000602082019050610bb66000830184610b92565b92915050565b600080600060608486031215610bd557610bd4610a7e565b5b6000610be386828701610ad1565b9350506020610bf486828701610ad1565b9250506040610c0586828701610b07565b9150509250925092565b600060ff82169050919050565b610c2581610c0f565b82525050565b6000602082019050610c406000830184610c1c565b92915050565b600060208284031215610c5c57610c5b610a7e565b5b6000610c6a84828501610ad1565b91505092915050565b60008060408385031215610c8a57610c89610a7e565b5b6000610c9885828601610ad1565b9250506020610ca985828601610ad1565b9150509250929050565b6000819050919050565b6000610cd8610cd3610cce84610a88565b610cb3565b610a88565b9050919050565b6000610cea82610cbd565b9050919050565b6000610cfc82610cdf565b9050919050565b610d0c81610cf1565b82525050565b6000602082019050610d276000830184610d03565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610d6f82610a08565b810181811067ffffffffffffffff82111715610d8e57610d8d610d37565b5b80604052505050565b6000610da1610a74565b9050610dad8282610d66565b919050565b600067ffffffffffffffff821115610dcd57610dcc610d37565b5b610dd682610a08565b9050602081019050919050565b6000610df6610df184610db2565b610d97565b905082815260208101848484011115610e1257610e11610d32565b5b610e1d8482856109de565b509392505050565b600082601f830112610e3a57610e39610d2d565b5b8151610e4a848260208601610de3565b91505092915050565b600060208284031215610e6957610e68610a7e565b5b600082015167ffffffffffffffff811115610e8757610e86610a83565b5b610e9384828501610e25565b91505092915050565b610ea581610aa8565b82525050565b6000604082019050610ec06000830185610e9c565b610ecd6020830184610b92565b9392505050565b610edd81610b5c565b8114610ee857600080fd5b50565b600081519050610efa81610ed4565b92915050565b600060208284031215610f1657610f15610a7e565b5b6000610f2484828501610eeb565b91505092915050565b600081519050610f3c81610af0565b92915050565b600060208284031215610f5857610f57610a7e565b5b6000610f6684828501610f2d565b91505092915050565b6000606082019050610f846000830186610e9c565b610f916020830185610e9c565b610f9e6040830184610b92565b949350505050565b610faf81610c0f565b8114610fba57600080fd5b50565b600081519050610fcc81610fa6565b92915050565b600060208284031215610fe857610fe7610a7e565b5b6000610ff684828501610fbd565b91505092915050565b60006020820190506110146000830184610e9c565b92915050565b600060408201905061102f6000830185610e9c565b61103c6020830184610e9c565b939250505056fea2646970667358221220637880a86b5674a1029aca57cde1625d2301a03c9bb21329d064a801f8d8916664736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/erc20/testdata/ERC20AllowanceCaller.sol b/precompiles/erc20/testdata/ERC20AllowanceCaller.sol
new file mode 100644
index 00000000..eeca20ee
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20AllowanceCaller.sol
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../IERC20MetadataAllowance.sol" as erc20Allowance;
+
+/// @title ERC20AllowanceCaller
+/// @author Evmos Core Team
+/// @dev This contract is used to test external contract calls to the ERC20 precompile.
+contract ERC20AllowanceCaller {
+ erc20Allowance.IERC20MetadataAllowance public token;
+
+ constructor(address tokenAddress) {
+ token = erc20Allowance.IERC20MetadataAllowance(tokenAddress);
+ }
+
+ function transfer(address to, uint256 amount) external returns (bool) {
+ return token.transfer(to, amount);
+ }
+
+ function transferFrom(address from, address to, uint256 amount) external returns (bool) {
+ return token.transferFrom(from, to, amount);
+ }
+
+ function approve(address spender, uint256 amount) external returns (bool) {
+ return token.approve(spender, amount);
+ }
+
+ function allowance(address owner, address spender) external view returns (uint256) {
+ return token.allowance(owner, spender);
+ }
+
+ function balanceOf(address owner) external view returns (uint256) {
+ return token.balanceOf(owner);
+ }
+
+ function totalSupply() external view returns (uint256) {
+ return token.totalSupply();
+ }
+
+ function name() external view returns (string memory) {
+ return token.name();
+ }
+
+ function symbol() external view returns (string memory) {
+ return token.symbol();
+ }
+
+ function decimals() external view returns (uint8) {
+ return token.decimals();
+ }
+
+ function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {
+ return token.increaseAllowance(spender, addedValue);
+ }
+
+ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {
+ return token.decreaseAllowance(spender, subtractedValue);
+ }
+}
diff --git a/precompiles/erc20/testdata/ERC20Minter_OpenZeppelinV5.json b/precompiles/erc20/testdata/ERC20Minter_OpenZeppelinV5.json
new file mode 100644
index 00000000..65310cf4
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20Minter_OpenZeppelinV5.json
@@ -0,0 +1,5 @@
+{
+ "abi": "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ "bin": "608060405234801562000010575f80fd5b5060405162001945380380620019458339818101604052810190620000369190620001eb565b81818160039081620000499190620004a5565b5080600490816200005b9190620004a5565b505050505062000589565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b620000c7826200007f565b810181811067ffffffffffffffff82111715620000e957620000e86200008f565b5b80604052505050565b5f620000fd62000066565b90506200010b8282620000bc565b919050565b5f67ffffffffffffffff8211156200012d576200012c6200008f565b5b62000138826200007f565b9050602081019050919050565b5f5b838110156200016457808201518184015260208101905062000147565b5f8484015250505050565b5f620001856200017f8462000110565b620000f2565b905082815260208101848484011115620001a457620001a36200007b565b5b620001b184828562000145565b509392505050565b5f82601f830112620001d057620001cf62000077565b5b8151620001e28482602086016200016f565b91505092915050565b5f80604083850312156200020457620002036200006f565b5b5f83015167ffffffffffffffff81111562000224576200022362000073565b5b6200023285828601620001b9565b925050602083015167ffffffffffffffff81111562000256576200025562000073565b5b6200026485828601620001b9565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680620002bd57607f821691505b602082108103620002d357620002d262000278565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620003377fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620002fa565b620003438683620002fa565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200038d6200038762000381846200035b565b62000364565b6200035b565b9050919050565b5f819050919050565b620003a8836200036d565b620003c0620003b78262000394565b84845462000306565b825550505050565b5f90565b620003d6620003c8565b620003e38184846200039d565b505050565b5b818110156200040a57620003fe5f82620003cc565b600181019050620003e9565b5050565b601f82111562000459576200042381620002d9565b6200042e84620002eb565b810160208510156200043e578190505b620004566200044d85620002eb565b830182620003e8565b50505b505050565b5f82821c905092915050565b5f6200047b5f19846008026200045e565b1980831691505092915050565b5f6200049583836200046a565b9150826002028217905092915050565b620004b0826200026e565b67ffffffffffffffff811115620004cc57620004cb6200008f565b5b620004d88254620002a5565b620004e58282856200040e565b5f60209050601f8311600181146200051b575f841562000506578287015190505b62000512858262000488565b86555062000581565b601f1984166200052b86620002d9565b5f5b8281101562000554578489015182556001820191506020850194506020810190506200052d565b8683101562000574578489015162000570601f8916826200046a565b8355505b6001600288020188555050505b505050505050565b6113ae80620005975f395ff3fe608060405234801561000f575f80fd5b50600436106100b2575f3560e01c806340c10f191161006f57806340c10f19146101a057806370a08231146101bc57806395d89b41146101ec578063a457c2d71461020a578063a9059cbb1461023a578063dd62ed3e1461026a576100b2565b806306fdde03146100b6578063095ea7b3146100d457806318160ddd1461010457806323b872dd14610122578063313ce567146101525780633950935114610170575b5f80fd5b6100be61029a565b6040516100cb9190610c60565b60405180910390f35b6100ee60048036038101906100e99190610d11565b61032a565b6040516100fb9190610d69565b60405180910390f35b61010c61034c565b6040516101199190610d91565b60405180910390f35b61013c60048036038101906101379190610daa565b610355565b6040516101499190610d69565b60405180910390f35b61015a610383565b6040516101679190610e15565b60405180910390f35b61018a60048036038101906101859190610d11565b61038b565b6040516101979190610d69565b60405180910390f35b6101ba60048036038101906101b59190610d11565b6103c1565b005b6101d660048036038101906101d19190610e2e565b6103cf565b6040516101e39190610d91565b60405180910390f35b6101f4610414565b6040516102019190610c60565b60405180910390f35b610224600480360381019061021f9190610d11565b6104a4565b6040516102319190610d69565b60405180910390f35b610254600480360381019061024f9190610d11565b610519565b6040516102619190610d69565b60405180910390f35b610284600480360381019061027f9190610e59565b61053b565b6040516102919190610d91565b60405180910390f35b6060600380546102a990610ec4565b80601f01602080910402602001604051908101604052809291908181526020018280546102d590610ec4565b80156103205780601f106102f757610100808354040283529160200191610320565b820191905f5260205f20905b81548152906001019060200180831161030357829003601f168201915b5050505050905090565b5f806103346105bd565b90506103418185856105c4565b600191505092915050565b5f600254905090565b5f8061035f6105bd565b905061036c858285610787565b610377858585610812565b60019150509392505050565b5f6012905090565b5f806103956105bd565b90506103b68185856103a7858961053b565b6103b19190610f21565b6105c4565b600191505092915050565b6103cb8282610a7e565b5050565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b60606004805461042390610ec4565b80601f016020809104026020016040519081016040528092919081815260200182805461044f90610ec4565b801561049a5780601f106104715761010080835404028352916020019161049a565b820191905f5260205f20905b81548152906001019060200180831161047d57829003601f168201915b5050505050905090565b5f806104ae6105bd565b90505f6104bb828661053b565b905083811015610500576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104f790610fc4565b60405180910390fd5b61050d82868684036105c4565b60019250505092915050565b5f806105236105bd565b9050610530818585610812565b600191505092915050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062990611052565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610697906110e0565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258360405161077a9190610d91565b60405180910390a3505050565b5f610792848461053b565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461080c57818110156107fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f590611148565b60405180910390fd5b61080b84848484036105c4565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610880576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610877906111d6565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e590611264565b60405180910390fd5b6108f9838383610bcc565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561097c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610973906112f2565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550815f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610a659190610d91565b60405180910390a3610a78848484610bd1565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610aec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae39061135a565b60405180910390fd5b610af75f8383610bcc565b8060025f828254610b089190610f21565b92505081905550805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508173ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610bb59190610d91565b60405180910390a3610bc85f8383610bd1565b5050565b505050565b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610c0d578082015181840152602081019050610bf2565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610c3282610bd6565b610c3c8185610be0565b9350610c4c818560208601610bf0565b610c5581610c18565b840191505092915050565b5f6020820190508181035f830152610c788184610c28565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610cad82610c84565b9050919050565b610cbd81610ca3565b8114610cc7575f80fd5b50565b5f81359050610cd881610cb4565b92915050565b5f819050919050565b610cf081610cde565b8114610cfa575f80fd5b50565b5f81359050610d0b81610ce7565b92915050565b5f8060408385031215610d2757610d26610c80565b5b5f610d3485828601610cca565b9250506020610d4585828601610cfd565b9150509250929050565b5f8115159050919050565b610d6381610d4f565b82525050565b5f602082019050610d7c5f830184610d5a565b92915050565b610d8b81610cde565b82525050565b5f602082019050610da45f830184610d82565b92915050565b5f805f60608486031215610dc157610dc0610c80565b5b5f610dce86828701610cca565b9350506020610ddf86828701610cca565b9250506040610df086828701610cfd565b9150509250925092565b5f60ff82169050919050565b610e0f81610dfa565b82525050565b5f602082019050610e285f830184610e06565b92915050565b5f60208284031215610e4357610e42610c80565b5b5f610e5084828501610cca565b91505092915050565b5f8060408385031215610e6f57610e6e610c80565b5b5f610e7c85828601610cca565b9250506020610e8d85828601610cca565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610edb57607f821691505b602082108103610eee57610eed610e97565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610f2b82610cde565b9150610f3683610cde565b9250828201905080821115610f4e57610f4d610ef4565b5b92915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f775f8201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b5f610fae602583610be0565b9150610fb982610f54565b604082019050919050565b5f6020820190508181035f830152610fdb81610fa2565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f206164645f8201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b5f61103c602483610be0565b915061104782610fe2565b604082019050919050565b5f6020820190508181035f83015261106981611030565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f2061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f6110ca602283610be0565b91506110d582611070565b604082019050919050565b5f6020820190508181035f8301526110f7816110be565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000005f82015250565b5f611132601d83610be0565b915061113d826110fe565b602082019050919050565b5f6020820190508181035f83015261115f81611126565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f6111c0602583610be0565b91506111cb82611166565b604082019050919050565b5f6020820190508181035f8301526111ed816111b4565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f20616464725f8201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b5f61124e602383610be0565b9150611259826111f4565b604082019050919050565b5f6020820190508181035f83015261127b81611242565b9050919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320625f8201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b5f6112dc602683610be0565b91506112e782611282565b604082019050919050565b5f6020820190508181035f830152611309816112d0565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f2061646472657373005f82015250565b5f611344601f83610be0565b915061134f82611310565b602082019050919050565b5f6020820190508181035f83015261137181611338565b905091905056fea26469706673582212208879d77a1f3c9529d8474acf01f35418acde477cd7f2bedd3c2947c2c8d4a89a64736f6c63430008140033",
+ "contractName": "ERC20Minter_OpenZeppelinV5"
+}
diff --git a/precompiles/erc20/testdata/ERC20Minter_OpenZeppelinV5.sol b/precompiles/erc20/testdata/ERC20Minter_OpenZeppelinV5.sol
new file mode 100644
index 00000000..271e2400
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20Minter_OpenZeppelinV5.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: MIT
+//
+// Based on OpenZeppelin Contracts v5.0.0 (token/ERC20/ERC20.sol)
+//
+// NOTE: This was compiled using REMIX IDE.
+
+pragma solidity ^0.8.20;
+
+import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC20/ERC20.sol";
+
+/**
+ * @dev {ERC20} token, including:
+ *
+ * - ability to mint tokens
+ *
+ * ATTENTION: This contract does not restrict minting tokens to any particular address
+ * and should thus ONLY BE USED FOR TESTING.
+ */
+contract ERC20Minter_OpenZeppelinV5 is ERC20 {
+ constructor(string memory name, string memory symbol)
+ ERC20(name, symbol) {}
+
+ function mint(address to, uint256 amount) public {
+ _mint(to, amount);
+ }
+}
diff --git a/precompiles/erc20/testdata/ERC20NoMetadata.json b/precompiles/erc20/testdata/ERC20NoMetadata.json
new file mode 100644
index 00000000..47171170
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20NoMetadata.json
@@ -0,0 +1,247 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "ERC20NoMetadata",
+ "sourceName": "solidity/precompiles/erc20/testdata/ERC20NoMetadata.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "subtractedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "decreaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "addedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "increaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b50610f4f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806370a082311161005b57806370a082311461013b578063a457c2d71461016b578063a9059cbb1461019b578063dd62ed3e146101cb57610088565b8063095ea7b31461008d57806318160ddd146100bd57806323b872dd146100db578063395093511461010b575b600080fd5b6100a760048036038101906100a2919061096d565b6101fb565b6040516100b491906109c8565b60405180910390f35b6100c561021e565b6040516100d291906109f2565b60405180910390f35b6100f560048036038101906100f09190610a0d565b610228565b60405161010291906109c8565b60405180910390f35b6101256004803603810190610120919061096d565b610257565b60405161013291906109c8565b60405180910390f35b61015560048036038101906101509190610a60565b61028e565b60405161016291906109f2565b60405180910390f35b6101856004803603810190610180919061096d565b6102d6565b60405161019291906109c8565b60405180910390f35b6101b560048036038101906101b0919061096d565b61034d565b6040516101c291906109c8565b60405180910390f35b6101e560048036038101906101e09190610a8d565b610370565b6040516101f291906109f2565b60405180910390f35b6000806102066103f7565b90506102138185856103ff565b600191505092915050565b6000600254905090565b6000806102336103f7565b90506102408582856105c8565b61024b858585610654565b60019150509392505050565b6000806102626103f7565b90506102838185856102748589610370565b61027e9190610afc565b6103ff565b600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000806102e16103f7565b905060006102ef8286610370565b905083811015610334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032b90610bb3565b60405180910390fd5b61034182868684036103ff565b60019250505092915050565b6000806103586103f7565b9050610365818585610654565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361046e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046590610c45565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d490610cd7565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516105bb91906109f2565b60405180910390a3505050565b60006105d48484610370565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461064e5781811015610640576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063790610d43565b60405180910390fd5b61064d84848484036103ff565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ba90610dd5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072990610e67565b60405180910390fd5b61073d8383836108ca565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156107c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ba90610ef9565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108b191906109f2565b60405180910390a36108c48484846108cf565b50505050565b505050565b505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610904826108d9565b9050919050565b610914816108f9565b811461091f57600080fd5b50565b6000813590506109318161090b565b92915050565b6000819050919050565b61094a81610937565b811461095557600080fd5b50565b60008135905061096781610941565b92915050565b60008060408385031215610984576109836108d4565b5b600061099285828601610922565b92505060206109a385828601610958565b9150509250929050565b60008115159050919050565b6109c2816109ad565b82525050565b60006020820190506109dd60008301846109b9565b92915050565b6109ec81610937565b82525050565b6000602082019050610a0760008301846109e3565b92915050565b600080600060608486031215610a2657610a256108d4565b5b6000610a3486828701610922565b9350506020610a4586828701610922565b9250506040610a5686828701610958565b9150509250925092565b600060208284031215610a7657610a756108d4565b5b6000610a8484828501610922565b91505092915050565b60008060408385031215610aa457610aa36108d4565b5b6000610ab285828601610922565b9250506020610ac385828601610922565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610b0782610937565b9150610b1283610937565b9250828201905080821115610b2a57610b29610acd565b5b92915050565b600082825260208201905092915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000610b9d602583610b30565b9150610ba882610b41565b604082019050919050565b60006020820190508181036000830152610bcc81610b90565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000610c2f602483610b30565b9150610c3a82610bd3565b604082019050919050565b60006020820190508181036000830152610c5e81610c22565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000610cc1602283610b30565b9150610ccc82610c65565b604082019050919050565b60006020820190508181036000830152610cf081610cb4565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b6000610d2d601d83610b30565b9150610d3882610cf7565b602082019050919050565b60006020820190508181036000830152610d5c81610d20565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b6000610dbf602583610b30565b9150610dca82610d63565b604082019050919050565b60006020820190508181036000830152610dee81610db2565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b6000610e51602383610b30565b9150610e5c82610df5565b604082019050919050565b60006020820190508181036000830152610e8081610e44565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b6000610ee3602683610b30565b9150610eee82610e87565b604082019050919050565b60006020820190508181036000830152610f1281610ed6565b905091905056fea26469706673582212201af30586fb0c9726887634543373816a162692c9d54b10d1f17ff104d3a1df5964736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c806370a082311161005b57806370a082311461013b578063a457c2d71461016b578063a9059cbb1461019b578063dd62ed3e146101cb57610088565b8063095ea7b31461008d57806318160ddd146100bd57806323b872dd146100db578063395093511461010b575b600080fd5b6100a760048036038101906100a2919061096d565b6101fb565b6040516100b491906109c8565b60405180910390f35b6100c561021e565b6040516100d291906109f2565b60405180910390f35b6100f560048036038101906100f09190610a0d565b610228565b60405161010291906109c8565b60405180910390f35b6101256004803603810190610120919061096d565b610257565b60405161013291906109c8565b60405180910390f35b61015560048036038101906101509190610a60565b61028e565b60405161016291906109f2565b60405180910390f35b6101856004803603810190610180919061096d565b6102d6565b60405161019291906109c8565b60405180910390f35b6101b560048036038101906101b0919061096d565b61034d565b6040516101c291906109c8565b60405180910390f35b6101e560048036038101906101e09190610a8d565b610370565b6040516101f291906109f2565b60405180910390f35b6000806102066103f7565b90506102138185856103ff565b600191505092915050565b6000600254905090565b6000806102336103f7565b90506102408582856105c8565b61024b858585610654565b60019150509392505050565b6000806102626103f7565b90506102838185856102748589610370565b61027e9190610afc565b6103ff565b600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000806102e16103f7565b905060006102ef8286610370565b905083811015610334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032b90610bb3565b60405180910390fd5b61034182868684036103ff565b60019250505092915050565b6000806103586103f7565b9050610365818585610654565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361046e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046590610c45565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d490610cd7565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516105bb91906109f2565b60405180910390a3505050565b60006105d48484610370565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461064e5781811015610640576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063790610d43565b60405180910390fd5b61064d84848484036103ff565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ba90610dd5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072990610e67565b60405180910390fd5b61073d8383836108ca565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156107c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ba90610ef9565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108b191906109f2565b60405180910390a36108c48484846108cf565b50505050565b505050565b505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610904826108d9565b9050919050565b610914816108f9565b811461091f57600080fd5b50565b6000813590506109318161090b565b92915050565b6000819050919050565b61094a81610937565b811461095557600080fd5b50565b60008135905061096781610941565b92915050565b60008060408385031215610984576109836108d4565b5b600061099285828601610922565b92505060206109a385828601610958565b9150509250929050565b60008115159050919050565b6109c2816109ad565b82525050565b60006020820190506109dd60008301846109b9565b92915050565b6109ec81610937565b82525050565b6000602082019050610a0760008301846109e3565b92915050565b600080600060608486031215610a2657610a256108d4565b5b6000610a3486828701610922565b9350506020610a4586828701610922565b9250506040610a5686828701610958565b9150509250925092565b600060208284031215610a7657610a756108d4565b5b6000610a8484828501610922565b91505092915050565b60008060408385031215610aa457610aa36108d4565b5b6000610ab285828601610922565b9250506020610ac385828601610922565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610b0782610937565b9150610b1283610937565b9250828201905080821115610b2a57610b29610acd565b5b92915050565b600082825260208201905092915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000610b9d602583610b30565b9150610ba882610b41565b604082019050919050565b60006020820190508181036000830152610bcc81610b90565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000610c2f602483610b30565b9150610c3a82610bd3565b604082019050919050565b60006020820190508181036000830152610c5e81610c22565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000610cc1602283610b30565b9150610ccc82610c65565b604082019050919050565b60006020820190508181036000830152610cf081610cb4565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b6000610d2d601d83610b30565b9150610d3882610cf7565b602082019050919050565b60006020820190508181036000830152610d5c81610d20565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b6000610dbf602583610b30565b9150610dca82610d63565b604082019050919050565b60006020820190508181036000830152610dee81610db2565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b6000610e51602383610b30565b9150610e5c82610df5565b604082019050919050565b60006020820190508181036000830152610e8081610e44565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b6000610ee3602683610b30565b9150610eee82610e87565b604082019050919050565b60006020820190508181036000830152610f1281610ed6565b905091905056fea26469706673582212201af30586fb0c9726887634543373816a162692c9d54b10d1f17ff104d3a1df5964736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/erc20/testdata/ERC20NoMetadata.sol b/precompiles/erc20/testdata/ERC20NoMetadata.sol
new file mode 100644
index 00000000..b412bad4
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20NoMetadata.sol
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
+
+pragma solidity ^0.8.0;
+
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+import "@openzeppelin/contracts/utils/Context.sol";
+
+/**
+ * @dev Implementation of the {IERC20} interface.
+ *
+ * This implementation is agnostic to the way tokens are created. This means
+ * that a supply mechanism has to be added in a derived contract using {_mint}.
+ * For a generic mechanism see {ERC20PresetMinterPauser}.
+ *
+ * TIP: For a detailed writeup see our guide
+ * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
+ * to implement supply mechanisms].
+ *
+ * The default value of {decimals} is 18. To change this, you should override
+ * this function so it returns a different value.
+ *
+ * We have followed general OpenZeppelin Contracts guidelines: functions revert
+ * instead returning `false` on failure. This behavior is nonetheless
+ * conventional and does not conflict with the expectations of ERC20
+ * applications.
+ *
+ * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
+ * This allows applications to reconstruct the allowance for all accounts just
+ * by listening to said events. Other implementations of the EIP may not emit
+ * these events, as it isn't required by the specification.
+ *
+ * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
+ * functions have been added to mitigate the well-known issues around setting
+ * allowances. See {IERC20-approve}.
+ */
+contract ERC20NoMetadata is Context, IERC20 {
+ mapping(address => uint256) private _balances;
+
+ mapping(address => mapping(address => uint256)) private _allowances;
+
+ uint256 private _totalSupply;
+
+ /**
+ * @dev Sets the values for {name} and {symbol}.
+ *
+ * All two of these values are immutable: they can only be set once during
+ * construction.
+ */
+ constructor() {}
+
+ /**
+ * @dev See {IERC20-totalSupply}.
+ */
+ function totalSupply() public view virtual override returns (uint256) {
+ return _totalSupply;
+ }
+
+ /**
+ * @dev See {IERC20-balanceOf}.
+ */
+ function balanceOf(
+ address account
+ ) public view virtual override returns (uint256) {
+ return _balances[account];
+ }
+
+ /**
+ * @dev See {IERC20-transfer}.
+ *
+ * Requirements:
+ *
+ * - `to` cannot be the zero address.
+ * - the caller must have a balance of at least `amount`.
+ */
+ function transfer(
+ address to,
+ uint256 amount
+ ) public virtual override returns (bool) {
+ address owner = _msgSender();
+ _transfer(owner, to, amount);
+ return true;
+ }
+
+ /**
+ * @dev See {IERC20-allowance}.
+ */
+ function allowance(
+ address owner,
+ address spender
+ ) public view virtual override returns (uint256) {
+ return _allowances[owner][spender];
+ }
+
+ /**
+ * @dev See {IERC20-approve}.
+ *
+ * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
+ * `transferFrom`. This is semantically equivalent to an infinite approval.
+ *
+ * Requirements:
+ *
+ * - `spender` cannot be the zero address.
+ */
+ function approve(
+ address spender,
+ uint256 amount
+ ) public virtual override returns (bool) {
+ address owner = _msgSender();
+ _approve(owner, spender, amount);
+ return true;
+ }
+
+ /**
+ * @dev See {IERC20-transferFrom}.
+ *
+ * Emits an {Approval} event indicating the updated allowance. This is not
+ * required by the EIP. See the note at the beginning of {ERC20}.
+ *
+ * NOTE: Does not update the allowance if the current allowance
+ * is the maximum `uint256`.
+ *
+ * Requirements:
+ *
+ * - `from` and `to` cannot be the zero address.
+ * - `from` must have a balance of at least `amount`.
+ * - the caller must have allowance for ``from``'s tokens of at least
+ * `amount`.
+ */
+ function transferFrom(
+ address from,
+ address to,
+ uint256 amount
+ ) public virtual override returns (bool) {
+ address spender = _msgSender();
+ _spendAllowance(from, spender, amount);
+ _transfer(from, to, amount);
+ return true;
+ }
+
+ /**
+ * @dev Atomically increases the allowance granted to `spender` by the caller.
+ *
+ * This is an alternative to {approve} that can be used as a mitigation for
+ * problems described in {IERC20-approve}.
+ *
+ * Emits an {Approval} event indicating the updated allowance.
+ *
+ * Requirements:
+ *
+ * - `spender` cannot be the zero address.
+ */
+ function increaseAllowance(
+ address spender,
+ uint256 addedValue
+ ) public virtual returns (bool) {
+ address owner = _msgSender();
+ _approve(owner, spender, allowance(owner, spender) + addedValue);
+ return true;
+ }
+
+ /**
+ * @dev Atomically decreases the allowance granted to `spender` by the caller.
+ *
+ * This is an alternative to {approve} that can be used as a mitigation for
+ * problems described in {IERC20-approve}.
+ *
+ * Emits an {Approval} event indicating the updated allowance.
+ *
+ * Requirements:
+ *
+ * - `spender` cannot be the zero address.
+ * - `spender` must have allowance for the caller of at least
+ * `subtractedValue`.
+ */
+ function decreaseAllowance(
+ address spender,
+ uint256 subtractedValue
+ ) public virtual returns (bool) {
+ address owner = _msgSender();
+ uint256 currentAllowance = allowance(owner, spender);
+ require(
+ currentAllowance >= subtractedValue,
+ "ERC20: decreased allowance below zero"
+ );
+ unchecked {
+ _approve(owner, spender, currentAllowance - subtractedValue);
+ }
+
+ return true;
+ }
+
+ /**
+ * @dev Moves `amount` of tokens from `from` to `to`.
+ *
+ * This internal function is equivalent to {transfer}, and can be used to
+ * e.g. implement automatic token fees, slashing mechanisms, etc.
+ *
+ * Emits a {Transfer} event.
+ *
+ * Requirements:
+ *
+ * - `from` cannot be the zero address.
+ * - `to` cannot be the zero address.
+ * - `from` must have a balance of at least `amount`.
+ */
+ function _transfer(
+ address from,
+ address to,
+ uint256 amount
+ ) internal virtual {
+ require(from != address(0), "ERC20: transfer from the zero address");
+ require(to != address(0), "ERC20: transfer to the zero address");
+
+ _beforeTokenTransfer(from, to, amount);
+
+ uint256 fromBalance = _balances[from];
+ require(
+ fromBalance >= amount,
+ "ERC20: transfer amount exceeds balance"
+ );
+ unchecked {
+ _balances[from] = fromBalance - amount;
+ // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
+ // decrementing then incrementing.
+ _balances[to] += amount;
+ }
+
+ emit Transfer(from, to, amount);
+
+ _afterTokenTransfer(from, to, amount);
+ }
+
+ /** @dev Creates `amount` tokens and assigns them to `account`, increasing
+ * the total supply.
+ *
+ * Emits a {Transfer} event with `from` set to the zero address.
+ *
+ * Requirements:
+ *
+ * - `account` cannot be the zero address.
+ */
+ function _mint(address account, uint256 amount) internal virtual {
+ require(account != address(0), "ERC20: mint to the zero address");
+
+ _beforeTokenTransfer(address(0), account, amount);
+
+ _totalSupply += amount;
+ unchecked {
+ // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
+ _balances[account] += amount;
+ }
+ emit Transfer(address(0), account, amount);
+
+ _afterTokenTransfer(address(0), account, amount);
+ }
+
+ /**
+ * @dev Destroys `amount` tokens from `account`, reducing the
+ * total supply.
+ *
+ * Emits a {Transfer} event with `to` set to the zero address.
+ *
+ * Requirements:
+ *
+ * - `account` cannot be the zero address.
+ * - `account` must have at least `amount` tokens.
+ */
+ function _burn(address account, uint256 amount) internal virtual {
+ require(account != address(0), "ERC20: burn from the zero address");
+
+ _beforeTokenTransfer(account, address(0), amount);
+
+ uint256 accountBalance = _balances[account];
+ require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
+ unchecked {
+ _balances[account] = accountBalance - amount;
+ // Overflow not possible: amount <= accountBalance <= totalSupply.
+ _totalSupply -= amount;
+ }
+
+ emit Transfer(account, address(0), amount);
+
+ _afterTokenTransfer(account, address(0), amount);
+ }
+
+ /**
+ * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
+ *
+ * This internal function is equivalent to `approve`, and can be used to
+ * e.g. set automatic allowances for certain subsystems, etc.
+ *
+ * Emits an {Approval} event.
+ *
+ * Requirements:
+ *
+ * - `owner` cannot be the zero address.
+ * - `spender` cannot be the zero address.
+ */
+ function _approve(
+ address owner,
+ address spender,
+ uint256 amount
+ ) internal virtual {
+ require(owner != address(0), "ERC20: approve from the zero address");
+ require(spender != address(0), "ERC20: approve to the zero address");
+
+ _allowances[owner][spender] = amount;
+ emit Approval(owner, spender, amount);
+ }
+
+ /**
+ * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
+ *
+ * Does not update the allowance amount in case of infinite allowance.
+ * Revert if not enough allowance is available.
+ *
+ * Might emit an {Approval} event.
+ */
+ function _spendAllowance(
+ address owner,
+ address spender,
+ uint256 amount
+ ) internal virtual {
+ uint256 currentAllowance = allowance(owner, spender);
+ if (currentAllowance != type(uint256).max) {
+ require(
+ currentAllowance >= amount,
+ "ERC20: insufficient allowance"
+ );
+ unchecked {
+ _approve(owner, spender, currentAllowance - amount);
+ }
+ }
+ }
+
+ /**
+ * @dev Hook that is called before any transfer of tokens. This includes
+ * minting and burning.
+ *
+ * Calling conditions:
+ *
+ * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
+ * will be transferred to `to`.
+ * - when `from` is zero, `amount` tokens will be minted for `to`.
+ * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
+ * - `from` and `to` are never both zero.
+ *
+ * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
+ */
+ function _beforeTokenTransfer(
+ address from,
+ address to,
+ uint256 amount
+ ) internal virtual {}
+
+ /**
+ * @dev Hook that is called after any transfer of tokens. This includes
+ * minting and burning.
+ *
+ * Calling conditions:
+ *
+ * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
+ * has been transferred to `to`.
+ * - when `from` is zero, `amount` tokens have been minted for `to`.
+ * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
+ * - `from` and `to` are never both zero.
+ *
+ * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
+ */
+ function _afterTokenTransfer(
+ address from,
+ address to,
+ uint256 amount
+ ) internal virtual {}
+}
diff --git a/precompiles/erc20/testdata/ERC20TestCaller.json b/precompiles/erc20/testdata/ERC20TestCaller.json
new file mode 100644
index 00000000..8d916470
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20TestCaller.json
@@ -0,0 +1,149 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "ERC20TestCaller",
+ "sourceName": "solidity/precompiles/erc20/testdata/ERC20TestCaller.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "tokenAddress",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "counter",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount_to_transfer",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount_to_send",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount_to_send_after",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testTransferAndSend",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "token",
+ "outputs": [
+ {
+ "internalType": "contract IERC20",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "aft",
+ "type": "bool"
+ }
+ ],
+ "name": "transferWithRevert",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount_to_transfer",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount_to_fail",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfersWithTry",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b50604051610f46380380610f46833981810160405281019061003291906100e3565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060018190555050610110565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b082610085565b9050919050565b6100c0816100a5565b81146100cb57600080fd5b50565b6000815190506100dd816100b7565b92915050565b6000602082840312156100f9576100f8610080565b5b6000610107848285016100ce565b91505092915050565b610e278061011f6000396000f3fe60806040526004361061004a5760003560e01c8063268d070a1461004f57806361bc221a1461006b5780636bc7b7cd14610096578063d0fedf55146100c6578063fc0c546a146100f6575b600080fd5b610069600480360381019061006491906107fc565b610121565b005b34801561007757600080fd5b506100806102bd565b60405161008d919061085e565b60405180910390f35b6100b060048036038101906100ab91906108b1565b6102c3565b6040516100bd919061094d565b60405180910390f35b6100e060048036038101906100db91906109a6565b6105ce565b6040516100ed919061094d565b60405180910390f35b34801561010257600080fd5b5061010b61073f565b6040516101189190610a6c565b60405180910390f35b6001600081548092919061013490610ab6565b919050555060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b8152600401610197929190610b1f565b6020604051808303816000875af11580156101b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101da9190610b5d565b90508061021c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021390610be7565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff1663d0fedf5585846001806040518563ffffffff1660e01b815260040161025c9493929190610c07565b6020604051808303816000875af192505050801561029857506040513d601f19601f820116820180604052508101906102959190610b5d565b60015b1561029f57505b600160008154809291906102b290610ab6565b919050555050505050565b60015481565b6000808773ffffffffffffffffffffffffffffffffffffffff16866040516102ea90610c7d565b60006040518083038185875af1925050503d8060008114610327576040519150601f19603f3d011682016040523d82523d6000602084013e61032c565b606091505b5050905080610370576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036790610d04565b60405180910390fd5b83156103d0576001600081548092919061038990610ab6565b919050555060006103cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103c690610d70565b60405180910390fd5b5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a8a6040518363ffffffff1660e01b815260040161042e929190610b1f565b6020604051808303816000875af115801561044d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104719190610b5d565b9050806104b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104aa90610d04565b60405180910390fd5b831561051357600160008154809291906104cc90610ab6565b91905055506000610512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050990610d70565b60405180910390fd5b5b8873ffffffffffffffffffffffffffffffffffffffff168660405161053790610c7d565b60006040518083038185875af1925050503d8060008114610574576040519150601f19603f3d011682016040523d82523d6000602084013e610579565b606091505b505080925050816105bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105b690610d04565b60405180910390fd5b81925050509695505050505050565b6000600160008154809291906105e390610ab6565b919050555060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb87876040518363ffffffff1660e01b8152600401610646929190610d9f565b6020604051808303816000875af1158015610665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106899190610b5d565b905083156106d35760006106d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c990610d70565b60405180910390fd5b5b600160008154809291906106e690610dc8565b91905055508215610733576000610732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072990610d70565b60405180910390fd5b5b80915050949350505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061079382610768565b9050919050565b6107a381610788565b81146107ae57600080fd5b50565b6000813590506107c08161079a565b92915050565b6000819050919050565b6107d9816107c6565b81146107e457600080fd5b50565b6000813590506107f6816107d0565b92915050565b60008060006060848603121561081557610814610763565b5b6000610823868287016107b1565b9350506020610834868287016107e7565b9250506040610845868287016107e7565b9150509250925092565b610858816107c6565b82525050565b6000602082019050610873600083018461084f565b92915050565b60008115159050919050565b61088e81610879565b811461089957600080fd5b50565b6000813590506108ab81610885565b92915050565b60008060008060008060c087890312156108ce576108cd610763565b5b60006108dc89828a016107b1565b96505060206108ed89828a016107e7565b95505060406108fe89828a016107e7565b945050606061090f89828a016107e7565b935050608061092089828a0161089c565b92505060a061093189828a0161089c565b9150509295509295509295565b61094781610879565b82525050565b6000602082019050610962600083018461093e565b92915050565b600061097382610768565b9050919050565b61098381610968565b811461098e57600080fd5b50565b6000813590506109a08161097a565b92915050565b600080600080608085870312156109c0576109bf610763565b5b60006109ce87828801610991565b94505060206109df878288016107e7565b93505060406109f08782880161089c565b9250506060610a018782880161089c565b91505092959194509250565b6000819050919050565b6000610a32610a2d610a2884610768565b610a0d565b610768565b9050919050565b6000610a4482610a17565b9050919050565b6000610a5682610a39565b9050919050565b610a6681610a4b565b82525050565b6000602082019050610a816000830184610a5d565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610ac1826107c6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610af357610af2610a87565b5b600182019050919050565b6000610b0982610a39565b9050919050565b610b1981610afe565b82525050565b6000604082019050610b346000830185610b10565b610b41602083018461084f565b9392505050565b600081519050610b5781610885565b92915050565b600060208284031215610b7357610b72610763565b5b6000610b8184828501610b48565b91505092915050565b600082825260208201905092915050565b7f6661696c20746f207472616e7366657200000000000000000000000000000000600082015250565b6000610bd1601083610b8a565b9150610bdc82610b9b565b602082019050919050565b60006020820190508181036000830152610c0081610bc4565b9050919050565b6000608082019050610c1c6000830187610b10565b610c29602083018661084f565b610c36604083018561093e565b610c43606083018461093e565b95945050505050565b600081905092915050565b50565b6000610c67600083610c4c565b9150610c7282610c57565b600082019050919050565b6000610c8882610c5a565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000610cee602183610b8a565b9150610cf982610c92565b604082019050919050565b60006020820190508181036000830152610d1d81610ce1565b9050919050565b7f7265766572742068657265000000000000000000000000000000000000000000600082015250565b6000610d5a600b83610b8a565b9150610d6582610d24565b602082019050919050565b60006020820190508181036000830152610d8981610d4d565b9050919050565b610d9981610968565b82525050565b6000604082019050610db46000830185610d90565b610dc1602083018461084f565b9392505050565b6000610dd3826107c6565b915060008203610de657610de5610a87565b5b60018203905091905056fea2646970667358221220585fa7c4d4a54121bbfa7152809da68f2c4de484e09def8d1501a0fb7048e3f064736f6c63430008130033",
+ "deployedBytecode": "0x60806040526004361061004a5760003560e01c8063268d070a1461004f57806361bc221a1461006b5780636bc7b7cd14610096578063d0fedf55146100c6578063fc0c546a146100f6575b600080fd5b610069600480360381019061006491906107fc565b610121565b005b34801561007757600080fd5b506100806102bd565b60405161008d919061085e565b60405180910390f35b6100b060048036038101906100ab91906108b1565b6102c3565b6040516100bd919061094d565b60405180910390f35b6100e060048036038101906100db91906109a6565b6105ce565b6040516100ed919061094d565b60405180910390f35b34801561010257600080fd5b5061010b61073f565b6040516101189190610a6c565b60405180910390f35b6001600081548092919061013490610ab6565b919050555060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b8152600401610197929190610b1f565b6020604051808303816000875af11580156101b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101da9190610b5d565b90508061021c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021390610be7565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff1663d0fedf5585846001806040518563ffffffff1660e01b815260040161025c9493929190610c07565b6020604051808303816000875af192505050801561029857506040513d601f19601f820116820180604052508101906102959190610b5d565b60015b1561029f57505b600160008154809291906102b290610ab6565b919050555050505050565b60015481565b6000808773ffffffffffffffffffffffffffffffffffffffff16866040516102ea90610c7d565b60006040518083038185875af1925050503d8060008114610327576040519150601f19603f3d011682016040523d82523d6000602084013e61032c565b606091505b5050905080610370576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036790610d04565b60405180910390fd5b83156103d0576001600081548092919061038990610ab6565b919050555060006103cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103c690610d70565b60405180910390fd5b5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a8a6040518363ffffffff1660e01b815260040161042e929190610b1f565b6020604051808303816000875af115801561044d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104719190610b5d565b9050806104b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104aa90610d04565b60405180910390fd5b831561051357600160008154809291906104cc90610ab6565b91905055506000610512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050990610d70565b60405180910390fd5b5b8873ffffffffffffffffffffffffffffffffffffffff168660405161053790610c7d565b60006040518083038185875af1925050503d8060008114610574576040519150601f19603f3d011682016040523d82523d6000602084013e610579565b606091505b505080925050816105bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105b690610d04565b60405180910390fd5b81925050509695505050505050565b6000600160008154809291906105e390610ab6565b919050555060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb87876040518363ffffffff1660e01b8152600401610646929190610d9f565b6020604051808303816000875af1158015610665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106899190610b5d565b905083156106d35760006106d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c990610d70565b60405180910390fd5b5b600160008154809291906106e690610dc8565b91905055508215610733576000610732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072990610d70565b60405180910390fd5b5b80915050949350505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061079382610768565b9050919050565b6107a381610788565b81146107ae57600080fd5b50565b6000813590506107c08161079a565b92915050565b6000819050919050565b6107d9816107c6565b81146107e457600080fd5b50565b6000813590506107f6816107d0565b92915050565b60008060006060848603121561081557610814610763565b5b6000610823868287016107b1565b9350506020610834868287016107e7565b9250506040610845868287016107e7565b9150509250925092565b610858816107c6565b82525050565b6000602082019050610873600083018461084f565b92915050565b60008115159050919050565b61088e81610879565b811461089957600080fd5b50565b6000813590506108ab81610885565b92915050565b60008060008060008060c087890312156108ce576108cd610763565b5b60006108dc89828a016107b1565b96505060206108ed89828a016107e7565b95505060406108fe89828a016107e7565b945050606061090f89828a016107e7565b935050608061092089828a0161089c565b92505060a061093189828a0161089c565b9150509295509295509295565b61094781610879565b82525050565b6000602082019050610962600083018461093e565b92915050565b600061097382610768565b9050919050565b61098381610968565b811461098e57600080fd5b50565b6000813590506109a08161097a565b92915050565b600080600080608085870312156109c0576109bf610763565b5b60006109ce87828801610991565b94505060206109df878288016107e7565b93505060406109f08782880161089c565b9250506060610a018782880161089c565b91505092959194509250565b6000819050919050565b6000610a32610a2d610a2884610768565b610a0d565b610768565b9050919050565b6000610a4482610a17565b9050919050565b6000610a5682610a39565b9050919050565b610a6681610a4b565b82525050565b6000602082019050610a816000830184610a5d565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610ac1826107c6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610af357610af2610a87565b5b600182019050919050565b6000610b0982610a39565b9050919050565b610b1981610afe565b82525050565b6000604082019050610b346000830185610b10565b610b41602083018461084f565b9392505050565b600081519050610b5781610885565b92915050565b600060208284031215610b7357610b72610763565b5b6000610b8184828501610b48565b91505092915050565b600082825260208201905092915050565b7f6661696c20746f207472616e7366657200000000000000000000000000000000600082015250565b6000610bd1601083610b8a565b9150610bdc82610b9b565b602082019050919050565b60006020820190508181036000830152610c0081610bc4565b9050919050565b6000608082019050610c1c6000830187610b10565b610c29602083018661084f565b610c36604083018561093e565b610c43606083018461093e565b95945050505050565b600081905092915050565b50565b6000610c67600083610c4c565b9150610c7282610c57565b600082019050919050565b6000610c8882610c5a565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000610cee602183610b8a565b9150610cf982610c92565b604082019050919050565b60006020820190508181036000830152610d1d81610ce1565b9050919050565b7f7265766572742068657265000000000000000000000000000000000000000000600082015250565b6000610d5a600b83610b8a565b9150610d6582610d24565b602082019050919050565b60006020820190508181036000830152610d8981610d4d565b9050919050565b610d9981610968565b82525050565b6000604082019050610db46000830185610d90565b610dc1602083018461084f565b9392505050565b6000610dd3826107c6565b915060008203610de657610de5610a87565b5b60018203905091905056fea2646970667358221220585fa7c4d4a54121bbfa7152809da68f2c4de484e09def8d1501a0fb7048e3f064736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/erc20/testdata/ERC20TestCaller.sol b/precompiles/erc20/testdata/ERC20TestCaller.sol
new file mode 100644
index 00000000..dabb16e5
--- /dev/null
+++ b/precompiles/erc20/testdata/ERC20TestCaller.sol
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../IERC20.sol" as erc20Precompile;
+
+/// @title ERC20TestCaller
+/// @author Evmos Core Team
+/// @dev This contract is used to test external contract calls to the ERC20 precompile.
+contract ERC20TestCaller {
+ erc20Precompile.IERC20 public token;
+ uint256 public counter;
+
+ constructor(address tokenAddress) {
+ token = erc20Precompile.IERC20(tokenAddress);
+ counter = 0;
+ }
+
+ function transferWithRevert(
+ address to,
+ uint256 amount,
+ bool before,
+ bool aft
+ ) public payable returns (bool) {
+ counter++;
+
+ bool res = token.transfer(to, amount);
+
+ if (before) {
+ require(false, "revert here");
+ }
+
+ counter--;
+
+ if (aft) {
+ require(false, "revert here");
+ }
+ return res;
+ }
+
+ function testTransferAndSend(
+ address payable _source,
+ uint256 amount_to_transfer,
+ uint256 amount_to_send,
+ uint256 amount_to_send_after,
+ bool _before,
+ bool _after
+ ) public payable returns (bool) {
+ (bool sent, ) = _source.call{value: amount_to_send}("");
+ require(sent, "Failed to send Ether to delegator");
+
+ if (_before) {
+ counter++;
+ require(false, "revert here");
+ }
+
+ bool res = token.transfer(_source, amount_to_transfer);
+ require(res, "Failed to send Ether to delegator");
+
+ if (_after) {
+ counter++;
+ require(false, "revert here");
+ }
+
+ (sent, ) = _source.call{value: amount_to_send_after}("");
+ require(sent, "Failed to send Ether to delegator");
+
+ return sent;
+ }
+
+ function transfersWithTry(
+ address payable receiver,
+ uint256 amount_to_transfer,
+ uint256 amount_to_fail
+ ) public payable {
+ counter++;
+ bool res = token.transfer(receiver, amount_to_transfer);
+ require(res, "fail to transfer");
+ try
+ ERC20TestCaller(address(this))
+ .transferWithRevert(
+ receiver,
+ amount_to_fail,
+ true,
+ true
+ )
+ {} catch {}
+ counter++;
+ }
+}
diff --git a/precompiles/erc20/testdata/erc20_allowance_caller.go b/precompiles/erc20/testdata/erc20_allowance_caller.go
new file mode 100644
index 00000000..46a47ca7
--- /dev/null
+++ b/precompiles/erc20/testdata/erc20_allowance_caller.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadERC20AllowanceCaller() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("ERC20AllowanceCaller.json")
+}
diff --git a/precompiles/erc20/testdata/erc20_no_metadata.go b/precompiles/erc20/testdata/erc20_no_metadata.go
new file mode 100644
index 00000000..5b5b7c0d
--- /dev/null
+++ b/precompiles/erc20/testdata/erc20_no_metadata.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadERC20NoMetadataContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("ERC20NoMetadata.json")
+}
diff --git a/precompiles/erc20/testdata/erc20_test_caller.go b/precompiles/erc20/testdata/erc20_test_caller.go
new file mode 100644
index 00000000..58bc5b01
--- /dev/null
+++ b/precompiles/erc20/testdata/erc20_test_caller.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadERC20TestCaller() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("ERC20TestCaller.json")
+}
diff --git a/precompiles/erc20/testdata/erc20minter_openzeppelinv5.go b/precompiles/erc20/testdata/erc20minter_openzeppelinv5.go
new file mode 100644
index 00000000..e3604dbe
--- /dev/null
+++ b/precompiles/erc20/testdata/erc20minter_openzeppelinv5.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadERC20MinterV5Contract() (evmtypes.CompiledContract, error) {
+ return contractutils.LegacyLoadContractFromJSONFile("ERC20Minter_OpenZeppelinV5.json")
+}
diff --git a/precompiles/erc20/tx.go b/precompiles/erc20/tx.go
new file mode 100644
index 00000000..a4f69840
--- /dev/null
+++ b/precompiles/erc20/tx.go
@@ -0,0 +1,142 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package erc20
+
+import (
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // TransferMethod defines the ABI method name for the ERC-20 transfer
+ // transaction.
+ TransferMethod = "transfer"
+ // TransferFromMethod defines the ABI method name for the ERC-20 transferFrom
+ // transaction.
+ TransferFromMethod = "transferFrom"
+)
+
+// SendMsgURL defines the authorization type for MsgSend
+var SendMsgURL = sdk.MsgTypeURL(&banktypes.MsgSend{})
+
+// Transfer executes a direct transfer from the caller address to the
+// destination address.
+func (p *Precompile) Transfer(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ from := contract.CallerAddress
+ to, amount, err := ParseTransferArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ return p.transfer(ctx, contract, stateDB, method, from, to, amount)
+}
+
+// TransferFrom executes a transfer on behalf of the specified from address in
+// the call data to the destination address.
+func (p *Precompile) TransferFrom(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ from, to, amount, err := ParseTransferFromArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ return p.transfer(ctx, contract, stateDB, method, from, to, amount)
+}
+
+// transfer is a common function that handles transfers for the ERC-20 Transfer
+// and TransferFrom methods. It executes a bank Send message if the spender is
+// the sender of the transfer, otherwise it executes an authorization.
+func (p *Precompile) transfer(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ from, to common.Address,
+ amount *big.Int,
+) (data []byte, err error) {
+ coins := sdk.Coins{{Denom: p.tokenPair.Denom, Amount: math.NewIntFromBigInt(amount)}}
+
+ msg := banktypes.NewMsgSend(from.Bytes(), to.Bytes(), coins)
+
+ if err = msg.ValidateBasic(); err != nil {
+ return nil, err
+ }
+
+ isTransferFrom := method.Name == TransferFromMethod
+ owner := sdk.AccAddress(from.Bytes())
+ spenderAddr := contract.CallerAddress
+ spender := sdk.AccAddress(spenderAddr.Bytes()) // aka. grantee
+ ownerIsSpender := spender.Equals(owner)
+
+ var prevAllowance *big.Int
+ if ownerIsSpender {
+ msgSrv := bankkeeper.NewMsgServerImpl(p.bankKeeper)
+ _, err = msgSrv.Send(sdk.WrapSDKContext(ctx), msg)
+ } else {
+ _, _, prevAllowance, err = GetAuthzExpirationAndAllowance(p.AuthzKeeper, ctx, spenderAddr, from, p.tokenPair.Denom)
+ if err != nil {
+ return nil, ConvertErrToERC20Error(errorsmod.Wrapf(authz.ErrNoAuthorizationFound, err.Error()))
+ }
+
+ _, err = p.AuthzKeeper.DispatchActions(ctx, spender, []sdk.Msg{msg})
+ }
+
+ if err != nil {
+ err = ConvertErrToERC20Error(err)
+ // This should return an error to avoid the contract from being executed and an event being emitted
+ return nil, err
+ }
+
+ // TODO: where should we get this
+ if p.tokenPair.Denom == utils.BaseDenom {
+ p.SetBalanceChangeEntries(cmn.NewBalanceChangeEntry(from, msg.Amount.AmountOf(utils.BaseDenom).BigInt(), cmn.Sub),
+ cmn.NewBalanceChangeEntry(to, msg.Amount.AmountOf(utils.BaseDenom).BigInt(), cmn.Add))
+ }
+
+ if err = p.EmitTransferEvent(ctx, stateDB, from, to, amount); err != nil {
+ return nil, err
+ }
+
+ // NOTE: if it's a direct transfer, we return here but if used through transferFrom,
+ // we need to emit the approval event with the new allowance.
+ if !isTransferFrom {
+ return method.Outputs.Pack(true)
+ }
+
+ var newAllowance *big.Int
+ if ownerIsSpender {
+ // NOTE: in case the spender is the owner we emit an approval event with
+ // the maxUint256 value.
+ newAllowance = abi.MaxUint256
+ } else {
+ newAllowance = new(big.Int).Sub(prevAllowance, amount)
+ }
+
+ if err = p.EmitApprovalEvent(ctx, stateDB, from, spenderAddr, newAllowance); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
diff --git a/precompiles/erc20/tx_test.go b/precompiles/erc20/tx_test.go
new file mode 100644
index 00000000..673292f0
--- /dev/null
+++ b/precompiles/erc20/tx_test.go
@@ -0,0 +1,259 @@
+package erc20_test
+
+import (
+ "math/big"
+ "time"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ erc20types "github.com/evmos/evmos/v19/x/erc20/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+var (
+ tokenDenom = "xmpl"
+ // XMPLCoin is a dummy coin used for testing purposes.
+ XMPLCoin = sdk.NewCoins(sdk.NewInt64Coin(tokenDenom, 1e18))
+ // toAddr is a dummy address used for testing purposes.
+ toAddr = utiltx.GenerateAddress()
+)
+
+func (s *PrecompileTestSuite) TestTransfer() {
+ method := s.precompile.Methods[erc20.TransferMethod]
+ // fromAddr is the address of the keyring account used for testing.
+ fromAddr := s.keyring.GetKey(0).Addr
+ testcases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func()
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - negative amount",
+ func() []interface{} {
+ return []interface{}{toAddr, big.NewInt(-1)}
+ },
+ func() {},
+ true,
+ "-1xmpl: invalid coins",
+ },
+ {
+ "fail - invalid to address",
+ func() []interface{} {
+ return []interface{}{"", big.NewInt(100)}
+ },
+ func() {},
+ true,
+ "invalid to address",
+ },
+ {
+ "fail - invalid amount",
+ func() []interface{} {
+ return []interface{}{toAddr, ""}
+ },
+ func() {},
+ true,
+ "invalid amount",
+ },
+ {
+ "fail - not enough balance",
+ func() []interface{} {
+ return []interface{}{toAddr, big.NewInt(2e18)}
+ },
+ func() {},
+ true,
+ erc20.ErrTransferAmountExceedsBalance.Error(),
+ },
+ {
+ "pass",
+ func() []interface{} {
+ return []interface{}{toAddr, big.NewInt(100)}
+ },
+ func() {
+ toAddrBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), toAddr.Bytes(), tokenDenom)
+ s.Require().Equal(big.NewInt(100), toAddrBalance.Amount.BigInt(), "expected toAddr to have 100 XMPL")
+ },
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ stateDB := s.network.GetStateDB()
+
+ var contract *vm.Contract
+ contract, ctx := testutil.NewPrecompileContract(s.T(), s.network.GetContext(), fromAddr, s.precompile, 0)
+
+ // Mint some coins to the module account and then send to the from address
+ err := s.network.App.BankKeeper.MintCoins(s.network.GetContext(), erc20types.ModuleName, XMPLCoin)
+ s.Require().NoError(err, "failed to mint coins")
+ err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(s.network.GetContext(), erc20types.ModuleName, fromAddr.Bytes(), XMPLCoin)
+ s.Require().NoError(err, "failed to send coins from module to account")
+
+ _, err = s.precompile.Transfer(ctx, contract, stateDB, &method, tc.malleate())
+ if tc.expErr {
+ s.Require().Error(err, "expected transfer transaction to fail")
+ s.Require().Contains(err.Error(), tc.errContains, "expected transfer transaction to fail with specific error")
+ } else {
+ s.Require().NoError(err, "expected transfer transaction succeeded")
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestTransferFrom() {
+ method := s.precompile.Methods[erc20.TransferFromMethod]
+ // owner of the tokens
+ owner := s.keyring.GetKey(0)
+ // spender of the tokens
+ spender := s.keyring.GetKey(1)
+
+ testcases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func()
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - negative amount",
+ func() []interface{} {
+ return []interface{}{owner.Addr, toAddr, big.NewInt(-1)}
+ },
+ func() {},
+ true,
+ "-1xmpl: invalid coins",
+ },
+ {
+ "fail - invalid from address",
+ func() []interface{} {
+ return []interface{}{"", toAddr, big.NewInt(100)}
+ },
+ func() {},
+ true,
+ "invalid from address",
+ },
+ {
+ "fail - invalid to address",
+ func() []interface{} {
+ return []interface{}{owner.Addr, "", big.NewInt(100)}
+ },
+ func() {},
+ true,
+ "invalid to address",
+ },
+ {
+ "fail - invalid amount",
+ func() []interface{} {
+ return []interface{}{owner.Addr, toAddr, ""}
+ },
+ func() {},
+ true,
+ "invalid amount",
+ },
+ {
+ "fail - not enough allowance",
+ func() []interface{} {
+ return []interface{}{owner.Addr, toAddr, big.NewInt(100)}
+ },
+ func() {},
+ true,
+ erc20.ErrInsufficientAllowance.Error(),
+ },
+ {
+ "fail - not enough balance",
+ func() []interface{} {
+ expiration := time.Now().Add(time.Hour)
+ err := s.network.App.AuthzKeeper.SaveGrant(
+ s.network.GetContext(),
+ spender.AccAddr,
+ owner.AccAddr,
+ &banktypes.SendAuthorization{SpendLimit: sdk.Coins{sdk.Coin{Denom: s.tokenDenom, Amount: math.NewInt(5e18)}}},
+ &expiration,
+ )
+ s.Require().NoError(err, "failed to save grant")
+
+ return []interface{}{owner.Addr, toAddr, big.NewInt(2e18)}
+ },
+ func() {},
+ true,
+ erc20.ErrTransferAmountExceedsBalance.Error(),
+ },
+ {
+ "pass - spend on behalf of other account",
+ func() []interface{} {
+ expiration := time.Now().Add(time.Hour)
+ err := s.network.App.AuthzKeeper.SaveGrant(
+ s.network.GetContext(),
+ spender.AccAddr,
+ owner.AccAddr,
+ &banktypes.SendAuthorization{SpendLimit: sdk.Coins{sdk.Coin{Denom: tokenDenom, Amount: math.NewInt(300)}}},
+ &expiration,
+ )
+ s.Require().NoError(err, "failed to save grant")
+
+ return []interface{}{owner.Addr, toAddr, big.NewInt(100)}
+ },
+ func() {
+ toAddrBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), toAddr.Bytes(), tokenDenom)
+ s.Require().Equal(big.NewInt(100), toAddrBalance.Amount.BigInt(), "expected toAddr to have 100 XMPL")
+ },
+ false,
+ "",
+ },
+ {
+ "pass - spend on behalf of own account",
+ func() []interface{} {
+ // Mint some coins to the module account and then send to the spender address
+ err := s.network.App.BankKeeper.MintCoins(s.network.GetContext(), erc20types.ModuleName, XMPLCoin)
+ s.Require().NoError(err, "failed to mint coins")
+ err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(s.network.GetContext(), erc20types.ModuleName, spender.AccAddr, XMPLCoin)
+ s.Require().NoError(err, "failed to send coins from module to account")
+
+ // NOTE: no authorization is necessary to spend on behalf of the same account
+ return []interface{}{spender.Addr, toAddr, big.NewInt(100)}
+ },
+ func() {
+ toAddrBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), toAddr.Bytes(), tokenDenom)
+ s.Require().Equal(big.NewInt(100), toAddrBalance.Amount.BigInt(), "expected toAddr to have 100 XMPL")
+ },
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ stateDB := s.network.GetStateDB()
+
+ var contract *vm.Contract
+ contract, ctx := testutil.NewPrecompileContract(s.T(), s.network.GetContext(), spender.Addr, s.precompile, 0)
+
+ // Mint some coins to the module account and then send to the from address
+ err := s.network.App.BankKeeper.MintCoins(s.network.GetContext(), erc20types.ModuleName, XMPLCoin)
+ s.Require().NoError(err, "failed to mint coins")
+ err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(s.network.GetContext(), erc20types.ModuleName, owner.AccAddr, XMPLCoin)
+ s.Require().NoError(err, "failed to send coins from module to account")
+
+ _, err = s.precompile.TransferFrom(ctx, contract, stateDB, &method, tc.malleate())
+ if tc.expErr {
+ s.Require().Error(err, "expected transfer transaction to fail")
+ s.Require().Contains(err.Error(), tc.errContains, "expected transfer transaction to fail with specific error")
+ } else {
+ s.Require().NoError(err, "expected transfer transaction succeeded")
+ tc.postCheck()
+ }
+ })
+ }
+}
diff --git a/precompiles/erc20/types.go b/precompiles/erc20/types.go
new file mode 100644
index 00000000..3b52ad75
--- /dev/null
+++ b/precompiles/erc20/types.go
@@ -0,0 +1,159 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package erc20
+
+import (
+ "fmt"
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+const (
+ // WEVMOSContractMainnet is the WEVMOS contract address for mainnet
+ WEVMOSContractMainnet = "0xD4949664cD82660AaE99bEdc034a0deA8A0bd517"
+ // WEVMOSContractTestnet is the WEVMOS contract address for testnet
+ WEVMOSContractTestnet = "0xcc491f589b45d4a3c679016195b3fb87d7848210"
+)
+
+// EventTransfer defines the event data for the ERC20 Transfer events.
+type EventTransfer struct {
+ From common.Address
+ To common.Address
+ Value *big.Int
+}
+
+// EventApproval defines the event data for the ERC20 Approval events.
+type EventApproval struct {
+ Owner common.Address
+ Spender common.Address
+ Value *big.Int
+}
+
+// ParseTransferArgs parses the arguments from the transfer method and returns
+// the destination address (to) and amount.
+func ParseTransferArgs(args []interface{}) (
+ to common.Address, amount *big.Int, err error,
+) {
+ if len(args) != 2 {
+ return common.Address{}, nil, fmt.Errorf("invalid number of arguments; expected 2; got: %d", len(args))
+ }
+
+ to, ok := args[0].(common.Address)
+ if !ok {
+ return common.Address{}, nil, fmt.Errorf("invalid to address: %v", args[0])
+ }
+
+ amount, ok = args[1].(*big.Int)
+ if !ok {
+ return common.Address{}, nil, fmt.Errorf("invalid amount: %v", args[1])
+ }
+
+ return to, amount, nil
+}
+
+// ParseTransferFromArgs parses the arguments from the transferFrom method and returns
+// the sender address (from), destination address (to) and amount.
+func ParseTransferFromArgs(args []interface{}) (
+ from, to common.Address, amount *big.Int, err error,
+) {
+ if len(args) != 3 {
+ return common.Address{}, common.Address{}, nil, fmt.Errorf("invalid number of arguments; expected 3; got: %d", len(args))
+ }
+
+ from, ok := args[0].(common.Address)
+ if !ok {
+ return common.Address{}, common.Address{}, nil, fmt.Errorf("invalid from address: %v", args[0])
+ }
+
+ to, ok = args[1].(common.Address)
+ if !ok {
+ return common.Address{}, common.Address{}, nil, fmt.Errorf("invalid to address: %v", args[1])
+ }
+
+ amount, ok = args[2].(*big.Int)
+ if !ok {
+ return common.Address{}, common.Address{}, nil, fmt.Errorf("invalid amount: %v", args[2])
+ }
+
+ return from, to, amount, nil
+}
+
+// ParseApproveArgs parses the approval arguments and returns the spender address
+// and amount.
+func ParseApproveArgs(args []interface{}) (
+ spender common.Address, amount *big.Int, err error,
+) {
+ if len(args) != 2 {
+ return common.Address{}, nil, fmt.Errorf("invalid number of arguments; expected 2; got: %d", len(args))
+ }
+
+ spender, ok := args[0].(common.Address)
+ if !ok {
+ return common.Address{}, nil, fmt.Errorf("invalid spender address: %v", args[0])
+ }
+
+ amount, ok = args[1].(*big.Int)
+ if !ok {
+ return common.Address{}, nil, fmt.Errorf("invalid amount: %v", args[1])
+ }
+
+ return spender, amount, nil
+}
+
+// ParseAllowanceArgs parses the allowance arguments and returns the owner and
+// the spender addresses.
+func ParseAllowanceArgs(args []interface{}) (
+ owner, spender common.Address, err error,
+) {
+ if len(args) != 2 {
+ return common.Address{}, common.Address{}, fmt.Errorf("invalid number of arguments; expected 2; got: %d", len(args))
+ }
+
+ owner, ok := args[0].(common.Address)
+ if !ok {
+ return common.Address{}, common.Address{}, fmt.Errorf("invalid owner address: %v", args[0])
+ }
+
+ spender, ok = args[1].(common.Address)
+ if !ok {
+ return common.Address{}, common.Address{}, fmt.Errorf("invalid spender address: %v", args[1])
+ }
+
+ return owner, spender, nil
+}
+
+// ParseBalanceOfArgs parses the balanceOf arguments and returns the account address.
+func ParseBalanceOfArgs(args []interface{}) (common.Address, error) {
+ if len(args) != 1 {
+ return common.Address{}, fmt.Errorf("invalid number of arguments; expected 1; got: %d", len(args))
+ }
+
+ account, ok := args[0].(common.Address)
+ if !ok {
+ return common.Address{}, fmt.Errorf("invalid account address: %v", args[0])
+ }
+
+ return account, nil
+}
+
+// updateOrAddCoin replaces the coin of the given denomination in the coins slice or adds it if it
+// does not exist yet.
+//
+// CONTRACT: Requires the coins struct to contain at most one coin of the given
+// denom.
+func updateOrAddCoin(coins sdk.Coins, coin sdk.Coin) sdk.Coins {
+ for idx, c := range coins {
+ if c.Denom == coin.Denom {
+ coins[idx] = coin
+ return coins
+ }
+ }
+
+ // NOTE: if no coin with the correct denomination is in the coins slice, we
+ // add it here.
+ return coins.Add(coin)
+}
diff --git a/precompiles/erc20/types_test.go b/precompiles/erc20/types_test.go
new file mode 100644
index 00000000..92a63a58
--- /dev/null
+++ b/precompiles/erc20/types_test.go
@@ -0,0 +1,307 @@
+package erc20_test
+
+import (
+ "math/big"
+
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+)
+
+//nolint:dupl // these tests are not duplicates
+func (s *PrecompileTestSuite) TestParseTransferArgs() {
+ to := utiltx.GenerateAddress()
+ amount := big.NewInt(100)
+
+ testcases := []struct {
+ name string
+ args []interface{}
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "pass - correct arguments",
+ args: []interface{}{
+ to,
+ amount,
+ },
+ expPass: true,
+ },
+ {
+ name: "fail - invalid to address",
+ args: []interface{}{
+ "invalid address",
+ amount,
+ },
+ errContains: "invalid to address",
+ },
+ {
+ name: "fail - invalid amount",
+ args: []interface{}{
+ to,
+ "invalid amount",
+ },
+ errContains: "invalid amount",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ args: []interface{}{
+ 1, 2, 3,
+ },
+ errContains: "invalid number of arguments",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ to, amount, err := erc20.ParseTransferArgs(tc.args)
+ if tc.expPass {
+ s.Require().NoError(err, "unexpected error parsing the transfer arguments")
+ s.Require().Equal(to, tc.args[0], "expected different to address")
+ s.Require().Equal(amount, tc.args[1], "expected different amount")
+ } else {
+ s.Require().Error(err, "expected an error parsing the transfer arguments")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestParseTransferFromArgs() {
+ from := utiltx.GenerateAddress()
+ to := utiltx.GenerateAddress()
+ amount := big.NewInt(100)
+
+ testcases := []struct {
+ name string
+ args []interface{}
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "pass - correct arguments",
+ args: []interface{}{
+ from,
+ to,
+ amount,
+ },
+ expPass: true,
+ },
+ {
+ name: "fail - invalid from address",
+ args: []interface{}{
+ "invalid address",
+ to,
+ amount,
+ },
+ errContains: "invalid from address",
+ },
+ {
+ name: "fail - invalid to address",
+ args: []interface{}{
+ from,
+ "invalid address",
+ amount,
+ },
+ errContains: "invalid to address",
+ },
+ {
+ name: "fail - invalid amount",
+ args: []interface{}{
+ from,
+ to,
+ "invalid amount",
+ },
+ errContains: "invalid amount",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ args: []interface{}{
+ 1, 2, 3, 4,
+ },
+ errContains: "invalid number of arguments",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ from, to, amount, err := erc20.ParseTransferFromArgs(tc.args)
+ if tc.expPass {
+ s.Require().NoError(err, "unexpected error parsing the transferFrom arguments")
+ s.Require().Equal(from, tc.args[0], "expected different from address")
+ s.Require().Equal(to, tc.args[1], "expected different to address")
+ s.Require().Equal(amount, tc.args[2], "expected different amount")
+ } else {
+ s.Require().Error(err, "expected an error parsing the transferFrom arguments")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ }
+ })
+ }
+}
+
+//nolint:dupl // these tests are not duplicates
+func (s *PrecompileTestSuite) TestParseApproveArgs() {
+ spender := utiltx.GenerateAddress()
+ amount := big.NewInt(100)
+
+ testcases := []struct {
+ name string
+ args []interface{}
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "pass - correct arguments",
+ args: []interface{}{
+ spender,
+ amount,
+ },
+ expPass: true,
+ },
+ {
+ name: "fail - invalid spender address",
+ args: []interface{}{
+ "invalid address",
+ amount,
+ },
+ errContains: "invalid spender address",
+ },
+ {
+ name: "fail - invalid amount",
+ args: []interface{}{
+ spender,
+ "invalid amount",
+ },
+ errContains: "invalid amount",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ args: []interface{}{
+ 1, 2, 3,
+ },
+ errContains: "invalid number of arguments",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ spender, amount, err := erc20.ParseApproveArgs(tc.args)
+ if tc.expPass {
+ s.Require().NoError(err, "unexpected error parsing the approve arguments")
+ s.Require().Equal(spender, tc.args[0], "expected different spender address")
+ s.Require().Equal(amount, tc.args[1], "expected different amount")
+ } else {
+ s.Require().Error(err, "expected an error parsing the approve arguments")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestParseAllowanceArgs() {
+ owner := utiltx.GenerateAddress()
+ spender := utiltx.GenerateAddress()
+
+ testcases := []struct {
+ name string
+ args []interface{}
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "pass - correct arguments",
+ args: []interface{}{
+ owner,
+ spender,
+ },
+ expPass: true,
+ },
+ {
+ name: "fail - invalid owner address",
+ args: []interface{}{
+ "invalid address",
+ spender,
+ },
+ errContains: "invalid owner address",
+ },
+ {
+ name: "fail - invalid spender address",
+ args: []interface{}{
+ owner,
+ "invalid address",
+ },
+ errContains: "invalid spender address",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ args: []interface{}{
+ 1, 2, 3,
+ },
+ errContains: "invalid number of arguments",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ owner, spender, err := erc20.ParseAllowanceArgs(tc.args)
+ if tc.expPass {
+ s.Require().NoError(err, "unexpected error parsing the allowance arguments")
+ s.Require().Equal(owner, tc.args[0], "expected different owner address")
+ s.Require().Equal(spender, tc.args[1], "expected different spender address")
+ } else {
+ s.Require().Error(err, "expected an error parsing the allowance arguments")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestParseBalanceOfArgs() {
+ account := utiltx.GenerateAddress()
+
+ testcases := []struct {
+ name string
+ args []interface{}
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "pass - correct arguments",
+ args: []interface{}{
+ account,
+ },
+ expPass: true,
+ },
+ {
+ name: "fail - invalid account address",
+ args: []interface{}{
+ "invalid address",
+ },
+ errContains: "invalid account address",
+ },
+ {
+ name: "fail - invalid number of arguments",
+ args: []interface{}{
+ 1, 2, 3,
+ },
+ errContains: "invalid number of arguments",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ s.Run(tc.name, func() {
+ account, err := erc20.ParseBalanceOfArgs(tc.args)
+ if tc.expPass {
+ s.Require().NoError(err, "unexpected error parsing the balanceOf arguments")
+ s.Require().Equal(account, tc.args[0], "expected different account address")
+ } else {
+ s.Require().Error(err, "expected an error parsing the balanceOf arguments")
+ s.Require().ErrorContains(err, tc.errContains, "expected different error message")
+ }
+ })
+ }
+}
diff --git a/precompiles/erc20/utils_test.go b/precompiles/erc20/utils_test.go
new file mode 100644
index 00000000..d78872b2
--- /dev/null
+++ b/precompiles/erc20/utils_test.go
@@ -0,0 +1,517 @@
+package erc20_test
+
+import (
+ "fmt"
+ "math/big"
+ "slices"
+ "time"
+
+ errorsmod "cosmossdk.io/errors"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ auth "github.com/evmos/evmos/v19/precompiles/authorization"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ commonfactory "github.com/evmos/evmos/v19/testutil/integration/common/factory"
+ commonnetwork "github.com/evmos/evmos/v19/testutil/integration/common/network"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ network "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ erc20types "github.com/evmos/evmos/v19/x/erc20/types"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ //nolint:revive // dot imports are fine for Gomega
+ . "github.com/onsi/gomega"
+)
+
+// setupSendAuthz is a helper function to set up a SendAuthorization for
+// a given grantee and granter combination for a given amount.
+//
+// NOTE: A default expiration of 1 hour after the current block time is used.
+func (s *PrecompileTestSuite) setupSendAuthz(
+ grantee sdk.AccAddress, granterPriv cryptotypes.PrivKey, amount sdk.Coins,
+) {
+ err := setupSendAuthz(
+ s.network,
+ s.factory,
+ grantee,
+ granterPriv,
+ amount,
+ )
+ s.Require().NoError(err, "failed to set up send authorization")
+}
+
+func (is *IntegrationTestSuite) setupSendAuthz(
+ grantee sdk.AccAddress, granterPriv cryptotypes.PrivKey, amount sdk.Coins,
+) {
+ err := setupSendAuthz(
+ is.network,
+ is.factory,
+ grantee,
+ granterPriv,
+ amount,
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to set up send authorization")
+}
+
+func setupSendAuthz(
+ network commonnetwork.Network,
+ factory commonfactory.TxFactory,
+ grantee sdk.AccAddress,
+ granterPriv cryptotypes.PrivKey,
+ amount sdk.Coins,
+) error {
+ granter := sdk.AccAddress(granterPriv.PubKey().Address())
+ expiration := network.GetContext().BlockHeader().Time.Add(time.Hour)
+ sendAuthz := banktypes.NewSendAuthorization(
+ amount,
+ []sdk.AccAddress{},
+ )
+
+ msgGrant, err := authz.NewMsgGrant(
+ granter,
+ grantee,
+ sendAuthz,
+ &expiration,
+ )
+ if err != nil {
+ return errorsmod.Wrap(err, "failed to create MsgGrant")
+ }
+
+ // Create an authorization
+ txArgs := commonfactory.CosmosTxArgs{Msgs: []sdk.Msg{msgGrant}}
+ _, err = factory.ExecuteCosmosTx(granterPriv, txArgs)
+ if err != nil {
+ return errorsmod.Wrap(err, "failed to execute MsgGrant")
+ }
+
+ return nil
+}
+
+// setupSendAuthzForContract is a helper function which executes an approval
+// for the given contract data.
+//
+// If:
+// - the classic ERC20 contract is used, it calls the `approve` method on the contract.
+// - in other cases, it sends a `MsgGrant` to set up the authorization.
+func (is *IntegrationTestSuite) setupSendAuthzForContract(
+ callType CallType, contractData ContractsData, grantee common.Address, granterPriv cryptotypes.PrivKey, amount sdk.Coins,
+) {
+ Expect(amount).To(HaveLen(1), "expected only one coin")
+ Expect(amount[0].Denom).To(Equal(is.tokenDenom),
+ "this test utility only works with the token denom in the context of these integration tests",
+ )
+
+ switch {
+ case slices.Contains(nativeCallTypes, callType):
+ is.setupSendAuthz(grantee.Bytes(), granterPriv, amount)
+ case slices.Contains(erc20CallTypes, callType):
+ is.setupSendAuthzForERC20(callType, contractData, grantee, granterPriv, amount)
+ default:
+ panic("unknown contract call type")
+ }
+}
+
+// setupSendAuthzForERC20 is a helper function to set up a SendAuthorization for
+// a given grantee and granter combination for a given amount.
+func (is *IntegrationTestSuite) setupSendAuthzForERC20(
+ callType CallType, contractData ContractsData, grantee common.Address, granterPriv cryptotypes.PrivKey, amount sdk.Coins,
+) {
+ if callType == erc20V5CallerCall {
+ // NOTE: When using the ERC20 caller contract, we must still approve from the actual ERC20 v5 contract.
+ callType = erc20V5Call
+ }
+
+ abiEvents := contractData.GetContractData(callType).ABI.Events
+
+ txArgs, callArgs := is.getTxAndCallArgs(callType, contractData, auth.ApproveMethod, grantee, amount.AmountOf(is.tokenDenom).BigInt())
+
+ approveCheck := testutil.LogCheckArgs{
+ ABIEvents: abiEvents,
+ ExpEvents: []string{auth.EventTypeApproval},
+ ExpPass: true,
+ }
+
+ _, _, err := is.factory.CallContractAndCheckLogs(granterPriv, txArgs, callArgs, approveCheck)
+ Expect(err).ToNot(HaveOccurred(), "failed to execute approve")
+}
+
+// requireOut is a helper utility to reduce the amount of boilerplate code in the query tests.
+//
+// It requires the output bytes and error to match the expected values. Additionally, the method outputs
+// are unpacked and the first value is compared to the expected value.
+//
+// NOTE: It's sufficient to only check the first value because all methods in the ERC20 precompile only
+// return a single value.
+func (s *PrecompileTestSuite) requireOut(
+ bz []byte,
+ err error,
+ method abi.Method,
+ expPass bool,
+ errContains string,
+ expValue interface{},
+) {
+ if expPass {
+ s.Require().NoError(err, "expected no error")
+ s.Require().NotEmpty(bz, "expected bytes not to be empty")
+
+ // Unpack the name into a string
+ out, err := method.Outputs.Unpack(bz)
+ s.Require().NoError(err, "expected no error unpacking")
+
+ // Check if expValue is a big.Int. Because of a difference in uninitialized/empty values for big.Ints,
+ // this comparison is often not working as expected, so we convert to Int64 here and compare those values.
+ bigExp, ok := expValue.(*big.Int)
+ if ok {
+ bigOut, ok := out[0].(*big.Int)
+ s.Require().True(ok, "expected output to be a big.Int")
+ s.Require().Equal(bigExp.Int64(), bigOut.Int64(), "expected different value")
+ } else {
+ s.Require().Equal(expValue, out[0], "expected different value")
+ }
+ } else {
+ s.Require().Error(err, "expected error")
+ s.Require().Contains(err.Error(), errContains, "expected different error")
+ }
+}
+
+// requireSendAuthz is a helper function to check that a SendAuthorization
+// exists for a given grantee and granter combination for a given amount.
+//
+// NOTE: This helper expects only one authorization to exist.
+func (s *PrecompileTestSuite) requireSendAuthz(grantee, granter sdk.AccAddress, amount sdk.Coins, allowList []string) {
+ grants, err := s.grpcHandler.GetGrantsByGrantee(grantee.String())
+ s.Require().NoError(err, "expected no error querying the grants")
+ s.Require().Len(grants, 1, "expected one grant")
+ s.Require().Equal(grantee.String(), grants[0].Grantee, "expected different grantee")
+ s.Require().Equal(granter.String(), grants[0].Granter, "expected different granter")
+
+ authzs, err := s.grpcHandler.GetAuthorizationsByGrantee(grantee.String())
+ s.Require().NoError(err, "expected no error unpacking the authorization")
+ s.Require().Len(authzs, 1, "expected one authorization")
+
+ sendAuthz, ok := authzs[0].(*banktypes.SendAuthorization)
+ s.Require().True(ok, "expected send authorization")
+
+ s.Require().Equal(amount, sendAuthz.SpendLimit, "expected different spend limit amount")
+ if len(allowList) == 0 {
+ s.Require().Empty(sendAuthz.AllowList, "expected empty allow list")
+ } else {
+ s.Require().Equal(allowList, sendAuthz.AllowList, "expected different allow list")
+ }
+}
+
+// setupERC20Precompile is a helper function to set up an instance of the ERC20 precompile for
+// a given token denomination, set the token pair in the ERC20 keeper and adds the precompile
+// to the available and active precompiles.
+func (s *PrecompileTestSuite) setupERC20Precompile(denom string) *erc20.Precompile {
+ tokenPair := erc20types.NewTokenPair(utiltx.GenerateAddress(), denom, erc20types.OWNER_MODULE)
+ s.network.App.Erc20Keeper.SetTokenPair(s.network.GetContext(), tokenPair)
+
+ precompile, err := setupERC20PrecompileForTokenPair(*s.network, tokenPair)
+ s.Require().NoError(err, "failed to set up %q erc20 precompile", tokenPair.Denom)
+
+ return precompile
+}
+
+// setupERC20Precompile is a helper function to set up an instance of the ERC20 precompile for
+// a given token denomination, set the token pair in the ERC20 keeper and adds the precompile
+// to the available and active precompiles.
+//
+// TODO: refactor
+func (is *IntegrationTestSuite) setupERC20Precompile(denom string) *erc20.Precompile {
+ tokenPair := erc20types.NewTokenPair(utiltx.GenerateAddress(), denom, erc20types.OWNER_MODULE)
+ is.network.App.Erc20Keeper.SetToken(is.network.GetContext(), tokenPair)
+
+ precompile, err := setupERC20PrecompileForTokenPair(*is.network, tokenPair)
+ Expect(err).ToNot(HaveOccurred(), "failed to set up %q erc20 precompile", tokenPair.Denom)
+
+ return precompile
+}
+
+// setupERC20PrecompileForTokenPair is a helper function to set up an instance of the ERC20 precompile for
+// a given token pair and adds the precompile to the available and active precompiles.
+func setupERC20PrecompileForTokenPair(
+ unitNetwork network.UnitTestNetwork, tokenPair erc20types.TokenPair,
+) (*erc20.Precompile, error) {
+ precompile, err := erc20.NewPrecompile(
+ tokenPair,
+ unitNetwork.App.BankKeeper,
+ unitNetwork.App.AuthzKeeper,
+ unitNetwork.App.TransferKeeper,
+ )
+ if err != nil {
+ return nil, errorsmod.Wrapf(err, "failed to create %q erc20 precompile", tokenPair.Denom)
+ }
+
+ err = unitNetwork.App.Erc20Keeper.EnableDynamicPrecompiles(
+ unitNetwork.GetContext(),
+ precompile.Address(),
+ )
+ if err != nil {
+ return nil, errorsmod.Wrapf(err, "failed to add %q erc20 precompile to EVM extensions", tokenPair.Denom)
+ }
+
+ return precompile, nil
+}
+
+// CallType indicates which type of contract call is made during the integration tests.
+type CallType int
+
+// callType constants to differentiate between direct calls and calls through a contract.
+const (
+ directCall CallType = iota + 1
+ contractCall
+ erc20Call
+ erc20CallerCall
+ erc20V5Call
+ erc20V5CallerCall
+)
+
+var (
+ nativeCallTypes = []CallType{directCall, contractCall}
+ erc20CallTypes = []CallType{erc20Call, erc20CallerCall, erc20V5Call, erc20V5CallerCall}
+)
+
+// getTxAndCallArgs is a helper function to return the correct call arguments for a given call type.
+//
+// In case of a direct call to the precompile, the precompile's ABI is used. Otherwise, the
+// ERC20CallerContract's ABI is used and the given contract address.
+func (is *IntegrationTestSuite) getTxAndCallArgs(
+ callType CallType,
+ contractData ContractsData,
+ methodName string,
+ args ...interface{},
+) (evmtypes.EvmTxArgs, factory.CallArgs) {
+ cd := contractData.GetContractData(callType)
+
+ txArgs := evmtypes.EvmTxArgs{
+ To: &cd.Address,
+ }
+
+ callArgs := factory.CallArgs{
+ ContractABI: cd.ABI,
+ MethodName: methodName,
+ Args: args,
+ }
+
+ return txArgs, callArgs
+}
+
+// ExpectedBalance is a helper struct to check the balances of accounts.
+type ExpectedBalance struct {
+ address sdk.AccAddress
+ expCoins sdk.Coins
+}
+
+// ExpectBalances is a helper function to check if the balances of the given accounts are as expected.
+func (is *IntegrationTestSuite) ExpectBalances(expBalances []ExpectedBalance) {
+ for _, expBalance := range expBalances {
+ for _, expCoin := range expBalance.expCoins {
+ coinBalance, err := is.handler.GetBalance(expBalance.address, expCoin.Denom)
+ Expect(err).ToNot(HaveOccurred(), "expected no error getting balance")
+ Expect(coinBalance.Balance.Amount.Int64()).To(Equal(expCoin.Amount.Int64()), "expected different balance")
+ }
+ }
+}
+
+// ExpectBalancesForContract is a helper function to check expected balances for given accounts depending
+// on the call type.
+func (is *IntegrationTestSuite) ExpectBalancesForContract(callType CallType, contractData ContractsData, expBalances []ExpectedBalance) {
+ switch {
+ case slices.Contains(nativeCallTypes, callType):
+ is.ExpectBalances(expBalances)
+ case slices.Contains(erc20CallTypes, callType):
+ is.ExpectBalancesForERC20(callType, contractData, expBalances)
+ default:
+ panic("unknown contract call type")
+ }
+}
+
+// ExpectBalancesForERC20 is a helper function to check expected balances for given accounts
+// when using the ERC20 contract.
+func (is *IntegrationTestSuite) ExpectBalancesForERC20(callType CallType, contractData ContractsData, expBalances []ExpectedBalance) {
+ contractABI := contractData.GetContractData(callType).ABI
+
+ for _, expBalance := range expBalances {
+ addr := common.BytesToAddress(expBalance.address.Bytes())
+ txArgs, callArgs := is.getTxAndCallArgs(callType, contractData, "balanceOf", addr)
+
+ passCheck := testutil.LogCheckArgs{ExpPass: true}
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(contractData.ownerPriv, txArgs, callArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "expected no error getting balance")
+
+ var balance *big.Int
+ err = contractABI.UnpackIntoInterface(&balance, "balanceOf", ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "expected no error unpacking balance")
+ Expect(balance.Int64()).To(Equal(expBalance.expCoins.AmountOf(is.tokenDenom).Int64()), "expected different balance")
+ }
+}
+
+// expectSendAuthz is a helper function to check that a SendAuthorization
+// exists for a given grantee and granter combination for a given amount and optionally an access list.
+//
+// NOTE: This helper expects only one authorization to exist.
+//
+// NOTE 2: This mirrors the requireSendAuthz method but adapted to Ginkgo.
+func (is *IntegrationTestSuite) expectSendAuthz(grantee, granter sdk.AccAddress, expAmount sdk.Coins) {
+ authzs, err := is.handler.GetAuthorizations(grantee.String(), granter.String())
+ Expect(err).ToNot(HaveOccurred(), "expected no error unpacking the authorization")
+ Expect(authzs).To(HaveLen(1), "expected one authorization")
+
+ sendAuthz, ok := authzs[0].(*banktypes.SendAuthorization)
+ Expect(ok).To(BeTrue(), "expected send authorization")
+
+ Expect(sendAuthz.SpendLimit).To(Equal(expAmount), "expected different spend limit amount")
+}
+
+// expectSendAuthzForERC20 is a helper function to check that a SendAuthorization
+// exists for a given grantee and granter combination for a given amount.
+func (is *IntegrationTestSuite) expectSendAuthzForERC20(callType CallType, contractData ContractsData, grantee, granter common.Address, expAmount sdk.Coins) {
+ contractABI := contractData.GetContractData(callType).ABI
+
+ txArgs, callArgs := is.getTxAndCallArgs(callType, contractData, auth.AllowanceMethod, granter, grantee)
+
+ passCheck := testutil.LogCheckArgs{ExpPass: true}
+
+ _, ethRes, err := is.factory.CallContractAndCheckLogs(contractData.ownerPriv, txArgs, callArgs, passCheck)
+ Expect(err).ToNot(HaveOccurred(), "expected no error getting allowance")
+
+ var allowance *big.Int
+ err = contractABI.UnpackIntoInterface(&allowance, "allowance", ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "expected no error unpacking allowance")
+ Expect(allowance.Int64()).To(Equal(expAmount.AmountOf(is.tokenDenom).Int64()), "expected different allowance")
+}
+
+// ExpectSendAuthzForContract is a helper function to check that a SendAuthorization
+// exists for a given grantee and granter combination for a given amount and optionally an access list.
+//
+// NOTE: This helper expects only one authorization to exist.
+func (is *IntegrationTestSuite) ExpectSendAuthzForContract(
+ callType CallType, contractData ContractsData, grantee, granter common.Address, expAmount sdk.Coins,
+) {
+ switch {
+ case slices.Contains(nativeCallTypes, callType):
+ is.expectSendAuthz(grantee.Bytes(), granter.Bytes(), expAmount)
+ case slices.Contains(erc20CallTypes, callType):
+ is.expectSendAuthzForERC20(callType, contractData, grantee, granter, expAmount)
+ default:
+ panic("unknown contract call type")
+ }
+}
+
+// expectNoSendAuthz is a helper function to check that no SendAuthorization
+// exists for a given grantee and granter combination.
+func (is *IntegrationTestSuite) expectNoSendAuthz(grantee, granter sdk.AccAddress) {
+ authzs, err := is.handler.GetAuthorizations(grantee.String(), granter.String())
+ Expect(err).ToNot(HaveOccurred(), "expected no error unpacking the authorizations")
+ Expect(authzs).To(HaveLen(0), "expected no authorizations")
+}
+
+// expectNoSendAuthzForERC20 is a helper function to check that no SendAuthorization
+// exists for a given grantee and granter combination.
+func (is *IntegrationTestSuite) expectNoSendAuthzForERC20(callType CallType, contractData ContractsData, grantee, granter common.Address) {
+ is.expectSendAuthzForERC20(callType, contractData, grantee, granter, sdk.Coins{})
+}
+
+// ExpectNoSendAuthzForContract is a helper function to check that no SendAuthorization
+// exists for a given grantee and granter combination.
+func (is *IntegrationTestSuite) ExpectNoSendAuthzForContract(
+ callType CallType, contractData ContractsData, grantee, granter common.Address,
+) {
+ switch {
+ case slices.Contains(nativeCallTypes, callType):
+ is.expectNoSendAuthz(grantee.Bytes(), granter.Bytes())
+ case slices.Contains(erc20CallTypes, callType):
+ is.expectNoSendAuthzForERC20(callType, contractData, grantee, granter)
+ default:
+ panic("unknown contract call type")
+ }
+}
+
+// ExpectTrueToBeReturned is a helper function to check that the precompile returns true
+// in the ethereum transaction response.
+func (is *IntegrationTestSuite) ExpectTrueToBeReturned(res *evmtypes.MsgEthereumTxResponse, methodName string) {
+ var ret bool
+ err := is.precompile.UnpackIntoInterface(&ret, methodName, res.Ret)
+ Expect(err).ToNot(HaveOccurred(), "expected no error unpacking")
+ Expect(ret).To(BeTrue(), "expected true to be returned")
+}
+
+// ContractsData is a helper struct to hold the addresses and ABIs for the
+// different contract instances that are subject to testing here.
+type ContractsData struct {
+ contractData map[CallType]ContractData
+ ownerPriv cryptotypes.PrivKey
+}
+
+// ContractData is a helper struct to hold the address and ABI for a given contract.
+type ContractData struct {
+ Address common.Address
+ ABI abi.ABI
+}
+
+// GetContractData is a helper function to return the contract data for a given call type.
+func (cd ContractsData) GetContractData(callType CallType) ContractData {
+ data, found := cd.contractData[callType]
+ if !found {
+ panic(fmt.Sprintf("no contract data found for call type: %d", callType))
+ }
+ return data
+}
+
+// fundWithTokens is a helper function for the scope of the ERC20 integration tests.
+// Depending on the passed call type, it funds the given address with tokens either
+// using the Bank module or by minting straight on the ERC20 contract.
+func (is *IntegrationTestSuite) fundWithTokens(
+ callType CallType,
+ contractData ContractsData,
+ receiver common.Address,
+ fundCoins sdk.Coins,
+) {
+ Expect(fundCoins).To(HaveLen(1), "expected only one coin")
+ Expect(fundCoins[0].Denom).To(Equal(is.tokenDenom),
+ "this helper function only supports funding with the token denom in the context of these integration tests",
+ )
+
+ var err error
+
+ switch {
+ case slices.Contains(nativeCallTypes, callType):
+ err = is.network.FundAccount(receiver.Bytes(), fundCoins)
+ case slices.Contains(erc20CallTypes, callType):
+ err = is.MintERC20(callType, contractData, receiver, fundCoins.AmountOf(is.tokenDenom).BigInt())
+ default:
+ panic("unknown contract call type")
+ }
+
+ Expect(err).ToNot(HaveOccurred(), "failed to fund account")
+}
+
+// MintERC20 is a helper function to mint tokens on the ERC20 contract.
+//
+// NOTE: we are checking that there was a Transfer event emitted (which happens on minting).
+func (is *IntegrationTestSuite) MintERC20(callType CallType, contractData ContractsData, receiver common.Address, amount *big.Int) error {
+ if callType == erc20V5CallerCall {
+ // NOTE: When using the ERC20 caller contract, we must still mint from the actual ERC20 v5 contract.
+ callType = erc20V5Call
+ }
+ abiEvents := contractData.GetContractData(callType).ABI.Events
+
+ txArgs, callArgs := is.getTxAndCallArgs(callType, contractData, "mint", receiver, amount)
+
+ mintCheck := testutil.LogCheckArgs{
+ ABIEvents: abiEvents,
+ ExpEvents: []string{erc20.EventTypeTransfer}, // NOTE: this event occurs when calling "mint" on ERC20s
+ ExpPass: true,
+ }
+
+ _, _, err := is.factory.CallContractAndCheckLogs(contractData.ownerPriv, txArgs, callArgs, mintCheck)
+
+ return err
+}
diff --git a/precompiles/ics20/ICS20I.sol b/precompiles/ics20/ICS20I.sol
new file mode 100644
index 00000000..80af1db6
--- /dev/null
+++ b/precompiles/ics20/ICS20I.sol
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.18;
+
+import "../common/Types.sol";
+import "../authorization/IICS20Authorization.sol";
+
+/// @dev The ICS20I contract's address.
+address constant ICS20_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000802;
+
+/// @dev The ICS20 contract's instance.
+ICS20I constant ICS20_CONTRACT = ICS20I(ICS20_PRECOMPILE_ADDRESS);
+
+/// @dev DenomTrace contains the base denomination for ICS20 fungible tokens and the
+/// source tracing information path.
+struct DenomTrace {
+ // path defines the chain of port/channel identifiers used for tracing the
+ // source of the fungible token.
+ string path;
+ // base denomination of the relayed fungible token.
+ string baseDenom;
+}
+
+/// @author Evmos Team
+/// @title ICS20 Transfer Precompiled Contract
+/// @dev The interface through which solidity contracts will interact with IBC Transfer (ICS20)
+/// @custom:address 0x0000000000000000000000000000000000000802
+interface ICS20I is IICS20Authorization {
+ /// @dev Emitted when an ICS-20 transfer is executed.
+ /// @param sender The address of the sender.
+ /// @param receiver The address of the receiver.
+ /// @param sourcePort The source port of the IBC transaction.
+ /// @param sourceChannel The source channel of the IBC transaction.
+ /// @param denom The denomination of the tokens transferred.
+ /// @param amount The amount of tokens transferred.
+ /// @param memo The IBC transaction memo.
+ event IBCTransfer(
+ address indexed sender,
+ string indexed receiver,
+ string sourcePort,
+ string sourceChannel,
+ string denom,
+ uint256 amount,
+ string memo
+ );
+
+ /// @dev Transfer defines a method for performing an IBC transfer.
+ /// @param sourcePort the port on which the packet will be sent
+ /// @param sourceChannel the channel by which the packet will be sent
+ /// @param denom the denomination of the Coin to be transferred to the receiver
+ /// @param amount the amount of the Coin to be transferred to the receiver
+ /// @param sender the hex address of the sender
+ /// @param receiver the bech32 address of the receiver
+ /// @param timeoutHeight the timeout height relative to the current block height.
+ /// The timeout is disabled when set to 0
+ /// @param timeoutTimestamp the timeout timestamp in absolute nanoseconds since unix epoch.
+ /// The timeout is disabled when set to 0
+ /// @param memo optional memo
+ /// @return nextSequence sequence number of the transfer packet sent
+ function transfer(
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ address sender,
+ string memory receiver,
+ Height memory timeoutHeight,
+ uint64 timeoutTimestamp,
+ string memory memo
+ ) external returns (uint64 nextSequence);
+
+ /// @dev DenomTraces Defines a method for returning all denom traces.
+ /// @param pageRequest Defines the pagination parameters to for the request.
+ function denomTraces(
+ PageRequest memory pageRequest
+ )
+ external
+ view
+ returns (
+ DenomTrace[] memory denomTraces,
+ PageResponse memory pageResponse
+ );
+
+ /// @dev DenomTrace defines a method for returning a denom trace.
+ function denomTrace(
+ string memory hash
+ ) external view returns (DenomTrace memory denomTrace);
+
+ /// @dev DenomHash defines a method for returning a hash of the denomination trace info.
+ function denomHash(
+ string memory trace
+ ) external view returns (string memory hash);
+
+}
diff --git a/precompiles/ics20/abi.json b/precompiles/ics20/abi.json
new file mode 100644
index 00000000..6f475e6d
--- /dev/null
+++ b/precompiles/ics20/abi.json
@@ -0,0 +1,543 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "ICS20I",
+ "sourceName": "solidity/precompiles/ics20/ICS20I.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "memo",
+ "type": "string"
+ }
+ ],
+ "name": "IBCTransfer",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "granter",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "spendLimit",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowList",
+ "type": "string[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowedPacketData",
+ "type": "string[]"
+ }
+ ],
+ "indexed": false,
+ "internalType": "struct ICS20Allocation[]",
+ "name": "allocations",
+ "type": "tuple[]"
+ }
+ ],
+ "name": "IBCTransferAuthorization",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "granter",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "spendLimit",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowList",
+ "type": "string[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowedPacketData",
+ "type": "string[]"
+ }
+ ],
+ "internalType": "struct ICS20Allocation[]",
+ "name": "allocations",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "spendLimit",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowList",
+ "type": "string[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowedPacketData",
+ "type": "string[]"
+ }
+ ],
+ "internalType": "struct ICS20Allocation[]",
+ "name": "allocations",
+ "type": "tuple[]"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "decreaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "trace",
+ "type": "string"
+ }
+ ],
+ "name": "denomHash",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "hash",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "hash",
+ "type": "string"
+ }
+ ],
+ "name": "denomTrace",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "path",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "baseDenom",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct DenomTrace",
+ "name": "denomTrace",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "denomTraces",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "path",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "baseDenom",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct DenomTrace[]",
+ "name": "denomTraces",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "pageResponse",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "increaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ }
+ ],
+ "name": "revoke",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "revoked",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint64",
+ "name": "revisionNumber",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "revisionHeight",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct Height",
+ "name": "timeoutHeight",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint64",
+ "name": "timeoutTimestamp",
+ "type": "uint64"
+ },
+ {
+ "internalType": "string",
+ "name": "memo",
+ "type": "string"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "internalType": "uint64",
+ "name": "nextSequence",
+ "type": "uint64"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x",
+ "deployedBytecode": "0x",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/ics20/approve.go b/precompiles/ics20/approve.go
new file mode 100644
index 00000000..4f5e115b
--- /dev/null
+++ b/precompiles/ics20/approve.go
@@ -0,0 +1,139 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// Approve implements the ICS20 approve transactions.
+func (p Precompile) Approve(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, transferAuthz, err := NewTransferAuthorization(method, args)
+ if err != nil {
+ return nil, err
+ }
+
+ // Approve from ICS20 common module
+ if err := Approve(
+ ctx,
+ p.AuthzKeeper,
+ p.channelKeeper,
+ p.Address(),
+ grantee,
+ origin,
+ p.ApprovalExpiration,
+ transferAuthz,
+ p.ABI.Events[authorization.EventTypeIBCTransferAuthorization],
+ stateDB,
+ ); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// Revoke implements the ICS20 authorization revoke transactions.
+func (p Precompile) Revoke(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, err := checkRevokeArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // Revoke from ICS20 common module
+ if err := Revoke(
+ ctx,
+ p.AuthzKeeper,
+ p.Address(),
+ grantee,
+ origin,
+ p.ABI.Events[authorization.EventTypeIBCTransferAuthorization],
+ stateDB,
+ ); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// IncreaseAllowance implements the ICS20 increase allowance transactions.
+func (p Precompile) IncreaseAllowance(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, sourcePort, sourceChannel, denom, amount, err := checkAllowanceArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // IncreaseAllowance from ICS20 common module
+ if err := IncreaseAllowance(
+ ctx,
+ p.AuthzKeeper,
+ p.Address(),
+ grantee,
+ origin,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ p.ABI.Events[authorization.EventTypeIBCTransferAuthorization],
+ stateDB,
+ ); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// DecreaseAllowance implements the ICS20 decrease allowance transactions.
+func (p Precompile) DecreaseAllowance(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, sourcePort, sourceChannel, denom, amount, err := checkAllowanceArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ // DecreaseAllowance from ICS20 common module
+ if err := DecreaseAllowance(
+ ctx,
+ p.AuthzKeeper,
+ p.Address(),
+ grantee,
+ origin,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ p.ABI.Events[authorization.EventTypeIBCTransferAuthorization],
+ stateDB,
+ ); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
diff --git a/precompiles/ics20/approve_common.go b/precompiles/ics20/approve_common.go
new file mode 100644
index 00000000..35489f60
--- /dev/null
+++ b/precompiles/ics20/approve_common.go
@@ -0,0 +1,268 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+ "time"
+
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ channelkeeper "github.com/cosmos/ibc-go/v7/modules/core/04-channel/keeper"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// TransferMsgURL is the ICS20 transfer message URL string.
+var TransferMsgURL = sdk.MsgTypeURL(&transfertypes.MsgTransfer{})
+
+// Approve implements the ICS20 Authorization approve transactions.
+func Approve(
+ ctx sdk.Context,
+ authzKeeper authzkeeper.Keeper,
+ channelKeeper channelkeeper.Keeper,
+ precompileAddr, grantee, origin common.Address,
+ approvalExpiration time.Duration,
+ transferAuthz *transfertypes.TransferAuthorization,
+ event abi.Event,
+ stateDB vm.StateDB,
+) error {
+ // If one of the allocations contains a non-existing channel, throw and error
+ for _, allocation := range transferAuthz.Allocations {
+ found := channelKeeper.HasChannel(ctx, allocation.SourcePort, allocation.SourceChannel)
+ if !found {
+ return errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", allocation.SourcePort, allocation.SourceChannel)
+ }
+ }
+
+ // Only the origin can approve a transfer to the grantee address
+ expiration := ctx.BlockTime().Add(approvalExpiration).UTC()
+ if err := authzKeeper.SaveGrant(ctx, grantee.Bytes(), origin.Bytes(), transferAuthz, &expiration); err != nil {
+ return err
+ }
+
+ allocations := convertToAllocation(transferAuthz.Allocations)
+ // Emit the IBC transfer authorization event
+ return authorization.EmitIBCTransferAuthorizationEvent(
+ event,
+ ctx,
+ stateDB,
+ precompileAddr,
+ grantee,
+ origin,
+ allocations,
+ )
+}
+
+// Revoke implements the ICS20 Authorization revoke transactions.
+func Revoke(
+ ctx sdk.Context,
+ authzKeeper authzkeeper.Keeper,
+ precompileAddr, grantee, origin common.Address,
+ event abi.Event,
+ stateDB vm.StateDB,
+) error {
+ // NOTE: we do not need to check the expiration as it will return nil if both not found or expired
+ msgAuthz, _, err := authorization.CheckAuthzExists(ctx, authzKeeper, grantee, origin, TransferMsgURL)
+ if err != nil {
+ return fmt.Errorf(authorization.ErrAuthzDoesNotExistOrExpired, grantee, origin)
+ }
+
+ // check that the stored authorization matches the transfer authorization
+ if _, ok := msgAuthz.(*transfertypes.TransferAuthorization); !ok {
+ return authz.ErrUnknownAuthorizationType
+ }
+
+ if err = authzKeeper.DeleteGrant(ctx, grantee.Bytes(), origin.Bytes(), TransferMsgURL); err != nil {
+ return err
+ }
+
+ return authorization.EmitIBCTransferAuthorizationEvent(
+ event,
+ ctx,
+ stateDB,
+ precompileAddr,
+ grantee,
+ origin,
+ []cmn.ICS20Allocation{},
+ )
+}
+
+// IncreaseAllowance implements the ICS20 Authorization increase allowance transactions.
+func IncreaseAllowance(
+ ctx sdk.Context,
+ authzKeeper authzkeeper.Keeper,
+ precompileAddr, grantee, granter common.Address,
+ sourcePort, sourceChannel, denom string,
+ amount *big.Int,
+ event abi.Event,
+ stateDB vm.StateDB,
+) error {
+ // NOTE: we do not need to check the expiration as it will return nil if both found or expired
+ msgAuthz, expiration, err := authorization.CheckAuthzExists(ctx, authzKeeper, grantee, granter, TransferMsgURL)
+ if err != nil {
+ return fmt.Errorf(authorization.ErrAuthzDoesNotExistOrExpired, grantee, granter)
+ }
+
+ // NOTE: we do not need to check the expiration as it will return nil if both found or expired
+ transferAuthz, ok := msgAuthz.(*transfertypes.TransferAuthorization)
+ if !ok {
+ return authz.ErrUnknownAuthorizationType
+ }
+
+ // Check if the allocations matches the arguments provided and returns the index of the allocation and coin found
+ spendLimit, allocationIdx, err := checkAllocationExists(transferAuthz.Allocations, sourcePort, sourceChannel, denom)
+ if err != nil {
+ return err
+ }
+
+ allowance := math.NewIntFromBigInt(amount)
+ if _, overflow := cmn.SafeAdd(spendLimit.Amount, allowance); overflow {
+ return errors.New(cmn.ErrIntegerOverflow)
+ }
+
+ allowanceCoin := sdk.Coin{Denom: denom, Amount: allowance}
+
+ transferAuthz.Allocations[allocationIdx].SpendLimit = transferAuthz.Allocations[allocationIdx].SpendLimit.Add(allowanceCoin)
+
+ if err = authzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), transferAuthz, expiration); err != nil {
+ return err
+ }
+
+ allocations := convertToAllocation(transferAuthz.Allocations)
+ // Emit the IBC transfer authorization event
+ return authorization.EmitIBCTransferAuthorizationEvent(
+ event,
+ ctx,
+ stateDB,
+ precompileAddr,
+ grantee,
+ granter,
+ allocations,
+ )
+}
+
+// DecreaseAllowance implements the ICS20 Authorization decrease allowance transactions.
+func DecreaseAllowance(
+ ctx sdk.Context,
+ authzKeeper authzkeeper.Keeper,
+ precompileAddr, grantee, granter common.Address,
+ sourcePort, sourceChannel, denom string,
+ amount *big.Int,
+ event abi.Event,
+ stateDB vm.StateDB,
+) error {
+ // NOTE: we do not need to check the expiration as it will return nil if both found or expired
+ msgAuthz, expiration, err := authorization.CheckAuthzExists(ctx, authzKeeper, grantee, granter, TransferMsgURL)
+ if err != nil {
+ return fmt.Errorf(authorization.ErrAuthzDoesNotExistOrExpired, grantee, granter)
+ }
+
+ transferAuthz, ok := msgAuthz.(*transfertypes.TransferAuthorization)
+ if !ok {
+ return authz.ErrUnknownAuthorizationType
+ }
+
+ // Check if the allocations matches the arguments provided and returns the index of the allocation and spend limit found
+ spendLimit, allocationIdx, err := checkAllocationExists(transferAuthz.Allocations, sourcePort, sourceChannel, denom)
+ if err != nil {
+ return err
+ }
+
+ expense := math.NewIntFromBigInt(amount)
+ if spendLimit.Amount.LT(expense) {
+ return fmt.Errorf(cmn.ErrNegativeAmount)
+ }
+
+ // Checking if the amount here is negative or zero and remove the coin from the spend limit otherwise
+ // subtract from the allowance like normal
+ allocation := transferAuthz.Allocations[allocationIdx]
+ for i, coin := range allocation.SpendLimit {
+ if coin.Denom != denom {
+ continue
+ }
+ coinDiff := coin.Amount.Sub(expense)
+ // Remove if it's negative or 0
+ if !coinDiff.IsPositive() {
+ allocation.SpendLimit = append(
+ allocation.SpendLimit[:i],
+ allocation.SpendLimit[i+1:]...)
+ } else {
+ allocation.SpendLimit[i].Amount = coinDiff
+ }
+ }
+ transferAuthz.Allocations[allocationIdx] = allocation
+ if err = authzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), transferAuthz, expiration); err != nil {
+ return err
+ }
+
+ allocations := convertToAllocation(transferAuthz.Allocations)
+ // Emit the IBC transfer authorization event
+ return authorization.EmitIBCTransferAuthorizationEvent(
+ event,
+ ctx,
+ stateDB,
+ precompileAddr,
+ grantee,
+ granter,
+ allocations,
+ )
+}
+
+// AcceptGrant implements the ICS20 accept grant.
+func AcceptGrant(
+ ctx sdk.Context,
+ contractCaller, granter common.Address,
+ msg *transfertypes.MsgTransfer,
+ authzAuthorization authz.Authorization,
+) (*authz.AcceptResponse, error) {
+ transferAuthz, ok := authzAuthorization.(*transfertypes.TransferAuthorization)
+ if !ok {
+ return nil, authz.ErrUnknownAuthorizationType
+ }
+
+ resp, err := transferAuthz.Accept(ctx, msg)
+ if err != nil {
+ return nil, err
+ }
+
+ if !resp.Accept {
+ return nil, fmt.Errorf(authorization.ErrAuthzNotAccepted, contractCaller, granter)
+ }
+
+ return &resp, nil
+}
+
+// UpdateGrant implements the ICS20 authz update grant.
+func UpdateGrant(
+ ctx sdk.Context,
+ authzKeeper authzkeeper.Keeper,
+ grantee, granter common.Address,
+ expiration *time.Time,
+ resp *authz.AcceptResponse,
+) (err error) {
+ if resp.Delete {
+ err = authzKeeper.DeleteGrant(ctx, grantee.Bytes(), granter.Bytes(), TransferMsgURL)
+ } else if resp.Updated != nil {
+ err = authzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), resp.Updated, expiration)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/precompiles/ics20/approve_test.go b/precompiles/ics20/approve_test.go
new file mode 100644
index 00000000..2a1f93b2
--- /dev/null
+++ b/precompiles/ics20/approve_test.go
@@ -0,0 +1,611 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package ics20_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/ics20"
+ "github.com/evmos/evmos/v19/utils"
+)
+
+type allowanceTestCase struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+}
+
+var defaultAllowanceCases = []allowanceTestCase{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 5, 0),
+ },
+ // { // TODO uncomment when corresponding logic included
+ // "fail - origin same as spender",
+ // func() []interface{} {
+ // return []interface{}{
+ // common.BytesToAddress(s.chainA.SenderAccount.GetAddress().Bytes()),
+ // "port-1",
+ // "channel-1",
+ // utils.BaseDenom,
+ // big.NewInt(1e18),
+ // }
+ // },
+ // func(data []byte, inputArgs []interface{}) {},
+ // 200000,
+ // true,
+ // "origin is the same as spender",
+ // },
+ {
+ "fail - authorization does not exist",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ "port-1",
+ "channel-1",
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ "does not exist",
+ },
+ {
+ "fail - allocation for specified denom does not exist",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, s.address, s.address, path, maxUint256Coins, nil, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ "atom",
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte, []interface{}) {
+ },
+ 200000,
+ true,
+ "no matching allocation found",
+ },
+ {
+ "fail - allocation for specified channel and port id does not exist",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, s.address, s.address, path, maxUint256Coins, nil, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ "port-1",
+ "channel-1",
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte, []interface{}) {
+ },
+ 200000,
+ true,
+ "no matching allocation found",
+ },
+}
+
+func (s *PrecompileTestSuite) TestApprove() {
+ method := s.precompile.Methods[authorization.ApproveMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - channel does not exist",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ []cmn.ICS20Allocation{
+ {
+ SourcePort: "port-1",
+ SourceChannel: "channel-1",
+ SpendLimit: defaultCmnCoins,
+ AllowList: nil,
+ },
+ },
+ }
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ channeltypes.ErrChannelNotFound.Error(),
+ },
+ {
+ "pass - MaxInt256 allocation",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ return []interface{}{
+ s.address,
+ []cmn.ICS20Allocation{
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: maxUint256CmnCoins,
+ AllowList: nil,
+ },
+ },
+ }
+ },
+ func(_ []byte, _ []interface{}) {
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, s.address.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, maxUint256Coins)
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "pass - create authorization with specific spend limit",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ return []interface{}{
+ differentAddress,
+ []cmn.ICS20Allocation{
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: defaultCmnCoins,
+ AllowList: nil,
+ },
+ },
+ }
+ },
+ func(_ []byte, _ []interface{}) {
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, differentAddress.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, defaultCoins)
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ args := tc.malleate()
+ bz, err := s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().Equal(bz, cmn.TrueValue)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRevoke() {
+ method := s.precompile.Methods[authorization.RevokeMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func()
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func() {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 0),
+ },
+ {
+ "fail - not a correct grantee address",
+ func() []interface{} {
+ return []interface{}{
+ "test string",
+ }
+ },
+ func() {},
+ 200000,
+ true,
+ fmt.Sprintf(authorization.ErrInvalidGrantee, "test string"),
+ },
+ {
+ "fail - authorization does not exist",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ }
+ },
+ func() {},
+ 200000,
+ true,
+ "does not exist",
+ },
+ {
+ "pass - deletes authorization grant",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, differentAddress, s.address, path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, differentAddress.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ s.Require().NotNil(authz)
+ return []interface{}{
+ differentAddress,
+ }
+ },
+ func() {
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, differentAddress.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ s.Require().Nil(authz)
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ args := tc.malleate()
+ bz, err := s.precompile.Revoke(s.ctx, s.address, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().Equal(bz, cmn.TrueValue)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestIncreaseAllowance() {
+ method := s.precompile.Methods[authorization.IncreaseAllowanceMethod]
+
+ testCases := []allowanceTestCase{
+ {
+ "fail - the new spend limit overflows the maxUint256",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ overflowTestCoins := maxUint256Coins.Sub(sdk.NewInt64Coin(utils.BaseDenom, 1))
+ err := s.NewTransferAuthorization(s.ctx, s.app, differentAddress, s.address, path, overflowTestCoins, nil, nil)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, overflowTestCoins)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(2e18),
+ }
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ cmn.ErrIntegerOverflow,
+ },
+ {
+ "pass - increase allowance by 1 EVMOS for a single allocation with a single coin denomination",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, differentAddress, s.address, path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, defaultCoins)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte, []interface{}) {
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[0].Amount, math.NewInt(2e18))
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[0].Denom, utils.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "pass - increase allowance by 1 Atom for single allocation with a multiple coin denomination",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, differentAddress, s.address, path, mutliSpendLimit, nil, nil)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, mutliSpendLimit)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ "uatom",
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte, []interface{}) {
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[1].Amount, math.NewInt(2e18))
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[1].Denom, "uatom")
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "pass - increase allowance by 1 Evmos for multiple allocations with a single coin denomination",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ allocations := []transfertypes.Allocation{
+ {
+ SourcePort: "port-01",
+ SourceChannel: "channel-03",
+ SpendLimit: atomCoins,
+ AllowList: nil,
+ },
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: defaultCoins,
+ AllowList: nil,
+ },
+ }
+ err := s.NewTransferAuthorizationWithAllocations(s.ctx, s.app, differentAddress, s.address, allocations)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, atomCoins)
+ s.Require().Equal(transferAuthz.Allocations[1].SpendLimit, defaultCoins)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ }
+ },
+ func([]byte, []interface{}) {
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, atomCoins)
+ s.Require().Equal(transferAuthz.Allocations[1].SpendLimit[0].Amount, math.NewInt(2e18))
+ s.Require().Equal(transferAuthz.Allocations[1].SpendLimit[0].Denom, utils.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+ testCases = append(testCases, defaultAllowanceCases...)
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ args := tc.malleate()
+ bz, err := s.precompile.IncreaseAllowance(s.ctx, s.address, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().Equal(bz, cmn.TrueValue)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDecreaseAllowance() {
+ method := s.precompile.Methods[authorization.DecreaseAllowanceMethod]
+
+ testCases := []allowanceTestCase{
+ {
+ "fail - the new spend limit is negative",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, differentAddress, s.address, path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().NotNil(transferAuthz)
+ s.Require().Len(transferAuthz.Allocations, 1)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, defaultCoins)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(2e18),
+ }
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ cmn.ErrNegativeAmount,
+ },
+ {
+ "pass - decrease allowance by 1 EVMOS for a single allocation with a single coin denomination",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, differentAddress, s.address, path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().NotNil(transferAuthz)
+ s.Require().Len(transferAuthz.Allocations, 1)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, defaultCoins)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(500000000000000000),
+ }
+ },
+ func(_ []byte, _ []interface{}) {
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().NotNil(transferAuthz)
+ s.Require().Len(transferAuthz.Allocations, 1, "should have at least one allocation", transferAuthz)
+ s.Require().Len(transferAuthz.Allocations[0].SpendLimit, 1, "should have at least one coin; allocation %s", transferAuthz.Allocations[0])
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[0].Denom, utils.BaseDenom)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[0].Amount, math.NewInt(500000000000000000))
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "pass - decrease allowance by 1 Atom for single allocation with a multiple coin denomination",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, differentAddress, s.address, path, mutliSpendLimit, nil, nil)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, mutliSpendLimit)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ "uatom",
+ big.NewInt(500000000000000000),
+ }
+ },
+ func(_ []byte, _ []interface{}) {
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().NotNil(transferAuthz)
+ s.Require().Len(transferAuthz.Allocations, 1, "should have at least one allocation")
+ s.Require().Len(transferAuthz.Allocations[0].SpendLimit, len(mutliSpendLimit), "should have two coins; allocation %s", transferAuthz.Allocations[0])
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[1].Amount, math.NewInt(500000000000000000))
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[1].Denom, "uatom")
+ // other denom should remain unchanged
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit[0], defaultCoins[0])
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "pass - decrease allowance by 0.5 Evmos for multiple allocations with a single coin denomination",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ allocations := []transfertypes.Allocation{
+ {
+ SourcePort: "port-01",
+ SourceChannel: "channel-03",
+ SpendLimit: atomCoins,
+ AllowList: nil,
+ },
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: defaultCoins,
+ AllowList: nil,
+ },
+ }
+ err := s.NewTransferAuthorizationWithAllocations(s.ctx, s.app, differentAddress, s.address, allocations)
+ s.Require().NoError(err)
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, atomCoins)
+ s.Require().Equal(transferAuthz.Allocations[1].SpendLimit, defaultCoins)
+ return []interface{}{
+ differentAddress,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointB.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18 / 2),
+ }
+ },
+ func(_ []byte, _ []interface{}) {
+ transferAuthz := s.GetTransferAuthorization(s.ctx, differentAddress, s.address)
+ s.Require().Equal(transferAuthz.Allocations[1].SpendLimit[0].Amount, math.NewInt(1e18/2))
+ s.Require().Equal(transferAuthz.Allocations[1].SpendLimit[0].Denom, utils.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ testCases = append(testCases, defaultAllowanceCases...)
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ args := tc.malleate()
+ bz, err := s.precompile.DecreaseAllowance(s.ctx, s.address, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().Equal(bz, cmn.TrueValue)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
diff --git a/precompiles/ics20/errors.go b/precompiles/ics20/errors.go
new file mode 100644
index 00000000..84dca0ce
--- /dev/null
+++ b/precompiles/ics20/errors.go
@@ -0,0 +1,27 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+const (
+ // ErrInvalidSourcePort is raised when the source port is invalid.
+ ErrInvalidSourcePort = "invalid source port"
+ // ErrInvalidSourceChannel is raised when the source channel is invalid.
+ ErrInvalidSourceChannel = "invalid source port"
+ // ErrInvalidSender is raised when the sender is invalid.
+ ErrInvalidSender = "invalid sender: %s"
+ // ErrInvalidReceiver is raised when the receiver is invalid.
+ ErrInvalidReceiver = "invalid receiver: %s"
+ // ErrInvalidTimeoutTimestamp is raised when the timeout timestamp is invalid.
+ ErrInvalidTimeoutTimestamp = "invalid timeout timestamp: %d"
+ // ErrInvalidMemo is raised when the memo is invalid.
+ ErrInvalidMemo = "invalid memo: %s"
+ // ErrInvalidHash is raised when the hash is invalid.
+ ErrInvalidHash = "invalid hash: %s"
+ // ErrNoMatchingAllocation is raised when no matching allocation is found.
+ ErrNoMatchingAllocation = "no matching allocation found for source port: %s, source channel: %s, and denom: %s"
+ // ErrDifferentOriginFromSender is raised when the origin address is not the same as the sender address.
+ ErrDifferentOriginFromSender = "origin address %s is not the same as sender address %s"
+ // ErrTraceNotFound is raised when the denom trace for the specified request does not exist.
+ ErrTraceNotFound = "denomination trace not found"
+)
diff --git a/precompiles/ics20/events.go b/precompiles/ics20/events.go
new file mode 100644
index 00000000..cb135f02
--- /dev/null
+++ b/precompiles/ics20/events.go
@@ -0,0 +1,63 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // EventTypeIBCTransfer defines the event type for the ICS20 Transfer transaction.
+ EventTypeIBCTransfer = "IBCTransfer"
+)
+
+// EmitIBCTransferEvent creates a new IBC transfer event emitted on a Transfer transaction.
+func EmitIBCTransferEvent(
+ ctx sdk.Context,
+ stateDB vm.StateDB,
+ event abi.Event,
+ precompileAddr, senderAddr common.Address,
+ receiver string,
+ sourcePort, sourceChannel string,
+ token sdk.Coin,
+ memo string,
+) error {
+ // Prepare the event topics
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ // sender and receiver are indexed
+ topics[1], err = cmn.MakeTopic(senderAddr)
+ if err != nil {
+ return err
+ }
+ topics[2], err = cmn.MakeTopic(receiver)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data: denom, amount, memo
+ arguments := abi.Arguments{event.Inputs[2], event.Inputs[3], event.Inputs[4], event.Inputs[5], event.Inputs[6]}
+ packed, err := arguments.Pack(sourcePort, sourceChannel, token.Denom, token.Amount.BigInt(), memo)
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: precompileAddr,
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
diff --git a/precompiles/ics20/events_test.go b/precompiles/ics20/events_test.go
new file mode 100644
index 00000000..63f289e7
--- /dev/null
+++ b/precompiles/ics20/events_test.go
@@ -0,0 +1,311 @@
+package ics20_test
+
+import (
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/ics20"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func (s *PrecompileTestSuite) TestTransferEvent() {
+ method := s.precompile.Methods[ics20.TransferMethod]
+ testCases := []struct {
+ name string
+ malleate func(sender, receiver sdk.AccAddress) []interface{}
+ expErr bool
+ errContains string
+ postCheck func(sender, receiver sdk.AccAddress)
+ }{
+ {
+ "success - transfer event emitted",
+ func(sender, receiver sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, common.BytesToAddress(sender), common.BytesToAddress(sender), path, defaultCoins, nil, []string{"memo"})
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(sender.Bytes()),
+ receiver.String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ false,
+ "",
+ func(sender, receiver sdk.AccAddress) {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[ics20.EventTypeIBCTransfer]
+ s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var ibcTransferEvent ics20.EventIBCTransfer
+ err := cmn.UnpackLog(s.precompile.ABI, &ibcTransferEvent, ics20.EventTypeIBCTransfer, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(common.BytesToAddress(sender.Bytes()), ibcTransferEvent.Sender)
+ s.Require().Equal(crypto.Keccak256Hash([]byte(receiver.String())), ibcTransferEvent.Receiver)
+ s.Require().Equal("transfer", ibcTransferEvent.SourcePort)
+ s.Require().Equal("channel-0", ibcTransferEvent.SourceChannel)
+ s.Require().Equal(big.NewInt(1e18), ibcTransferEvent.Amount)
+ s.Require().Equal(utils.BaseDenom, ibcTransferEvent.Denom)
+ s.Require().Equal("memo", ibcTransferEvent.Memo)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ sender := s.chainA.SenderAccount.GetAddress()
+ receiver := s.chainB.SenderAccount.GetAddress()
+ contract := vm.NewContract(vm.AccountRef(sender), s.precompile, big.NewInt(0), 20000)
+ _, err := s.precompile.Transfer(s.ctx, common.BytesToAddress(sender), contract, s.stateDB, &method, tc.malleate(sender, receiver))
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(sender, receiver)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestApproveTransferAuthorizationEvent() {
+ method := s.precompile.Methods[authorization.ApproveMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - transfer authorization event emitted with default coins ",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ return []interface{}{
+ s.address,
+ []cmn.ICS20Allocation{
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: defaultCmnCoins,
+ AllowList: nil,
+ },
+ },
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[authorization.EventTypeIBCTransferAuthorization]
+ s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var transferAuthorizationEvent ics20.EventTransferAuthorization
+ err := cmn.UnpackLog(s.precompile.ABI, &transferAuthorizationEvent, authorization.EventTypeIBCTransferAuthorization, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, transferAuthorizationEvent.Granter)
+ s.Require().Equal(s.address, transferAuthorizationEvent.Grantee)
+ s.Require().Equal("transfer", transferAuthorizationEvent.Allocations[0].SourcePort)
+ s.Require().Equal("channel-0", transferAuthorizationEvent.Allocations[0].SourceChannel)
+ abiCoins := cmn.NewCoinsResponse(defaultCoins)
+ s.Require().Equal(abiCoins, transferAuthorizationEvent.Allocations[0].SpendLimit)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ _, err := s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRevokeTransferAuthorizationEvent() {
+ method := s.precompile.Methods[authorization.ApproveMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - transfer revoke authorization event emitted",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, s.address, s.address, path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[authorization.EventTypeIBCTransferAuthorization]
+ s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var transferRevokeAuthorizationEvent ics20.EventTransferAuthorization
+ err := cmn.UnpackLog(s.precompile.ABI, &transferRevokeAuthorizationEvent, authorization.EventTypeIBCTransferAuthorization, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, transferRevokeAuthorizationEvent.Grantee)
+ s.Require().Equal(s.address, transferRevokeAuthorizationEvent.Granter)
+ s.Require().Equal(0, len(transferRevokeAuthorizationEvent.Allocations))
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ _, err := s.precompile.Revoke(s.ctx, s.address, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestIncreaseAllowanceEvent() {
+ method := s.precompile.Methods[authorization.IncreaseAllowanceMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - increased allowance by 1 Evmos",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, s.address, s.address, path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ amount := big.NewInt(1e18)
+ s.CheckAllowanceChangeEvent(log, amount, true)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ _, err := s.precompile.IncreaseAllowance(s.ctx, s.address, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDecreaseAllowanceEvent() {
+ method := s.precompile.Methods[authorization.DecreaseAllowanceMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - decrease allowance by 0.5 Evmos",
+ func() []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, s.address, s.address, path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18 / 2),
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ amount := big.NewInt(1e18 / 2)
+ s.CheckAllowanceChangeEvent(log, amount, false)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ _, err := s.precompile.DecreaseAllowance(s.ctx, s.address, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
diff --git a/precompiles/ics20/ics20.go b/precompiles/ics20/ics20.go
new file mode 100644
index 00000000..9ae43952
--- /dev/null
+++ b/precompiles/ics20/ics20.go
@@ -0,0 +1,162 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+import (
+ "embed"
+ "fmt"
+
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ channelkeeper "github.com/cosmos/ibc-go/v7/modules/core/04-channel/keeper"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ transferkeeper "github.com/evmos/evmos/v19/x/ibc/transfer/keeper"
+ stakingkeeper "github.com/evmos/evmos/v19/x/staking/keeper"
+)
+
+var _ vm.PrecompiledContract = &Precompile{}
+
+// Embed abi json file to the executable binary. Needed when importing as dependency.
+//
+//go:embed abi.json
+var f embed.FS
+
+type Precompile struct {
+ cmn.Precompile
+ stakingKeeper stakingkeeper.Keeper
+ transferKeeper transferkeeper.Keeper
+ channelKeeper channelkeeper.Keeper
+}
+
+// NewPrecompile creates a new ICS-20 Precompile instance as a
+// PrecompiledContract interface.
+func NewPrecompile(
+ stakingKeeper stakingkeeper.Keeper,
+ transferKeeper transferkeeper.Keeper,
+ channelKeeper channelkeeper.Keeper,
+ authzKeeper authzkeeper.Keeper,
+) (*Precompile, error) {
+ newAbi, err := cmn.LoadABI(f, "abi.json")
+ if err != nil {
+ return nil, err
+ }
+
+ p := &Precompile{
+ Precompile: cmn.Precompile{
+ ABI: newAbi,
+ AuthzKeeper: authzKeeper,
+ KvGasConfig: storetypes.KVGasConfig(),
+ TransientKVGasConfig: storetypes.TransientGasConfig(),
+ ApprovalExpiration: cmn.DefaultExpirationDuration, // should be configurable in the future.
+ },
+ transferKeeper: transferKeeper,
+ channelKeeper: channelKeeper,
+ stakingKeeper: stakingKeeper,
+ }
+
+ // SetAddress defines the address of the ICS-20 compile contract.
+ p.SetAddress(common.HexToAddress(evmtypes.ICS20PrecompileAddress))
+
+ return p, nil
+}
+
+// RequiredGas calculates the precompiled contract's base gas rate.
+func (p Precompile) RequiredGas(input []byte) uint64 {
+ // NOTE: This check avoid panicking when trying to decode the method ID
+ if len(input) < 4 {
+ return 0
+ }
+
+ methodID := input[:4]
+
+ method, err := p.MethodById(methodID)
+ if err != nil {
+ // This should never happen since this method is going to fail during Run
+ return 0
+ }
+
+ return p.Precompile.RequiredGas(input, p.IsTransaction(method.Name))
+}
+
+// Run executes the precompiled contract IBC transfer methods defined in the ABI.
+func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) {
+ ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction)
+ if err != nil {
+ return nil, err
+ }
+
+ // This handles any out of gas errors that may occur during the execution of a precompile tx or query.
+ // It avoids panics and returns the out of gas error so the EVM can continue gracefully.
+ defer cmn.HandleGasError(ctx, contract, initialGas, &err)()
+
+ switch method.Name {
+ // TODO Approval transactions => need cosmos-sdk v0.46 & ibc-go v6.2.0
+ // Authorization Methods:
+ case authorization.ApproveMethod:
+ bz, err = p.Approve(ctx, evm.Origin, stateDB, method, args)
+ case authorization.RevokeMethod:
+ bz, err = p.Revoke(ctx, evm.Origin, stateDB, method, args)
+ case authorization.IncreaseAllowanceMethod:
+ bz, err = p.IncreaseAllowance(ctx, evm.Origin, stateDB, method, args)
+ case authorization.DecreaseAllowanceMethod:
+ bz, err = p.DecreaseAllowance(ctx, evm.Origin, stateDB, method, args)
+ // ICS20 transactions
+ case TransferMethod:
+ bz, err = p.Transfer(ctx, evm.Origin, contract, stateDB, method, args)
+ // ICS20 queries
+ case DenomTraceMethod:
+ bz, err = p.DenomTrace(ctx, contract, method, args)
+ case DenomTracesMethod:
+ bz, err = p.DenomTraces(ctx, contract, method, args)
+ case DenomHashMethod:
+ bz, err = p.DenomHash(ctx, contract, method, args)
+ case authorization.AllowanceMethod:
+ bz, err = p.Allowance(ctx, method, args)
+ default:
+ return nil, fmt.Errorf(cmn.ErrUnknownMethod, method.Name)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ cost := ctx.GasMeter().GasConsumed() - initialGas
+
+ if !contract.UseGas(cost) {
+ return nil, vm.ErrOutOfGas
+ }
+
+ if err := p.AddJournalEntries(stateDB, snapshot); err != nil {
+ return nil, err
+ }
+
+ return bz, nil
+}
+
+// IsTransaction checks if the given method name corresponds to a transaction or query.
+//
+// Available ics20 transactions are:
+// - Transfer
+//
+// Available authorization transactions are:
+// - Approve
+// - Revoke
+// - IncreaseAllowance
+// - DecreaseAllowance
+func (Precompile) IsTransaction(method string) bool {
+ switch method {
+ case TransferMethod,
+ authorization.ApproveMethod,
+ authorization.RevokeMethod,
+ authorization.IncreaseAllowanceMethod,
+ authorization.DecreaseAllowanceMethod:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/precompiles/ics20/integration_test.go b/precompiles/ics20/integration_test.go
new file mode 100644
index 00000000..0aa24e08
--- /dev/null
+++ b/precompiles/ics20/integration_test.go
@@ -0,0 +1,1726 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package ics20_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ "github.com/ethereum/go-ethereum/common"
+ evmoscontracts "github.com/evmos/evmos/v19/contracts"
+ evmostesting "github.com/evmos/evmos/v19/ibc/testing"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/precompiles/ics20"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/precompiles/testutil/contracts"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ teststypes "github.com/evmos/evmos/v19/types/tests"
+ "github.com/evmos/evmos/v19/utils"
+ erc20types "github.com/evmos/evmos/v19/x/erc20/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+)
+
+// General variables used for integration tests
+var (
+ // defaultCallArgs and defaultApproveArgs are the default arguments for calling the smart contract and to
+ // call the approve method specifically.
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultCallArgs, defaultApproveArgs contracts.CallArgs
+
+ // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated.
+ defaultLogCheck testutil.LogCheckArgs
+ // passCheck defines the arguments to check if the precompile returns no error
+ passCheck testutil.LogCheckArgs
+ // outOfGasCheck defines the arguments to check if the precompile returns out of gas error
+ outOfGasCheck testutil.LogCheckArgs
+
+ // gasPrice defines a default gas price to be used in the testing suite
+ gasPrice = big.NewInt(200_000)
+
+ // array of allocations with only one allocation for 'aevmos' coin
+ defaultSingleAlloc []cmn.ICS20Allocation
+
+ // interchainSenderContract is the compiled contract calling the interchain functionality
+ interchainSenderContract evmtypes.CompiledContract
+)
+
+var _ = Describe("IBCTransfer Precompile", func() {
+ BeforeEach(func() {
+ s.suiteIBCTesting = true
+ s.SetupTest()
+ s.setupAllocationsForTesting()
+
+ var err error
+ Expect(err).To(BeNil(), "error while loading the interchain sender contract: %v", err)
+
+ // set the default call arguments
+ defaultCallArgs = contracts.CallArgs{
+ ContractAddr: s.precompile.Address(),
+ ContractABI: s.precompile.ABI,
+ PrivKey: s.privKey,
+ GasPrice: gasPrice,
+ }
+ defaultApproveArgs = defaultCallArgs.WithMethodName(authorization.ApproveMethod)
+
+ defaultLogCheck = testutil.LogCheckArgs{
+ ABIEvents: s.precompile.ABI.Events,
+ }
+ passCheck = defaultLogCheck.WithExpPass(true)
+ outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error())
+ })
+
+ Describe("Execute approve transaction", func() {
+ BeforeEach(func() {
+ // check no previous authorization exist
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(0), "expected no authorizations before tests")
+ defaultSingleAlloc = []cmn.ICS20Allocation{
+ {
+ SourcePort: ibctesting.TransferPort,
+ SourceChannel: s.transferPath.EndpointA.ChannelID,
+ SpendLimit: defaultCmnCoins,
+ AllowedPacketData: []string{"memo"},
+ },
+ }
+ })
+
+ // TODO uncomment when enforcing grantee != origin
+ // It("should return error if the origin is same as the spender", func() {
+ // approveArgs := defaultApproveArgs.WithArgs(
+ // s.address,
+ // defaultSingleAlloc,
+ // )
+
+ // _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, approveArgs, differentOriginCheck)
+ // Expect(err).To(BeNil(), "error while calling the precompile")
+
+ // s.chainA.NextBlock()
+
+ // // check no authorization exist
+ // auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ // Expect(err).To(BeNil(), "error while getting authorizations")
+ // Expect(auths).To(HaveLen(0), "expected no authorization")
+ // })
+
+ It("should return error if the provided gasLimit is too low", func() {
+ approveArgs := defaultApproveArgs.
+ WithGasLimit(30000).
+ WithArgs(
+ s.differentAddr,
+ defaultSingleAlloc,
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, approveArgs, outOfGasCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring(vm.ErrOutOfGas.Error()))
+
+ s.chainA.NextBlock()
+
+ // check no authorization exist
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil())
+ Expect(auths).To(HaveLen(0))
+ })
+
+ It("should approve the corresponding allocation", func() {
+ approveArgs := defaultApproveArgs.WithArgs(
+ s.differentAddr,
+ defaultSingleAlloc,
+ )
+
+ approvalCheck := passCheck.
+ WithExpEvents(authorization.EventTypeIBCTransferAuthorization)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, approveArgs, approvalCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check GetAuthorizations is returning the record
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit).To(Equal(defaultCoins))
+ })
+ })
+
+ Describe("Execute revoke transaction", func() {
+ var defaultRevokeArgs contracts.CallArgs
+ BeforeEach(func() {
+ // create authorization
+ s.setTransferApproval(defaultCallArgs, s.differentAddr, defaultSingleAlloc)
+ defaultRevokeArgs = defaultCallArgs.WithMethodName(authorization.RevokeMethod)
+ })
+
+ It("should revoke authorization", func() {
+ revokeArgs := defaultRevokeArgs.WithArgs(
+ s.differentAddr,
+ )
+ revokeCheck := passCheck.
+ WithExpEvents(authorization.EventTypeIBCTransferAuthorization)
+
+ _, _, err := contracts.CallContractAndCheckLogs(
+ s.chainA.GetContext(),
+ s.app,
+ revokeArgs,
+ revokeCheck,
+ )
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check no authorization exist
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(0), "expected no authorization")
+ })
+ })
+
+ Describe("Execute increase allowance transaction", func() {
+ BeforeEach(func() {
+ s.setTransferApproval(defaultCallArgs, s.differentAddr, defaultSingleAlloc)
+ })
+
+ // TODO uncomment when enforcing grantee != origin
+ // this is a copy of a different test but for a different method
+ // It("should return an error if the origin is same as the spender", func() {
+ // increaseAllowanceArgs := defaultCallArgs.
+ // WithMethodName(authorization.IncreaseAllowanceMethod).
+ // WithArgs(
+ // s.address,
+ // s.transferPath.EndpointA.ChannelConfig.PortID,
+ // s.transferPath.EndpointA.ChannelID,
+ // utils.BaseDenom,
+ // big.NewInt(1e18),
+ // )
+
+ // differentOriginCheck := defaultLogCheck.WithErrContains(cmn.ErrDifferentOrigin, s.address, s.differentAddr)
+
+ // _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, increaseAllowanceArgs, differentOriginCheck)
+ // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // // check no authorization exist
+ // auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.address.Bytes(), s.address.Bytes())
+ // Expect(err).To(BeNil(), "error while getting authorizations")
+ // Expect(auths).To(BeNil())
+ // })
+
+ It("should return an error if the allocation denom is not present", func() { //nolint:dupl
+ increaseAllowanceArgs := defaultCallArgs.
+ WithMethodName(authorization.IncreaseAllowanceMethod).
+ WithArgs(
+ s.differentAddr,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ "urandom",
+ big.NewInt(1e18),
+ )
+
+ noMatchingAllocation := defaultLogCheck.WithErrContains(
+ ics20.ErrNoMatchingAllocation,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ "urandom",
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, increaseAllowanceArgs, noMatchingAllocation)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring(ics20.ErrNoMatchingAllocation, "transfer", "channel-0", "urandom"))
+
+ // check authorization didn't change
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit).To(Equal(defaultCoins))
+ })
+
+ It("should increase allowance by 1 EVMOS", func() {
+ s.setTransferApproval(defaultCallArgs, s.differentAddr, defaultSingleAlloc)
+
+ increaseAllowanceArgs := defaultCallArgs.
+ WithMethodName(authorization.IncreaseAllowanceMethod).
+ WithArgs(
+ s.differentAddr,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ )
+
+ allowanceCheck := passCheck.WithExpEvents(authorization.EventTypeIBCTransferAuthorization)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, increaseAllowanceArgs, allowanceCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check auth was updated
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit).To(Equal(defaultCoins.Add(sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewInt(1e18)})))
+ })
+ })
+
+ Describe("Execute decrease allowance transaction", func() {
+ BeforeEach(func() {
+ s.setTransferApproval(defaultCallArgs, s.differentAddr, defaultSingleAlloc)
+ })
+
+ It("should fail if decreased amount is more than the total spend limit left", func() {
+ decreaseAllowance := defaultCallArgs.
+ WithMethodName(authorization.DecreaseAllowanceMethod).
+ WithArgs(
+ s.differentAddr,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(2e18),
+ )
+
+ allowanceCheck := defaultLogCheck.WithErrContains("negative amount")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, decreaseAllowance, allowanceCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring("negative amount"))
+ })
+
+ // TODO uncomment when enforcing grantee != origin
+ // //nolint:dupl // this is a copy of a different test but for a different method
+ // It("should return an error if the origin same the spender", func() {
+ // decreaseAllowance := defaultCallArgs.
+ // WithMethodName(authorization.DecreaseAllowanceMethod).
+ // WithArgs(
+ // s.address,
+ // s.transferPath.EndpointA.ChannelConfig.PortID,
+ // s.transferPath.EndpointA.ChannelID,
+ // utils.BaseDenom,
+ // big.NewInt(1e18),
+ // )
+
+ // differentOriginCheck := defaultLogCheck.WithErrContains(cmn.ErrDifferentOrigin, s.address, s.differentAddr)
+
+ // _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, decreaseAllowance, differentOriginCheck)
+ // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // // check authorization does not exist
+ // auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.address.Bytes(), s.address.Bytes())
+ // Expect(err).To(BeNil(), "error while getting authorizations")
+ // Expect(auths).To(BeNil())
+ // })
+
+ It("should return an error if the allocation denom is not present", func() { //nolint:dupl
+ decreaseAllowance := defaultCallArgs.
+ WithMethodName(authorization.DecreaseAllowanceMethod).
+ WithArgs(
+ s.differentAddr,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ "urandom",
+ big.NewInt(1e18),
+ )
+
+ noMatchingAllocation := defaultLogCheck.WithErrContains(
+ ics20.ErrNoMatchingAllocation,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ "urandom",
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, decreaseAllowance, noMatchingAllocation)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring(ics20.ErrNoMatchingAllocation, "transfer", "channel-0", "urandom"))
+
+ // check authorization didn't change
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit).To(Equal(defaultCoins))
+ })
+
+ It("should delete grant if allowance is decreased to 0", func() {
+ decreaseAllowance := defaultCallArgs.
+ WithMethodName(authorization.DecreaseAllowanceMethod).
+ WithArgs(
+ s.differentAddr,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ )
+
+ allowanceCheck := passCheck.WithExpEvents(authorization.EventTypeIBCTransferAuthorization)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, decreaseAllowance, allowanceCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check auth record
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), s.differentAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit).To(HaveLen(0))
+ })
+ })
+
+ Describe("Execute transfer transaction", func() {
+ var defaultTransferArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ // populate the default transfer args
+ defaultTransferArgs = defaultCallArgs.
+ WithMethodName(ics20.TransferMethod).
+ WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.bondDenom,
+ defaultCmnCoins[0].Amount,
+ s.address,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+ })
+
+ Context("without authorization", func() {
+ It("owner should transfer without authorization", func() {
+ initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultTransferArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // check the sender balance was deducted
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees).Sub(defaultCoins[0].Amount)))
+ })
+
+ It("should succeed in transfer transaction but should timeout and refund sender", func() {
+ initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+ timeoutHeight := clienttypes.NewHeight(clienttypes.ParseChainID(s.chainB.ChainID), uint64(s.chainB.GetContext().BlockHeight())+1)
+
+ transferArgs := defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.bondDenom,
+ defaultCmnCoins[0].Amount,
+ s.address,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ timeoutHeight,
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, transferArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ sequence, ok := out[0].(uint64)
+ Expect(ok).To(BeTrue())
+ Expect(sequence).To(Equal(uint64(1)))
+
+ // check the sender balance was deducted
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees).Sub(defaultCoins[0].Amount)))
+
+ // the transfer is reverted because the packet times out
+ // build the sent packet
+ // this is the packet sent
+ packet := s.makePacket(
+ sdk.AccAddress(s.address.Bytes()).String(),
+ s.chainB.SenderAccount.GetAddress().String(),
+ s.bondDenom,
+ "memo",
+ defaultCmnCoins[0].Amount,
+ sequence,
+ timeoutHeight,
+ )
+
+ // packet times out and the OnTimeoutPacket callback is executed
+ s.chainA.NextBlock()
+ // increment block height on chainB to make the packet timeout
+ s.chainB.NextBlock()
+
+ // increment sequence for successful transaction execution
+ err = s.chainA.SenderAccount.SetSequence(s.chainA.SenderAccount.GetSequence() + 1)
+ s.Require().NoError(err)
+
+ err = s.transferPath.EndpointA.UpdateClient()
+ Expect(err).To(BeNil())
+
+ // Receive timeout
+ err = s.transferPath.EndpointA.TimeoutPacket(packet)
+ Expect(err).To(BeNil())
+
+ // To submit a timeoutMsg, the TimeoutPacket function
+ // uses a default fee amount
+ timeoutMsgFee := math.NewInt(evmostesting.DefaultFeeAmt * 2)
+ fees = fees.Add(timeoutMsgFee)
+
+ finalBalance = s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees)))
+ })
+
+ It("should not transfer other account's balance", func() {
+ // initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ // fund senders account
+ err := evmosutil.FundAccountWithBaseDenom(s.chainA.GetContext(), s.app.BankKeeper, s.differentAddr.Bytes(), amt)
+ Expect(err).To(BeNil())
+ senderInitialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.differentAddr.Bytes(), s.bondDenom)
+ Expect(senderInitialBalance.Amount).To(Equal(math.NewInt(amt)))
+
+ transferArgs := defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.bondDenom,
+ defaultCmnCoins[0].Amount,
+ s.differentAddr,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(ics20.ErrDifferentOriginFromSender, s.address, s.differentAddr)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, transferArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring(ics20.ErrDifferentOriginFromSender, s.address, s.differentAddr))
+
+ // check the sender only paid for the fees
+ // and funds were not transferred
+ // TODO: fees are not calculated correctly with this logic
+ // fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ // finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ // Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees)))
+
+ senderFinalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.differentAddr.Bytes(), s.bondDenom)
+ Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount))
+ })
+ })
+
+ Context("with authorization", func() {
+ BeforeEach(func() {
+ expTime := s.chainA.GetContext().BlockTime().Add(s.precompile.ApprovalExpiration)
+
+ allocations := []transfertypes.Allocation{
+ {
+ SourcePort: s.transferPath.EndpointA.ChannelConfig.PortID,
+ SourceChannel: s.transferPath.EndpointA.ChannelID,
+ SpendLimit: defaultCoins,
+ },
+ }
+
+ // create grant to allow s.address to spend differentAddr funds
+ err := s.app.AuthzKeeper.SaveGrant(
+ s.chainA.GetContext(),
+ s.address.Bytes(),
+ s.differentAddr.Bytes(),
+ &transfertypes.TransferAuthorization{Allocations: allocations},
+ &expTime,
+ )
+ Expect(err).To(BeNil())
+
+ // fund the account from which funds will be sent
+ err = evmosutil.FundAccountWithBaseDenom(s.chainA.GetContext(), s.app.BankKeeper, s.differentAddr.Bytes(), amt)
+ Expect(err).To(BeNil())
+ senderInitialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.differentAddr.Bytes(), s.bondDenom)
+ Expect(senderInitialBalance.Amount).To(Equal(math.NewInt(amt)))
+ })
+
+ It("should not transfer other account's balance", func() {
+ // ATM it is not allowed for another EOA to spend other EOA
+ // funds via EVM extensions.
+ // However, it is allowed for a contract to spend an EOA's account and
+ // an EOA account to spend a contract's balance
+ // if the required authorization exist
+ // initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ transferArgs := defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.bondDenom,
+ defaultCmnCoins[0].Amount,
+ s.differentAddr,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(ics20.ErrDifferentOriginFromSender, s.address, s.differentAddr)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, transferArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring(ics20.ErrDifferentOriginFromSender, s.address, s.differentAddr))
+
+ // check the sender only paid for the fees
+ // and funds from the other account were not transferred
+ // TODO: fees are not calculated correctly with this logic
+ // fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ // finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ // Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees)))
+
+ senderFinalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.differentAddr.Bytes(), s.bondDenom)
+ Expect(senderFinalBalance.Amount).To(Equal(math.NewInt(amt)))
+ })
+ })
+
+ Context("sending ERC20 coins", func() {
+ var (
+ // erc20Addr is the address of the ERC20 contract
+ erc20Addr common.Address
+ // sentAmount is the amount of tokens to send for testing
+ sentAmount = big.NewInt(1000)
+ tokenPair *erc20types.TokenPair
+ defaultErc20TransferArgs contracts.CallArgs
+ err error
+ )
+
+ BeforeEach(func() {
+ erc20Addr = s.setupERC20ContractTests(sentAmount)
+ // register the token pair
+ tokenPair, err = s.app.Erc20Keeper.RegisterERC20(s.chainA.GetContext(), erc20Addr)
+ Expect(err).To(BeNil(), "error while registering the token pair: %v", err)
+
+ defaultErc20TransferArgs = defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ tokenPair.Denom,
+ sentAmount,
+ s.address,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+ })
+
+ Context("without authorization", func() {
+ It("should transfer registered ERC20s", func() {
+ preBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultErc20TransferArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ Expect(out[0]).To(Equal(uint64(1)))
+
+ s.chainA.NextBlock()
+
+ // check only fees were deducted from sending account
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(preBalance.Amount.Sub(fees)))
+
+ // check Erc20 balance was reduced by sent amount
+ balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(balance.Int64()).To(BeZero(), "address does not have the expected amount of tokens")
+ })
+
+ It("should not transfer other account's balance", func() {
+ // mint some ERC20 to the sender's account
+ defaultERC20CallArgs := contracts.CallArgs{
+ ContractAddr: erc20Addr,
+ ContractABI: evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ PrivKey: s.privKey,
+ GasPrice: gasPrice,
+ }
+
+ // mint coins to the address
+ mintCoinsArgs := defaultERC20CallArgs.
+ WithMethodName("mint").
+ WithArgs(s.differentAddr, defaultCmnCoins[0].Amount)
+
+ mintCheck := testutil.LogCheckArgs{
+ ABIEvents: evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI.Events,
+ ExpEvents: []string{erc20.EventTypeTransfer}, // upon minting the tokens are sent to the receiving address
+ ExpPass: true,
+ }
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, mintCoinsArgs, mintCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // try to transfer other account's erc20 tokens
+ transferArgs := defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ tokenPair.Denom,
+ defaultCmnCoins[0].Amount,
+ s.differentAddr,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(ics20.ErrDifferentOriginFromSender, s.address, s.differentAddr)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, transferArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring(ics20.ErrDifferentOriginFromSender, s.address, s.differentAddr))
+
+ // check funds were not transferred
+ balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.differentAddr,
+ )
+ Expect(balance).To(Equal(defaultCmnCoins[0].Amount), "address does not have the expected amount of tokens")
+ })
+
+ It("should succeed in transfer transaction but should error on packet destination if the receiver address is wrong", func() {
+ preBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ invalidReceiverAddr := "invalid_address"
+ transferArgs := defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ tokenPair.Denom,
+ sentAmount,
+ s.address,
+ invalidReceiverAddr, // invalid receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, transferArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ sequence, ok := out[0].(uint64)
+ Expect(ok).To(BeTrue())
+ Expect(sequence).To(Equal(uint64(1)))
+
+ s.chainA.NextBlock()
+
+ // check only fees were deducted from sending account
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(preBalance.Amount.Sub(fees)))
+
+ // check Erc20 balance was reduced by sent amount (escrowed on ibc escrow account)
+ balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(balance.Int64()).To(BeZero(), "address does not have the expected amount of tokens")
+
+ // the transfer is reverted because fails checks on the receiving chain
+ // this is the packet sent
+ packet := s.makePacket(
+ sdk.AccAddress(s.address.Bytes()).String(),
+ invalidReceiverAddr,
+ tokenPair.Denom,
+ "memo",
+ sentAmount,
+ sequence,
+ s.chainB.GetTimeoutHeight(),
+ )
+
+ // increment sequence for successful transaction execution
+ err = s.chainA.SenderAccount.SetSequence(s.chainA.SenderAccount.GetSequence() + 3)
+ s.Require().NoError(err)
+
+ err = s.transferPath.EndpointA.UpdateClient()
+ Expect(err).To(BeNil())
+
+ // Relay packet
+ err = s.transferPath.RelayPacket(packet)
+ Expect(err).To(BeNil())
+
+ // check escrowed funds are refunded to sender
+ finalERC20balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(finalERC20balance).To(Equal(sentAmount), "address does not have the expected amount of tokens")
+ })
+
+ It("should succeed in transfer transaction but should timeout", func() {
+ preBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ timeoutHeight := clienttypes.NewHeight(clienttypes.ParseChainID(s.chainB.ChainID), uint64(s.chainB.GetContext().BlockHeight())+1)
+
+ transferArgs := defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ tokenPair.Denom,
+ sentAmount,
+ s.address,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ timeoutHeight,
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, transferArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ sequence, ok := out[0].(uint64)
+ Expect(ok).To(BeTrue())
+ Expect(sequence).To(Equal(uint64(1)))
+
+ s.chainA.NextBlock()
+
+ // check only fees were deducted from sending account
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(preBalance.Amount.Sub(fees)))
+
+ // check Erc20 balance was reduced by sent amount
+ balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(balance.Int64()).To(BeZero(), "address does not have the expected amount of tokens")
+
+ // the transfer is reverted because the packet times out
+ // this is the packet sent
+ packet := s.makePacket(
+ sdk.AccAddress(s.address.Bytes()).String(),
+ s.chainB.SenderAccount.GetAddress().String(),
+ tokenPair.Denom,
+ "memo",
+ sentAmount,
+ sequence,
+ timeoutHeight,
+ )
+
+ // packet times out and the OnTimeoutPacket callback is executed
+ s.chainA.NextBlock()
+ // increment block height on chainB to make the packet timeout
+ s.chainB.NextBlock()
+
+ // increment sequence for successful transaction execution
+ err = s.chainA.SenderAccount.SetSequence(s.chainA.SenderAccount.GetSequence() + 3)
+ s.Require().NoError(err)
+
+ err = s.transferPath.EndpointA.UpdateClient()
+ Expect(err).To(BeNil())
+
+ // Receive timeout
+ err = s.transferPath.EndpointA.TimeoutPacket(packet)
+ Expect(err).To(BeNil())
+
+ // check escrowed funds are refunded to sender
+ finalERC20balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(finalERC20balance).To(Equal(sentAmount), "address does not have the expected amount of tokens")
+ })
+ })
+ })
+ })
+
+ Context("Queries", func() {
+ var (
+ path string
+ expTrace transfertypes.DenomTrace
+ )
+
+ BeforeEach(func() {
+ path = fmt.Sprintf(
+ "%s/%s/%s/%s",
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.transferPath.EndpointB.ChannelConfig.PortID,
+ s.transferPath.EndpointB.ChannelID,
+ )
+ expTrace = transfertypes.DenomTrace{
+ Path: path,
+ BaseDenom: utils.BaseDenom,
+ }
+ })
+
+ It("should query denom trace", func() {
+ // setup - create a denom trace to get it on the query result
+ method := ics20.DenomTraceMethod
+ s.app.TransferKeeper.SetDenomTrace(s.chainA.GetContext(), expTrace)
+
+ args := defaultCallArgs.
+ WithMethodName(method).
+ WithArgs(expTrace.IBCDenom())
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out ics20.DenomTraceResponse
+ err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the output: %v", err)
+ Expect(out.DenomTrace.Path).To(Equal(expTrace.Path))
+ Expect(out.DenomTrace.BaseDenom).To(Equal(expTrace.BaseDenom))
+ })
+
+ Context("denom traces query", func() {
+ var (
+ method string
+ expTraces []transfertypes.DenomTrace
+ )
+ BeforeEach(func() {
+ method = ics20.DenomTracesMethod
+ // setup - create some denom traces to get on the query result
+ expTraces = []transfertypes.DenomTrace{
+ {Path: "", BaseDenom: utils.BaseDenom},
+ {Path: fmt.Sprintf("%s/%s", s.transferPath.EndpointA.ChannelConfig.PortID, s.transferPath.EndpointA.ChannelID), BaseDenom: utils.BaseDenom},
+ expTrace,
+ }
+
+ for _, trace := range expTraces {
+ s.app.TransferKeeper.SetDenomTrace(s.chainA.GetContext(), trace)
+ }
+ })
+ It("should query denom traces - w/all results on page", func() {
+ args := defaultCallArgs.
+ WithMethodName(method).
+ WithArgs(
+ query.PageRequest{
+ Limit: 3,
+ CountTotal: true,
+ })
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out ics20.DenomTracesResponse
+ err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the output: %v", err)
+ Expect(out.DenomTraces).To(HaveLen(3), "expected 3 denom traces to be returned")
+ Expect(out.PageResponse.Total).To(Equal(uint64(3)))
+ Expect(out.PageResponse.NextKey).To(BeEmpty())
+
+ for i, dt := range out.DenomTraces {
+ // order can change
+ Expect(dt.Path).To(Equal(expTraces[i].Path))
+ Expect(dt.BaseDenom).To(Equal(expTraces[i].BaseDenom))
+ }
+ })
+
+ It("should query denom traces - w/pagination", func() {
+ args := defaultCallArgs.
+ WithMethodName(method).
+ WithArgs(
+ query.PageRequest{
+ Limit: 1,
+ CountTotal: true,
+ })
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out ics20.DenomTracesResponse
+ err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the output: %v", err)
+ Expect(out.DenomTraces).To(HaveLen(1), "expected 1 denom traces to be returned")
+ Expect(out.PageResponse.Total).To(Equal(uint64(3)))
+ Expect(out.PageResponse.NextKey).NotTo(BeEmpty())
+ })
+ })
+
+ It("should query denom hash", func() {
+ method := ics20.DenomHashMethod
+ // setup - create a denom expTrace
+ s.app.TransferKeeper.SetDenomTrace(s.chainA.GetContext(), expTrace)
+
+ args := defaultCallArgs.
+ WithMethodName(method).
+ WithArgs(expTrace.GetFullDenomPath())
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(method, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the output: %v", err)
+ Expect(out).To(HaveLen(1))
+ Expect(out[0]).To(Equal(expTrace.Hash().String()))
+ })
+ })
+
+ Context("query allowance", func() {
+ Context("No authorization", func() {
+ It("should return empty array", func() {
+ method := authorization.AllowanceMethod
+
+ args := defaultCallArgs.
+ WithMethodName(method).
+ WithArgs(s.address, s.differentAddr)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out []cmn.ICS20Allocation
+ err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the output: %v", err)
+ Expect(out).To(HaveLen(0))
+ })
+ })
+
+ Context("with authorization", func() {
+ BeforeEach(func() {
+ s.setTransferApproval(defaultCallArgs, s.differentAddr, defaultSingleAlloc)
+ })
+
+ It("should return the allowance", func() {
+ method := authorization.AllowanceMethod
+
+ args := defaultCallArgs.
+ WithMethodName(method).
+ WithArgs(s.differentAddr, s.address)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var out []cmn.ICS20Allocation
+ err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the output: %v", err)
+ Expect(out).To(HaveLen(1))
+ Expect(len(out)).To(Equal(len(defaultSingleAlloc)))
+ Expect(out[0].SourcePort).To(Equal(defaultSingleAlloc[0].SourcePort))
+ Expect(out[0].SourceChannel).To(Equal(defaultSingleAlloc[0].SourceChannel))
+ Expect(out[0].SpendLimit).To(Equal(defaultSingleAlloc[0].SpendLimit))
+ Expect(out[0].AllowList).To(HaveLen(0))
+ Expect(out[0].AllowedPacketData).To(HaveLen(1))
+ Expect(out[0].AllowedPacketData[0]).To(Equal("memo"))
+ })
+ })
+ })
+})
+
+var _ = Describe("Calling ICS20 precompile from another contract", func() {
+ var (
+
+ // interchainSenderCallerContract is the compiled contract calling the interchain functionality
+ interchainSenderCallerContract evmtypes.CompiledContract
+ // contractAddr is the address of the smart contract that will be deployed
+ contractAddr common.Address
+ // senderCallerContractAddr is the address of the InterchainSenderCaller smart contract that will be deployed
+ senderCallerContractAddr common.Address
+ // execRevertedCheck defines the default log checking arguments which includes the
+ // standard revert message.
+ execRevertedCheck testutil.LogCheckArgs
+ // err is a basic error type
+ err error
+ )
+
+ BeforeEach(func() {
+ s.suiteIBCTesting = true
+ s.SetupTest()
+ s.setupAllocationsForTesting()
+
+ // Deploy InterchainSender contract
+ interchainSenderContract, err = contracts.LoadInterchainSenderContract()
+ Expect(err).To(BeNil(), "error while loading the interchain sender contract: %v", err)
+
+ contractAddr, err = DeployContract(
+ s.chainA.GetContext(),
+ s.app,
+ s.privKey,
+ gasPrice,
+ s.queryClientEVM,
+ interchainSenderContract,
+ )
+ Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err)
+
+ // NextBlock the smart contract
+ s.chainA.NextBlock()
+
+ // Deploy InterchainSenderCaller contract
+ interchainSenderCallerContract, err = contracts.LoadInterchainSenderCallerContract()
+ Expect(err).To(BeNil(), "error while loading the interchain sender contract: %v", err)
+
+ senderCallerContractAddr, err = DeployContract(
+ s.chainA.GetContext(),
+ s.app,
+ s.privKey,
+ gasPrice,
+ s.queryClientEVM,
+ interchainSenderCallerContract,
+ contractAddr,
+ )
+ Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err)
+
+ // NextBlock the smart contract
+ s.chainA.NextBlock()
+
+ // check contracts were correctly deployed
+ cAcc := s.app.EvmKeeper.GetAccount(s.chainA.GetContext(), contractAddr)
+ Expect(cAcc).ToNot(BeNil(), "contract account should exist")
+ Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract")
+
+ cAcc = s.app.EvmKeeper.GetAccount(s.chainA.GetContext(), senderCallerContractAddr)
+ Expect(cAcc).ToNot(BeNil(), "contract account should exist")
+ Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract")
+
+ // populate default call args
+ defaultCallArgs = contracts.CallArgs{
+ ContractAddr: contractAddr,
+ ContractABI: interchainSenderContract.ABI,
+ PrivKey: s.privKey,
+ GasPrice: gasPrice,
+ }
+ defaultApproveArgs = defaultCallArgs.
+ WithMethodName("testApprove").
+ WithArgs(defaultSingleAlloc)
+
+ // default log check arguments
+ defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.Events}
+ execRevertedCheck = defaultLogCheck.WithErrContains("execution reverted")
+ passCheck = defaultLogCheck.WithExpPass(true)
+ })
+
+ Context("approving methods", func() {
+ Context("with valid input", func() {
+ It("should approve one allocation", func() {
+ approvalCheck := passCheck.
+ WithExpEvents(authorization.EventTypeIBCTransferAuthorization)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultApproveArgs, approvalCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check GetAuthorizations is returning the record
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit).To(Equal(defaultCoins))
+ })
+ })
+ })
+
+ Context("revoke method", func() {
+ var defaultRevokeArgs contracts.CallArgs
+ BeforeEach(func() {
+ s.setTransferApprovalForContract(defaultApproveArgs)
+ defaultRevokeArgs = defaultCallArgs.WithMethodName(
+ "testRevoke",
+ )
+ })
+
+ It("should revoke authorization", func() {
+ // used to check if the corresponding event is emitted
+ revokeCheck := passCheck.
+ WithExpEvents(authorization.EventTypeIBCTransferAuthorization)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultRevokeArgs, revokeCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check authorization was removed
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(BeNil())
+ })
+ })
+
+ Context("update allowance methods", func() {
+ var (
+ amt *big.Int
+ allowanceChangeCheck testutil.LogCheckArgs
+ defaultChangeAllowanceArg contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ amt = big.NewInt(1e10)
+ allowanceChangeCheck = passCheck.
+ WithExpEvents(authorization.EventTypeIBCTransferAuthorization)
+ s.setTransferApprovalForContract(defaultApproveArgs)
+ defaultChangeAllowanceArg = defaultCallArgs.
+ WithMethodName("testIncreaseAllowance").
+ WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ utils.BaseDenom,
+ amt,
+ )
+ })
+
+ Context("Increase allowance", func() {
+ It("should increase allowance", func() { //nolint:dupl
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultChangeAllowanceArg, allowanceChangeCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check authorization spend limit increased
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit.AmountOf(utils.BaseDenom)).To(Equal(defaultCoins.AmountOf(utils.BaseDenom).Add(math.NewIntFromBigInt(amt))))
+ })
+ })
+
+ Context("Decrease allowance", func() {
+ var defaultDecreaseAllowanceArg contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultDecreaseAllowanceArg = defaultChangeAllowanceArg.
+ WithMethodName("testDecreaseAllowance")
+ })
+
+ It("should decrease allowance", func() { //nolint:dupl
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultDecreaseAllowanceArg, allowanceChangeCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ s.chainA.NextBlock()
+
+ // check authorization spend limit decreased
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations")
+ Expect(auths).To(HaveLen(1), "expected one authorization")
+ Expect(auths[0].MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := auths[0].(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit.AmountOf(utils.BaseDenom)).To(Equal(defaultCoins.AmountOf(utils.BaseDenom).Sub(math.NewIntFromBigInt(amt))))
+ })
+ })
+ })
+
+ Context("transfer method", func() {
+ var defaultTransferArgs contracts.CallArgs
+ BeforeEach(func() {
+ defaultTransferArgs = defaultCallArgs.WithMethodName(
+ "testTransferUserFunds",
+ )
+ })
+
+ Context("'aevmos' coin", func() {
+ Context("with authorization", func() {
+ BeforeEach(func() {
+ // set approval to transfer 'aevmos'
+ s.setTransferApprovalForContract(defaultApproveArgs)
+ })
+
+ It("should transfer funds", func() {
+ initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ transferArgs := defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.bondDenom,
+ defaultCmnCoins[0].Amount,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, transferArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ Expect(out[0]).To(Equal(uint64(1)))
+
+ s.chainA.NextBlock()
+
+ // The allowance is spent after the transfer thus the authorization is deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ Expect(authz).To(BeNil())
+
+ // check sent tokens were deducted from sending account
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(defaultCoins.AmountOf(s.bondDenom)).Sub(fees)))
+ })
+
+ Context("Calling the InterchainSender caller contract", func() {
+ It("should perform 2 transfers and revert 2 transfers", func() {
+ // setup approval to send transfer without memo
+ alloc := defaultSingleAlloc
+ alloc[0].AllowedPacketData = []string{""}
+ appArgs := defaultApproveArgs.WithArgs(alloc)
+ s.setTransferApprovalForContract(appArgs)
+ // Send some funds to the InterchainSender
+ // to perform internal transfers
+ initialContractBal := math.NewInt(1e18)
+ err := evmosutil.FundAccountWithBaseDenom(s.chainA.GetContext(), s.app.BankKeeper, contractAddr.Bytes(), initialContractBal.Int64())
+ Expect(err).To(BeNil(), "error while funding account")
+
+ // get initial balances
+ initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ // use half of the allowance when calling the fn
+ // because in total we'll try to send (2 * amt)
+ // with 4 IBC transfers (2 will succeed & 2 will revert)
+ amt := defaultCmnCoins[0].ToSDKType().Amount.QuoRaw(2)
+ args := contracts.CallArgs{
+ PrivKey: s.privKey,
+ ContractAddr: senderCallerContractAddr,
+ ContractABI: interchainSenderCallerContract.ABI,
+ MethodName: "transfersWithRevert",
+ GasPrice: gasPrice,
+ Args: []interface{}{
+ s.address,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.bondDenom,
+ amt.BigInt(),
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ },
+ }
+
+ logCheckArgs := passCheck.WithExpEvents([]string{ics20.EventTypeIBCTransfer, ics20.EventTypeIBCTransfer}...)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+ Expect(res.IsOK()).To(BeTrue())
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+
+ // the response should have two IBC transfer cosmos events (required for the relayer)
+ expIBCPackets := 2
+ ibcTransferCount := 0
+ sendPacketCount := 0
+ for _, event := range res.Events {
+ if event.Type == transfertypes.EventTypeTransfer {
+ ibcTransferCount++
+ }
+ if event.Type == channeltypes.EventTypeSendPacket {
+ sendPacketCount++
+ }
+ }
+ Expect(ibcTransferCount).To(Equal(expIBCPackets))
+ Expect(sendPacketCount).To(Equal(expIBCPackets))
+
+ // Check that 2 packages were created
+ pkgs := s.app.IBCKeeper.ChannelKeeper.GetAllPacketCommitments(s.chainA.GetContext())
+ Expect(pkgs).To(HaveLen(expIBCPackets))
+
+ // check that the escrow amount corresponds to the 2 transfers
+ coinsEscrowed := s.app.TransferKeeper.GetTotalEscrowForDenom(s.chainA.GetContext(), s.bondDenom)
+ Expect(coinsEscrowed.Amount).To(Equal(amt))
+
+ amtTransferredFromContract := math.NewInt(45)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(amt).Sub(fees).Add(amtTransferredFromContract)))
+
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), contractAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(initialContractBal.Sub(amtTransferredFromContract)))
+ })
+ })
+ })
+ })
+
+ Context("IBC coin", func() {
+ var (
+ ibcDenom = teststypes.UosmoIbcdenom
+ amt, _ = math.NewIntFromString("1000000000000000000000")
+ sentAmt, _ = math.NewIntFromString("100000000000000000000")
+ coinOsmo = sdk.NewCoin(ibcDenom, amt)
+ coins = sdk.NewCoins(coinOsmo)
+ initialOsmoBalance sdk.Coin
+ defaultTransferIbcCoinArgs contracts.CallArgs
+ )
+ BeforeEach(func() {
+ // set IBC denom trace
+ s.app.TransferKeeper.SetDenomTrace(
+ s.chainA.GetContext(),
+ transfertypes.DenomTrace{
+ Path: teststypes.UosmoDenomtrace.Path,
+ BaseDenom: teststypes.UosmoDenomtrace.BaseDenom,
+ },
+ )
+
+ // Mint IBC coins and add them to sender balance
+ err = s.app.BankKeeper.MintCoins(s.chainA.GetContext(), inflationtypes.ModuleName, coins)
+ s.Require().NoError(err)
+ err = s.app.BankKeeper.SendCoinsFromModuleToAccount(s.chainA.GetContext(), inflationtypes.ModuleName, s.chainA.SenderAccount.GetAddress(), coins)
+ s.Require().NoError(err)
+
+ initialOsmoBalance = s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), ibcDenom)
+ Expect(initialOsmoBalance.Amount).To(Equal(amt))
+
+ defaultTransferIbcCoinArgs = defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ ibcDenom,
+ sentAmt.BigInt(),
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+ })
+
+ Context("without authorization", func() {
+ It("should not transfer IBC coin", func() {
+ // initialEvmosBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultTransferIbcCoinArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // check only fees were deducted from sending account
+ // TODO: fees are not calculated correctly with this logic
+ // fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ // finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ // Expect(finalBalance.Amount).To(Equal(initialEvmosBalance.Amount.Sub(fees)))
+
+ // check IBC coins balance remains unchanged
+ finalOsmoBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), ibcDenom)
+ Expect(finalOsmoBalance.Amount).To(Equal(initialOsmoBalance.Amount))
+ })
+ })
+
+ Context("with authorization", func() {
+ BeforeEach(func() {
+ // create grant to allow spending the ibc coins
+ args := defaultApproveArgs.WithArgs([]cmn.ICS20Allocation{
+ {
+ SourcePort: ibctesting.TransferPort,
+ SourceChannel: s.transferPath.EndpointA.ChannelID,
+ SpendLimit: []cmn.Coin{{Denom: ibcDenom, Amount: amt.BigInt()}},
+ AllowList: []string{},
+ AllowedPacketData: []string{"memo"},
+ },
+ })
+ s.setTransferApprovalForContract(args)
+ })
+
+ It("should transfer IBC coin", func() {
+ initialEvmosBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultTransferIbcCoinArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ Expect(out[0]).To(Equal(uint64(1)))
+
+ s.chainA.NextBlock()
+
+ // Check the allowance spend limit is updated
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ Expect(authz).NotTo(BeNil(), "expected one authorization")
+ Expect(authz.MsgTypeURL()).To(Equal(ics20.TransferMsgURL))
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ Expect(transferAuthz.Allocations[0].SpendLimit.AmountOf(ibcDenom)).To(Equal(amt.Sub(sentAmt)))
+
+ // check only fees were deducted from sending account
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialEvmosBalance.Amount.Sub(fees)))
+
+ // check sent tokens were deducted from sending account
+ finalOsmoBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), ibcDenom)
+ Expect(finalOsmoBalance.Amount).To(Equal(initialOsmoBalance.Amount.Sub(sentAmt)))
+ })
+ })
+ })
+
+ Context("transfer ERC20", func() {
+ var (
+ // denom is the registered token pair denomination
+ denom string
+ // erc20Addr is the address of the ERC20 contract
+ erc20Addr common.Address
+ defaultTransferERC20Args contracts.CallArgs
+ // sentAmount is the amount of tokens to send for testing
+ sentAmount = big.NewInt(1000)
+ )
+
+ BeforeEach(func() {
+ erc20Addr = s.setupERC20ContractTests(sentAmount)
+
+ // Register ERC20 token pair to send via IBC
+ _, err := s.app.Erc20Keeper.RegisterERC20(s.chainA.GetContext(), erc20Addr)
+ Expect(err).To(BeNil(), "error while registering the token pair: %v", err)
+
+ denom = fmt.Sprintf("erc20/%s", erc20Addr.String())
+
+ defaultTransferERC20Args = defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ denom,
+ sentAmount,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+ })
+
+ Context("without authorization", func() {
+ tryERC20Transfer := func() {
+ // initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultTransferERC20Args, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // check only fees were deducted from sending account
+ // TODO: fees are not calculated correctly with this logic
+ // fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ // finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ // Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees)))
+
+ // check Erc20 balance remained unchanged by sent amount
+ balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(balance).To(Equal(sentAmount), "address does not have the expected amount of tokens")
+ }
+
+ It("should not transfer registered ERC-20 token", func() {
+ tryERC20Transfer()
+ })
+
+ Context("with authorization, but not for ERC20 token", func() {
+ BeforeEach(func() {
+ // create grant to allow spending the ibc coins
+ args := defaultApproveArgs.WithArgs([]cmn.ICS20Allocation{
+ {
+ SourcePort: ibctesting.TransferPort,
+ SourceChannel: s.transferPath.EndpointA.ChannelID,
+ SpendLimit: []cmn.Coin{{Denom: teststypes.UosmoIbcdenom, Amount: big.NewInt(10000)}},
+ AllowList: []string{},
+ },
+ })
+ s.setTransferApprovalForContract(args)
+ })
+
+ It("should not transfer registered ERC-20 token", func() {
+ tryERC20Transfer()
+ })
+ })
+ })
+
+ Context("with authorization", func() {
+ BeforeEach(func() {
+ // create grant to allow spending the erc20 tokens
+ args := defaultApproveArgs.WithArgs([]cmn.ICS20Allocation{
+ {
+ SourcePort: ibctesting.TransferPort,
+ SourceChannel: s.transferPath.EndpointA.ChannelID,
+ SpendLimit: []cmn.Coin{{Denom: denom, Amount: sentAmount}},
+ AllowList: []string{},
+ AllowedPacketData: []string{"memo"},
+ },
+ })
+ s.setTransferApprovalForContract(args)
+ })
+
+ It("should transfer registered ERC-20 token", func() {
+ initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultTransferERC20Args, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ Expect(out[0]).To(Equal(uint64(1)))
+
+ s.chainA.NextBlock()
+
+ // The allowance is spent after the transfer thus the authorization is deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ Expect(authz).To(BeNil())
+
+ // check only fees were deducted from sending account
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees)))
+
+ // check Erc20 balance was reduced by sent amount
+ balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(balance.Int64()).To(BeZero(), "address does not have the expected amount of tokens")
+ })
+ })
+ })
+ })
+
+ Context("transfer a contract's funds", func() {
+ var defaultTransferArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultTransferArgs = defaultCallArgs.WithMethodName(
+ "testTransferContractFunds",
+ )
+ })
+
+ Context("transfer 'aevmos", func() {
+ var defaultTransferEvmosArgs contracts.CallArgs
+ BeforeEach(func() {
+ // send some funds to the contract from which the funds will be sent
+ err = evmosutil.FundAccountWithBaseDenom(s.chainA.GetContext(), s.app.BankKeeper, contractAddr.Bytes(), amt)
+ Expect(err).To(BeNil())
+ senderInitialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), contractAddr.Bytes(), s.bondDenom)
+ Expect(senderInitialBalance.Amount).To(Equal(math.NewInt(amt)))
+
+ defaultTransferEvmosArgs = defaultTransferArgs.WithArgs(
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.bondDenom,
+ defaultCmnCoins[0].Amount,
+ s.chainB.SenderAccount.GetAddress().String(), // receiver
+ s.chainB.GetTimeoutHeight(),
+ uint64(0), // disable timeout timestamp
+ "memo",
+ )
+ })
+
+ Context("without authorization", func() {
+ It("should not transfer funds", func() {
+ initialBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), contractAddr.Bytes(), s.bondDenom)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultTransferEvmosArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // check sent tokens remained unchanged from sending account (contract)
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), contractAddr.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(initialBalance.Amount))
+ })
+ })
+
+ Context("with authorization", func() {
+ BeforeEach(func() {
+ // set approval to transfer 'aevmos'
+ s.setTransferApprovalForContract(defaultApproveArgs)
+ })
+
+ It("should transfer funds", func() {
+ initialSignerBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+
+ logCheckArgs := passCheck.WithExpEvents(ics20.EventTypeIBCTransfer)
+
+ res, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultTransferEvmosArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ out, err := s.precompile.Unpack(ics20.TransferMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking response: %v", err)
+ // check sequence in returned data
+ Expect(out[0]).To(Equal(uint64(1)))
+
+ s.chainA.NextBlock()
+
+ // The allowance is spent after the transfer thus the authorization is deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.chainA.GetContext(), contractAddr.Bytes(), s.address.Bytes(), ics20.TransferMsgURL)
+ Expect(authz).To(BeNil())
+
+ // check sent tokens were deducted from sending account
+ finalBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), contractAddr.Bytes(), s.bondDenom)
+ Expect(finalBalance.Amount).To(Equal(math.ZeroInt()))
+
+ // tx fees are paid by the tx signer
+ fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed)
+ finalSignerBalance := s.app.BankKeeper.GetBalance(s.chainA.GetContext(), s.address.Bytes(), s.bondDenom)
+ Expect(finalSignerBalance.Amount).To(Equal(initialSignerBalance.Amount.Sub(fees)))
+ })
+ })
+ })
+ })
+
+ // ===============================================
+ // QUERIES
+ // ===============================================
+
+ Context("allowance query method", func() {
+ var defaultAllowanceArgs contracts.CallArgs
+ BeforeEach(func() {
+ s.setTransferApprovalForContract(defaultApproveArgs)
+ defaultAllowanceArgs = defaultCallArgs.
+ WithMethodName("testAllowance").
+ WithArgs(contractAddr, s.address)
+ })
+
+ It("should return allocations", func() {
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, defaultAllowanceArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the precompile")
+
+ var out []cmn.ICS20Allocation
+ err = interchainSenderContract.ABI.UnpackIntoInterface(&out, "testAllowance", ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the output: %v", err)
+ Expect(out).To(HaveLen(1))
+ Expect(len(out)).To(Equal(len(defaultSingleAlloc)))
+ Expect(out[0].SourcePort).To(Equal(defaultSingleAlloc[0].SourcePort))
+ Expect(out[0].SourceChannel).To(Equal(defaultSingleAlloc[0].SourceChannel))
+ Expect(out[0].SpendLimit).To(Equal(defaultSingleAlloc[0].SpendLimit))
+ Expect(out[0].AllowList).To(HaveLen(0))
+ Expect(out[0].AllowedPacketData).To(HaveLen(1))
+ Expect(out[0].AllowedPacketData[0]).To(Equal("memo"))
+ })
+ })
+})
diff --git a/precompiles/ics20/query.go b/precompiles/ics20/query.go
new file mode 100644
index 00000000..0854fdcd
--- /dev/null
+++ b/precompiles/ics20/query.go
@@ -0,0 +1,148 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+import (
+ "fmt"
+ "strings"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // DenomTraceMethod defines the ABI method name for the ICS20 DenomTrace
+ // query.
+ DenomTraceMethod = "denomTrace"
+ // DenomTracesMethod defines the ABI method name for the ICS20 DenomTraces
+ // query.
+ DenomTracesMethod = "denomTraces"
+ // DenomHashMethod defines the ABI method name for the ICS20 DenomHash
+ // query.
+ DenomHashMethod = "denomHash"
+)
+
+// DenomTrace returns the requested denomination trace information.
+func (p Precompile) DenomTrace(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDenomTraceRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ res, err := p.transferKeeper.DenomTrace(sdk.WrapSDKContext(ctx), req)
+ if err != nil {
+ // if the trace does not exist, return empty array
+ if strings.Contains(err.Error(), ErrTraceNotFound) {
+ return method.Outputs.Pack(transfertypes.DenomTrace{})
+ }
+ return nil, err
+ }
+
+ return method.Outputs.Pack(*res.DenomTrace)
+}
+
+// DenomTraces returns the requested denomination traces information.
+func (p Precompile) DenomTraces(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDenomTracesRequest(method, args)
+ if err != nil {
+ return nil, err
+ }
+
+ res, err := p.transferKeeper.DenomTraces(sdk.WrapSDKContext(ctx), req)
+ if err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(res.DenomTraces, res.Pagination)
+}
+
+// DenomHash returns the denom hash (in hex format) of the denomination trace information.
+func (p Precompile) DenomHash(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDenomHashRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ res, err := p.transferKeeper.DenomHash(sdk.WrapSDKContext(ctx), req)
+ if err != nil {
+ // if the denom hash does not exist, return empty string
+ if strings.Contains(err.Error(), ErrTraceNotFound) {
+ return method.Outputs.Pack("")
+ }
+ return nil, err
+ }
+
+ return method.Outputs.Pack(res.Hash)
+}
+
+// Allowance returns the remaining allowance of for a combination of grantee - granter.
+// The grantee is the smart contract that was authorized by the granter to spend.
+func (p Precompile) Allowance(
+ ctx sdk.Context,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ // append here the msg type. Will always be the TransferMsg
+ // for this precompile
+ args = append(args, TransferMsgURL)
+
+ grantee, granter, msg, err := authorization.CheckAllowanceArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ msgAuthz, _ := p.AuthzKeeper.GetAuthorization(ctx, grantee.Bytes(), granter.Bytes(), msg)
+
+ if msgAuthz == nil {
+ // return empty array
+ return method.Outputs.Pack([]cmn.ICS20Allocation{})
+ }
+
+ transferAuthz, ok := msgAuthz.(*transfertypes.TransferAuthorization)
+ if !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "transfer authorization", &transfertypes.TransferAuthorization{}, transferAuthz)
+ }
+
+ // need to convert to cmn.ICS20Allocation (uses big.Int)
+ // because ibc ICS20Allocation has sdkmath.Int
+ allocs := make([]cmn.ICS20Allocation, len(transferAuthz.Allocations))
+ for i, a := range transferAuthz.Allocations {
+ spendLimit := make([]cmn.Coin, len(a.SpendLimit))
+ for j, c := range a.SpendLimit {
+ spendLimit[j] = cmn.Coin{
+ Denom: c.Denom,
+ Amount: c.Amount.BigInt(),
+ }
+ }
+
+ allocs[i] = cmn.ICS20Allocation{
+ SourcePort: a.SourcePort,
+ SourceChannel: a.SourceChannel,
+ SpendLimit: spendLimit,
+ AllowList: a.AllowList,
+ AllowedPacketData: a.AllowedPacketData,
+ }
+ }
+
+ return method.Outputs.Pack(allocs)
+}
diff --git a/precompiles/ics20/query_test.go b/precompiles/ics20/query_test.go
new file mode 100644
index 00000000..b99f900f
--- /dev/null
+++ b/precompiles/ics20/query_test.go
@@ -0,0 +1,398 @@
+package ics20_test
+
+import (
+ "fmt"
+
+ "github.com/cosmos/cosmos-sdk/types/query"
+ "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/ics20"
+ "github.com/evmos/evmos/v19/utils"
+)
+
+func (s *PrecompileTestSuite) TestDenomTrace() {
+ var expTrace types.DenomTrace
+ method := s.precompile.Methods[ics20.DenomTraceMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty args",
+ func() []interface{} { return []interface{}{} },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ "invalid input arguments",
+ },
+ {
+ "fail - invalid denom trace",
+ func() []interface{} {
+ return []interface{}{"invalid denom trace"}
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ "invalid denom trace",
+ },
+ {
+ "success - denom trace not found, return empty struct",
+ func() []interface{} {
+ expTrace.Path = "transfer/channelToA/transfer/channelToB"
+ expTrace.BaseDenom = utils.BaseDenom
+ return []interface{}{
+ expTrace.IBCDenom(),
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ var out ics20.DenomTraceResponse
+ err := s.precompile.UnpackIntoInterface(&out, ics20.DenomTraceMethod, data)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal("", out.DenomTrace.BaseDenom)
+ s.Require().Equal("", out.DenomTrace.Path)
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "success - denom trace",
+ func() []interface{} {
+ expTrace.Path = "transfer/channelToA/transfer/channelToB"
+ expTrace.BaseDenom = utils.BaseDenom
+ s.app.TransferKeeper.SetDenomTrace(s.ctx, expTrace)
+ return []interface{}{
+ expTrace.IBCDenom(),
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ var out ics20.DenomTraceResponse
+ err := s.precompile.UnpackIntoInterface(&out, ics20.DenomTraceMethod, data)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(expTrace.Path, out.DenomTrace.Path)
+ s.Require().Equal(expTrace.BaseDenom, out.DenomTrace.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ contract := s.NewPrecompileContract(tc.gas)
+ args := tc.malleate()
+ bz, err := s.precompile.DenomTrace(s.ctx, contract, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDenomTraces() {
+ expTraces := types.Traces(nil)
+ method := s.precompile.Methods[ics20.DenomTracesMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty args",
+ func() []interface{} { return []interface{}{} },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ "invalid number of arguments",
+ },
+ {
+ "success - gets denom traces",
+ func() []interface{} {
+ expTraces = append(expTraces, types.DenomTrace{Path: "", BaseDenom: utils.BaseDenom})
+ expTraces = append(expTraces, types.DenomTrace{Path: "transfer/channelToA/transfer/channelToB", BaseDenom: utils.BaseDenom})
+ expTraces = append(expTraces, types.DenomTrace{Path: "transfer/channelToB", BaseDenom: utils.BaseDenom})
+
+ for _, trace := range expTraces {
+ s.app.TransferKeeper.SetDenomTrace(s.ctx, trace)
+ }
+ return []interface{}{
+ query.PageRequest{
+ Limit: 3,
+ CountTotal: true,
+ },
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ var denomTraces ics20.DenomTracesResponse
+ err := s.precompile.UnpackIntoInterface(&denomTraces, ics20.DenomTracesMethod, data)
+ s.Require().Equal(denomTraces.PageResponse.Total, uint64(3))
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(3, len(denomTraces.DenomTraces))
+ for i, trace := range denomTraces.DenomTraces {
+ s.Require().Equal(expTraces[i].Path, trace.Path)
+ }
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ contract := s.NewPrecompileContract(tc.gas)
+ args := tc.malleate()
+ bz, err := s.precompile.DenomTraces(s.ctx, contract, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDenomHash() {
+ reqTrace := types.DenomTrace{
+ Path: "transfer/channelToA/transfer/channelToB",
+ BaseDenom: utils.BaseDenom,
+ }
+ method := s.precompile.Methods[ics20.DenomHashMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "success - trace not found, returns empty string",
+ func() []interface{} { return []interface{}{"transfer/channelToB/transfer/channelToA"} },
+ func(data []byte, _ []interface{}) {
+ var hash string
+ err := s.precompile.UnpackIntoInterface(&hash, ics20.DenomHashMethod, data)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal("", hash)
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "success - get the hash of a denom trace",
+ func() []interface{} {
+ s.app.TransferKeeper.SetDenomTrace(s.ctx, reqTrace)
+ return []interface{}{
+ reqTrace.GetFullDenomPath(),
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ var hash string
+ err := s.precompile.UnpackIntoInterface(&hash, ics20.DenomHashMethod, data)
+ s.Require().NoError(err, "failed to unpack output", err)
+ s.Require().Equal(reqTrace.Hash().String(), hash)
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ contract := s.NewPrecompileContract(tc.gas)
+ args := tc.malleate()
+
+ bz, err := s.precompile.DenomHash(s.ctx, contract, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestAllowance() {
+ var (
+ path = NewTransferPath(s.chainA, s.chainB)
+ path2 = NewTransferPath(s.chainA, s.chainB)
+ paths = []*ibctesting.Path{path, path2}
+ method = s.precompile.Methods[authorization.AllowanceMethod]
+ )
+ // set channel, otherwise is "" and throws error
+ path.EndpointA.ChannelID = "channel-0"
+ path2.EndpointA.ChannelID = "channel-1"
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 1),
+ },
+ {
+ "success - no allowance == empty array",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ s.differentAddr,
+ }
+ },
+ func(bz []byte) {
+ var allocations []cmn.ICS20Allocation
+ err := s.precompile.UnpackIntoInterface(&allocations, authorization.AllowanceMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(allocations, 0)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - auth with one allocation",
+ func() []interface{} {
+ err := s.NewTransferAuthorization(
+ s.ctx,
+ s.app,
+ s.differentAddr,
+ s.address,
+ path,
+ defaultCoins,
+ []string{s.chainB.SenderAccount.GetAddress().String()},
+ []string{"memo"},
+ )
+ s.Require().NoError(err)
+
+ return []interface{}{
+ s.differentAddr,
+ s.address,
+ }
+ },
+ func(bz []byte) {
+ expAllocs := []cmn.ICS20Allocation{
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: defaultCmnCoins,
+ AllowList: []string{s.chainB.SenderAccount.GetAddress().String()},
+ AllowedPacketData: []string{"memo"},
+ },
+ }
+
+ var allocations []cmn.ICS20Allocation
+ err := s.precompile.UnpackIntoInterface(&allocations, authorization.AllowanceMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+
+ s.Require().Equal(expAllocs, allocations)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - auth with multiple allocations",
+ func() []interface{} {
+ allocs := make([]types.Allocation, len(paths))
+ for i, p := range paths {
+ allocs[i] = types.Allocation{
+ SourcePort: p.EndpointA.ChannelConfig.PortID,
+ SourceChannel: p.EndpointA.ChannelID,
+ SpendLimit: mutliSpendLimit,
+ AllowList: []string{s.chainB.SenderAccount.GetAddress().String()},
+ AllowedPacketData: []string{"memo"},
+ }
+ }
+
+ err := s.NewTransferAuthorizationWithAllocations(
+ s.ctx,
+ s.app,
+ s.differentAddr,
+ s.address,
+ allocs,
+ )
+ s.Require().NoError(err)
+
+ return []interface{}{
+ s.differentAddr,
+ s.address,
+ }
+ },
+ func(bz []byte) {
+ expAllocs := make([]cmn.ICS20Allocation, len(paths))
+ for i, p := range paths {
+ expAllocs[i] = cmn.ICS20Allocation{
+ SourcePort: p.EndpointA.ChannelConfig.PortID,
+ SourceChannel: p.EndpointA.ChannelID,
+ SpendLimit: mutliCmnCoins,
+ AllowList: []string{s.chainB.SenderAccount.GetAddress().String()},
+ AllowedPacketData: []string{"memo"},
+ }
+ }
+
+ var allocations []cmn.ICS20Allocation
+ err := s.precompile.UnpackIntoInterface(&allocations, authorization.AllowanceMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+
+ s.Require().Equal(expAllocs, allocations)
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ args := tc.malleate()
+ bz, err := s.precompile.Allowance(s.ctx, &method, args)
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
diff --git a/precompiles/ics20/setup_test.go b/precompiles/ics20/setup_test.go
new file mode 100644
index 00000000..76af00b4
--- /dev/null
+++ b/precompiles/ics20/setup_test.go
@@ -0,0 +1,72 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package ics20_test
+
+import (
+ "testing"
+ "time"
+
+ tmtypes "github.com/cometbft/cometbft/types"
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ evmosapp "github.com/evmos/evmos/v19/app"
+ evmosibc "github.com/evmos/evmos/v19/ibc/testing"
+ "github.com/evmos/evmos/v19/precompiles/ics20"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "github.com/stretchr/testify/suite"
+)
+
+var s *PrecompileTestSuite
+
+type PrecompileTestSuite struct {
+ suite.Suite
+
+ ctx sdk.Context
+ app *evmosapp.Evmos
+ address common.Address
+ differentAddr common.Address
+ validators []stakingtypes.Validator
+ valSet *tmtypes.ValidatorSet
+ ethSigner ethtypes.Signer
+ privKey cryptotypes.PrivKey
+ signer keyring.Signer
+ bondDenom string
+
+ precompile *ics20.Precompile
+ stateDB *statedb.StateDB
+
+ coordinator *ibctesting.Coordinator
+ chainA *ibctesting.TestChain
+ chainB *ibctesting.TestChain
+ transferPath *evmosibc.Path
+ queryClientEVM evmtypes.QueryClient
+
+ defaultExpirationDuration time.Time
+
+ suiteIBCTesting bool
+}
+
+func TestPrecompileTestSuite(t *testing.T) {
+ s = new(PrecompileTestSuite)
+ suite.Run(t, s)
+
+ // Run Ginkgo integration tests
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "ICS20 Precompile Suite")
+}
+
+func (s *PrecompileTestSuite) SetupTest() {
+ s.DoSetupTest()
+}
diff --git a/precompiles/ics20/tx.go b/precompiles/ics20/tx.go
new file mode 100644
index 00000000..4f9a21b2
--- /dev/null
+++ b/precompiles/ics20/tx.go
@@ -0,0 +1,103 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+import (
+ "fmt"
+
+ errorsmod "cosmossdk.io/errors"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/utils"
+)
+
+const (
+ // TransferMethod defines the ABI method name for the ICS20 Transfer
+ // transaction.
+ TransferMethod = "transfer"
+)
+
+// Transfer implements the ICS20 transfer transactions.
+func (p *Precompile) Transfer(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, sender, err := NewMsgTransfer(method, args)
+ if err != nil {
+ return nil, err
+ }
+
+ // check if channel exists and is open
+ if !p.channelKeeper.HasChannel(ctx, msg.SourcePort, msg.SourceChannel) {
+ return nil, errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", msg.SourcePort, msg.SourceChannel)
+ }
+
+ // isCallerSender is true when the contract caller is the same as the sender
+ isCallerSender := contract.CallerAddress == sender
+
+ // If the contract caller is not the same as the sender, the sender must be the origin
+ if !isCallerSender && origin != sender {
+ return nil, fmt.Errorf(ErrDifferentOriginFromSender, origin.String(), sender.String())
+ }
+
+ // no need to have authorization when the contract caller is the same as origin (owner of funds)
+ // and the sender is the origin
+ resp, expiration, err := CheckAndAcceptAuthorizationIfNeeded(ctx, contract, origin, p.AuthzKeeper, msg)
+ if err != nil {
+ return nil, err
+ }
+
+ res, err := p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), msg)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := UpdateGrantIfNeeded(ctx, contract, p.AuthzKeeper, origin, expiration, resp); err != nil {
+ return nil, err
+ }
+
+ if contract.CallerAddress != origin && msg.Token.Denom == utils.BaseDenom {
+ // escrow address is also changed on this tx, and it is not a module account
+ // so we need to account for this on the UpdateDirties
+ escrowAccAddress := transfertypes.GetEscrowAddress(msg.SourcePort, msg.SourceChannel)
+ escrowHexAddr := common.BytesToAddress(escrowAccAddress)
+ // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB
+ // when calling the precompile from another smart contract.
+ // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state.
+ amt := msg.Token.Amount.BigInt()
+ p.SetBalanceChangeEntries(
+ cmn.NewBalanceChangeEntry(sender, amt, cmn.Sub),
+ cmn.NewBalanceChangeEntry(escrowHexAddr, amt, cmn.Add),
+ )
+ }
+
+ if err = EmitIBCTransferEvent(
+ ctx,
+ stateDB,
+ p.ABI.Events[EventTypeIBCTransfer],
+ p.Address(),
+ sender,
+ msg.Receiver,
+ msg.SourcePort,
+ msg.SourceChannel,
+ msg.Token,
+ msg.Memo,
+ ); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(res.Sequence)
+}
diff --git a/precompiles/ics20/tx_test.go b/precompiles/ics20/tx_test.go
new file mode 100644
index 00000000..5719e10d
--- /dev/null
+++ b/precompiles/ics20/tx_test.go
@@ -0,0 +1,392 @@
+package ics20_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/ics20"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ testutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+var (
+ differentAddress = testutiltx.GenerateAddress()
+ amt int64 = 1000000000000000000
+)
+
+func (s *PrecompileTestSuite) TestTransfer() {
+ callingContractAddr := differentAddress
+ method := s.precompile.Methods[ics20.TransferMethod]
+ testCases := []struct {
+ name string
+ malleate func(sender, receiver sdk.AccAddress) []interface{}
+ postCheck func(sender, receiver sdk.AccAddress, data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty args",
+ func(sdk.AccAddress, sdk.AccAddress) []interface{} {
+ return []interface{}{}
+ },
+ func(sdk.AccAddress, sdk.AccAddress, []byte, []interface{}) {
+ },
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 9, 0),
+ },
+ {
+ "fail - no transfer authorization",
+ func(sdk.AccAddress, sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(s.chainA.SenderAccount.GetAddress().Bytes()),
+ s.chainB.SenderAccount.GetAddress().String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sdk.AccAddress, sdk.AccAddress, []byte, []interface{}) {
+ },
+ 200000,
+ true,
+ "does not exist",
+ },
+ {
+ "fail - channel does not exist",
+ func(sdk.AccAddress, sdk.AccAddress) []interface{} {
+ return []interface{}{
+ "port",
+ "channel-01",
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(s.chainA.SenderAccount.GetAddress().Bytes()),
+ s.chainB.SenderAccount.GetAddress().String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sdk.AccAddress, sdk.AccAddress, []byte, []interface{}) {
+ },
+ 200000,
+ true,
+ channeltypes.ErrChannelNotFound.Error(),
+ },
+ {
+ "fail - non authorized denom",
+ func(sender, _ sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, callingContractAddr, common.BytesToAddress(sender), path, defaultCoins, nil, []string{"memo"})
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ "uatom",
+ big.NewInt(1e18),
+ common.BytesToAddress(s.chainA.SenderAccount.GetAddress().Bytes()),
+ s.chainB.SenderAccount.GetAddress().String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sdk.AccAddress, sdk.AccAddress, []byte, []interface{}) {
+ },
+ 200000,
+ true,
+ "requested amount is more than spend limit",
+ },
+ {
+ "fail - allowance is less than transfer amount",
+ func(sender, _ sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, callingContractAddr, common.BytesToAddress(sender), path, defaultCoins, nil, []string{"memo"})
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(2e18),
+ common.BytesToAddress(s.chainA.SenderAccount.GetAddress().Bytes()),
+ s.chainB.SenderAccount.GetAddress().String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sdk.AccAddress, sdk.AccAddress, []byte, []interface{}) {
+ },
+ 200000,
+ true,
+ "requested amount is more than spend limit",
+ },
+ {
+ "fail - transfer 1 Evmos from chainA to chainB from somebody else's account",
+ func(sender, receiver sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, common.BytesToAddress(sender), common.BytesToAddress(sender), path, defaultCoins, nil, []string{"memo"})
+ s.Require().NoError(err)
+ // fund another user's account
+ err = evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, differentAddress.Bytes(), amt)
+ s.Require().NoError(err)
+
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(amt),
+ common.BytesToAddress(differentAddress.Bytes()),
+ receiver.String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sender, _ sdk.AccAddress, _ []byte, _ []interface{}) {
+ // The allowance is spent after the transfer thus the authorization is deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, sender, sender, ics20.TransferMsgURL)
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, defaultCoins)
+
+ // the balance on other user's account should remain unchanged
+ balance := s.app.BankKeeper.GetBalance(s.ctx, differentAddress.Bytes(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount, math.NewInt(amt))
+ s.Require().Equal(balance.Denom, utils.BaseDenom)
+ },
+ 200000,
+ true,
+ "does not exist",
+ },
+ {
+ "fail - transfer with memo string, but authorization does not allows it",
+ func(sender, receiver sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, callingContractAddr, common.BytesToAddress(sender), path, defaultCoins, nil, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(sender.Bytes()),
+ receiver.String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sender, _ sdk.AccAddress, _ []byte, _ []interface{}) {
+ // Check allowance remains unchanged
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, callingContractAddr.Bytes(), sender, ics20.TransferMsgURL)
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, defaultCoins)
+ },
+ 200000,
+ true,
+ "memo must be empty because allowed packet data in allocation is empty",
+ },
+ {
+ "pass - transfer 1 Evmos from chainA to chainB and spend the entire allowance",
+ func(sender, receiver sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, callingContractAddr, common.BytesToAddress(sender), path, defaultCoins, nil, []string{"memo"})
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(sender.Bytes()),
+ receiver.String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sender, _ sdk.AccAddress, _ []byte, _ []interface{}) {
+ // Check allowance was deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, callingContractAddr.Bytes(), sender, ics20.TransferMsgURL)
+ s.Require().Nil(authz)
+
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.chainA.SenderAccount.GetAddress(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount, math.NewInt(4e18))
+ s.Require().Equal(balance.Denom, utils.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ //nolint:dupl
+ {
+ "pass - transfer 1 Evmos from chainA to chainB and don't change the unlimited spending limit",
+ func(sender, receiver sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, callingContractAddr, common.BytesToAddress(sender), path, maxUint256Coins, nil, []string{"memo"})
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(sender.Bytes()),
+ receiver.String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sender, _ sdk.AccAddress, _ []byte, _ []interface{}) {
+ // The allowance is spent after the transfer thus the authorization is deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, callingContractAddr.Bytes(), sender, ics20.TransferMsgURL)
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, maxUint256Coins)
+
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.chainA.SenderAccount.GetAddress(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount, math.NewInt(4e18))
+ s.Require().Equal(balance.Denom, utils.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ //nolint:dupl
+ {
+ "pass - transfer 1 Evmos from chainA to chainB and only change 1 spend limit",
+ func(sender, receiver sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ err := s.NewTransferAuthorization(s.ctx, s.app, callingContractAddr, common.BytesToAddress(sender), path, mutliSpendLimit, nil, []string{"memo"})
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(sender.Bytes()),
+ receiver.String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sender, _ sdk.AccAddress, _ []byte, _ []interface{}) {
+ // The allowance is spent after the transfer thus the authorization is deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, callingContractAddr.Bytes(), sender, ics20.TransferMsgURL)
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, atomCoins)
+
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.chainA.SenderAccount.GetAddress(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount, math.NewInt(4e18))
+ s.Require().Equal(balance.Denom, utils.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "pass - transfer 1 Evmos from chainA to chainB and only change 1 spend limit for the associated allocation",
+ func(sender, receiver sdk.AccAddress) []interface{} {
+ path := NewTransferPath(s.chainA, s.chainB)
+ s.coordinator.Setup(path)
+ allocations := []transfertypes.Allocation{
+ {
+ SourcePort: "port-01",
+ SourceChannel: "channel-03",
+ SpendLimit: atomCoins,
+ AllowList: nil,
+ AllowedPacketData: []string{"*"}, // allow any memo string
+
+ },
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: defaultCoins,
+ AllowList: nil,
+ AllowedPacketData: []string{"*"}, // allow any memo string
+ },
+ }
+ err := s.NewTransferAuthorizationWithAllocations(s.ctx, s.app, callingContractAddr, common.BytesToAddress(sender), allocations)
+ s.Require().NoError(err)
+ return []interface{}{
+ path.EndpointA.ChannelConfig.PortID,
+ path.EndpointA.ChannelID,
+ utils.BaseDenom,
+ big.NewInt(1e18),
+ common.BytesToAddress(sender.Bytes()),
+ receiver.String(),
+ s.chainB.GetTimeoutHeight(),
+ uint64(0),
+ "memo",
+ }
+ },
+ func(sender, _ sdk.AccAddress, _ []byte, _ []interface{}) {
+ // The allowance is spent after the transfer thus the authorization is deleted
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, callingContractAddr.Bytes(), sender, ics20.TransferMsgURL)
+ transferAuthz := authz.(*transfertypes.TransferAuthorization)
+ s.Require().Equal(transferAuthz.Allocations[0].SpendLimit, atomCoins)
+
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.chainA.SenderAccount.GetAddress(), utils.BaseDenom)
+ s.Require().Equal(balance.Amount, math.NewInt(4e18))
+ s.Require().Equal(balance.Denom, utils.BaseDenom)
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ sender := s.chainA.SenderAccount.GetAddress()
+ receiver := s.chainB.SenderAccount.GetAddress()
+
+ contract := vm.NewContract(vm.AccountRef(common.BytesToAddress(sender)), s.precompile, big.NewInt(0), tc.gas)
+
+ s.ctx = s.ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
+ initialGas := s.ctx.GasMeter().GasConsumed()
+ s.Require().Zero(initialGas)
+
+ args := tc.malleate(sender, receiver)
+
+ // set the caller address to be another address (so we can test the authorization logic)
+ contract.CallerAddress = callingContractAddr
+ bz, err := s.precompile.Transfer(s.ctx, common.BytesToAddress(sender), contract, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ if tc.postCheck != nil {
+ tc.postCheck(sender, receiver, bz, args)
+ }
+ } else {
+ s.Require().NoError(err)
+ s.Require().Equal(bz, cmn.TrueValue)
+ tc.postCheck(sender, receiver, bz, args)
+ }
+ })
+ }
+}
diff --git a/precompiles/ics20/types.go b/precompiles/ics20/types.go
new file mode 100644
index 00000000..169065f1
--- /dev/null
+++ b/precompiles/ics20/types.go
@@ -0,0 +1,423 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ics20
+
+import (
+ "fmt"
+ "math/big"
+ "time"
+
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+const (
+ // DefaultRevisionNumber is the default value used to not set a timeout revision number
+ DefaultRevisionNumber = 0
+
+ // DefaultRevisionHeight is the default value used to not set a timeout revision height
+ DefaultRevisionHeight = 0
+
+ // DefaultTimeoutMinutes is the default value in minutes used to set a timeout timestamp
+ DefaultTimeoutMinutes = 10
+)
+
+// DefaultTimeoutHeight is the default value used to set a timeout height
+var DefaultTimeoutHeight = clienttypes.NewHeight(DefaultRevisionNumber, DefaultRevisionHeight)
+
+// EventIBCTransfer is the event type emitted when a transfer is executed.
+type EventIBCTransfer struct {
+ Sender common.Address
+ Receiver common.Hash
+ SourcePort string
+ SourceChannel string
+ Denom string
+ Amount *big.Int
+ Memo string
+}
+
+// EventTransferAuthorization is the event type emitted when a transfer authorization is created.
+type EventTransferAuthorization struct {
+ Grantee common.Address
+ Granter common.Address
+ Allocations []cmn.ICS20Allocation
+}
+
+// DenomTraceResponse defines the data for the denom trace response.
+type DenomTraceResponse struct {
+ DenomTrace transfertypes.DenomTrace
+}
+
+// PageRequest defines the data for the page request.
+type PageRequest struct {
+ PageRequest query.PageRequest
+}
+
+// DenomTracesResponse defines the data for the denom traces response.
+type DenomTracesResponse struct {
+ DenomTraces []transfertypes.DenomTrace
+ PageResponse query.PageResponse
+}
+
+// height is a struct used to parse the TimeoutHeight parameter
+// used as input in the transfer method
+type height struct {
+ TimeoutHeight clienttypes.Height
+}
+
+// allocs is a struct used to parse the Allocations parameter
+// used as input in the transfer authorization method
+type allocs struct {
+ Allocations []cmn.ICS20Allocation
+}
+
+// NewTransferAuthorization returns a new transfer authorization authz type from the given arguments.
+func NewTransferAuthorization(method *abi.Method, args []interface{}) (common.Address, *transfertypes.TransferAuthorization, error) {
+ grantee, allocations, err := checkTransferAuthzArgs(method, args)
+ if err != nil {
+ return common.Address{}, nil, err
+ }
+
+ transferAuthz := &transfertypes.TransferAuthorization{Allocations: allocations}
+ if err = transferAuthz.ValidateBasic(); err != nil {
+ return common.Address{}, nil, err
+ }
+
+ return grantee, transferAuthz, nil
+}
+
+// NewMsgTransfer returns a new transfer message from the given arguments.
+func NewMsgTransfer(method *abi.Method, args []interface{}) (*transfertypes.MsgTransfer, common.Address, error) {
+ if len(args) != 9 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 9, len(args))
+ }
+
+ sourcePort, ok := args[0].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(ErrInvalidSourcePort)
+ }
+
+ sourceChannel, ok := args[1].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(ErrInvalidSourceChannel)
+ }
+
+ denom, ok := args[2].(string)
+ if !ok {
+ return nil, common.Address{}, errorsmod.Wrapf(transfertypes.ErrInvalidDenomForTransfer, cmn.ErrInvalidDenom, args[2])
+ }
+
+ amount, ok := args[3].(*big.Int)
+ if !ok || amount == nil {
+ return nil, common.Address{}, errorsmod.Wrapf(transfertypes.ErrInvalidAmount, cmn.ErrInvalidAmount, args[3])
+ }
+
+ sender, ok := args[4].(common.Address)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(ErrInvalidSender, args[4])
+ }
+
+ receiver, ok := args[5].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(ErrInvalidReceiver, args[5])
+ }
+
+ var input height
+ heightArg := abi.Arguments{method.Inputs[6]}
+ if err := heightArg.Copy(&input, []interface{}{args[6]}); err != nil {
+ return nil, common.Address{}, fmt.Errorf("error while unpacking args to TransferInput struct: %s", err)
+ }
+
+ timeoutTimestamp, ok := args[7].(uint64)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(ErrInvalidTimeoutTimestamp, args[7])
+ }
+
+ memo, ok := args[8].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(ErrInvalidMemo, args[8])
+ }
+
+ // Use instance to prevent errors on denom or amount
+ token := sdk.Coin{
+ Denom: denom,
+ Amount: math.NewIntFromBigInt(amount),
+ }
+
+ msg, err := CreateAndValidateMsgTransfer(sourcePort, sourceChannel, token, sdk.AccAddress(sender.Bytes()).String(), receiver, input.TimeoutHeight, timeoutTimestamp, memo)
+ if err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, sender, nil
+}
+
+// CreateAndValidateMsgTransfer creates a new MsgTransfer message and run validate basic.
+func CreateAndValidateMsgTransfer(
+ sourcePort, sourceChannel string,
+ coin sdk.Coin, senderAddress, receiverAddress string,
+ timeoutHeight clienttypes.Height,
+ timeoutTimestamp uint64,
+ memo string,
+) (*transfertypes.MsgTransfer, error) {
+ msg := transfertypes.NewMsgTransfer(
+ sourcePort,
+ sourceChannel,
+ coin,
+ senderAddress,
+ receiverAddress,
+ timeoutHeight,
+ timeoutTimestamp,
+ memo,
+ )
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, err
+ }
+
+ return msg, nil
+}
+
+// NewDenomTraceRequest returns a new denom trace request from the given arguments.
+func NewDenomTraceRequest(args []interface{}) (*transfertypes.QueryDenomTraceRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf("invalid input arguments. Expected 1, got %d", len(args))
+ }
+
+ hash, ok := args[0].(string)
+ if !ok {
+ return nil, fmt.Errorf(ErrInvalidHash, args[0])
+ }
+
+ req := &transfertypes.QueryDenomTraceRequest{
+ Hash: hash,
+ }
+
+ return req, nil
+}
+
+// NewDenomTracesRequest returns a new denom traces request from the given arguments.
+func NewDenomTracesRequest(method *abi.Method, args []interface{}) (*transfertypes.QueryDenomTracesRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ var pageRequest PageRequest
+ if err := method.Inputs.Copy(&pageRequest, args); err != nil {
+ return nil, fmt.Errorf("error while unpacking args to PageRequest: %w", err)
+ }
+
+ req := &transfertypes.QueryDenomTracesRequest{
+ Pagination: &pageRequest.PageRequest,
+ }
+
+ return req, nil
+}
+
+// NewDenomHashRequest returns a new denom hash request from the given arguments.
+func NewDenomHashRequest(args []interface{}) (*transfertypes.QueryDenomHashRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf("invalid input arguments. Expected 1, got %d", len(args))
+ }
+
+ trace, ok := args[0].(string)
+ if !ok {
+ return nil, fmt.Errorf("invalid denom trace")
+ }
+
+ req := &transfertypes.QueryDenomHashRequest{
+ Trace: trace,
+ }
+
+ return req, nil
+}
+
+// checkRevokeArgs checks if the given arguments are valid for the Revoke tx.
+func checkRevokeArgs(args []interface{}) (common.Address, error) {
+ if len(args) != 1 {
+ return common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ grantee, ok := args[0].(common.Address)
+ if !ok || grantee == (common.Address{}) {
+ return common.Address{}, fmt.Errorf(authorization.ErrInvalidGrantee, args[0])
+ }
+
+ return grantee, nil
+}
+
+// checkAllowanceArgs checks if the given arguments are valid for the DecreaseAllowance and IncreaseAllowance txs.
+func checkAllowanceArgs(args []interface{}) (common.Address, string, string, string, *big.Int, error) {
+ if len(args) != 5 {
+ return common.Address{}, "", "", "", nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 5, len(args))
+ }
+
+ grantee, ok := args[0].(common.Address)
+ if !ok || grantee == (common.Address{}) {
+ return common.Address{}, "", "", "", nil, fmt.Errorf(authorization.ErrInvalidGrantee, args[0])
+ }
+
+ sourcePort, ok := args[1].(string)
+ if !ok {
+ return common.Address{}, "", "", "", nil, fmt.Errorf(ErrInvalidSourcePort)
+ }
+
+ sourceChannel, ok := args[2].(string)
+ if !ok {
+ return common.Address{}, "", "", "", nil, fmt.Errorf(ErrInvalidSourceChannel)
+ }
+
+ denom, ok := args[3].(string)
+ if !ok {
+ return common.Address{}, "", "", "", nil, errorsmod.Wrapf(transfertypes.ErrInvalidDenomForTransfer, cmn.ErrInvalidDenom, args[2])
+ }
+
+ amount, ok := args[4].(*big.Int)
+ if !ok || amount == nil {
+ return common.Address{}, "", "", "", nil, errorsmod.Wrapf(transfertypes.ErrInvalidAmount, cmn.ErrInvalidAmount, args[3])
+ }
+
+ return grantee, sourcePort, sourceChannel, denom, amount, nil
+}
+
+// checkTransferArgs checks if the given arguments are valid for the Transfer Approve tx.
+func checkTransferAuthzArgs(method *abi.Method, args []interface{}) (common.Address, []transfertypes.Allocation, error) {
+ if len(args) != 2 {
+ return common.Address{}, nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ grantee, ok := args[0].(common.Address)
+ if !ok {
+ return common.Address{}, nil, fmt.Errorf(authorization.ErrInvalidGrantee, args[0])
+ }
+
+ var input allocs
+ allocArg := abi.Arguments{method.Inputs[1]}
+ if err := allocArg.Copy(&input, []interface{}{args[1]}); err != nil {
+ return common.Address{}, nil, fmt.Errorf("error while unpacking args to AuthInput struct: %s", err)
+ }
+
+ allocations := make([]transfertypes.Allocation, len(input.Allocations))
+ for i, a := range input.Allocations {
+ spendLimit := make(sdk.Coins, len(a.SpendLimit))
+ for is, sl := range a.SpendLimit {
+ spendLimit[is] = sdk.Coin{
+ Amount: math.NewIntFromBigInt(sl.Amount),
+ Denom: sl.Denom,
+ }
+ }
+
+ allocations[i] = transfertypes.Allocation{
+ SourcePort: a.SourcePort,
+ SourceChannel: a.SourceChannel,
+ SpendLimit: spendLimit,
+ AllowList: a.AllowList,
+ AllowedPacketData: a.AllowedPacketData,
+ }
+ }
+
+ return grantee, allocations, nil
+}
+
+// CheckAllocationExists checks if the given authorization allocation matches the given arguments.
+func checkAllocationExists(allocations []transfertypes.Allocation, sourcePort, sourceChannel, denom string) (spendLimit sdk.Coin, allocationIdx int, err error) {
+ var found bool
+ spendLimit = sdk.Coin{Denom: denom, Amount: math.ZeroInt()}
+
+ for i, allocation := range allocations {
+ if allocation.SourcePort != sourcePort || allocation.SourceChannel != sourceChannel {
+ continue
+ }
+
+ found, spendLimit = allocation.SpendLimit.Find(denom)
+ if !found {
+ return spendLimit, 0, fmt.Errorf(ErrNoMatchingAllocation, sourcePort, sourceChannel, denom)
+ }
+
+ return spendLimit, i, nil
+ }
+
+ return spendLimit, 0, fmt.Errorf(ErrNoMatchingAllocation, sourcePort, sourceChannel, denom)
+}
+
+// convertToAllocation converts the Allocation type from the IBC transfer types to our implementation of ICS20 Allocation. The conversion maps the native SDK coin type to the custom coin type, which uses Ethereum native big integers.
+func convertToAllocation(allocs []transfertypes.Allocation) []cmn.ICS20Allocation {
+ // Convert to Allocations to emit the IBC transfer authorization event
+ allocations := make([]cmn.ICS20Allocation, len(allocs))
+ for i, allocation := range allocs {
+ spendLimit := make([]cmn.Coin, len(allocation.SpendLimit))
+ for j, coin := range allocation.SpendLimit {
+ spendLimit[j] = cmn.Coin{
+ Denom: coin.Denom,
+ Amount: coin.Amount.BigInt(),
+ }
+ }
+
+ allocations[i] = cmn.ICS20Allocation{
+ SourcePort: allocation.SourcePort,
+ SourceChannel: allocation.SourceChannel,
+ SpendLimit: spendLimit,
+ AllowList: allocation.AllowList,
+ AllowedPacketData: allocation.AllowedPacketData,
+ }
+ }
+
+ return allocations
+}
+
+// CheckOriginAndSender ensures the correct sender is being used.
+func CheckOriginAndSender(contract *vm.Contract, origin common.Address, sender common.Address) (common.Address, error) {
+ if contract.CallerAddress == sender {
+ return sender, nil
+ } else if origin != sender {
+ return common.Address{}, fmt.Errorf(ErrDifferentOriginFromSender, origin.String(), sender.String())
+ }
+ return sender, nil
+}
+
+// CheckAndAcceptAuthorizationIfNeeded checks if authorization exists and accepts the grant.
+// In case the origin is the caller of the address, no authorization is required.
+func CheckAndAcceptAuthorizationIfNeeded(
+ ctx sdk.Context,
+ contract *vm.Contract,
+ origin common.Address,
+ authzKeeper authzkeeper.Keeper,
+ msg *transfertypes.MsgTransfer,
+) (*authz.AcceptResponse, *time.Time, error) {
+ if contract.CallerAddress == origin {
+ return nil, nil, nil
+ }
+
+ auth, expiration, err := authorization.CheckAuthzExists(ctx, authzKeeper, contract.CallerAddress, origin, TransferMsgURL)
+ if err != nil {
+ return nil, nil, fmt.Errorf(authorization.ErrAuthzDoesNotExistOrExpired, contract.CallerAddress, origin)
+ }
+
+ resp, err := AcceptGrant(ctx, contract.CallerAddress, origin, msg, auth)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return resp, expiration, nil
+}
+
+// UpdateGrantIfNeeded updates the grant in case the contract caller is not the origin of the message.
+func UpdateGrantIfNeeded(ctx sdk.Context, contract *vm.Contract, authzKeeper authzkeeper.Keeper, origin common.Address, expiration *time.Time, resp *authz.AcceptResponse) error {
+ if contract.CallerAddress != origin {
+ return UpdateGrant(ctx, authzKeeper, contract.CallerAddress, origin, expiration, resp)
+ }
+ return nil
+}
diff --git a/precompiles/ics20/utils_test.go b/precompiles/ics20/utils_test.go
new file mode 100644
index 00000000..636b2ca2
--- /dev/null
+++ b/precompiles/ics20/utils_test.go
@@ -0,0 +1,642 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package ics20_test
+
+import (
+ "encoding/json"
+ "math/big"
+ "time"
+
+ "cosmossdk.io/math"
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/cometbft/cometbft/crypto/tmhash"
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ tmtypes "github.com/cometbft/cometbft/types"
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/testutil/mock"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ evmosapp "github.com/evmos/evmos/v19/app"
+ evmoscontracts "github.com/evmos/evmos/v19/contracts"
+ evmosibc "github.com/evmos/evmos/v19/ibc/testing"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/erc20"
+ "github.com/evmos/evmos/v19/precompiles/ics20"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/precompiles/testutil/contracts"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ evmosutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ evmostypes "github.com/evmos/evmos/v19/types"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+)
+
+type erc20Meta struct {
+ Name string
+ Symbol string
+ Decimals uint8
+}
+
+var (
+ maxUint256Coins = sdk.Coins{sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewIntFromBigInt(abi.MaxUint256)}}
+ maxUint256CmnCoins = []cmn.Coin{{Denom: utils.BaseDenom, Amount: abi.MaxUint256}}
+ defaultCoins = sdk.Coins{sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewInt(1e18)}}
+ baseDenomCmnCoin = cmn.Coin{Denom: utils.BaseDenom, Amount: big.NewInt(1e18)}
+ defaultCmnCoins = []cmn.Coin{baseDenomCmnCoin}
+ atomCoins = sdk.Coins{sdk.Coin{Denom: "uatom", Amount: math.NewInt(1e18)}}
+ atomCmnCoin = cmn.Coin{Denom: "uatom", Amount: big.NewInt(1e18)}
+ mutliSpendLimit = sdk.Coins{sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewInt(1e18)}, sdk.Coin{Denom: "uatom", Amount: math.NewInt(1e18)}}
+ mutliCmnCoins = []cmn.Coin{baseDenomCmnCoin, atomCmnCoin}
+ testERC20 = erc20Meta{
+ Name: "TestCoin",
+ Symbol: "TC",
+ Decimals: 18,
+ }
+)
+
+// SetupWithGenesisValSet initializes a new EvmosApp with a validator set and genesis accounts
+// that also act as delegators. For simplicity, each validator is bonded with a delegation
+// of one consensus engine unit (10^6) in the default token of the simapp from first genesis
+// account. A Nop logger is set in SimApp.
+func (s *PrecompileTestSuite) SetupWithGenesisValSet(valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) {
+ appI, genesisState := evmosapp.SetupTestingApp(cmn.DefaultChainID)()
+ app, ok := appI.(*evmosapp.Evmos)
+ s.Require().True(ok)
+
+ // set genesis accounts
+ authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
+ genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
+
+ validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
+ delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
+
+ bondAmt := sdk.TokensFromConsensusPower(1, evmostypes.PowerReduction)
+
+ for _, val := range valSet.Validators {
+ pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
+ s.Require().NoError(err)
+ pkAny, err := codectypes.NewAnyWithValue(pk)
+ s.Require().NoError(err)
+ validator := stakingtypes.Validator{
+ OperatorAddress: sdk.ValAddress(val.Address).String(),
+ ConsensusPubkey: pkAny,
+ Jailed: false,
+ Status: stakingtypes.Bonded,
+ Tokens: bondAmt,
+ DelegatorShares: math.LegacyOneDec(),
+ Description: stakingtypes.Description{},
+ UnbondingHeight: int64(0),
+ UnbondingTime: time.Unix(0, 0).UTC(),
+ Commission: stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()),
+ MinSelfDelegation: math.ZeroInt(),
+ }
+ validators = append(validators, validator)
+ delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), math.LegacyOneDec()))
+ }
+ s.validators = validators
+
+ // set validators and delegations
+ stakingParams := stakingtypes.DefaultParams()
+ // set bond demon to be aevmos
+ stakingParams.BondDenom = utils.BaseDenom
+ stakingGenesis := stakingtypes.NewGenesisState(stakingParams, validators, delegations)
+ genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
+
+ totalBondAmt := bondAmt.Mul(math.NewInt(int64(len(validators))))
+ totalSupply := sdk.NewCoins()
+ for _, b := range balances {
+ // add genesis acc tokens and delegated tokens to total supply
+ totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(utils.BaseDenom, totalBondAmt))...)
+ }
+
+ // add bonded amount to bonded pool module account
+ balances = append(balances, banktypes.Balance{
+ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
+ Coins: sdk.Coins{sdk.NewCoin(utils.BaseDenom, totalBondAmt)},
+ })
+
+ // update total supply
+ bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{})
+ genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
+
+ stateBytes, err := json.MarshalIndent(genesisState, "", " ")
+ s.Require().NoError(err)
+
+ feeGenesis := feemarkettypes.NewGenesisState(feemarkettypes.DefaultGenesisState().Params, 0)
+ genesisState[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feeGenesis)
+
+ // init chain will set the validator set and initialize the genesis accounts
+ app.InitChain(
+ abci.RequestInitChain{
+ ChainId: cmn.DefaultChainID,
+ Validators: []abci.ValidatorUpdate{},
+ ConsensusParams: evmosapp.DefaultConsensusParams,
+ AppStateBytes: stateBytes,
+ },
+ )
+
+ // commit genesis changes
+ app.Commit()
+
+ // instantiate new header
+ header := evmosutil.NewHeader(
+ 2,
+ time.Now().UTC(),
+ cmn.DefaultChainID,
+ sdk.ConsAddress(validators[0].GetOperator()),
+ tmhash.Sum([]byte("app")),
+ tmhash.Sum([]byte("validators")),
+ )
+
+ app.BeginBlock(abci.RequestBeginBlock{Header: header})
+
+ // create Contexts
+ s.ctx = app.BaseApp.NewContext(false, header)
+ s.app = app
+}
+
+func (s *PrecompileTestSuite) DoSetupTest() {
+ s.defaultExpirationDuration = s.ctx.BlockTime().Add(cmn.DefaultExpirationDuration).UTC()
+
+ // generate validators private/public key
+ var (
+ validatorsPerChain = 2
+ validators []*tmtypes.Validator
+ signersByAddress = make(map[string]tmtypes.PrivValidator, validatorsPerChain)
+ )
+
+ for i := 0; i < validatorsPerChain; i++ {
+ privVal := mock.NewPV()
+ pubKey, err := privVal.GetPubKey()
+ s.Require().NoError(err)
+ validators = append(validators, tmtypes.NewValidator(pubKey, 1))
+ signersByAddress[pubKey.Address().String()] = privVal
+ }
+
+ // construct validator set;
+ // Note that the validators are sorted by voting power
+ // or, if equal, by address lexical order
+ s.valSet = tmtypes.NewValidatorSet(validators)
+
+ // Create a coordinator and 2 test chains that will be used in the testing suite
+ chains := make(map[string]*ibctesting.TestChain)
+ s.coordinator = &ibctesting.Coordinator{
+ T: s.T(),
+ // NOTE: This year has to be updated otherwise the client will be shown as expired
+ CurrentTime: time.Date(time.Now().Year()+1, 1, 2, 0, 0, 0, 0, time.UTC),
+ }
+ // Create 2 Evmos chains
+ chains[cmn.DefaultChainID] = s.NewTestChainWithValSet(s.coordinator, s.valSet, signersByAddress)
+ // TODO: Figure out if we want to make the second chain keepers accessible to the tests to check the state
+ chainID2 := utils.MainnetChainID + "-2"
+ chains[chainID2] = ibctesting.NewTestChain(s.T(), s.coordinator, chainID2)
+ s.coordinator.Chains = chains
+
+ // Setup Chains in the testing suite
+ s.chainA = s.coordinator.GetChain(cmn.DefaultChainID)
+ s.chainB = s.coordinator.GetChain(chainID2)
+
+ if s.suiteIBCTesting {
+ s.setupIBCTest()
+ }
+}
+
+func (s *PrecompileTestSuite) NewTestChainWithValSet(coord *ibctesting.Coordinator, valSet *tmtypes.ValidatorSet, signers map[string]tmtypes.PrivValidator) *ibctesting.TestChain {
+ // generate genesis account
+ addr, priv := evmosutiltx.NewAddrKey()
+ s.privKey = priv
+ s.address = addr
+ // differentAddr is an address generated for testing purposes that e.g. raises the different origin error
+ s.differentAddr = evmosutiltx.GenerateAddress()
+ s.signer = evmosutiltx.NewSigner(priv)
+
+ baseAcc := authtypes.NewBaseAccount(priv.PubKey().Address().Bytes(), priv.PubKey(), 0, 0)
+ amount := sdk.TokensFromConsensusPower(5, evmostypes.PowerReduction)
+
+ balance := banktypes.Balance{
+ Address: baseAcc.GetAddress().String(),
+ Coins: sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, amount)),
+ }
+
+ s.SetupWithGenesisValSet(s.valSet, []authtypes.GenesisAccount{baseAcc}, balance)
+
+ // create current header and call begin block
+ header := tmproto.Header{
+ ChainID: cmn.DefaultChainID,
+ Height: 1,
+ Time: coord.CurrentTime.UTC(),
+ }
+
+ txConfig := s.app.GetTxConfig()
+
+ // Create StateDB
+ s.stateDB = statedb.New(s.ctx, s.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.ctx.HeaderHash().Bytes())))
+
+ // bond denom
+ stakingParams := s.app.StakingKeeper.GetParams(s.ctx)
+ stakingParams.BondDenom = utils.BaseDenom
+ s.bondDenom = stakingParams.BondDenom
+ err := s.app.StakingKeeper.SetParams(s.ctx, stakingParams)
+ s.Require().NoError(err)
+
+ s.ethSigner = ethtypes.LatestSignerForChainID(s.app.EvmKeeper.ChainID())
+
+ // Setting up the fee market to 0 so the transactions don't fail in IBC testing
+ s.app.FeeMarketKeeper.SetBaseFee(s.ctx, big.NewInt(0))
+ s.app.FeeMarketKeeper.SetBlockGasWanted(s.ctx, 0)
+ s.app.FeeMarketKeeper.SetTransientBlockGasWanted(s.ctx, 0)
+
+ precompile, err := ics20.NewPrecompile(s.app.StakingKeeper, s.app.TransferKeeper, s.app.IBCKeeper.ChannelKeeper, s.app.AuthzKeeper)
+ s.Require().NoError(err)
+ s.precompile = precompile
+
+ queryHelperEvm := baseapp.NewQueryServerTestHelper(s.ctx, s.app.InterfaceRegistry())
+ evmtypes.RegisterQueryServer(queryHelperEvm, s.app.EvmKeeper)
+ s.queryClientEVM = evmtypes.NewQueryClient(queryHelperEvm)
+
+ // create an account to send transactions from
+ chain := &ibctesting.TestChain{
+ T: s.T(),
+ Coordinator: coord,
+ ChainID: cmn.DefaultChainID,
+ App: s.app,
+ CurrentHeader: header,
+ QueryServer: s.app.GetIBCKeeper(),
+ TxConfig: txConfig,
+ Codec: s.app.AppCodec(),
+ Vals: valSet,
+ NextVals: valSet,
+ Signers: signers,
+ SenderPrivKey: priv,
+ SenderAccount: baseAcc,
+ SenderAccounts: []ibctesting.SenderAccount{{SenderPrivKey: priv, SenderAccount: baseAcc}},
+ }
+
+ coord.CommitBlock(chain)
+
+ return chain
+}
+
+// NewPrecompileContract creates a new precompile contract and sets the gas meter
+func (s *PrecompileTestSuite) NewPrecompileContract(gas uint64) *vm.Contract {
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), gas)
+
+ s.ctx = s.ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
+ initialGas := s.ctx.GasMeter().GasConsumed()
+ s.Require().Zero(initialGas)
+
+ return contract
+}
+
+// NewTransferAuthorizationWithAllocations creates a new allocation for the given grantee and granter and the given coins
+func (s *PrecompileTestSuite) NewTransferAuthorizationWithAllocations(ctx sdk.Context, app *evmosapp.Evmos, grantee, granter common.Address, allocations []transfertypes.Allocation) error {
+ transferAuthz := &transfertypes.TransferAuthorization{Allocations: allocations}
+ if err := transferAuthz.ValidateBasic(); err != nil {
+ return err
+ }
+
+ // create the authorization
+ return app.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), transferAuthz, &s.defaultExpirationDuration)
+}
+
+// NewTransferAuthorization creates a new transfer authorization for the given grantee and granter and the given coins
+func (s *PrecompileTestSuite) NewTransferAuthorization(ctx sdk.Context, app *evmosapp.Evmos, grantee, granter common.Address, path *ibctesting.Path, coins sdk.Coins, allowList []string, allowedPacketData []string) error {
+ allocations := []transfertypes.Allocation{
+ {
+ SourcePort: path.EndpointA.ChannelConfig.PortID,
+ SourceChannel: path.EndpointA.ChannelID,
+ SpendLimit: coins,
+ AllowList: allowList,
+ AllowedPacketData: allowedPacketData,
+ },
+ }
+
+ transferAuthz := &transfertypes.TransferAuthorization{Allocations: allocations}
+ if err := transferAuthz.ValidateBasic(); err != nil {
+ return err
+ }
+
+ // create the authorization
+ return app.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), transferAuthz, &s.defaultExpirationDuration)
+}
+
+// GetTransferAuthorization returns the transfer authorization for the given grantee and granter
+func (s *PrecompileTestSuite) GetTransferAuthorization(ctx sdk.Context, grantee, granter common.Address) *transfertypes.TransferAuthorization {
+ grant, _ := s.app.AuthzKeeper.GetAuthorization(ctx, grantee.Bytes(), granter.Bytes(), ics20.TransferMsgURL)
+ s.Require().NotNil(grant)
+ transferAuthz, ok := grant.(*transfertypes.TransferAuthorization)
+ s.Require().True(ok)
+ s.Require().NotNil(transferAuthz)
+ return transferAuthz
+}
+
+// CheckAllowanceChangeEvent is a helper function used to check the allowance change event arguments.
+func (s *PrecompileTestSuite) CheckAllowanceChangeEvent(log *ethtypes.Log, amount *big.Int, isIncrease bool) {
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[authorization.EventTypeIBCTransferAuthorization]
+ s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var approvalEvent ics20.EventTransferAuthorization
+ err := cmn.UnpackLog(s.precompile.ABI, &approvalEvent, authorization.EventTypeIBCTransferAuthorization, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, approvalEvent.Grantee)
+ s.Require().Equal(s.address, approvalEvent.Granter)
+ s.Require().Equal("transfer", approvalEvent.Allocations[0].SourcePort)
+ s.Require().Equal("channel-0", approvalEvent.Allocations[0].SourceChannel)
+
+ allocationAmount := approvalEvent.Allocations[0].SpendLimit[0].Amount
+ if isIncrease {
+ newTotal := amount.Add(allocationAmount, amount)
+ s.Require().Equal(amount, newTotal)
+ } else {
+ newTotal := amount.Sub(allocationAmount, amount)
+ s.Require().Equal(amount, newTotal)
+ }
+}
+
+// NewTransferPath creates a new path between two chains with the specified portIds and version.
+func NewTransferPath(chainA, chainB *ibctesting.TestChain) *ibctesting.Path {
+ path := ibctesting.NewPath(chainA, chainB)
+ path.EndpointA.ChannelConfig.PortID = transfertypes.PortID
+ path.EndpointB.ChannelConfig.PortID = transfertypes.PortID
+ path.EndpointA.ChannelConfig.Version = transfertypes.Version
+ path.EndpointB.ChannelConfig.Version = transfertypes.Version
+
+ return path
+}
+
+// setupIBCTest makes the necessary setup of chains A & B
+// for integration tests
+func (s *PrecompileTestSuite) setupIBCTest() {
+ s.coordinator.CommitNBlocks(s.chainA, 2)
+ s.coordinator.CommitNBlocks(s.chainB, 2)
+
+ s.app = s.chainA.App.(*evmosapp.Evmos)
+ evmParams := s.app.EvmKeeper.GetParams(s.chainA.GetContext())
+ evmParams.EvmDenom = utils.BaseDenom
+ err := s.app.EvmKeeper.SetParams(s.chainA.GetContext(), evmParams)
+ s.Require().NoError(err)
+
+ // Set block proposer once, so its carried over on the ibc-go-testing suite
+ validators := s.app.StakingKeeper.GetValidators(s.chainA.GetContext(), 2)
+ cons, err := validators[0].GetConsAddr()
+ s.Require().NoError(err)
+ s.chainA.CurrentHeader.ProposerAddress = cons.Bytes()
+
+ err = s.app.StakingKeeper.SetValidatorByConsAddr(s.chainA.GetContext(), validators[0])
+ s.Require().NoError(err)
+
+ _, err = s.app.EvmKeeper.GetCoinbaseAddress(s.chainA.GetContext(), sdk.ConsAddress(s.chainA.CurrentHeader.ProposerAddress))
+ s.Require().NoError(err)
+
+ // Mint coins locked on the evmos account generated with secp.
+ amt, ok := math.NewIntFromString("1000000000000000000000")
+ s.Require().True(ok)
+ coinEvmos := sdk.NewCoin(utils.BaseDenom, amt)
+ coins := sdk.NewCoins(coinEvmos)
+ err = s.app.BankKeeper.MintCoins(s.chainA.GetContext(), inflationtypes.ModuleName, coins)
+ s.Require().NoError(err)
+ err = s.app.BankKeeper.SendCoinsFromModuleToAccount(s.chainA.GetContext(), inflationtypes.ModuleName, s.chainA.SenderAccount.GetAddress(), coins)
+ s.Require().NoError(err)
+
+ s.transferPath = evmosibc.NewTransferPath(s.chainA, s.chainB) // clientID, connectionID, channelID empty
+ evmosibc.SetupPath(s.coordinator, s.transferPath) // clientID, connectionID, channelID filled
+ s.Require().Equal("07-tendermint-0", s.transferPath.EndpointA.ClientID)
+ s.Require().Equal("connection-0", s.transferPath.EndpointA.ConnectionID)
+ s.Require().Equal("channel-0", s.transferPath.EndpointA.ChannelID)
+}
+
+// setTransferApproval sets the transfer approval for the given grantee and allocations
+func (s *PrecompileTestSuite) setTransferApproval(
+ args contracts.CallArgs,
+ grantee common.Address,
+ allocations []cmn.ICS20Allocation,
+) {
+ args.MethodName = authorization.ApproveMethod
+ args.Args = []interface{}{
+ grantee,
+ allocations,
+ }
+
+ logCheckArgs := testutil.LogCheckArgs{
+ ABIEvents: s.precompile.Events,
+ ExpEvents: []string{authorization.EventTypeIBCTransferAuthorization},
+ ExpPass: true,
+ }
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the contract to approve")
+
+ s.chainA.NextBlock()
+
+ // check auth created successfully
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.chainA.GetContext(), grantee.Bytes(), args.PrivKey.PubKey().Address().Bytes(), ics20.TransferMsgURL)
+ Expect(authz).NotTo(BeNil())
+ transferAuthz, ok := authz.(*transfertypes.TransferAuthorization)
+ Expect(ok).To(BeTrue())
+ Expect(len(transferAuthz.Allocations[0].SpendLimit)).To(Equal(len(allocations[0].SpendLimit)))
+ for i, sl := range transferAuthz.Allocations[0].SpendLimit {
+ // NOTE order may change if there're more than one coin
+ Expect(sl.Denom).To(Equal(allocations[0].SpendLimit[i].Denom))
+ Expect(sl.Amount.BigInt()).To(Equal(allocations[0].SpendLimit[i].Amount))
+ }
+}
+
+// setTransferApprovalForContract sets the transfer approval for the given contract
+func (s *PrecompileTestSuite) setTransferApprovalForContract(args contracts.CallArgs) {
+ logCheckArgs := testutil.LogCheckArgs{
+ ABIEvents: s.precompile.Events,
+ ExpEvents: []string{authorization.EventTypeIBCTransferAuthorization},
+ ExpPass: true,
+ }
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, args, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the contract to approve")
+
+ s.chainA.NextBlock()
+
+ // check auth created successfully
+ authz, _ := s.app.AuthzKeeper.GetAuthorization(s.chainA.GetContext(), args.ContractAddr.Bytes(), args.PrivKey.PubKey().Address().Bytes(), ics20.TransferMsgURL)
+ Expect(authz).NotTo(BeNil())
+ transferAuthz, ok := authz.(*transfertypes.TransferAuthorization)
+ Expect(ok).To(BeTrue())
+ Expect(len(transferAuthz.Allocations) > 0).To(BeTrue())
+}
+
+// setupAllocationsForTesting sets the allocations for testing
+func (s *PrecompileTestSuite) setupAllocationsForTesting() {
+ defaultSingleAlloc = []cmn.ICS20Allocation{
+ {
+ SourcePort: ibctesting.TransferPort,
+ SourceChannel: s.transferPath.EndpointA.ChannelID,
+ SpendLimit: defaultCmnCoins,
+ AllowedPacketData: []string{"memo"},
+ },
+ }
+}
+
+// TODO upstream this change to evmos (adding gasPrice)
+// DeployContract deploys a contract with the provided private key,
+// compiled contract data and constructor arguments
+func DeployContract(
+ ctx sdk.Context,
+ evmosApp *evmosapp.Evmos,
+ priv cryptotypes.PrivKey,
+ gasPrice *big.Int,
+ queryClientEvm evmtypes.QueryClient,
+ contract evmtypes.CompiledContract,
+ constructorArgs ...interface{},
+) (common.Address, error) {
+ chainID := evmosApp.EvmKeeper.ChainID()
+ from := common.BytesToAddress(priv.PubKey().Address().Bytes())
+ nonce := evmosApp.EvmKeeper.GetNonce(ctx, from)
+
+ ctorArgs, err := contract.ABI.Pack("", constructorArgs...)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ data := append(contract.Bin, ctorArgs...) //nolint:gocritic
+ gas, err := evmosutiltx.GasLimit(ctx, from, data, queryClientEvm)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ msgEthereumTx := evmtypes.NewTx(&evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ GasLimit: gas,
+ GasFeeCap: evmosApp.FeeMarketKeeper.GetBaseFee(ctx),
+ GasTipCap: big.NewInt(1),
+ GasPrice: gasPrice,
+ Input: data,
+ Accesses: ðtypes.AccessList{},
+ })
+ msgEthereumTx.From = from.String()
+
+ res, err := evmosutil.DeliverEthTx(evmosApp, priv, msgEthereumTx)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ if _, err := evmosutil.CheckEthTxResponse(res, evmosApp.AppCodec()); err != nil {
+ return common.Address{}, err
+ }
+
+ return crypto.CreateAddress(from, nonce), nil
+}
+
+// DeployERC20Contract deploys a ERC20 token with the provided name, symbol and decimals
+func (s *PrecompileTestSuite) DeployERC20Contract(chain *ibctesting.TestChain, name, symbol string, decimals uint8) (common.Address, error) {
+ addr, err := DeployContract(
+ chain.GetContext(),
+ s.app,
+ s.privKey,
+ gasPrice,
+ s.queryClientEVM,
+ evmoscontracts.ERC20MinterBurnerDecimalsContract,
+ name,
+ symbol,
+ decimals,
+ )
+ chain.NextBlock()
+ return addr, err
+}
+
+// setupERC20ContractTests deploys a ERC20 token
+// and mint some tokens to the deployer address (s.address).
+// The amount of tokens sent to the deployer address is defined in
+// the 'amount' input argument
+func (s *PrecompileTestSuite) setupERC20ContractTests(amount *big.Int) common.Address {
+ erc20Addr, err := s.DeployERC20Contract(s.chainA, testERC20.Name, testERC20.Symbol, testERC20.Decimals)
+ Expect(err).To(BeNil(), "error while deploying ERC20 contract: %v", err)
+
+ defaultERC20CallArgs := contracts.CallArgs{
+ ContractAddr: erc20Addr,
+ ContractABI: evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ PrivKey: s.privKey,
+ GasPrice: gasPrice,
+ }
+
+ // mint coins to the address
+ mintCoinsArgs := defaultERC20CallArgs.
+ WithMethodName("mint").
+ WithArgs(s.address, amount)
+
+ mintCheck := testutil.LogCheckArgs{
+ ABIEvents: evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI.Events,
+ ExpEvents: []string{erc20.EventTypeTransfer}, // upon minting the tokens are sent to the receiving address
+ ExpPass: true,
+ }
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.chainA.GetContext(), s.app, mintCoinsArgs, mintCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ s.chainA.NextBlock()
+
+ // check that the address has the tokens -- this has to be done using the stateDB because
+ // unregistered token pairs do not show up in the bank keeper
+ balance := s.app.Erc20Keeper.BalanceOf(
+ s.chainA.GetContext(),
+ evmoscontracts.ERC20MinterBurnerDecimalsContract.ABI,
+ erc20Addr,
+ s.address,
+ )
+ Expect(balance).To(Equal(amount), "address does not have the expected amount of tokens")
+
+ return erc20Addr
+}
+
+// makePacket is a helper function to build the sent IBC packet
+// to perform an ICS20 transfer.
+// This packet is then used to test the IBC callbacks (Timeout, Ack)
+func (s *PrecompileTestSuite) makePacket(
+ senderAddr,
+ receiverAddr,
+ denom,
+ memo string,
+ amt *big.Int,
+ seq uint64,
+ timeoutHeight clienttypes.Height,
+) channeltypes.Packet {
+ packetData := transfertypes.NewFungibleTokenPacketData(
+ denom,
+ amt.String(),
+ senderAddr,
+ receiverAddr,
+ memo,
+ )
+
+ return channeltypes.NewPacket(
+ packetData.GetBytes(),
+ seq,
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.transferPath.EndpointB.ChannelConfig.PortID,
+ s.transferPath.EndpointB.ChannelID,
+ timeoutHeight,
+ 0,
+ )
+}
diff --git a/precompiles/p256/integration_test.go b/precompiles/p256/integration_test.go
new file mode 100644
index 00000000..24019c75
--- /dev/null
+++ b/precompiles/p256/integration_test.go
@@ -0,0 +1,168 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package p256_test
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+
+ "github.com/cometbft/cometbft/crypto"
+ "github.com/ethereum/go-ethereum/common"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "github.com/evmos/evmos/v19/precompiles/p256"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+type IntegrationTestSuite struct {
+ network network.Network
+ factory factory.TxFactory
+ keyring testkeyring.Keyring
+ precompileAddress common.Address
+ p256Priv *ecdsa.PrivateKey
+}
+
+var _ = Describe("Calling p256 precompile directly", Label("P256 Precompile"), Ordered, func() {
+ var s *IntegrationTestSuite
+
+ BeforeAll(func() {
+ keyring := testkeyring.New(1)
+ integrationNetwork := network.New(
+ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ grpcHandler := grpc.NewIntegrationHandler(integrationNetwork)
+ txFactory := factory.New(integrationNetwork, grpcHandler)
+ p256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ Expect(err).To(BeNil())
+
+ s = &IntegrationTestSuite{
+ network: integrationNetwork,
+ factory: txFactory,
+ keyring: keyring,
+ precompileAddress: p256.Precompile{}.Address(),
+ p256Priv: p256Priv,
+ }
+ })
+
+ AfterEach(func() {
+ // Start each test with a fresh block
+ err := s.network.NextBlock()
+ Expect(err).To(BeNil())
+ })
+
+ When("the precompile is enabled in the EVM params", func() {
+ DescribeTable("execute contract call", func(inputFn func() (input, expOutput []byte, expErr string)) {
+ senderKey := s.keyring.GetKey(0)
+
+ input, expOutput, expErr := inputFn()
+ args := evmtypes.EvmTxArgs{
+ To: &s.precompileAddress,
+ Input: input,
+ }
+
+ resDeliverTx, err := s.factory.ExecuteEthTx(senderKey.Priv, args)
+ Expect(err).To(BeNil())
+ Expect(resDeliverTx.IsOK()).To(Equal(true), "transaction should have succeeded", resDeliverTx.GetLog())
+
+ res, err := utils.DecodeResponseDeliverTx(resDeliverTx)
+ Expect(err).To(BeNil())
+ Expect(res.VmError).To(Equal(expErr), "expected different vm error")
+ Expect(res.Ret).To(Equal(expOutput))
+ },
+ Entry(
+ "valid signature",
+ func() (input, expOutput []byte, expErr string) {
+ input = signMsg([]byte("hello world"), s.p256Priv)
+ return input, trueValue, ""
+ },
+ ),
+ Entry(
+ "invalid signature",
+ func() (input, expOutput []byte, expErr string) {
+ privB, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ Expect(err).To(BeNil())
+
+ hash := crypto.Sha256([]byte("hello world"))
+
+ rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash)
+ Expect(err).To(BeNil())
+
+ input = make([]byte, p256.VerifyInputLength)
+ copy(input[0:32], hash)
+ copy(input[32:64], rInt.Bytes())
+ copy(input[64:96], sInt.Bytes())
+ copy(input[96:128], privB.PublicKey.X.Bytes())
+ copy(input[128:160], privB.PublicKey.Y.Bytes())
+ return input, nil, ""
+ },
+ ),
+ )
+ })
+
+ When("the precompile is not enabled in the EVM params", func() {
+ BeforeEach(func() {
+ params := evmtypes.DefaultParams()
+ addr := s.precompileAddress.String()
+ var activePrecompiles []string
+ for _, precompile := range params.ActiveStaticPrecompiles {
+ if precompile != addr {
+ activePrecompiles = append(activePrecompiles, precompile)
+ }
+ }
+ params.ActiveStaticPrecompiles = activePrecompiles
+ err := s.network.UpdateEvmParams(params)
+ Expect(err).To(BeNil())
+ })
+
+ DescribeTable("execute contract call", func(inputFn func() (input []byte)) {
+ senderKey := s.keyring.GetKey(0)
+
+ input := inputFn()
+ args := evmtypes.EvmTxArgs{
+ To: &s.precompileAddress,
+ Input: input,
+ }
+
+ _, err := s.factory.ExecuteEthTx(senderKey.Priv, args)
+ Expect(err).To(BeNil(), "expected no error since contract doesn't exists")
+ },
+ Entry(
+ "valid signature",
+ func() (input []byte) {
+ input = signMsg([]byte("hello world"), s.p256Priv)
+ return input
+ },
+ ),
+ Entry(
+ "invalid signature",
+ func() (input []byte) {
+ privB, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ Expect(err).To(BeNil())
+
+ hash := crypto.Sha256([]byte("hello world"))
+
+ rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash)
+ Expect(err).To(BeNil())
+
+ input = make([]byte, p256.VerifyInputLength)
+ copy(input[0:32], hash)
+ copy(input[32:64], rInt.Bytes())
+ copy(input[64:96], sInt.Bytes())
+ copy(input[96:128], privB.PublicKey.X.Bytes())
+ copy(input[128:160], privB.PublicKey.Y.Bytes())
+ return input
+ },
+ ),
+ )
+ })
+})
diff --git a/precompiles/p256/p256.go b/precompiles/p256/p256.go
new file mode 100644
index 00000000..0b855573
--- /dev/null
+++ b/precompiles/p256/p256.go
@@ -0,0 +1,84 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package p256
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/crypto/secp256r1"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+var _ vm.PrecompiledContract = &Precompile{}
+
+const (
+ // VerifyGas is the secp256r1 elliptic curve signature verifier gas price.
+ VerifyGas uint64 = 3450
+ // VerifyInputLength defines the required input length (160 bytes).
+ VerifyInputLength = 160
+)
+
+// Precompile secp256r1 (P256) signature verification
+// implemented as a native contract as per EIP-7212.
+// See https://eips.ethereum.org/EIPS/eip-7212 for details
+type Precompile struct{}
+
+// Address defines the address of the p256 precompiled contract.
+func (Precompile) Address() common.Address {
+ return common.HexToAddress(evmtypes.P256PrecompileAddress)
+}
+
+// RequiredGas returns the static gas required to execute the precompiled contract.
+func (p Precompile) RequiredGas(_ []byte) uint64 {
+ return VerifyGas
+}
+
+// Run executes the p256 signature verification using ECDSA.
+//
+// Input data: 160 bytes of data including:
+// - 32 bytes of the signed data hash
+// - 32 bytes of the r component of the signature
+// - 32 bytes of the s component of the signature
+// - 32 bytes of the x coordinate of the public key
+// - 32 bytes of the y coordinate of the public key
+//
+// Output data: 32 bytes of result data and error
+// - If the signature verification process succeeds, it returns 1 in 32 bytes format
+func (p *Precompile) Run(_ *vm.EVM, contract *vm.Contract, _ bool) (bz []byte, err error) {
+ input := contract.Input
+ // Check the input length
+ if len(input) != VerifyInputLength {
+ // Input length is invalid
+ return nil, nil
+ }
+
+ // Extract the hash, r, s, x, y from the input
+ hash := input[0:32]
+ r, s := new(big.Int).SetBytes(input[32:64]), new(big.Int).SetBytes(input[64:96])
+ x, y := new(big.Int).SetBytes(input[96:128]), new(big.Int).SetBytes(input[128:160])
+
+ // Verify the secp256r1 signature
+ if secp256r1.Verify(hash, r, s, x, y) {
+ // Signature is valid
+ return common.LeftPadBytes(common.Big1.Bytes(), 32), nil
+ }
+
+ // Signature is invalid
+ return nil, nil
+}
diff --git a/precompiles/p256/p256_test.go b/precompiles/p256/p256_test.go
new file mode 100644
index 00000000..c03fd518
--- /dev/null
+++ b/precompiles/p256/p256_test.go
@@ -0,0 +1,130 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package p256_test
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+
+ "github.com/cometbft/cometbft/crypto"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/p256"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+var trueValue = common.LeftPadBytes(common.Big1.Bytes(), 32)
+
+func (s *PrecompileTestSuite) TestAddress() {
+ s.Require().Equal(evmtypes.P256PrecompileAddress, s.precompile.Address().String())
+}
+
+func (s *PrecompileTestSuite) TestRequiredGas() {
+ s.Require().Equal(p256.VerifyGas, s.precompile.RequiredGas(nil))
+}
+
+func (s *PrecompileTestSuite) TestRun() {
+ testCases := []struct {
+ name string
+ sign func() []byte
+ expPass bool
+ }{
+ {
+ "pass - Sign",
+ func() []byte {
+ msg := []byte("hello world")
+ hash := crypto.Sha256(msg)
+
+ rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash)
+ s.Require().NoError(err)
+
+ input := make([]byte, p256.VerifyInputLength)
+ copy(input[0:32], hash)
+ copy(input[32:64], rInt.Bytes())
+ copy(input[64:96], sInt.Bytes())
+ copy(input[96:128], s.p256Priv.PublicKey.X.Bytes())
+ copy(input[128:160], s.p256Priv.PublicKey.Y.Bytes())
+
+ return input
+ },
+ true,
+ },
+ {
+ "pass - sign ASN.1 encoded signature",
+ func() []byte {
+ msg := []byte("hello world")
+ hash := crypto.Sha256(msg)
+
+ sig, err := ecdsa.SignASN1(rand.Reader, s.p256Priv, hash)
+ s.Require().NoError(err)
+
+ rBz, sBz, err := parseSignature(sig)
+ s.Require().NoError(err)
+
+ input := make([]byte, p256.VerifyInputLength)
+ copy(input[0:32], hash)
+ copy(input[32:64], rBz)
+ copy(input[64:96], sBz)
+ copy(input[96:128], s.p256Priv.PublicKey.X.Bytes())
+ copy(input[128:160], s.p256Priv.PublicKey.Y.Bytes())
+
+ return input
+ },
+ true,
+ },
+ {
+ "fail - invalid signature",
+ func() []byte {
+ privB, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ s.Require().NoError(err)
+
+ bz := elliptic.MarshalCompressed(elliptic.P256(), s.p256Priv.X, s.p256Priv.Y)
+ s.Require().NotEmpty(bz)
+
+ msg := []byte("hello world")
+ hash := crypto.Sha256(msg)
+
+ rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash)
+ s.Require().NoError(err)
+
+ input := make([]byte, p256.VerifyInputLength)
+ copy(input[0:32], hash)
+ copy(input[32:64], rInt.Bytes())
+ copy(input[64:96], sInt.Bytes())
+ copy(input[96:128], privB.PublicKey.X.Bytes())
+ copy(input[128:160], privB.PublicKey.Y.Bytes())
+
+ return input
+ },
+ false,
+ },
+ {
+ "fail - invalid length",
+ func() []byte {
+ msg := []byte("hello world")
+ hash := crypto.Sha256(msg)
+
+ input := make([]byte, 32)
+ copy(input[0:32], hash)
+
+ return input
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ input := tc.sign()
+ bz, err := s.precompile.Run(nil, &vm.Contract{Input: input}, false)
+ if tc.expPass {
+ s.Require().NoError(err)
+ s.Require().Equal(trueValue, bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().Empty(bz)
+ }
+ })
+ }
+}
diff --git a/precompiles/p256/setup_test.go b/precompiles/p256/setup_test.go
new file mode 100644
index 00000000..3cc4f021
--- /dev/null
+++ b/precompiles/p256/setup_test.go
@@ -0,0 +1,75 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package p256_test
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "errors"
+ "testing"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "github.com/cometbft/cometbft/crypto"
+ "github.com/evmos/evmos/v19/precompiles/p256"
+ "github.com/stretchr/testify/suite"
+ "golang.org/x/crypto/cryptobyte"
+ "golang.org/x/crypto/cryptobyte/asn1"
+)
+
+var s *PrecompileTestSuite
+
+type PrecompileTestSuite struct {
+ suite.Suite
+ p256Priv *ecdsa.PrivateKey
+ precompile *p256.Precompile
+}
+
+func TestPrecompileTestSuite(t *testing.T) {
+ s = new(PrecompileTestSuite)
+ suite.Run(t, s)
+
+ // Run Ginkgo integration tests
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Precompile Test Suite")
+}
+
+func (s *PrecompileTestSuite) SetupTest() {
+ p256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ s.Require().NoError(err)
+ s.p256Priv = p256Priv
+ s.precompile = &p256.Precompile{}
+}
+
+func signMsg(msg []byte, priv *ecdsa.PrivateKey) []byte {
+ hash := crypto.Sha256(msg)
+
+ rInt, sInt, err := ecdsa.Sign(rand.Reader, priv, hash)
+ s.Require().NoError(err)
+
+ input := make([]byte, p256.VerifyInputLength)
+ copy(input[0:32], hash)
+ copy(input[32:64], rInt.Bytes())
+ copy(input[64:96], sInt.Bytes())
+ copy(input[96:128], priv.PublicKey.X.Bytes())
+ copy(input[128:160], priv.PublicKey.Y.Bytes())
+
+ return input
+}
+
+func parseSignature(sig []byte) (r, s []byte, err error) {
+ var inner cryptobyte.String
+ input := cryptobyte.String(sig)
+ if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
+ !input.Empty() ||
+ !inner.ReadASN1Integer(&r) ||
+ !inner.ReadASN1Integer(&s) ||
+ !inner.Empty() {
+ return nil, nil, errors.New("invalid ASN.1")
+ }
+ return r, s, nil
+}
diff --git a/precompiles/staking/StakingI.sol b/precompiles/staking/StakingI.sol
new file mode 100644
index 00000000..5ebe752c
--- /dev/null
+++ b/precompiles/staking/StakingI.sol
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../authorization/AuthorizationI.sol" as authorization;
+import "../common/Types.sol";
+
+/// @dev The StakingI contract's address.
+address constant STAKING_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000800;
+
+/// @dev The StakingI contract's instance.
+StakingI constant STAKING_CONTRACT = StakingI(STAKING_PRECOMPILE_ADDRESS);
+
+/// @dev Define all the available staking methods.
+string constant MSG_CREATE_VALIDATOR = "/cosmos.staking.v1beta1.MsgCreateValidator";
+string constant MSG_EDIT_VALIDATOR = "/cosmos.staking.v1beta1.MsgEditValidator";
+string constant MSG_DELEGATE = "/cosmos.staking.v1beta1.MsgDelegate";
+string constant MSG_UNDELEGATE = "/cosmos.staking.v1beta1.MsgUndelegate";
+string constant MSG_REDELEGATE = "/cosmos.staking.v1beta1.MsgBeginRedelegate";
+string constant MSG_CANCEL_UNDELEGATION = "/cosmos.staking.v1beta1.MsgCancelUnbondingDelegation";
+
+/// @dev Constant used in flags to indicate that commission rate field should not be updated
+int256 constant DO_NOT_MODIFY_COMMISSION_RATE = -1;
+
+/// @dev Constant used in flags to indicate that min self delegation field should not be updated
+int256 constant DO_NOT_MODIFY_MIN_SELF_DELEGATION = -1;
+
+/// @dev Defines the initial description to be used for creating
+/// a validator.
+struct Description {
+ string moniker;
+ string identity;
+ string website;
+ string securityContact;
+ string details;
+}
+
+/// @dev Defines the initial commission rates to be used for creating
+/// a validator.
+struct CommissionRates {
+ uint256 rate;
+ uint256 maxRate;
+ uint256 maxChangeRate;
+}
+
+/// @dev Defines commission parameters for a given validator.
+struct Commission {
+ CommissionRates commissionRates;
+ uint256 updateTime;
+}
+
+/// @dev Represents a validator in the staking module.
+struct Validator {
+ string operatorAddress;
+ string consensusPubkey;
+ bool jailed;
+ BondStatus status;
+ uint256 tokens;
+ uint256 delegatorShares; // TODO: decimal
+ string description;
+ int64 unbondingHeight;
+ int64 unbondingTime;
+ uint256 commission;
+ uint256 minSelfDelegation;
+}
+
+/// @dev Represents the output of a Redelegations query.
+struct RedelegationResponse {
+ Redelegation redelegation;
+ RedelegationEntryResponse[] entries;
+}
+
+/// @dev Represents a redelegation between a delegator and a validator.
+struct Redelegation {
+ string delegatorAddress;
+ string validatorSrcAddress;
+ string validatorDstAddress;
+ RedelegationEntry[] entries;
+}
+
+/// @dev Represents a RedelegationEntryResponse for the Redelegations query.
+struct RedelegationEntryResponse {
+ RedelegationEntry redelegationEntry;
+ uint256 balance;
+}
+
+/// @dev Represents a single Redelegation entry.
+struct RedelegationEntry {
+ int64 creationHeight;
+ int64 completionTime;
+ uint256 initialBalance;
+ uint256 sharesDst; // TODO: decimal
+}
+
+/// @dev Represents the output of the Redelegation query.
+struct RedelegationOutput {
+ string delegatorAddress;
+ string validatorSrcAddress;
+ string validatorDstAddress;
+ RedelegationEntry[] entries;
+}
+
+/// @dev Represents a single entry of an unbonding delegation.
+struct UnbondingDelegationEntry {
+ int64 creationHeight;
+ int64 completionTime;
+ uint256 initialBalance;
+ uint256 balance;
+ uint64 unbondingId;
+ int64 unbondingOnHoldRefCount;
+}
+
+/// @dev Represents the output of the UnbondingDelegation query.
+struct UnbondingDelegationOutput {
+ string delegatorAddress;
+ string validatorAddress;
+ UnbondingDelegationEntry[] entries;
+}
+
+/// @dev The status of the validator.
+enum BondStatus {
+ Unspecified,
+ Unbonded,
+ Unbonding,
+ Bonded
+}
+
+/// @author Evmos Team
+/// @title Staking Precompiled Contract
+/// @dev The interface through which solidity contracts will interact with staking.
+/// We follow this same interface including four-byte function selectors, in the precompile that
+/// wraps the pallet.
+/// @custom:address 0x0000000000000000000000000000000000000800
+interface StakingI is authorization.AuthorizationI {
+ /// @dev Defines a method for creating a new validator.
+ /// @param description The initial description
+ /// @param commissionRates The initial commissionRates
+ /// @param minSelfDelegation The validator's self declared minimum self delegation
+ /// @param validatorAddress The validator address
+ /// @param pubkey The consensus public key of the validator
+ /// @param value The amount of the coin to be self delegated to the validator
+ /// @return success Whether or not the create validator was successful
+ function createValidator(
+ Description calldata description,
+ CommissionRates calldata commissionRates,
+ uint256 minSelfDelegation,
+ address validatorAddress,
+ string memory pubkey,
+ uint256 value
+ ) external returns (bool success);
+
+ /// @dev Defines a method for edit a validator.
+ /// @param description Description parameter to be updated. Use the string "[do-not-modify]"
+ /// as the value of fields that should not be updated.
+ /// @param commissionRate CommissionRate parameter to be updated.
+ /// Use commissionRate = -1 to keep the current value and not update it.
+ /// @param minSelfDelegation MinSelfDelegation parameter to be updated.
+ /// Use minSelfDelegation = -1 to keep the current value and not update it.
+ /// @return success Whether or not edit validator was successful.
+ function editValidator(
+ Description calldata description,
+ address validatorAddress,
+ int256 commissionRate,
+ int256 minSelfDelegation
+ ) external returns (bool success);
+
+ /// @dev Defines a method for performing a delegation of coins from a delegator to a validator.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @param amount The amount of the Coin to be delegated to the validator
+ /// @return success Whether or not the delegate was successful
+ function delegate(
+ address delegatorAddress,
+ string memory validatorAddress,
+ uint256 amount
+ ) external returns (bool success);
+
+ /// @dev Defines a method for performing an undelegation from a delegate and a validator.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @param amount The amount to be undelegated from the validator
+ /// @return completionTime The time when the undelegation is completed
+ function undelegate(
+ address delegatorAddress,
+ string memory validatorAddress,
+ uint256 amount
+ ) external returns (int64 completionTime);
+
+ /// @dev Defines a method for performing a redelegation
+ /// of coins from a delegator and source validator to a destination validator.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorSrcAddress The validator from which the redelegation is initiated
+ /// @param validatorDstAddress The validator to which the redelegation is destined
+ /// @param amount The amount to be redelegated to the validator
+ /// @return completionTime The time when the redelegation is completed
+ function redelegate(
+ address delegatorAddress,
+ string memory validatorSrcAddress,
+ string memory validatorDstAddress,
+ uint256 amount
+ ) external returns (int64 completionTime);
+
+ /// @dev Allows delegators to cancel the unbondingDelegation entry
+ /// and to delegate back to a previous validator.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @param amount The amount of the Coin
+ /// @param creationHeight The height at which the unbonding took place
+ /// @return success Whether or not the unbonding delegation was cancelled
+ function cancelUnbondingDelegation(
+ address delegatorAddress,
+ string memory validatorAddress,
+ uint256 amount,
+ uint256 creationHeight
+ ) external returns (bool success);
+
+ /// @dev Queries the given amount of the bond denomination to a validator.
+ /// @param delegatorAddress The address of the delegator.
+ /// @param validatorAddress The address of the validator.
+ /// @return shares The amount of shares, that the delegator has received.
+ /// @return balance The amount in Coin, that the delegator has delegated to the given validator.
+ function delegation(
+ address delegatorAddress,
+ string memory validatorAddress
+ ) external view returns (uint256 shares, Coin calldata balance);
+
+ /// @dev Returns the delegation shares and coins, that are currently
+ /// unbonding for a given delegator and validator pair.
+ /// @param delegatorAddress The address of the delegator.
+ /// @param validatorAddress The address of the validator.
+ /// @return unbondingDelegation The delegations that are currently unbonding.
+ function unbondingDelegation(
+ address delegatorAddress,
+ string memory validatorAddress
+ )
+ external
+ view
+ returns (UnbondingDelegationOutput calldata unbondingDelegation);
+
+ /// @dev Queries validator info for a given validator address.
+ /// @param validatorAddress The address of the validator.
+ /// @return validator The validator info for the given validator address.
+ function validator(
+ address validatorAddress
+ ) external view returns (Validator calldata validator);
+
+ /// @dev Queries all validators that match the given status.
+ /// @param status Enables to query for validators matching a given status.
+ /// @param pageRequest Defines an optional pagination for the request.
+ function validators(
+ string memory status,
+ PageRequest calldata pageRequest
+ )
+ external
+ view
+ returns (
+ Validator[] calldata validators,
+ PageResponse calldata pageResponse
+ );
+
+ /// @dev Queries all redelegations from a source to a destination validator for a given delegator.
+ /// @param delegatorAddress The address of the delegator.
+ /// @param srcValidatorAddress Defines the validator address to redelegate from.
+ /// @param dstValidatorAddress Defines the validator address to redelegate to.
+ /// @return redelegation The active redelegations for the given delegator, source and destination
+ /// validator combination.
+ function redelegation(
+ address delegatorAddress,
+ string memory srcValidatorAddress,
+ string memory dstValidatorAddress
+ ) external view returns (RedelegationOutput calldata redelegation);
+
+ /// @dev Queries all redelegations based on the specified criteria:
+ /// for a given delegator and/or origin validator address
+ /// and/or destination validator address
+ /// in a specified pagination manner.
+ /// @param delegatorAddress The address of the delegator as string (can be a zero address).
+ /// @param srcValidatorAddress Defines the validator address to redelegate from (can be empty string).
+ /// @param dstValidatorAddress Defines the validator address to redelegate to (can be empty string).
+ /// @param pageRequest Defines an optional pagination for the request.
+ /// @return response Holds the redelegations for the given delegator, source and destination validator combination.
+ function redelegations(
+ address delegatorAddress,
+ string memory srcValidatorAddress,
+ string memory dstValidatorAddress,
+ PageRequest calldata pageRequest
+ )
+ external
+ view
+ returns (
+ RedelegationResponse[] calldata response,
+ PageResponse calldata pageResponse
+ );
+
+ /// @dev CreateValidator defines an Event emitted when a create a new validator.
+ /// @param validatorAddress The address of the validator
+ /// @param value The amount of coin being self delegated
+ event CreateValidator(address indexed validatorAddress, uint256 value);
+
+ /// @dev EditValidator defines an Event emitted when edit a validator.
+ /// @param validatorAddress The address of the validator.
+ /// @param commissionRate The commission rate.
+ /// @param minSelfDelegation The min self delegation.
+ event EditValidator(
+ address indexed validatorAddress,
+ int256 commissionRate,
+ int256 minSelfDelegation
+ );
+
+ /// @dev Delegate defines an Event emitted when a given amount of tokens are delegated from the
+ /// delegator address to the validator address.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @param amount The amount of Coin being delegated
+ /// @param newShares The new delegation shares being held
+ event Delegate(
+ address indexed delegatorAddress,
+ address indexed validatorAddress,
+ uint256 amount,
+ uint256 newShares
+ );
+
+ /// @dev Unbond defines an Event emitted when a given amount of tokens are unbonded from the
+ /// validator address to the delegator address.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @param amount The amount of Coin being unbonded
+ /// @param completionTime The time at which the unbonding is completed
+ event Unbond(
+ address indexed delegatorAddress,
+ address indexed validatorAddress,
+ uint256 amount,
+ uint256 completionTime
+ );
+
+ /// @dev Redelegate defines an Event emitted when a given amount of tokens are redelegated from
+ /// the source validator address to the destination validator address.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorSrcAddress The address of the validator from which the delegation is retracted
+ /// @param validatorDstAddress The address of the validator to which the delegation is directed
+ /// @param amount The amount of Coin being redelegated
+ /// @param completionTime The time at which the redelegation is completed
+ event Redelegate(
+ address indexed delegatorAddress,
+ address indexed validatorSrcAddress,
+ address indexed validatorDstAddress,
+ uint256 amount,
+ uint256 completionTime
+ );
+
+ /// @dev CancelUnbondingDelegation defines an Event emitted when a given amount of tokens
+ /// that are in the process of unbonding from the validator address are bonded again.
+ /// @param delegatorAddress The address of the delegator
+ /// @param validatorAddress The address of the validator
+ /// @param amount The amount of Coin that was in the unbonding process which is to be canceled
+ /// @param creationHeight The block height at which the unbonding of a delegation was initiated
+ event CancelUnbondingDelegation(
+ address indexed delegatorAddress,
+ address indexed validatorAddress,
+ uint256 amount,
+ uint256 creationHeight
+ );
+}
diff --git a/precompiles/staking/abi.json b/precompiles/staking/abi.json
new file mode 100644
index 00000000..aecfb48a
--- /dev/null
+++ b/precompiles/staking/abi.json
@@ -0,0 +1,1243 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "StakingI",
+ "sourceName": "solidity/precompiles/staking/StakingI.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "granter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "string[]",
+ "name": "methods",
+ "type": "string[]"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256[]",
+ "name": "values",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "AllowanceChange",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "granter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "string[]",
+ "name": "methods",
+ "type": "string[]"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "creationHeight",
+ "type": "uint256"
+ }
+ ],
+ "name": "CancelUnbondingDelegation",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "CreateValidator",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "newShares",
+ "type": "uint256"
+ }
+ ],
+ "name": "Delegate",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "int256",
+ "name": "commissionRate",
+ "type": "int256"
+ },
+ {
+ "indexed": false,
+ "internalType": "int256",
+ "name": "minSelfDelegation",
+ "type": "int256"
+ }
+ ],
+ "name": "EditValidator",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorSrcAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorDstAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "completionTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "Redelegate",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "granter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "string[]",
+ "name": "methods",
+ "type": "string[]"
+ }
+ ],
+ "name": "Revocation",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "completionTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "Unbond",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "granter",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "method",
+ "type": "string"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "remaining",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string[]",
+ "name": "methods",
+ "type": "string[]"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "creationHeight",
+ "type": "uint256"
+ }
+ ],
+ "name": "cancelUnbondingDelegation",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "moniker",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "identity",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "website",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "securityContact",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "details",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct Description",
+ "name": "description",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "rate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxRate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxChangeRate",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct CommissionRates",
+ "name": "commissionRates",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minSelfDelegation",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "pubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "createValidator",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string[]",
+ "name": "methods",
+ "type": "string[]"
+ }
+ ],
+ "name": "decreaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "delegate",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "delegation",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "shares",
+ "type": "uint256"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin",
+ "name": "balance",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "moniker",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "identity",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "website",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "securityContact",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "details",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct Description",
+ "name": "description",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "int256",
+ "name": "commissionRate",
+ "type": "int256"
+ },
+ {
+ "internalType": "int256",
+ "name": "minSelfDelegation",
+ "type": "int256"
+ }
+ ],
+ "name": "editValidator",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string[]",
+ "name": "methods",
+ "type": "string[]"
+ }
+ ],
+ "name": "increaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorSrcAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorDstAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "redelegate",
+ "outputs": [
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "srcValidatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "dstValidatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "redelegation",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "delegatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorSrcAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorDstAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sharesDst",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntry[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct RedelegationOutput",
+ "name": "redelegation",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "srcValidatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "dstValidatorAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "redelegations",
+ "outputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "delegatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorSrcAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorDstAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sharesDst",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntry[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct Redelegation",
+ "name": "redelegation",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sharesDst",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntry",
+ "name": "redelegationEntry",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint256",
+ "name": "balance",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntryResponse[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct RedelegationResponse[]",
+ "name": "response",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "pageResponse",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "string[]",
+ "name": "methods",
+ "type": "string[]"
+ }
+ ],
+ "name": "revoke",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "revoked",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "unbondingDelegation",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "delegatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "balance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint64",
+ "name": "unbondingId",
+ "type": "uint64"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingOnHoldRefCount",
+ "type": "int64"
+ }
+ ],
+ "internalType": "struct UnbondingDelegationEntry[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct UnbondingDelegationOutput",
+ "name": "unbondingDelegation",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "undelegate",
+ "outputs": [
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ }
+ ],
+ "name": "validator",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "operatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "consensusPubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "jailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "enum BondStatus",
+ "name": "status",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokens",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatorShares",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "description",
+ "type": "string"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "commission",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minSelfDelegation",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Validator",
+ "name": "validator",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "status",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "validators",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "operatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "consensusPubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "jailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "enum BondStatus",
+ "name": "status",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokens",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatorShares",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "description",
+ "type": "string"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "commission",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minSelfDelegation",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Validator[]",
+ "name": "validators",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "pageResponse",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x",
+ "deployedBytecode": "0x",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/staking/approve.go b/precompiles/staking/approve.go
new file mode 100644
index 00000000..618d514a
--- /dev/null
+++ b/precompiles/staking/approve.go
@@ -0,0 +1,355 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package staking
+
+import (
+ "fmt"
+ "time"
+
+ errorsmod "cosmossdk.io/errors"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+var (
+ // DelegateMsg defines the authorization type for MsgDelegate
+ DelegateMsg = sdk.MsgTypeURL(&stakingtypes.MsgDelegate{})
+ // UndelegateMsg defines the authorization type for MsgUndelegate
+ UndelegateMsg = sdk.MsgTypeURL(&stakingtypes.MsgUndelegate{})
+ // RedelegateMsg defines the authorization type for MsgRedelegate
+ RedelegateMsg = sdk.MsgTypeURL(&stakingtypes.MsgBeginRedelegate{})
+ // CancelUnbondingDelegationMsg defines the authorization type for MsgCancelUnbondingDelegation
+ CancelUnbondingDelegationMsg = sdk.MsgTypeURL(&stakingtypes.MsgCancelUnbondingDelegation{})
+)
+
+// Approve sets amount as the allowance of a grantee over the caller’s tokens.
+// Returns a boolean value indicating whether the operation succeeded.
+func (p Precompile) Approve(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, coin, typeURLs, err := authorization.CheckApprovalArgs(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ for _, typeURL := range typeURLs {
+ switch typeURL {
+ case DelegateMsg, UndelegateMsg, RedelegateMsg, CancelUnbondingDelegationMsg:
+ authzType, err := convertMsgToAuthz(typeURL)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, fmt.Sprintf(cmn.ErrInvalidMsgType, "staking", typeURL))
+ }
+ if err = p.grantOrDeleteStakingAuthz(ctx, grantee, origin, coin, authzType); err != nil {
+ return nil, err
+ }
+ default:
+ // TODO: do we need to return an error here or just no-op?
+ // Implications of returning an error could be that we approve some parts of the txs but not all
+ return nil, fmt.Errorf(cmn.ErrInvalidMsgType, "staking", typeURL)
+ }
+ }
+
+ // TODO: do we want to emit one approval for all typeUrls, or one approval for each typeUrl?
+ // NOTE: This might have gas implications as we are emitting a slice of strings
+ if err := p.EmitApprovalEvent(ctx, stateDB, grantee, origin, coin, typeURLs); err != nil {
+ return nil, err
+ }
+ return method.Outputs.Pack(true)
+}
+
+// Revoke removes the authorization grants given in the typeUrls for a given granter to a given grantee.
+// It only works if the origin matches the spender to avoid unauthorized revocations.
+// Works only for staking messages.
+func (p Precompile) Revoke(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, typeURLs, err := authorization.CheckRevokeArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, typeURL := range typeURLs {
+ switch typeURL {
+ case DelegateMsg, UndelegateMsg, RedelegateMsg, CancelUnbondingDelegationMsg:
+ if err = p.AuthzKeeper.DeleteGrant(ctx, grantee.Bytes(), origin.Bytes(), typeURL); err != nil {
+ return nil, err
+ }
+ default:
+ // TODO: do we need to return an error here or just no-op?
+ // Implications of returning an error could be that we approve some parts of the txs but not all
+ return nil, fmt.Errorf(cmn.ErrInvalidMsgType, "staking", typeURL)
+ }
+ }
+
+ // NOTE: Using the new more generic event emitter that was created
+ if err = authorization.EmitRevocationEvent(cmn.EmitEventArgs{
+ Ctx: ctx,
+ StateDB: stateDB,
+ ContractAddr: p.Address(),
+ ContractEvents: p.ABI.Events,
+ EventData: authorization.EventRevocation{
+ Granter: origin,
+ Grantee: grantee,
+ TypeUrls: typeURLs,
+ },
+ }); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// DecreaseAllowance decreases the allowance of grantee over the caller’s tokens by the amount.
+func (p Precompile) DecreaseAllowance(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, coin, typeUrls, err := authorization.CheckApprovalArgs(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ for _, typeURL := range typeUrls {
+ switch typeURL {
+ case DelegateMsg, UndelegateMsg, RedelegateMsg, CancelUnbondingDelegationMsg:
+ authzGrant, expiration, err := authorization.CheckAuthzExists(ctx, p.AuthzKeeper, grantee, origin, typeURL)
+ if err != nil {
+ return nil, err
+ }
+
+ stakeAuthz, ok := authzGrant.(*stakingtypes.StakeAuthorization)
+ if !ok {
+ return nil, errorsmod.Wrapf(authz.ErrUnknownAuthorizationType, "expected: *types.StakeAuthorization, received: %T", authzGrant)
+ }
+
+ if err = p.decreaseAllowance(ctx, grantee, origin, coin, stakeAuthz, expiration); err != nil {
+ return nil, err
+ }
+ default:
+ // TODO: do we need to return an error here or just no-op?
+ // Implications of returning an error could be that we decrease allowance for some parts of the typeUrls but not all
+ return nil, fmt.Errorf(cmn.ErrInvalidMsgType, "staking", typeURL)
+ }
+ }
+
+ if err := p.EmitAllowanceChangeEvent(ctx, stateDB, grantee, origin, typeUrls); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// IncreaseAllowance increases the allowance of grantee over the caller’s tokens by the amount.
+func (p Precompile) IncreaseAllowance(
+ ctx sdk.Context,
+ origin common.Address,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ grantee, coin, typeUrls, err := authorization.CheckApprovalArgs(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ for _, typeURL := range typeUrls {
+ switch typeURL {
+ case DelegateMsg, UndelegateMsg, RedelegateMsg:
+ if err = p.increaseAllowance(ctx, grantee, origin, coin, typeURL); err != nil {
+ return nil, err
+ }
+ default:
+ // TODO: do we need to return an error here or just no-op?
+ // Implications of returning an error could be that we decrease allowance for some parts of the typeUrls but not all
+ return nil, fmt.Errorf(cmn.ErrInvalidMsgType, "staking", typeURL)
+ }
+ }
+ if err := p.EmitAllowanceChangeEvent(ctx, stateDB, grantee, origin, typeUrls); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// grantOrDeleteStakingAuthz grants staking method authorization to the precompiled contract for a spender.
+// If the amount is zero, it deletes the authorization if it exists.
+func (p Precompile) grantOrDeleteStakingAuthz(
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ coin *sdk.Coin,
+ authzType stakingtypes.AuthorizationType,
+) error {
+ // Case 1: coin is nil -> set authorization with no limit
+ if coin == nil || coin.IsNil() {
+ p.Logger(ctx).Debug(
+ "setting authorization without limit",
+ "grantee", grantee.String(),
+ "granter", granter.String(),
+ )
+ return p.createStakingAuthz(ctx, grantee, granter, coin, authzType)
+ }
+
+ // Case 2: coin amount is zero or negative -> delete the authorization
+ if !coin.Amount.IsPositive() {
+ p.Logger(ctx).Debug(
+ "deleting authorization",
+ "grantee", grantee.String(),
+ "granter", granter.String(),
+ )
+ stakingAuthz := stakingtypes.StakeAuthorization{AuthorizationType: authzType}
+ return p.AuthzKeeper.DeleteGrant(ctx, grantee.Bytes(), granter.Bytes(), stakingAuthz.MsgTypeURL())
+ }
+
+ // Case 3: coin amount is non zero -> and not coin is not nil set with custom amount
+ return p.createStakingAuthz(ctx, grantee, granter, coin, authzType)
+}
+
+// createStakingAuthz creates a staking authorization for a spender.
+func (p Precompile) createStakingAuthz(
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ coin *sdk.Coin,
+ authzType stakingtypes.AuthorizationType,
+) error {
+ // Get all available validators and filter out jailed validators
+ validators := make([]sdk.ValAddress, 0)
+ p.stakingKeeper.IterateValidators(
+ ctx, func(_ int64, validator stakingtypes.ValidatorI) (stop bool) {
+ if validator.IsJailed() {
+ return
+ }
+ validators = append(validators, validator.GetOperator())
+ return
+ },
+ )
+ stakingAuthz, err := stakingtypes.NewStakeAuthorization(validators, nil, authzType, coin)
+ if err != nil {
+ return err
+ }
+
+ if err := stakingAuthz.ValidateBasic(); err != nil {
+ return err
+ }
+
+ expiration := ctx.BlockTime().Add(p.ApprovalExpiration).UTC()
+ return p.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), stakingAuthz, &expiration)
+}
+
+// decreaseAllowance decreases the allowance of spender over the caller’s tokens by the amount.
+func (p Precompile) decreaseAllowance(
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ coin *sdk.Coin,
+ stakeAuthz *stakingtypes.StakeAuthorization,
+ expiration *time.Time,
+) error {
+ // If the authorization has no limit, no operation is performed
+ if stakeAuthz.MaxTokens == nil {
+ p.Logger(ctx).Debug("decreaseAllowance called with no limit (stakeAuthz.MaxTokens == nil): no-op")
+ return nil
+ }
+
+ // If the authorization limit is less than the substation amount, return error
+ if stakeAuthz.MaxTokens.Amount.LT(coin.Amount) {
+ return fmt.Errorf(ErrDecreaseAmountTooBig, coin.Amount, stakeAuthz.MaxTokens.Amount)
+ }
+
+ // If amount is less than or equal to the Authorization amount, subtract the amount from the limit
+ if coin.Amount.LTE(stakeAuthz.MaxTokens.Amount) {
+ stakeAuthz.MaxTokens.Amount = stakeAuthz.MaxTokens.Amount.Sub(coin.Amount)
+ }
+
+ return p.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), stakeAuthz, expiration)
+}
+
+// increaseAllowance increases the allowance of spender over the caller’s tokens by the amount.
+func (p Precompile) increaseAllowance(
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ coin *sdk.Coin,
+ msgURL string,
+) error {
+ // Check if the authorization exists for the given spender
+ existingAuthz, expiration, err := authorization.CheckAuthzExists(ctx, p.AuthzKeeper, grantee, granter, msgURL)
+ if err != nil {
+ return err
+ }
+
+ // Cast the authorization to a staking authorization
+ stakeAuthz, ok := existingAuthz.(*stakingtypes.StakeAuthorization)
+ if !ok {
+ return errorsmod.Wrapf(authz.ErrUnknownAuthorizationType, "expected: *types.StakeAuthorization, received: %T", existingAuthz)
+ }
+
+ // If the authorization has no limit, no operation is performed
+ if stakeAuthz.MaxTokens == nil {
+ p.Logger(ctx).Debug("increaseAllowance called with no limit (stakeAuthz.MaxTokens == nil): no-op")
+ return nil
+ }
+
+ // Add the amount to the limit
+ stakeAuthz.MaxTokens.Amount = stakeAuthz.MaxTokens.Amount.Add(coin.Amount)
+
+ return p.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), stakeAuthz, expiration)
+}
+
+// UpdateStakingAuthorization updates the staking grant based on the authz AcceptResponse for the given granter and grantee.
+func (p Precompile) UpdateStakingAuthorization(
+ ctx sdk.Context,
+ grantee, granter common.Address,
+ stakeAuthz *stakingtypes.StakeAuthorization,
+ expiration *time.Time,
+ messageType string,
+ msg sdk.Msg,
+) error {
+ updatedResponse, err := stakeAuthz.Accept(ctx, msg)
+ if err != nil {
+ return err
+ }
+
+ if updatedResponse.Delete {
+ err = p.AuthzKeeper.DeleteGrant(ctx, grantee.Bytes(), granter.Bytes(), messageType)
+ } else {
+ err = p.AuthzKeeper.SaveGrant(ctx, grantee.Bytes(), granter.Bytes(), updatedResponse.Updated, expiration)
+ }
+
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// convertMsgToAuthz converts a msg to an authorization type.
+func convertMsgToAuthz(msg string) (stakingtypes.AuthorizationType, error) {
+ switch msg {
+ case DelegateMsg:
+ return DelegateAuthz, nil
+ case UndelegateMsg:
+ return UndelegateAuthz, nil
+ case RedelegateMsg:
+ return RedelegateAuthz, nil
+ case CancelUnbondingDelegationMsg:
+ return CancelUnbondingDelegationAuthz, nil
+ default:
+ return stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNSPECIFIED, authz.ErrUnknownAuthorizationType.Wrapf("cannot convert msg to authorization type with %T", msg)
+ }
+}
diff --git a/precompiles/staking/approve_test.go b/precompiles/staking/approve_test.go
new file mode 100644
index 00000000..08cfc9aa
--- /dev/null
+++ b/precompiles/staking/approve_test.go
@@ -0,0 +1,727 @@
+package staking_test
+
+import (
+ "fmt"
+ "math/big"
+ "time"
+
+ "cosmossdk.io/math"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ evmosutiltx "github.com/evmos/evmos/v19/testutil/tx"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ sdkauthz "github.com/cosmos/cosmos-sdk/x/authz"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func (s *PrecompileTestSuite) TestApprove() {
+ method := s.precompile.Methods[authorization.ApproveMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(*vm.Contract) []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 0),
+ },
+ {
+ "fail - invalid message type",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ abi.MaxUint256,
+ []string{"invalid"},
+ }
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidMsgType, "staking", "invalid"),
+ },
+ // TODO: enable this test once we check if spender and origin are the same
+ // {
+ // "fail - origin address is the same the spender address",
+ // func(_ *vm.Contract) []interface{} {
+ // return []interface{}{
+ // s.address,
+ // abi.MaxUint256,
+ // []string{"invalid"},
+ // }
+ // },
+ // (data []byte inputArgs []interface{}) {},
+ // 200000,
+ // true,
+ // "is the same as spender",
+ // },
+ {
+ "success - MsgDelegate with unlimited coins",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ abi.MaxUint256,
+ []string{staking.DelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+ authz, expirationTime := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ var coin *sdk.Coin
+ s.Require().Equal(authz.MaxTokens, coin)
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - MsgUndelegate with unlimited coins",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ abi.MaxUint256,
+ []string{staking.UndelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.UndelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ s.Require().Equal(authz.AuthorizationType, staking.UndelegateAuthz)
+ var coin *sdk.Coin
+ s.Require().Equal(authz.MaxTokens, coin)
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - MsgRedelegate with unlimited coins",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ abi.MaxUint256,
+ []string{staking.RedelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.RedelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ s.Require().Equal(authz.AuthorizationType, staking.RedelegateAuthz)
+ var coin *sdk.Coin
+ s.Require().Equal(authz.MaxTokens, coin)
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - All staking methods with certain amount of coins",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ },
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ allAuthz, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, s.address.Bytes(), s.address.Bytes())
+ s.Require().NoError(err)
+ s.Require().Len(allAuthz, 3)
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - remove MsgDelegate authorization",
+ func(*vm.Contract) []interface{} {
+ res, err := s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, []interface{}{s.address, big.NewInt(1), []string{staking.DelegateMsg}})
+ s.Require().NoError(err)
+ s.Require().Equal(res, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+
+ return []interface{}{
+ s.address,
+ big.NewInt(0),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().Nil(authz)
+ s.Require().Nil(expirationTime)
+ },
+ 200000,
+ false,
+ "",
+ },
+ {
+ "success - MsgDelegate with 1 Evmos as limit amount",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - Authorization should only be created for validators that are not jailed",
+ func(_ *vm.Contract) []interface{} {
+ // Commit block (otherwise test logic will not be executed correctly, i.e. somehow unbonding does not take effect)
+ var err error
+ s.ctx, err = evmosutil.Commit(s.ctx, s.app, time.Second, nil)
+ s.Require().NoError(err, "failed to commit block")
+
+ // Jail a validator
+ s.app.StakingKeeper.Jail(s.ctx, sdk.ConsAddress(s.validators[0].GetOperator()))
+
+ // When a delegator redelegates/undelegates from a validator, the validator
+ // switches to Unbonding status.
+ // Thus, validators with this status should be considered for the authorization
+
+ // Unbond another validator
+ amount, err := s.app.StakingKeeper.Unbond(s.ctx, s.address.Bytes(), s.validators[1].GetOperator(), math.LegacyOneDec())
+ s.Require().NoError(err, "expected no error unbonding validator")
+ s.Require().Equal(math.NewInt(1e18), amount, "expected different amount of tokens to be unbonded")
+
+ // Commit block and update time to one year later
+ s.ctx, err = evmosutil.Commit(s.ctx, s.app, time.Hour*24*365, nil)
+ s.Require().NoError(err, "failed to commit block")
+
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+ // Check that the bonded and unbonding validators are included on the authorization
+ s.Require().Len(authz.GetAllowList().Address, 2, "should only be two validators in the allow list")
+ },
+ 1e6,
+ false,
+ "",
+ },
+ {
+ "success - MsgUndelegate with 1 Evmos as limit amount",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{staking.UndelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.UndelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ s.Require().Equal(authz.AuthorizationType, staking.UndelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - MsgRedelegate with 1 Evmos as limit amount",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{staking.RedelegateMsg},
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.RedelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ },
+ 20000,
+ false,
+ "",
+ },
+ {
+ "success - MsgRedelegate, MsgUndelegate and MsgDelegate with 1 Evmos as limit amount",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{
+ staking.RedelegateMsg,
+ staking.UndelegateMsg,
+ staking.DelegateMsg,
+ },
+ }
+ },
+ func(data []byte, _ []interface{}) {
+ s.Require().Equal(data, cmn.TrueValue)
+
+ authz, expirationTime := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+
+ authz, expirationTime = s.CheckAuthorization(staking.UndelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+
+ s.Require().Equal(authz.AuthorizationType, staking.UndelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+
+ authz, expirationTime = s.CheckAuthorization(staking.RedelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().NotNil(expirationTime)
+
+ s.Require().Equal(authz.AuthorizationType, staking.RedelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+
+ // TODO: Bug here it returns 3 REDELEGATE authorizations
+ allAuthz, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, s.address.Bytes(), s.address.Bytes())
+ s.Require().NoError(err)
+ s.Require().Len(allAuthz, 3)
+ },
+ 20000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ args := tc.malleate(contract)
+ bz, err := s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDecreaseAllowance() {
+ method := s.precompile.Methods[authorization.DecreaseAllowanceMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(_ *vm.Contract) []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 0),
+ },
+ //// TODO: enable this once we check origin is not the spender
+ // {
+ // "fail - origin address is the spender address",
+ // func(_ *vm.Contract) []interface{} {
+ // return []interface{}{
+ // s.address,
+ // abi.MaxUint256,
+ // []string{staking.DelegateMsg},
+ // }
+ // },
+ // (data []byte inputArgs []interface{}) {},
+ // 200000,
+ // true,
+ // "is the same as spender",
+ // },
+ {
+ "fail - delegate authorization does not exists",
+ func(_ *vm.Contract) []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(15000),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func([]byte, []interface{}) {
+ },
+ 200000,
+ true,
+ "authorization to /cosmos.staking.v1beta1.MsgDelegate",
+ },
+ {
+ "fail - delegate authorization is a generic Authorization",
+ func(_ *vm.Contract) []interface{} {
+ authz := sdkauthz.NewGenericAuthorization(staking.DelegateMsg)
+ exp := time.Now().Add(time.Hour)
+ err := s.app.AuthzKeeper.SaveGrant(s.ctx, s.address.Bytes(), s.address.Bytes(), authz, &exp)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ big.NewInt(15000),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func([]byte, []interface{}) {
+ },
+ 200000,
+ true,
+ sdkauthz.ErrUnknownAuthorizationType.Error(),
+ },
+ {
+ "fail - decrease allowance amount is greater than the authorization limit",
+ func(*vm.Contract) []interface{} {
+ approveArgs := []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{staking.DelegateMsg},
+ }
+ resp, err := s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, approveArgs)
+ s.Require().NoError(err)
+ s.Require().Equal(resp, cmn.TrueValue)
+
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+
+ return []interface{}{
+ s.address,
+ big.NewInt(2e18),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ "amount by which the allowance should be decreased is greater than the authorization limit",
+ },
+ {
+ "success - decrease delegate authorization allowance by 1 Evmos",
+ func(_ *vm.Contract) []interface{} {
+ s.ApproveAndCheckAuthz(method, staking.DelegateMsg, big.NewInt(2e18))
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func([]byte, []interface{}) {
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)})
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ args := tc.malleate(contract)
+ bz, err := s.precompile.DecreaseAllowance(s.ctx, s.address, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestIncreaseAllowance() {
+ method := s.precompile.Methods[authorization.IncreaseAllowanceMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ gas uint64
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 0),
+ },
+ // TODO: enable this once we check origin is not the same as spender
+ // {
+ // "fail - origin address is the spender address",
+ // func(_ *vm.Contract) []interface{} {
+ // return []interface{}{
+ // s.address,
+ // abi.MaxUint256,
+ // []string{staking.DelegateMsg},
+ // }
+ // },
+ // (data []byte inputArgs []interface{}) {},
+ // 200000,
+ // true,
+ // "is the same as spender",
+ // },
+ {
+ "fail - delegate authorization does not exists",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(15000),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func([]byte, []interface{}) {
+ },
+ 200000,
+ true,
+ "authorization to /cosmos.staking.v1beta1.MsgDelegate",
+ },
+ {
+ "success - no-op, allowance amount is already set to the maximum value",
+ func() []interface{} {
+ approveArgs := []interface{}{
+ s.address,
+ abi.MaxUint256,
+ []string{staking.DelegateMsg},
+ }
+ resp, err := s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, approveArgs)
+ s.Require().NoError(err)
+ s.Require().Equal(resp, cmn.TrueValue)
+
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ var coin *sdk.Coin
+ s.Require().Equal(authz.MaxTokens, coin)
+
+ return []interface{}{
+ s.address,
+ big.NewInt(2e18),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func([]byte, []interface{}) {},
+ 200000,
+ false,
+ "",
+ },
+ {
+ "success - increase delegate authorization allowance by 1 Evmos",
+ func() []interface{} {
+ s.ApproveAndCheckAuthz(method, staking.DelegateMsg, big.NewInt(1e18))
+ return []interface{}{
+ s.address,
+ big.NewInt(1e18),
+ []string{staking.DelegateMsg},
+ }
+ },
+ func([]byte, []interface{}) {
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(authz)
+ s.Require().Equal(authz.AuthorizationType, staking.DelegateAuthz)
+ s.Require().Equal(authz.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(2e18)})
+ },
+ 200000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ args := tc.malleate()
+ bz, err := s.precompile.IncreaseAllowance(s.ctx, s.address, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRevoke() {
+ method := s.precompile.Methods[authorization.RevokeMethod]
+ granteeAddr := evmosutiltx.GenerateAddress()
+ granterAddr := s.address
+ createdAuthz := staking.DelegateAuthz
+ approvedCoin := &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)}
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(data []byte, inputArgs []interface{})
+ expError bool
+ errContains string
+ }{
+ {
+ name: "fail - empty input args",
+ malleate: func() []interface{} {
+ return []interface{}{}
+ },
+ expError: true,
+ errContains: fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ name: "fail - authorization does not exist",
+ malleate: func() []interface{} {
+ return []interface{}{
+ granteeAddr,
+ []string{staking.UndelegateMsg},
+ }
+ },
+ postCheck: func([]byte, []interface{}) {
+ // expect authorization to still be there
+ authz, _ := s.CheckAuthorization(createdAuthz, granteeAddr, granterAddr)
+ s.Require().NotNil(authz)
+ },
+ expError: true,
+ errContains: "authorization not found",
+ },
+ {
+ name: "pass - authorization revoked",
+ malleate: func() []interface{} {
+ return []interface{}{
+ granteeAddr,
+ []string{staking.DelegateMsg},
+ }
+ },
+ postCheck: func([]byte, []interface{}) {
+ // expect authorization to be removed
+ authz, _ := s.CheckAuthorization(createdAuthz, granteeAddr, granterAddr)
+ s.Require().Nil(authz, "expected authorization to be removed")
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ // Create a delegate authorization
+ validators := s.app.StakingKeeper.GetLastValidators(s.ctx)
+ valAddrs := make([]sdk.ValAddress, len(validators))
+ for i, val := range validators {
+ valAddrs[i] = val.GetOperator()
+ }
+ delegationAuthz, err := stakingtypes.NewStakeAuthorization(
+ valAddrs,
+ nil,
+ createdAuthz,
+ approvedCoin,
+ )
+ s.Require().NoError(err)
+
+ expiration := s.ctx.BlockTime().Add(time.Hour * 24 * 365).UTC()
+ err = s.app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr.Bytes(), granterAddr.Bytes(), delegationAuthz, &expiration)
+ s.Require().NoError(err, "failed to save authorization")
+ authz, _ := s.CheckAuthorization(createdAuthz, granteeAddr, granterAddr)
+ s.Require().NotNil(authz, "expected authorization to be set")
+
+ args := tc.malleate()
+ bz, err := s.precompile.Revoke(s.ctx, granterAddr, s.stateDB, &method, args)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz, args)
+ }
+ })
+ }
+}
diff --git a/precompiles/staking/errors.go b/precompiles/staking/errors.go
new file mode 100644
index 00000000..13fc2c0b
--- /dev/null
+++ b/precompiles/staking/errors.go
@@ -0,0 +1,17 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package staking
+
+const (
+ // ErrDecreaseAmountTooBig is raised when the amount by which the allowance should be decreased is greater
+ // than the authorization limit.
+ ErrDecreaseAmountTooBig = "amount by which the allowance should be decreased is greater than the authorization limit: %s > %s"
+ // ErrDifferentOriginFromDelegator is raised when the origin address is not the same as the delegator address.
+ ErrDifferentOriginFromDelegator = "origin address %s is not the same as delegator address %s"
+ // ErrNoDelegationFound is raised when no delegation is found for the given delegator and validator addresses.
+ ErrNoDelegationFound = "delegation with delegator %s not found for validator %s"
+ // ErrDifferentOriginFromValidator is raised when the origin address is not the same as the validator address.
+ ErrDifferentOriginFromValidator = "origin address %s is not the same as validator operator address %s"
+ // ErrCannotCallFromContract is raised when a function cannot be called from a smart contract.
+ ErrCannotCallFromContract = "this method can only be called directly to the precompile, not from a smart contract"
+)
diff --git a/precompiles/staking/events.go b/precompiles/staking/events.go
new file mode 100644
index 00000000..f1c3dfba
--- /dev/null
+++ b/precompiles/staking/events.go
@@ -0,0 +1,363 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package staking
+
+import (
+ "bytes"
+ "math/big"
+ "reflect"
+
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // EventTypeCreateValidator defines the event type for the staking CreateValidator transaction.
+ EventTypeCreateValidator = "CreateValidator"
+ // EventTypeEditValidator defines the event type for the staking EditValidator transaction.
+ EventTypeEditValidator = "EditValidator"
+ // EventTypeDelegate defines the event type for the staking Delegate transaction.
+ EventTypeDelegate = "Delegate"
+ // EventTypeUnbond defines the event type for the staking Undelegate transaction.
+ EventTypeUnbond = "Unbond"
+ // EventTypeRedelegate defines the event type for the staking Redelegate transaction.
+ EventTypeRedelegate = "Redelegate"
+ // EventTypeCancelUnbondingDelegation defines the event type for the staking CancelUnbondingDelegation transaction.
+ EventTypeCancelUnbondingDelegation = "CancelUnbondingDelegation"
+)
+
+// EmitApprovalEvent creates a new approval event emitted on an Approve, IncreaseAllowance and DecreaseAllowance transactions.
+func (p Precompile) EmitApprovalEvent(ctx sdk.Context, stateDB vm.StateDB, grantee, granter common.Address, coin *sdk.Coin, typeUrls []string) error {
+ // Prepare the event topics
+ event := p.ABI.Events[authorization.EventTypeApproval]
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(grantee)
+ if err != nil {
+ return err
+ }
+
+ topics[2], err = cmn.MakeTopic(granter)
+ if err != nil {
+ return err
+ }
+
+ // Check if the coin is set to infinite
+ value := abi.MaxUint256
+ if coin != nil {
+ value = coin.Amount.BigInt()
+ }
+
+ // Pack the arguments to be used as the Data field
+ arguments := abi.Arguments{event.Inputs[2], event.Inputs[3]}
+ packed, err := arguments.Pack(typeUrls, value)
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitAllowanceChangeEvent creates a new allowance change event emitted on an IncreaseAllowance and DecreaseAllowance transactions.
+func (p Precompile) EmitAllowanceChangeEvent(ctx sdk.Context, stateDB vm.StateDB, grantee, granter common.Address, typeUrls []string) error {
+ // Prepare the event topics
+ event := p.ABI.Events[authorization.EventTypeAllowanceChange]
+ topics := make([]common.Hash, 3)
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(grantee)
+ if err != nil {
+ return err
+ }
+
+ topics[2], err = cmn.MakeTopic(granter)
+ if err != nil {
+ return err
+ }
+
+ newValues := make([]*big.Int, len(typeUrls))
+ for i, msgURL := range typeUrls {
+ // Not including expiration and convert check because we have already checked it in the previous call
+ msgAuthz, _ := p.AuthzKeeper.GetAuthorization(ctx, grantee.Bytes(), granter.Bytes(), msgURL)
+ stakeAuthz, _ := msgAuthz.(*stakingtypes.StakeAuthorization)
+ if stakeAuthz.MaxTokens == nil {
+ newValues[i] = abi.MaxUint256
+ } else {
+ newValues[i] = stakeAuthz.MaxTokens.Amount.BigInt()
+ }
+ }
+
+ // Pack the arguments to be used as the Data field
+ arguments := abi.Arguments{event.Inputs[2], event.Inputs[3]}
+ packed, err := arguments.Pack(typeUrls, newValues)
+ if err != nil {
+ return err
+ }
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: packed,
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitCreateValidatorEvent creates a new create validator event emitted on a CreateValidator transaction.
+func (p Precompile) EmitCreateValidatorEvent(ctx sdk.Context, stateDB vm.StateDB, msg *stakingtypes.MsgCreateValidator, validatorAddr common.Address) error {
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeCreateValidator]
+
+ topics, err := p.createEditValidatorTxTopics(2, event, validatorAddr)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(msg.Value.Amount.BigInt())))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitEditValidatorEvent creates a new edit validator event emitted on a EditValidator transaction.
+func (p Precompile) EmitEditValidatorEvent(ctx sdk.Context, stateDB vm.StateDB, msg *stakingtypes.MsgEditValidator, validatorAddr common.Address) error {
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeEditValidator]
+
+ topics, err := p.createEditValidatorTxTopics(2, event, validatorAddr)
+ if err != nil {
+ return err
+ }
+
+ commissionRate := big.NewInt(DoNotModifyCommissionRate)
+ if msg.CommissionRate != nil {
+ commissionRate = msg.CommissionRate.BigInt()
+ }
+
+ minSelfDelegation := big.NewInt(DoNotModifyMinSelfDelegation)
+ if msg.MinSelfDelegation != nil {
+ minSelfDelegation = msg.MinSelfDelegation.BigInt()
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(commissionRate)))
+ b.Write(cmn.PackNum(reflect.ValueOf(minSelfDelegation)))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitDelegateEvent creates a new delegate event emitted on a Delegate transaction.
+func (p Precompile) EmitDelegateEvent(ctx sdk.Context, stateDB vm.StateDB, msg *stakingtypes.MsgDelegate, delegatorAddr common.Address) error {
+ valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
+ if err != nil {
+ return err
+ }
+
+ // Get the validator to estimate the new shares delegated
+ // NOTE: At this point the validator has already been checked, so no need to check again
+ validator, _ := p.stakingKeeper.GetValidator(ctx, valAddr)
+
+ // Get only the new shares based on the delegation amount
+ newShares, err := validator.SharesFromTokens(msg.Amount.Amount)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeDelegate]
+ topics, err := p.createStakingTxTopics(3, event, delegatorAddr, common.BytesToAddress(valAddr.Bytes()))
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(msg.Amount.Amount.BigInt())))
+ b.Write(cmn.PackNum(reflect.ValueOf(newShares.BigInt())))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitUnbondEvent creates a new unbond event emitted on an Undelegate transaction.
+func (p Precompile) EmitUnbondEvent(ctx sdk.Context, stateDB vm.StateDB, msg *stakingtypes.MsgUndelegate, delegatorAddr common.Address, completionTime int64) error {
+ valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeUnbond]
+ topics, err := p.createStakingTxTopics(3, event, delegatorAddr, common.BytesToAddress(valAddr.Bytes()))
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(msg.Amount.Amount.BigInt())))
+ b.Write(cmn.PackNum(reflect.ValueOf(big.NewInt(completionTime))))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitRedelegateEvent creates a new redelegate event emitted on a Redelegate transaction.
+func (p Precompile) EmitRedelegateEvent(ctx sdk.Context, stateDB vm.StateDB, msg *stakingtypes.MsgBeginRedelegate, delegatorAddr common.Address, completionTime int64) error {
+ valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddress)
+ if err != nil {
+ return err
+ }
+
+ valDstAddr, err := sdk.ValAddressFromBech32(msg.ValidatorDstAddress)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeRedelegate]
+ topics, err := p.createStakingTxTopics(4, event, delegatorAddr, common.BytesToAddress(valSrcAddr.Bytes()))
+ if err != nil {
+ return err
+ }
+
+ topics[3], err = cmn.MakeTopic(common.BytesToAddress(valDstAddr.Bytes()))
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(msg.Amount.Amount.BigInt())))
+ b.Write(cmn.PackNum(reflect.ValueOf(big.NewInt(completionTime))))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// EmitCancelUnbondingDelegationEvent creates a new cancel unbonding delegation event emitted on a CancelUnbondingDelegation transaction.
+func (p Precompile) EmitCancelUnbondingDelegationEvent(ctx sdk.Context, stateDB vm.StateDB, msg *stakingtypes.MsgCancelUnbondingDelegation, delegatorAddr common.Address) error {
+ valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event topics
+ event := p.ABI.Events[EventTypeCancelUnbondingDelegation]
+ topics, err := p.createStakingTxTopics(3, event, delegatorAddr, common.BytesToAddress(valAddr.Bytes()))
+ if err != nil {
+ return err
+ }
+
+ // Prepare the event data
+ var b bytes.Buffer
+ b.Write(cmn.PackNum(reflect.ValueOf(msg.Amount.Amount.BigInt())))
+ b.Write(cmn.PackNum(reflect.ValueOf(big.NewInt(msg.CreationHeight))))
+
+ stateDB.AddLog(ðtypes.Log{
+ Address: p.Address(),
+ Topics: topics,
+ Data: b.Bytes(),
+ BlockNumber: uint64(ctx.BlockHeight()),
+ })
+
+ return nil
+}
+
+// createStakingTxTopics creates the topics for staking transactions Delegate, Undelegate, Redelegate and CancelUnbondingDelegation.
+func (p Precompile) createStakingTxTopics(topicsLen uint64, event abi.Event, delegatorAddr common.Address, validatorAddr common.Address) ([]common.Hash, error) {
+ topics := make([]common.Hash, topicsLen)
+ // NOTE: If your solidity event contains indexed event types, then they become a topic rather than part of the data property of the log.
+ // In solidity you may only have up to 4 topics but only 3 indexed event types. The first topic is always the signature of the event.
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(delegatorAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ topics[2], err = cmn.MakeTopic(validatorAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ return topics, nil
+}
+
+// createEditValidatorTxTopics creates the topics for staking transactions CreateValidator and EditValidator.
+func (p Precompile) createEditValidatorTxTopics(topicsLen uint64, event abi.Event, validatorAddr common.Address) ([]common.Hash, error) {
+ topics := make([]common.Hash, topicsLen)
+ // NOTE: If your solidity event contains indexed event types, then they become a topic rather than part of the data property of the log.
+ // In solidity you may only have up to 4 topics but only 3 indexed event types. The first topic is always the signature of the event.
+
+ // The first topic is always the signature of the event.
+ topics[0] = event.ID
+
+ var err error
+ topics[1], err = cmn.MakeTopic(validatorAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ return topics, nil
+}
diff --git a/precompiles/staking/events_test.go b/precompiles/staking/events_test.go
new file mode 100644
index 00000000..1da1e789
--- /dev/null
+++ b/precompiles/staking/events_test.go
@@ -0,0 +1,652 @@
+package staking_test
+
+import (
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func (s *PrecompileTestSuite) TestApprovalEvent() {
+ method := s.precompile.Methods[authorization.ApproveMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - all four methods are present in the emitted event",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ abi.MaxUint256,
+ []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ staking.CancelUnbondingDelegationMsg,
+ },
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[authorization.EventTypeApproval]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var approvalEvent authorization.EventApproval
+ err := cmn.UnpackLog(s.precompile.ABI, &approvalEvent, authorization.EventTypeApproval, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, approvalEvent.Grantee)
+ s.Require().Equal(s.address, approvalEvent.Granter)
+ s.Require().Equal(abi.MaxUint256, approvalEvent.Value)
+ s.Require().Equal(4, len(approvalEvent.Methods))
+ s.Require().Equal(staking.DelegateMsg, approvalEvent.Methods[0])
+ s.Require().Equal(staking.UndelegateMsg, approvalEvent.Methods[1])
+ s.Require().Equal(staking.RedelegateMsg, approvalEvent.Methods[2])
+ s.Require().Equal(staking.CancelUnbondingDelegationMsg, approvalEvent.Methods[3])
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ _, err = s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestIncreaseAllowanceEvent() {
+ approvalMethod := s.precompile.Methods[authorization.ApproveMethod]
+ method := s.precompile.Methods[authorization.IncreaseAllowanceMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - increased allowance for all 3 methods by 1 evmos",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1000000000000000000),
+ []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ },
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[1]
+ methods := []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ }
+ amounts := []*big.Int{
+ big.NewInt(2000000000000000000),
+ big.NewInt(2000000000000000000),
+ big.NewInt(2000000000000000000),
+ }
+ s.CheckAllowanceChangeEvent(log, methods, amounts)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ // Approve first with 1 evmos
+ _, err = s.precompile.Approve(s.ctx, s.address, s.stateDB, &approvalMethod, tc.malleate())
+ s.Require().NoError(err)
+
+ // Increase allowance after approval
+ _, err = s.precompile.IncreaseAllowance(s.ctx, s.address, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDecreaseAllowanceEvent() {
+ approvalMethod := s.precompile.Methods[authorization.ApproveMethod]
+ method := s.precompile.Methods[authorization.DecreaseAllowanceMethod]
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - decreased allowance for all 3 methods by 1 evmos",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ big.NewInt(1000000000000000000),
+ []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ },
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[1]
+ methods := []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ }
+ amounts := []*big.Int{
+ big.NewInt(1000000000000000000),
+ big.NewInt(1000000000000000000),
+ big.NewInt(1000000000000000000),
+ }
+ s.CheckAllowanceChangeEvent(log, methods, amounts)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ // Approve first with 2 evmos
+ args := []interface{}{
+ s.address,
+ big.NewInt(2000000000000000000),
+ []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ },
+ }
+ _, err = s.precompile.Approve(s.ctx, s.address, s.stateDB, &approvalMethod, args)
+ s.Require().NoError(err)
+
+ // Decrease allowance after approval
+ _, err = s.precompile.DecreaseAllowance(s.ctx, s.address, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestCreateValidatorEvent() {
+ var (
+ delegationValue = big.NewInt(1205000000000000000)
+ method = s.precompile.Methods[staking.CreateValidatorMethod]
+ pubkey = "nfJ0axJC9dhta1MAE1EBFaVdxxkYzxYrBaHuJVjG//M="
+ )
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ name: "success - the correct event is emitted",
+ malleate: func() []interface{} {
+ return []interface{}{
+ staking.Description{
+ Moniker: "node0",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ },
+ staking.Commission{
+ Rate: math.LegacyOneDec().BigInt(),
+ MaxRate: math.LegacyOneDec().BigInt(),
+ MaxChangeRate: math.LegacyOneDec().BigInt(),
+ },
+ big.NewInt(1),
+ s.address,
+ pubkey,
+ delegationValue,
+ }
+ },
+ postCheck: func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeCreateValidator]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var createValidatorEvent staking.EventCreateValidator
+ err := cmn.UnpackLog(s.precompile.ABI, &createValidatorEvent, staking.EventTypeCreateValidator, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, createValidatorEvent.ValidatorAddress)
+ s.Require().Equal(delegationValue, createValidatorEvent.Value)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), 200000)
+ _, err := s.precompile.CreateValidator(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestEditValidatorEvent() {
+ var (
+ valOperAddr common.Address
+ method = s.precompile.Methods[staking.EditValidatorMethod]
+ minSelfDel = big.NewInt(11)
+ commRate = math.LegacyNewDecWithPrec(5, 2).BigInt()
+ )
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ name: "success - the correct event is emitted",
+ malleate: func() []interface{} {
+ return []interface{}{
+ staking.Description{
+ Moniker: "node0-edited",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ },
+ valOperAddr,
+ commRate,
+ minSelfDel,
+ }
+ },
+ postCheck: func() {
+ s.Require().Equal(len(s.stateDB.Logs()), 1)
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeEditValidator]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var editValidatorEvent staking.EventEditValidator
+ err := cmn.UnpackLog(s.precompile.ABI, &editValidatorEvent, staking.EventTypeEditValidator, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(valOperAddr, editValidatorEvent.ValidatorAddress)
+ s.Require().Equal(minSelfDel, editValidatorEvent.MinSelfDelegation)
+ s.Require().Equal(commRate, editValidatorEvent.CommissionRate)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ valOperAddr = common.BytesToAddress(s.validators[0].GetOperator().Bytes())
+
+ contract := vm.NewContract(vm.AccountRef(valOperAddr), s.precompile, big.NewInt(0), 200000)
+ _, err := s.precompile.EditValidator(s.ctx, valOperAddr, contract, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDelegateEvent() {
+ var (
+ delegationAmt = big.NewInt(1500000000000000000)
+ newSharesExp = delegationAmt
+ method = s.precompile.Methods[staking.DelegateMethod]
+ )
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - the correct event is emitted",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ delegationAmt,
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeDelegate]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ optAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ optHexAddr := common.BytesToAddress(optAddr)
+
+ // Check the fully unpacked event matches the one emitted
+ var delegationEvent staking.EventDelegate
+ err = cmn.UnpackLog(s.precompile.ABI, &delegationEvent, staking.EventTypeDelegate, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, delegationEvent.DelegatorAddress)
+ s.Require().Equal(optHexAddr, delegationEvent.ValidatorAddress)
+ s.Require().Equal(delegationAmt, delegationEvent.Amount)
+ s.Require().Equal(newSharesExp, delegationEvent.NewShares)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), 20000)
+ _, err = s.precompile.Delegate(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestUnbondEvent() {
+ method := s.precompile.Methods[staking.UndelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - the correct event is emitted",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ big.NewInt(1000000000000000000),
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeUnbond]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ optAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ optHexAddr := common.BytesToAddress(optAddr)
+
+ // Check the fully unpacked event matches the one emitted
+ var unbondEvent staking.EventUnbond
+ err = cmn.UnpackLog(s.precompile.ABI, &unbondEvent, staking.EventTypeUnbond, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, unbondEvent.DelegatorAddress)
+ s.Require().Equal(optHexAddr, unbondEvent.ValidatorAddress)
+ s.Require().Equal(big.NewInt(1000000000000000000), unbondEvent.Amount)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ err := s.CreateAuthorization(s.address, staking.UndelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), 20000)
+ _, err = s.precompile.Undelegate(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRedelegateEvent() {
+ method := s.precompile.Methods[staking.RedelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - the correct event is emitted",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ s.validators[1].OperatorAddress,
+ big.NewInt(1000000000000000000),
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[0]
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeRedelegate]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ optSrcAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ optSrcHexAddr := common.BytesToAddress(optSrcAddr)
+
+ optDstAddr, err := sdk.ValAddressFromBech32(s.validators[1].OperatorAddress)
+ s.Require().NoError(err)
+ optDstHexAddr := common.BytesToAddress(optDstAddr)
+
+ var redelegateEvent staking.EventRedelegate
+ err = cmn.UnpackLog(s.precompile.ABI, &redelegateEvent, staking.EventTypeRedelegate, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, redelegateEvent.DelegatorAddress)
+ s.Require().Equal(optSrcHexAddr, redelegateEvent.ValidatorSrcAddress)
+ s.Require().Equal(optDstHexAddr, redelegateEvent.ValidatorDstAddress)
+ s.Require().Equal(big.NewInt(1000000000000000000), redelegateEvent.Amount)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ err := s.CreateAuthorization(s.address, staking.RedelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), 20000)
+ _, err = s.precompile.Redelegate(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+ s.Require().NoError(err)
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ tc.postCheck()
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestCancelUnbondingDelegationEvent() {
+ methodCancelUnbonding := s.precompile.Methods[staking.CancelUnbondingDelegationMethod]
+ methodUndelegate := s.precompile.Methods[staking.UndelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(contract *vm.Contract) []interface{}
+ expErr bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - the correct event is emitted",
+ func(contract *vm.Contract) []interface{} {
+ err := s.CreateAuthorization(s.address, staking.UndelegateAuthz, nil)
+ s.Require().NoError(err)
+ undelegateArgs := []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ big.NewInt(1000000000000000000),
+ }
+ _, err = s.precompile.Undelegate(s.ctx, s.address, contract, s.stateDB, &methodUndelegate, undelegateArgs)
+ s.Require().NoError(err)
+
+ return []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ big.NewInt(1000000000000000000),
+ big.NewInt(2),
+ }
+ },
+ false,
+ "",
+ func() {
+ log := s.stateDB.Logs()[1]
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeCancelUnbondingDelegation]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ optAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+ optHexAddr := common.BytesToAddress(optAddr)
+
+ // Check event fields match the ones emitted
+ var cancelUnbondEvent staking.EventCancelUnbonding
+ err = cmn.UnpackLog(s.precompile.ABI, &cancelUnbondEvent, staking.EventTypeCancelUnbondingDelegation, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, cancelUnbondEvent.DelegatorAddress)
+ s.Require().Equal(optHexAddr, cancelUnbondEvent.ValidatorAddress)
+ s.Require().Equal(big.NewInt(1000000000000000000), cancelUnbondEvent.Amount)
+ s.Require().Equal(big.NewInt(2), cancelUnbondEvent.CreationHeight)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+
+ err := s.CreateAuthorization(s.address, staking.CancelUnbondingDelegationAuthz, nil)
+ s.Require().NoError(err)
+
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), 20000)
+ callArgs := tc.malleate(contract)
+ _, err = s.precompile.CancelUnbondingDelegation(s.ctx, s.address, contract, s.stateDB, &methodCancelUnbonding, callArgs)
+ s.Require().NoError(err)
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ tc.postCheck()
+ }
+ })
+ }
+}
diff --git a/precompiles/staking/integration_test.go b/precompiles/staking/integration_test.go
new file mode 100644
index 00000000..809921fd
--- /dev/null
+++ b/precompiles/staking/integration_test.go
@@ -0,0 +1,3866 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package staking_test
+
+import (
+ "fmt"
+ "math/big"
+ "time"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ compiledcontracts "github.com/evmos/evmos/v19/contracts"
+ "github.com/evmos/evmos/v19/crypto/ethsecp256k1"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/distribution"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/precompiles/staking/testdata"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/precompiles/testutil/contracts"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ testutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ vestingtypes "github.com/evmos/evmos/v19/x/vesting/types"
+)
+
+// General variables used for integration tests
+var (
+ // valAddr and valAddr2 are the two validator addresses used for testing
+ valAddr, valAddr2 sdk.ValAddress
+
+ // defaultCallArgs and defaultApproveArgs are the default arguments for calling the smart contract and to
+ // call the approve method specifically.
+ //
+ // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address.
+ defaultCallArgs, defaultApproveArgs contracts.CallArgs
+
+ // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated.
+ defaultLogCheck testutil.LogCheckArgs
+ // passCheck defines the arguments to check if the precompile returns no error
+ passCheck testutil.LogCheckArgs
+ // outOfGasCheck defines the arguments to check if the precompile returns out of gas error
+ outOfGasCheck testutil.LogCheckArgs
+)
+
+var _ = Describe("Calling staking precompile directly", func() {
+ var (
+ // oneE18Coin is a sdk.Coin with an amount of 1e18 in the test suite's bonding denomination
+ oneE18Coin = sdk.NewCoin(s.bondDenom, math.NewInt(1e18))
+ // twoE18Coin is a sdk.Coin with an amount of 2e18 in the test suite's bonding denomination
+ twoE18Coin = sdk.NewCoin(s.bondDenom, math.NewInt(2e18))
+ )
+
+ BeforeEach(func() {
+ s.SetupTest()
+ s.NextBlock()
+
+ valAddr = s.validators[0].GetOperator()
+ valAddr2 = s.validators[1].GetOperator()
+
+ defaultCallArgs = contracts.CallArgs{
+ ContractAddr: s.precompile.Address(),
+ ContractABI: s.precompile.ABI,
+ PrivKey: s.privKey,
+ }
+ defaultApproveArgs = defaultCallArgs.WithMethodName(authorization.ApproveMethod)
+
+ defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.ABI.Events}
+ passCheck = defaultLogCheck.WithExpPass(true)
+ outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error())
+ })
+
+ Describe("when the precompile is not enabled in the EVM params", func() {
+ It("should succeed but not perform delegation", func() {
+ // disable the precompile
+ params := s.app.EvmKeeper.GetParams(s.ctx)
+ var activePrecompiles []string
+ for _, precompile := range params.ActiveStaticPrecompiles {
+ if precompile != s.precompile.Address().String() {
+ activePrecompiles = append(activePrecompiles, precompile)
+ }
+ }
+ params.ActiveStaticPrecompiles = activePrecompiles
+ err := s.app.EvmKeeper.SetParams(s.ctx, params)
+ Expect(err).To(BeNil(), "error while setting params")
+
+ // get the delegation that is available prior to the test
+ prevDelegation, _ := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+
+ // try to call the precompile
+ delegateArgs := defaultCallArgs.
+ WithMethodName(staking.DelegateMethod).
+ WithArgs(
+ s.address, valAddr.String(), big.NewInt(2e18),
+ )
+ // Contract should not be called but the transaction should be successful
+ // This is the expected behavior in Ethereum where there is a contract call
+ // to a non existing contract
+ expectedCheck := defaultLogCheck.
+ WithExpEvents([]string{}...).
+ WithExpPass(true)
+
+ _, _, err = contracts.CallContractAndCheckLogs(
+ s.ctx,
+ s.app,
+ delegateArgs,
+ expectedCheck,
+ )
+ Expect(err).To(BeNil(), "unexpected error while calling the precompile")
+
+ postDelegation, _ := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+ Expect(postDelegation).To(Equal(prevDelegation), "expected delegation to not change")
+ })
+ })
+
+ Describe("Revert transaction", func() {
+ It("should run out of gas if the gas limit is too low", func() {
+ outOfGasArgs := defaultApproveArgs.
+ WithGasLimit(30000).
+ WithArgs(
+ s.precompile.Address(),
+ abi.MaxUint256,
+ []string{staking.DelegateMsg},
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, outOfGasArgs, outOfGasCheck)
+ Expect(err).To(HaveOccurred(), "error while calling precompile")
+ })
+ })
+
+ Describe("Execute approve transaction", func() {
+ // TODO: enable once we check that the spender is not the origin
+ // It("should return error if the origin is the spender", func() {
+ // args := defaultApproveArgs.WithArgs(
+ // s.address,
+ // abi.MaxUint256,
+ // []string{staking.DelegateMsg},
+ // )
+ //
+ // differentOriginCheck := defaultLogCheck.WithErrContains(cmn.ErrDifferentOrigin, s.address, addr)
+ //
+ // _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, args, differentOriginCheck)
+ // Expect(err).To(BeNil(), "error while calling precompile")
+ // })
+
+ It("should return error if the staking method is not supported on the precompile", func() {
+ approveArgs := defaultApproveArgs.WithArgs(
+ s.precompile.Address(), abi.MaxUint256, []string{distribution.DelegationRewardsMethod},
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(
+ cmn.ErrInvalidMsgType, "staking", distribution.DelegationRewardsMethod,
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, approveArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the contract and checking logs")
+ })
+
+ It("should approve the delegate method with the max uint256 value", func() {
+ s.SetupApproval(
+ s.privKey, s.precompile.Address(), abi.MaxUint256, []string{staking.DelegateMsg},
+ )
+
+ s.ExpectAuthorization(staking.DelegateAuthz, s.precompile.Address(), s.address, nil)
+ })
+
+ It("should approve the undelegate method with 1 evmos", func() {
+ s.SetupApproval(
+ s.privKey, s.precompile.Address(), big.NewInt(1e18), []string{staking.UndelegateMsg},
+ )
+
+ s.ExpectAuthorization(staking.UndelegateAuthz, s.precompile.Address(), s.address, &oneE18Coin)
+ })
+
+ It("should approve the redelegate method with 2 evmos", func() {
+ s.SetupApproval(
+ s.privKey, s.precompile.Address(), big.NewInt(2e18), []string{staking.RedelegateMsg},
+ )
+
+ s.ExpectAuthorization(staking.RedelegateAuthz, s.precompile.Address(), s.address, &twoE18Coin)
+ })
+
+ It("should approve the cancel unbonding delegation method with 1 evmos", func() {
+ s.SetupApproval(
+ s.privKey, s.precompile.Address(), big.NewInt(1e18), []string{staking.CancelUnbondingDelegationMsg},
+ )
+
+ s.ExpectAuthorization(staking.CancelUnbondingDelegationAuthz, s.precompile.Address(), s.address, &oneE18Coin)
+ })
+ })
+
+ Describe("Execute increase allowance transaction", func() {
+ // defaultIncreaseArgs are the default arguments to call the increase allowance method.
+ //
+ // NOTE: this has to be populated in BeforeEach, because the private key is not initialized outside of it.
+ var defaultIncreaseArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ s.SetupApproval(
+ s.privKey, s.precompile.Address(), big.NewInt(1e18), []string{staking.DelegateMsg},
+ )
+
+ defaultIncreaseArgs = defaultCallArgs.WithMethodName(authorization.IncreaseAllowanceMethod)
+ })
+
+ // TODO: enable once we check that the spender is not the origin
+ // It("should return error if the origin is the spender", func() {
+ // increaseArgs := defaultCallArgs.
+ // WithMethodName(authorization.IncreaseAllowanceMethod).
+ // WithArgs(
+ // s.address, big.NewInt(1e18), []string{staking.DelegateMsg},
+ // )
+ //
+ // _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, increaseArgs, differentOriginCheck)
+ // Expect(err).To(BeNil(), "error while calling the contract and checking logs")
+ // })
+
+ It("Should increase the allowance of the delegate method with 1 evmos", func() {
+ increaseArgs := defaultCallArgs.
+ WithMethodName(authorization.IncreaseAllowanceMethod).
+ WithArgs(
+ s.precompile.Address(), big.NewInt(1e18), []string{staking.DelegateMsg},
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(authorization.EventTypeAllowanceChange)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, increaseArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the contract and checking logs")
+
+ s.ExpectAuthorization(staking.DelegateAuthz, s.precompile.Address(), s.address, &twoE18Coin)
+ })
+
+ It("should return error if the allowance to increase does not exist", func() {
+ increaseArgs := defaultIncreaseArgs.WithArgs(
+ s.precompile.Address(), big.NewInt(1e18), []string{staking.UndelegateMsg},
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(
+ "does not exist",
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, increaseArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the contract and checking logs")
+ Expect(err.Error()).To(ContainSubstring("does not exist"))
+
+ authz, _ := s.CheckAuthorization(staking.UndelegateAuthz, s.precompile.Address(), s.address)
+ Expect(authz).To(BeNil(), "expected authorization to not be set")
+ })
+ })
+
+ Describe("Execute decrease allowance transaction", func() {
+ // defaultDecreaseArgs are the default arguments to call the decrease allowance method.
+ //
+ // NOTE: this has to be populated in BeforeEach, because the private key is not initialized outside of it.
+ var defaultDecreaseArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ s.SetupApproval(
+ s.privKey, s.precompile.Address(), big.NewInt(2e18), []string{staking.DelegateMsg},
+ )
+
+ defaultDecreaseArgs = defaultCallArgs.WithMethodName(authorization.DecreaseAllowanceMethod)
+ })
+
+ // TODO: enable once we check that the spender is not the origin
+ // It("should return error if the origin is the spender", func() {
+ // addr, _ := testutiltx.NewAddrKey()
+ // decreaseArgs := defaultDecreaseArgs.WithArgs(
+ // s.precompile.Address(), big.NewInt(1e18), []string{staking.DelegateMsg},
+ // )
+ //
+ // logCheckArgs := defaultLogCheck.WithErrContains(
+ // cmn.ErrDifferentOrigin, s.address, addr,
+ // )
+ //
+ // _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, decreaseArgs, logCheckArgs)
+ // Expect(err).To(BeNil(), "error while calling the contract and checking logs")
+ // })
+
+ It("Should decrease the allowance of the delegate method with 1 evmos", func() {
+ decreaseArgs := defaultDecreaseArgs.WithArgs(
+ s.precompile.Address(), big.NewInt(1e18), []string{staking.DelegateMsg},
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(authorization.EventTypeAllowanceChange)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, decreaseArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the contract and checking logs")
+
+ s.ExpectAuthorization(staking.DelegateAuthz, s.precompile.Address(), s.address, &oneE18Coin)
+ })
+
+ It("should return error if the allowance to decrease does not exist", func() {
+ decreaseArgs := defaultDecreaseArgs.WithArgs(
+ s.precompile.Address(), big.NewInt(1e18), []string{staking.UndelegateMsg},
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(
+ "does not exist",
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, decreaseArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the contract and checking logs")
+ Expect(err.Error()).To(ContainSubstring("does not exist"))
+
+ authz, _ := s.CheckAuthorization(staking.UndelegateAuthz, s.precompile.Address(), s.address)
+ Expect(authz).To(BeNil(), "expected authorization to not be set")
+ })
+ })
+
+ Describe("to revoke an approval", func() {
+ var (
+ // defaultRevokeArgs are the default arguments to call the revoke method.
+ //
+ // NOTE: this has to be populated in BeforeEach, because the default call args are not initialized outside of it.
+ defaultRevokeArgs contracts.CallArgs
+
+ // granteeAddr is the address of the grantee used in the revocation tests.
+ granteeAddr = testutiltx.GenerateAddress()
+ )
+
+ BeforeEach(func() {
+ defaultRevokeArgs = defaultCallArgs.WithMethodName(authorization.RevokeMethod)
+ })
+
+ It("should revoke the approval when executing as the granter", func() {
+ typeURLs := []string{staking.DelegateMsg}
+
+ s.SetupApproval(
+ s.privKey, granteeAddr, abi.MaxUint256, typeURLs,
+ )
+ s.ExpectAuthorization(staking.DelegateAuthz, granteeAddr, s.address, nil)
+
+ revokeArgs := defaultRevokeArgs.WithArgs(
+ granteeAddr, typeURLs,
+ )
+
+ revocationCheck := passCheck.WithExpEvents(authorization.EventTypeRevocation)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, revocationCheck)
+ Expect(err).To(BeNil(), "error while calling the contract and checking logs")
+
+ // check that the authorization is revoked
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, granteeAddr, s.address)
+ Expect(authz).To(BeNil(), "expected authorization to be revoked")
+ })
+
+ It("should not revoke the approval when trying to revoke for a different message type", func() {
+ typeURLs := []string{staking.DelegateMsg}
+
+ s.SetupApproval(
+ s.privKey, granteeAddr, abi.MaxUint256, typeURLs,
+ )
+ s.ExpectAuthorization(staking.DelegateAuthz, granteeAddr, s.address, nil)
+
+ revokeArgs := defaultRevokeArgs.WithArgs(
+ granteeAddr, []string{staking.UndelegateMsg},
+ )
+
+ notFoundCheck := defaultLogCheck.
+ WithErrContains("failed to delete grant")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, notFoundCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the contract and checking logs")
+
+ // the authorization should still be there.
+ s.ExpectAuthorization(staking.DelegateAuthz, granteeAddr, s.address, nil)
+ })
+
+ It("should return error if the approval does not exist", func() {
+ revokeArgs := defaultRevokeArgs.WithArgs(
+ s.address, []string{staking.DelegateMsg},
+ )
+
+ notFoundCheck := defaultLogCheck.
+ WithErrContains("failed to delete grant")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, notFoundCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the contract and checking logs")
+ })
+
+ It("should not revoke the approval if sent by someone else than the granter", func() {
+ typeURLs := []string{staking.DelegateMsg}
+
+ // set up an approval with a different key than the one used to sign the transaction.
+ differentAddr, differentPriv := testutiltx.NewAddrKey()
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, differentAddr.Bytes(), 1e18)
+ Expect(err).To(BeNil(), "error while funding account")
+
+ s.NextBlock()
+ s.SetupApproval(
+ differentPriv, granteeAddr, abi.MaxUint256, typeURLs,
+ )
+ s.ExpectAuthorization(staking.DelegateAuthz, granteeAddr, differentAddr, nil)
+
+ revokeArgs := defaultRevokeArgs.WithArgs(
+ differentAddr, typeURLs,
+ )
+
+ notFoundCheck := defaultLogCheck.
+ WithErrContains("failed to delete grant")
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, notFoundCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the contract and checking logs")
+
+ // the authorization should still be set
+ s.ExpectAuthorization(staking.DelegateAuthz, granteeAddr, differentAddr, nil)
+ })
+ })
+
+ Describe("to create validator", func() {
+ var (
+ defaultDescription = staking.Description{
+ Moniker: "new node",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ }
+ defaultCommission = staking.Commission{
+ Rate: big.NewInt(100000000000000000),
+ MaxRate: big.NewInt(100000000000000000),
+ MaxChangeRate: big.NewInt(100000000000000000),
+ }
+ defaultMinSelfDelegation = big.NewInt(1)
+ defaultPubkeyBase64Str = GenerateBase64PubKey()
+ defaultValue = big.NewInt(1)
+
+ // defaultCreateValidatorArgs are the default arguments for the createValidator call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultCreateValidatorArgs contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ // populate the default createValidator args
+ defaultCreateValidatorArgs = defaultCallArgs.WithMethodName(staking.CreateValidatorMethod)
+ })
+
+ Context("when validator address is the origin", func() {
+ It("should succeed", func() {
+ createValidatorArgs := defaultCreateValidatorArgs.WithArgs(
+ defaultDescription, defaultCommission, defaultMinSelfDelegation, s.address, defaultPubkeyBase64Str, defaultValue,
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, createValidatorArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ _, found := s.app.StakingKeeper.GetValidator(s.ctx, s.address.Bytes())
+ Expect(found).To(BeTrue(), "expected validator to be found")
+ })
+ })
+
+ Context("when validator address is not the origin", func() {
+ It("should fail", func() {
+ differentAddr := testutiltx.GenerateAddress()
+
+ createValidatorArgs := defaultCreateValidatorArgs.WithArgs(
+ defaultDescription, defaultCommission, defaultMinSelfDelegation, differentAddr, defaultPubkeyBase64Str, defaultValue,
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(
+ fmt.Sprintf(staking.ErrDifferentOriginFromDelegator, s.address, differentAddr),
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, createValidatorArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ })
+ })
+ })
+
+ Describe("to edit validator", func() {
+ var (
+ defaultDescription = staking.Description{
+ Moniker: "edit node",
+ Identity: "[do-not-modify]",
+ Website: "[do-not-modify]",
+ SecurityContact: "[do-not-modify]",
+ Details: "[do-not-modify]",
+ }
+ defaultCommissionRate = big.NewInt(staking.DoNotModifyCommissionRate)
+ defaultMinSelfDelegation = big.NewInt(staking.DoNotModifyMinSelfDelegation)
+
+ // defaultEditValidatorArgs are the default arguments for the editValidator call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultEditValidatorArgs contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ // populate the default editValidator args
+ defaultEditValidatorArgs = defaultCallArgs.WithMethodName(staking.EditValidatorMethod)
+ })
+
+ Context("when origin is equal to validator address", func() {
+ It("should succeed", func() {
+ // create a new validator
+ newAddr, newPriv := testutiltx.NewAccAddressAndKey()
+ hexAddr := common.BytesToAddress(newAddr.Bytes())
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, newAddr, 2e18)
+ Expect(err).To(BeNil(), "error while funding account: %v", err)
+
+ description := staking.Description{
+ Moniker: "new node",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ }
+ commission := staking.Commission{
+ Rate: big.NewInt(100000000000000000),
+ MaxRate: big.NewInt(100000000000000000),
+ MaxChangeRate: big.NewInt(100000000000000000),
+ }
+ minSelfDelegation := big.NewInt(1)
+ pubkeyBase64Str := "UuhHQmkUh2cPBA6Rg4ei0M2B04cVYGNn/F8SAUsYIb4="
+ value := big.NewInt(1e18)
+
+ createValidatorArgs := defaultCallArgs.WithMethodName(staking.CreateValidatorMethod).
+ WithPrivKey(newPriv).
+ WithArgs(description, commission, minSelfDelegation, hexAddr, pubkeyBase64Str, value)
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, createValidatorArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ s.NextBlock()
+
+ // edit validator
+ editValidatorArgs := defaultEditValidatorArgs.
+ WithPrivKey(newPriv).
+ WithArgs(defaultDescription, hexAddr, defaultCommissionRate, defaultMinSelfDelegation)
+
+ logCheckArgs = passCheck.WithExpEvents(staking.EventTypeEditValidator)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, editValidatorArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ validator, found := s.app.StakingKeeper.GetValidator(s.ctx, newAddr.Bytes())
+ Expect(found).To(BeTrue(), "expected validator to be found")
+ Expect(validator.Description.Moniker).To(Equal(defaultDescription.Moniker), "expected validator moniker is updated")
+ // Other fields should not be modified due to the value "[do-not-modify]".
+ Expect(validator.Description.Identity).To(Equal(description.Identity), "expected validator identity not to be updated")
+ Expect(validator.Description.Website).To(Equal(description.Website), "expected validator website not to be updated")
+ Expect(validator.Description.SecurityContact).To(Equal(description.SecurityContact), "expected validator security contact not to be updated")
+ Expect(validator.Description.Details).To(Equal(description.Details), "expected validator details not to be updated")
+
+ Expect(validator.Commission.Rate.BigInt().String()).To(Equal(commission.Rate.String()), "expected validator commission rate remain unchanged")
+ Expect(validator.Commission.MaxRate.BigInt().String()).To(Equal(commission.MaxRate.String()), "expected validator max commission rate remain unchanged")
+ Expect(validator.Commission.MaxChangeRate.BigInt().String()).To(Equal(commission.MaxChangeRate.String()), "expected validator max change rate remain unchanged")
+ Expect(validator.MinSelfDelegation.String()).To(Equal(minSelfDelegation.String()), "expected validator min self delegation remain unchanged")
+ })
+ })
+
+ Context("with origin different than validator address", func() {
+ It("should fail", func() {
+ editValidatorArgs := defaultEditValidatorArgs.WithArgs(
+ defaultDescription, common.BytesToAddress(valAddr.Bytes()), defaultCommissionRate, defaultMinSelfDelegation,
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeEditValidator)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, editValidatorArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ })
+ })
+ })
+
+ Describe("to delegate", func() {
+ var (
+ // prevDelegation is the delegation that is available prior to the test (an initial delegation is
+ // added in the test suite setup).
+ prevDelegation stakingtypes.Delegation
+ // defaultDelegateArgs are the default arguments for the delegate call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultDelegateArgs contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ // get the delegation that is available prior to the test
+ prevDelegation, _ = s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+
+ // populate the default delegate args
+ defaultDelegateArgs = defaultCallArgs.WithMethodName(staking.DelegateMethod)
+ })
+
+ Context("as the token owner", func() {
+ It("should delegate without need for authorization", func() {
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(2e18),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ expShares := prevDelegation.GetShares().Add(math.LegacyNewDec(2))
+ Expect(delegation.GetShares()).To(Equal(expShares), "expected different delegation shares")
+ })
+
+ It("should not delegate if the account has no sufficient balance", func() {
+ // send funds away from account to only have target balance remaining
+ balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ targetBalance := math.NewInt(1e17)
+ sentBalance := balance.Amount.Sub(targetBalance)
+ newAddr, _ := testutiltx.NewAccAddressAndKey()
+ err := s.app.BankKeeper.SendCoins(s.ctx, s.address.Bytes(), newAddr,
+ sdk.Coins{sdk.Coin{Denom: s.bondDenom, Amount: sentBalance}})
+ Expect(err).To(BeNil(), "error while sending coins")
+
+ // try to delegate more than left in account
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("insufficient funds")
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("insufficient funds"))
+ })
+
+ It("should not delegate if the validator does not exist", func() {
+ nonExistingAddr := testutiltx.GenerateAddress()
+ nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes())
+
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ s.address, nonExistingValAddr.String(), big.NewInt(2e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("validator does not exist")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("validator does not exist"))
+ })
+ })
+
+ Context("on behalf of another account", func() {
+ It("should not delegate if delegator address is not the origin", func() {
+ differentAddr := testutiltx.GenerateAddress()
+
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ differentAddr, valAddr.String(), big.NewInt(2e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(
+ fmt.Sprintf(staking.ErrDifferentOriginFromDelegator, s.address, differentAddr),
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ })
+ })
+ })
+
+ Describe("to undelegate", func() {
+ // defaultUndelegateArgs are the default arguments for the undelegate call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultUndelegateArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultUndelegateArgs = defaultCallArgs.WithMethodName(staking.UndelegateMethod)
+ })
+
+ Context("as the token owner", func() {
+ It("should undelegate without need for authorization", func() {
+ undelegations := s.app.StakingKeeper.GetUnbondingDelegationsFromValidator(s.ctx, s.validators[0].GetOperator())
+ Expect(undelegations).To(HaveLen(0), "expected no unbonding delegations before test")
+
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeUnbond)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ undelegations = s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(1), "expected one undelegation")
+ Expect(undelegations[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr)
+ })
+
+ It("should not undelegate if the amount exceeds the delegation", func() {
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(2e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("invalid shares amount")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("invalid shares amount"))
+ })
+
+ It("should not undelegate if the validator does not exist", func() {
+ nonExistingAddr := testutiltx.GenerateAddress()
+ nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes())
+
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ s.address, nonExistingValAddr.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("validator does not exist")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("validator does not exist"))
+ })
+ })
+
+ Context("on behalf of another account", func() {
+ It("should not undelegate if delegator address is not the origin", func() {
+ differentAddr := testutiltx.GenerateAddress()
+
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ differentAddr, valAddr.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(
+ fmt.Sprintf(staking.ErrDifferentOriginFromDelegator, s.address, differentAddr),
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ })
+ })
+ })
+
+ Describe("to redelegate", func() {
+ // defaultRedelegateArgs are the default arguments for the redelegate call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultRedelegateArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultRedelegateArgs = defaultCallArgs.WithMethodName(staking.RedelegateMethod)
+ })
+
+ Context("as the token owner", func() {
+ It("should redelegate without need for authorization", func() {
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeRedelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, valAddr2)
+ Expect(redelegations).To(HaveLen(1), "expected one redelegation to be found")
+ bech32Addr := sdk.AccAddress(s.address.Bytes())
+ Expect(redelegations[0].DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", s.address)
+ Expect(redelegations[0].ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr)
+ Expect(redelegations[0].ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2)
+ })
+
+ It("should not redelegate if the amount exceeds the delegation", func() {
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(), big.NewInt(2e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("invalid shares amount")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("invalid shares amount"))
+ })
+
+ It("should not redelegate if the validator does not exist", func() {
+ nonExistingAddr := testutiltx.GenerateAddress()
+ nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes())
+
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), nonExistingValAddr.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("redelegation destination validator not found")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("redelegation destination validator not found"))
+ })
+ })
+
+ Context("on behalf of another account", func() {
+ It("should not redelegate if delegator address is not the origin", func() {
+ differentAddr := testutiltx.GenerateAddress()
+
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ differentAddr, valAddr.String(), valAddr2.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains(
+ fmt.Sprintf(staking.ErrDifferentOriginFromDelegator, s.address, differentAddr),
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ })
+ })
+ })
+
+ Describe("to cancel an unbonding delegation", func() {
+ var (
+ // defaultCancelUnbondingArgs are the default arguments for the cancelUnbondingDelegation call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultCancelUnbondingArgs contracts.CallArgs
+
+ // expCreationHeight is the expected creation height of the unbonding delegation
+ expCreationHeight = int64(3)
+ )
+
+ BeforeEach(func() {
+ defaultCancelUnbondingArgs = defaultCallArgs.WithMethodName(staking.CancelUnbondingDelegationMethod)
+
+ // Set up an unbonding delegation
+ undelegateArgs := defaultCallArgs.
+ WithMethodName(staking.UndelegateMethod).
+ WithArgs(s.address, valAddr.String(), big.NewInt(1e18))
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeUnbond)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err)
+
+ s.NextBlock()
+
+ // Check that the unbonding delegation was created
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected one unbonding delegation to be found")
+ Expect(unbondingDelegations[0].DelegatorAddress).To(Equal(sdk.AccAddress(s.address.Bytes()).String()), "expected delegator address to be %s", s.address)
+ Expect(unbondingDelegations[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr)
+ Expect(unbondingDelegations[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found")
+ Expect(unbondingDelegations[0].Entries[0].CreationHeight).To(Equal(expCreationHeight), "expected different creation height")
+ Expect(unbondingDelegations[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance")
+ })
+
+ Context("as the token owner", func() {
+ It("should cancel unbonding delegation", func() {
+ delegations := s.app.StakingKeeper.GetValidatorDelegations(s.ctx, s.validators[0].GetOperator())
+ Expect(delegations).To(HaveLen(0))
+
+ cArgs := defaultCancelUnbondingArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18), big.NewInt(expCreationHeight),
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeCancelUnbondingDelegation)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(0), "expected unbonding delegation to be canceled")
+
+ delegations = s.app.StakingKeeper.GetValidatorDelegations(s.ctx, s.validators[0].GetOperator())
+ Expect(delegations).To(HaveLen(1), "expected one delegation to be found")
+ })
+
+ It("should not cancel an unbonding delegation if the amount is not correct", func() {
+ cArgs := defaultCancelUnbondingArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(2e18), big.NewInt(expCreationHeight),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("amount is greater than the unbonding delegation entry balance")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("amount is greater than the unbonding delegation entry balance"))
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected unbonding delegation not to have been canceled")
+ })
+
+ It("should not cancel an unbonding delegation if the creation height is not correct", func() {
+ cArgs := defaultCancelUnbondingArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18), big.NewInt(expCreationHeight+1),
+ )
+
+ logCheckArgs := defaultLogCheck.WithErrContains("unbonding delegation entry is not found at block height")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("unbonding delegation entry is not found at block height"))
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected unbonding delegation not to have been canceled")
+ })
+ })
+ })
+
+ Describe("Calling precompile txs from a vesting account", func() {
+ var (
+ funder common.Address
+ vestAcc common.Address
+ vestAccPriv *ethsecp256k1.PrivKey
+ clawbackAccount *vestingtypes.ClawbackVestingAccount
+ unvested sdk.Coins
+ vested sdk.Coins
+ // unlockedVested are unlocked vested coins of the vesting schedule
+ unlockedVested sdk.Coins
+ defaultDelegateArgs contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ // Setup vesting account
+ funder = s.address
+ vestAcc, vestAccPriv = testutiltx.NewAddrKey()
+ vestingAmtTotal := evmosutil.TestVestingSchedule.TotalVestingCoins
+
+ clawbackAccount = s.setupVestingAccount(funder.Bytes(), vestAcc.Bytes())
+
+ // Check if all tokens are unvested at vestingStart
+ unvested = clawbackAccount.GetVestingCoins(s.ctx.BlockTime())
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ Expect(vestingAmtTotal).To(Equal(unvested))
+ Expect(vested.IsZero()).To(BeTrue())
+
+ // populate the default delegate args
+ defaultDelegateArgs = defaultCallArgs.WithMethodName(staking.DelegateMethod)
+ defaultDelegateArgs = defaultDelegateArgs.WithPrivKey(vestAccPriv)
+ })
+
+ Context("before first vesting period - all tokens locked and unvested", func() {
+ BeforeEach(func() {
+ s.NextBlock()
+
+ // Ensure no tokens are vested
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ unvested = clawbackAccount.GetVestingCoins(s.ctx.BlockTime())
+ unlocked := clawbackAccount.GetUnlockedCoins(s.ctx.BlockTime())
+ zeroCoins := sdk.NewCoins(sdk.NewCoin(s.bondDenom, math.ZeroInt()))
+ Expect(vested).To(Equal(zeroCoins), "expected different vested coins")
+ Expect(unvested).To(Equal(evmosutil.TestVestingSchedule.TotalVestingCoins), "expected different unvested coins")
+ Expect(unlocked).To(Equal(zeroCoins), "expected different unlocked coins")
+ })
+
+ It("Should not be able to delegate unvested tokens", func() {
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ vestAcc, valAddr.String(), unvested.AmountOf(s.bondDenom).BigInt(),
+ )
+
+ failCheck := defaultLogCheck.
+ WithErrContains("cannot delegate unvested coins")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, failCheck)
+ Expect(err).NotTo(BeNil(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("coins available for delegation < delegation amount"))
+ })
+
+ It("Should be able to delegate tokens not involved in vesting schedule", func() {
+ // send some coins to the vesting account
+ coinsToDelegate := sdk.NewCoins(sdk.NewCoin(s.bondDenom, math.NewInt(1e18)))
+ err := evmosutil.FundAccount(s.ctx, s.app.BankKeeper, clawbackAccount.GetAddress(), coinsToDelegate)
+ Expect(err).To(BeNil())
+
+ // check balance is updated
+ balance := s.app.BankKeeper.GetBalance(s.ctx, clawbackAccount.GetAddress(), s.bondDenom)
+ Expect(balance).To(Equal(accountGasCoverage[0].Add(evmosutil.TestVestingSchedule.TotalVestingCoins[0]).Add(coinsToDelegate[0])))
+
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ vestAcc, valAddr.String(), coinsToDelegate.AmountOf(s.bondDenom).BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(coinsToDelegate[0].Amount.BigInt()))
+
+ // check vesting balance is untouched
+ balancePost := s.app.BankKeeper.GetBalance(s.ctx, clawbackAccount.GetAddress(), s.bondDenom)
+ Expect(balancePost.IsGTE(evmosutil.TestVestingSchedule.TotalVestingCoins[0])).To(BeTrue())
+ })
+ })
+
+ Context("after first vesting period and before lockup - some vested tokens, but still all locked", func() {
+ BeforeEach(func() {
+ // Surpass cliff but none of lockup duration
+ cliffDuration := time.Duration(evmosutil.TestVestingSchedule.CliffPeriodLength)
+ s.NextBlockAfter(cliffDuration * time.Second)
+
+ // Check if some, but not all tokens are vested
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ expVested := sdk.NewCoins(sdk.NewCoin(s.bondDenom, evmosutil.TestVestingSchedule.VestedCoinsPerPeriod[0].Amount.Mul(math.NewInt(evmosutil.TestVestingSchedule.CliffMonths))))
+ Expect(vested).NotTo(Equal(evmosutil.TestVestingSchedule.TotalVestingCoins), "expected some tokens to have been vested")
+ Expect(vested).To(Equal(expVested), "expected different vested amount")
+
+ // check the vested tokens are still locked
+ unlockedVested = clawbackAccount.GetUnlockedVestedCoins(s.ctx.BlockTime())
+ Expect(unlockedVested).To(Equal(sdk.Coins{}))
+
+ vestingAmtTotal := evmosutil.TestVestingSchedule.TotalVestingCoins
+ res, err := s.app.VestingKeeper.Balances(s.ctx, &vestingtypes.QueryBalancesRequest{Address: clawbackAccount.Address})
+ Expect(err).To(BeNil())
+ Expect(res.Vested).To(Equal(expVested))
+ Expect(res.Unvested).To(Equal(vestingAmtTotal.Sub(expVested...)))
+ // All coins from vesting schedule should be locked
+ Expect(res.Locked).To(Equal(vestingAmtTotal))
+ })
+
+ It("Should be able to delegate locked vested tokens", func() {
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ vestAcc, valAddr.String(), vested[0].Amount.BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(vested[0].Amount.BigInt()))
+ })
+
+ It("Should be able to delegate locked vested tokens + free tokens (not in vesting schedule)", func() {
+ // send some coins to the vesting account
+ amt := sdk.NewCoins(sdk.NewCoin(s.bondDenom, math.NewInt(1e18)))
+ err := evmosutil.FundAccount(s.ctx, s.app.BankKeeper, clawbackAccount.GetAddress(), amt)
+ Expect(err).To(BeNil())
+
+ // check balance is updated
+ balance := s.app.BankKeeper.GetBalance(s.ctx, clawbackAccount.GetAddress(), s.bondDenom)
+ Expect(balance).To(Equal(accountGasCoverage[0].Add(evmosutil.TestVestingSchedule.TotalVestingCoins[0]).Add(amt[0])))
+
+ coinsToDelegate := amt.Add(vested...)
+
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ vestAcc, valAddr.String(), coinsToDelegate[0].Amount.BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(coinsToDelegate[0].Amount.BigInt()))
+ })
+ })
+
+ Context("Between first and second lockup periods - vested coins are unlocked", func() {
+ BeforeEach(func() {
+ // Surpass first lockup
+ vestDuration := time.Duration(evmosutil.TestVestingSchedule.LockupPeriodLength)
+ s.NextBlockAfter(vestDuration * time.Second)
+
+ // Check if some, but not all tokens are vested and unlocked
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ unlocked := clawbackAccount.GetUnlockedCoins(s.ctx.BlockTime())
+ unlockedVested = clawbackAccount.GetUnlockedVestedCoins(s.ctx.BlockTime())
+
+ expVested := sdk.NewCoins(sdk.NewCoin(s.bondDenom, evmosutil.TestVestingSchedule.VestedCoinsPerPeriod[0].Amount.Mul(math.NewInt(evmosutil.TestVestingSchedule.LockupMonths))))
+ expUnlockedVested := expVested
+
+ Expect(vested).NotTo(Equal(evmosutil.TestVestingSchedule.TotalVestingCoins), "expected not all tokens to be vested")
+ Expect(vested).To(Equal(expVested), "expected different amount of vested tokens")
+ // all vested coins are unlocked
+ Expect(unlockedVested).To(Equal(vested))
+ Expect(unlocked).To(Equal(evmosutil.TestVestingSchedule.UnlockedCoinsPerLockup))
+ Expect(unlockedVested).To(Equal(expUnlockedVested))
+ })
+ It("Should be able to delegate unlocked vested tokens", func() {
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ vestAcc, valAddr.String(), unlockedVested[0].Amount.BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(unlockedVested[0].Amount.BigInt()))
+ })
+
+ It("Cannot delegate more than vested tokens (and free tokens)", func() {
+ // calculate the delegatable amount
+ balance := s.app.BankKeeper.GetBalance(s.ctx, vestAcc.Bytes(), s.bondDenom)
+ unvestedOnly := clawbackAccount.GetVestingCoins(s.ctx.BlockTime())
+ delegatable := balance.Sub(unvestedOnly[0])
+
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ vestAcc, valAddr.String(), delegatable.Amount.Add(sdk.OneInt()).BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).NotTo(BeNil(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("cannot delegate unvested coins"))
+
+ _, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeFalse(), "expected delegation NOT to be found")
+ })
+ })
+ })
+
+ Describe("to query allowance", func() {
+ var (
+ defaultAllowanceArgs contracts.CallArgs
+
+ differentAddr = testutiltx.GenerateAddress()
+ )
+
+ BeforeEach(func() {
+ defaultAllowanceArgs = defaultCallArgs.WithMethodName(authorization.AllowanceMethod)
+ })
+
+ It("should return an empty allowance if none is set", func() {
+ allowanceArgs := defaultAllowanceArgs.WithArgs(
+ s.address, differentAddr, staking.CancelUnbondingDelegationMsg,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, allowanceArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var allowanceInt *big.Int
+ err = s.precompile.UnpackIntoInterface(&allowanceInt, "allowance", ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unmarshalling the allowance: %v", err)
+ Expect(allowanceInt.Int64()).To(BeZero(), "expected allowance to be zero")
+ })
+
+ It("should return the granted allowance if set", func() {
+ // setup approval for another address
+ s.SetupApproval(
+ s.privKey, differentAddr, big.NewInt(1e18), []string{staking.CancelUnbondingDelegationMsg},
+ )
+
+ // query allowance
+ allowanceArgs := defaultAllowanceArgs.WithArgs(
+ differentAddr, s.address, staking.CancelUnbondingDelegationMsg,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, allowanceArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var allowanceInt *big.Int
+ err = s.precompile.UnpackIntoInterface(&allowanceInt, "allowance", ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unmarshalling the allowance: %v", err)
+ Expect(allowanceInt).To(Equal(big.NewInt(1e18)), "expected allowance to be 1e18")
+ })
+ })
+
+ Describe("Validator queries", func() {
+ // defaultValidatorArgs are the default arguments for the validator call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultValidatorArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultValidatorArgs = defaultCallArgs.WithMethodName(staking.ValidatorMethod)
+ })
+
+ It("should return validator", func() {
+ varHexAddr := common.BytesToAddress(valAddr.Bytes())
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ varHexAddr,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+ Expect(valOut.Validator.OperatorAddress).To(Equal(varHexAddr.String()), "expected validator address to match")
+ Expect(valOut.Validator.DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares")
+ })
+
+ It("should return an empty validator if the validator is not found", func() {
+ newValHexAddr := testutiltx.GenerateAddress()
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ newValHexAddr,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+ Expect(valOut.Validator.OperatorAddress).To(Equal(""), "expected validator address to be empty")
+ Expect(valOut.Validator.Status).To(BeZero(), "expected unspecified bonding status")
+ })
+ })
+
+ Describe("Validators queries", func() {
+ var defaultValidatorArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultValidatorArgs = defaultCallArgs.WithMethodName(staking.ValidatorsMethod)
+ })
+
+ It("should return validators (default pagination)", func() {
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ stakingtypes.Bonded.String(),
+ query.PageRequest{},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorsOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ Expect(valOut.PageResponse.NextKey).To(BeEmpty())
+ Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.validators))))
+
+ Expect(valOut.Validators).To(HaveLen(len(s.validators)), "expected two validators to be returned")
+ // return order can change, that's why each validator is checked individually
+ for _, val := range valOut.Validators {
+ s.CheckValidatorOutput(val)
+ }
+ })
+
+ //nolint:dupl // this is a duplicate of the test for smart contract calls to the precompile
+ It("should return validators w/pagination limit = 1", func() {
+ const limit uint64 = 1
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ stakingtypes.Bonded.String(),
+ query.PageRequest{
+ Limit: limit,
+ CountTotal: true,
+ },
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorsOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ // no pagination, should return default values
+ Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty())
+ Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.validators))))
+
+ Expect(valOut.Validators).To(HaveLen(int(limit)), "expected one validator to be returned")
+
+ // return order can change, that's why each validator is checked individually
+ for _, val := range valOut.Validators {
+ s.CheckValidatorOutput(val)
+ }
+ })
+
+ It("should return an error if the bonding type is not known", func() {
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ "15", // invalid bonding type
+ query.PageRequest{},
+ )
+
+ invalidStatusCheck := defaultLogCheck.WithErrContains("invalid validator status 15")
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, invalidStatusCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ Expect(err.Error()).To(ContainSubstring("invalid validator status 15"))
+ })
+
+ It("should return an empty array if there are no validators with the given bonding type", func() {
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ stakingtypes.Unbonded.String(),
+ query.PageRequest{},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorsOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ Expect(valOut.PageResponse.NextKey).To(BeEmpty())
+ Expect(valOut.PageResponse.Total).To(Equal(uint64(0)))
+ Expect(valOut.Validators).To(HaveLen(0), "expected no validators to be returned")
+ })
+ })
+
+ Describe("Delegation queries", func() {
+ var defaultDelegationArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultDelegationArgs = defaultCallArgs.WithMethodName(staking.DelegationMethod)
+ })
+
+ It("should return a delegation if it is found", func() {
+ delegationArgs := defaultDelegationArgs.WithArgs(
+ s.address,
+ valAddr.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var delOut staking.DelegationOutput
+ err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err)
+ Expect(delOut.Shares).To(Equal(big.NewInt(1e18)), "expected different shares")
+ Expect(delOut.Balance).To(Equal(cmn.Coin{Denom: s.bondDenom, Amount: big.NewInt(1e18)}), "expected different shares")
+ })
+
+ It("should return an empty delegation if it is not found", func() {
+ newValAddr := sdk.ValAddress(testutiltx.GenerateAddress().Bytes())
+ delegationArgs := defaultDelegationArgs.WithArgs(
+ s.address, newValAddr.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var delOut staking.DelegationOutput
+ err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err)
+ Expect(delOut.Shares.Int64()).To(BeZero(), "expected no shares")
+ Expect(delOut.Balance.Denom).To(Equal(s.bondDenom), "expected different denomination")
+ Expect(delOut.Balance.Amount.Int64()).To(BeZero(), "expected a zero amount")
+ })
+ })
+
+ Describe("UnbondingDelegation queries", func() {
+ var (
+ defaultUnbondingDelegationArgs contracts.CallArgs
+
+ // undelAmount is the amount of tokens to be unbonded
+ undelAmount = big.NewInt(1e17)
+ )
+
+ BeforeEach(func() {
+ defaultUnbondingDelegationArgs = defaultCallArgs.WithMethodName(staking.UnbondingDelegationMethod)
+
+ // unbond a delegation
+ s.SetupApproval(s.privKey, s.precompile.Address(), abi.MaxUint256, []string{staking.UndelegateMsg})
+
+ unbondArgs := defaultCallArgs.
+ WithMethodName(staking.UndelegateMethod).
+ WithArgs(s.address, valAddr.String(), undelAmount)
+ unbondCheck := passCheck.WithExpEvents(staking.EventTypeUnbond)
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, unbondArgs, unbondCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // check that the unbonding delegation exists
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected one unbonding delegation")
+ })
+
+ It("should return an unbonding delegation if it is found", func() {
+ unbondingDelegationsArgs := defaultUnbondingDelegationArgs.WithArgs(
+ s.address,
+ valAddr.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, unbondingDelegationsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var unbondingDelegationOutput staking.UnbondingDelegationOutput
+ err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err)
+ Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(1), "expected one unbonding delegation entry")
+ // TODO: why are initial balance and balance the same always?
+ Expect(unbondingDelegationOutput.UnbondingDelegation.Entries[0].InitialBalance).To(Equal(undelAmount), "expected different initial balance")
+ Expect(unbondingDelegationOutput.UnbondingDelegation.Entries[0].Balance).To(Equal(undelAmount), "expected different balance")
+ })
+
+ It("should return an empty slice if the unbonding delegation is not found", func() {
+ unbondingDelegationsArgs := defaultUnbondingDelegationArgs.WithArgs(
+ s.address,
+ valAddr2.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, unbondingDelegationsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var unbondingDelegationOutput staking.UnbondingDelegationOutput
+ err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err)
+ Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(0), "expected one unbonding delegation entry")
+ })
+ })
+
+ Describe("to query a redelegation", func() {
+ var defaultRedelegationArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultRedelegationArgs = defaultCallArgs.WithMethodName(staking.RedelegationMethod)
+ })
+
+ It("should return the redelegation if it exists", func() {
+ // approve the redelegation
+ s.SetupApproval(s.privKey, s.precompile.Address(), abi.MaxUint256, []string{staking.RedelegateMsg})
+
+ // create a redelegation
+ redelegateArgs := defaultCallArgs.
+ WithMethodName(staking.RedelegateMethod).
+ WithArgs(s.address, valAddr.String(), valAddr2.String(), big.NewInt(1e17))
+
+ redelegateCheck := passCheck.WithExpEvents(staking.EventTypeRedelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, redelegateCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // query the redelegation
+ redelegationArgs := defaultRedelegationArgs.WithArgs(
+ s.address,
+ valAddr.String(),
+ valAddr2.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var redelegationOutput staking.RedelegationOutput
+ err = s.precompile.UnpackIntoInterface(&redelegationOutput, staking.RedelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err)
+ Expect(redelegationOutput.Redelegation.Entries).To(HaveLen(1), "expected one redelegation entry")
+ Expect(redelegationOutput.Redelegation.Entries[0].InitialBalance).To(Equal(big.NewInt(1e17)), "expected different initial balance")
+ Expect(redelegationOutput.Redelegation.Entries[0].SharesDst).To(Equal(big.NewInt(1e17)), "expected different balance")
+ })
+
+ It("should return an empty output if the redelegation is not found", func() {
+ redelegationArgs := defaultRedelegationArgs.WithArgs(
+ s.address,
+ valAddr.String(),
+ valAddr2.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var redelegationOutput staking.RedelegationOutput
+ err = s.precompile.UnpackIntoInterface(&redelegationOutput, staking.RedelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err)
+ Expect(redelegationOutput.Redelegation.Entries).To(HaveLen(0), "expected no redelegation entries")
+ })
+ })
+
+ Describe("Redelegations queries", func() {
+ var (
+ // defaultRedelegationsArgs are the default arguments for the redelegations query
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultRedelegationsArgs contracts.CallArgs
+
+ // delAmt is the amount of tokens to be delegated
+ delAmt = big.NewInt(3e17)
+ // redelTotalCount is the total number of redelegations
+ redelTotalCount uint64 = 1
+ )
+
+ BeforeEach(func() {
+ defaultRedelegationsArgs = defaultCallArgs.WithMethodName(staking.RedelegationsMethod)
+ // create some redelegations
+ s.SetupApproval(
+ s.privKey, s.precompile.Address(), abi.MaxUint256, []string{staking.RedelegateMsg},
+ )
+
+ defaultRedelegateArgs := defaultCallArgs.WithMethodName(staking.RedelegateMethod)
+ redelegationsArgs := []contracts.CallArgs{
+ defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(), delAmt,
+ ),
+ defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(), delAmt,
+ ),
+ }
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeRedelegate)
+
+ for _, args := range redelegationsArgs {
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, args, logCheckArgs)
+ Expect(err).To(BeNil(), "error while creating redelegation: %v", err)
+ }
+ })
+
+ It("should return all redelegations for delegator (default pagination)", func() {
+ redelegationArgs := defaultRedelegationsArgs.WithArgs(
+ s.address,
+ "",
+ "",
+ query.PageRequest{},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var redelOut staking.RedelegationsOutput
+ err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ Expect(redelOut.PageResponse.NextKey).To(BeEmpty())
+ Expect(redelOut.PageResponse.Total).To(Equal(redelTotalCount))
+
+ Expect(redelOut.Response).To(HaveLen(int(redelTotalCount)), "expected two redelegations to be returned")
+ // return order can change
+ redOrder := []int{0, 1}
+ if len(redelOut.Response[0].Entries) == 2 {
+ redOrder = []int{1, 0}
+ }
+
+ for i, r := range redelOut.Response {
+ Expect(r.Entries).To(HaveLen(redOrder[i] + 1))
+ }
+ })
+
+ It("should return all redelegations for delegator w/pagination", func() {
+ // make 2 queries
+ // 1st one with pagination limit = 1
+ // 2nd using the next page key
+ var nextPageKey []byte
+ for i := 0; i < 2; i++ {
+ var pagination query.PageRequest
+ if nextPageKey == nil {
+ pagination.Limit = 1
+ pagination.CountTotal = true
+ } else {
+ pagination.Key = nextPageKey
+ }
+ redelegationArgs := defaultRedelegationsArgs.WithArgs(
+ s.address,
+ "",
+ "",
+ pagination,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var redelOut staking.RedelegationsOutput
+ err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ if nextPageKey == nil {
+ nextPageKey = redelOut.PageResponse.NextKey
+ Expect(redelOut.PageResponse.Total).To(Equal(redelTotalCount))
+ } else {
+ Expect(redelOut.PageResponse.NextKey).To(BeEmpty())
+ Expect(redelOut.PageResponse.Total).To(Equal(uint64(1)))
+ }
+
+ Expect(redelOut.Response).To(HaveLen(1), "expected two redelegations to be returned")
+ // return order can change
+ redOrder := []int{0, 1}
+ if len(redelOut.Response[0].Entries) == 2 {
+ redOrder = []int{1, 0}
+ }
+
+ for i, r := range redelOut.Response {
+ Expect(r.Entries).To(HaveLen(redOrder[i] + 1))
+ }
+ }
+ })
+
+ It("should return an empty array if no redelegation is found for the given source validator", func() {
+ // NOTE: the way that the functionality is implemented in the Cosmos SDK, the following combinations are
+ // possible (see https://github.com/evmos/cosmos-sdk/blob/e773cf768844c87245d0c737cda1893a2819dd89/x/staking/keeper/querier.go#L361-L373):
+ //
+ // - delegator is NOT empty, source validator is empty, destination validator is empty
+ // --> filtering for all redelegations of the given delegator
+ // - delegator is empty, source validator is NOT empty, destination validator is empty
+ // --> filtering for all redelegations with the given source validator
+ // - delegator is NOT empty, source validator is NOT empty, destination validator is NOT empty
+ // --> filtering for all redelegations with the given combination of delegator, source and destination validator
+ redelegationsArgs := defaultRedelegationsArgs.WithArgs(
+ common.Address{}, // passing in an empty address to filter for all redelegations from valAddr2
+ valAddr2.String(),
+ "",
+ query.PageRequest{},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationsArgs, passCheck)
+ Expect(err).To(BeNil(), "expected error while calling the smart contract")
+
+ var redelOut staking.RedelegationsOutput
+ err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ Expect(redelOut.PageResponse.NextKey).To(BeEmpty())
+ Expect(redelOut.PageResponse.Total).To(BeZero(), "expected no redelegations to be returned")
+
+ Expect(redelOut.Response).To(HaveLen(0), "expected no redelegations to be returned")
+ })
+ })
+
+ It("Should refund leftover gas", func() {
+ balancePre := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ gasPrice := big.NewInt(1e9)
+
+ // Call the precompile with a lot of gas
+ approveArgs := defaultApproveArgs.
+ WithGasPrice(gasPrice).
+ WithArgs(s.precompile.Address(), big.NewInt(1e18), []string{staking.DelegateMsg})
+
+ approvalCheck := passCheck.WithExpEvents(authorization.EventTypeApproval)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, approveArgs, approvalCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ s.NextBlock()
+
+ balancePost := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ difference := balancePre.Sub(balancePost)
+
+ // NOTE: the expected difference is the gas price multiplied by the gas used, because the rest should be refunded
+ expDifference := gasPrice.Int64() * res.GasUsed
+ Expect(difference.Amount.Int64()).To(Equal(expDifference), "expected different total transaction cost")
+ })
+})
+
+var _ = Describe("Calling staking precompile via Solidity", func() {
+ var (
+ // contractAddr is the address of the smart contract that will be deployed
+ contractAddr common.Address
+ contractTwoAddr common.Address
+ stkReverterAddr common.Address
+
+ // stakingCallerContract is the contract instance calling into the staking precompile
+ stakingCallerContract evmtypes.CompiledContract
+ stakingCallerTwoContract evmtypes.CompiledContract
+ stakingReverterContract evmtypes.CompiledContract
+
+ // approvalCheck is a configuration for the log checker to see if an approval event was emitted.
+ approvalCheck testutil.LogCheckArgs
+ // execRevertedCheck defines the default log checking arguments which include the
+ // standard revert message
+ execRevertedCheck testutil.LogCheckArgs
+ // err is a basic error type
+ err error
+
+ // nonExistingAddr is an address that does not exist in the state of the test suite
+ nonExistingAddr = testutiltx.GenerateAddress()
+ // nonExistingVal is a validator address that does not exist in the state of the test suite
+ nonExistingVal = sdk.ValAddress(nonExistingAddr.Bytes())
+
+ testContractInitialBalance = math.NewInt(100)
+ )
+
+ BeforeEach(func() {
+ s.SetupTest()
+
+ stakingCallerContract, err = testdata.LoadStakingCallerContract()
+ Expect(err).To(BeNil(), "error while loading the staking caller contract: %v", err)
+
+ contractAddr, err = s.DeployContract(stakingCallerContract)
+ Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err)
+ s.NextBlock()
+
+ // Deploy StakingCallerTwo contract
+ stakingCallerTwoContract, err = testdata.LoadStakingCallerTwoContract()
+ Expect(err).To(BeNil(), "error while loading the StakingCallerTwo contract")
+
+ contractTwoAddr, err = s.DeployContract(stakingCallerTwoContract)
+ Expect(err).To(BeNil(), "error while deploying the StakingCallerTwo contract")
+ s.NextBlock()
+
+ // Deploy StakingReverter contract
+ stakingReverterContract, err = contracts.LoadStakingReverterContract()
+ Expect(err).To(BeNil(), "error while loading the StakingReverter contract")
+
+ stkReverterAddr, err = s.DeployContract(stakingReverterContract)
+ Expect(err).To(BeNil(), "error while deploying the StakingReverter contract")
+ s.NextBlock()
+
+ // send some funds to the StakingCallerTwo & StakingReverter contracts to transfer to the
+ // delegator during the tx
+ err = evmosutil.FundAccount(s.ctx, s.app.BankKeeper, contractTwoAddr.Bytes(), sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, testContractInitialBalance)))
+ Expect(err).To(BeNil(), "error while funding the smart contract: %v", err)
+
+ err = evmosutil.FundAccount(s.ctx, s.app.BankKeeper, stkReverterAddr.Bytes(), sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, testContractInitialBalance)))
+ Expect(err).To(BeNil(), "error while funding the smart contract: %v", err)
+
+ valAddr = s.validators[0].GetOperator()
+ valAddr2 = s.validators[1].GetOperator()
+
+ // check contract was correctly deployed
+ cAcc := s.app.EvmKeeper.GetAccount(s.ctx, contractAddr)
+ Expect(cAcc).ToNot(BeNil(), "contract account should exist")
+ Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract")
+
+ // populate default call args
+ defaultCallArgs = contracts.CallArgs{
+ ContractAddr: contractAddr,
+ ContractABI: stakingCallerContract.ABI,
+ PrivKey: s.privKey,
+ }
+ // populate default approval args
+ defaultApproveArgs = defaultCallArgs.WithMethodName("testApprove")
+
+ // populate default log check args
+ defaultLogCheck = testutil.LogCheckArgs{
+ ABIEvents: s.precompile.Events,
+ }
+ execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error())
+ passCheck = defaultLogCheck.WithExpPass(true)
+ approvalCheck = passCheck.WithExpEvents(authorization.EventTypeApproval)
+ })
+
+ Describe("when the precompile is not enabled in the EVM params", func() {
+ It("should return an error", func() {
+ // disable the precompile
+ params := s.app.EvmKeeper.GetParams(s.ctx)
+ var activePrecompiles []string
+ for _, precompile := range params.ActiveStaticPrecompiles {
+ if precompile != s.precompile.Address().String() {
+ activePrecompiles = append(activePrecompiles, precompile)
+ }
+ }
+ params.ActiveStaticPrecompiles = activePrecompiles
+ err := s.app.EvmKeeper.SetParams(s.ctx, params)
+ Expect(err).To(BeNil(), "error while setting params")
+
+ // try to call the precompile
+ delegateArgs := defaultCallArgs.
+ WithMethodName("testDelegate").
+ WithArgs(
+ s.address, valAddr.String(), big.NewInt(2e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "expected error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring(vm.ErrExecutionReverted.Error()))
+ })
+ })
+
+ Context("approving methods", func() {
+ Context("with valid input", func() {
+ It("should approve one method", func() {
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+ })
+
+ It("should approve all methods", func() {
+ approvalArgs := defaultApproveArgs.
+ WithGasLimit(1e8).
+ WithArgs(
+ contractAddr,
+ []string{staking.DelegateMsg, staking.RedelegateMsg, staking.UndelegateMsg, staking.CancelUnbondingDelegationMsg},
+ big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+ })
+
+ It("should update a previous approval", func() {
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+
+ s.NextBlock()
+
+ // update approval
+ approvalArgs = defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, big.NewInt(2e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, approvalArgs, approvalCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // check approvals
+ authorization, expirationTime := s.CheckAuthorization(staking.DelegateAuthz, contractAddr, s.address)
+ Expect(authorization).ToNot(BeNil(), "expected authorization to not be nil")
+ Expect(expirationTime).ToNot(BeNil(), "expected expiration time to not be nil")
+ Expect(authorization.MsgTypeURL()).To(Equal(staking.DelegateMsg), "expected authorization msg type url to be %s", staking.DelegateMsg)
+ Expect(authorization.MaxTokens.Amount).To(Equal(math.NewInt(2e18)), "expected different max tokens after updated approval")
+ })
+
+ It("should remove approval when setting amount to zero", func() {
+ s.SetupApprovalWithContractCalls(
+ defaultApproveArgs.WithArgs(contractAddr, []string{staking.DelegateMsg}, big.NewInt(1e18)),
+ )
+
+ s.NextBlock()
+
+ // check approvals pre-removal
+ allAuthz, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while reading authorizations")
+ Expect(allAuthz).To(HaveLen(1), "expected no authorizations")
+
+ approveArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, big.NewInt(0),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, approveArgs, approvalCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract")
+
+ // check approvals after approving with amount 0
+ allAuthz, err = s.app.AuthzKeeper.GetAuthorizations(s.ctx, contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while reading authorizations")
+ Expect(allAuthz).To(HaveLen(0), "expected no authorizations")
+ })
+
+ It("should not approve if the gas is not enough", func() {
+ approveArgs := defaultApproveArgs.
+ WithGasLimit(1e5).
+ WithArgs(
+ contractAddr,
+ []string{
+ staking.DelegateMsg,
+ staking.UndelegateMsg,
+ staking.RedelegateMsg,
+ staking.CancelUnbondingDelegationMsg,
+ },
+ big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, approveArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract")
+ })
+ })
+
+ Context("with invalid input", func() {
+ // TODO: enable once we check that origin is not the sender
+ // It("shouldn't approve any methods for if the sender is the origin", func() {
+ // approveArgs := defaultApproveArgs.WithArgs(
+ // nonExistingAddr, []string{staking.DelegateMsg}, big.NewInt(1e18),
+ // )
+ //
+ // _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, approveArgs, execRevertedCheck)
+ // Expect(err).To(BeNil(), "error while calling the smart contract")
+ //
+ // // check approvals
+ // allAuthz, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, contractAddr.Bytes(), s.address.Bytes())
+ // Expect(err).To(BeNil(), "error while reading authorizations")
+ // Expect(allAuthz).To(HaveLen(0), "expected no authorizations")
+ // })
+
+ It("shouldn't approve for invalid methods", func() {
+ approveArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{"invalid method"}, big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, approveArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract")
+
+ // check approvals
+ allAuthz, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while reading authorizations")
+ Expect(allAuthz).To(HaveLen(0), "expected no authorizations")
+ })
+ })
+ })
+
+ Context("to revoke an approval", func() {
+ var defaultRevokeArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultRevokeArgs = defaultCallArgs.WithMethodName("testRevoke")
+ })
+
+ It("should revoke when sending as the granter", func() {
+ // set up an approval to be revoked
+ cArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(cArgs)
+
+ s.NextBlock()
+
+ revokeArgs := defaultRevokeArgs.WithArgs(contractAddr, []string{staking.DelegateMsg})
+
+ revocationCheck := passCheck.WithExpEvents(authorization.EventTypeRevocation)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, revocationCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract")
+
+ // check approvals
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, contractAddr, s.address)
+ Expect(authz).To(BeNil(), "expected authorization to be revoked")
+ })
+
+ It("should not revoke when approval is issued by a different granter", func() {
+ // Create a delegate authorization where the granter is a different account from the default test suite one
+ createdAuthz := staking.DelegateAuthz
+ granteeAddr := testutiltx.GenerateAddress()
+ granterAddr := testutiltx.GenerateAddress()
+ validators := s.app.StakingKeeper.GetLastValidators(s.ctx)
+ valAddrs := make([]sdk.ValAddress, len(validators))
+ for i, val := range validators {
+ valAddrs[i] = val.GetOperator()
+ }
+ delegationAuthz, err := stakingtypes.NewStakeAuthorization(
+ valAddrs,
+ nil,
+ createdAuthz,
+ &sdk.Coin{Denom: sdk.DefaultBondDenom, Amount: math.NewInt(1e18)},
+ )
+ Expect(err).To(BeNil(), "failed to create authorization")
+
+ expiration := s.ctx.BlockTime().Add(time.Hour * 24 * 365).UTC()
+ err = s.app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr.Bytes(), granterAddr.Bytes(), delegationAuthz, &expiration)
+ Expect(err).ToNot(HaveOccurred(), "failed to save authorization")
+ authz, _ := s.CheckAuthorization(createdAuthz, granteeAddr, granterAddr)
+ Expect(authz).ToNot(BeNil(), "expected authorization to be created")
+
+ revokeArgs := defaultRevokeArgs.WithArgs(granteeAddr, []string{staking.DelegateMsg})
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract")
+
+ // check approvals
+ authz, _ = s.CheckAuthorization(createdAuthz, granteeAddr, granterAddr)
+ Expect(authz).ToNot(BeNil(), "expected authorization not to be revoked")
+ })
+
+ It("should revert the execution when no approval is found", func() {
+ revokeArgs := defaultRevokeArgs.WithArgs(contractAddr, []string{staking.DelegateMsg})
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract")
+
+ // check approvals
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, contractAddr, s.address)
+ Expect(authz).To(BeNil(), "expected no authorization to be found")
+ })
+
+ It("should not revoke if the approval is for a different message type", func() {
+ // set up an approval
+ cArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(cArgs)
+
+ s.NextBlock()
+
+ revokeArgs := defaultRevokeArgs.WithArgs(contractAddr, []string{staking.UndelegateMsg})
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, revokeArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract")
+
+ // check approval is still there
+ s.ExpectAuthorization(
+ staking.DelegateAuthz,
+ contractAddr,
+ s.address,
+ &sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)},
+ )
+ })
+ })
+
+ Context("create a validator", func() {
+ var (
+ valPriv *ethsecp256k1.PrivKey
+ valAddr sdk.AccAddress
+
+ defaultDescription = staking.Description{
+ Moniker: "new node",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ }
+ defaultCommission = staking.Commission{
+ Rate: big.NewInt(100000000000000000),
+ MaxRate: big.NewInt(100000000000000000),
+ MaxChangeRate: big.NewInt(100000000000000000),
+ }
+ defaultMinSelfDelegation = big.NewInt(1)
+ defaultPubkeyBase64Str = GenerateBase64PubKey()
+ defaultValue = big.NewInt(1e8)
+
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultCreateValidatorArgs contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ defaultCreateValidatorArgs = defaultCallArgs.WithMethodName("testCreateValidator")
+ valAddr, valPriv = testutiltx.NewAccAddressAndKey()
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, valAddr, 1e18)
+ Expect(err).To(BeNil(), "error while funding account: %v", err)
+
+ s.NextBlock()
+ })
+
+ It("tx from validator operator - should NOT create a validator", func() {
+ cArgs := defaultCreateValidatorArgs.
+ WithPrivKey(s.privKey).
+ WithArgs(defaultDescription, defaultCommission, defaultMinSelfDelegation, s.address, defaultPubkeyBase64Str, defaultValue)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).NotTo(BeNil(), "error while calling the smart contract: %v", err)
+
+ _, found := s.app.StakingKeeper.GetValidator(s.ctx, s.address.Bytes())
+ Expect(found).To(BeFalse(), "expected validator NOT to be found")
+ })
+
+ It("tx from another EOA - should create a validator fail", func() {
+ cArgs := defaultCreateValidatorArgs.
+ WithPrivKey(valPriv).
+ WithArgs(defaultDescription, defaultCommission, defaultMinSelfDelegation, s.address, defaultPubkeyBase64Str, defaultValue)
+
+ logCheckArgs := defaultLogCheck.WithErrContains(fmt.Sprintf(staking.ErrDifferentOriginFromDelegator, s.address.String(), common.BytesToAddress(valAddr.Bytes()).String()))
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ _, found := s.app.StakingKeeper.GetValidator(s.ctx, s.address.Bytes())
+ Expect(found).To(BeFalse(), "expected validator not to be found")
+ })
+ })
+
+ Context("to edit a validator", func() {
+ var (
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultEditValArgs contracts.CallArgs
+ valPriv *ethsecp256k1.PrivKey
+ valAddr sdk.AccAddress
+ valHexAddr common.Address
+
+ defaultDescription = staking.Description{
+ Moniker: "edit node",
+ Identity: "[do-not-modify]",
+ Website: "[do-not-modify]",
+ SecurityContact: "[do-not-modify]",
+ Details: "[do-not-modify]",
+ }
+ defaultCommissionRate = big.NewInt(staking.DoNotModifyCommissionRate)
+ defaultMinSelfDelegation = big.NewInt(staking.DoNotModifyMinSelfDelegation)
+
+ minSelfDelegation = big.NewInt(1)
+
+ description = staking.Description{}
+ commission = staking.Commission{}
+ )
+
+ BeforeEach(func() {
+ defaultEditValArgs = defaultCallArgs.WithMethodName("testEditValidator")
+
+ // create a new validator
+ valAddr, valPriv = testutiltx.NewAccAddressAndKey()
+ valHexAddr = common.BytesToAddress(valAddr.Bytes())
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, valAddr, 2e18)
+ Expect(err).To(BeNil(), "error while funding account: %v", err)
+
+ description = staking.Description{
+ Moniker: "original moniker",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ }
+ commission = staking.Commission{
+ Rate: big.NewInt(100000000000000000),
+ MaxRate: big.NewInt(100000000000000000),
+ MaxChangeRate: big.NewInt(100000000000000000),
+ }
+ pubkeyBase64Str := "UuhHQmkUh2cPBA6Rg4ei0M2B04cVYGNn/F8SAUsYIb4="
+ value := big.NewInt(1e18)
+
+ createValidatorArgs := contracts.CallArgs{
+ ContractAddr: s.precompile.Address(),
+ ContractABI: s.precompile.ABI,
+ MethodName: staking.CreateValidatorMethod,
+ PrivKey: valPriv,
+ Args: []interface{}{description, commission, minSelfDelegation, valHexAddr, pubkeyBase64Str, value},
+ }
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, createValidatorArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ s.NextBlock()
+ })
+
+ It("with tx from validator operator - should NOT edit a validator", func() {
+ cArgs := defaultEditValArgs.
+ WithPrivKey(valPriv).
+ WithArgs(
+ defaultDescription, valHexAddr,
+ defaultCommissionRate, defaultMinSelfDelegation,
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).NotTo(BeNil(), "error while calling the smart contract: %v", err)
+
+ validator, found := s.app.StakingKeeper.GetValidator(s.ctx, valAddr.Bytes())
+ Expect(found).To(BeTrue(), "expected validator to be found")
+ Expect(validator.Description.Moniker).NotTo(Equal(defaultDescription.Moniker), "expected validator moniker NOT to be updated")
+ })
+
+ It("with tx from another EOA - should fail", func() {
+ cArgs := defaultEditValArgs.
+ WithPrivKey(s.privKey).
+ WithArgs(
+ defaultDescription, valHexAddr,
+ defaultCommissionRate, defaultMinSelfDelegation,
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "expected error while calling the precompile")
+ Expect(err.Error()).To(ContainSubstring(vm.ErrExecutionReverted.Error()))
+
+ // validator should remain unchanged
+ validator, found := s.app.StakingKeeper.GetValidator(s.ctx, valAddr.Bytes())
+ Expect(found).To(BeTrue(), "expected validator to be found")
+ Expect(validator.Description.Moniker).To(Equal("original moniker"), "expected validator moniker is updated")
+ Expect(validator.Commission.Rate.BigInt().String()).To(Equal("100000000000000000"), "expected validator commission rate remain unchanged")
+ })
+ })
+
+ Context("delegating", func() {
+ var (
+ // prevDelegation is the delegation that is available prior to the test (an initial delegation is
+ // added in the test suite setup).
+ prevDelegation stakingtypes.Delegation
+ // defaultDelegateArgs are the default arguments for the delegate call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ defaultDelegateArgs contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ // get the delegation that is available prior to the test
+ prevDelegation, _ = s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+
+ defaultDelegateArgs = defaultCallArgs.WithMethodName("testDelegate")
+ })
+
+ Context("without approval set", func() {
+ BeforeEach(func() {
+ authz, _ := s.CheckAuthorization(staking.DelegateAuthz, contractAddr, s.address)
+ Expect(authz).To(BeNil(), "expected authorization to be nil")
+ })
+
+ It("should not delegate", func() {
+ Expect(s.app.EvmKeeper.GetAccount(s.ctx, contractAddr)).ToNot(BeNil(), "expected contract to exist")
+
+ cArgs := defaultDelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ del, _ := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+ Expect(del).To(Equal(prevDelegation), "no new delegation to be found")
+ })
+ })
+
+ Context("with approval set", func() {
+ BeforeEach(func() {
+ cArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(cArgs)
+ })
+
+ It("should delegate when not exceeding the allowance", func() {
+ cArgs := defaultDelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ expShares := prevDelegation.GetShares().Add(math.LegacyNewDec(1))
+ Expect(delegation.GetShares()).To(Equal(expShares), "expected delegation shares to be 2")
+ })
+
+ Context("Calling the precompile from the StakingReverter contract", func() {
+ var (
+ txSenderInitialBal sdk.Coin
+ contractInitialBalance sdk.Coin
+ gasPrice = math.NewInt(1e9)
+ delAmt = math.NewInt(1e18)
+ )
+
+ BeforeEach(func() {
+ // set approval for the StakingReverter contract
+ s.SetupApproval(s.privKey, stkReverterAddr, delAmt.BigInt(), []string{staking.DelegateMsg})
+
+ txSenderInitialBal = s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ contractInitialBalance = s.app.BankKeeper.GetBalance(s.ctx, stkReverterAddr.Bytes(), s.bondDenom)
+ })
+
+ It("should revert the changes and NOT delegate - successful tx", func() {
+ callArgs := contracts.CallArgs{
+ ContractAddr: stkReverterAddr,
+ ContractABI: stakingReverterContract.ABI,
+ PrivKey: s.privKey,
+ MethodName: "run",
+ Args: []interface{}{
+ big.NewInt(5), s.validators[0].GetOperator().String(),
+ },
+ GasPrice: gasPrice.BigInt(),
+ }
+
+ // Tx should be successful, but no state changes happened
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, callArgs, passCheck)
+ Expect(err).To(BeNil())
+ fees := gasPrice.MulRaw(res.GasUsed)
+
+ // contract balance should remain unchanged
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, stkReverterAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount))
+
+ // No delegation should be created
+ _, found := s.app.StakingKeeper.GetDelegation(s.ctx, stkReverterAddr.Bytes(), s.validators[0].GetOperator())
+ Expect(found).To(BeFalse(), "expected NO delegation to be found")
+
+ // Only fees deducted on tx sender
+ txSenderFinalBal := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(txSenderFinalBal.Amount).To(Equal(txSenderInitialBal.Amount.Sub(fees)))
+ })
+
+ It("should revert the changes and NOT delegate - failed tx - max precompile calls reached", func() {
+ callArgs := contracts.CallArgs{
+ ContractAddr: stkReverterAddr,
+ ContractABI: stakingReverterContract.ABI,
+ PrivKey: s.privKey,
+ MethodName: "run",
+ Args: []interface{}{
+ big.NewInt(7), s.validators[0].GetOperator().String(),
+ },
+ GasPrice: gasPrice.BigInt(),
+ }
+
+ // Tx should fail due to MaxPrecompileCalls
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, callArgs, execRevertedCheck)
+ Expect(err).NotTo(BeNil())
+
+ // contract balance should remain unchanged
+ contractFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, stkReverterAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount))
+
+ // No delegation should be created
+ _, found := s.app.StakingKeeper.GetDelegation(s.ctx, stkReverterAddr.Bytes(), s.validators[0].GetOperator())
+ Expect(found).To(BeFalse(), "expected NO delegation to be found")
+ })
+ })
+
+ Context("Table-driven tests for Delegate method", func() {
+ // testCase is a struct used for cases of contracts calls that have some operation
+ // performed before and/or after the precompile call
+ type testCase struct {
+ before bool
+ after bool
+ }
+
+ var (
+ args contracts.CallArgs
+ delegatorInitialBal sdk.Coin
+ contractInitialBalance sdk.Coin
+ bondedTokensPoolInitialBalance sdk.Coin
+ delAmt = math.NewInt(1e18)
+ gasPrice = math.NewInt(1e9)
+ bondedTokensPoolAccAddr = authtypes.NewModuleAddress("bonded_tokens_pool")
+ )
+
+ BeforeEach(func() {
+ // set authorization for contract
+ callCArgs := contracts.CallArgs{
+ ContractAddr: contractTwoAddr,
+ ContractABI: stakingCallerTwoContract.ABI,
+ PrivKey: s.privKey,
+ MethodName: "testApprove",
+ Args: []interface{}{
+ contractTwoAddr, []string{staking.DelegateMsg}, delAmt.BigInt(),
+ },
+ }
+
+ s.SetupApprovalWithContractCalls(callCArgs)
+
+ args = callCArgs.
+ WithMethodName("testDelegateWithCounterAndTransfer").
+ WithGasPrice(gasPrice.BigInt())
+
+ delegatorInitialBal = s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ contractInitialBalance = s.app.BankKeeper.GetBalance(s.ctx, contractTwoAddr.Bytes(), s.bondDenom)
+ bondedTokensPoolInitialBalance = s.app.BankKeeper.GetBalance(s.ctx, bondedTokensPoolAccAddr, s.bondDenom)
+ })
+
+ DescribeTable("should delegate and update balances accordingly", func(tc testCase) {
+ cArgs := args.
+ WithArgs(
+ s.address, valAddr.String(), delAmt.BigInt(), tc.before, tc.after,
+ )
+
+ // This is the amount of tokens transferred from the contract to the delegator
+ // during the contract call
+ transferToDelAmt := math.ZeroInt()
+ for _, transferred := range []bool{tc.before, tc.after} {
+ if transferred {
+ transferToDelAmt = transferToDelAmt.AddRaw(15)
+ }
+ }
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeDelegate)
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+ fees := gasPrice.MulRaw(res.GasUsed)
+
+ // check the contract's balance was deducted to fund the vesting account
+ contractFinalBal := s.app.BankKeeper.GetBalance(s.ctx, contractTwoAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBal.Amount).To(Equal(contractInitialBalance.Amount.Sub(transferToDelAmt)))
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ expShares := prevDelegation.GetShares().Add(math.LegacyNewDec(1))
+ Expect(delegation.GetShares()).To(Equal(expShares), "expected delegation shares to be 2")
+
+ delegatorFinalBal := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), s.bondDenom)
+ Expect(delegatorFinalBal.Amount).To(Equal(delegatorInitialBal.Amount.Sub(fees).Sub(delAmt).Add(transferToDelAmt)))
+
+ // check the bondedTokenPool is updated with the delegated tokens
+ bondedTokensPoolFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, bondedTokensPoolAccAddr, s.bondDenom)
+ Expect(bondedTokensPoolFinalBalance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount.Add(delAmt)))
+ },
+ Entry("contract tx with transfer to delegator before and after precompile call ", testCase{
+ before: true,
+ after: true,
+ }),
+ Entry("contract tx with transfer to delegator before precompile call ", testCase{
+ before: true,
+ after: false,
+ }),
+ Entry("contract tx with transfer to delegator after precompile call ", testCase{
+ before: false,
+ after: true,
+ }),
+ )
+
+ It("should NOT delegate and update balances accordingly - internal transfer to tokens pool", func() {
+ cArgs := args.
+ WithMethodName("testDelegateWithTransfer").
+ WithArgs(
+ common.BytesToAddress(bondedTokensPoolAccAddr),
+ s.address, valAddr.String(), delAmt.BigInt(), true, true,
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).NotTo(BeNil())
+
+ // contract balance should remain unchanged
+ contractFinalBal := s.app.BankKeeper.GetBalance(s.ctx, contractTwoAddr.Bytes(), s.bondDenom)
+ Expect(contractFinalBal.Amount).To(Equal(contractInitialBalance.Amount))
+
+ // check the bondedTokenPool should remain unchanged
+ bondedTokensPoolFinalBalance := s.app.BankKeeper.GetBalance(s.ctx, bondedTokensPoolAccAddr, s.bondDenom)
+ Expect(bondedTokensPoolFinalBalance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount))
+ })
+ })
+
+ It("should not delegate when exceeding the allowance", func() {
+ cArgs := defaultDelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(2e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ del, _ := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+ Expect(del).To(Equal(prevDelegation), "no new delegation to be found")
+ })
+
+ It("should not delegate when sending from a different address", func() {
+ newAddr, newPriv := testutiltx.NewAccAddressAndKey()
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, newAddr, 1e18)
+ Expect(err).To(BeNil(), "error while funding account: %v", err)
+
+ s.NextBlock()
+
+ delegateArgs := defaultDelegateArgs.
+ WithPrivKey(newPriv).
+ WithArgs(s.address, valAddr.String(), big.NewInt(1e18))
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ del, _ := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), valAddr)
+ Expect(del).To(Equal(prevDelegation), "no new delegation to be found")
+ })
+
+ It("should not delegate when validator does not exist", func() {
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ s.address, nonExistingVal.String(), big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ del, _ := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), nonExistingVal)
+ Expect(del).To(BeZero(), "expected no delegation to be found")
+ })
+
+ It("shouldn't delegate to a validator that is not in the allow list of the approval", func() {
+ // create a new validator, which is not included in the active set of the last block
+ testutil.CreateValidator(s.ctx, s.T(), s.privKey.PubKey(), *s.app.StakingKeeper.Keeper, math.NewInt(100))
+ newValAddr := sdk.ValAddress(s.address.Bytes())
+
+ delegateArgs := defaultDelegateArgs.WithArgs(
+ s.address, newValAddr.String(), big.NewInt(2e18),
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ delegation, _ := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), newValAddr)
+ Expect(delegation.GetShares()).To(Equal(math.LegacyNewDecFromInt(math.NewInt(100))), "expected only the delegation from creating the validator, no more")
+ })
+ })
+
+ Describe("delegation from a vesting account", func() {
+ var (
+ funder common.Address
+ vestAcc common.Address
+ vestAccPriv *ethsecp256k1.PrivKey
+ clawbackAccount *vestingtypes.ClawbackVestingAccount
+ unvested sdk.Coins
+ vested sdk.Coins
+ // unlockedVested are unlocked vested coins of the vesting schedule
+ unlockedVested sdk.Coins
+ defaultArgs contracts.CallArgs
+ )
+
+ BeforeEach(func() {
+ // Setup vesting account
+ funder = s.address
+ vestAcc, vestAccPriv = testutiltx.NewAddrKey()
+
+ clawbackAccount = s.setupVestingAccount(funder.Bytes(), vestAcc.Bytes())
+
+ // Check if all tokens are unvested at vestingStart
+ totalVestingCoins := evmosutil.TestVestingSchedule.TotalVestingCoins
+ unvested = clawbackAccount.GetVestingCoins(s.ctx.BlockTime())
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ Expect(unvested).To(Equal(totalVestingCoins))
+ Expect(vested.IsZero()).To(BeTrue())
+
+ // create approval to allow spending all vesting coins
+ cArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.DelegateMsg}, totalVestingCoins.AmountOf(s.bondDenom).BigInt(),
+ ).WithPrivKey(vestAccPriv)
+ s.SetupApprovalWithContractCalls(cArgs)
+
+ // add the vesting account priv key to the delegate args
+ defaultArgs = defaultDelegateArgs.WithPrivKey(vestAccPriv)
+ })
+
+ Context("before first vesting period - all tokens locked and unvested", func() {
+ BeforeEach(func() {
+ s.NextBlock()
+
+ // Ensure no tokens are vested
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ unvested = clawbackAccount.GetVestingCoins(s.ctx.BlockTime())
+ unlocked := clawbackAccount.GetUnlockedCoins(s.ctx.BlockTime())
+ zeroCoins := sdk.NewCoins(sdk.NewCoin(s.bondDenom, math.ZeroInt()))
+ Expect(vested).To(Equal(zeroCoins))
+ Expect(unvested).To(Equal(evmosutil.TestVestingSchedule.TotalVestingCoins))
+ Expect(unlocked).To(Equal(zeroCoins))
+ })
+
+ It("Should not be able to delegate unvested tokens", func() {
+ delegateArgs := defaultArgs.WithArgs(
+ vestAcc, valAddr.String(), unvested.AmountOf(s.bondDenom).BigInt(),
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ })
+
+ It("Should be able to delegate tokens not involved in vesting schedule", func() {
+ // send some coins to the vesting account
+ coinsToDelegate := sdk.NewCoins(sdk.NewCoin(s.bondDenom, math.NewInt(1e18)))
+ err := evmosutil.FundAccount(s.ctx, s.app.BankKeeper, clawbackAccount.GetAddress(), coinsToDelegate)
+ Expect(err).To(BeNil())
+
+ delegateArgs := defaultArgs.WithArgs(
+ vestAcc, valAddr.String(), coinsToDelegate.AmountOf(s.bondDenom).BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(coinsToDelegate[0].Amount.BigInt()))
+ })
+ })
+
+ Context("after first vesting period and before lockup - some vested tokens, but still all locked", func() {
+ BeforeEach(func() {
+ // Surpass cliff but none of lockup duration
+ cliffDuration := time.Duration(evmosutil.TestVestingSchedule.CliffPeriodLength)
+ s.NextBlockAfter(cliffDuration * time.Second)
+
+ // Check if some, but not all tokens are vested
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ expVested := sdk.NewCoins(sdk.NewCoin(s.bondDenom, evmosutil.TestVestingSchedule.VestedCoinsPerPeriod[0].Amount.Mul(math.NewInt(evmosutil.TestVestingSchedule.CliffMonths))))
+ Expect(vested).NotTo(Equal(evmosutil.TestVestingSchedule.TotalVestingCoins))
+ Expect(vested).To(Equal(expVested))
+
+ // check the vested tokens are still locked
+ unlockedVested = clawbackAccount.GetUnlockedVestedCoins(s.ctx.BlockTime())
+ Expect(unlockedVested).To(Equal(sdk.Coins{}))
+
+ vestingAmtTotal := evmosutil.TestVestingSchedule.TotalVestingCoins
+ res, err := s.app.VestingKeeper.Balances(s.ctx, &vestingtypes.QueryBalancesRequest{Address: clawbackAccount.Address})
+ Expect(err).To(BeNil())
+ Expect(res.Vested).To(Equal(expVested))
+ Expect(res.Unvested).To(Equal(vestingAmtTotal.Sub(expVested...)))
+ // All coins from vesting schedule should be locked
+ Expect(res.Locked).To(Equal(vestingAmtTotal))
+ })
+
+ It("Should be able to delegate locked vested tokens", func() {
+ delegateArgs := defaultArgs.WithArgs(
+ vestAcc, valAddr.String(), vested[0].Amount.BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(vested[0].Amount.BigInt()))
+ })
+
+ It("Should be able to delegate locked vested tokens + free tokens (not in vesting schedule)", func() {
+ // send some coins to the vesting account
+ amt := sdk.NewCoins(sdk.NewCoin(s.bondDenom, math.NewInt(1e18)))
+ err := evmosutil.FundAccount(s.ctx, s.app.BankKeeper, clawbackAccount.GetAddress(), amt)
+ Expect(err).To(BeNil())
+
+ coinsToDelegate := amt.Add(vested...)
+
+ delegateArgs := defaultArgs.WithArgs(
+ vestAcc, valAddr.String(), coinsToDelegate[0].Amount.BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(coinsToDelegate[0].Amount.BigInt()))
+ })
+ })
+
+ Context("Between first and second lockup periods - vested coins are unlocked", func() {
+ BeforeEach(func() {
+ // Surpass first lockup
+ vestDuration := time.Duration(evmosutil.TestVestingSchedule.LockupPeriodLength)
+ s.NextBlockAfter(vestDuration * time.Second)
+
+ // Check if some, but not all tokens are vested and unlocked
+ vested = clawbackAccount.GetVestedCoins(s.ctx.BlockTime())
+ unlocked := clawbackAccount.GetUnlockedCoins(s.ctx.BlockTime())
+ unlockedVested = clawbackAccount.GetUnlockedVestedCoins(s.ctx.BlockTime())
+
+ expVested := sdk.NewCoins(sdk.NewCoin(s.bondDenom, evmosutil.TestVestingSchedule.VestedCoinsPerPeriod[0].Amount.Mul(math.NewInt(evmosutil.TestVestingSchedule.LockupMonths))))
+ expUnlockedVested := expVested
+
+ Expect(vested).NotTo(Equal(evmosutil.TestVestingSchedule.TotalVestingCoins))
+ Expect(vested).To(Equal(expVested))
+ // all vested coins are unlocked
+ Expect(unlockedVested).To(Equal(vested))
+ Expect(unlocked).To(Equal(evmosutil.TestVestingSchedule.UnlockedCoinsPerLockup))
+ Expect(unlockedVested).To(Equal(expUnlockedVested))
+ })
+ It("Should be able to delegate unlocked vested tokens", func() {
+ delegateArgs := defaultArgs.WithArgs(
+ vestAcc, valAddr.String(), unlockedVested[0].Amount.BigInt(),
+ )
+
+ logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, vestAcc.Bytes(), valAddr)
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(delegation.Shares.BigInt()).To(Equal(unlockedVested[0].Amount.BigInt()))
+ })
+ })
+ })
+ })
+
+ Context("unbonding", func() {
+ // NOTE: there's no additional setup necessary because the test suite is already set up with
+ // delegations to the validator
+
+ // defaultUndelegateArgs are the default arguments for the undelegate call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultUndelegateArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultUndelegateArgs = defaultCallArgs.WithMethodName("testUndelegate")
+ })
+
+ Context("without approval set", func() {
+ BeforeEach(func() {
+ authz, _ := s.CheckAuthorization(staking.UndelegateAuthz, contractAddr, s.address)
+ Expect(authz).To(BeNil(), "expected authorization to be nil before test execution")
+ })
+ It("should not undelegate", func() {
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(0), "expected no undelegations to be found")
+ })
+ })
+
+ Context("with approval set", func() {
+ BeforeEach(func() {
+ approveArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.UndelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approveArgs)
+ })
+
+ It("should undelegate when not exceeding the allowance", func() {
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := defaultLogCheck.
+ WithExpEvents(staking.EventTypeUnbond).
+ WithExpPass(true)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(1), "expected one undelegation")
+ Expect(undelegations[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr)
+ })
+
+ It("should not undelegate when exceeding the allowance", func() {
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(2e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(0), "expected no undelegations to be found")
+ })
+
+ It("should not undelegate if the delegation does not exist", func() {
+ undelegateArgs := defaultUndelegateArgs.WithArgs(
+ s.address, nonExistingVal.String(), big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(0), "expected no undelegations to be found")
+ })
+
+ It("should not undelegate when called from a different address", func() {
+ newAddr, newPriv := testutiltx.NewAccAddressAndKey()
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, newAddr, 1e18)
+ Expect(err).To(BeNil(), "error while funding account: %v", err)
+
+ s.NextBlock()
+
+ undelegateArgs := defaultUndelegateArgs.
+ WithPrivKey(newPriv).
+ WithArgs(s.address, valAddr.String(), big.NewInt(1e18))
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(0), "expected no undelegations to be found")
+ })
+ })
+ })
+
+ Context("redelegating", func() {
+ // NOTE: there's no additional setup necessary because the test suite is already set up with
+ // delegations to the validator
+
+ // defaultRedelegateArgs are the default arguments for the redelegate call
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultRedelegateArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultRedelegateArgs = defaultCallArgs.WithMethodName("testRedelegate")
+ })
+
+ Context("without approval set", func() {
+ BeforeEach(func() {
+ authz, _ := s.CheckAuthorization(staking.UndelegateAuthz, contractAddr, s.address)
+ Expect(authz).To(BeNil(), "expected authorization to be nil before test execution")
+ })
+
+ It("should not redelegate", func() {
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(), big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, valAddr2)
+ Expect(redelegations).To(HaveLen(0), "expected no redelegations to be found")
+ })
+ })
+
+ Context("with approval set", func() {
+ BeforeEach(func() {
+ approveArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.RedelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approveArgs)
+ })
+
+ It("should redelegate when not exceeding the allowance", func() {
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(), big.NewInt(1e18),
+ )
+
+ logCheckArgs := defaultLogCheck.
+ WithExpEvents(staking.EventTypeRedelegate).
+ WithExpPass(true)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, valAddr2)
+ Expect(redelegations).To(HaveLen(1), "expected one redelegation to be found")
+ bech32Addr := sdk.AccAddress(s.address.Bytes())
+ Expect(redelegations[0].DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", s.address)
+ Expect(redelegations[0].ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr)
+ Expect(redelegations[0].ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2)
+ })
+
+ It("should not redelegate when exceeding the allowance", func() {
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(), big.NewInt(2e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, valAddr2)
+ Expect(redelegations).To(HaveLen(0), "expected no redelegations to be found")
+ })
+
+ It("should not redelegate if the delegation does not exist", func() {
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, nonExistingVal.String(), valAddr2.String(), big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), nonExistingVal, valAddr2)
+ Expect(redelegations).To(HaveLen(0), "expected no redelegations to be found")
+ })
+
+ It("should not redelegate when calling from a different address", func() {
+ newAddr, newPriv := testutiltx.NewAccAddressAndKey()
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, newAddr, 1e18)
+ Expect(err).To(BeNil(), "error while funding account: %v", err)
+
+ s.NextBlock()
+
+ redelegateArgs := defaultRedelegateArgs.
+ WithPrivKey(newPriv).
+ WithArgs(s.address, valAddr.String(), valAddr2.String(), big.NewInt(1e18))
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, valAddr2)
+ Expect(redelegations).To(HaveLen(0), "expected no redelegations to be found")
+ })
+
+ It("should not redelegate when the validator does not exist", func() {
+ redelegateArgs := defaultRedelegateArgs.WithArgs(
+ s.address, valAddr.String(), nonExistingVal.String(), big.NewInt(1e18),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, nonExistingVal)
+ Expect(redelegations).To(HaveLen(0), "expected no redelegations to be found")
+ })
+ })
+ })
+
+ Context("canceling unbonding delegations", func() {
+ var (
+ // defaultCancelUnbondingArgs are the default arguments for the cancelUnbondingDelegation call
+ //
+ // NOTE: this has to be set up in the BeforeEach block because the private key is only available then
+ defaultCancelUnbondingArgs contracts.CallArgs
+
+ // expCreationHeight is the expected creation height of the unbonding delegation
+ expCreationHeight = int64(6)
+ )
+
+ BeforeEach(func() {
+ defaultCancelUnbondingArgs = defaultCallArgs.WithMethodName("testCancelUnbonding")
+
+ // Set up an unbonding delegation
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.UndelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+
+ s.NextBlock()
+
+ undelegateArgs := defaultCallArgs.
+ WithMethodName("testUndelegate").
+ WithArgs(s.address, valAddr.String(), big.NewInt(1e18))
+
+ logCheckArgs := defaultLogCheck.
+ WithExpEvents(staking.EventTypeUnbond).
+ WithExpPass(true)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err)
+
+ s.NextBlock()
+
+ // Check that the unbonding delegation was created
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected one unbonding delegation to be found")
+ Expect(unbondingDelegations[0].DelegatorAddress).To(Equal(sdk.AccAddress(s.address.Bytes()).String()), "expected delegator address to be %s", s.address)
+ Expect(unbondingDelegations[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr)
+ Expect(unbondingDelegations[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found")
+ Expect(unbondingDelegations[0].Entries[0].CreationHeight).To(Equal(s.ctx.BlockHeight()-1), "expected different creation height")
+ Expect(unbondingDelegations[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance")
+ })
+
+ Context("without approval set", func() {
+ It("should not cancel unbonding delegations", func() {
+ cArgs := defaultCancelUnbondingArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18), big.NewInt(s.ctx.BlockHeight()),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected unbonding delegation not to be canceled")
+ })
+ })
+
+ Context("with approval set", func() {
+ BeforeEach(func() {
+ // Set up an unbonding delegation
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.CancelUnbondingDelegationMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+
+ s.NextBlock()
+ })
+
+ It("should cancel unbonding delegations when not exceeding allowance", func() {
+ cArgs := defaultCancelUnbondingArgs.WithGasLimit(1e9).WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18), big.NewInt(expCreationHeight),
+ )
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeCancelUnbondingDelegation)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(0), "expected unbonding delegation to be canceled")
+ })
+
+ It("should not cancel unbonding delegations when exceeding allowance", func() {
+ approvalArgs := defaultApproveArgs.
+ WithArgs(contractAddr, []string{staking.CancelUnbondingDelegationMsg}, big.NewInt(1))
+ s.SetupApprovalWithContractCalls(approvalArgs)
+
+ cArgs := defaultCancelUnbondingArgs.WithArgs(
+ s.address, valAddr.String(), big.NewInt(1e18), big.NewInt(s.ctx.BlockHeight()),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected unbonding delegation to not be canceled")
+ })
+
+ It("should not cancel unbonding any delegations when unbonding delegation does not exist", func() {
+ cancelArgs := defaultCancelUnbondingArgs.WithArgs(
+ s.address, nonExistingVal.String(), big.NewInt(1e18), big.NewInt(s.ctx.BlockHeight()),
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cancelArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected unbonding delegation to not be canceled")
+ })
+
+ It("should not cancel unbonding delegations when calling from a different address", func() {
+ newAddr, newPriv := testutiltx.NewAccAddressAndKey()
+ err := evmosutil.FundAccountWithBaseDenom(s.ctx, s.app.BankKeeper, newAddr, 1e18)
+ Expect(err).To(BeNil(), "error while funding account: %v", err)
+
+ s.NextBlock()
+
+ cancelUnbondArgs := defaultCancelUnbondingArgs.
+ WithPrivKey(newPriv).
+ WithArgs(s.address, valAddr.String(), big.NewInt(1e18), big.NewInt(s.ctx.BlockHeight()))
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cancelUnbondArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected unbonding delegation to not be canceled")
+ })
+ })
+ })
+
+ Context("querying allowance", func() {
+ // defaultAllowanceArgs are the default arguments for querying the allowance
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultAllowanceArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultAllowanceArgs = defaultCallArgs.WithMethodName("getAllowance")
+ })
+
+ It("without approval set it should show no allowance", func() {
+ allowanceArgs := defaultAllowanceArgs.WithArgs(
+ contractAddr, staking.CancelUnbondingDelegationMsg,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, allowanceArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var allowanceInt *big.Int
+ err = s.precompile.UnpackIntoInterface(&allowanceInt, "allowance", ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unmarshalling the allowance: %v", err)
+ Expect(allowanceInt.Int64()).To(Equal(int64(0)), "expected empty allowance")
+ })
+
+ It("with approval set it should show the granted allowance", func() {
+ // setup approval
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.CancelUnbondingDelegationMsg}, big.NewInt(1e18),
+ )
+
+ s.SetupApprovalWithContractCalls(approvalArgs)
+
+ // query allowance
+ allowanceArgs := defaultAllowanceArgs.WithArgs(
+ contractAddr, staking.CancelUnbondingDelegationMsg,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, allowanceArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var allowanceInt *big.Int
+ err = s.precompile.UnpackIntoInterface(&allowanceInt, "allowance", ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unmarshalling the allowance: %v", err)
+ Expect(allowanceInt).To(Equal(big.NewInt(1e18)), "expected allowance to be 1e18")
+ })
+ })
+
+ Context("querying validator", func() {
+ // defaultValidatorArgs are the default arguments for querying the validator
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultValidatorArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultValidatorArgs = defaultCallArgs.WithMethodName("getValidator")
+ })
+
+ It("with non-existing address should return an empty validator", func() {
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ nonExistingAddr,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+ Expect(valOut.Validator.OperatorAddress).To(Equal(""), "expected empty validator address")
+ Expect(valOut.Validator.Status).To(Equal(uint8(0)), "expected validator status to be 0 (unspecified)")
+ })
+
+ It("with existing address should return the validator", func() {
+ varHexAddr := common.BytesToAddress(valAddr.Bytes())
+ validatorArgs := defaultValidatorArgs.WithArgs(
+ varHexAddr,
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+ Expect(valOut.Validator.OperatorAddress).To(Equal(varHexAddr.String()), "expected validator address to match")
+ Expect(valOut.Validator.DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares")
+ })
+
+ It("with status bonded and pagination", func() {
+ validatorArgs := defaultCallArgs.
+ WithMethodName("getValidators").
+ WithArgs(
+ stakingtypes.Bonded.String(),
+ query.PageRequest{
+ Limit: 1,
+ CountTotal: true,
+ },
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorsOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+ Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.validators))))
+ Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty())
+ Expect(valOut.Validators[0].DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares")
+ })
+ })
+
+ Context("querying validators", func() {
+ var defaultValidatorsArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultValidatorsArgs = defaultCallArgs.WithMethodName("getValidators")
+ })
+
+ It("should return validators (default pagination)", func() {
+ validatorsArgs := defaultValidatorsArgs.WithArgs(
+ stakingtypes.Bonded.String(),
+ query.PageRequest{},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorsArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorsOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+ Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.validators))))
+ Expect(valOut.PageResponse.NextKey).To(BeEmpty())
+ Expect(valOut.Validators).To(HaveLen(len(s.validators)), "expected all validators to be returned")
+ // return order can change, that's why each validator is checked individually
+ for _, val := range valOut.Validators {
+ s.CheckValidatorOutput(val)
+ }
+ })
+
+ //nolint:dupl // this is a duplicate of the test for EOA calls to the precompile
+ It("should return validators with pagination limit = 1", func() {
+ const limit uint64 = 1
+ validatorArgs := defaultValidatorsArgs.WithArgs(
+ stakingtypes.Bonded.String(),
+ query.PageRequest{
+ Limit: limit,
+ CountTotal: true,
+ },
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorsOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ // no pagination, should return default values
+ Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty())
+ Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.validators))))
+
+ Expect(valOut.Validators).To(HaveLen(int(limit)), "expected one validator to be returned")
+
+ // return order can change, that's why each validator is checked individually
+ for _, val := range valOut.Validators {
+ s.CheckValidatorOutput(val)
+ }
+ })
+
+ It("should revert the execution if the bonding type is not known", func() {
+ validatorArgs := defaultValidatorsArgs.WithArgs(
+ "15", // invalid bonding type
+ query.PageRequest{},
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+ })
+
+ It("should return an empty array if there are no validators with the given bonding type", func() {
+ validatorArgs := defaultValidatorsArgs.WithArgs(
+ stakingtypes.Unbonded.String(),
+ query.PageRequest{},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, validatorArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var valOut staking.ValidatorsOutput
+ err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err)
+
+ Expect(valOut.PageResponse.NextKey).To(BeEmpty())
+ Expect(valOut.PageResponse.Total).To(Equal(uint64(0)))
+ Expect(valOut.Validators).To(HaveLen(0), "expected no validators to be returned")
+ })
+ })
+
+ Context("querying delegation", func() {
+ // defaultDelegationArgs are the default arguments for querying the delegation
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultDelegationArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultDelegationArgs = defaultCallArgs.WithMethodName("getDelegation")
+ })
+
+ It("which does not exist should return an empty delegation", func() {
+ delegationArgs := defaultDelegationArgs.WithArgs(
+ nonExistingAddr, valAddr.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var delOut staking.DelegationOutput
+ err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err)
+ Expect(delOut.Balance.Amount.Int64()).To(Equal(int64(0)), "expected a different delegation balance")
+ Expect(delOut.Balance.Denom).To(Equal(utils.BaseDenom), "expected a different delegation balance")
+ })
+
+ It("which exists should return the delegation", func() {
+ delegationArgs := defaultDelegationArgs.WithArgs(
+ s.address, valAddr.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var delOut staking.DelegationOutput
+ err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err)
+ Expect(delOut.Balance).To(Equal(
+ cmn.Coin{Denom: utils.BaseDenom, Amount: big.NewInt(1e18)}),
+ "expected a different delegation balance",
+ )
+ })
+ })
+
+ Context("querying redelegation", func() {
+ // defaultRedelegationArgs are the default arguments for querying the redelegation
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultRedelegationArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultRedelegationArgs = defaultCallArgs.WithMethodName("getRedelegation")
+ })
+
+ It("which does not exist should return an empty redelegation", func() {
+ redelegationArgs := defaultRedelegationArgs.WithArgs(
+ s.address, valAddr.String(), nonExistingVal.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var redOut staking.RedelegationOutput
+ err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err)
+ Expect(redOut.Redelegation.Entries).To(HaveLen(0), "expected no redelegation entries")
+ })
+
+ It("which exists should return the redelegation", func() {
+ // set up approval
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.RedelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+
+ s.NextBlock()
+
+ // set up redelegation
+ redelegateArgs := defaultCallArgs.
+ WithMethodName("testRedelegate").
+ WithArgs(s.address, valAddr.String(), valAddr2.String(), big.NewInt(1))
+
+ redelegateCheck := passCheck.
+ WithExpEvents(staking.EventTypeRedelegate)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, redelegateCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // check that the redelegation was created
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, valAddr2)
+ Expect(redelegations).To(HaveLen(1), "expected one redelegation to be found")
+ bech32Addr := sdk.AccAddress(s.address.Bytes())
+ Expect(redelegations[0].DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", s.address)
+ Expect(redelegations[0].ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr)
+ Expect(redelegations[0].ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2)
+
+ // query redelegation
+ redelegationArgs := defaultRedelegationArgs.WithArgs(
+ s.address, valAddr.String(), valAddr2.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var redOut staking.RedelegationOutput
+ err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err)
+ Expect(redOut.Redelegation.Entries).To(HaveLen(1), "expected one redelegation entry to be returned")
+ })
+ })
+
+ Describe("query redelegations", func() {
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultRedelegationsArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultRedelegationsArgs = defaultCallArgs.WithMethodName("getRedelegations")
+ })
+
+ It("which exists should return all the existing redelegations w/pagination", func() {
+ // set up approval
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.RedelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+ s.NextBlock()
+
+ // set up redelegation
+ redelegateArgs := defaultCallArgs.
+ WithMethodName("testRedelegate").
+ WithArgs(s.address, valAddr.String(), valAddr2.String(), big.NewInt(1))
+
+ redelegateCheck := passCheck.
+ WithExpEvents(staking.EventTypeRedelegate)
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegateArgs, redelegateCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ // check that the redelegation was created
+ redelegations := s.app.StakingKeeper.GetAllRedelegations(s.ctx, s.address.Bytes(), valAddr, valAddr2)
+ Expect(redelegations).To(HaveLen(1), "expected one redelegation to be found")
+ bech32Addr := sdk.AccAddress(s.address.Bytes())
+ Expect(redelegations[0].DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", s.address)
+ Expect(redelegations[0].ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr)
+ Expect(redelegations[0].ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2)
+
+ // query redelegations by delegator address
+ redelegationArgs := defaultRedelegationsArgs.
+ WithArgs(
+ s.address, "", "", query.PageRequest{Limit: 1, CountTotal: true},
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, redelegationArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var redOut staking.RedelegationsOutput
+ err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationsMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err)
+ Expect(redOut.Response).To(HaveLen(1), "expected one redelegation entry to be returned")
+ Expect(redOut.Response[0].Entries).To(HaveLen(1), "expected one redelegation entry to be returned")
+ Expect(redOut.PageResponse.Total).To(Equal(uint64(1)))
+ Expect(redOut.PageResponse.NextKey).To(BeEmpty())
+ })
+ })
+
+ Context("querying unbonding delegation", func() {
+ // defaultQueryUnbondingArgs are the default arguments for querying the unbonding delegation
+ //
+ // NOTE: this has to be populated in the BeforeEach block because the private key is not initialized before
+ var defaultQueryUnbondingArgs contracts.CallArgs
+
+ BeforeEach(func() {
+ defaultQueryUnbondingArgs = defaultCallArgs.WithMethodName("getUnbondingDelegation")
+
+ // Set up an unbonding delegation
+ approvalArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.UndelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approvalArgs)
+
+ s.NextBlock()
+
+ undelegateArgs := defaultCallArgs.
+ WithMethodName("testUndelegate").
+ WithArgs(s.address, valAddr.String(), big.NewInt(1e18))
+
+ logCheckArgs := passCheck.
+ WithExpEvents(staking.EventTypeUnbond)
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, undelegateArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err)
+
+ // Check that the unbonding delegation was created
+ unbondingDelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(unbondingDelegations).To(HaveLen(1), "expected one unbonding delegation to be found")
+ Expect(unbondingDelegations[0].DelegatorAddress).To(Equal(sdk.AccAddress(s.address.Bytes()).String()), "expected delegator address to be %s", s.address)
+ Expect(unbondingDelegations[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr)
+ Expect(unbondingDelegations[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found")
+ Expect(unbondingDelegations[0].Entries[0].CreationHeight).To(Equal(s.ctx.BlockHeight()), "expected different creation height")
+ Expect(unbondingDelegations[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance")
+ })
+
+ It("which does not exist should return an empty unbonding delegation", func() {
+ queryUnbondingArgs := defaultQueryUnbondingArgs.WithArgs(
+ s.address, valAddr2.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, queryUnbondingArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var unbondingDelegationOutput staking.UnbondingDelegationOutput
+ err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err)
+ Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(0), "expected one unbonding delegation entry")
+ })
+
+ It("which exists should return the unbonding delegation", func() {
+ queryUnbondingArgs := defaultQueryUnbondingArgs.WithArgs(
+ s.address, valAddr.String(),
+ )
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, queryUnbondingArgs, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var unbondOut staking.UnbondingDelegationOutput
+ err = s.precompile.UnpackIntoInterface(&unbondOut, staking.UnbondingDelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err)
+ Expect(unbondOut.UnbondingDelegation.Entries).To(HaveLen(1), "expected one unbonding delegation entry to be returned")
+ Expect(unbondOut.UnbondingDelegation.Entries[0].Balance).To(Equal(big.NewInt(1e18)), "expected different balance")
+ })
+ })
+
+ Context("testing sequential function calls to the precompile", func() {
+ // NOTE: there's no additional setup necessary because the test suite is already set up with
+ // delegations to the validator
+ It("should revert everything if any operation fails", func() {
+ cArgs := defaultCallArgs.
+ WithMethodName("testApproveAndThenUndelegate").
+ WithGasLimit(1e8).
+ WithArgs(contractAddr, big.NewInt(250), big.NewInt(500), valAddr.String())
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ // There should be no authorizations because everything should have been reverted
+ authz, _ := s.CheckAuthorization(staking.UndelegateAuthz, contractAddr, s.address)
+ Expect(authz).To(BeNil(), "expected authorization to be nil")
+
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(0), "expected no unbonding delegations")
+ })
+
+ It("should write to state if all operations succeed", func() {
+ cArgs := defaultCallArgs.
+ WithMethodName("testApproveAndThenUndelegate").
+ WithGasLimit(1e8).
+ WithArgs(contractAddr, big.NewInt(1000), big.NewInt(500), valAddr.String())
+
+ logCheckArgs := passCheck.
+ WithExpEvents(authorization.EventTypeApproval, staking.EventTypeUnbond)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, cArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ authz, _ := s.CheckAuthorization(staking.UndelegateAuthz, contractAddr, s.address)
+ Expect(authz).ToNot(BeNil(), "expected authorization not to be nil")
+
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+ Expect(undelegations).To(HaveLen(1), "expected one unbonding delegation")
+ Expect(undelegations[0].ValidatorAddress).To(Equal(valAddr.String()), "expected different validator address")
+ })
+ })
+
+ Context("when using special call opcodes", func() {
+ testcases := []struct {
+ // calltype is the opcode to use
+ calltype string
+ // expTxPass defines if executing transactions should be possible with the given opcode.
+ // Queries should work for all options.
+ expTxPass bool
+ }{
+ {"call", true},
+ {"callcode", false},
+ {"staticcall", false},
+ {"delegatecall", false},
+ }
+
+ BeforeEach(func() {
+ // approve undelegate message
+ approveArgs := defaultApproveArgs.WithArgs(
+ contractAddr, []string{staking.UndelegateMsg}, big.NewInt(1e18),
+ )
+ s.SetupApprovalWithContractCalls(approveArgs)
+
+ s.NextBlock()
+ })
+
+ for _, tc := range testcases {
+ // NOTE: this is necessary because of Ginkgo behavior -- if not done, the value of tc
+ // inside the It block will always be the last entry in the testcases slice
+ testcase := tc
+
+ It(fmt.Sprintf("should not execute transactions for calltype %q", testcase.calltype), func() {
+ args := defaultCallArgs.
+ WithMethodName("testCallUndelegate").
+ WithArgs(s.address, valAddr.String(), big.NewInt(1e18), testcase.calltype)
+
+ checkArgs := execRevertedCheck
+ if testcase.expTxPass {
+ checkArgs = passCheck.WithExpEvents(staking.EventTypeUnbond)
+ }
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, args, checkArgs)
+ if testcase.expTxPass {
+ Expect(err).To(BeNil(), "error while calling the smart contract for calltype %s: %v", testcase.calltype, err)
+ } else {
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract for calltype %s: %v", testcase.calltype, err)
+ }
+ // check no delegations are unbonding
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+
+ if testcase.expTxPass {
+ Expect(undelegations).To(HaveLen(1), "expected an unbonding delegation")
+ Expect(undelegations[0].ValidatorAddress).To(Equal(valAddr.String()), "expected different validator address")
+ Expect(undelegations[0].DelegatorAddress).To(Equal(sdk.AccAddress(s.address.Bytes()).String()), "expected different delegator address")
+ } else {
+ Expect(undelegations).To(HaveLen(0), "expected no unbonding delegations for calltype %s", testcase.calltype)
+ }
+ })
+
+ It(fmt.Sprintf("should execute queries for calltype %q", testcase.calltype), func() {
+ args := defaultCallArgs.
+ WithMethodName("testCallDelegation").
+ WithArgs(s.address, valAddr.String(), testcase.calltype)
+
+ _, ethRes, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, args, passCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ var delOut staking.DelegationOutput
+ err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret)
+ Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err)
+ Expect(delOut.Shares).To(Equal(math.LegacyNewDec(1).BigInt()), "expected different delegation shares")
+ Expect(delOut.Balance.Amount).To(Equal(big.NewInt(1e18)), "expected different delegation balance")
+ if testcase.calltype != "callcode" { // having some trouble with returning the denom from inline assembly but that's a very special edge case which might never be used
+ Expect(delOut.Balance.Denom).To(Equal(s.bondDenom), "expected different denomination")
+ }
+ })
+ }
+ })
+
+ // NOTE: These tests were added to replicate a problematic behavior, that occurred when a contract
+ // adjusted the state in multiple subsequent function calls, which adjusted the EVM state as well as
+ // things from the Cosmos SDK state (e.g. a bank balance).
+ // The result was, that changes made to the Cosmos SDK state have been overwritten during the next function
+ // call, because the EVM state was not updated in between.
+ //
+ // This behavior was fixed by updating the EVM state after each function call.
+ Context("when triggering multiple state changes in one function", func() {
+ // delegationAmount is the amount to be delegated
+ delegationAmount := big.NewInt(1e18)
+
+ BeforeEach(func() {
+ // Set up funding for the contract address.
+ // NOTE: we are first asserting that no balance exists and then check successful
+ // funding afterwards.
+ balanceBefore := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(balanceBefore.Amount.Int64()).To(BeZero(), "expected contract balance to be 0 before funding")
+
+ err = s.app.BankKeeper.SendCoins(
+ s.ctx, s.address.Bytes(), contractAddr.Bytes(),
+ sdk.Coins{sdk.Coin{Denom: s.bondDenom, Amount: math.NewIntFromBigInt(delegationAmount)}},
+ )
+ Expect(err).To(BeNil(), "error while sending coins: %v", err)
+
+ s.NextBlock()
+
+ balanceAfterFunding := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(balanceAfterFunding.Amount.BigInt()).To(Equal(delegationAmount), "expected different contract balance after funding")
+
+ // Check no delegation exists from the contract to the validator
+ _, found := s.app.StakingKeeper.GetDelegation(s.ctx, contractAddr.Bytes(), valAddr)
+ Expect(found).To(BeFalse(), "expected delegation not to be found before testing")
+ })
+
+ It("delegating and increasing counter should change the bank balance accordingly", func() {
+ delegationArgs := defaultCallArgs.
+ WithGasLimit(1e9).
+ WithMethodName("testDelegateIncrementCounter").
+ WithArgs(valAddr.String(), delegationAmount)
+
+ approvalAndDelegationCheck := passCheck.WithExpEvents(
+ authorization.EventTypeApproval, staking.EventTypeDelegate,
+ )
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, approvalAndDelegationCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+
+ del, found := s.app.StakingKeeper.GetDelegation(s.ctx, contractAddr.Bytes(), valAddr)
+
+ Expect(found).To(BeTrue(), "expected delegation to be found")
+ Expect(del.GetShares().BigInt()).To(Equal(delegationAmount), "expected different delegation shares")
+
+ postBalance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(postBalance.Amount.Int64()).To(BeZero(), "expected balance to be 0 after contract call")
+ })
+ })
+
+ Context("when updating the stateDB prior to calling the precompile", func() {
+ It("should utilize the same contract balance to delegate", func() {
+ delegationArgs := defaultCallArgs.
+ WithGasLimit(1e9).
+ WithMethodName("approveDepositAndDelegate").
+ WithArgs(valAddr.String()).
+ WithAmount(big.NewInt(2e18))
+
+ approvalAndDelegationCheck := passCheck.WithExpEvents(
+ authorization.EventTypeApproval, staking.EventTypeDelegate,
+ )
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, approvalAndDelegationCheck)
+ Expect(err).To(BeNil(), "error while calling the smart contract: %v", err)
+ balance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(balance.Amount.Int64()).To(BeZero(), "expected different contract balance after funding")
+ delegation := s.app.StakingKeeper.GetAllDelegatorDelegations(s.ctx, contractAddr.Bytes())
+ Expect(delegation).To(HaveLen(1), "expected one delegation")
+ Expect(delegation[0].GetShares().BigInt()).To(Equal(big.NewInt(2e18)), "expected different delegation shares")
+ })
+ //nolint:dupl
+ It("should revert the contract balance to the original value when the precompile fails", func() {
+ delegationArgs := defaultCallArgs.
+ WithGasLimit(1e9).
+ WithMethodName("approveDepositAndDelegateExceedingAllowance").
+ WithArgs(valAddr.String()).
+ WithAmount(big.NewInt(2e18))
+
+ approvalAndDelegationCheck := defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error())
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, approvalAndDelegationCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ balance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(balance.Amount.Int64()).To(BeZero(), "expected different contract balance after funding")
+ auth, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, contractAddr.Bytes(), s.address.Bytes(), staking.DelegateMsg)
+ Expect(auth).To(BeNil(), "expected no authorization")
+ delegation := s.app.StakingKeeper.GetAllDelegatorDelegations(s.ctx, contractAddr.Bytes())
+ Expect(delegation).To(HaveLen(0), "expected no delegations")
+ })
+
+ //nolint:dupl
+ It("should revert the contract balance to the original value when the custom logic after the precompile fails ", func() {
+ delegationArgs := defaultCallArgs.
+ WithGasLimit(1e9).
+ WithMethodName("approveDepositDelegateAndFailCustomLogic").
+ WithArgs(valAddr.String()).
+ WithAmount(big.NewInt(2e18))
+
+ approvalAndDelegationCheck := defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error())
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, delegationArgs, approvalAndDelegationCheck)
+ Expect(err).To(HaveOccurred(), "error while calling the smart contract: %v", err)
+
+ balance := s.app.BankKeeper.GetBalance(s.ctx, contractAddr.Bytes(), s.bondDenom)
+ Expect(balance.Amount.Int64()).To(BeZero(), "expected different contract balance after funding")
+ auth, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, contractAddr.Bytes(), s.address.Bytes(), staking.DelegateMsg)
+ Expect(auth).To(BeNil(), "expected no authorization")
+ delegation := s.app.StakingKeeper.GetAllDelegatorDelegations(s.ctx, contractAddr.Bytes())
+ Expect(delegation).To(HaveLen(0), "expected no delegations")
+ })
+ })
+})
+
+// These tests are used to check that when batching multiple state changing transactions
+// in one block, both states (Cosmos and EVM) are updated or reverted correctly.
+//
+// For this purpose, we are deploying an ERC20 contract and updating StakingCaller.sol
+// to include a method where an ERC20 balance is sent between accounts as well as
+// an interaction with the staking precompile is made.
+//
+// There are ERC20 tokens minted to the address of the deployed StakingCaller contract,
+// which will transfer these to the message sender when successfully executed.
+// Using the staking EVM extension, there is an approval made before the ERC20 transfer
+// as well as a delegation after the ERC20 transfer.
+var _ = Describe("Batching cosmos and eth interactions", func() {
+ const (
+ erc20Name = "Test"
+ erc20Token = "TTT"
+ erc20Decimals = uint8(18)
+ )
+
+ var (
+ // contractAddr is the address of the deployed StakingCaller contract
+ contractAddr common.Address
+ // stakingCallerContract is the contract instance calling into the staking precompile
+ stakingCallerContract evmtypes.CompiledContract
+ // erc20ContractAddr is the address of the deployed ERC20 contract
+ erc20ContractAddr common.Address
+ // erc20Contract is the compiled ERC20 contract
+ erc20Contract = compiledcontracts.ERC20MinterBurnerDecimalsContract
+
+ // err is a standard error
+ err error
+ // execRevertedCheck is a standard log check for a reverted transaction
+ execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error())
+
+ // mintAmount is the amount of ERC20 tokens minted to the StakingCaller contract
+ mintAmount = big.NewInt(1e18)
+ // transferredAmount is the amount of ERC20 tokens to transfer during the tests
+ transferredAmount = big.NewInt(1234e9)
+ )
+
+ BeforeEach(func() {
+ s.SetupTest()
+ s.NextBlock()
+
+ stakingCallerContract, err = testdata.LoadStakingCallerContract()
+ Expect(err).To(BeNil(), "error while loading the StakingCaller contract")
+
+ // Deploy StakingCaller contract
+ contractAddr, err = evmosutil.DeployContract(s.ctx, s.app, s.privKey, s.queryClientEVM, stakingCallerContract)
+ Expect(err).To(BeNil(), "error while deploying the StakingCaller contract")
+
+ // Deploy ERC20 contract
+ erc20ContractAddr, err = evmosutil.DeployContract(s.ctx, s.app, s.privKey, s.queryClientEVM, erc20Contract,
+ erc20Name, erc20Token, erc20Decimals,
+ )
+ Expect(err).To(BeNil(), "error while deploying the ERC20 contract")
+
+ // Mint tokens to the StakingCaller contract
+ mintArgs := contracts.CallArgs{
+ ContractAddr: erc20ContractAddr,
+ ContractABI: erc20Contract.ABI,
+ MethodName: "mint",
+ PrivKey: s.privKey,
+ Args: []interface{}{contractAddr, mintAmount},
+ }
+
+ mintCheck := testutil.LogCheckArgs{
+ ABIEvents: erc20Contract.ABI.Events,
+ ExpEvents: []string{"Transfer"}, // minting produces a Transfer event
+ ExpPass: true,
+ }
+
+ _, _, err = contracts.CallContractAndCheckLogs(s.ctx, s.app, mintArgs, mintCheck)
+ Expect(err).To(BeNil(), "error while minting tokens to the StakingCaller contract")
+
+ // Check that the StakingCaller contract has the correct balance
+ erc20Balance := s.app.Erc20Keeper.BalanceOf(s.ctx, erc20Contract.ABI, erc20ContractAddr, contractAddr)
+ Expect(erc20Balance).To(Equal(mintAmount), "expected different ERC20 balance for the StakingCaller contract")
+
+ // populate default call args
+ defaultCallArgs = contracts.CallArgs{
+ ContractABI: stakingCallerContract.ABI,
+ ContractAddr: contractAddr,
+ MethodName: "callERC20AndDelegate",
+ PrivKey: s.privKey,
+ }
+
+ // populate default log check args
+ defaultLogCheck = testutil.LogCheckArgs{
+ ABIEvents: s.precompile.Events,
+ }
+ execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error())
+ passCheck = defaultLogCheck.WithExpPass(true)
+ })
+
+ Describe("when batching multiple transactions", func() {
+ // validator is the validator address used for testing
+ var validator sdk.ValAddress
+
+ BeforeEach(func() {
+ delegations := s.app.StakingKeeper.GetAllDelegatorDelegations(s.ctx, s.address.Bytes())
+ Expect(delegations).ToNot(HaveLen(0), "expected address to have delegations")
+
+ validator = delegations[0].GetValidatorAddr()
+
+ _ = erc20ContractAddr
+ })
+
+ It("should revert both states if a staking transaction fails", func() {
+ delegationPre, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), validator)
+ Expect(found).To(BeTrue(),
+ "expected delegation from %s to validator %s to be found",
+ sdk.AccAddress(s.address.Bytes()).String(), validator.String(),
+ )
+
+ sharesPre := delegationPre.GetShares()
+
+ // NOTE: passing an invalid validator address here should fail AFTER the erc20 transfer was made in the smart contract.
+ // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly.
+ failArgs := defaultCallArgs.
+ WithArgs(erc20ContractAddr, "invalid validator", transferredAmount)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, failArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "expected error while calling the smart contract")
+ Expect(err.Error()).To(ContainSubstring("execution reverted"), "expected different error message")
+
+ delegationPost, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), validator)
+ Expect(found).To(BeTrue(),
+ "expected delegation from %s to validator %s to be found after calling the smart contract",
+ sdk.AccAddress(s.address.Bytes()).String(), validator.String(),
+ )
+
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations: %v", err)
+ sharesPost := delegationPost.GetShares()
+ erc20BalancePost := s.app.Erc20Keeper.BalanceOf(s.ctx, erc20Contract.ABI, erc20ContractAddr, s.address)
+
+ Expect(auths).To(BeEmpty(), "expected no authorizations when reverting state")
+ Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state")
+ Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state")
+ })
+
+ It("should revert both states if an ERC20 transaction fails", func() {
+ delegationPre, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), validator)
+ Expect(found).To(BeTrue(),
+ "expected delegation from %s to validator %s to be found",
+ sdk.AccAddress(s.address.Bytes()).String(), validator.String(),
+ )
+
+ sharesPre := delegationPre.GetShares()
+
+ // NOTE: trying to transfer more than the balance of the contract should fail AFTER the approval
+ // for delegating was made in the smart contract.
+ // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly.
+ moreThanMintedAmount := new(big.Int).Add(mintAmount, big.NewInt(1))
+ failArgs := defaultCallArgs.
+ WithArgs(erc20ContractAddr, s.validators[0].OperatorAddress, moreThanMintedAmount)
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, failArgs, execRevertedCheck)
+ Expect(err).To(HaveOccurred(), "expected error while calling the smart contract")
+ Expect(err.Error()).To(ContainSubstring("execution reverted"), "expected different error message")
+
+ delegationPost, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), validator)
+ Expect(found).To(BeTrue(),
+ "expected delegation from %s to validator %s to be found after calling the smart contract",
+ sdk.AccAddress(s.address.Bytes()).String(), validator.String(),
+ )
+
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations: %v", err)
+ sharesPost := delegationPost.GetShares()
+ erc20BalancePost := s.app.Erc20Keeper.BalanceOf(s.ctx, erc20Contract.ABI, erc20ContractAddr, s.address)
+
+ Expect(auths).To(BeEmpty(), "expected no authorizations when reverting state")
+ Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state")
+ Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state")
+ })
+
+ It("should persist changes in both the cosmos and eth states", func() {
+ delegationPre, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), validator)
+ Expect(found).To(BeTrue(),
+ "expected delegation from %s to validator %s to be found",
+ sdk.AccAddress(s.address.Bytes()).String(), validator.String(),
+ )
+
+ sharesPre := delegationPre.GetShares()
+
+ // NOTE: trying to transfer more than the balance of the contract should fail AFTER the approval
+ // for delegating was made in the smart contract.
+ // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly.
+ successArgs := defaultCallArgs.
+ WithArgs(erc20ContractAddr, s.validators[0].OperatorAddress, transferredAmount)
+
+ // Build combined map of ABI events to check for both ERC20 events as well as precompile events
+ //
+ // NOTE: only add the transfer event - when adding all contract events to the combined map,
+ // the ERC20 Approval event will overwrite the precompile Approval event, which will cause
+ // the check to fail because of unexpected events in the logs.
+ combinedABIEvents := s.precompile.Events
+ combinedABIEvents["Transfer"] = erc20Contract.ABI.Events["Transfer"]
+
+ successCheck := passCheck.
+ WithABIEvents(combinedABIEvents).
+ WithExpEvents(
+ authorization.EventTypeApproval, "Transfer", staking.EventTypeDelegate,
+ )
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, successArgs, successCheck)
+ Expect(err).ToNot(HaveOccurred(), "error while calling the smart contract")
+
+ delegationPost, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), validator)
+ Expect(found).To(BeTrue(),
+ "expected delegation from %s to validator %s to be found after calling the smart contract",
+ sdk.AccAddress(s.address.Bytes()).String(), validator.String(),
+ )
+
+ auths, err := s.app.AuthzKeeper.GetAuthorizations(s.ctx, contractAddr.Bytes(), s.address.Bytes())
+ Expect(err).To(BeNil(), "error while getting authorizations: %v", err)
+ sharesPost := delegationPost.GetShares()
+ erc20BalancePost := s.app.Erc20Keeper.BalanceOf(s.ctx, erc20Contract.ABI, erc20ContractAddr, s.address)
+
+ Expect(sharesPost.GT(sharesPre)).To(BeTrue(), "expected shares to be more than before")
+ Expect(erc20BalancePost).To(Equal(transferredAmount), "expected different erc20 balance of target address")
+ // NOTE: there should be no authorizations because the full approved amount is delegated
+ Expect(auths).To(HaveLen(0), "expected no authorization to be found")
+ })
+ })
+})
diff --git a/precompiles/staking/query.go b/precompiles/staking/query.go
new file mode 100644
index 00000000..2ad3808b
--- /dev/null
+++ b/precompiles/staking/query.go
@@ -0,0 +1,227 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package staking
+
+import (
+ "fmt"
+ "math/big"
+ "strings"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ // DelegationMethod defines the ABI method name for the staking Delegation
+ // query.
+ DelegationMethod = "delegation"
+ // UnbondingDelegationMethod defines the ABI method name for the staking
+ // UnbondingDelegationMethod query.
+ UnbondingDelegationMethod = "unbondingDelegation"
+ // ValidatorMethod defines the ABI method name for the staking
+ // Validator query.
+ ValidatorMethod = "validator"
+ // ValidatorsMethod defines the ABI method name for the staking
+ // Validators query.
+ ValidatorsMethod = "validators"
+ // RedelegationMethod defines the ABI method name for the staking
+ // Redelegation query.
+ RedelegationMethod = "redelegation"
+ // RedelegationsMethod defines the ABI method name for the staking
+ // Redelegations query.
+ RedelegationsMethod = "redelegations"
+)
+
+// Delegation returns the delegation that a delegator has with a specific validator.
+func (p Precompile) Delegation(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewDelegationRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ queryServer := stakingkeeper.Querier{Keeper: p.stakingKeeper.Keeper}
+
+ res, err := queryServer.Delegation(sdk.WrapSDKContext(ctx), req)
+ if err != nil {
+ // If there is no delegation found, return the response with zero values.
+ if strings.Contains(err.Error(), fmt.Sprintf(ErrNoDelegationFound, req.DelegatorAddr, req.ValidatorAddr)) {
+ return method.Outputs.Pack(big.NewInt(0), cmn.Coin{Denom: p.stakingKeeper.BondDenom(ctx), Amount: big.NewInt(0)})
+ }
+
+ return nil, err
+ }
+
+ out := new(DelegationOutput).FromResponse(res)
+
+ return out.Pack(method.Outputs)
+}
+
+// UnbondingDelegation returns the delegation currently being unbonded for a delegator from
+// a specific validator.
+func (p Precompile) UnbondingDelegation(
+ ctx sdk.Context,
+ _ *vm.Contract,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewUnbondingDelegationRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ queryServer := stakingkeeper.Querier{Keeper: p.stakingKeeper.Keeper}
+
+ res, err := queryServer.UnbondingDelegation(sdk.WrapSDKContext(ctx), req)
+ if err != nil {
+ // return empty unbonding delegation output if the unbonding delegation is not found
+ expError := fmt.Sprintf("unbonding delegation with delegator %s not found for validator %s", req.DelegatorAddr, req.ValidatorAddr)
+ if strings.Contains(err.Error(), expError) {
+ return method.Outputs.Pack(UnbondingDelegationResponse{})
+ }
+ return nil, err
+ }
+
+ out := new(UnbondingDelegationOutput).FromResponse(res)
+
+ return method.Outputs.Pack(out.UnbondingDelegation)
+}
+
+// Validator returns the validator information for a given validator address.
+func (p Precompile) Validator(
+ ctx sdk.Context,
+ method *abi.Method,
+ _ *vm.Contract,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewValidatorRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ queryServer := stakingkeeper.Querier{Keeper: p.stakingKeeper.Keeper}
+
+ res, err := queryServer.Validator(sdk.WrapSDKContext(ctx), req)
+ if err != nil {
+ // return empty validator info if the validator is not found
+ expError := fmt.Sprintf("validator %s not found", req.ValidatorAddr)
+ if strings.Contains(err.Error(), expError) {
+ return method.Outputs.Pack(DefaultValidatorOutput().Validator)
+ }
+ return nil, err
+ }
+
+ out := new(ValidatorOutput).FromResponse(res)
+
+ return method.Outputs.Pack(out.Validator)
+}
+
+// Validators returns the validators information with a provided status & pagination (optional).
+func (p Precompile) Validators(
+ ctx sdk.Context,
+ method *abi.Method,
+ _ *vm.Contract,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewValidatorsRequest(method, args)
+ if err != nil {
+ return nil, err
+ }
+
+ queryServer := stakingkeeper.Querier{Keeper: p.stakingKeeper.Keeper}
+
+ res, err := queryServer.Validators(sdk.WrapSDKContext(ctx), req)
+ if err != nil {
+ return nil, err
+ }
+
+ out := new(ValidatorsOutput).FromResponse(res)
+
+ return out.Pack(method.Outputs)
+}
+
+// Redelegation returns the redelegation between two validators for a delegator.
+func (p Precompile) Redelegation(
+ ctx sdk.Context,
+ method *abi.Method,
+ _ *vm.Contract,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewRedelegationRequest(args)
+ if err != nil {
+ return nil, err
+ }
+
+ res, _ := p.stakingKeeper.GetRedelegation(ctx, req.DelegatorAddress, req.ValidatorSrcAddress, req.ValidatorDstAddress)
+
+ out := new(RedelegationOutput).FromResponse(res)
+
+ return method.Outputs.Pack(out.Redelegation)
+}
+
+// Redelegations returns the redelegations according to
+// the specified criteria (delegator address and/or validator source address
+// and/or validator destination address or all existing redelegations) with pagination.
+// Pagination is only supported for querying redelegations from a source validator or to query all redelegations.
+func (p Precompile) Redelegations(
+ ctx sdk.Context,
+ method *abi.Method,
+ _ *vm.Contract,
+ args []interface{},
+) ([]byte, error) {
+ req, err := NewRedelegationsRequest(method, args)
+ if err != nil {
+ return nil, err
+ }
+
+ queryServer := stakingkeeper.Querier{Keeper: p.stakingKeeper.Keeper}
+
+ res, err := queryServer.Redelegations(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ out := new(RedelegationsOutput).FromResponse(res)
+
+ return out.Pack(method.Outputs)
+}
+
+// Allowance returns the remaining allowance of a grantee to the contract.
+func (p Precompile) Allowance(
+ ctx sdk.Context,
+ method *abi.Method,
+ _ *vm.Contract,
+ args []interface{},
+) ([]byte, error) {
+ grantee, granter, msg, err := authorization.CheckAllowanceArgs(args)
+ if err != nil {
+ return nil, err
+ }
+
+ msgAuthz, _ := p.AuthzKeeper.GetAuthorization(ctx, grantee.Bytes(), granter.Bytes(), msg)
+
+ if msgAuthz == nil {
+ return method.Outputs.Pack(big.NewInt(0))
+ }
+
+ stakeAuthz, ok := msgAuthz.(*stakingtypes.StakeAuthorization)
+ if !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "staking authorization", &stakingtypes.StakeAuthorization{}, stakeAuthz)
+ }
+
+ if stakeAuthz.MaxTokens == nil {
+ return method.Outputs.Pack(abi.MaxUint256)
+ }
+
+ return method.Outputs.Pack(stakeAuthz.MaxTokens.Amount.BigInt())
+}
diff --git a/precompiles/staking/query_test.go b/precompiles/staking/query_test.go
new file mode 100644
index 00000000..782bf14b
--- /dev/null
+++ b/precompiles/staking/query_test.go
@@ -0,0 +1,787 @@
+package staking_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ testutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func (s *PrecompileTestSuite) TestDelegation() {
+ method := s.precompile.Methods[staking.DelegationMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ "invalid",
+ operatorAddress,
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, "invalid"),
+ },
+ {
+ "fail - invalid operator address",
+ func(string) []interface{} {
+ return []interface{}{
+ s.address,
+ "invalid",
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "decoding bech32 failed: invalid bech32 string",
+ },
+ {
+ "success - empty delegation",
+ func(operatorAddress string) []interface{} {
+ addr, _ := testutiltx.NewAddrKey()
+ return []interface{}{
+ addr,
+ operatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var delOut staking.DelegationOutput
+ err := s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(delOut.Shares.Int64(), big.NewInt(0).Int64())
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ }
+ },
+ func(bz []byte) {
+ var delOut staking.DelegationOutput
+ err := s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(delOut.Shares, big.NewInt(1e18))
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.Delegation(s.ctx, contract, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestUnbondingDelegation() {
+ method := s.precompile.Methods[staking.UnbondingDelegationMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ "invalid",
+ operatorAddress,
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, "invalid"),
+ },
+ {
+ "success - no unbonding delegation found",
+ func(operatorAddress string) []interface{} {
+ addr, _ := testutiltx.NewAddrKey()
+ return []interface{}{
+ addr,
+ operatorAddress,
+ }
+ },
+ func(data []byte) {
+ var ubdOut staking.UnbondingDelegationOutput
+ err := s.precompile.UnpackIntoInterface(&ubdOut, staking.UnbondingDelegationMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(ubdOut.UnbondingDelegation.Entries, 0)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ }
+ },
+ func(data []byte) {
+ var ubdOut staking.UnbondingDelegationOutput
+ err := s.precompile.UnpackIntoInterface(&ubdOut, staking.UnbondingDelegationMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(ubdOut.UnbondingDelegation.Entries, 1)
+ s.Require().Equal(ubdOut.UnbondingDelegation.Entries[0].CreationHeight, s.ctx.BlockHeight())
+ s.Require().Equal(ubdOut.UnbondingDelegation.Entries[0].Balance, big.NewInt(1e18))
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ _, err := s.app.StakingKeeper.Undelegate(s.ctx, s.address.Bytes(), s.validators[0].GetOperator(), math.LegacyNewDec(1))
+ s.Require().NoError(err)
+
+ bz, err := s.precompile.UnbondingDelegation(s.ctx, contract, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestValidator() {
+ method := s.precompile.Methods[staking.ValidatorMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress common.Address) []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(common.Address) []interface{} {
+ return []interface{}{}
+ },
+ func(_ []byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 1, 0),
+ },
+ {
+ "success",
+ func(operatorAddress common.Address) []interface{} {
+ return []interface{}{
+ operatorAddress,
+ }
+ },
+ func(data []byte) {
+ var valOut staking.ValidatorOutput
+ err := s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+
+ operatorAddress, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+
+ s.Require().Equal(common.HexToAddress(valOut.Validator.OperatorAddress), common.BytesToAddress(operatorAddress.Bytes()))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ name: "success - empty validator",
+ malleate: func(_ common.Address) []interface{} {
+ newAddr, _ := testutiltx.NewAccAddressAndKey()
+ newValAddr := sdk.ValAddress(newAddr)
+ return []interface{}{
+ common.BytesToAddress(newValAddr.Bytes()),
+ }
+ },
+ postCheck: func(data []byte) {
+ var valOut staking.ValidatorOutput
+ err := s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(valOut.Validator.OperatorAddress, "")
+ s.Require().Equal(valOut.Validator.Status, uint8(0))
+ },
+ gas: 100000,
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ operatorAddress, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+
+ bz, err := s.precompile.Validator(s.ctx, &method, contract, tc.malleate(common.BytesToAddress(operatorAddress.Bytes())))
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestValidators() {
+ method := s.precompile.Methods[staking.ValidatorsMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func(_ []byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
+ },
+ {
+ "fail - invalid number of arguments",
+ func() []interface{} {
+ return []interface{}{
+ stakingtypes.Bonded.String(),
+ }
+ },
+ func(_ []byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 1),
+ },
+ {
+ "success - bonded status & pagination w/countTotal",
+ func() []interface{} {
+ return []interface{}{
+ stakingtypes.Bonded.String(),
+ query.PageRequest{
+ Limit: 1,
+ CountTotal: true,
+ },
+ }
+ },
+ func(data []byte) {
+ const expLen = 1
+ var valOut staking.ValidatorsOutput
+ err := s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+
+ s.Require().Len(valOut.Validators, expLen)
+ // passed CountTotal = true
+ s.Require().Equal(len(s.validators), int(valOut.PageResponse.Total))
+ s.Require().NotEmpty(valOut.PageResponse.NextKey)
+ s.assertValidatorsResponse(valOut.Validators, expLen)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - bonded status & pagination w/countTotal & key is []byte{0}",
+ func() []interface{} {
+ return []interface{}{
+ stakingtypes.Bonded.String(),
+ query.PageRequest{
+ Key: []byte{0},
+ Limit: 1,
+ CountTotal: true,
+ },
+ }
+ },
+ func(data []byte) {
+ const expLen = 1
+ var valOut staking.ValidatorsOutput
+ err := s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+
+ s.Require().Len(valOut.Validators, expLen)
+ // passed CountTotal = true
+ s.Require().Equal(len(s.validators), int(valOut.PageResponse.Total))
+ s.Require().NotEmpty(valOut.PageResponse.NextKey)
+ s.assertValidatorsResponse(valOut.Validators, expLen)
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ bz, err := s.precompile.Validators(s.ctx, &method, contract, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRedelegation() {
+ method := s.precompile.Methods[staking.RedelegationMethod]
+ redelegateMethod := s.precompile.Methods[staking.RedelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(srcOperatorAddr, destOperatorAddr string) []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string, string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func(srcOperatorAddr, destOperatorAddr string) []interface{} {
+ return []interface{}{
+ "invalid",
+ srcOperatorAddr,
+ destOperatorAddr,
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, "invalid"),
+ },
+ {
+ "fail - empty src validator addr",
+ func(_, destOperatorAddr string) []interface{} {
+ return []interface{}{
+ s.address,
+ "",
+ destOperatorAddr,
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "empty address string is not allowed",
+ },
+ {
+ "fail - empty destination addr",
+ func(srcOperatorAddr, _ string) []interface{} {
+ return []interface{}{
+ s.address,
+ srcOperatorAddr,
+ "",
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "empty address string is not allowed",
+ },
+ {
+ "success",
+ func(srcOperatorAddr, destOperatorAddr string) []interface{} {
+ return []interface{}{
+ s.address,
+ srcOperatorAddr,
+ destOperatorAddr,
+ }
+ },
+ func(data []byte) {
+ var redOut staking.RedelegationOutput
+ err := s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(redOut.Redelegation.Entries, 1)
+ s.Require().Equal(redOut.Redelegation.Entries[0].CreationHeight, s.ctx.BlockHeight())
+ s.Require().Equal(redOut.Redelegation.Entries[0].SharesDst, big.NewInt(1e18))
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ name: "success - no redelegation found",
+ malleate: func(srcOperatorAddr, _ string) []interface{} {
+ nonExistentOperator := sdk.ValAddress([]byte("non-existent-operator"))
+ return []interface{}{
+ s.address,
+ srcOperatorAddr,
+ nonExistentOperator.String(),
+ }
+ },
+ postCheck: func(data []byte) {
+ var redOut staking.RedelegationOutput
+ err := s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(redOut.Redelegation.Entries, 0)
+ },
+ gas: 100000,
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ delegationArgs := []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ s.validators[1].OperatorAddress,
+ big.NewInt(1e18),
+ }
+
+ err := s.CreateAuthorization(s.address, staking.RedelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ _, err = s.precompile.Redelegate(s.ctx, s.address, contract, s.stateDB, &redelegateMethod, delegationArgs)
+ s.Require().NoError(err)
+
+ bz, err := s.precompile.Redelegation(s.ctx, &method, contract, tc.malleate(s.validators[0].OperatorAddress, s.validators[1].OperatorAddress))
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRedelegations() {
+ var (
+ delAmt = big.NewInt(3e17)
+ redelTotalCount uint64 = 2
+ method = s.precompile.Methods[staking.RedelegationsMethod]
+ )
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 4, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func() []interface{} {
+ return []interface{}{
+ common.BytesToAddress([]byte("invalid")),
+ s.validators[0].OperatorAddress,
+ s.validators[1].OperatorAddress,
+ query.PageRequest{},
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "redelegation not found",
+ },
+ {
+ "fail - invalid query | all empty args ",
+ func() []interface{} {
+ return []interface{}{
+ common.Address{},
+ "",
+ "",
+ query.PageRequest{},
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "invalid query. Need to specify at least a source validator address or delegator address",
+ },
+ {
+ "fail - invalid query | only destination validator address",
+ func() []interface{} {
+ return []interface{}{
+ common.Address{},
+ "",
+ s.validators[1].OperatorAddress,
+ query.PageRequest{},
+ }
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ "invalid query. Need to specify at least a source validator address or delegator address",
+ },
+ {
+ "success - specified delegator, source & destination",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ s.validators[1].OperatorAddress,
+ query.PageRequest{},
+ }
+ },
+ func(data []byte) {
+ s.assertRedelegationsOutput(data, 0, delAmt, 2, false)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - specifying only source w/pagination",
+ func() []interface{} {
+ return []interface{}{
+ common.Address{},
+ s.validators[0].OperatorAddress,
+ "",
+ query.PageRequest{
+ Limit: 1,
+ CountTotal: true,
+ },
+ }
+ },
+ func(data []byte) {
+ s.assertRedelegationsOutput(data, redelTotalCount, delAmt, 2, true)
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - get all existing redelegations for a delegator w/pagination",
+ func() []interface{} {
+ return []interface{}{
+ s.address,
+ "",
+ "",
+ query.PageRequest{
+ Limit: 1,
+ CountTotal: true,
+ },
+ }
+ },
+ func(data []byte) {
+ s.assertRedelegationsOutput(data, redelTotalCount, delAmt, 2, true)
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ err := s.setupRedelegations(delAmt)
+ s.Require().NoError(err)
+
+ // query redelegations
+ bz, err := s.precompile.Redelegations(s.ctx, &method, contract, tc.malleate())
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestAllowance() {
+ approvedCoin := sdk.Coin{Denom: s.bondDenom, Amount: math.NewInt(1e18)}
+ granteeAddr := testutiltx.GenerateAddress()
+ method := s.precompile.Methods[authorization.AllowanceMethod]
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ postCheck func(bz []byte)
+ gas uint64
+ expErr bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 100000,
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 0),
+ },
+ {
+ "success - query delegate method allowance",
+ func() []interface{} {
+ err := s.CreateAuthorization(granteeAddr, staking.DelegateAuthz, &approvedCoin)
+ s.Require().NoError(err)
+
+ return []interface{}{
+ granteeAddr,
+ s.address,
+ staking.DelegateMsg,
+ }
+ },
+ func(bz []byte) {
+ var amountsOut *big.Int
+ err := s.precompile.UnpackIntoInterface(&amountsOut, authorization.AllowanceMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(big.NewInt(1e18), amountsOut, "expected different allowed amount")
+ },
+ 100000,
+ false,
+ "",
+ },
+ {
+ "success - return empty allowance if authorization is not found",
+ func() []interface{} {
+ return []interface{}{
+ granteeAddr,
+ s.address,
+ staking.UndelegateMsg,
+ }
+ },
+ func(bz []byte) {
+ var amountsOut *big.Int
+ err := s.precompile.UnpackIntoInterface(&amountsOut, authorization.AllowanceMethod, bz)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Equal(int64(0), amountsOut.Int64(), "expected no allowance")
+ },
+ 100000,
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest() // reset
+ contract := vm.NewContract(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+
+ args := tc.malleate()
+ bz, err := s.precompile.Allowance(s.ctx, &method, contract, args)
+
+ if tc.expErr {
+ s.Require().Error(err)
+ s.Require().Contains(err.Error(), tc.errContains)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(bz)
+ tc.postCheck(bz)
+ }
+ })
+ }
+}
diff --git a/precompiles/staking/setup_test.go b/precompiles/staking/setup_test.go
new file mode 100644
index 00000000..373108ab
--- /dev/null
+++ b/precompiles/staking/setup_test.go
@@ -0,0 +1,56 @@
+package staking_test
+
+import (
+ "testing"
+
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ evmosapp "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "github.com/stretchr/testify/suite"
+)
+
+var s *PrecompileTestSuite
+
+type PrecompileTestSuite struct {
+ suite.Suite
+
+ ctx sdk.Context
+ app *evmosapp.Evmos
+ address common.Address
+ validators []stakingtypes.Validator
+ ethSigner ethtypes.Signer
+ privKey cryptotypes.PrivKey
+ signer keyring.Signer
+ bondDenom string
+
+ precompile *staking.Precompile
+ stateDB *statedb.StateDB
+
+ queryClientEVM evmtypes.QueryClient
+}
+
+func TestPrecompileTestSuite(t *testing.T) {
+ s = new(PrecompileTestSuite)
+ suite.Run(t, s)
+
+ // Run Ginkgo integration tests
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Precompile Test Suite")
+}
+
+func (s *PrecompileTestSuite) SetupTest() {
+ s.DoSetupTest()
+}
diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go
new file mode 100644
index 00000000..5bcc42b2
--- /dev/null
+++ b/precompiles/staking/staking.go
@@ -0,0 +1,192 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package staking
+
+import (
+ "embed"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/cometbft/cometbft/libs/log"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ stakingkeeper "github.com/evmos/evmos/v19/x/staking/keeper"
+)
+
+var _ vm.PrecompiledContract = &Precompile{}
+
+// Embed abi json file to the executable binary. Needed when importing as dependency.
+//
+//go:embed abi.json
+var f embed.FS
+
+// Precompile defines the precompiled contract for staking.
+type Precompile struct {
+ cmn.Precompile
+ stakingKeeper stakingkeeper.Keeper
+}
+
+// LoadABI loads the staking ABI from the embedded abi.json file
+// for the staking precompile.
+func LoadABI() (abi.ABI, error) {
+ return cmn.LoadABI(f, "abi.json")
+}
+
+// NewPrecompile creates a new staking Precompile instance as a
+// PrecompiledContract interface.
+func NewPrecompile(
+ stakingKeeper stakingkeeper.Keeper,
+ authzKeeper authzkeeper.Keeper,
+) (*Precompile, error) {
+ abi, err := LoadABI()
+ if err != nil {
+ return nil, err
+ }
+
+ p := &Precompile{
+ Precompile: cmn.Precompile{
+ ABI: abi,
+ AuthzKeeper: authzKeeper,
+ KvGasConfig: storetypes.KVGasConfig(),
+ TransientKVGasConfig: storetypes.TransientGasConfig(),
+ ApprovalExpiration: cmn.DefaultExpirationDuration, // should be configurable in the future.
+ },
+ stakingKeeper: stakingKeeper,
+ }
+ // SetAddress defines the address of the staking precompiled contract.
+ p.SetAddress(common.HexToAddress(evmtypes.StakingPrecompileAddress))
+
+ return p, nil
+}
+
+// RequiredGas returns the required bare minimum gas to execute the precompile.
+func (p Precompile) RequiredGas(input []byte) uint64 {
+ // NOTE: This check avoid panicking when trying to decode the method ID
+ if len(input) < 4 {
+ return 0
+ }
+
+ methodID := input[:4]
+
+ method, err := p.MethodById(methodID)
+ if err != nil {
+ // This should never happen since this method is going to fail during Run
+ return 0
+ }
+
+ return p.Precompile.RequiredGas(input, p.IsTransaction(method.Name))
+}
+
+// Run executes the precompiled contract staking methods defined in the ABI.
+func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) {
+ ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction)
+ if err != nil {
+ return nil, err
+ }
+
+ // This handles any out of gas errors that may occur during the execution of a precompile tx or query.
+ // It avoids panics and returns the out of gas error so the EVM can continue gracefully.
+ defer cmn.HandleGasError(ctx, contract, initialGas, &err)()
+
+ switch method.Name {
+ // Authorization transactions
+ case authorization.ApproveMethod:
+ bz, err = p.Approve(ctx, evm.Origin, stateDB, method, args)
+ case authorization.RevokeMethod:
+ bz, err = p.Revoke(ctx, evm.Origin, stateDB, method, args)
+ case authorization.IncreaseAllowanceMethod:
+ bz, err = p.IncreaseAllowance(ctx, evm.Origin, stateDB, method, args)
+ case authorization.DecreaseAllowanceMethod:
+ bz, err = p.DecreaseAllowance(ctx, evm.Origin, stateDB, method, args)
+ // Staking transactions
+ case CreateValidatorMethod:
+ bz, err = p.CreateValidator(ctx, evm.Origin, contract, stateDB, method, args)
+ case EditValidatorMethod:
+ bz, err = p.EditValidator(ctx, evm.Origin, contract, stateDB, method, args)
+ case DelegateMethod:
+ bz, err = p.Delegate(ctx, evm.Origin, contract, stateDB, method, args)
+ case UndelegateMethod:
+ bz, err = p.Undelegate(ctx, evm.Origin, contract, stateDB, method, args)
+ case RedelegateMethod:
+ bz, err = p.Redelegate(ctx, evm.Origin, contract, stateDB, method, args)
+ case CancelUnbondingDelegationMethod:
+ bz, err = p.CancelUnbondingDelegation(ctx, evm.Origin, contract, stateDB, method, args)
+ // Staking queries
+ case DelegationMethod:
+ bz, err = p.Delegation(ctx, contract, method, args)
+ case UnbondingDelegationMethod:
+ bz, err = p.UnbondingDelegation(ctx, contract, method, args)
+ case ValidatorMethod:
+ bz, err = p.Validator(ctx, method, contract, args)
+ case ValidatorsMethod:
+ bz, err = p.Validators(ctx, method, contract, args)
+ case RedelegationMethod:
+ bz, err = p.Redelegation(ctx, method, contract, args)
+ case RedelegationsMethod:
+ bz, err = p.Redelegations(ctx, method, contract, args)
+ // Authorization queries
+ case authorization.AllowanceMethod:
+ bz, err = p.Allowance(ctx, method, contract, args)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ cost := ctx.GasMeter().GasConsumed() - initialGas
+
+ if !contract.UseGas(cost) {
+ return nil, vm.ErrOutOfGas
+ }
+
+ if err := p.AddJournalEntries(stateDB, snapshot); err != nil {
+ return nil, err
+ }
+
+ return bz, nil
+}
+
+// IsTransaction checks if the given method name corresponds to a transaction or query.
+//
+// Available staking transactions are:
+// - CreateValidator
+// - EditValidator
+// - Delegate
+// - Undelegate
+// - Redelegate
+// - CancelUnbondingDelegation
+//
+// Available authorization transactions are:
+// - Approve
+// - Revoke
+// - IncreaseAllowance
+// - DecreaseAllowance
+func (Precompile) IsTransaction(method string) bool {
+ switch method {
+ case CreateValidatorMethod,
+ EditValidatorMethod,
+ DelegateMethod,
+ UndelegateMethod,
+ RedelegateMethod,
+ CancelUnbondingDelegationMethod,
+ authorization.ApproveMethod,
+ authorization.RevokeMethod,
+ authorization.IncreaseAllowanceMethod,
+ authorization.DecreaseAllowanceMethod:
+ return true
+ default:
+ return false
+ }
+}
+
+// Logger returns a precompile-specific logger.
+func (p Precompile) Logger(ctx sdk.Context) log.Logger {
+ return ctx.Logger().With("evm extension", "staking")
+}
diff --git a/precompiles/staking/staking_test.go b/precompiles/staking/staking_test.go
new file mode 100644
index 00000000..4a90d290
--- /dev/null
+++ b/precompiles/staking/staking_test.go
@@ -0,0 +1,475 @@
+package staking_test
+
+import (
+ "math/big"
+ "time"
+
+ "cosmossdk.io/math"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (s *PrecompileTestSuite) TestIsTransaction() {
+ testCases := []struct {
+ name string
+ method string
+ isTx bool
+ }{
+ {
+ authorization.ApproveMethod,
+ s.precompile.Methods[authorization.ApproveMethod].Name,
+ true,
+ },
+ {
+ authorization.IncreaseAllowanceMethod,
+ s.precompile.Methods[authorization.IncreaseAllowanceMethod].Name,
+ true,
+ },
+ {
+ authorization.DecreaseAllowanceMethod,
+ s.precompile.Methods[authorization.DecreaseAllowanceMethod].Name,
+ true,
+ },
+ {
+ staking.CreateValidatorMethod,
+ s.precompile.Methods[staking.CreateValidatorMethod].Name,
+ true,
+ },
+ {
+ staking.DelegateMethod,
+ s.precompile.Methods[staking.DelegateMethod].Name,
+ true,
+ },
+ {
+ staking.UndelegateMethod,
+ s.precompile.Methods[staking.UndelegateMethod].Name,
+ true,
+ },
+ {
+ staking.RedelegateMethod,
+ s.precompile.Methods[staking.RedelegateMethod].Name,
+ true,
+ },
+ {
+ staking.CancelUnbondingDelegationMethod,
+ s.precompile.Methods[staking.CancelUnbondingDelegationMethod].Name,
+ true,
+ },
+ {
+ staking.DelegationMethod,
+ s.precompile.Methods[staking.DelegationMethod].Name,
+ false,
+ },
+ {
+ "invalid",
+ "invalid",
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.Require().Equal(s.precompile.IsTransaction(tc.method), tc.isTx)
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRequiredGas() {
+ testcases := []struct {
+ name string
+ malleate func() []byte
+ expGas uint64
+ }{
+ {
+ "success - delegate transaction with correct gas estimation",
+ func() []byte {
+ input, err := s.precompile.Pack(
+ staking.DelegateMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ big.NewInt(10000000000),
+ )
+ s.Require().NoError(err)
+ return input
+ },
+ 7760,
+ },
+ {
+ "success - undelegate transaction with correct gas estimation",
+ func() []byte {
+ input, err := s.precompile.Pack(
+ staking.UndelegateMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ big.NewInt(1),
+ )
+ s.Require().NoError(err)
+ return input
+ },
+ 7760,
+ },
+ }
+
+ for _, tc := range testcases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ // malleate contract input
+ input := tc.malleate()
+ gas := s.precompile.RequiredGas(input)
+
+ s.Require().Equal(gas, tc.expGas)
+ })
+ }
+}
+
+// TestRun tests the precompile's Run method.
+func (s *PrecompileTestSuite) TestRun() {
+ testcases := []struct {
+ name string
+ malleate func() []byte
+ gas uint64
+ readOnly bool
+ expPass bool
+ errContains string
+ }{
+ {
+ "fail - contract gas limit is < gas cost to run a query / tx",
+ func() []byte {
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ input, err := s.precompile.Pack(
+ staking.DelegateMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ big.NewInt(1000),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 8000,
+ false,
+ false,
+ "out of gas",
+ },
+ {
+ "pass - delegate transaction",
+ func() []byte {
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ input, err := s.precompile.Pack(
+ staking.DelegateMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ big.NewInt(1000),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ false,
+ true,
+ "",
+ },
+ {
+ "pass - undelegate transaction",
+ func() []byte {
+ err := s.CreateAuthorization(s.address, staking.UndelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ input, err := s.precompile.Pack(
+ staking.UndelegateMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ big.NewInt(1),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ false,
+ true,
+ "",
+ },
+ {
+ "pass - redelegate transaction",
+ func() []byte {
+ err := s.CreateAuthorization(s.address, staking.RedelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ input, err := s.precompile.Pack(
+ staking.RedelegateMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ s.validators[1].GetOperator().String(),
+ big.NewInt(1),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ false,
+ true,
+ "failed to redelegate tokens",
+ },
+ {
+ "pass - cancel unbonding delegation transaction",
+ func() []byte {
+ // add unbonding delegation to staking keeper
+ ubd := stakingtypes.NewUnbondingDelegation(
+ s.address.Bytes(),
+ s.validators[0].GetOperator(),
+ 1000,
+ time.Now().Add(time.Hour),
+ math.NewInt(1000),
+ 0,
+ )
+ s.app.StakingKeeper.SetUnbondingDelegation(s.ctx, ubd)
+
+ err := s.CreateAuthorization(s.address, staking.CancelUnbondingDelegationAuthz, nil)
+ s.Require().NoError(err)
+
+ // Needs to be called after setting unbonding delegation
+ // In order to mimic the coins being added to the unboding pool
+ coin := sdk.NewCoin(utils.BaseDenom, math.NewInt(1000))
+ err = s.app.BankKeeper.SendCoinsFromModuleToModule(s.ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin})
+ s.Require().NoError(err, "failed to send coins from module to module")
+
+ input, err := s.precompile.Pack(
+ staking.CancelUnbondingDelegationMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ big.NewInt(1000),
+ big.NewInt(1000),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ false,
+ true,
+ "",
+ },
+ {
+ "pass - delegation query",
+ func() []byte {
+ input, err := s.precompile.Pack(
+ staking.DelegationMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ false,
+ true,
+ "",
+ },
+ {
+ "pass - validator query",
+ func() []byte {
+ valAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
+ s.Require().NoError(err)
+
+ input, err := s.precompile.Pack(
+ staking.ValidatorMethod,
+ common.BytesToAddress(valAddr.Bytes()),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ false,
+ true,
+ "",
+ },
+ {
+ "pass - redelgation query",
+ func() []byte {
+ // add redelegation to staking keeper
+ redelegation := stakingtypes.NewRedelegation(
+ s.address.Bytes(),
+ s.validators[0].GetOperator(),
+ s.validators[1].GetOperator(),
+ 1000,
+ time.Now().Add(time.Hour),
+ math.NewInt(1000),
+ math.LegacyNewDec(1),
+ 0,
+ )
+
+ s.app.StakingKeeper.SetRedelegation(s.ctx, redelegation)
+
+ input, err := s.precompile.Pack(
+ staking.RedelegationMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ s.validators[1].GetOperator().String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ false,
+ true,
+ "",
+ },
+ {
+ "pass - delegation query - read only",
+ func() []byte {
+ input, err := s.precompile.Pack(
+ staking.DelegationMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ true,
+ true,
+ "",
+ },
+ {
+ "pass - unbonding delegation query",
+ func() []byte {
+ // add unbonding delegation to staking keeper
+ ubd := stakingtypes.NewUnbondingDelegation(
+ s.address.Bytes(),
+ s.validators[0].GetOperator(),
+ 1000,
+ time.Now().Add(time.Hour),
+ math.NewInt(1000),
+ 0,
+ )
+ s.app.StakingKeeper.SetUnbondingDelegation(s.ctx, ubd)
+
+ // Needs to be called after setting unbonding delegation
+ // In order to mimic the coins being added to the unboding pool
+ coin := sdk.NewCoin(utils.BaseDenom, math.NewInt(1000))
+ err := s.app.BankKeeper.SendCoinsFromModuleToModule(s.ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin})
+ s.Require().NoError(err, "failed to send coins from module to module")
+
+ input, err := s.precompile.Pack(
+ staking.UnbondingDelegationMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 1000000,
+ true,
+ true,
+ "",
+ },
+ {
+ "fail - delegate method - read only",
+ func() []byte {
+ input, err := s.precompile.Pack(
+ staking.DelegateMethod,
+ s.address,
+ s.validators[0].GetOperator().String(),
+ big.NewInt(1000),
+ )
+ s.Require().NoError(err, "failed to pack input")
+ return input
+ },
+ 0,
+ true,
+ false,
+ "write protection",
+ },
+ {
+ "fail - invalid method",
+ func() []byte {
+ return []byte("invalid")
+ },
+ 0,
+ false,
+ false,
+ "no method with id",
+ },
+ }
+
+ for _, tc := range testcases {
+ s.Run(tc.name, func() {
+ // setup basic test suite
+ s.SetupTest()
+
+ baseFee := s.app.FeeMarketKeeper.GetBaseFee(s.ctx)
+
+ contract := vm.NewPrecompile(vm.AccountRef(s.address), s.precompile, big.NewInt(0), tc.gas)
+ contractAddr := contract.Address()
+
+ // malleate testcase
+ contract.Input = tc.malleate()
+
+ // Build and sign Ethereum transaction
+ txArgs := evmtypes.EvmTxArgs{
+ ChainID: s.app.EvmKeeper.ChainID(),
+ Nonce: 0,
+ To: &contractAddr,
+ Amount: nil,
+ GasLimit: tc.gas,
+ GasPrice: app.MainnetMinGasPrices.BigInt(),
+ GasFeeCap: baseFee,
+ GasTipCap: big.NewInt(1),
+ Accesses: ðtypes.AccessList{},
+ }
+ msgEthereumTx := evmtypes.NewTx(&txArgs)
+
+ msgEthereumTx.From = s.address.String()
+ err := msgEthereumTx.Sign(s.ethSigner, s.signer)
+ s.Require().NoError(err, "failed to sign Ethereum message")
+
+ // Instantiate config
+ proposerAddress := s.ctx.BlockHeader().ProposerAddress
+ cfg, err := s.app.EvmKeeper.EVMConfig(s.ctx, proposerAddress, s.app.EvmKeeper.ChainID())
+ s.Require().NoError(err, "failed to instantiate EVM config")
+
+ msg, err := msgEthereumTx.AsMessage(s.ethSigner, baseFee)
+ s.Require().NoError(err, "failed to instantiate Ethereum message")
+
+ // Instantiate EVM
+ evm := s.app.EvmKeeper.NewEVM(
+ s.ctx, msg, cfg, nil, s.stateDB,
+ )
+
+ precompiles, found, err := s.app.EvmKeeper.GetPrecompileInstance(s.ctx, contractAddr)
+ s.Require().NoError(err, "failed to instantiate precompile")
+ s.Require().True(found, "not found precompile")
+ evm.WithPrecompiles(precompiles.Map, precompiles.Addresses)
+
+ // Run precompiled contract
+ bz, err := s.precompile.Run(evm, contract, tc.readOnly)
+
+ // Check results
+ if tc.expPass {
+ s.Require().NoError(err, "expected no error when running the precompile")
+ s.Require().NotNil(bz, "expected returned bytes not to be nil")
+ } else {
+ s.Require().Error(err, "expected error to be returned when running the precompile")
+ s.Require().Nil(bz, "expected returned bytes to be nil")
+ s.Require().ErrorContains(err, tc.errContains)
+ consumed := s.ctx.GasMeter().GasConsumed()
+ // LessThanOrEqual because the gas is consumed before the error is returned
+ s.Require().LessOrEqual(tc.gas, consumed, "expected gas consumed to be equal to gas limit")
+
+ }
+ })
+ }
+}
diff --git a/precompiles/staking/testdata/StakingCaller.json b/precompiles/staking/testdata/StakingCaller.json
new file mode 100644
index 00000000..fa01a3c8
--- /dev/null
+++ b/precompiles/staking/testdata/StakingCaller.json
@@ -0,0 +1,1078 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "StakingCaller",
+ "sourceName": "solidity/precompiles/staking/testdata/StakingCaller.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ }
+ ],
+ "name": "approveDepositAndDelegate",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ }
+ ],
+ "name": "approveDepositAndDelegateExceedingAllowance",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ }
+ ],
+ "name": "approveDepositDelegateAndFailCustomLogic",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_contract",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "callERC20AndDelegate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "counter",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "method",
+ "type": "string"
+ }
+ ],
+ "name": "getAllowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "allowance",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ }
+ ],
+ "name": "getDelegation",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "shares",
+ "type": "uint256"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin",
+ "name": "balance",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorSrcAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorDstAddr",
+ "type": "string"
+ }
+ ],
+ "name": "getRedelegation",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "delegatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorSrcAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorDstAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sharesDst",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntry[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct RedelegationOutput",
+ "name": "redelegation",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delegatorAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorSrcAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorDstAddr",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "_pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "getRedelegations",
+ "outputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "delegatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorSrcAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorDstAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sharesDst",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntry[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct Redelegation",
+ "name": "redelegation",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sharesDst",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntry",
+ "name": "redelegationEntry",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint256",
+ "name": "balance",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct RedelegationEntryResponse[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct RedelegationResponse[]",
+ "name": "response",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "pageResponse",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ }
+ ],
+ "name": "getUnbondingDelegation",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "delegatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "int64",
+ "name": "creationHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "completionTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialBalance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "balance",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint64",
+ "name": "unbondingId",
+ "type": "uint64"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingOnHoldRefCount",
+ "type": "int64"
+ }
+ ],
+ "internalType": "struct UnbondingDelegationEntry[]",
+ "name": "entries",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct UnbondingDelegationOutput",
+ "name": "unbondingDelegation",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_validatorAddr",
+ "type": "address"
+ }
+ ],
+ "name": "getValidator",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "operatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "consensusPubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "jailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "enum BondStatus",
+ "name": "status",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokens",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatorShares",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "description",
+ "type": "string"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "commission",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minSelfDelegation",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Validator",
+ "name": "validator",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_status",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "_pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "getValidators",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "operatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "consensusPubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "jailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "enum BondStatus",
+ "name": "status",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokens",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatorShares",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "description",
+ "type": "string"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "commission",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minSelfDelegation",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Validator[]",
+ "name": "validators",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "pageResponse",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string[]",
+ "name": "_methods",
+ "type": "string[]"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testApprove",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_approveAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_undelegateAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ }
+ ],
+ "name": "testApproveAndThenUndelegate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "_calltype",
+ "type": "string"
+ }
+ ],
+ "name": "testCallDelegation",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "shares",
+ "type": "uint256"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin",
+ "name": "coin",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "_calltype",
+ "type": "string"
+ }
+ ],
+ "name": "testCallUndelegate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_creationHeight",
+ "type": "uint256"
+ }
+ ],
+ "name": "testCancelUnbonding",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "moniker",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "identity",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "website",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "securityContact",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "details",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct Description",
+ "name": "_descr",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "rate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxRate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxChangeRate",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct CommissionRates",
+ "name": "_commRates",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_minSelfDel",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "_valAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_pubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "testCreateValidator",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testDelegate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testDelegateIncrementCounter",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "moniker",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "identity",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "website",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "securityContact",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "details",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct Description",
+ "name": "_descr",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "_valAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "int256",
+ "name": "_commRate",
+ "type": "int256"
+ },
+ {
+ "internalType": "int256",
+ "name": "_minSelfDel",
+ "type": "int256"
+ }
+ ],
+ "name": "testEditValidator",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorSrcAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorDstAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testRedelegate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_grantee",
+ "type": "address"
+ },
+ {
+ "internalType": "string[]",
+ "name": "_methods",
+ "type": "string[]"
+ }
+ ],
+ "name": "testRevoke",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testUndelegate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x60806040526040518060200160405280604051806060016040528060238152602001620062646023913981525060019060016200003e92919062000053565b503480156200004c57600080fd5b50620004a1565b828054828255906000526020600020908101928215620000a0579160200282015b828111156200009f5782518290816200008e9190620003ba565b509160200191906001019062000074565b5b509050620000af9190620000b3565b5090565b5b80821115620000d75760008181620000cd9190620000db565b50600101620000b4565b5090565b508054620000e990620001a9565b6000825580601f10620000fd57506200011e565b601f0160209004906000526020600020908101906200011d919062000121565b5b50565b5b808211156200013c57600081600090555060010162000122565b5090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620001c257607f821691505b602082108103620001d857620001d76200017a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620002427fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000203565b6200024e868362000203565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006200029b620002956200028f8462000266565b62000270565b62000266565b9050919050565b6000819050919050565b620002b7836200027a565b620002cf620002c682620002a2565b84845462000210565b825550505050565b600090565b620002e6620002d7565b620002f3818484620002ac565b505050565b5b818110156200031b576200030f600082620002dc565b600181019050620002f9565b5050565b601f8211156200036a576200033481620001de565b6200033f84620001f3565b810160208510156200034f578190505b620003676200035e85620001f3565b830182620002f8565b50505b505050565b600082821c905092915050565b60006200038f600019846008026200036f565b1980831691505092915050565b6000620003aa83836200037c565b9150826002028217905092915050565b620003c58262000140565b67ffffffffffffffff811115620003e157620003e06200014b565b5b620003ed8254620001a9565b620003fa8282856200031f565b600060209050601f8311600181146200043257600084156200041d578287015190505b6200042985826200039c565b86555062000499565b601f1984166200044286620001de565b60005b828110156200046c5784890151825560018201915060208501945060208101905062000445565b868310156200048c578489015162000488601f8916826200037c565b8355505b6001600288020188555050505b505050505050565b615db380620004b16000396000f3fe60806040526004361061014b5760003560e01c80637e51b811116100b6578063cf2753cf1161006f578063cf2753cf146104a8578063ec9485df146104e6578063f40a214614610523578063f5714e641461054c578063f700dbd214610568578063f732b065146105915761014b565b80637e51b811146103965780638939e783146103bf5780638edb3f8b146103e85780639eab671114610404578063af9a90b21461042d578063b13d42421461046a5761014b565b806355dc4b221161010857806355dc4b2214610283578063570467ac146102ac5780635e269bfe146102e957806360deaa2a1461031257806361bc221a1461032e57806368ac3df3146103595761014b565b80630a4433e2146101505780631904bb2e1461017957806319b16c4c146101b657806331bcbcb3146101f45780633566cb951461021d578063455b855114610246575b600080fd5b34801561015c57600080fd5b5061017760048036038101906101729190612402565b6105cf565b005b34801561018557600080fd5b506101a0600480360381019061019b9190612476565b61069e565b6040516101ad91906126ed565b60405180910390f35b3480156101c257600080fd5b506101dd60048036038101906101d8919061283f565b61072e565b6040516101eb929190612916565b60405180910390f35b34801561020057600080fd5b5061021b60048036038101906102169190612946565b610c2d565b005b34801561022957600080fd5b50610244600480360381019061023f91906129b5565b610eba565b005b34801561025257600080fd5b5061026d60048036038101906102689190612a11565b611022565b60405161027a9190612c18565b60405180910390f35b34801561028f57600080fd5b506102aa60048036038101906102a59190612c3a565b6110b5565b005b3480156102b857600080fd5b506102d360048036038101906102ce919061283f565b6114a7565b6040516102e09190612e55565b60405180910390f35b3480156102f557600080fd5b50610310600480360381019061030b9190612e77565b61153d565b005b61032c60048036038101906103279190612efa565b6115c8565b005b34801561033a57600080fd5b50610343611716565b6040516103509190612f43565b60405180910390f35b34801561036557600080fd5b50610380600480360381019061037b9190612fa1565b61171c565b60405161038d9190613076565b60405180910390f35b3480156103a257600080fd5b506103bd60048036038101906103b89190612946565b6117b2565b005b3480156103cb57600080fd5b506103e660048036038101906103e19190612946565b61183a565b005b61040260048036038101906103fd9190612efa565b6118f0565b005b34801561041057600080fd5b5061042b60048036038101906104269190613091565b611a85565b005b34801561043957600080fd5b50610454600480360381019061044f9190613166565b611b10565b6040516104619190613076565b60405180910390f35b34801561047657600080fd5b50610491600480360381019061048c9190613208565b611ba0565b60405161049f9291906134d1565b60405180910390f35b3480156104b457600080fd5b506104cf60048036038101906104ca9190612a11565b611c38565b6040516104dd929190612916565b60405180910390f35b3480156104f257600080fd5b5061050d60048036038101906105089190612a11565b611cd0565b60405161051a9190612f43565b60405180910390f35b34801561052f57600080fd5b5061054a60048036038101906105459190613508565b611d5a565b005b61056660048036038101906105619190612efa565b611f36565b005b34801561057457600080fd5b5061058f600480360381019061058a919061358b565b612090565b005b34801561059d57600080fd5b506105b860048036038101906105b39190613796565b61215c565b6040516105c6929190613aad565b60405180910390f35b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895868487876040518563ffffffff1660e01b81526004016106129493929190613c46565b6020604051808303816000875af1158015610631573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106559190613c9b565b905080610697576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068e90613d4b565b60405180910390fd5b5050505050565b6106a66121fa565b61080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a836040518263ffffffff1660e01b81526004016106e19190613d6b565b600060405180830381865afa1580156106fe573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107279190613fbc565b9050919050565b600061073861226e565b600061080090506000868660405160240161075492919061403e565b6040516020818303038152906040527f241774e6000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000856040516020016107e691906140aa565b60405160208183030381529060405280519060200120905060405160200161080d9061410d565b6040516020818303038152906040528051906020012081036108f9576000808473ffffffffffffffffffffffffffffffffffffffff1684604051610851919061415e565b600060405180830381855af49150503d806000811461088c576040519150601f19603f3d011682016040523d82523d6000602084013e610891565b606091505b5091509150816108d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cd906141e7565b60405180910390fd5b808060200190518101906108ea9190614273565b80975081985050505050610c22565b6040516020016109089061431b565b6040516020818303038152906040528051906020012081036109f4576000808473ffffffffffffffffffffffffffffffffffffffff168460405161094c919061415e565b600060405180830381855afa9150503d8060008114610987576040519150601f19603f3d011682016040523d82523d6000602084013e61098c565b606091505b5091509150816109d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109c89061437c565b60405180910390fd5b808060200190518101906109e59190614273565b80975081985050505050610c21565b604051602001610a03906143e8565b604051602081830303815290604052805190602001208103610af1576000808473ffffffffffffffffffffffffffffffffffffffff1684604051610a47919061415e565b6000604051808303816000865af19150503d8060008114610a84576040519150601f19603f3d011682016040523d82523d6000602084013e610a89565b606091505b509150915081610ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac590614449565b60405180910390fd5b80806020019051810190610ae29190614273565b80975081985050505050610c20565b604051602001610b00906144b5565b604051602081830303815290604052805190602001208103610be45760006040518060400160405280601a81526020017f64656c65676174696f6e28616464726573732c737472696e6729000000000000815250805190602001209050600060a490506060600060208b01516020808d0101516040518681528e6004820152604060248201526033604482015282606482015281608482015260c081878360008e5af281519c5060608201519450610100820160405280610bc057600080fd5b50505050604051806040016040528083815260200182815250975050505050610c1f565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1690614516565b60405180910390fd5b5b5b5b505050935093915050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895308460016040518463ffffffff1660e01b8152600401610c6f939291906146e4565b6020604051808303816000875af1158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb29190613c9b565b905080610cf4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ceb9061476e565b60405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff163384604051602401610d2092919061478e565b6040516020818303038152906040527fa9059cbb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610daa919061415e565b6000604051808303816000865af19150503d8060008114610de7576040519150601f19603f3d011682016040523d82523d6000602084013e610dec565b606091505b5050905080610e30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2790614803565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3386866040518463ffffffff1660e01b8152600401610e6f93929190614823565b6020604051808303816000875af1158015610e8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb29190613c9b565b505050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895308460016040518463ffffffff1660e01b8152600401610efc939291906146e4565b6020604051808303816000875af1158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f9190613c9b565b905080610f81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f78906148ad565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3085856040518463ffffffff1660e01b8152600401610fc093929190614823565b6020604051808303816000875af1158015610fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110039190613c9b565b50600160008082825461101691906148fc565b92505081905550505050565b61102a612288565b61080073ffffffffffffffffffffffffffffffffffffffff1663a03ffee184846040518363ffffffff1660e01b815260040161106792919061403e565b600060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906110ad9190614b60565b905092915050565b6000610800905060008585856040516024016110d393929190614823565b6040516020818303038152906040527f3edab33c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008360405160200161116591906140aa565b60405160208183030381529060405280519060200120905060405160200161118c9061410d565b6040516020818303038152906040528051906020012081036112595760008373ffffffffffffffffffffffffffffffffffffffff16836040516111cf919061415e565b600060405180830381855af49150503d806000811461120a576040519150601f19603f3d011682016040523d82523d6000602084013e61120f565b606091505b5050905080611253576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124a906141e7565b60405180910390fd5b5061149e565b6040516020016112689061431b565b6040516020818303038152906040528051906020012081036113355760008373ffffffffffffffffffffffffffffffffffffffff16836040516112ab919061415e565b600060405180830381855afa9150503d80600081146112e6576040519150601f19603f3d011682016040523d82523d6000602084013e6112eb565b606091505b505090508061132f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113269061437c565b60405180910390fd5b5061149d565b604051602001611344906143e8565b6040516020818303038152906040528051906020012081036114135760008373ffffffffffffffffffffffffffffffffffffffff1683604051611387919061415e565b6000604051808303816000865af19150503d80600081146113c4576040519150601f19603f3d011682016040523d82523d6000602084013e6113c9565b606091505b505090508061140d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140490614449565b60405180910390fd5b5061149c565b604051602001611422906144b5565b6040516020818303038152906040528051906020012081036114605760208201825160008082846000895af28061145857600080fd5b50505061149b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149290614516565b60405180910390fd5b5b5b5b50505050505050565b6114af6122a9565b61080073ffffffffffffffffffffffffffffffffffffffff16637d9f939c8585856040518463ffffffff1660e01b81526004016114ee93929190614ba9565b600060405180830381865afa15801561150b573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906115349190614e11565b90509392505050565b61080073ffffffffffffffffffffffffffffffffffffffff166312d58dfe858585856040518563ffffffff1660e01b815260040161157e9493929190614e5a565b6020604051808303816000875af115801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c19190613c9b565b5050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895303460016040518463ffffffff1660e01b815260040161160a939291906146e4565b6020604051808303816000875af1158015611629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164d9190613c9b565b90508061168f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161168690614ef2565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3084346040518463ffffffff1660e01b81526004016116ce93929190614823565b6020604051808303816000875af11580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117119190613c9b565b505050565b60005481565b600061080073ffffffffffffffffffffffffffffffffffffffff1663f7cd55168888888888886040518763ffffffff1660e01b815260040161176396959493929190615047565b6020604051808303816000875af1158015611782573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a69190613c9b565b90509695505050505050565b61080073ffffffffffffffffffffffffffffffffffffffff16633edab33c8484846040518463ffffffff1660e01b81526004016117f193929190614823565b6020604051808303816000875af1158015611810573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183491906150b7565b50505050565b60008081548092919061184c906150e4565b919050555061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8484846040518463ffffffff1660e01b815260040161189093929190614823565b6020604051808303816000875af11580156118af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d39190613c9b565b506000808154809291906118e69061512c565b9190505550505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895323460016040518463ffffffff1660e01b8152600401611932939291906146e4565b6020604051808303816000875af1158015611951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119759190613c9b565b9050806119b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ae90614ef2565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3084346040518463ffffffff1660e01b81526004016119f693929190614823565b6020604051808303816000875af1158015611a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a399190613c9b565b503373ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050158015611a80573d6000803e3d6000fd5b505050565b61080073ffffffffffffffffffffffffffffffffffffffff166354b826f5858585856040518563ffffffff1660e01b8152600401611ac69493929190615155565b6020604051808303816000875af1158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0991906150b7565b5050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663a50f05ac868686866040518563ffffffff1660e01b8152600401611b5394939291906151b7565b6020604051808303816000875af1158015611b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b969190613c9b565b9050949350505050565b6060611baa6122d1565b61080073ffffffffffffffffffffffffffffffffffffffff1663186b216785856040518363ffffffff1660e01b8152600401611be7929190615361565b600060405180830381865afa158015611c04573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611c2d9190615555565b915091509250929050565b6000611c4261226e565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e685856040518363ffffffff1660e01b8152600401611c7f92919061403e565b600060405180830381865afa158015611c9c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611cc59190614273565b915091509250929050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663fc08930c8433856040518463ffffffff1660e01b8152600401611d11939291906155cd565b602060405180830381865afa158015611d2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d52919061560b565b905092915050565b6000600167ffffffffffffffff811115611d7757611d76612714565b5b604051908082528060200260200182016040528015611daa57816020015b6060815260200190600190039081611d955790505b509050604051806060016040528060258152602001615d596025913981600081518110611dda57611dd9615638565b5b6020026020010181905250600061080073ffffffffffffffffffffffffffffffffffffffff1663b60398958787856040518463ffffffff1660e01b8152600401611e2693929190615718565b6020604051808303816000875af1158015611e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e699190613c9b565b905080611eab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea2906157c8565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff16633edab33c3285876040518463ffffffff1660e01b8152600401611eea93929190614823565b6020604051808303816000875af1158015611f09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2d91906150b7565b50505050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895323460016040518463ffffffff1660e01b8152600401611f78939291906146e4565b6020604051808303816000875af1158015611f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fbb9190613c9b565b905080611ffd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff490614ef2565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308460013461202a91906148fc565b6040518463ffffffff1660e01b815260040161204893929190614823565b6020604051808303816000875af1158015612067573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208b9190613c9b565b505050565b600061080073ffffffffffffffffffffffffffffffffffffffff166361dc5c3b8585856040518463ffffffff1660e01b81526004016120d1939291906157e8565b6020604051808303816000875af11580156120f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121149190613c9b565b905080612156576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214d9061588c565b60405180910390fd5b50505050565b60606121666122d1565b61080073ffffffffffffffffffffffffffffffffffffffff166310a2851c878787876040518563ffffffff1660e01b81526004016121a79493929190615922565b600060405180830381865afa1580156121c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121ed9190615ce0565b9150915094509492505050565b6040518061016001604052806060815260200160608152602001600015158152602001600060038111156122315761223061254e565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b604051806040016040528060608152602001600081525090565b60405180606001604052806060815260200160608152602001606081525090565b6040518060800160405280606081526020016060815260200160608152602001606081525090565b604051806040016040528060608152602001600067ffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061233482612309565b9050919050565b61234481612329565b811461234f57600080fd5b50565b6000813590506123618161233b565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261238c5761238b612367565b5b8235905067ffffffffffffffff8111156123a9576123a861236c565b5b6020830191508360208202830111156123c5576123c4612371565b5b9250929050565b6000819050919050565b6123df816123cc565b81146123ea57600080fd5b50565b6000813590506123fc816123d6565b92915050565b6000806000806060858703121561241c5761241b6122ff565b5b600061242a87828801612352565b945050602085013567ffffffffffffffff81111561244b5761244a612304565b5b61245787828801612376565b9350935050604061246a878288016123ed565b91505092959194509250565b60006020828403121561248c5761248b6122ff565b5b600061249a84828501612352565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156124dd5780820151818401526020810190506124c2565b60008484015250505050565b6000601f19601f8301169050919050565b6000612505826124a3565b61250f81856124ae565b935061251f8185602086016124bf565b612528816124e9565b840191505092915050565b60008115159050919050565b61254881612533565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061258e5761258d61254e565b5b50565b600081905061259f8261257d565b919050565b60006125af82612591565b9050919050565b6125bf816125a4565b82525050565b6125ce816123cc565b82525050565b60008160070b9050919050565b6125ea816125d4565b82525050565b600061016083016000830151848203600086015261260e82826124fa565b9150506020830151848203602086015261262882826124fa565b915050604083015161263d604086018261253f565b50606083015161265060608601826125b6565b50608083015161266360808601826125c5565b5060a083015161267660a08601826125c5565b5060c083015184820360c086015261268e82826124fa565b91505060e08301516126a360e08601826125e1565b506101008301516126b86101008601826125e1565b506101208301516126cd6101208601826125c5565b506101408301516126e26101408601826125c5565b508091505092915050565b6000602082019050818103600083015261270781846125f0565b905092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61274c826124e9565b810181811067ffffffffffffffff8211171561276b5761276a612714565b5b80604052505050565b600061277e6122f5565b905061278a8282612743565b919050565b600067ffffffffffffffff8211156127aa576127a9612714565b5b6127b3826124e9565b9050602081019050919050565b82818337600083830152505050565b60006127e26127dd8461278f565b612774565b9050828152602081018484840111156127fe576127fd61270f565b5b6128098482856127c0565b509392505050565b600082601f83011261282657612825612367565b5b81356128368482602086016127cf565b91505092915050565b600080600060608486031215612858576128576122ff565b5b600061286686828701612352565b935050602084013567ffffffffffffffff81111561288757612886612304565b5b61289386828701612811565b925050604084013567ffffffffffffffff8111156128b4576128b3612304565b5b6128c086828701612811565b9150509250925092565b6128d3816123cc565b82525050565b600060408301600083015184820360008601526128f682826124fa565b915050602083015161290b60208601826125c5565b508091505092915050565b600060408201905061292b60008301856128ca565b818103602083015261293d81846128d9565b90509392505050565b60008060006060848603121561295f5761295e6122ff565b5b600061296d86828701612352565b935050602084013567ffffffffffffffff81111561298e5761298d612304565b5b61299a86828701612811565b92505060406129ab868287016123ed565b9150509250925092565b600080604083850312156129cc576129cb6122ff565b5b600083013567ffffffffffffffff8111156129ea576129e9612304565b5b6129f685828601612811565b9250506020612a07858286016123ed565b9150509250929050565b60008060408385031215612a2857612a276122ff565b5b6000612a3685828601612352565b925050602083013567ffffffffffffffff811115612a5757612a56612304565b5b612a6385828601612811565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600067ffffffffffffffff82169050919050565b612ab681612a99565b82525050565b60c082016000820151612ad260008501826125e1565b506020820151612ae560208501826125e1565b506040820151612af860408501826125c5565b506060820151612b0b60608501826125c5565b506080820151612b1e6080850182612aad565b5060a0820151612b3160a08501826125e1565b50505050565b6000612b438383612abc565b60c08301905092915050565b6000602082019050919050565b6000612b6782612a6d565b612b718185612a78565b9350612b7c83612a89565b8060005b83811015612bad578151612b948882612b37565b9750612b9f83612b4f565b925050600181019050612b80565b5085935050505092915050565b60006060830160008301518482036000860152612bd782826124fa565b91505060208301518482036020860152612bf182826124fa565b91505060408301518482036040860152612c0b8282612b5c565b9150508091505092915050565b60006020820190508181036000830152612c328184612bba565b905092915050565b60008060008060808587031215612c5457612c536122ff565b5b6000612c6287828801612352565b945050602085013567ffffffffffffffff811115612c8357612c82612304565b5b612c8f87828801612811565b9350506040612ca0878288016123ed565b925050606085013567ffffffffffffffff811115612cc157612cc0612304565b5b612ccd87828801612811565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b608082016000820151612d1b60008501826125e1565b506020820151612d2e60208501826125e1565b506040820151612d4160408501826125c5565b506060820151612d5460608501826125c5565b50505050565b6000612d668383612d05565b60808301905092915050565b6000602082019050919050565b6000612d8a82612cd9565b612d948185612ce4565b9350612d9f83612cf5565b8060005b83811015612dd0578151612db78882612d5a565b9750612dc283612d72565b925050600181019050612da3565b5085935050505092915050565b60006080830160008301518482036000860152612dfa82826124fa565b91505060208301518482036020860152612e1482826124fa565b91505060408301518482036040860152612e2e82826124fa565b91505060608301518482036060860152612e488282612d7f565b9150508091505092915050565b60006020820190508181036000830152612e6f8184612ddd565b905092915050565b60008060008060808587031215612e9157612e906122ff565b5b6000612e9f87828801612352565b945050602085013567ffffffffffffffff811115612ec057612ebf612304565b5b612ecc87828801612811565b9350506040612edd878288016123ed565b9250506060612eee878288016123ed565b91505092959194509250565b600060208284031215612f1057612f0f6122ff565b5b600082013567ffffffffffffffff811115612f2e57612f2d612304565b5b612f3a84828501612811565b91505092915050565b6000602082019050612f5860008301846128ca565b92915050565b600080fd5b600060a08284031215612f7957612f78612f5e565b5b81905092915050565b600060608284031215612f9857612f97612f5e565b5b81905092915050565b6000806000806000806101008789031215612fbf57612fbe6122ff565b5b600087013567ffffffffffffffff811115612fdd57612fdc612304565b5b612fe989828a01612f63565b9650506020612ffa89828a01612f82565b955050608061300b89828a016123ed565b94505060a061301c89828a01612352565b93505060c087013567ffffffffffffffff81111561303d5761303c612304565b5b61304989828a01612811565b92505060e061305a89828a016123ed565b9150509295509295509295565b61307081612533565b82525050565b600060208201905061308b6000830184613067565b92915050565b600080600080608085870312156130ab576130aa6122ff565b5b60006130b987828801612352565b945050602085013567ffffffffffffffff8111156130da576130d9612304565b5b6130e687828801612811565b935050604085013567ffffffffffffffff81111561310757613106612304565b5b61311387828801612811565b9250506060613124878288016123ed565b91505092959194509250565b6000819050919050565b61314381613130565b811461314e57600080fd5b50565b6000813590506131608161313a565b92915050565b600080600080608085870312156131805761317f6122ff565b5b600085013567ffffffffffffffff81111561319e5761319d612304565b5b6131aa87828801612f63565b94505060206131bb87828801612352565b93505060406131cc87828801613151565b92505060606131dd87828801613151565b91505092959194509250565b600060a082840312156131ff576131fe612f5e565b5b81905092915050565b6000806040838503121561321f5761321e6122ff565b5b600083013567ffffffffffffffff81111561323d5761323c612304565b5b61324985828601612811565b925050602083013567ffffffffffffffff81111561326a57613269612304565b5b613276858286016131e9565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006101608301600083015184820360008601526132ca82826124fa565b915050602083015184820360208601526132e482826124fa565b91505060408301516132f9604086018261253f565b50606083015161330c60608601826125b6565b50608083015161331f60808601826125c5565b5060a083015161333260a08601826125c5565b5060c083015184820360c086015261334a82826124fa565b91505060e083015161335f60e08601826125e1565b506101008301516133746101008601826125e1565b506101208301516133896101208601826125c5565b5061014083015161339e6101408601826125c5565b508091505092915050565b60006133b583836132ac565b905092915050565b6000602082019050919050565b60006133d582613280565b6133df818561328b565b9350836020820285016133f18561329c565b8060005b8581101561342d578484038952815161340e85826133a9565b9450613419836133bd565b925060208a019950506001810190506133f5565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b60006134668261343f565b613470818561344a565b93506134808185602086016124bf565b613489816124e9565b840191505092915050565b600060408301600083015184820360008601526134b1828261345b565b91505060208301516134c66020860182612aad565b508091505092915050565b600060408201905081810360008301526134eb81856133ca565b905081810360208301526134ff8184613494565b90509392505050565b60008060008060808587031215613522576135216122ff565b5b600061353087828801612352565b9450506020613541878288016123ed565b9350506040613552878288016123ed565b925050606085013567ffffffffffffffff81111561357357613572612304565b5b61357f87828801612811565b91505092959194509250565b6000806000604084860312156135a4576135a36122ff565b5b60006135b286828701612352565b935050602084013567ffffffffffffffff8111156135d3576135d2612304565b5b6135df86828701612376565b92509250509250925092565b600080fd5b600080fd5b600067ffffffffffffffff8211156136105761360f612714565b5b613619826124e9565b9050602081019050919050565b6000613639613634846135f5565b612774565b9050828152602081018484840111156136555761365461270f565b5b6136608482856127c0565b509392505050565b600082601f83011261367d5761367c612367565b5b813561368d848260208601613626565b91505092915050565b61369f81612a99565b81146136aa57600080fd5b50565b6000813590506136bc81613696565b92915050565b6136cb81612533565b81146136d657600080fd5b50565b6000813590506136e8816136c2565b92915050565b600060a08284031215613704576137036135eb565b5b61370e60a0612774565b9050600082013567ffffffffffffffff81111561372e5761372d6135f0565b5b61373a84828501613668565b600083015250602061374e848285016136ad565b6020830152506040613762848285016136ad565b6040830152506060613776848285016136d9565b606083015250608061378a848285016136d9565b60808301525092915050565b600080600080608085870312156137b0576137af6122ff565b5b60006137be87828801612352565b945050602085013567ffffffffffffffff8111156137df576137de612304565b5b6137eb87828801612811565b935050604085013567ffffffffffffffff81111561380c5761380b612304565b5b61381887828801612811565b925050606085013567ffffffffffffffff81111561383957613838612304565b5b613845878288016136ee565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000608083016000830151848203600086015261389a82826124fa565b915050602083015184820360208601526138b482826124fa565b915050604083015184820360408601526138ce82826124fa565b915050606083015184820360608601526138e88282612d7f565b9150508091505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60a0820160008201516139376000850182612d05565b50602082015161394a60808501826125c5565b50505050565b600061395c8383613921565b60a08301905092915050565b6000602082019050919050565b6000613980826138f5565b61398a8185613900565b935061399583613911565b8060005b838110156139c65781516139ad8882613950565b97506139b883613968565b925050600181019050613999565b5085935050505092915050565b600060408301600083015184820360008601526139f0828261387d565b91505060208301518482036020860152613a0a8282613975565b9150508091505092915050565b6000613a2383836139d3565b905092915050565b6000602082019050919050565b6000613a4382613851565b613a4d818561385c565b935083602082028501613a5f8561386d565b8060005b85811015613a9b5784840389528151613a7c8582613a17565b9450613a8783613a2b565b925060208a01995050600181019050613a63565b50829750879550505050505092915050565b60006040820190508181036000830152613ac78185613a38565b90508181036020830152613adb8184613494565b90509392505050565b613aed81612329565b82525050565b600082825260208201905092915050565b6000819050919050565b6000613b1a83856124ae565b9350613b278385846127c0565b613b30836124e9565b840190509392505050565b6000613b48848484613b0e565b90509392505050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613b7d57613b7c613b5b565b5b83810192508235915060208301925067ffffffffffffffff821115613ba557613ba4613b51565b5b600182023603831315613bbb57613bba613b56565b5b509250929050565b6000602082019050919050565b6000613bdc8385613af3565b935083602084028501613bee84613b04565b8060005b87811015613c34578484038952613c098284613b60565b613c14868284613b3b565b9550613c1f84613bc3565b935060208b019a505050600181019050613bf2565b50829750879450505050509392505050565b6000606082019050613c5b6000830187613ae4565b613c6860208301866128ca565b8181036040830152613c7b818486613bd0565b905095945050505050565b600081519050613c95816136c2565b92915050565b600060208284031215613cb157613cb06122ff565b5b6000613cbf84828501613c86565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f20617070726f7665207374616b696e67206d6574686f6460008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d35602183613cc8565b9150613d4082613cd9565b604082019050919050565b60006020820190508181036000830152613d6481613d28565b9050919050565b6000602082019050613d806000830184613ae4565b92915050565b6000613d99613d948461278f565b612774565b905082815260208101848484011115613db557613db461270f565b5b613dc08482856124bf565b509392505050565b600082601f830112613ddd57613ddc612367565b5b8151613ded848260208601613d86565b91505092915050565b60048110613e0357600080fd5b50565b600081519050613e1581613df6565b92915050565b600081519050613e2a816123d6565b92915050565b613e39816125d4565b8114613e4457600080fd5b50565b600081519050613e5681613e30565b92915050565b60006101608284031215613e7357613e726135eb565b5b613e7e610160612774565b9050600082015167ffffffffffffffff811115613e9e57613e9d6135f0565b5b613eaa84828501613dc8565b600083015250602082015167ffffffffffffffff811115613ece57613ecd6135f0565b5b613eda84828501613dc8565b6020830152506040613eee84828501613c86565b6040830152506060613f0284828501613e06565b6060830152506080613f1684828501613e1b565b60808301525060a0613f2a84828501613e1b565b60a08301525060c082015167ffffffffffffffff811115613f4e57613f4d6135f0565b5b613f5a84828501613dc8565b60c08301525060e0613f6e84828501613e47565b60e083015250610100613f8384828501613e47565b61010083015250610120613f9984828501613e1b565b61012083015250610140613faf84828501613e1b565b6101408301525092915050565b600060208284031215613fd257613fd16122ff565b5b600082015167ffffffffffffffff811115613ff057613fef612304565b5b613ffc84828501613e5c565b91505092915050565b6000614010826124a3565b61401a8185613cc8565b935061402a8185602086016124bf565b614033816124e9565b840191505092915050565b60006040820190506140536000830185613ae4565b81810360208301526140658184614005565b90509392505050565b600081905092915050565b6000614084826124a3565b61408e818561406e565b935061409e8185602086016124bf565b80840191505092915050565b60006140b68284614079565b915081905092915050565b7f64656c656761746563616c6c0000000000000000000000000000000000000000600082015250565b60006140f7600c8361406e565b9150614102826140c1565b600c82019050919050565b6000614118826140ea565b9150819050919050565b600081905092915050565b60006141388261343f565b6141428185614122565b93506141528185602086016124bf565b80840191505092915050565b600061416a828461412d565b915081905092915050565b7f6661696c65642064656c656761746563616c6c20746f20707265636f6d70696c60008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b60006141d1602183613cc8565b91506141dc82614175565b604082019050919050565b60006020820190508181036000830152614200816141c4565b9050919050565b60006040828403121561421d5761421c6135eb565b5b6142276040612774565b9050600082015167ffffffffffffffff811115614247576142466135f0565b5b61425384828501613dc8565b600083015250602061426784828501613e1b565b60208301525092915050565b6000806040838503121561428a576142896122ff565b5b600061429885828601613e1b565b925050602083015167ffffffffffffffff8111156142b9576142b8612304565b5b6142c585828601614207565b9150509250929050565b7f73746174696363616c6c00000000000000000000000000000000000000000000600082015250565b6000614305600a8361406e565b9150614310826142cf565b600a82019050919050565b6000614326826142f8565b9150819050919050565b7f6661696c65642073746174696363616c6c20746f20707265636f6d70696c6500600082015250565b6000614366601f83613cc8565b915061437182614330565b602082019050919050565b6000602082019050818103600083015261439581614359565b9050919050565b7f63616c6c00000000000000000000000000000000000000000000000000000000600082015250565b60006143d260048361406e565b91506143dd8261439c565b600482019050919050565b60006143f3826143c5565b9150819050919050565b7f6661696c65642063616c6c20746f20707265636f6d70696c6500000000000000600082015250565b6000614433601983613cc8565b915061443e826143fd565b602082019050919050565b6000602082019050818103600083015261446281614426565b9050919050565b7f63616c6c636f6465000000000000000000000000000000000000000000000000600082015250565b600061449f60088361406e565b91506144aa82614469565b600882019050919050565b60006144c082614492565b9150819050919050565b7f696e76616c69642063616c6c7479706500000000000000000000000000000000600082015250565b6000614500601083613cc8565b915061450b826144ca565b602082019050919050565b6000602082019050818103600083015261452f816144f3565b9050919050565b600081549050919050565b60008190508160005260206000209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061459d57607f821691505b6020821081036145b0576145af614556565b5b50919050565b60008190508160005260206000209050919050565b600081546145d881614585565b6145e281866124ae565b945060018216600081146145fd576001811461461357614646565b60ff198316865281151560200286019350614646565b61461c856145b6565b60005b8381101561463e5781548189015260018201915060208101905061461f565b808801955050505b50505092915050565b600061465b83836145cb565b905092915050565b6000600182019050919050565b600061467b82614536565b6146858185613af3565b93508360208202850161469785614541565b8060005b858110156146d2578484038952816146b3858261464f565b94506146be83614663565b925060208a0199505060018101905061469b565b50829750879550505050505092915050565b60006060820190506146f96000830186613ae4565b61470660208301856128ca565b81810360408301526147188184614670565b9050949350505050565b7f64656c65676174696f6e20617070726f76616c206661696c6564000000000000600082015250565b6000614758601a83613cc8565b915061476382614722565b602082019050919050565b600060208201905081810360008301526147878161474b565b9050919050565b60006040820190506147a36000830185613ae4565b6147b060208301846128ca565b9392505050565b7f7472616e73666572206661696c65640000000000000000000000000000000000600082015250565b60006147ed600f83613cc8565b91506147f8826147b7565b602082019050919050565b6000602082019050818103600083015261481c816147e0565b9050919050565b60006060820190506148386000830186613ae4565b818103602083015261484a8185614005565b905061485960408301846128ca565b949350505050565b7f5374616b696e6720417070726f7665206661696c656400000000000000000000600082015250565b6000614897601683613cc8565b91506148a282614861565b602082019050919050565b600060208201905081810360008301526148c68161488a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614907826123cc565b9150614912836123cc565b925082820190508082111561492a576149296148cd565b5b92915050565b600067ffffffffffffffff82111561494b5761494a612714565b5b602082029050602081019050919050565b60008151905061496b81613696565b92915050565b600060c08284031215614987576149866135eb565b5b61499160c0612774565b905060006149a184828501613e47565b60008301525060206149b584828501613e47565b60208301525060406149c984828501613e1b565b60408301525060606149dd84828501613e1b565b60608301525060806149f18482850161495c565b60808301525060a0614a0584828501613e47565b60a08301525092915050565b6000614a24614a1f84614930565b612774565b90508083825260208201905060c08402830185811115614a4757614a46612371565b5b835b81811015614a705780614a5c8882614971565b84526020840193505060c081019050614a49565b5050509392505050565b600082601f830112614a8f57614a8e612367565b5b8151614a9f848260208601614a11565b91505092915050565b600060608284031215614abe57614abd6135eb565b5b614ac86060612774565b9050600082015167ffffffffffffffff811115614ae857614ae76135f0565b5b614af484828501613dc8565b600083015250602082015167ffffffffffffffff811115614b1857614b176135f0565b5b614b2484828501613dc8565b602083015250604082015167ffffffffffffffff811115614b4857614b476135f0565b5b614b5484828501614a7a565b60408301525092915050565b600060208284031215614b7657614b756122ff565b5b600082015167ffffffffffffffff811115614b9457614b93612304565b5b614ba084828501614aa8565b91505092915050565b6000606082019050614bbe6000830186613ae4565b8181036020830152614bd08185614005565b90508181036040830152614be48184614005565b9050949350505050565b600067ffffffffffffffff821115614c0957614c08612714565b5b602082029050602081019050919050565b600060808284031215614c3057614c2f6135eb565b5b614c3a6080612774565b90506000614c4a84828501613e47565b6000830152506020614c5e84828501613e47565b6020830152506040614c7284828501613e1b565b6040830152506060614c8684828501613e1b565b60608301525092915050565b6000614ca5614ca084614bee565b612774565b90508083825260208201905060808402830185811115614cc857614cc7612371565b5b835b81811015614cf15780614cdd8882614c1a565b845260208401935050608081019050614cca565b5050509392505050565b600082601f830112614d1057614d0f612367565b5b8151614d20848260208601614c92565b91505092915050565b600060808284031215614d3f57614d3e6135eb565b5b614d496080612774565b9050600082015167ffffffffffffffff811115614d6957614d686135f0565b5b614d7584828501613dc8565b600083015250602082015167ffffffffffffffff811115614d9957614d986135f0565b5b614da584828501613dc8565b602083015250604082015167ffffffffffffffff811115614dc957614dc86135f0565b5b614dd584828501613dc8565b604083015250606082015167ffffffffffffffff811115614df957614df86135f0565b5b614e0584828501614cfb565b60608301525092915050565b600060208284031215614e2757614e266122ff565b5b600082015167ffffffffffffffff811115614e4557614e44612304565b5b614e5184828501614d29565b91505092915050565b6000608082019050614e6f6000830187613ae4565b8181036020830152614e818186614005565b9050614e9060408301856128ca565b614e9d60608301846128ca565b95945050505050565b7f44656c656761746520417070726f7665206661696c6564000000000000000000600082015250565b6000614edc601783613cc8565b9150614ee782614ea6565b602082019050919050565b60006020820190508181036000830152614f0b81614ecf565b9050919050565b600060a08301614f256000840184613b60565b8583036000870152614f38838284613b0e565b92505050614f496020840184613b60565b8583036020870152614f5c838284613b0e565b92505050614f6d6040840184613b60565b8583036040870152614f80838284613b0e565b92505050614f916060840184613b60565b8583036060870152614fa4838284613b0e565b92505050614fb56080840184613b60565b8583036080870152614fc8838284613b0e565b925050508091505092915050565b6000614fe560208401846123ed565b905092915050565b60608201614ffe6000830183614fd6565b61500b60008501826125c5565b506150196020830183614fd6565b61502660208501826125c5565b506150346040830183614fd6565b61504160408501826125c5565b50505050565b60006101008201905081810360008301526150628189614f12565b90506150716020830188614fed565b61507e60808301876128ca565b61508b60a0830186613ae4565b81810360c083015261509d8185614005565b90506150ac60e08301846128ca565b979650505050505050565b6000602082840312156150cd576150cc6122ff565b5b60006150db84828501613e47565b91505092915050565b60006150ef826123cc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615121576151206148cd565b5b600182019050919050565b6000615137826123cc565b91506000820361514a576151496148cd565b5b600182039050919050565b600060808201905061516a6000830187613ae4565b818103602083015261517c8186614005565b905081810360408301526151908185614005565b905061519f60608301846128ca565b95945050505050565b6151b181613130565b82525050565b600060808201905081810360008301526151d18187614f12565b90506151e06020830186613ae4565b6151ed60408301856151a8565b6151fa60608301846151a8565b95945050505050565b600080833560016020038436030381126152205761521f613b5b565b5b83810192508235915060208301925067ffffffffffffffff82111561524857615247613b51565b5b60018202360383131561525e5761525d613b56565b5b509250929050565b6000615272838561344a565b935061527f8385846127c0565b615288836124e9565b840190509392505050565b60006152a260208401846136ad565b905092915050565b60006152b960208401846136d9565b905092915050565b600060a083016152d46000840184615203565b85830360008701526152e7838284615266565b925050506152f86020840184615293565b6153056020860182612aad565b506153136040840184615293565b6153206040860182612aad565b5061532e60608401846152aa565b61533b606086018261253f565b5061534960808401846152aa565b615356608086018261253f565b508091505092915050565b6000604082019050818103600083015261537b8185614005565b9050818103602083015261538f81846152c1565b90509392505050565b600067ffffffffffffffff8211156153b3576153b2612714565b5b602082029050602081019050919050565b60006153d76153d284615398565b612774565b905080838252602082019050602084028301858111156153fa576153f9612371565b5b835b8181101561544157805167ffffffffffffffff81111561541f5761541e612367565b5b80860161542c8982613e5c565b855260208501945050506020810190506153fc565b5050509392505050565b600082601f8301126154605761545f612367565b5b81516154708482602086016153c4565b91505092915050565b600061548c615487846135f5565b612774565b9050828152602081018484840111156154a8576154a761270f565b5b6154b38482856124bf565b509392505050565b600082601f8301126154d0576154cf612367565b5b81516154e0848260208601615479565b91505092915050565b6000604082840312156154ff576154fe6135eb565b5b6155096040612774565b9050600082015167ffffffffffffffff811115615529576155286135f0565b5b615535848285016154bb565b60008301525060206155498482850161495c565b60208301525092915050565b6000806040838503121561556c5761556b6122ff565b5b600083015167ffffffffffffffff81111561558a57615589612304565b5b6155968582860161544b565b925050602083015167ffffffffffffffff8111156155b7576155b6612304565b5b6155c3858286016154e9565b9150509250929050565b60006060820190506155e26000830186613ae4565b6155ef6020830185613ae4565b81810360408301526156018184614005565b9050949350505050565b600060208284031215615621576156206122ff565b5b600061562f84828501613e1b565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b6000819050602082019050919050565b600061568e83836124fa565b905092915050565b6000602082019050919050565b60006156ae82615667565b6156b88185613af3565b9350836020820285016156ca85615672565b8060005b8581101561570657848403895281516156e78582615682565b94506156f283615696565b925060208a019950506001810190506156ce565b50829750879550505050505092915050565b600060608201905061572d6000830186613ae4565b61573a60208301856128ca565b818103604083015261574c81846156a3565b9050949350505050565b7f6661696c656420746f20617070726f766520756e64656c65676174696f6e206d60008201527f6574686f64000000000000000000000000000000000000000000000000000000602082015250565b60006157b2602583613cc8565b91506157bd82615756565b604082019050919050565b600060208201905081810360008301526157e1816157a5565b9050919050565b60006040820190506157fd6000830186613ae4565b8181036020830152615810818486613bd0565b9050949350505050565b7f4661696c656420746f207265766f6b6520617070726f76616c20666f7220737460008201527f616b696e67206d6574686f647300000000000000000000000000000000000000602082015250565b6000615876602d83613cc8565b91506158818261581a565b604082019050919050565b600060208201905081810360008301526158a581615869565b9050919050565b600060a08301600083015184820360008601526158c9828261345b565b91505060208301516158de6020860182612aad565b5060408301516158f16040860182612aad565b506060830151615904606086018261253f565b506080830151615917608086018261253f565b508091505092915050565b60006080820190506159376000830187613ae4565b81810360208301526159498186614005565b9050818103604083015261595d8185614005565b9050818103606083015261597181846158ac565b905095945050505050565b600067ffffffffffffffff82111561599757615996612714565b5b602082029050602081019050919050565b6000608082840312156159be576159bd6135eb565b5b6159c86080612774565b9050600082015167ffffffffffffffff8111156159e8576159e76135f0565b5b6159f484828501613dc8565b600083015250602082015167ffffffffffffffff811115615a1857615a176135f0565b5b615a2484828501613dc8565b602083015250604082015167ffffffffffffffff811115615a4857615a476135f0565b5b615a5484828501613dc8565b604083015250606082015167ffffffffffffffff811115615a7857615a776135f0565b5b615a8484828501614cfb565b60608301525092915050565b600067ffffffffffffffff821115615aab57615aaa612714565b5b602082029050602081019050919050565b600060a08284031215615ad257615ad16135eb565b5b615adc6040612774565b90506000615aec84828501614c1a565b6000830152506080615b0084828501613e1b565b60208301525092915050565b6000615b1f615b1a84615a90565b612774565b90508083825260208201905060a08402830185811115615b4257615b41612371565b5b835b81811015615b6b5780615b578882615abc565b84526020840193505060a081019050615b44565b5050509392505050565b600082601f830112615b8a57615b89612367565b5b8151615b9a848260208601615b0c565b91505092915050565b600060408284031215615bb957615bb86135eb565b5b615bc36040612774565b9050600082015167ffffffffffffffff811115615be357615be26135f0565b5b615bef848285016159a8565b600083015250602082015167ffffffffffffffff811115615c1357615c126135f0565b5b615c1f84828501615b75565b60208301525092915050565b6000615c3e615c398461597c565b612774565b90508083825260208201905060208402830185811115615c6157615c60612371565b5b835b81811015615ca857805167ffffffffffffffff811115615c8657615c85612367565b5b808601615c938982615ba3565b85526020850194505050602081019050615c63565b5050509392505050565b600082601f830112615cc757615cc6612367565b5b8151615cd7848260208601615c2b565b91505092915050565b60008060408385031215615cf757615cf66122ff565b5b600083015167ffffffffffffffff811115615d1557615d14612304565b5b615d2185828601615cb2565b925050602083015167ffffffffffffffff811115615d4257615d41612304565b5b615d4e858286016154e9565b915050925092905056fe2f636f736d6f732e7374616b696e672e763162657461312e4d7367556e64656c6567617465a2646970667358221220610cb91a8933e1804929f56c9cd7a1adc794d98816aa48df9e694b7cd16e831b64736f6c634300081300332f636f736d6f732e7374616b696e672e763162657461312e4d736744656c6567617465",
+ "deployedBytecode": "0x60806040526004361061014b5760003560e01c80637e51b811116100b6578063cf2753cf1161006f578063cf2753cf146104a8578063ec9485df146104e6578063f40a214614610523578063f5714e641461054c578063f700dbd214610568578063f732b065146105915761014b565b80637e51b811146103965780638939e783146103bf5780638edb3f8b146103e85780639eab671114610404578063af9a90b21461042d578063b13d42421461046a5761014b565b806355dc4b221161010857806355dc4b2214610283578063570467ac146102ac5780635e269bfe146102e957806360deaa2a1461031257806361bc221a1461032e57806368ac3df3146103595761014b565b80630a4433e2146101505780631904bb2e1461017957806319b16c4c146101b657806331bcbcb3146101f45780633566cb951461021d578063455b855114610246575b600080fd5b34801561015c57600080fd5b5061017760048036038101906101729190612402565b6105cf565b005b34801561018557600080fd5b506101a0600480360381019061019b9190612476565b61069e565b6040516101ad91906126ed565b60405180910390f35b3480156101c257600080fd5b506101dd60048036038101906101d8919061283f565b61072e565b6040516101eb929190612916565b60405180910390f35b34801561020057600080fd5b5061021b60048036038101906102169190612946565b610c2d565b005b34801561022957600080fd5b50610244600480360381019061023f91906129b5565b610eba565b005b34801561025257600080fd5b5061026d60048036038101906102689190612a11565b611022565b60405161027a9190612c18565b60405180910390f35b34801561028f57600080fd5b506102aa60048036038101906102a59190612c3a565b6110b5565b005b3480156102b857600080fd5b506102d360048036038101906102ce919061283f565b6114a7565b6040516102e09190612e55565b60405180910390f35b3480156102f557600080fd5b50610310600480360381019061030b9190612e77565b61153d565b005b61032c60048036038101906103279190612efa565b6115c8565b005b34801561033a57600080fd5b50610343611716565b6040516103509190612f43565b60405180910390f35b34801561036557600080fd5b50610380600480360381019061037b9190612fa1565b61171c565b60405161038d9190613076565b60405180910390f35b3480156103a257600080fd5b506103bd60048036038101906103b89190612946565b6117b2565b005b3480156103cb57600080fd5b506103e660048036038101906103e19190612946565b61183a565b005b61040260048036038101906103fd9190612efa565b6118f0565b005b34801561041057600080fd5b5061042b60048036038101906104269190613091565b611a85565b005b34801561043957600080fd5b50610454600480360381019061044f9190613166565b611b10565b6040516104619190613076565b60405180910390f35b34801561047657600080fd5b50610491600480360381019061048c9190613208565b611ba0565b60405161049f9291906134d1565b60405180910390f35b3480156104b457600080fd5b506104cf60048036038101906104ca9190612a11565b611c38565b6040516104dd929190612916565b60405180910390f35b3480156104f257600080fd5b5061050d60048036038101906105089190612a11565b611cd0565b60405161051a9190612f43565b60405180910390f35b34801561052f57600080fd5b5061054a60048036038101906105459190613508565b611d5a565b005b61056660048036038101906105619190612efa565b611f36565b005b34801561057457600080fd5b5061058f600480360381019061058a919061358b565b612090565b005b34801561059d57600080fd5b506105b860048036038101906105b39190613796565b61215c565b6040516105c6929190613aad565b60405180910390f35b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895868487876040518563ffffffff1660e01b81526004016106129493929190613c46565b6020604051808303816000875af1158015610631573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106559190613c9b565b905080610697576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068e90613d4b565b60405180910390fd5b5050505050565b6106a66121fa565b61080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a836040518263ffffffff1660e01b81526004016106e19190613d6b565b600060405180830381865afa1580156106fe573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107279190613fbc565b9050919050565b600061073861226e565b600061080090506000868660405160240161075492919061403e565b6040516020818303038152906040527f241774e6000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000856040516020016107e691906140aa565b60405160208183030381529060405280519060200120905060405160200161080d9061410d565b6040516020818303038152906040528051906020012081036108f9576000808473ffffffffffffffffffffffffffffffffffffffff1684604051610851919061415e565b600060405180830381855af49150503d806000811461088c576040519150601f19603f3d011682016040523d82523d6000602084013e610891565b606091505b5091509150816108d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cd906141e7565b60405180910390fd5b808060200190518101906108ea9190614273565b80975081985050505050610c22565b6040516020016109089061431b565b6040516020818303038152906040528051906020012081036109f4576000808473ffffffffffffffffffffffffffffffffffffffff168460405161094c919061415e565b600060405180830381855afa9150503d8060008114610987576040519150601f19603f3d011682016040523d82523d6000602084013e61098c565b606091505b5091509150816109d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109c89061437c565b60405180910390fd5b808060200190518101906109e59190614273565b80975081985050505050610c21565b604051602001610a03906143e8565b604051602081830303815290604052805190602001208103610af1576000808473ffffffffffffffffffffffffffffffffffffffff1684604051610a47919061415e565b6000604051808303816000865af19150503d8060008114610a84576040519150601f19603f3d011682016040523d82523d6000602084013e610a89565b606091505b509150915081610ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac590614449565b60405180910390fd5b80806020019051810190610ae29190614273565b80975081985050505050610c20565b604051602001610b00906144b5565b604051602081830303815290604052805190602001208103610be45760006040518060400160405280601a81526020017f64656c65676174696f6e28616464726573732c737472696e6729000000000000815250805190602001209050600060a490506060600060208b01516020808d0101516040518681528e6004820152604060248201526033604482015282606482015281608482015260c081878360008e5af281519c5060608201519450610100820160405280610bc057600080fd5b50505050604051806040016040528083815260200182815250975050505050610c1f565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1690614516565b60405180910390fd5b5b5b5b505050935093915050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895308460016040518463ffffffff1660e01b8152600401610c6f939291906146e4565b6020604051808303816000875af1158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb29190613c9b565b905080610cf4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ceb9061476e565b60405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff163384604051602401610d2092919061478e565b6040516020818303038152906040527fa9059cbb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610daa919061415e565b6000604051808303816000865af19150503d8060008114610de7576040519150601f19603f3d011682016040523d82523d6000602084013e610dec565b606091505b5050905080610e30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2790614803565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3386866040518463ffffffff1660e01b8152600401610e6f93929190614823565b6020604051808303816000875af1158015610e8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb29190613c9b565b505050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895308460016040518463ffffffff1660e01b8152600401610efc939291906146e4565b6020604051808303816000875af1158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f9190613c9b565b905080610f81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f78906148ad565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3085856040518463ffffffff1660e01b8152600401610fc093929190614823565b6020604051808303816000875af1158015610fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110039190613c9b565b50600160008082825461101691906148fc565b92505081905550505050565b61102a612288565b61080073ffffffffffffffffffffffffffffffffffffffff1663a03ffee184846040518363ffffffff1660e01b815260040161106792919061403e565b600060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906110ad9190614b60565b905092915050565b6000610800905060008585856040516024016110d393929190614823565b6040516020818303038152906040527f3edab33c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008360405160200161116591906140aa565b60405160208183030381529060405280519060200120905060405160200161118c9061410d565b6040516020818303038152906040528051906020012081036112595760008373ffffffffffffffffffffffffffffffffffffffff16836040516111cf919061415e565b600060405180830381855af49150503d806000811461120a576040519150601f19603f3d011682016040523d82523d6000602084013e61120f565b606091505b5050905080611253576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124a906141e7565b60405180910390fd5b5061149e565b6040516020016112689061431b565b6040516020818303038152906040528051906020012081036113355760008373ffffffffffffffffffffffffffffffffffffffff16836040516112ab919061415e565b600060405180830381855afa9150503d80600081146112e6576040519150601f19603f3d011682016040523d82523d6000602084013e6112eb565b606091505b505090508061132f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113269061437c565b60405180910390fd5b5061149d565b604051602001611344906143e8565b6040516020818303038152906040528051906020012081036114135760008373ffffffffffffffffffffffffffffffffffffffff1683604051611387919061415e565b6000604051808303816000865af19150503d80600081146113c4576040519150601f19603f3d011682016040523d82523d6000602084013e6113c9565b606091505b505090508061140d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140490614449565b60405180910390fd5b5061149c565b604051602001611422906144b5565b6040516020818303038152906040528051906020012081036114605760208201825160008082846000895af28061145857600080fd5b50505061149b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149290614516565b60405180910390fd5b5b5b5b50505050505050565b6114af6122a9565b61080073ffffffffffffffffffffffffffffffffffffffff16637d9f939c8585856040518463ffffffff1660e01b81526004016114ee93929190614ba9565b600060405180830381865afa15801561150b573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906115349190614e11565b90509392505050565b61080073ffffffffffffffffffffffffffffffffffffffff166312d58dfe858585856040518563ffffffff1660e01b815260040161157e9493929190614e5a565b6020604051808303816000875af115801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c19190613c9b565b5050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895303460016040518463ffffffff1660e01b815260040161160a939291906146e4565b6020604051808303816000875af1158015611629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164d9190613c9b565b90508061168f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161168690614ef2565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3084346040518463ffffffff1660e01b81526004016116ce93929190614823565b6020604051808303816000875af11580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117119190613c9b565b505050565b60005481565b600061080073ffffffffffffffffffffffffffffffffffffffff1663f7cd55168888888888886040518763ffffffff1660e01b815260040161176396959493929190615047565b6020604051808303816000875af1158015611782573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a69190613c9b565b90509695505050505050565b61080073ffffffffffffffffffffffffffffffffffffffff16633edab33c8484846040518463ffffffff1660e01b81526004016117f193929190614823565b6020604051808303816000875af1158015611810573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183491906150b7565b50505050565b60008081548092919061184c906150e4565b919050555061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8484846040518463ffffffff1660e01b815260040161189093929190614823565b6020604051808303816000875af11580156118af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d39190613c9b565b506000808154809291906118e69061512c565b9190505550505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895323460016040518463ffffffff1660e01b8152600401611932939291906146e4565b6020604051808303816000875af1158015611951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119759190613c9b565b9050806119b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ae90614ef2565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3084346040518463ffffffff1660e01b81526004016119f693929190614823565b6020604051808303816000875af1158015611a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a399190613c9b565b503373ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050158015611a80573d6000803e3d6000fd5b505050565b61080073ffffffffffffffffffffffffffffffffffffffff166354b826f5858585856040518563ffffffff1660e01b8152600401611ac69493929190615155565b6020604051808303816000875af1158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0991906150b7565b5050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663a50f05ac868686866040518563ffffffff1660e01b8152600401611b5394939291906151b7565b6020604051808303816000875af1158015611b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b969190613c9b565b9050949350505050565b6060611baa6122d1565b61080073ffffffffffffffffffffffffffffffffffffffff1663186b216785856040518363ffffffff1660e01b8152600401611be7929190615361565b600060405180830381865afa158015611c04573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611c2d9190615555565b915091509250929050565b6000611c4261226e565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e685856040518363ffffffff1660e01b8152600401611c7f92919061403e565b600060405180830381865afa158015611c9c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611cc59190614273565b915091509250929050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663fc08930c8433856040518463ffffffff1660e01b8152600401611d11939291906155cd565b602060405180830381865afa158015611d2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d52919061560b565b905092915050565b6000600167ffffffffffffffff811115611d7757611d76612714565b5b604051908082528060200260200182016040528015611daa57816020015b6060815260200190600190039081611d955790505b509050604051806060016040528060258152602001615d596025913981600081518110611dda57611dd9615638565b5b6020026020010181905250600061080073ffffffffffffffffffffffffffffffffffffffff1663b60398958787856040518463ffffffff1660e01b8152600401611e2693929190615718565b6020604051808303816000875af1158015611e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e699190613c9b565b905080611eab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea2906157c8565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff16633edab33c3285876040518463ffffffff1660e01b8152600401611eea93929190614823565b6020604051808303816000875af1158015611f09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2d91906150b7565b50505050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895323460016040518463ffffffff1660e01b8152600401611f78939291906146e4565b6020604051808303816000875af1158015611f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fbb9190613c9b565b905080611ffd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff490614ef2565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308460013461202a91906148fc565b6040518463ffffffff1660e01b815260040161204893929190614823565b6020604051808303816000875af1158015612067573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208b9190613c9b565b505050565b600061080073ffffffffffffffffffffffffffffffffffffffff166361dc5c3b8585856040518463ffffffff1660e01b81526004016120d1939291906157e8565b6020604051808303816000875af11580156120f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121149190613c9b565b905080612156576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214d9061588c565b60405180910390fd5b50505050565b60606121666122d1565b61080073ffffffffffffffffffffffffffffffffffffffff166310a2851c878787876040518563ffffffff1660e01b81526004016121a79493929190615922565b600060405180830381865afa1580156121c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121ed9190615ce0565b9150915094509492505050565b6040518061016001604052806060815260200160608152602001600015158152602001600060038111156122315761223061254e565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b604051806040016040528060608152602001600081525090565b60405180606001604052806060815260200160608152602001606081525090565b6040518060800160405280606081526020016060815260200160608152602001606081525090565b604051806040016040528060608152602001600067ffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061233482612309565b9050919050565b61234481612329565b811461234f57600080fd5b50565b6000813590506123618161233b565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261238c5761238b612367565b5b8235905067ffffffffffffffff8111156123a9576123a861236c565b5b6020830191508360208202830111156123c5576123c4612371565b5b9250929050565b6000819050919050565b6123df816123cc565b81146123ea57600080fd5b50565b6000813590506123fc816123d6565b92915050565b6000806000806060858703121561241c5761241b6122ff565b5b600061242a87828801612352565b945050602085013567ffffffffffffffff81111561244b5761244a612304565b5b61245787828801612376565b9350935050604061246a878288016123ed565b91505092959194509250565b60006020828403121561248c5761248b6122ff565b5b600061249a84828501612352565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156124dd5780820151818401526020810190506124c2565b60008484015250505050565b6000601f19601f8301169050919050565b6000612505826124a3565b61250f81856124ae565b935061251f8185602086016124bf565b612528816124e9565b840191505092915050565b60008115159050919050565b61254881612533565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061258e5761258d61254e565b5b50565b600081905061259f8261257d565b919050565b60006125af82612591565b9050919050565b6125bf816125a4565b82525050565b6125ce816123cc565b82525050565b60008160070b9050919050565b6125ea816125d4565b82525050565b600061016083016000830151848203600086015261260e82826124fa565b9150506020830151848203602086015261262882826124fa565b915050604083015161263d604086018261253f565b50606083015161265060608601826125b6565b50608083015161266360808601826125c5565b5060a083015161267660a08601826125c5565b5060c083015184820360c086015261268e82826124fa565b91505060e08301516126a360e08601826125e1565b506101008301516126b86101008601826125e1565b506101208301516126cd6101208601826125c5565b506101408301516126e26101408601826125c5565b508091505092915050565b6000602082019050818103600083015261270781846125f0565b905092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61274c826124e9565b810181811067ffffffffffffffff8211171561276b5761276a612714565b5b80604052505050565b600061277e6122f5565b905061278a8282612743565b919050565b600067ffffffffffffffff8211156127aa576127a9612714565b5b6127b3826124e9565b9050602081019050919050565b82818337600083830152505050565b60006127e26127dd8461278f565b612774565b9050828152602081018484840111156127fe576127fd61270f565b5b6128098482856127c0565b509392505050565b600082601f83011261282657612825612367565b5b81356128368482602086016127cf565b91505092915050565b600080600060608486031215612858576128576122ff565b5b600061286686828701612352565b935050602084013567ffffffffffffffff81111561288757612886612304565b5b61289386828701612811565b925050604084013567ffffffffffffffff8111156128b4576128b3612304565b5b6128c086828701612811565b9150509250925092565b6128d3816123cc565b82525050565b600060408301600083015184820360008601526128f682826124fa565b915050602083015161290b60208601826125c5565b508091505092915050565b600060408201905061292b60008301856128ca565b818103602083015261293d81846128d9565b90509392505050565b60008060006060848603121561295f5761295e6122ff565b5b600061296d86828701612352565b935050602084013567ffffffffffffffff81111561298e5761298d612304565b5b61299a86828701612811565b92505060406129ab868287016123ed565b9150509250925092565b600080604083850312156129cc576129cb6122ff565b5b600083013567ffffffffffffffff8111156129ea576129e9612304565b5b6129f685828601612811565b9250506020612a07858286016123ed565b9150509250929050565b60008060408385031215612a2857612a276122ff565b5b6000612a3685828601612352565b925050602083013567ffffffffffffffff811115612a5757612a56612304565b5b612a6385828601612811565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600067ffffffffffffffff82169050919050565b612ab681612a99565b82525050565b60c082016000820151612ad260008501826125e1565b506020820151612ae560208501826125e1565b506040820151612af860408501826125c5565b506060820151612b0b60608501826125c5565b506080820151612b1e6080850182612aad565b5060a0820151612b3160a08501826125e1565b50505050565b6000612b438383612abc565b60c08301905092915050565b6000602082019050919050565b6000612b6782612a6d565b612b718185612a78565b9350612b7c83612a89565b8060005b83811015612bad578151612b948882612b37565b9750612b9f83612b4f565b925050600181019050612b80565b5085935050505092915050565b60006060830160008301518482036000860152612bd782826124fa565b91505060208301518482036020860152612bf182826124fa565b91505060408301518482036040860152612c0b8282612b5c565b9150508091505092915050565b60006020820190508181036000830152612c328184612bba565b905092915050565b60008060008060808587031215612c5457612c536122ff565b5b6000612c6287828801612352565b945050602085013567ffffffffffffffff811115612c8357612c82612304565b5b612c8f87828801612811565b9350506040612ca0878288016123ed565b925050606085013567ffffffffffffffff811115612cc157612cc0612304565b5b612ccd87828801612811565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b608082016000820151612d1b60008501826125e1565b506020820151612d2e60208501826125e1565b506040820151612d4160408501826125c5565b506060820151612d5460608501826125c5565b50505050565b6000612d668383612d05565b60808301905092915050565b6000602082019050919050565b6000612d8a82612cd9565b612d948185612ce4565b9350612d9f83612cf5565b8060005b83811015612dd0578151612db78882612d5a565b9750612dc283612d72565b925050600181019050612da3565b5085935050505092915050565b60006080830160008301518482036000860152612dfa82826124fa565b91505060208301518482036020860152612e1482826124fa565b91505060408301518482036040860152612e2e82826124fa565b91505060608301518482036060860152612e488282612d7f565b9150508091505092915050565b60006020820190508181036000830152612e6f8184612ddd565b905092915050565b60008060008060808587031215612e9157612e906122ff565b5b6000612e9f87828801612352565b945050602085013567ffffffffffffffff811115612ec057612ebf612304565b5b612ecc87828801612811565b9350506040612edd878288016123ed565b9250506060612eee878288016123ed565b91505092959194509250565b600060208284031215612f1057612f0f6122ff565b5b600082013567ffffffffffffffff811115612f2e57612f2d612304565b5b612f3a84828501612811565b91505092915050565b6000602082019050612f5860008301846128ca565b92915050565b600080fd5b600060a08284031215612f7957612f78612f5e565b5b81905092915050565b600060608284031215612f9857612f97612f5e565b5b81905092915050565b6000806000806000806101008789031215612fbf57612fbe6122ff565b5b600087013567ffffffffffffffff811115612fdd57612fdc612304565b5b612fe989828a01612f63565b9650506020612ffa89828a01612f82565b955050608061300b89828a016123ed565b94505060a061301c89828a01612352565b93505060c087013567ffffffffffffffff81111561303d5761303c612304565b5b61304989828a01612811565b92505060e061305a89828a016123ed565b9150509295509295509295565b61307081612533565b82525050565b600060208201905061308b6000830184613067565b92915050565b600080600080608085870312156130ab576130aa6122ff565b5b60006130b987828801612352565b945050602085013567ffffffffffffffff8111156130da576130d9612304565b5b6130e687828801612811565b935050604085013567ffffffffffffffff81111561310757613106612304565b5b61311387828801612811565b9250506060613124878288016123ed565b91505092959194509250565b6000819050919050565b61314381613130565b811461314e57600080fd5b50565b6000813590506131608161313a565b92915050565b600080600080608085870312156131805761317f6122ff565b5b600085013567ffffffffffffffff81111561319e5761319d612304565b5b6131aa87828801612f63565b94505060206131bb87828801612352565b93505060406131cc87828801613151565b92505060606131dd87828801613151565b91505092959194509250565b600060a082840312156131ff576131fe612f5e565b5b81905092915050565b6000806040838503121561321f5761321e6122ff565b5b600083013567ffffffffffffffff81111561323d5761323c612304565b5b61324985828601612811565b925050602083013567ffffffffffffffff81111561326a57613269612304565b5b613276858286016131e9565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006101608301600083015184820360008601526132ca82826124fa565b915050602083015184820360208601526132e482826124fa565b91505060408301516132f9604086018261253f565b50606083015161330c60608601826125b6565b50608083015161331f60808601826125c5565b5060a083015161333260a08601826125c5565b5060c083015184820360c086015261334a82826124fa565b91505060e083015161335f60e08601826125e1565b506101008301516133746101008601826125e1565b506101208301516133896101208601826125c5565b5061014083015161339e6101408601826125c5565b508091505092915050565b60006133b583836132ac565b905092915050565b6000602082019050919050565b60006133d582613280565b6133df818561328b565b9350836020820285016133f18561329c565b8060005b8581101561342d578484038952815161340e85826133a9565b9450613419836133bd565b925060208a019950506001810190506133f5565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b60006134668261343f565b613470818561344a565b93506134808185602086016124bf565b613489816124e9565b840191505092915050565b600060408301600083015184820360008601526134b1828261345b565b91505060208301516134c66020860182612aad565b508091505092915050565b600060408201905081810360008301526134eb81856133ca565b905081810360208301526134ff8184613494565b90509392505050565b60008060008060808587031215613522576135216122ff565b5b600061353087828801612352565b9450506020613541878288016123ed565b9350506040613552878288016123ed565b925050606085013567ffffffffffffffff81111561357357613572612304565b5b61357f87828801612811565b91505092959194509250565b6000806000604084860312156135a4576135a36122ff565b5b60006135b286828701612352565b935050602084013567ffffffffffffffff8111156135d3576135d2612304565b5b6135df86828701612376565b92509250509250925092565b600080fd5b600080fd5b600067ffffffffffffffff8211156136105761360f612714565b5b613619826124e9565b9050602081019050919050565b6000613639613634846135f5565b612774565b9050828152602081018484840111156136555761365461270f565b5b6136608482856127c0565b509392505050565b600082601f83011261367d5761367c612367565b5b813561368d848260208601613626565b91505092915050565b61369f81612a99565b81146136aa57600080fd5b50565b6000813590506136bc81613696565b92915050565b6136cb81612533565b81146136d657600080fd5b50565b6000813590506136e8816136c2565b92915050565b600060a08284031215613704576137036135eb565b5b61370e60a0612774565b9050600082013567ffffffffffffffff81111561372e5761372d6135f0565b5b61373a84828501613668565b600083015250602061374e848285016136ad565b6020830152506040613762848285016136ad565b6040830152506060613776848285016136d9565b606083015250608061378a848285016136d9565b60808301525092915050565b600080600080608085870312156137b0576137af6122ff565b5b60006137be87828801612352565b945050602085013567ffffffffffffffff8111156137df576137de612304565b5b6137eb87828801612811565b935050604085013567ffffffffffffffff81111561380c5761380b612304565b5b61381887828801612811565b925050606085013567ffffffffffffffff81111561383957613838612304565b5b613845878288016136ee565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000608083016000830151848203600086015261389a82826124fa565b915050602083015184820360208601526138b482826124fa565b915050604083015184820360408601526138ce82826124fa565b915050606083015184820360608601526138e88282612d7f565b9150508091505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60a0820160008201516139376000850182612d05565b50602082015161394a60808501826125c5565b50505050565b600061395c8383613921565b60a08301905092915050565b6000602082019050919050565b6000613980826138f5565b61398a8185613900565b935061399583613911565b8060005b838110156139c65781516139ad8882613950565b97506139b883613968565b925050600181019050613999565b5085935050505092915050565b600060408301600083015184820360008601526139f0828261387d565b91505060208301518482036020860152613a0a8282613975565b9150508091505092915050565b6000613a2383836139d3565b905092915050565b6000602082019050919050565b6000613a4382613851565b613a4d818561385c565b935083602082028501613a5f8561386d565b8060005b85811015613a9b5784840389528151613a7c8582613a17565b9450613a8783613a2b565b925060208a01995050600181019050613a63565b50829750879550505050505092915050565b60006040820190508181036000830152613ac78185613a38565b90508181036020830152613adb8184613494565b90509392505050565b613aed81612329565b82525050565b600082825260208201905092915050565b6000819050919050565b6000613b1a83856124ae565b9350613b278385846127c0565b613b30836124e9565b840190509392505050565b6000613b48848484613b0e565b90509392505050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613b7d57613b7c613b5b565b5b83810192508235915060208301925067ffffffffffffffff821115613ba557613ba4613b51565b5b600182023603831315613bbb57613bba613b56565b5b509250929050565b6000602082019050919050565b6000613bdc8385613af3565b935083602084028501613bee84613b04565b8060005b87811015613c34578484038952613c098284613b60565b613c14868284613b3b565b9550613c1f84613bc3565b935060208b019a505050600181019050613bf2565b50829750879450505050509392505050565b6000606082019050613c5b6000830187613ae4565b613c6860208301866128ca565b8181036040830152613c7b818486613bd0565b905095945050505050565b600081519050613c95816136c2565b92915050565b600060208284031215613cb157613cb06122ff565b5b6000613cbf84828501613c86565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f20617070726f7665207374616b696e67206d6574686f6460008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d35602183613cc8565b9150613d4082613cd9565b604082019050919050565b60006020820190508181036000830152613d6481613d28565b9050919050565b6000602082019050613d806000830184613ae4565b92915050565b6000613d99613d948461278f565b612774565b905082815260208101848484011115613db557613db461270f565b5b613dc08482856124bf565b509392505050565b600082601f830112613ddd57613ddc612367565b5b8151613ded848260208601613d86565b91505092915050565b60048110613e0357600080fd5b50565b600081519050613e1581613df6565b92915050565b600081519050613e2a816123d6565b92915050565b613e39816125d4565b8114613e4457600080fd5b50565b600081519050613e5681613e30565b92915050565b60006101608284031215613e7357613e726135eb565b5b613e7e610160612774565b9050600082015167ffffffffffffffff811115613e9e57613e9d6135f0565b5b613eaa84828501613dc8565b600083015250602082015167ffffffffffffffff811115613ece57613ecd6135f0565b5b613eda84828501613dc8565b6020830152506040613eee84828501613c86565b6040830152506060613f0284828501613e06565b6060830152506080613f1684828501613e1b565b60808301525060a0613f2a84828501613e1b565b60a08301525060c082015167ffffffffffffffff811115613f4e57613f4d6135f0565b5b613f5a84828501613dc8565b60c08301525060e0613f6e84828501613e47565b60e083015250610100613f8384828501613e47565b61010083015250610120613f9984828501613e1b565b61012083015250610140613faf84828501613e1b565b6101408301525092915050565b600060208284031215613fd257613fd16122ff565b5b600082015167ffffffffffffffff811115613ff057613fef612304565b5b613ffc84828501613e5c565b91505092915050565b6000614010826124a3565b61401a8185613cc8565b935061402a8185602086016124bf565b614033816124e9565b840191505092915050565b60006040820190506140536000830185613ae4565b81810360208301526140658184614005565b90509392505050565b600081905092915050565b6000614084826124a3565b61408e818561406e565b935061409e8185602086016124bf565b80840191505092915050565b60006140b68284614079565b915081905092915050565b7f64656c656761746563616c6c0000000000000000000000000000000000000000600082015250565b60006140f7600c8361406e565b9150614102826140c1565b600c82019050919050565b6000614118826140ea565b9150819050919050565b600081905092915050565b60006141388261343f565b6141428185614122565b93506141528185602086016124bf565b80840191505092915050565b600061416a828461412d565b915081905092915050565b7f6661696c65642064656c656761746563616c6c20746f20707265636f6d70696c60008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b60006141d1602183613cc8565b91506141dc82614175565b604082019050919050565b60006020820190508181036000830152614200816141c4565b9050919050565b60006040828403121561421d5761421c6135eb565b5b6142276040612774565b9050600082015167ffffffffffffffff811115614247576142466135f0565b5b61425384828501613dc8565b600083015250602061426784828501613e1b565b60208301525092915050565b6000806040838503121561428a576142896122ff565b5b600061429885828601613e1b565b925050602083015167ffffffffffffffff8111156142b9576142b8612304565b5b6142c585828601614207565b9150509250929050565b7f73746174696363616c6c00000000000000000000000000000000000000000000600082015250565b6000614305600a8361406e565b9150614310826142cf565b600a82019050919050565b6000614326826142f8565b9150819050919050565b7f6661696c65642073746174696363616c6c20746f20707265636f6d70696c6500600082015250565b6000614366601f83613cc8565b915061437182614330565b602082019050919050565b6000602082019050818103600083015261439581614359565b9050919050565b7f63616c6c00000000000000000000000000000000000000000000000000000000600082015250565b60006143d260048361406e565b91506143dd8261439c565b600482019050919050565b60006143f3826143c5565b9150819050919050565b7f6661696c65642063616c6c20746f20707265636f6d70696c6500000000000000600082015250565b6000614433601983613cc8565b915061443e826143fd565b602082019050919050565b6000602082019050818103600083015261446281614426565b9050919050565b7f63616c6c636f6465000000000000000000000000000000000000000000000000600082015250565b600061449f60088361406e565b91506144aa82614469565b600882019050919050565b60006144c082614492565b9150819050919050565b7f696e76616c69642063616c6c7479706500000000000000000000000000000000600082015250565b6000614500601083613cc8565b915061450b826144ca565b602082019050919050565b6000602082019050818103600083015261452f816144f3565b9050919050565b600081549050919050565b60008190508160005260206000209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061459d57607f821691505b6020821081036145b0576145af614556565b5b50919050565b60008190508160005260206000209050919050565b600081546145d881614585565b6145e281866124ae565b945060018216600081146145fd576001811461461357614646565b60ff198316865281151560200286019350614646565b61461c856145b6565b60005b8381101561463e5781548189015260018201915060208101905061461f565b808801955050505b50505092915050565b600061465b83836145cb565b905092915050565b6000600182019050919050565b600061467b82614536565b6146858185613af3565b93508360208202850161469785614541565b8060005b858110156146d2578484038952816146b3858261464f565b94506146be83614663565b925060208a0199505060018101905061469b565b50829750879550505050505092915050565b60006060820190506146f96000830186613ae4565b61470660208301856128ca565b81810360408301526147188184614670565b9050949350505050565b7f64656c65676174696f6e20617070726f76616c206661696c6564000000000000600082015250565b6000614758601a83613cc8565b915061476382614722565b602082019050919050565b600060208201905081810360008301526147878161474b565b9050919050565b60006040820190506147a36000830185613ae4565b6147b060208301846128ca565b9392505050565b7f7472616e73666572206661696c65640000000000000000000000000000000000600082015250565b60006147ed600f83613cc8565b91506147f8826147b7565b602082019050919050565b6000602082019050818103600083015261481c816147e0565b9050919050565b60006060820190506148386000830186613ae4565b818103602083015261484a8185614005565b905061485960408301846128ca565b949350505050565b7f5374616b696e6720417070726f7665206661696c656400000000000000000000600082015250565b6000614897601683613cc8565b91506148a282614861565b602082019050919050565b600060208201905081810360008301526148c68161488a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614907826123cc565b9150614912836123cc565b925082820190508082111561492a576149296148cd565b5b92915050565b600067ffffffffffffffff82111561494b5761494a612714565b5b602082029050602081019050919050565b60008151905061496b81613696565b92915050565b600060c08284031215614987576149866135eb565b5b61499160c0612774565b905060006149a184828501613e47565b60008301525060206149b584828501613e47565b60208301525060406149c984828501613e1b565b60408301525060606149dd84828501613e1b565b60608301525060806149f18482850161495c565b60808301525060a0614a0584828501613e47565b60a08301525092915050565b6000614a24614a1f84614930565b612774565b90508083825260208201905060c08402830185811115614a4757614a46612371565b5b835b81811015614a705780614a5c8882614971565b84526020840193505060c081019050614a49565b5050509392505050565b600082601f830112614a8f57614a8e612367565b5b8151614a9f848260208601614a11565b91505092915050565b600060608284031215614abe57614abd6135eb565b5b614ac86060612774565b9050600082015167ffffffffffffffff811115614ae857614ae76135f0565b5b614af484828501613dc8565b600083015250602082015167ffffffffffffffff811115614b1857614b176135f0565b5b614b2484828501613dc8565b602083015250604082015167ffffffffffffffff811115614b4857614b476135f0565b5b614b5484828501614a7a565b60408301525092915050565b600060208284031215614b7657614b756122ff565b5b600082015167ffffffffffffffff811115614b9457614b93612304565b5b614ba084828501614aa8565b91505092915050565b6000606082019050614bbe6000830186613ae4565b8181036020830152614bd08185614005565b90508181036040830152614be48184614005565b9050949350505050565b600067ffffffffffffffff821115614c0957614c08612714565b5b602082029050602081019050919050565b600060808284031215614c3057614c2f6135eb565b5b614c3a6080612774565b90506000614c4a84828501613e47565b6000830152506020614c5e84828501613e47565b6020830152506040614c7284828501613e1b565b6040830152506060614c8684828501613e1b565b60608301525092915050565b6000614ca5614ca084614bee565b612774565b90508083825260208201905060808402830185811115614cc857614cc7612371565b5b835b81811015614cf15780614cdd8882614c1a565b845260208401935050608081019050614cca565b5050509392505050565b600082601f830112614d1057614d0f612367565b5b8151614d20848260208601614c92565b91505092915050565b600060808284031215614d3f57614d3e6135eb565b5b614d496080612774565b9050600082015167ffffffffffffffff811115614d6957614d686135f0565b5b614d7584828501613dc8565b600083015250602082015167ffffffffffffffff811115614d9957614d986135f0565b5b614da584828501613dc8565b602083015250604082015167ffffffffffffffff811115614dc957614dc86135f0565b5b614dd584828501613dc8565b604083015250606082015167ffffffffffffffff811115614df957614df86135f0565b5b614e0584828501614cfb565b60608301525092915050565b600060208284031215614e2757614e266122ff565b5b600082015167ffffffffffffffff811115614e4557614e44612304565b5b614e5184828501614d29565b91505092915050565b6000608082019050614e6f6000830187613ae4565b8181036020830152614e818186614005565b9050614e9060408301856128ca565b614e9d60608301846128ca565b95945050505050565b7f44656c656761746520417070726f7665206661696c6564000000000000000000600082015250565b6000614edc601783613cc8565b9150614ee782614ea6565b602082019050919050565b60006020820190508181036000830152614f0b81614ecf565b9050919050565b600060a08301614f256000840184613b60565b8583036000870152614f38838284613b0e565b92505050614f496020840184613b60565b8583036020870152614f5c838284613b0e565b92505050614f6d6040840184613b60565b8583036040870152614f80838284613b0e565b92505050614f916060840184613b60565b8583036060870152614fa4838284613b0e565b92505050614fb56080840184613b60565b8583036080870152614fc8838284613b0e565b925050508091505092915050565b6000614fe560208401846123ed565b905092915050565b60608201614ffe6000830183614fd6565b61500b60008501826125c5565b506150196020830183614fd6565b61502660208501826125c5565b506150346040830183614fd6565b61504160408501826125c5565b50505050565b60006101008201905081810360008301526150628189614f12565b90506150716020830188614fed565b61507e60808301876128ca565b61508b60a0830186613ae4565b81810360c083015261509d8185614005565b90506150ac60e08301846128ca565b979650505050505050565b6000602082840312156150cd576150cc6122ff565b5b60006150db84828501613e47565b91505092915050565b60006150ef826123cc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615121576151206148cd565b5b600182019050919050565b6000615137826123cc565b91506000820361514a576151496148cd565b5b600182039050919050565b600060808201905061516a6000830187613ae4565b818103602083015261517c8186614005565b905081810360408301526151908185614005565b905061519f60608301846128ca565b95945050505050565b6151b181613130565b82525050565b600060808201905081810360008301526151d18187614f12565b90506151e06020830186613ae4565b6151ed60408301856151a8565b6151fa60608301846151a8565b95945050505050565b600080833560016020038436030381126152205761521f613b5b565b5b83810192508235915060208301925067ffffffffffffffff82111561524857615247613b51565b5b60018202360383131561525e5761525d613b56565b5b509250929050565b6000615272838561344a565b935061527f8385846127c0565b615288836124e9565b840190509392505050565b60006152a260208401846136ad565b905092915050565b60006152b960208401846136d9565b905092915050565b600060a083016152d46000840184615203565b85830360008701526152e7838284615266565b925050506152f86020840184615293565b6153056020860182612aad565b506153136040840184615293565b6153206040860182612aad565b5061532e60608401846152aa565b61533b606086018261253f565b5061534960808401846152aa565b615356608086018261253f565b508091505092915050565b6000604082019050818103600083015261537b8185614005565b9050818103602083015261538f81846152c1565b90509392505050565b600067ffffffffffffffff8211156153b3576153b2612714565b5b602082029050602081019050919050565b60006153d76153d284615398565b612774565b905080838252602082019050602084028301858111156153fa576153f9612371565b5b835b8181101561544157805167ffffffffffffffff81111561541f5761541e612367565b5b80860161542c8982613e5c565b855260208501945050506020810190506153fc565b5050509392505050565b600082601f8301126154605761545f612367565b5b81516154708482602086016153c4565b91505092915050565b600061548c615487846135f5565b612774565b9050828152602081018484840111156154a8576154a761270f565b5b6154b38482856124bf565b509392505050565b600082601f8301126154d0576154cf612367565b5b81516154e0848260208601615479565b91505092915050565b6000604082840312156154ff576154fe6135eb565b5b6155096040612774565b9050600082015167ffffffffffffffff811115615529576155286135f0565b5b615535848285016154bb565b60008301525060206155498482850161495c565b60208301525092915050565b6000806040838503121561556c5761556b6122ff565b5b600083015167ffffffffffffffff81111561558a57615589612304565b5b6155968582860161544b565b925050602083015167ffffffffffffffff8111156155b7576155b6612304565b5b6155c3858286016154e9565b9150509250929050565b60006060820190506155e26000830186613ae4565b6155ef6020830185613ae4565b81810360408301526156018184614005565b9050949350505050565b600060208284031215615621576156206122ff565b5b600061562f84828501613e1b565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b6000819050602082019050919050565b600061568e83836124fa565b905092915050565b6000602082019050919050565b60006156ae82615667565b6156b88185613af3565b9350836020820285016156ca85615672565b8060005b8581101561570657848403895281516156e78582615682565b94506156f283615696565b925060208a019950506001810190506156ce565b50829750879550505050505092915050565b600060608201905061572d6000830186613ae4565b61573a60208301856128ca565b818103604083015261574c81846156a3565b9050949350505050565b7f6661696c656420746f20617070726f766520756e64656c65676174696f6e206d60008201527f6574686f64000000000000000000000000000000000000000000000000000000602082015250565b60006157b2602583613cc8565b91506157bd82615756565b604082019050919050565b600060208201905081810360008301526157e1816157a5565b9050919050565b60006040820190506157fd6000830186613ae4565b8181036020830152615810818486613bd0565b9050949350505050565b7f4661696c656420746f207265766f6b6520617070726f76616c20666f7220737460008201527f616b696e67206d6574686f647300000000000000000000000000000000000000602082015250565b6000615876602d83613cc8565b91506158818261581a565b604082019050919050565b600060208201905081810360008301526158a581615869565b9050919050565b600060a08301600083015184820360008601526158c9828261345b565b91505060208301516158de6020860182612aad565b5060408301516158f16040860182612aad565b506060830151615904606086018261253f565b506080830151615917608086018261253f565b508091505092915050565b60006080820190506159376000830187613ae4565b81810360208301526159498186614005565b9050818103604083015261595d8185614005565b9050818103606083015261597181846158ac565b905095945050505050565b600067ffffffffffffffff82111561599757615996612714565b5b602082029050602081019050919050565b6000608082840312156159be576159bd6135eb565b5b6159c86080612774565b9050600082015167ffffffffffffffff8111156159e8576159e76135f0565b5b6159f484828501613dc8565b600083015250602082015167ffffffffffffffff811115615a1857615a176135f0565b5b615a2484828501613dc8565b602083015250604082015167ffffffffffffffff811115615a4857615a476135f0565b5b615a5484828501613dc8565b604083015250606082015167ffffffffffffffff811115615a7857615a776135f0565b5b615a8484828501614cfb565b60608301525092915050565b600067ffffffffffffffff821115615aab57615aaa612714565b5b602082029050602081019050919050565b600060a08284031215615ad257615ad16135eb565b5b615adc6040612774565b90506000615aec84828501614c1a565b6000830152506080615b0084828501613e1b565b60208301525092915050565b6000615b1f615b1a84615a90565b612774565b90508083825260208201905060a08402830185811115615b4257615b41612371565b5b835b81811015615b6b5780615b578882615abc565b84526020840193505060a081019050615b44565b5050509392505050565b600082601f830112615b8a57615b89612367565b5b8151615b9a848260208601615b0c565b91505092915050565b600060408284031215615bb957615bb86135eb565b5b615bc36040612774565b9050600082015167ffffffffffffffff811115615be357615be26135f0565b5b615bef848285016159a8565b600083015250602082015167ffffffffffffffff811115615c1357615c126135f0565b5b615c1f84828501615b75565b60208301525092915050565b6000615c3e615c398461597c565b612774565b90508083825260208201905060208402830185811115615c6157615c60612371565b5b835b81811015615ca857805167ffffffffffffffff811115615c8657615c85612367565b5b808601615c938982615ba3565b85526020850194505050602081019050615c63565b5050509392505050565b600082601f830112615cc757615cc6612367565b5b8151615cd7848260208601615c2b565b91505092915050565b60008060408385031215615cf757615cf66122ff565b5b600083015167ffffffffffffffff811115615d1557615d14612304565b5b615d2185828601615cb2565b925050602083015167ffffffffffffffff811115615d4257615d41612304565b5b615d4e858286016154e9565b915050925092905056fe2f636f736d6f732e7374616b696e672e763162657461312e4d7367556e64656c6567617465a2646970667358221220610cb91a8933e1804929f56c9cd7a1adc794d98816aa48df9e694b7cd16e831b64736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/staking/testdata/StakingCaller.sol b/precompiles/staking/testdata/StakingCaller.sol
new file mode 100644
index 00000000..9d87ee9f
--- /dev/null
+++ b/precompiles/staking/testdata/StakingCaller.sol
@@ -0,0 +1,570 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../StakingI.sol" as staking;
+
+/// @title StakingCaller
+/// @author Evmos Core Team
+/// @dev This contract is used to test external contract calls to the staking precompile.
+contract StakingCaller {
+ /// counter is used to test the state persistence bug, when EVM and Cosmos state were both
+ /// changed in the same function.
+ uint256 public counter;
+ string[] private delegateMethod = [staking.MSG_DELEGATE];
+
+ /// @dev This function calls the staking precompile's approve method.
+ /// @param _addr The address to approve.
+ /// @param _methods The methods to approve.
+ function testApprove(
+ address _addr,
+ string[] calldata _methods,
+ uint256 _amount
+ ) public {
+ bool success = staking.STAKING_CONTRACT.approve(
+ _addr,
+ _amount,
+ _methods
+ );
+ require(success, "Failed to approve staking methods");
+ }
+
+ /// @dev This function calls the staking precompile's revoke method.
+ /// @param _grantee The address that was approved to spend the funds.
+ /// @param _methods The methods to revoke.
+ function testRevoke(address _grantee, string[] calldata _methods) public {
+ bool success = staking.STAKING_CONTRACT.revoke(_grantee, _methods);
+ require(success, "Failed to revoke approval for staking methods");
+ }
+
+ /// @dev This function calls the staking precompile's create validator method
+ /// using the msg.sender as the validator's operator address.
+ /// @param _descr The initial description
+ /// @param _commRates The initial commissionRates
+ /// @param _minSelfDel The validator's self declared minimum self delegation
+ /// @param _valAddr The validator's operator address
+ /// @param _pubkey The consensus public key of the validator
+ /// @param _value The amount of the coin to be self delegated to the validator
+ /// @return success Whether or not the create validator was successful
+ function testCreateValidator(
+ staking.Description calldata _descr,
+ staking.CommissionRates calldata _commRates,
+ uint256 _minSelfDel,
+ address _valAddr,
+ string memory _pubkey,
+ uint256 _value
+ ) public returns (bool) {
+ return
+ staking.STAKING_CONTRACT.createValidator(
+ _descr,
+ _commRates,
+ _minSelfDel,
+ _valAddr,
+ _pubkey,
+ _value
+ );
+ }
+
+ /// @dev This function calls the staking precompile's edit validator
+ /// method using the msg.sender as the validator's operator address.
+ /// @param _descr Description parameter to be updated. Use the string "[do-not-modify]"
+ /// as the value of fields that should not be updated.
+ /// @param _valAddr The validator's operator address
+ /// @param _commRate CommissionRate parameter to be updated.
+ /// Use commissionRate = -1 to keep the current value and not update it.
+ /// @param _minSelfDel MinSelfDelegation parameter to be updated.
+ /// Use minSelfDelegation = -1 to keep the current value and not update it.
+ /// @return success Whether or not edit validator was successful.
+ function testEditValidator(
+ staking.Description calldata _descr,
+ address _valAddr,
+ int256 _commRate,
+ int256 _minSelfDel
+ ) public returns (bool) {
+ return
+ staking.STAKING_CONTRACT.editValidator(
+ _descr,
+ _valAddr,
+ _commRate,
+ _minSelfDel
+ );
+ }
+
+ /// @dev This function calls the staking precompile's delegate method.
+ /// @param _addr The address to approve.
+ /// @param _validatorAddr The validator address to delegate to.
+ /// @param _amount The amount to delegate.
+ function testDelegate(
+ address _addr,
+ string memory _validatorAddr,
+ uint256 _amount
+ ) public {
+ counter++;
+ staking.STAKING_CONTRACT.delegate(_addr, _validatorAddr, _amount);
+ counter--;
+ }
+
+ /// @dev This function calls the staking precompile's undelegate method.
+ /// @param _addr The address to approve.
+ /// @param _validatorAddr The validator address to delegate to.
+ /// @param _amount The amount to delegate.
+ function testUndelegate(
+ address _addr,
+ string memory _validatorAddr,
+ uint256 _amount
+ ) public {
+ staking.STAKING_CONTRACT.undelegate(_addr, _validatorAddr, _amount);
+ }
+
+ /// @dev This function calls the staking precompile's redelegate method.
+ /// @param _addr The address to approve.
+ /// @param _validatorSrcAddr The validator address to delegate from.
+ /// @param _validatorDstAddr The validator address to delegate to.
+ /// @param _amount The amount to delegate.
+ function testRedelegate(
+ address _addr,
+ string memory _validatorSrcAddr,
+ string memory _validatorDstAddr,
+ uint256 _amount
+ ) public {
+ staking.STAKING_CONTRACT.redelegate(
+ _addr,
+ _validatorSrcAddr,
+ _validatorDstAddr,
+ _amount
+ );
+ }
+
+ /// @dev This function calls the staking precompile's cancel unbonding delegation method.
+ /// @param _addr The address to approve.
+ /// @param _validatorAddr The validator address to delegate from.
+ /// @param _amount The amount to delegate.
+ /// @param _creationHeight The creation height of the unbonding delegation.
+ function testCancelUnbonding(
+ address _addr,
+ string memory _validatorAddr,
+ uint256 _amount,
+ uint256 _creationHeight
+ ) public {
+ staking.STAKING_CONTRACT.cancelUnbondingDelegation(
+ _addr,
+ _validatorAddr,
+ _amount,
+ _creationHeight
+ );
+ }
+
+ /// @dev This function calls the staking precompile's allowance query method.
+ /// @param _grantee The address that received the grant.
+ /// @param method The method to query.
+ /// @return allowance The allowance.
+ function getAllowance(
+ address _grantee,
+ string memory method
+ ) public view returns (uint256 allowance) {
+ return staking.STAKING_CONTRACT.allowance(_grantee, msg.sender, method);
+ }
+
+ /// @dev This function calls the staking precompile's validator query method.
+ /// @param _validatorAddr The validator address to query.
+ /// @return validator The validator.
+ function getValidator(
+ address _validatorAddr
+ ) public view returns (staking.Validator memory validator) {
+ return staking.STAKING_CONTRACT.validator(_validatorAddr);
+ }
+
+ /// @dev This function calls the staking precompile's validators query method.
+ /// @param _status The status of the validators to query.
+ /// @param _pageRequest The page request to query.
+ /// @return validators The validators.
+ /// @return pageResponse The page response.
+ function getValidators(
+ string memory _status,
+ staking.PageRequest calldata _pageRequest
+ )
+ public
+ view
+ returns (
+ staking.Validator[] memory validators,
+ staking.PageResponse memory pageResponse
+ )
+ {
+ return staking.STAKING_CONTRACT.validators(_status, _pageRequest);
+ }
+
+ /// @dev This function calls the staking precompile's delegation query method.
+ /// @param _addr The address to approve.
+ /// @param _validatorAddr The validator address to delegate from.
+ /// @return shares The shares of the delegation.
+ /// @return balance The balance of the delegation.
+ function getDelegation(
+ address _addr,
+ string memory _validatorAddr
+ ) public view returns (uint256 shares, staking.Coin memory balance) {
+ return staking.STAKING_CONTRACT.delegation(_addr, _validatorAddr);
+ }
+
+ /// @dev This function calls the staking precompile's redelegations query method.
+ /// @param _addr The address to approve.
+ /// @param _validatorSrcAddr The validator address to delegate from.
+ /// @param _validatorDstAddr The validator address to delegate to.
+ /// @return redelegation The redelegation output.
+ function getRedelegation(
+ address _addr,
+ string memory _validatorSrcAddr,
+ string memory _validatorDstAddr
+ ) public view returns (staking.RedelegationOutput memory redelegation) {
+ return
+ staking.STAKING_CONTRACT.redelegation(
+ _addr,
+ _validatorSrcAddr,
+ _validatorDstAddr
+ );
+ }
+
+ /// @dev This function calls the staking precompile's redelegations query method.
+ /// @param _delegatorAddr The delegator address.
+ /// @param _validatorSrcAddr The validator address to delegate from.
+ /// @param _validatorDstAddr The validator address to delegate to.
+ /// @param _pageRequest The page request to query.
+ /// @return response The redelegation response.
+ function getRedelegations(
+ address _delegatorAddr,
+ string memory _validatorSrcAddr,
+ string memory _validatorDstAddr,
+ staking.PageRequest memory _pageRequest
+ )
+ public
+ view
+ returns (
+ staking.RedelegationResponse[] memory response,
+ staking.PageResponse memory pageResponse
+ )
+ {
+ return
+ staking.STAKING_CONTRACT.redelegations(
+ _delegatorAddr,
+ _validatorSrcAddr,
+ _validatorDstAddr,
+ _pageRequest
+ );
+ }
+
+ /// @dev This function calls the staking precompile's unbonding delegation query method.
+ /// @param _addr The address to approve.
+ /// @param _validatorAddr The validator address to delegate from.
+ /// @return unbondingDelegation The unbonding delegation output.
+ function getUnbondingDelegation(
+ address _addr,
+ string memory _validatorAddr
+ )
+ public
+ view
+ returns (staking.UnbondingDelegationOutput memory unbondingDelegation)
+ {
+ return
+ staking.STAKING_CONTRACT.unbondingDelegation(_addr, _validatorAddr);
+ }
+
+ /// @dev This function calls the staking precompile's approve method to grant approval for an undelegation.
+ /// Next, the undelegate method is called to execute an unbonding.
+ /// @param _addr The address to approve.
+ /// @param _approveAmount The amount to approve.
+ /// @param _undelegateAmount The amount to undelegate.
+ /// @param _validatorAddr The validator address to delegate from.
+ function testApproveAndThenUndelegate(
+ address _addr,
+ uint256 _approveAmount,
+ uint256 _undelegateAmount,
+ string memory _validatorAddr
+ ) public {
+ string[] memory approvedMethods = new string[](1);
+ approvedMethods[0] = staking.MSG_UNDELEGATE;
+ bool success = staking.STAKING_CONTRACT.approve(
+ _addr,
+ _approveAmount,
+ approvedMethods
+ );
+ require(success, "failed to approve undelegation method");
+ staking.STAKING_CONTRACT.undelegate(
+ tx.origin,
+ _validatorAddr,
+ _undelegateAmount
+ );
+ }
+
+ /// @dev This function is used to test the behaviour when executing transactions using special
+ /// function calling opcodes,
+ /// like call, delegatecall, staticcall, and callcode.
+ /// @param _addr The address to approve.
+ /// @param _validatorAddr The validator address to delegate from.
+ /// @param _amount The amount to undelegate.
+ /// @param _calltype The opcode to use.
+ function testCallUndelegate(
+ address _addr,
+ string memory _validatorAddr,
+ uint256 _amount,
+ string memory _calltype
+ ) public {
+ address calledContractAddress = staking.STAKING_PRECOMPILE_ADDRESS;
+ bytes memory payload = abi.encodeWithSignature(
+ "undelegate(address,string,uint256)",
+ _addr,
+ _validatorAddr,
+ _amount
+ );
+ bytes32 calltypeHash = keccak256(abi.encodePacked(_calltype));
+
+ if (calltypeHash == keccak256(abi.encodePacked("delegatecall"))) {
+ (bool success, ) = calledContractAddress.delegatecall(payload);
+ require(success, "failed delegatecall to precompile");
+ } else if (calltypeHash == keccak256(abi.encodePacked("staticcall"))) {
+ (bool success, ) = calledContractAddress.staticcall(payload);
+ require(success, "failed staticcall to precompile");
+ } else if (calltypeHash == keccak256(abi.encodePacked("call"))) {
+ (bool success, ) = calledContractAddress.call(payload);
+ require(success, "failed call to precompile");
+ } else if (calltypeHash == keccak256(abi.encodePacked("callcode"))) {
+ // NOTE: callcode is deprecated and now only available via inline assembly
+ assembly {
+ // Load the function signature and argument data onto the stack
+ let ptr := add(payload, 0x20)
+ let len := mload(payload)
+
+ // Invoke the contract at calledContractAddress in the context of the current contract
+ // using CALLCODE opcode and the loaded function signature and argument data
+ let success := callcode(
+ gas(),
+ calledContractAddress,
+ 0,
+ ptr,
+ len,
+ 0,
+ 0
+ )
+
+ // Check if the call was successful and revert the transaction if it failed
+ if iszero(success) {
+ revert(0, 0)
+ }
+ }
+ } else {
+ revert("invalid calltype");
+ }
+ }
+
+ /// @dev This function is used to test the behaviour when executing queries using special function calling opcodes,
+ /// like call, delegatecall, staticcall, and callcode.
+ /// @param _addr The address of the delegator.
+ /// @param _validatorAddr The validator address to query for.
+ /// @param _calltype The opcode to use.
+ function testCallDelegation(
+ address _addr,
+ string memory _validatorAddr,
+ string memory _calltype
+ ) public returns (uint256 shares, staking.Coin memory coin) {
+ address calledContractAddress = staking.STAKING_PRECOMPILE_ADDRESS;
+ bytes memory payload = abi.encodeWithSignature(
+ "delegation(address,string)",
+ _addr,
+ _validatorAddr
+ );
+ bytes32 calltypeHash = keccak256(abi.encodePacked(_calltype));
+
+ if (calltypeHash == keccak256(abi.encodePacked("delegatecall"))) {
+ (bool success, bytes memory data) = calledContractAddress
+ .delegatecall(payload);
+ require(success, "failed delegatecall to precompile");
+ (shares, coin) = abi.decode(data, (uint256, staking.Coin));
+ } else if (calltypeHash == keccak256(abi.encodePacked("staticcall"))) {
+ (bool success, bytes memory data) = calledContractAddress
+ .staticcall(payload);
+ require(success, "failed staticcall to precompile");
+ (shares, coin) = abi.decode(data, (uint256, staking.Coin));
+ } else if (calltypeHash == keccak256(abi.encodePacked("call"))) {
+ (bool success, bytes memory data) = calledContractAddress.call(
+ payload
+ );
+ require(success, "failed call to precompile");
+ (shares, coin) = abi.decode(data, (uint256, staking.Coin));
+ } else if (calltypeHash == keccak256(abi.encodePacked("callcode"))) {
+ //Function signature
+ bytes4 sig = bytes4(keccak256(bytes("delegation(address,string)")));
+ // Length of the input data is 164 bytes on 32bytes chunks:
+ // Memory location
+ // 0 - 4 byte signature x
+ // 1 - 0x0000..address x + 0x04
+ // 2 - 0x0000..00 x + 0x24
+ // 3 - 0x40..0000 x + 0x44
+ // 4 - val_addr_chunk1 x + 0x64
+ // 5 - val_addr_chunk2..000 x + 0x84
+ uint256 len = 164;
+ // Coin type includes denom & amount
+ // need to get these separately from the bytes response
+ string memory denom;
+ uint256 amt;
+
+ // NOTE: callcode is deprecated and now only available via inline assembly
+ assembly {
+ let chunk1 := mload(add(_validatorAddr, 32)) // first 32 bytes of validator address string
+ let chunk2 := mload(add(add(_validatorAddr, 32), 32)) // remaining 19 bytes of val address string
+
+ // Load the function signature and argument data onto the stack
+ let x := mload(0x40) // Find empty storage location using "free memory pointer"
+ mstore(x, sig) // Place function signature at beginning of empty storage
+ mstore(add(x, 0x04), _addr) // Place the address (input param) after the function sig
+ mstore(add(x, 0x24), 0x40) // These are needed for
+ mstore(add(x, 0x44), 0x33) // bytes unpacking
+ mstore(add(x, 0x64), chunk1) // Place the validator address in 2 chunks (input param)
+ mstore(add(x, 0x84), chunk2) // because mstore stores 32bytes
+
+ // Invoke the contract at calledContractAddress in the context of the current contract
+ // using CALLCODE opcode and the loaded function signature and argument data
+ let success := callcode(
+ gas(),
+ calledContractAddress, // to addr
+ 0, // no value
+ x, // inputs are stored at location x
+ len, // inputs length
+ x, //store output over input (saves space)
+ 0xC0 // output length for this call
+ )
+
+ // output length for this call is 192 bytes splitted on these 32 bytes chunks:
+ // 1 - 0x00..amt -> @ 0x40
+ // 2 - 0x000..00 -> @ 0x60
+ // 3 - 0x40..000 -> @ 0x80
+ // 4 - 0x00..amt -> @ 0xC0
+ // 5 - 0x00..denom -> @ 0xE0 TODO: cannot get the return value
+
+ shares := mload(x) // Assign shares output value - 32 bytes long
+ amt := mload(add(x, 0x60)) // Assign output value to c - 64 bytes long (string & uint256)
+
+ mstore(0x40, add(x, 0x100)) // Set storage pointer to empty space
+
+ // Check if the call was successful and revert the transaction if it failed
+ if iszero(success) {
+ revert(0, 0)
+ }
+ }
+ // NOTE: this is returning a blank denom because unpacking the denom is not
+ // straightforward and hasn't been solved, which is okay for this generic test case.
+ coin = staking.Coin(denom, amt);
+ } else {
+ revert("invalid calltype");
+ }
+
+ return (shares, coin);
+ }
+
+ /// @dev This function showcased, that there was a bug in the EVM implementation, that occurred when
+ /// Cosmos state is modified in the same transaction as state information inside
+ /// the EVM.
+ /// @param _validatorAddr Address of the validator to delegate to
+ /// @param _amount Amount to delegate
+ function testDelegateIncrementCounter(
+ string memory _validatorAddr,
+ uint256 _amount
+ ) public {
+ bool successStk = staking.STAKING_CONTRACT.approve(
+ address(this),
+ _amount,
+ delegateMethod
+ );
+ require(successStk, "Staking Approve failed");
+ staking.STAKING_CONTRACT.delegate(
+ address(this),
+ _validatorAddr,
+ _amount
+ );
+ counter += 1;
+ }
+
+ /// @dev This function showcases the possibility to deposit into the contract
+ /// and immediately delegate to a validator using the same balance in the same transaction.
+ function approveDepositAndDelegate(
+ string memory _validatorAddr
+ ) public payable {
+ bool successTx = staking.STAKING_CONTRACT.approve(
+ address(this),
+ msg.value,
+ delegateMethod
+ );
+ require(successTx, "Delegate Approve failed");
+ staking.STAKING_CONTRACT.delegate(
+ address(this),
+ _validatorAddr,
+ msg.value
+ );
+ }
+
+ /// @dev This function is suppose to fail because the amount to delegate is
+ /// higher than the amount approved.
+ function approveDepositAndDelegateExceedingAllowance(
+ string memory _validatorAddr
+ ) public payable {
+ bool successTx = staking.STAKING_CONTRACT.approve(
+ tx.origin,
+ msg.value,
+ delegateMethod
+ );
+ require(successTx, "Delegate Approve failed");
+ staking.STAKING_CONTRACT.delegate(
+ address(this),
+ _validatorAddr,
+ msg.value + 1
+ );
+ }
+
+ /// @dev This function is suppose to fail because the amount to delegate is
+ /// higher than the amount approved.
+ function approveDepositDelegateAndFailCustomLogic(
+ string memory _validatorAddr
+ ) public payable {
+ bool successTx = staking.STAKING_CONTRACT.approve(
+ tx.origin,
+ msg.value,
+ delegateMethod
+ );
+ require(successTx, "Delegate Approve failed");
+ staking.STAKING_CONTRACT.delegate(
+ address(this),
+ _validatorAddr,
+ msg.value
+ );
+ // This should fail since the balance is already spent in the previous call
+ payable(msg.sender).transfer(msg.value);
+ }
+
+ /// @dev This function is used to check that both the cosmos and evm state are correctly
+ /// updated for a successful transaction or reverted for a failed transaction.
+ /// To test this, deploy an ERC20 token contract to chain and mint some tokens to this
+ /// contract's address.
+ /// This contract will then transfer some tokens to the msg.sender address as well as
+ /// set up a delegation approval and stake funds using the staking EVM extension.
+ /// @param _contract Address of the ERC20 to call
+ /// @param _validatorAddr Address of the validator to delegate to
+ function callERC20AndDelegate(
+ address _contract,
+ string memory _validatorAddr,
+ uint256 _amount
+ ) public {
+ bool successApprove = staking.STAKING_CONTRACT.approve(
+ address(this),
+ _amount,
+ delegateMethod
+ );
+ require(successApprove, "delegation approval failed");
+
+ (bool success, ) = _contract.call(
+ abi.encodeWithSignature(
+ "transfer(address,uint256)",
+ msg.sender,
+ _amount
+ )
+ );
+ require(success, "transfer failed");
+
+ staking.STAKING_CONTRACT.delegate(msg.sender, _validatorAddr, _amount);
+ }
+}
\ No newline at end of file
diff --git a/precompiles/staking/testdata/StakingCallerTwo.json b/precompiles/staking/testdata/StakingCallerTwo.json
new file mode 100644
index 00000000..23e8173e
--- /dev/null
+++ b/precompiles/staking/testdata/StakingCallerTwo.json
@@ -0,0 +1,210 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "StakingCallerTwo",
+ "sourceName": "solidity/precompiles/staking/testdata/StakingCallerTwo.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "name": "counter",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "internalType": "string[]",
+ "name": "_methods",
+ "type": "string[]"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testApprove",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "moniker",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "identity",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "website",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "securityContact",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "details",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct Description",
+ "name": "_descr",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "rate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxRate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxChangeRate",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct CommissionRates",
+ "name": "_commRates",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_minSelfDel",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "_validator",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_pubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testCreateValidatorWithTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_delegator",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testDelegateWithCounterAndTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_dest",
+ "type": "address"
+ },
+ {
+ "internalType": "address payable",
+ "name": "_delegator",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validatorAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testDelegateWithTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b50611590806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80630a4433e21461005c578063365465a814610078578063405da99f1461009457806361bc221a146100b057806389493f41146100ce575b600080fd5b61007660048036038101906100719190610980565b6100ea565b005b610092600480360381019061008d9190610bb0565b6101b9565b005b6100ae60048036038101906100a99190610cde565b610428565b005b6100b861064a565b6040516100c59190610d84565b60405180910390f35b6100e860048036038101906100e39190610d9f565b610650565b005b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895868487876040518563ffffffff1660e01b815260040161012d9493929190610fbb565b6020604051808303816000875af115801561014c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101709190611010565b9050806101b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101a9906110c0565b60405180910390fd5b5050505050565b8115610285576000808154809291906101d19061110f565b919050555060008573ffffffffffffffffffffffffffffffffffffffff16600f6040516101fd90611188565b60006040518083038185875af1925050503d806000811461023a576040519150601f19603f3d011682016040523d82523d6000602084013e61023f565b606091505b5050905080610283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027a9061120f565b60405180910390fd5b505b600061080073ffffffffffffffffffffffffffffffffffffffff1663f7cd55168a8a8a8a8a8a6040518763ffffffff1660e01b81526004016102cc969594939291906113e1565b6020604051808303816000875af11580156102eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030f9190611010565b905080610351576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103489061149d565b60405180910390fd5b811561041d576000808154809291906103699061110f565b919050555060008673ffffffffffffffffffffffffffffffffffffffff16600f60405161039590611188565b60006040518083038185875af1925050503d80600081146103d2576040519150601f19603f3d011682016040523d82523d6000602084013e6103d7565b606091505b505090508061041b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104129061120f565b60405180910390fd5b505b505050505050505050565b81156104f4576000808154809291906104409061110f565b919050555060008573ffffffffffffffffffffffffffffffffffffffff16600f60405161046c90611188565b60006040518083038185875af1925050503d80600081146104a9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ae565b606091505b50509050806104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e99061120f565b60405180910390fd5b505b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8686866040518463ffffffff1660e01b81526004016105339392919061151c565b6020604051808303816000875af1158015610552573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105769190611010565b5080156106435760008081548092919061058f9061110f565b919050555060008573ffffffffffffffffffffffffffffffffffffffff16600f6040516105bb90611188565b60006040518083038185875af1925050503d80600081146105f8576040519150601f19603f3d011682016040523d82523d6000602084013e6105fd565b606091505b5050905080610641576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106389061120f565b60405180910390fd5b505b5050505050565b60005481565b811561071c576000808154809291906106689061110f565b919050555060008673ffffffffffffffffffffffffffffffffffffffff16600f60405161069490611188565b60006040518083038185875af1925050503d80600081146106d1576040519150601f19603f3d011682016040523d82523d6000602084013e6106d6565b606091505b505090508061071a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107119061120f565b60405180910390fd5b505b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8686866040518463ffffffff1660e01b815260040161075b9392919061151c565b6020604051808303816000875af115801561077a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079e9190611010565b50801561086b576000808154809291906107b79061110f565b919050555060008673ffffffffffffffffffffffffffffffffffffffff16600f6040516107e390611188565b60006040518083038185875af1925050503d8060008114610820576040519150601f19603f3d011682016040523d82523d6000602084013e610825565b606091505b5050905080610869576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108609061120f565b60405180910390fd5b505b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006108b282610887565b9050919050565b6108c2816108a7565b81146108cd57600080fd5b50565b6000813590506108df816108b9565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261090a576109096108e5565b5b8235905067ffffffffffffffff811115610927576109266108ea565b5b602083019150836020820283011115610943576109426108ef565b5b9250929050565b6000819050919050565b61095d8161094a565b811461096857600080fd5b50565b60008135905061097a81610954565b92915050565b6000806000806060858703121561099a5761099961087d565b5b60006109a8878288016108d0565b945050602085013567ffffffffffffffff8111156109c9576109c8610882565b5b6109d5878288016108f4565b935093505060406109e88782880161096b565b91505092959194509250565b600080fd5b600060a08284031215610a0f57610a0e6109f4565b5b81905092915050565b600060608284031215610a2e57610a2d6109f4565b5b81905092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610a8582610a3c565b810181811067ffffffffffffffff82111715610aa457610aa3610a4d565b5b80604052505050565b6000610ab7610873565b9050610ac38282610a7c565b919050565b600067ffffffffffffffff821115610ae357610ae2610a4d565b5b610aec82610a3c565b9050602081019050919050565b82818337600083830152505050565b6000610b1b610b1684610ac8565b610aad565b905082815260208101848484011115610b3757610b36610a37565b5b610b42848285610af9565b509392505050565b600082601f830112610b5f57610b5e6108e5565b5b8135610b6f848260208601610b08565b91505092915050565b60008115159050919050565b610b8d81610b78565b8114610b9857600080fd5b50565b600081359050610baa81610b84565b92915050565b600080600080600080600080610140898b031215610bd157610bd061087d565b5b600089013567ffffffffffffffff811115610bef57610bee610882565b5b610bfb8b828c016109f9565b9850506020610c0c8b828c01610a18565b9750506080610c1d8b828c0161096b565b96505060a0610c2e8b828c016108d0565b95505060c089013567ffffffffffffffff811115610c4f57610c4e610882565b5b610c5b8b828c01610b4a565b94505060e0610c6c8b828c0161096b565b935050610100610c7e8b828c01610b9b565b925050610120610c908b828c01610b9b565b9150509295985092959890939650565b6000610cab82610887565b9050919050565b610cbb81610ca0565b8114610cc657600080fd5b50565b600081359050610cd881610cb2565b92915050565b600080600080600060a08688031215610cfa57610cf961087d565b5b6000610d0888828901610cc9565b955050602086013567ffffffffffffffff811115610d2957610d28610882565b5b610d3588828901610b4a565b9450506040610d468882890161096b565b9350506060610d5788828901610b9b565b9250506080610d6888828901610b9b565b9150509295509295909350565b610d7e8161094a565b82525050565b6000602082019050610d996000830184610d75565b92915050565b60008060008060008060c08789031215610dbc57610dbb61087d565b5b6000610dca89828a01610cc9565b9650506020610ddb89828a01610cc9565b955050604087013567ffffffffffffffff811115610dfc57610dfb610882565b5b610e0889828a01610b4a565b9450506060610e1989828a0161096b565b9350506080610e2a89828a01610b9b565b92505060a0610e3b89828a01610b9b565b9150509295509295509295565b610e51816108a7565b82525050565b600082825260208201905092915050565b6000819050919050565b600082825260208201905092915050565b6000610e8f8385610e72565b9350610e9c838584610af9565b610ea583610a3c565b840190509392505050565b6000610ebd848484610e83565b90509392505050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112610ef257610ef1610ed0565b5b83810192508235915060208301925067ffffffffffffffff821115610f1a57610f19610ec6565b5b600182023603831315610f3057610f2f610ecb565b5b509250929050565b6000602082019050919050565b6000610f518385610e57565b935083602084028501610f6384610e68565b8060005b87811015610fa9578484038952610f7e8284610ed5565b610f89868284610eb0565b9550610f9484610f38565b935060208b019a505050600181019050610f67565b50829750879450505050509392505050565b6000606082019050610fd06000830187610e48565b610fdd6020830186610d75565b8181036040830152610ff0818486610f45565b905095945050505050565b60008151905061100a81610b84565b92915050565b6000602082840312156110265761102561087d565b5b600061103484828501610ffb565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f20617070726f7665207374616b696e67206d6574686f6460008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006110aa60218361103d565b91506110b58261104e565b604082019050919050565b600060208201905081810360008301526110d98161109d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061111a8261094a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361114c5761114b6110e0565b5b600182019050919050565b600081905092915050565b50565b6000611172600083611157565b915061117d82611162565b600082019050919050565b600061119382611165565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006111f960218361103d565b91506112048261119d565b604082019050919050565b60006020820190508181036000830152611228816111ec565b9050919050565b600060a083016112426000840184610ed5565b8583036000870152611255838284610e83565b925050506112666020840184610ed5565b8583036020870152611279838284610e83565b9250505061128a6040840184610ed5565b858303604087015261129d838284610e83565b925050506112ae6060840184610ed5565b85830360608701526112c1838284610e83565b925050506112d26080840184610ed5565b85830360808701526112e5838284610e83565b925050508091505092915050565b6000611302602084018461096b565b905092915050565b6113138161094a565b82525050565b6060820161132a60008301836112f3565b611337600085018261130a565b5061134560208301836112f3565b611352602085018261130a565b5061136060408301836112f3565b61136d604085018261130a565b50505050565b600081519050919050565b60005b8381101561139c578082015181840152602081019050611381565b60008484015250505050565b60006113b382611373565b6113bd818561103d565b93506113cd81856020860161137e565b6113d681610a3c565b840191505092915050565b60006101008201905081810360008301526113fc818961122f565b905061140b6020830188611319565b6114186080830187610d75565b61142560a0830186610e48565b81810360c083015261143781856113a8565b905061144660e0830184610d75565b979650505050505050565b7f4661696c656420746f20637265617465207468652076616c696461746f720000600082015250565b6000611487601e8361103d565b915061149282611451565b602082019050919050565b600060208201905081810360008301526114b68161147a565b9050919050565b6000819050919050565b60006114e26114dd6114d884610887565b6114bd565b610887565b9050919050565b60006114f4826114c7565b9050919050565b6000611506826114e9565b9050919050565b611516816114fb565b82525050565b6000606082019050611531600083018661150d565b818103602083015261154381856113a8565b90506115526040830184610d75565b94935050505056fea264697066735822122003832ab382861d2894e6822f69b8ae70f7e7900365e9a257288a1c0152b67c2364736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80630a4433e21461005c578063365465a814610078578063405da99f1461009457806361bc221a146100b057806389493f41146100ce575b600080fd5b61007660048036038101906100719190610980565b6100ea565b005b610092600480360381019061008d9190610bb0565b6101b9565b005b6100ae60048036038101906100a99190610cde565b610428565b005b6100b861064a565b6040516100c59190610d84565b60405180910390f35b6100e860048036038101906100e39190610d9f565b610650565b005b600061080073ffffffffffffffffffffffffffffffffffffffff1663b6039895868487876040518563ffffffff1660e01b815260040161012d9493929190610fbb565b6020604051808303816000875af115801561014c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101709190611010565b9050806101b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101a9906110c0565b60405180910390fd5b5050505050565b8115610285576000808154809291906101d19061110f565b919050555060008573ffffffffffffffffffffffffffffffffffffffff16600f6040516101fd90611188565b60006040518083038185875af1925050503d806000811461023a576040519150601f19603f3d011682016040523d82523d6000602084013e61023f565b606091505b5050905080610283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027a9061120f565b60405180910390fd5b505b600061080073ffffffffffffffffffffffffffffffffffffffff1663f7cd55168a8a8a8a8a8a6040518763ffffffff1660e01b81526004016102cc969594939291906113e1565b6020604051808303816000875af11580156102eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030f9190611010565b905080610351576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103489061149d565b60405180910390fd5b811561041d576000808154809291906103699061110f565b919050555060008673ffffffffffffffffffffffffffffffffffffffff16600f60405161039590611188565b60006040518083038185875af1925050503d80600081146103d2576040519150601f19603f3d011682016040523d82523d6000602084013e6103d7565b606091505b505090508061041b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104129061120f565b60405180910390fd5b505b505050505050505050565b81156104f4576000808154809291906104409061110f565b919050555060008573ffffffffffffffffffffffffffffffffffffffff16600f60405161046c90611188565b60006040518083038185875af1925050503d80600081146104a9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ae565b606091505b50509050806104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e99061120f565b60405180910390fd5b505b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8686866040518463ffffffff1660e01b81526004016105339392919061151c565b6020604051808303816000875af1158015610552573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105769190611010565b5080156106435760008081548092919061058f9061110f565b919050555060008573ffffffffffffffffffffffffffffffffffffffff16600f6040516105bb90611188565b60006040518083038185875af1925050503d80600081146105f8576040519150601f19603f3d011682016040523d82523d6000602084013e6105fd565b606091505b5050905080610641576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106389061120f565b60405180910390fd5b505b5050505050565b60005481565b811561071c576000808154809291906106689061110f565b919050555060008673ffffffffffffffffffffffffffffffffffffffff16600f60405161069490611188565b60006040518083038185875af1925050503d80600081146106d1576040519150601f19603f3d011682016040523d82523d6000602084013e6106d6565b606091505b505090508061071a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107119061120f565b60405180910390fd5b505b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8686866040518463ffffffff1660e01b815260040161075b9392919061151c565b6020604051808303816000875af115801561077a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079e9190611010565b50801561086b576000808154809291906107b79061110f565b919050555060008673ffffffffffffffffffffffffffffffffffffffff16600f6040516107e390611188565b60006040518083038185875af1925050503d8060008114610820576040519150601f19603f3d011682016040523d82523d6000602084013e610825565b606091505b5050905080610869576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108609061120f565b60405180910390fd5b505b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006108b282610887565b9050919050565b6108c2816108a7565b81146108cd57600080fd5b50565b6000813590506108df816108b9565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261090a576109096108e5565b5b8235905067ffffffffffffffff811115610927576109266108ea565b5b602083019150836020820283011115610943576109426108ef565b5b9250929050565b6000819050919050565b61095d8161094a565b811461096857600080fd5b50565b60008135905061097a81610954565b92915050565b6000806000806060858703121561099a5761099961087d565b5b60006109a8878288016108d0565b945050602085013567ffffffffffffffff8111156109c9576109c8610882565b5b6109d5878288016108f4565b935093505060406109e88782880161096b565b91505092959194509250565b600080fd5b600060a08284031215610a0f57610a0e6109f4565b5b81905092915050565b600060608284031215610a2e57610a2d6109f4565b5b81905092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610a8582610a3c565b810181811067ffffffffffffffff82111715610aa457610aa3610a4d565b5b80604052505050565b6000610ab7610873565b9050610ac38282610a7c565b919050565b600067ffffffffffffffff821115610ae357610ae2610a4d565b5b610aec82610a3c565b9050602081019050919050565b82818337600083830152505050565b6000610b1b610b1684610ac8565b610aad565b905082815260208101848484011115610b3757610b36610a37565b5b610b42848285610af9565b509392505050565b600082601f830112610b5f57610b5e6108e5565b5b8135610b6f848260208601610b08565b91505092915050565b60008115159050919050565b610b8d81610b78565b8114610b9857600080fd5b50565b600081359050610baa81610b84565b92915050565b600080600080600080600080610140898b031215610bd157610bd061087d565b5b600089013567ffffffffffffffff811115610bef57610bee610882565b5b610bfb8b828c016109f9565b9850506020610c0c8b828c01610a18565b9750506080610c1d8b828c0161096b565b96505060a0610c2e8b828c016108d0565b95505060c089013567ffffffffffffffff811115610c4f57610c4e610882565b5b610c5b8b828c01610b4a565b94505060e0610c6c8b828c0161096b565b935050610100610c7e8b828c01610b9b565b925050610120610c908b828c01610b9b565b9150509295985092959890939650565b6000610cab82610887565b9050919050565b610cbb81610ca0565b8114610cc657600080fd5b50565b600081359050610cd881610cb2565b92915050565b600080600080600060a08688031215610cfa57610cf961087d565b5b6000610d0888828901610cc9565b955050602086013567ffffffffffffffff811115610d2957610d28610882565b5b610d3588828901610b4a565b9450506040610d468882890161096b565b9350506060610d5788828901610b9b565b9250506080610d6888828901610b9b565b9150509295509295909350565b610d7e8161094a565b82525050565b6000602082019050610d996000830184610d75565b92915050565b60008060008060008060c08789031215610dbc57610dbb61087d565b5b6000610dca89828a01610cc9565b9650506020610ddb89828a01610cc9565b955050604087013567ffffffffffffffff811115610dfc57610dfb610882565b5b610e0889828a01610b4a565b9450506060610e1989828a0161096b565b9350506080610e2a89828a01610b9b565b92505060a0610e3b89828a01610b9b565b9150509295509295509295565b610e51816108a7565b82525050565b600082825260208201905092915050565b6000819050919050565b600082825260208201905092915050565b6000610e8f8385610e72565b9350610e9c838584610af9565b610ea583610a3c565b840190509392505050565b6000610ebd848484610e83565b90509392505050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112610ef257610ef1610ed0565b5b83810192508235915060208301925067ffffffffffffffff821115610f1a57610f19610ec6565b5b600182023603831315610f3057610f2f610ecb565b5b509250929050565b6000602082019050919050565b6000610f518385610e57565b935083602084028501610f6384610e68565b8060005b87811015610fa9578484038952610f7e8284610ed5565b610f89868284610eb0565b9550610f9484610f38565b935060208b019a505050600181019050610f67565b50829750879450505050509392505050565b6000606082019050610fd06000830187610e48565b610fdd6020830186610d75565b8181036040830152610ff0818486610f45565b905095945050505050565b60008151905061100a81610b84565b92915050565b6000602082840312156110265761102561087d565b5b600061103484828501610ffb565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f20617070726f7665207374616b696e67206d6574686f6460008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006110aa60218361103d565b91506110b58261104e565b604082019050919050565b600060208201905081810360008301526110d98161109d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061111a8261094a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361114c5761114b6110e0565b5b600182019050919050565b600081905092915050565b50565b6000611172600083611157565b915061117d82611162565b600082019050919050565b600061119382611165565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006111f960218361103d565b91506112048261119d565b604082019050919050565b60006020820190508181036000830152611228816111ec565b9050919050565b600060a083016112426000840184610ed5565b8583036000870152611255838284610e83565b925050506112666020840184610ed5565b8583036020870152611279838284610e83565b9250505061128a6040840184610ed5565b858303604087015261129d838284610e83565b925050506112ae6060840184610ed5565b85830360608701526112c1838284610e83565b925050506112d26080840184610ed5565b85830360808701526112e5838284610e83565b925050508091505092915050565b6000611302602084018461096b565b905092915050565b6113138161094a565b82525050565b6060820161132a60008301836112f3565b611337600085018261130a565b5061134560208301836112f3565b611352602085018261130a565b5061136060408301836112f3565b61136d604085018261130a565b50505050565b600081519050919050565b60005b8381101561139c578082015181840152602081019050611381565b60008484015250505050565b60006113b382611373565b6113bd818561103d565b93506113cd81856020860161137e565b6113d681610a3c565b840191505092915050565b60006101008201905081810360008301526113fc818961122f565b905061140b6020830188611319565b6114186080830187610d75565b61142560a0830186610e48565b81810360c083015261143781856113a8565b905061144660e0830184610d75565b979650505050505050565b7f4661696c656420746f20637265617465207468652076616c696461746f720000600082015250565b6000611487601e8361103d565b915061149282611451565b602082019050919050565b600060208201905081810360008301526114b68161147a565b9050919050565b6000819050919050565b60006114e26114dd6114d884610887565b6114bd565b610887565b9050919050565b60006114f4826114c7565b9050919050565b6000611506826114e9565b9050919050565b611516816114fb565b82525050565b6000606082019050611531600083018661150d565b818103602083015261154381856113a8565b90506115526040830184610d75565b94935050505056fea264697066735822122003832ab382861d2894e6822f69b8ae70f7e7900365e9a257288a1c0152b67c2364736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/staking/testdata/StakingCallerTwo.sol b/precompiles/staking/testdata/StakingCallerTwo.sol
new file mode 100644
index 00000000..5c13d36c
--- /dev/null
+++ b/precompiles/staking/testdata/StakingCallerTwo.sol
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../StakingI.sol" as staking;
+
+/// @title StakingCaller
+/// @author Evmos Core Team
+/// @dev This contract is used to test external contract calls to the staking precompile.
+contract StakingCallerTwo {
+ /// counter is used to test the state persistence bug, when EVM and Cosmos state were both
+ /// changed in the same function.
+ uint256 public counter;
+
+ /// @dev This function calls the staking precompile's approve method.
+ /// @param _addr The address to approve.
+ /// @param _methods The methods to approve.
+ function testApprove(
+ address _addr,
+ string[] calldata _methods,
+ uint256 _amount
+ ) public {
+ bool success = staking.STAKING_CONTRACT.approve(
+ _addr,
+ _amount,
+ _methods
+ );
+ require(success, "Failed to approve staking methods");
+ }
+
+ /// @dev This function showcased, that there was a bug in the EVM implementation, that occurred when
+ /// Cosmos state is modified in the same transaction as state information inside
+ /// the EVM.
+ /// @param _delegator Address of the delegator
+ /// @param _validatorAddr Address of the validator to delegate to
+ /// @param _amount Amount to delegate
+ /// @param _before Boolean to specify if funds should be transferred to delegator before the precompile call
+ /// @param _after Boolean to specify if funds should be transferred to delegator after the precompile call
+ function testDelegateWithCounterAndTransfer(
+ address payable _delegator,
+ string memory _validatorAddr,
+ uint256 _amount,
+ bool _before,
+ bool _after
+ ) public {
+ if (_before) {
+ counter++;
+ (bool sent, ) = _delegator.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ staking.STAKING_CONTRACT.delegate(_delegator, _validatorAddr, _amount);
+ if (_after) {
+ counter++;
+ (bool sent, ) = _delegator.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+
+ /// @dev This function showcased, that there was a bug in the EVM implementation, that occurred when
+ /// Cosmos state is modified in the same transaction as state information inside
+ /// the EVM.
+ /// @param _dest Address to send some funds from the contract
+ /// @param _delegator Address of the delegator
+ /// @param _validatorAddr Address of the validator to delegate to
+ /// @param _amount Amount to delegate
+ /// @param _before Boolean to specify if funds should be transferred to delegator before the precompile call
+ /// @param _after Boolean to specify if funds should be transferred to delegator after the precompile call
+ function testDelegateWithTransfer(
+ address payable _dest,
+ address payable _delegator,
+ string memory _validatorAddr,
+ uint256 _amount,
+ bool _before,
+ bool _after
+ ) public {
+ if (_before) {
+ counter++;
+ (bool sent, ) = _dest.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ staking.STAKING_CONTRACT.delegate(_delegator, _validatorAddr, _amount);
+ if (_after) {
+ counter++;
+ (bool sent, ) = _dest.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+
+ /// @dev This function calls the staking precompile's create validator method
+ /// and transfers of funds to the validator address (if specified).
+ /// @param _descr The initial description
+ /// @param _commRates The initial commissionRates
+ /// @param _minSelfDel The validator's self declared minimum self delegation
+ /// @param _validator The validator's operator address
+ /// @param _pubkey The consensus public key of the validator
+ /// @param _value The amount of the coin to be self delegated to the validator
+ /// @param _before Boolean to specify if funds should be transferred to delegator before the precompile call
+ /// @param _after Boolean to specify if funds should be transferred to delegator after the precompile call
+ function testCreateValidatorWithTransfer(
+ staking.Description calldata _descr,
+ staking.CommissionRates calldata _commRates,
+ uint256 _minSelfDel,
+ address _validator,
+ string memory _pubkey,
+ uint256 _value,
+ bool _before,
+ bool _after
+ ) public {
+ if (_before) {
+ counter++;
+ (bool sent, ) = _validator.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ bool success = staking.STAKING_CONTRACT.createValidator(
+ _descr,
+ _commRates,
+ _minSelfDel,
+ _validator,
+ _pubkey,
+ _value
+ );
+ require(success, "Failed to create the validator");
+ if (_after) {
+ counter++;
+ (bool sent, ) = _validator.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+}
diff --git a/precompiles/staking/testdata/staking_caller.go b/precompiles/staking/testdata/staking_caller.go
new file mode 100644
index 00000000..615015d5
--- /dev/null
+++ b/precompiles/staking/testdata/staking_caller.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadStakingCallerContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("StakingCaller.json")
+}
diff --git a/precompiles/staking/testdata/staking_caller_two.go b/precompiles/staking/testdata/staking_caller_two.go
new file mode 100644
index 00000000..8aee45a9
--- /dev/null
+++ b/precompiles/staking/testdata/staking_caller_two.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadStakingCallerTwoContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("StakingCallerTwo.json")
+}
diff --git a/precompiles/staking/tx.go b/precompiles/staking/tx.go
new file mode 100644
index 00000000..dc13d4fd
--- /dev/null
+++ b/precompiles/staking/tx.go
@@ -0,0 +1,477 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package staking
+
+import (
+ "fmt"
+ "time"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ stakingkeeper "github.com/evmos/evmos/v19/x/staking/keeper"
+)
+
+const (
+ // CreateValidatorMethod defines the ABI method name for the staking create validator transaction
+ CreateValidatorMethod = "createValidator"
+ // EditValidatorMethod defines the ABI method name for the staking edit validator transaction
+ EditValidatorMethod = "editValidator"
+ // DelegateMethod defines the ABI method name for the staking Delegate
+ // transaction.
+ DelegateMethod = "delegate"
+ // UndelegateMethod defines the ABI method name for the staking Undelegate
+ // transaction.
+ UndelegateMethod = "undelegate"
+ // RedelegateMethod defines the ABI method name for the staking Redelegate
+ // transaction.
+ RedelegateMethod = "redelegate"
+ // CancelUnbondingDelegationMethod defines the ABI method name for the staking
+ // CancelUnbondingDelegation transaction.
+ CancelUnbondingDelegationMethod = "cancelUnbondingDelegation"
+)
+
+const (
+ // DelegateAuthz defines the authorization type for the staking Delegate
+ DelegateAuthz = stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE
+ // UndelegateAuthz defines the authorization type for the staking Undelegate
+ UndelegateAuthz = stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE
+ // RedelegateAuthz defines the authorization type for the staking Redelegate
+ RedelegateAuthz = stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE
+ // CancelUnbondingDelegationAuthz defines the authorization type for the staking
+ CancelUnbondingDelegationAuthz = stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_CANCEL_UNBONDING_DELEGATION
+)
+
+// CreateValidator performs create validator.
+func (p Precompile) CreateValidator(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, validatorHexAddr, err := NewMsgCreateValidator(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ p.Logger(ctx).Debug(
+ "tx called",
+ "method", method.Name,
+ "commission", msg.Commission.String(),
+ "min_self_delegation", msg.MinSelfDelegation.String(),
+ "validator_address", validatorHexAddr.String(),
+ "pubkey", msg.Pubkey.String(),
+ "value", msg.Value.Amount.String(),
+ )
+
+ // ATM there's no authorization type for the MsgCreateValidator
+ // and MsgEditValidator (source: https://github.com/cosmos/cosmos-sdk/blob/4bd73b667f8aed50ad4602ddf862a4ed6e1450a8/x/staking/proto/cosmos/staking/v1beta1/authz.proto#L39-L50)
+ // so, for the time being, we won't allow calls from smart contracts
+ if contract.CallerAddress != origin {
+ return nil, fmt.Errorf(ErrCannotCallFromContract)
+ }
+
+ // we only allow the tx signer "origin" to create their own validator.
+ if origin != validatorHexAddr {
+ return nil, fmt.Errorf(ErrDifferentOriginFromDelegator, origin.String(), validatorHexAddr.String())
+ }
+
+ // Execute the transaction using the message server
+ msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper)
+ if _, err = msgSrv.CreateValidator(sdk.WrapSDKContext(ctx), msg); err != nil {
+ return nil, err
+ }
+
+ // Here we don't add journal entries here because calls from
+ // smart contracts are not supported at the moment for this method.
+
+ // Emit the event for the create validator transaction
+ if err = p.EmitCreateValidatorEvent(ctx, stateDB, msg, validatorHexAddr); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// EditValidator performs edit validator.
+func (p Precompile) EditValidator(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, validatorHexAddr, err := NewMsgEditValidator(args)
+ if err != nil {
+ return nil, err
+ }
+
+ p.Logger(ctx).Debug(
+ "tx called",
+ "method", method.Name,
+ "validator_address", msg.ValidatorAddress,
+ "commission_rate", msg.CommissionRate,
+ "min_self_delegation", msg.MinSelfDelegation,
+ )
+
+ // ATM there's no authorization type for the MsgCreateValidator
+ // and MsgEditValidator (source: https://github.com/cosmos/cosmos-sdk/blob/4bd73b667f8aed50ad4602ddf862a4ed6e1450a8/x/staking/proto/cosmos/staking/v1beta1/authz.proto#L39-L50)
+ // so, for the time being, we won't allow calls from smart contracts
+ if contract.CallerAddress != origin {
+ return nil, fmt.Errorf(ErrCannotCallFromContract)
+ }
+
+ // we only allow the tx signer "origin" to edit their own validator.
+ if origin != validatorHexAddr {
+ return nil, fmt.Errorf(ErrDifferentOriginFromValidator, origin.String(), validatorHexAddr.String())
+ }
+
+ // Execute the transaction using the message server
+ msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper)
+ if _, err = msgSrv.EditValidator(sdk.WrapSDKContext(ctx), msg); err != nil {
+ return nil, err
+ }
+
+ // Emit the event for the edit validator transaction
+ if err = p.EmitEditValidatorEvent(ctx, stateDB, msg, validatorHexAddr); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// Delegate performs a delegation of coins from a delegator to a validator.
+func (p *Precompile) Delegate(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, delegatorHexAddr, err := NewMsgDelegate(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ p.Logger(ctx).Debug(
+ "tx called",
+ "method", method.Name,
+ "args", fmt.Sprintf(
+ "{ delegator_address: %s, validator_address: %s, amount: %s }",
+ delegatorHexAddr,
+ msg.ValidatorAddress,
+ msg.Amount.Amount,
+ ),
+ )
+
+ var (
+ // stakeAuthz is the authorization grant for the caller and the delegator address
+ stakeAuthz *stakingtypes.StakeAuthorization
+ // expiration is the expiration time of the authorization grant
+ expiration *time.Time
+
+ // isCallerOrigin is true when the contract caller is the same as the origin
+ isCallerOrigin = contract.CallerAddress == origin
+ // isCallerDelegator is true when the contract caller is the same as the delegator
+ isCallerDelegator = contract.CallerAddress == delegatorHexAddr
+ )
+
+ // The provided delegator address should always be equal to the origin address.
+ // In case the contract caller address is the same as the delegator address provided,
+ // update the delegator address to be equal to the origin address.
+ // Otherwise, if the provided delegator address is different from the origin address,
+ // return an error because is a forbidden operation
+ if isCallerDelegator {
+ delegatorHexAddr = origin
+ } else if origin != delegatorHexAddr {
+ return nil, fmt.Errorf(ErrDifferentOriginFromDelegator, origin.String(), delegatorHexAddr.String())
+ }
+
+ // no need to have authorization when the contract caller is the same as origin (owner of funds)
+ if !isCallerOrigin {
+ // Check if the authorization grant exists for the caller and the origin
+ stakeAuthz, expiration, err = authorization.CheckAuthzAndAllowanceForGranter(ctx, p.AuthzKeeper, contract.CallerAddress, delegatorHexAddr, &msg.Amount, DelegateMsg)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Execute the transaction using the message server
+ msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper)
+ if _, err = msgSrv.Delegate(sdk.WrapSDKContext(ctx), msg); err != nil {
+ return nil, err
+ }
+
+ // Only update the authorization if the contract caller is different from the origin
+ if !isCallerOrigin {
+ if err := p.UpdateStakingAuthorization(ctx, contract.CallerAddress, delegatorHexAddr, stakeAuthz, expiration, DelegateMsg, msg); err != nil {
+ return nil, err
+ }
+ }
+
+ // Emit the event for the delegate transaction
+ if err = p.EmitDelegateEvent(ctx, stateDB, msg, delegatorHexAddr); err != nil {
+ return nil, err
+ }
+
+ if !isCallerOrigin {
+ // get the delegator address from the message
+ delAccAddr := sdk.MustAccAddressFromBech32(msg.DelegatorAddress)
+ delHexAddr := common.BytesToAddress(delAccAddr)
+ // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB
+ // when calling the precompile from a smart contract
+ // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state.
+ p.SetBalanceChangeEntries(cmn.NewBalanceChangeEntry(delHexAddr, msg.Amount.Amount.BigInt(), cmn.Sub))
+ }
+
+ return method.Outputs.Pack(true)
+}
+
+// Undelegate performs the undelegation of coins from a validator for a delegate.
+// The provided amount cannot be negative. This is validated in the msg.ValidateBasic() function.
+func (p Precompile) Undelegate(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, delegatorHexAddr, err := NewMsgUndelegate(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ p.Logger(ctx).Debug(
+ "tx called",
+ "method", method.Name,
+ "args", fmt.Sprintf(
+ "{ delegator_address: %s, validator_address: %s, amount: %s }",
+ delegatorHexAddr,
+ msg.ValidatorAddress,
+ msg.Amount.Amount,
+ ),
+ )
+
+ var (
+ // stakeAuthz is the authorization grant for the caller and the delegator address
+ stakeAuthz *stakingtypes.StakeAuthorization
+ // expiration is the expiration time of the authorization grant
+ expiration *time.Time
+
+ // isCallerOrigin is true when the contract caller is the same as the origin
+ isCallerOrigin = contract.CallerAddress == origin
+ // isCallerDelegator is true when the contract caller is the same as the delegator
+ isCallerDelegator = contract.CallerAddress == delegatorHexAddr
+ )
+
+ // The provided delegator address should always be equal to the origin address.
+ // In case the contract caller address is the same as the delegator address provided,
+ // update the delegator address to be equal to the origin address.
+ // Otherwise, if the provided delegator address is different from the origin address,
+ // return an error because is a forbidden operation
+ if isCallerDelegator {
+ delegatorHexAddr = origin
+ } else if origin != delegatorHexAddr {
+ return nil, fmt.Errorf(ErrDifferentOriginFromDelegator, origin.String(), delegatorHexAddr.String())
+ }
+
+ // no need to have authorization when the contract caller is the same as origin (owner of funds)
+ if !isCallerOrigin {
+ // Check if the authorization grant exists for the caller and the origin
+ stakeAuthz, expiration, err = authorization.CheckAuthzAndAllowanceForGranter(ctx, p.AuthzKeeper, contract.CallerAddress, delegatorHexAddr, &msg.Amount, UndelegateMsg)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Execute the transaction using the message server
+ msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper)
+ res, err := msgSrv.Undelegate(sdk.WrapSDKContext(ctx), msg)
+ if err != nil {
+ return nil, err
+ }
+
+ // Only update the authorization if the contract caller is different from the origin
+ if !isCallerOrigin {
+ if err := p.UpdateStakingAuthorization(ctx, contract.CallerAddress, delegatorHexAddr, stakeAuthz, expiration, UndelegateMsg, msg); err != nil {
+ return nil, err
+ }
+ }
+
+ // Emit the event for the undelegate transaction
+ if err = p.EmitUnbondEvent(ctx, stateDB, msg, delegatorHexAddr, res.CompletionTime.UTC().Unix()); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(res.CompletionTime.UTC().Unix())
+}
+
+// Redelegate performs a redelegation of coins for a delegate from a source validator
+// to a destination validator.
+// The provided amount cannot be negative. This is validated in the msg.ValidateBasic() function.
+func (p Precompile) Redelegate(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, delegatorHexAddr, err := NewMsgRedelegate(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ p.Logger(ctx).Debug(
+ "tx called",
+ "method", method.Name,
+ "args", fmt.Sprintf(
+ "{ delegator_address: %s, validator_src_address: %s, validator_dst_address: %s, amount: %s }",
+ delegatorHexAddr,
+ msg.ValidatorSrcAddress,
+ msg.ValidatorDstAddress,
+ msg.Amount.Amount,
+ ),
+ )
+
+ var (
+ // stakeAuthz is the authorization grant for the caller and the delegator address
+ stakeAuthz *stakingtypes.StakeAuthorization
+ // expiration is the expiration time of the authorization grant
+ expiration *time.Time
+
+ // isCallerOrigin is true when the contract caller is the same as the origin
+ isCallerOrigin = contract.CallerAddress == origin
+ // isCallerDelegator is true when the contract caller is the same as the delegator
+ isCallerDelegator = contract.CallerAddress == delegatorHexAddr
+ )
+
+ // The provided delegator address should always be equal to the origin address.
+ // In case the contract caller address is the same as the delegator address provided,
+ // update the delegator address to be equal to the origin address.
+ // Otherwise, if the provided delegator address is different from the origin address,
+ // return an error because is a forbidden operation
+ if isCallerDelegator {
+ delegatorHexAddr = origin
+ } else if origin != delegatorHexAddr {
+ return nil, fmt.Errorf(ErrDifferentOriginFromDelegator, origin.String(), delegatorHexAddr.String())
+ }
+
+ // no need to have authorization when the contract caller is the same as origin (owner of funds)
+ if !isCallerOrigin {
+ // Check if the authorization grant exists for the caller and the origin
+ stakeAuthz, expiration, err = authorization.CheckAuthzAndAllowanceForGranter(ctx, p.AuthzKeeper, contract.CallerAddress, delegatorHexAddr, &msg.Amount, RedelegateMsg)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper)
+ res, err := msgSrv.BeginRedelegate(sdk.WrapSDKContext(ctx), msg)
+ if err != nil {
+ return nil, err
+ }
+
+ // Only update the authorization if the contract caller is different from the origin
+ if !isCallerOrigin {
+ if err := p.UpdateStakingAuthorization(ctx, contract.CallerAddress, delegatorHexAddr, stakeAuthz, expiration, RedelegateMsg, msg); err != nil {
+ return nil, err
+ }
+ }
+
+ if err = p.EmitRedelegateEvent(ctx, stateDB, msg, delegatorHexAddr, res.CompletionTime.UTC().Unix()); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(res.CompletionTime.UTC().Unix())
+}
+
+// CancelUnbondingDelegation will cancel the unbonding of a delegation and delegate
+// back to the validator being unbonded from.
+// The provided amount cannot be negative. This is validated in the msg.ValidateBasic() function.
+func (p Precompile) CancelUnbondingDelegation(
+ ctx sdk.Context,
+ origin common.Address,
+ contract *vm.Contract,
+ stateDB vm.StateDB,
+ method *abi.Method,
+ args []interface{},
+) ([]byte, error) {
+ msg, delegatorHexAddr, err := NewMsgCancelUnbondingDelegation(args, p.stakingKeeper.BondDenom(ctx))
+ if err != nil {
+ return nil, err
+ }
+
+ p.Logger(ctx).Debug(
+ "tx called",
+ "method", method.Name,
+ "args", fmt.Sprintf(
+ "{ delegator_address: %s, validator_address: %s, amount: %s, creation_height: %d }",
+ delegatorHexAddr,
+ msg.ValidatorAddress,
+ msg.Amount.Amount,
+ msg.CreationHeight,
+ ),
+ )
+
+ var (
+ // stakeAuthz is the authorization grant for the caller and the delegator address
+ stakeAuthz *stakingtypes.StakeAuthorization
+ // expiration is the expiration time of the authorization grant
+ expiration *time.Time
+
+ // isCallerOrigin is true when the contract caller is the same as the origin
+ isCallerOrigin = contract.CallerAddress == origin
+ // isCallerDelegator is true when the contract caller is the same as the delegator
+ isCallerDelegator = contract.CallerAddress == delegatorHexAddr
+ )
+
+ // The provided delegator address should always be equal to the origin address.
+ // In case the contract caller address is the same as the delegator address provided,
+ // update the delegator address to be equal to the origin address.
+ // Otherwise, if the provided delegator address is different from the origin address,
+ // return an error because is a forbidden operation
+ if isCallerDelegator {
+ delegatorHexAddr = origin
+ } else if origin != delegatorHexAddr {
+ return nil, fmt.Errorf(ErrDifferentOriginFromDelegator, origin.String(), delegatorHexAddr.String())
+ }
+
+ // no need to have authorization when the contract caller is the same as origin (owner of funds)
+ if !isCallerOrigin {
+ // Check if the authorization grant exists for the caller and the origin
+ stakeAuthz, expiration, err = authorization.CheckAuthzAndAllowanceForGranter(ctx, p.AuthzKeeper, contract.CallerAddress, delegatorHexAddr, &msg.Amount, CancelUnbondingDelegationMsg)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper)
+ if _, err = msgSrv.CancelUnbondingDelegation(sdk.WrapSDKContext(ctx), msg); err != nil {
+ return nil, err
+ }
+
+ // Only update the authorization if the contract caller is different from the origin
+ if !isCallerOrigin {
+ if err := p.UpdateStakingAuthorization(ctx, contract.CallerAddress, delegatorHexAddr, stakeAuthz, expiration, CancelUnbondingDelegationMsg, msg); err != nil {
+ return nil, err
+ }
+ }
+
+ if err = p.EmitCancelUnbondingDelegationEvent(ctx, stateDB, msg, delegatorHexAddr); err != nil {
+ return nil, err
+ }
+
+ return method.Outputs.Pack(true)
+}
diff --git a/precompiles/staking/tx_test.go b/precompiles/staking/tx_test.go
new file mode 100644
index 00000000..fa157f4c
--- /dev/null
+++ b/precompiles/staking/tx_test.go
@@ -0,0 +1,1334 @@
+package staking_test
+
+import (
+ "encoding/base64"
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ geth "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/cmd/config"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ evmosutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func (s *PrecompileTestSuite) TestCreateValidator() {
+ var (
+ method = s.precompile.Methods[staking.CreateValidatorMethod]
+ description = staking.Description{
+ Moniker: "node0",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ }
+ commission = staking.Commission{
+ Rate: math.LegacyOneDec().BigInt(),
+ MaxRate: math.LegacyOneDec().BigInt(),
+ MaxChangeRate: math.LegacyOneDec().BigInt(),
+ }
+ minSelfDelegation = big.NewInt(1)
+ validatorAddress = s.address
+ pubkey = "nfJ0axJC9dhta1MAE1EBFaVdxxkYzxYrBaHuJVjG//M="
+ value = big.NewInt(1205000000000000000)
+ diffAddr, _ = evmosutiltx.NewAddrKey()
+ )
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ gas uint64
+ callerAddress *geth.Address
+ postCheck func(data []byte)
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 6, 0),
+ },
+ {
+ "fail - different origin than delegator",
+ func() []interface{} {
+ differentAddr := evmosutiltx.GenerateAddress()
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ differentAddr,
+ pubkey,
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "is not the same as delegator address",
+ },
+ {
+ "fail - invalid description",
+ func() []interface{} {
+ return []interface{}{
+ "",
+ commission,
+ minSelfDelegation,
+ validatorAddress,
+ pubkey,
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid description",
+ },
+ {
+ "fail - invalid commission",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ "",
+ minSelfDelegation,
+ validatorAddress,
+ pubkey,
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid commission",
+ },
+ {
+ "fail - invalid min self delegation",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ "",
+ validatorAddress,
+ pubkey,
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid amount",
+ },
+ {
+ "fail - invalid validator address",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ 1205,
+ pubkey,
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid validator address",
+ },
+ {
+ "fail - invalid pubkey",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ validatorAddress,
+ 1205,
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid type for",
+ },
+ {
+ "fail - pubkey decoding error",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ validatorAddress,
+ "bHVrZQ=", // base64.StdEncoding.DecodeString error
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "illegal base64 data",
+ },
+ {
+ "fail - consensus pubkey len is invalid",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ validatorAddress,
+ "bHVrZQ==",
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "consensus pubkey len is invalid",
+ },
+ {
+ "fail - invalid value",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ validatorAddress,
+ pubkey,
+ "",
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid amount",
+ },
+ {
+ "fail - cannot be called from address != than validator address",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ validatorAddress,
+ pubkey,
+ value,
+ }
+ },
+ 200000,
+ &diffAddr,
+ func([]byte) {},
+ true,
+ "this method can only be called directly to the precompile",
+ },
+ {
+ "success",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ commission,
+ minSelfDelegation,
+ validatorAddress,
+ pubkey,
+ value,
+ }
+ },
+ 200000,
+ nil,
+ func(data []byte) {
+ success, err := s.precompile.Unpack(staking.CreateValidatorMethod, data)
+ s.Require().NoError(err)
+ s.Require().Equal(success[0], true)
+
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeCreateValidator]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), geth.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var createValidatorEvent staking.EventCreateValidator
+ err = cmn.UnpackLog(s.precompile.ABI, &createValidatorEvent, staking.EventTypeCreateValidator, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, createValidatorEvent.ValidatorAddress)
+ s.Require().Equal(value, createValidatorEvent.Value)
+ },
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ // reset sender
+ validatorAddress = s.address
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+ if tc.callerAddress != nil {
+ contract.CallerAddress = *tc.callerAddress
+ }
+
+ bz, err := s.precompile.CreateValidator(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())
+
+ // query the validator in the staking keeper
+ validator := s.app.StakingKeeper.Validator(s.ctx, s.address.Bytes())
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ s.Require().Nil(validator)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(validator, "expected validator not to be nil")
+ tc.postCheck(bz)
+
+ isBonded := validator.IsBonded()
+ s.Require().Equal(false, isBonded, "expected validator bonded to be %t; got %t", false, isBonded)
+
+ consPubKey, err := validator.ConsPubKey()
+ s.Require().NoError(err)
+ consPubKeyBase64 := base64.StdEncoding.EncodeToString(consPubKey.Bytes())
+ s.Require().Equal(pubkey, consPubKeyBase64, "expected validator pubkey to be %s; got %s", pubkey, consPubKeyBase64)
+
+ operator := validator.GetOperator().String()
+ s.Require().Equal(sdk.ValAddress(validatorAddress.Bytes()).String(), operator, "expected validator operator to be %s; got %s", validatorAddress, operator)
+
+ commissionRate := validator.GetCommission()
+ s.Require().Equal(commission.Rate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", commission.Rate.String(), commissionRate.String())
+
+ valMinSelfDelegation := validator.GetMinSelfDelegation()
+ s.Require().Equal(minSelfDelegation.String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String())
+
+ moniker := validator.GetMoniker()
+ s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker)
+
+ jailed := validator.IsJailed()
+ s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestEditValidator() {
+ var (
+ validatorAddress geth.Address
+ commissionRate *big.Int
+ minSelfDelegation *big.Int
+ method = s.precompile.Methods[staking.EditValidatorMethod]
+ description = staking.Description{
+ Moniker: "node0-edited",
+ Identity: "",
+ Website: "",
+ SecurityContact: "",
+ Details: "",
+ }
+ )
+
+ testCases := []struct {
+ name string
+ malleate func() []interface{}
+ gas uint64
+ callerAddress *geth.Address
+ postCheck func(data []byte)
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func() []interface{} {
+ return []interface{}{}
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 4, 0),
+ },
+ {
+ "fail - different origin than delegator",
+ func() []interface{} {
+ differentAddr := evmosutiltx.GenerateAddress()
+ return []interface{}{
+ description,
+ differentAddr,
+ commissionRate,
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "is not the same as validator operator address",
+ },
+ {
+ "fail - invalid description",
+ func() []interface{} {
+ return []interface{}{
+ "",
+ validatorAddress,
+ commissionRate,
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid description",
+ },
+ {
+ "fail - invalid commission rate",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ validatorAddress,
+ "",
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid type for commissionRate",
+ },
+ {
+ "fail - invalid min self delegation",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ validatorAddress,
+ commissionRate,
+ "",
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid type for minSelfDelegation",
+ },
+ {
+ "fail - invalid validator address",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ 1205,
+ commissionRate,
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "invalid validator address",
+ },
+ {
+ "fail - commission change rate too high",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ validatorAddress,
+ math.LegacyNewDecWithPrec(7, 2).BigInt(),
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "commission cannot be changed more than max change rate",
+ },
+ {
+ "fail - negative commission rate",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ validatorAddress,
+ math.LegacyNewDecWithPrec(-5, 2).BigInt(),
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "commission rate must be between 0 and 1 (inclusive)",
+ },
+ {
+ "fail - negative min self delegation",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ validatorAddress,
+ commissionRate,
+ math.LegacyNewDecWithPrec(-5, 2).BigInt(),
+ }
+ },
+ 200000,
+ nil,
+ func([]byte) {},
+ true,
+ "minimum self delegation must be a positive integer",
+ },
+ {
+ "fail - calling precompile from a different address than validator (smart contract call)",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ validatorAddress,
+ commissionRate,
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ &s.address,
+ func([]byte) {},
+ true,
+ "this method can only be called directly to the precompile",
+ },
+ {
+ "success",
+ func() []interface{} {
+ return []interface{}{
+ description,
+ validatorAddress,
+ commissionRate,
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func(data []byte) {
+ success, err := s.precompile.Unpack(staking.EditValidatorMethod, data)
+ s.Require().NoError(err)
+ s.Require().Equal(success[0], true)
+
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeEditValidator]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), geth.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var editValidatorEvent staking.EventEditValidator
+ err = cmn.UnpackLog(s.precompile.ABI, &editValidatorEvent, staking.EventTypeEditValidator, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(validatorAddress, editValidatorEvent.ValidatorAddress)
+ s.Require().Equal(commissionRate, editValidatorEvent.CommissionRate)
+ s.Require().Equal(minSelfDelegation, editValidatorEvent.MinSelfDelegation)
+ },
+ false,
+ "",
+ },
+ {
+ "success - should not update commission rate",
+ func() []interface{} {
+ // expected commission rate is the previous one (0)
+ commissionRate = math.LegacyZeroDec().BigInt()
+ return []interface{}{
+ description,
+ validatorAddress,
+ big.NewInt(-1),
+ minSelfDelegation,
+ }
+ },
+ 200000,
+ nil,
+ func(data []byte) { //nolint:dupl
+ success, err := s.precompile.Unpack(staking.EditValidatorMethod, data)
+ s.Require().NoError(err)
+ s.Require().Equal(success[0], true)
+
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeEditValidator]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), geth.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var editValidatorEvent staking.EventEditValidator
+ err = cmn.UnpackLog(s.precompile.ABI, &editValidatorEvent, staking.EventTypeEditValidator, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(validatorAddress, editValidatorEvent.ValidatorAddress)
+ },
+ false,
+ "",
+ },
+ {
+ "success - should not update minimum self delegation",
+ func() []interface{} {
+ // expected min self delegation is the previous one (0)
+ minSelfDelegation = math.LegacyZeroDec().BigInt()
+ return []interface{}{
+ description,
+ validatorAddress,
+ commissionRate,
+ big.NewInt(-1),
+ }
+ },
+ 200000,
+ nil,
+ func(data []byte) { //nolint:dupl
+ success, err := s.precompile.Unpack(staking.EditValidatorMethod, data)
+ s.Require().NoError(err)
+ s.Require().Equal(success[0], true)
+
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeEditValidator]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), geth.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ // Check the fully unpacked event matches the one emitted
+ var editValidatorEvent staking.EventEditValidator
+ err = cmn.UnpackLog(s.precompile.ABI, &editValidatorEvent, staking.EventTypeEditValidator, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(validatorAddress, editValidatorEvent.ValidatorAddress)
+ },
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ commissionRate = math.LegacyNewDecWithPrec(5, 2).BigInt()
+ minSelfDelegation = big.NewInt(11)
+
+ // reset sender
+ validatorAddress = geth.BytesToAddress(s.validators[0].GetOperator().Bytes())
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, validatorAddress, s.precompile, tc.gas)
+ if tc.callerAddress != nil {
+ contract.CallerAddress = *tc.callerAddress
+ }
+
+ bz, err := s.precompile.EditValidator(s.ctx, validatorAddress, contract, s.stateDB, &method, tc.malleate())
+
+ // query the validator in the staking keeper
+ validator := s.app.StakingKeeper.Validator(s.ctx, validatorAddress.Bytes())
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(validator, "expected validator not to be nil")
+ tc.postCheck(bz)
+
+ isBonded := validator.IsBonded()
+ s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", true, isBonded)
+
+ operator := validator.GetOperator().String()
+ s.Require().Equal(sdk.ValAddress(validatorAddress.Bytes()).String(), operator, "expected validator operator to be %s; got %s", validatorAddress, operator)
+
+ updatedCommRate := validator.GetCommission()
+ s.Require().Equal(commissionRate.String(), updatedCommRate.BigInt().String(), "expected validator commission rate to be %s; got %s", commissionRate.String(), commissionRate.String())
+
+ valMinSelfDelegation := validator.GetMinSelfDelegation()
+ s.Require().Equal(minSelfDelegation.String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String())
+
+ moniker := validator.GetMoniker()
+ s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker)
+
+ jailed := validator.IsJailed()
+ s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestDelegate() {
+ method := s.precompile.Methods[staking.DelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ gas uint64
+ expDelegationShares *big.Int
+ postCheck func(data []byte)
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string) []interface{} {
+ return []interface{}{}
+ },
+ 200000,
+ big.NewInt(0),
+ func([]byte) {},
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 0),
+ },
+ // TODO: check case if authorization does not exist
+ {
+ name: "fail - different origin than delegator",
+ malleate: func(operatorAddress string) []interface{} {
+ differentAddr := evmosutiltx.GenerateAddress()
+ return []interface{}{
+ differentAddr,
+ operatorAddress,
+ big.NewInt(1e18),
+ }
+ },
+ gas: 200000,
+ expError: true,
+ errContains: "is not the same as delegator address",
+ },
+ {
+ "fail - invalid delegator address",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ "",
+ operatorAddress,
+ big.NewInt(1),
+ }
+ },
+ 200000,
+ big.NewInt(1),
+ func([]byte) {},
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, ""),
+ },
+ {
+ "fail - invalid amount",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ nil,
+ }
+ },
+ 200000,
+ big.NewInt(1),
+ func([]byte) {},
+ true,
+ fmt.Sprintf(cmn.ErrInvalidAmount, nil),
+ },
+ {
+ "fail - delegation failed because of insufficient funds",
+ func(operatorAddress string) []interface{} {
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ big.NewInt(9e18),
+ }
+ },
+ 200000,
+ big.NewInt(15),
+ func([]byte) {},
+ true,
+ "insufficient funds",
+ },
+ // TODO: adjust tests to work with authorizations (currently does not work because origin == precompile caller which needs no authorization)
+ // {
+ // "fail - delegation should not be possible to validators outside of the allow list",
+ // func(string) []interface{} {
+ // err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ // s.Require().NoError(err)
+ //
+ // // Create new validator --> this is not included in the authorized allow list
+ // testutil.CreateValidator(s.ctx, s.T(), s.privKey.PubKey(), s.app.StakingKeeper, math.NewInt(100))
+ // newValAddr := sdk.ValAddress(s.address.Bytes())
+ //
+ // return []interface{}{
+ // s.address,
+ // newValAddr.String(),
+ // big.NewInt(1e18),
+ // }
+ // },
+ // 200000,
+ // big.NewInt(15),
+ // func( []byte) {},
+ // true,
+ // "cannot delegate/undelegate",
+ // },
+ {
+ "success",
+ func(operatorAddress string) []interface{} {
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ big.NewInt(1e18),
+ }
+ },
+ 20000,
+ big.NewInt(2),
+ func(data []byte) {
+ success, err := s.precompile.Unpack(staking.DelegateMethod, data)
+ s.Require().NoError(err)
+ s.Require().Equal(success[0], true)
+
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[staking.EventTypeDelegate]
+ s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), geth.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+ },
+ false,
+ "",
+ },
+ // TODO: adjust tests to work with authorizations (currently does not work because origin == precompile caller which needs no authorization)
+ // {
+ // "success - delegate and update the authorization for the delegator",
+ // func(operatorAddress string) []interface{} {
+ // err := s.CreateAuthorization(s.address, staking.DelegateAuthz, &sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewInt(2e18)})
+ // s.Require().NoError(err)
+ // return []interface{}{
+ // s.address,
+ // operatorAddress,
+ // big.NewInt(1e18),
+ // }
+ // },
+ // 20000,
+ // big.NewInt(2),
+ // func(data []byte) {
+ // authorization, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, s.address.Bytes(), s.address.Bytes(), staking.DelegateMsg)
+ // s.Require().NotNil(authorization)
+ // stakeAuthorization := authorization.(*stakingtypes.StakeAuthorization)
+ // s.Require().Equal(math.NewInt(1e18), stakeAuthorization.MaxTokens.Amount)
+ // },
+ // false,
+ // "",
+ // },
+ // {
+ // "success - delegate and delete the authorization for the delegator",
+ // func(operatorAddress string) []interface{} {
+ // err := s.CreateAuthorization(s.address, staking.DelegateAuthz, &sdk.Coin{Denom: utils.BaseDenom, Amount: math.NewInt(1e18)})
+ // s.Require().NoError(err)
+ // return []interface{}{
+ // s.address,
+ // operatorAddress,
+ // big.NewInt(1e18),
+ // }
+ // },
+ // 20000,
+ // big.NewInt(2),
+ // func(data []byte) {
+ // authorization, _ := s.app.AuthzKeeper.GetAuthorization(s.ctx, s.address.Bytes(), s.address.Bytes(), staking.DelegateMsg)
+ // s.Require().Nil(authorization)
+ // },
+ // false,
+ // "",
+ // },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ bz, err := s.precompile.Delegate(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ // query the delegation in the staking keeper
+ delegation := s.app.StakingKeeper.Delegation(s.ctx, s.address.Bytes(), s.validators[0].GetOperator())
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ s.Require().Equal(s.validators[0].DelegatorShares, delegation.GetShares())
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotNil(delegation, "expected delegation not to be nil")
+ tc.postCheck(bz)
+
+ expDelegationAmt := math.NewIntFromBigInt(tc.expDelegationShares)
+ delegationAmt := delegation.GetShares().TruncateInt()
+
+ s.Require().Equal(expDelegationAmt, delegationAmt, "expected delegation amount to be %d; got %d", expDelegationAmt, delegationAmt)
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestUndelegate() {
+ method := s.precompile.Methods[staking.UndelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func(data []byte)
+ gas uint64
+ expUndelegationShares *big.Int
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(0),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 3, 0),
+ },
+ // TODO: check case if authorization does not exist
+ {
+ name: "fail - different origin than delegator",
+ malleate: func(operatorAddress string) []interface{} {
+ differentAddr := evmosutiltx.GenerateAddress()
+ return []interface{}{
+ differentAddr,
+ operatorAddress,
+ big.NewInt(1000000000000000000),
+ }
+ },
+ gas: 200000,
+ expError: true,
+ errContains: "is not the same as delegator",
+ },
+ {
+ "fail - invalid delegator address",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ "",
+ operatorAddress,
+ big.NewInt(1),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, ""),
+ },
+ {
+ "fail - invalid amount",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ nil,
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidAmount, nil),
+ },
+ {
+ "success",
+ func(operatorAddress string) []interface{} {
+ err := s.CreateAuthorization(s.address, staking.UndelegateAuthz, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ big.NewInt(1000000000000000000),
+ }
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(staking.UndelegateMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ completionTime, ok := args[0].(int64)
+ s.Require().True(ok, "completion time type %T", args[0])
+ params := s.app.StakingKeeper.GetParams(s.ctx)
+ expCompletionTime := s.ctx.BlockTime().Add(params.UnbondingTime).UTC().Unix()
+ s.Require().Equal(expCompletionTime, completionTime)
+ // Check the event emitted
+ log := s.stateDB.Logs()[0]
+ s.Require().Equal(log.Address, s.precompile.Address())
+ },
+ 20000,
+ big.NewInt(1000000000000000000),
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ bz, err := s.precompile.Undelegate(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+
+ // query the unbonding delegations in the staking keeper
+ undelegations := s.app.StakingKeeper.GetAllUnbondingDelegations(s.ctx, s.address.Bytes())
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+ tc.postCheck(bz)
+
+ bech32Addr, err := sdk.Bech32ifyAddressBytes(config.Bech32Prefix, s.address.Bytes())
+ s.Require().NoError(err)
+ s.Require().Equal(undelegations[0].DelegatorAddress, bech32Addr)
+ s.Require().Equal(undelegations[0].ValidatorAddress, s.validators[0].OperatorAddress)
+ s.Require().Equal(undelegations[0].Entries[0].Balance, math.NewIntFromBigInt(tc.expUndelegationShares))
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestRedelegate() {
+ method := s.precompile.Methods[staking.RedelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(srcOperatorAddr, dstOperatorAddr string) []interface{}
+ postCheck func(data []byte)
+ gas uint64
+ expRedelegationShares *big.Int
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string, string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(0),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 4, 0),
+ },
+ // TODO: check case if authorization does not exist
+ {
+ name: "fail - different origin than delegator",
+ malleate: func(srcOperatorAddr, dstOperatorAddr string) []interface{} {
+ differentAddr := evmosutiltx.GenerateAddress()
+ return []interface{}{
+ differentAddr,
+ srcOperatorAddr,
+ dstOperatorAddr,
+ big.NewInt(1000000000000000000),
+ }
+ },
+ gas: 200000,
+ expError: true,
+ errContains: "is not the same as delegator",
+ },
+ {
+ "fail - invalid delegator address",
+ func(srcOperatorAddr, dstOperatorAddr string) []interface{} {
+ return []interface{}{
+ "",
+ srcOperatorAddr,
+ dstOperatorAddr,
+ big.NewInt(1),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, ""),
+ },
+ {
+ "fail - invalid amount",
+ func(srcOperatorAddr, dstOperatorAddr string) []interface{} {
+ return []interface{}{
+ s.address,
+ srcOperatorAddr,
+ dstOperatorAddr,
+ nil,
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidAmount, nil),
+ },
+ {
+ "fail - invalid shares amount",
+ func(srcOperatorAddr, dstOperatorAddr string) []interface{} {
+ return []interface{}{
+ s.address,
+ srcOperatorAddr,
+ dstOperatorAddr,
+ big.NewInt(-1),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ "invalid shares amount",
+ },
+ {
+ "success",
+ func(srcOperatorAddr, dstOperatorAddr string) []interface{} {
+ err := s.CreateAuthorization(s.address, staking.RedelegateAuthz, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ srcOperatorAddr,
+ dstOperatorAddr,
+ big.NewInt(1000000000000000000),
+ }
+ },
+ func(data []byte) {
+ args, err := s.precompile.Unpack(staking.RedelegateMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+ s.Require().Len(args, 1)
+ completionTime, ok := args[0].(int64)
+ s.Require().True(ok, "completion time type %T", args[0])
+ params := s.app.StakingKeeper.GetParams(s.ctx)
+ expCompletionTime := s.ctx.BlockTime().Add(params.UnbondingTime).UTC().Unix()
+ s.Require().Equal(expCompletionTime, completionTime)
+ },
+ 200000,
+ big.NewInt(1),
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ bz, err := s.precompile.Redelegate(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress, s.validators[1].OperatorAddress))
+
+ // query the redelegations in the staking keeper
+ redelegations := s.app.StakingKeeper.GetRedelegations(s.ctx, s.address.Bytes(), 5)
+
+ if tc.expError {
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ s.Require().NoError(err)
+ s.Require().NotEmpty(bz)
+
+ bech32Addr, err := sdk.Bech32ifyAddressBytes(config.Bech32Prefix, s.address.Bytes())
+ s.Require().NoError(err)
+ s.Require().Equal(redelegations[0].DelegatorAddress, bech32Addr)
+ s.Require().Equal(redelegations[0].ValidatorSrcAddress, s.validators[0].OperatorAddress)
+ s.Require().Equal(redelegations[0].ValidatorDstAddress, s.validators[1].OperatorAddress)
+ s.Require().Equal(redelegations[0].Entries[0].SharesDst, math.LegacyNewDecFromBigInt(tc.expRedelegationShares))
+ }
+ })
+ }
+}
+
+func (s *PrecompileTestSuite) TestCancelUnbondingDelegation() {
+ method := s.precompile.Methods[staking.CancelUnbondingDelegationMethod]
+ undelegateMethod := s.precompile.Methods[staking.UndelegateMethod]
+
+ testCases := []struct {
+ name string
+ malleate func(operatorAddress string) []interface{}
+ postCheck func(data []byte)
+ gas uint64
+ expDelegatedShares *big.Int
+ expError bool
+ errContains string
+ }{
+ {
+ "fail - empty input args",
+ func(string) []interface{} {
+ return []interface{}{}
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(0),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 4, 0),
+ },
+ {
+ "fail - invalid delegator address",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ "",
+ operatorAddress,
+ big.NewInt(1),
+ big.NewInt(1),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidDelegator, ""),
+ },
+ {
+ "fail - creation height",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ big.NewInt(1),
+ nil,
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ "invalid creation height",
+ },
+ {
+ "fail - invalid amount",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ nil,
+ big.NewInt(1),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidAmount, nil),
+ },
+ {
+ "fail - invalid amount",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ nil,
+ big.NewInt(1),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ fmt.Sprintf(cmn.ErrInvalidAmount, nil),
+ },
+ {
+ "fail - invalid shares amount",
+ func(operatorAddress string) []interface{} {
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ big.NewInt(-1),
+ big.NewInt(1),
+ }
+ },
+ func([]byte) {},
+ 200000,
+ big.NewInt(1),
+ true,
+ "invalid amount: invalid request",
+ },
+ {
+ "success",
+ func(operatorAddress string) []interface{} {
+ err := s.CreateAuthorization(s.address, staking.DelegateAuthz, nil)
+ s.Require().NoError(err)
+ return []interface{}{
+ s.address,
+ operatorAddress,
+ big.NewInt(1),
+ big.NewInt(2),
+ }
+ },
+ func(data []byte) {
+ success, err := s.precompile.Unpack(staking.CancelUnbondingDelegationMethod, data)
+ s.Require().NoError(err)
+ s.Require().Equal(success[0], true)
+ },
+ 200000,
+ big.NewInt(1),
+ false,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+
+ var contract *vm.Contract
+ contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)
+
+ if tc.expError {
+ bz, err := s.precompile.CancelUnbondingDelegation(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+ s.Require().ErrorContains(err, tc.errContains)
+ s.Require().Empty(bz)
+ } else {
+ undelegateArgs := []interface{}{
+ s.address,
+ s.validators[0].OperatorAddress,
+ big.NewInt(1000000000000000000),
+ }
+
+ err := s.CreateAuthorization(s.address, staking.UndelegateAuthz, nil)
+ s.Require().NoError(err)
+
+ _, err = s.precompile.Undelegate(s.ctx, s.address, contract, s.stateDB, &undelegateMethod, undelegateArgs)
+ s.Require().NoError(err)
+
+ _, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), s.validators[0].GetOperator())
+ s.Require().False(found)
+
+ err = s.CreateAuthorization(s.address, staking.CancelUnbondingDelegationAuthz, nil)
+ s.Require().NoError(err)
+
+ bz, err := s.precompile.CancelUnbondingDelegation(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate(s.validators[0].OperatorAddress))
+ s.Require().NoError(err)
+ tc.postCheck(bz)
+
+ delegation, found := s.app.StakingKeeper.GetDelegation(s.ctx, s.address.Bytes(), s.validators[0].GetOperator())
+ s.Require().True(found)
+
+ bech32Addr, err := sdk.Bech32ifyAddressBytes(config.Bech32Prefix, s.address.Bytes())
+ s.Require().NoError(err)
+ s.Require().Equal(delegation.DelegatorAddress, bech32Addr)
+ s.Require().Equal(delegation.ValidatorAddress, s.validators[0].OperatorAddress)
+ s.Require().Equal(delegation.Shares, math.LegacyNewDecFromBigInt(tc.expDelegatedShares))
+
+ }
+ })
+ }
+}
diff --git a/precompiles/staking/types.go b/precompiles/staking/types.go
new file mode 100644
index 00000000..22ebf728
--- /dev/null
+++ b/precompiles/staking/types.go
@@ -0,0 +1,892 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package staking
+
+import (
+ "bytes"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/query"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+)
+
+const (
+ // DoNotModifyCommissionRate constant used in flags to indicate that commission rate field should not be updated
+ DoNotModifyCommissionRate = -1
+ // DoNotModifyMinSelfDelegation constant used in flags to indicate that min self delegation field should not be updated
+ DoNotModifyMinSelfDelegation = -1
+)
+
+// EventCreateValidator defines the event data for the staking CreateValidator transaction.
+type EventCreateValidator struct {
+ ValidatorAddress common.Address
+ Value *big.Int
+}
+
+// EventEditValidator defines the event data for the staking EditValidator transaction.
+type EventEditValidator struct {
+ ValidatorAddress common.Address
+ CommissionRate *big.Int
+ MinSelfDelegation *big.Int
+}
+
+// EventDelegate defines the event data for the staking Delegate transaction.
+type EventDelegate struct {
+ DelegatorAddress common.Address
+ ValidatorAddress common.Address
+ Amount *big.Int
+ NewShares *big.Int
+}
+
+// EventUnbond defines the event data for the staking Undelegate transaction.
+type EventUnbond struct {
+ DelegatorAddress common.Address
+ ValidatorAddress common.Address
+ Amount *big.Int
+ CompletionTime *big.Int
+}
+
+// EventRedelegate defines the event data for the staking Redelegate transaction.
+type EventRedelegate struct {
+ DelegatorAddress common.Address
+ ValidatorSrcAddress common.Address
+ ValidatorDstAddress common.Address
+ Amount *big.Int
+ CompletionTime *big.Int
+}
+
+// EventCancelUnbonding defines the event data for the staking CancelUnbond transaction.
+type EventCancelUnbonding struct {
+ DelegatorAddress common.Address
+ ValidatorAddress common.Address
+ Amount *big.Int
+ CreationHeight *big.Int
+}
+
+// Description use golang type alias defines a validator description.
+type Description = struct {
+ Moniker string "json:\"moniker\""
+ Identity string "json:\"identity\""
+ Website string "json:\"website\""
+ SecurityContact string "json:\"securityContact\""
+ Details string "json:\"details\""
+}
+
+// Commission use golang type alias defines a validator commission.
+// since solidity does not support decimals, after passing in the big int, convert the big int into a decimal with a precision of 18
+type Commission = struct {
+ Rate *big.Int "json:\"rate\""
+ MaxRate *big.Int "json:\"maxRate\""
+ MaxChangeRate *big.Int "json:\"maxChangeRate\""
+}
+
+// NewMsgCreateValidator creates a new MsgCreateValidator instance and does sanity checks
+// on the given arguments before populating the message.
+func NewMsgCreateValidator(args []interface{}, denom string) (*stakingtypes.MsgCreateValidator, common.Address, error) {
+ if len(args) != 6 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 6, len(args))
+ }
+
+ description, ok := args[0].(Description)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidDescription, args[0])
+ }
+
+ commission, ok := args[1].(Commission)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidCommission, args[1])
+ }
+
+ minSelfDelegation, ok := args[2].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidAmount, args[2])
+ }
+
+ validatorAddress, ok := args[3].(common.Address)
+ if !ok || validatorAddress == (common.Address{}) {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidValidator, args[3])
+ }
+
+ // use cli `evmosd tendermint show-validator` get pubkey
+ pubkeyBase64Str, ok := args[4].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "pubkey", "string", args[4])
+ }
+ pubkeyBytes, err := base64.StdEncoding.DecodeString(pubkeyBase64Str)
+ if err != nil {
+ return nil, common.Address{}, err
+ }
+
+ // more details see https://github.com/cosmos/cosmos-sdk/pull/18506
+ if len(pubkeyBytes) != ed25519.PubKeySize {
+ return nil, common.Address{}, fmt.Errorf("consensus pubkey len is invalid, got: %d, expected: %d", len(pubkeyBytes), ed25519.PubKeySize)
+ }
+
+ var ed25519pk cryptotypes.PubKey = &ed25519.PubKey{Key: pubkeyBytes}
+ pubkey, err := codectypes.NewAnyWithValue(ed25519pk)
+ if err != nil {
+ return nil, common.Address{}, err
+ }
+
+ value, ok := args[5].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidAmount, args[5])
+ }
+
+ msg := &stakingtypes.MsgCreateValidator{
+ Description: stakingtypes.Description{
+ Moniker: description.Moniker,
+ Identity: description.Identity,
+ Website: description.Website,
+ SecurityContact: description.SecurityContact,
+ Details: description.Details,
+ },
+ Commission: stakingtypes.CommissionRates{
+ Rate: sdk.NewDecFromBigIntWithPrec(commission.Rate, sdk.Precision),
+ MaxRate: sdk.NewDecFromBigIntWithPrec(commission.Rate, sdk.Precision),
+ MaxChangeRate: sdk.NewDecFromBigIntWithPrec(commission.Rate, sdk.Precision),
+ },
+ MinSelfDelegation: sdk.NewIntFromBigInt(minSelfDelegation),
+ DelegatorAddress: sdk.AccAddress(validatorAddress.Bytes()).String(),
+ ValidatorAddress: sdk.ValAddress(validatorAddress.Bytes()).String(),
+ Pubkey: pubkey,
+ Value: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(value)},
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, validatorAddress, nil
+}
+
+// NewMsgEditValidator creates a new MsgEditValidator instance and does sanity checks
+// on the given arguments before populating the message.
+func NewMsgEditValidator(args []interface{}) (*stakingtypes.MsgEditValidator, common.Address, error) {
+ if len(args) != 4 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 4, len(args))
+ }
+
+ description, ok := args[0].(Description)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidDescription, args[0])
+ }
+
+ validatorHexAddr, ok := args[1].(common.Address)
+ if !ok || validatorHexAddr == (common.Address{}) {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidValidator, args[1])
+ }
+
+ commissionRateBigInt, ok := args[2].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "commissionRate", &big.Int{}, args[2])
+ }
+
+ // The default value of a variable declared using a pointer is nil, indicating that the user does not want to modify its value.
+ // If the value passed in by the user is not DoNotModifyCommissionRate, which is -1, it means that the user wants to modify its value.
+ var commissionRate *math.LegacyDec
+ if commissionRateBigInt.Cmp(big.NewInt(DoNotModifyCommissionRate)) != 0 {
+ cr := sdk.NewDecFromBigIntWithPrec(commissionRateBigInt, sdk.Precision)
+ commissionRate = &cr
+ }
+
+ minSelfDelegationBigInt, ok := args[3].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "minSelfDelegation", &big.Int{}, args[3])
+ }
+
+ var minSelfDelegation *math.Int
+ if minSelfDelegationBigInt.Cmp(big.NewInt(DoNotModifyMinSelfDelegation)) != 0 {
+ msd := math.NewIntFromBigInt(minSelfDelegationBigInt)
+ minSelfDelegation = &msd
+ }
+
+ msg := &stakingtypes.MsgEditValidator{
+ Description: stakingtypes.Description{
+ Moniker: description.Moniker,
+ Identity: description.Identity,
+ Website: description.Website,
+ SecurityContact: description.SecurityContact,
+ Details: description.Details,
+ },
+ ValidatorAddress: sdk.ValAddress(validatorHexAddr.Bytes()).String(),
+ CommissionRate: commissionRate,
+ MinSelfDelegation: minSelfDelegation,
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, validatorHexAddr, nil
+}
+
+// NewMsgDelegate creates a new MsgDelegate instance and does sanity checks
+// on the given arguments before populating the message.
+func NewMsgDelegate(args []interface{}, denom string) (*stakingtypes.MsgDelegate, common.Address, error) {
+ delegatorAddr, validatorAddress, amount, err := checkDelegationUndelegationArgs(args)
+ if err != nil {
+ return nil, common.Address{}, err
+ }
+
+ msg := &stakingtypes.MsgDelegate{
+ DelegatorAddress: sdk.AccAddress(delegatorAddr.Bytes()).String(),
+ ValidatorAddress: validatorAddress,
+ Amount: sdk.Coin{
+ Denom: denom,
+ Amount: math.NewIntFromBigInt(amount),
+ },
+ }
+
+ if err = msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, delegatorAddr, nil
+}
+
+// NewMsgUndelegate creates a new MsgUndelegate instance and does sanity checks
+// on the given arguments before populating the message.
+func NewMsgUndelegate(args []interface{}, denom string) (*stakingtypes.MsgUndelegate, common.Address, error) {
+ delegatorAddr, validatorAddress, amount, err := checkDelegationUndelegationArgs(args)
+ if err != nil {
+ return nil, common.Address{}, err
+ }
+
+ msg := &stakingtypes.MsgUndelegate{
+ DelegatorAddress: sdk.AccAddress(delegatorAddr.Bytes()).String(),
+ ValidatorAddress: validatorAddress,
+ Amount: sdk.Coin{
+ Denom: denom,
+ Amount: math.NewIntFromBigInt(amount),
+ },
+ }
+
+ if err = msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, delegatorAddr, nil
+}
+
+// NewMsgRedelegate creates a new MsgRedelegate instance and does sanity checks
+// on the given arguments before populating the message.
+func NewMsgRedelegate(args []interface{}, denom string) (*stakingtypes.MsgBeginRedelegate, common.Address, error) {
+ if len(args) != 4 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 4, len(args))
+ }
+
+ delegatorAddr, ok := args[0].(common.Address)
+ if !ok || delegatorAddr == (common.Address{}) {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorSrcAddress, ok := args[1].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "validatorSrcAddress", "string", args[1])
+ }
+
+ validatorDstAddress, ok := args[2].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "validatorDstAddress", "string", args[2])
+ }
+
+ amount, ok := args[3].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidAmount, args[3])
+ }
+
+ msg := &stakingtypes.MsgBeginRedelegate{
+ DelegatorAddress: sdk.AccAddress(delegatorAddr.Bytes()).String(), // bech32 formatted
+ ValidatorSrcAddress: validatorSrcAddress,
+ ValidatorDstAddress: validatorDstAddress,
+ Amount: sdk.Coin{
+ Denom: denom,
+ Amount: math.NewIntFromBigInt(amount),
+ },
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, delegatorAddr, nil
+}
+
+// NewMsgCancelUnbondingDelegation creates a new MsgCancelUnbondingDelegation instance and does sanity checks
+// on the given arguments before populating the message.
+func NewMsgCancelUnbondingDelegation(args []interface{}, denom string) (*stakingtypes.MsgCancelUnbondingDelegation, common.Address, error) {
+ if len(args) != 4 {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 4, len(args))
+ }
+
+ delegatorAddr, ok := args[0].(common.Address)
+ if !ok || delegatorAddr == (common.Address{}) {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorAddress, ok := args[1].(string)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "validatorAddress", "string", args[1])
+ }
+
+ amount, ok := args[2].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidAmount, args[2])
+ }
+
+ creationHeight, ok := args[3].(*big.Int)
+ if !ok {
+ return nil, common.Address{}, fmt.Errorf("invalid creation height")
+ }
+
+ msg := &stakingtypes.MsgCancelUnbondingDelegation{
+ DelegatorAddress: sdk.AccAddress(delegatorAddr.Bytes()).String(), // bech32 formatted
+ ValidatorAddress: validatorAddress,
+ Amount: sdk.Coin{
+ Denom: denom,
+ Amount: math.NewIntFromBigInt(amount),
+ },
+ CreationHeight: creationHeight.Int64(),
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return nil, common.Address{}, err
+ }
+
+ return msg, delegatorAddr, nil
+}
+
+// NewDelegationRequest creates a new QueryDelegationRequest instance and does sanity checks
+// on the given arguments before populating the request.
+func NewDelegationRequest(args []interface{}) (*stakingtypes.QueryDelegationRequest, error) {
+ if len(args) != 2 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ delegatorAddr, ok := args[0].(common.Address)
+ if !ok || delegatorAddr == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorAddress, ok := args[1].(string)
+ if !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "validatorAddress", "string", args[1])
+ }
+
+ return &stakingtypes.QueryDelegationRequest{
+ DelegatorAddr: sdk.AccAddress(delegatorAddr.Bytes()).String(), // bech32 formatted
+ ValidatorAddr: validatorAddress,
+ }, nil
+}
+
+// NewValidatorRequest create a new QueryValidatorRequest instance and does sanity checks
+// on the given arguments before populating the request.
+func NewValidatorRequest(args []interface{}) (*stakingtypes.QueryValidatorRequest, error) {
+ if len(args) != 1 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args))
+ }
+
+ validatorHexAddr, ok := args[0].(common.Address)
+ if !ok || validatorHexAddr == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidValidator, args[0])
+ }
+
+ validatorAddress := sdk.ValAddress(validatorHexAddr.Bytes()).String()
+
+ return &stakingtypes.QueryValidatorRequest{ValidatorAddr: validatorAddress}, nil
+}
+
+// NewValidatorsRequest create a new QueryValidatorsRequest instance and does sanity checks
+// on the given arguments before populating the request.
+func NewValidatorsRequest(method *abi.Method, args []interface{}) (*stakingtypes.QueryValidatorsRequest, error) {
+ if len(args) != 2 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ var input ValidatorsInput
+ if err := method.Inputs.Copy(&input, args); err != nil {
+ return nil, fmt.Errorf("error while unpacking args to ValidatorsInput struct: %s", err)
+ }
+
+ if bytes.Equal(input.PageRequest.Key, []byte{0}) {
+ input.PageRequest.Key = nil
+ }
+
+ return &stakingtypes.QueryValidatorsRequest{
+ Status: input.Status,
+ Pagination: &input.PageRequest,
+ }, nil
+}
+
+// NewRedelegationRequest create a new QueryRedelegationRequest instance and does sanity checks
+// on the given arguments before populating the request.
+func NewRedelegationRequest(args []interface{}) (*RedelegationRequest, error) {
+ if len(args) != 3 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
+ }
+
+ delegatorAddr, ok := args[0].(common.Address)
+ if !ok || delegatorAddr == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorSrcAddress, ok := args[1].(string)
+ if !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "validatorSrcAddress", "string", args[1])
+ }
+
+ validatorSrcAddr, err := sdk.ValAddressFromBech32(validatorSrcAddress)
+ if err != nil {
+ return nil, err
+ }
+
+ validatorDstAddress, ok := args[2].(string)
+ if !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "validatorDstAddress", "string", args[2])
+ }
+
+ validatorDstAddr, err := sdk.ValAddressFromBech32(validatorDstAddress)
+ if err != nil {
+ return nil, err
+ }
+
+ return &RedelegationRequest{
+ DelegatorAddress: delegatorAddr.Bytes(), // bech32 formatted
+ ValidatorSrcAddress: validatorSrcAddr,
+ ValidatorDstAddress: validatorDstAddr,
+ }, nil
+}
+
+// NewRedelegationsRequest create a new QueryRedelegationsRequest instance and does sanity checks
+// on the given arguments before populating the request.
+func NewRedelegationsRequest(method *abi.Method, args []interface{}) (*stakingtypes.QueryRedelegationsRequest, error) {
+ if len(args) != 4 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 4, len(args))
+ }
+
+ // delAddr, srcValAddr & dstValAddr
+ // can be empty strings. The query will return the
+ // corresponding redelegations according to the addresses specified
+ // however, cannot pass all as empty strings, need to provide at least
+ // the delegator address or the source validator address
+ var input RedelegationsInput
+ if err := method.Inputs.Copy(&input, args); err != nil {
+ return nil, fmt.Errorf("error while unpacking args to RedelegationsInput struct: %s", err)
+ }
+
+ var (
+ // delegatorAddr is the string representation of the delegator address
+ delegatorAddr = ""
+ // emptyAddr is an empty address
+ emptyAddr = common.Address{}.Hex()
+ )
+ if input.DelegatorAddress.Hex() != emptyAddr {
+ delegatorAddr = sdk.AccAddress(input.DelegatorAddress.Bytes()).String() // bech32 formatted
+ }
+
+ if delegatorAddr == "" && input.SrcValidatorAddress == "" && input.DstValidatorAddress == "" ||
+ delegatorAddr == "" && input.SrcValidatorAddress == "" && input.DstValidatorAddress != "" {
+ return nil, errors.New("invalid query. Need to specify at least a source validator address or delegator address")
+ }
+
+ return &stakingtypes.QueryRedelegationsRequest{
+ DelegatorAddr: delegatorAddr, // bech32 formatted
+ SrcValidatorAddr: input.SrcValidatorAddress,
+ DstValidatorAddr: input.DstValidatorAddress,
+ Pagination: &input.PageRequest,
+ }, nil
+}
+
+// RedelegationRequest is a struct that contains the information to pass into a redelegation query.
+type RedelegationRequest struct {
+ DelegatorAddress sdk.AccAddress
+ ValidatorSrcAddress sdk.ValAddress
+ ValidatorDstAddress sdk.ValAddress
+}
+
+// RedelegationsRequest is a struct that contains the information to pass into a redelegations query.
+type RedelegationsRequest struct {
+ DelegatorAddress sdk.AccAddress
+ MaxRetrieve int64
+}
+
+// UnbondingDelegationEntry is a struct that contains the information about an unbonding delegation entry.
+type UnbondingDelegationEntry struct {
+ CreationHeight int64
+ CompletionTime int64
+ InitialBalance *big.Int
+ Balance *big.Int
+ UnbondingId uint64 //nolint
+ UnbondingOnHoldRefCount int64
+}
+
+// UnbondingDelegationResponse is a struct that contains the information about an unbonding delegation.
+type UnbondingDelegationResponse struct {
+ DelegatorAddress string
+ ValidatorAddress string
+ Entries []UnbondingDelegationEntry
+}
+
+// UnbondingDelegationOutput is the output response returned by the query method.
+type UnbondingDelegationOutput struct {
+ UnbondingDelegation UnbondingDelegationResponse
+}
+
+// FromResponse populates the DelegationOutput from a QueryDelegationResponse.
+func (do *UnbondingDelegationOutput) FromResponse(res *stakingtypes.QueryUnbondingDelegationResponse) *UnbondingDelegationOutput {
+ do.UnbondingDelegation.Entries = make([]UnbondingDelegationEntry, len(res.Unbond.Entries))
+ do.UnbondingDelegation.ValidatorAddress = res.Unbond.ValidatorAddress
+ do.UnbondingDelegation.DelegatorAddress = res.Unbond.DelegatorAddress
+ for i, entry := range res.Unbond.Entries {
+ do.UnbondingDelegation.Entries[i] = UnbondingDelegationEntry{
+ UnbondingId: entry.UnbondingId,
+ UnbondingOnHoldRefCount: entry.UnbondingOnHoldRefCount,
+ CreationHeight: entry.CreationHeight,
+ CompletionTime: entry.CompletionTime.UTC().Unix(),
+ InitialBalance: entry.InitialBalance.BigInt(),
+ Balance: entry.Balance.BigInt(),
+ }
+ }
+ return do
+}
+
+// DelegationOutput is a struct to represent the key information from
+// a delegation response.
+type DelegationOutput struct {
+ Shares *big.Int
+ Balance cmn.Coin
+}
+
+// FromResponse populates the DelegationOutput from a QueryDelegationResponse.
+func (do *DelegationOutput) FromResponse(res *stakingtypes.QueryDelegationResponse) *DelegationOutput {
+ do.Shares = res.DelegationResponse.Delegation.Shares.BigInt()
+ do.Balance = cmn.Coin{
+ Denom: res.DelegationResponse.Balance.Denom,
+ Amount: res.DelegationResponse.Balance.Amount.BigInt(),
+ }
+ return do
+}
+
+// Pack packs a given slice of abi arguments into a byte array.
+func (do *DelegationOutput) Pack(args abi.Arguments) ([]byte, error) {
+ return args.Pack(do.Shares, do.Balance)
+}
+
+// ValidatorInfo is a struct to represent the key information from
+// a validator response.
+type ValidatorInfo struct {
+ OperatorAddress string `abi:"operatorAddress"`
+ ConsensusPubkey string `abi:"consensusPubkey"`
+ Jailed bool `abi:"jailed"`
+ Status uint8 `abi:"status"`
+ Tokens *big.Int `abi:"tokens"`
+ DelegatorShares *big.Int `abi:"delegatorShares"` // TODO: Decimal
+ Description string `abi:"description"`
+ UnbondingHeight int64 `abi:"unbondingHeight"`
+ UnbondingTime int64 `abi:"unbondingTime"`
+ Commission *big.Int `abi:"commission"`
+ MinSelfDelegation *big.Int `abi:"minSelfDelegation"`
+}
+
+type ValidatorOutput struct {
+ Validator ValidatorInfo
+}
+
+// DefaultValidatorOutput returns a ValidatorOutput with default values.
+func DefaultValidatorOutput() ValidatorOutput {
+ return ValidatorOutput{
+ ValidatorInfo{
+ OperatorAddress: "",
+ ConsensusPubkey: "",
+ Jailed: false,
+ Status: uint8(0),
+ Tokens: big.NewInt(0),
+ DelegatorShares: big.NewInt(0),
+ Description: "",
+ UnbondingHeight: int64(0),
+ UnbondingTime: int64(0),
+ Commission: big.NewInt(0),
+ MinSelfDelegation: big.NewInt(0),
+ },
+ }
+}
+
+// FromResponse populates the ValidatorOutput from a QueryValidatorResponse.
+func (vo *ValidatorOutput) FromResponse(res *stakingtypes.QueryValidatorResponse) ValidatorOutput {
+ operatorAddress, err := sdk.ValAddressFromBech32(res.Validator.OperatorAddress)
+ if err != nil {
+ return DefaultValidatorOutput()
+ }
+
+ return ValidatorOutput{
+ Validator: ValidatorInfo{
+ OperatorAddress: common.BytesToAddress(operatorAddress.Bytes()).String(),
+ ConsensusPubkey: FormatConsensusPubkey(res.Validator.ConsensusPubkey),
+ Jailed: res.Validator.Jailed,
+ Status: uint8(stakingtypes.BondStatus_value[res.Validator.Status.String()]),
+ Tokens: res.Validator.Tokens.BigInt(),
+ DelegatorShares: res.Validator.DelegatorShares.BigInt(), // TODO: Decimal
+ // TODO: create description type,
+ Description: res.Validator.Description.Details,
+ UnbondingHeight: res.Validator.UnbondingHeight,
+ UnbondingTime: res.Validator.UnbondingTime.UTC().Unix(),
+ Commission: res.Validator.Commission.CommissionRates.Rate.BigInt(),
+ MinSelfDelegation: res.Validator.MinSelfDelegation.BigInt(),
+ },
+ }
+}
+
+// ValidatorsInput is a struct to represent the input information for
+// the validators query. Needed to unpack arguments into the PageRequest struct.
+type ValidatorsInput struct {
+ Status string
+ PageRequest query.PageRequest
+}
+
+// ValidatorsOutput is a struct to represent the key information from
+// a validators response.
+type ValidatorsOutput struct {
+ Validators []ValidatorInfo
+ PageResponse query.PageResponse
+}
+
+// FromResponse populates the ValidatorsOutput from a QueryValidatorsResponse.
+func (vo *ValidatorsOutput) FromResponse(res *stakingtypes.QueryValidatorsResponse) *ValidatorsOutput {
+ vo.Validators = make([]ValidatorInfo, len(res.Validators))
+ for i, v := range res.Validators {
+ operatorAddress, err := sdk.ValAddressFromBech32(v.OperatorAddress)
+ if err != nil {
+ vo.Validators[i] = DefaultValidatorOutput().Validator
+ } else {
+ vo.Validators[i] = ValidatorInfo{
+ OperatorAddress: common.BytesToAddress(operatorAddress.Bytes()).String(),
+ ConsensusPubkey: FormatConsensusPubkey(v.ConsensusPubkey),
+ Jailed: v.Jailed,
+ Status: uint8(stakingtypes.BondStatus_value[v.Status.String()]),
+ Tokens: v.Tokens.BigInt(),
+ DelegatorShares: v.DelegatorShares.BigInt(),
+ Description: v.Description.Details,
+ UnbondingHeight: v.UnbondingHeight,
+ UnbondingTime: v.UnbondingTime.UTC().Unix(),
+ Commission: v.Commission.CommissionRates.Rate.BigInt(),
+ MinSelfDelegation: v.MinSelfDelegation.BigInt(),
+ }
+ }
+ }
+
+ if res.Pagination != nil {
+ vo.PageResponse.Total = res.Pagination.Total
+ vo.PageResponse.NextKey = res.Pagination.NextKey
+ }
+
+ return vo
+}
+
+// Pack packs a given slice of abi arguments into a byte array.
+func (vo *ValidatorsOutput) Pack(args abi.Arguments) ([]byte, error) {
+ return args.Pack(vo.Validators, vo.PageResponse)
+}
+
+// RedelegationEntry is a struct to represent the key information from
+// a redelegation entry response.
+type RedelegationEntry struct {
+ CreationHeight int64
+ CompletionTime int64
+ InitialBalance *big.Int
+ SharesDst *big.Int
+}
+
+// RedelegationValues is a struct to represent the key information from
+// a redelegation response.
+type RedelegationValues struct {
+ DelegatorAddress string
+ ValidatorSrcAddress string
+ ValidatorDstAddress string
+ Entries []RedelegationEntry
+}
+
+// RedelegationOutput returns the output for a redelegation query.
+type RedelegationOutput struct {
+ Redelegation RedelegationValues
+}
+
+// FromResponse populates the RedelegationOutput from a QueryRedelegationsResponse.
+func (ro *RedelegationOutput) FromResponse(res stakingtypes.Redelegation) *RedelegationOutput {
+ ro.Redelegation.Entries = make([]RedelegationEntry, len(res.Entries))
+ ro.Redelegation.DelegatorAddress = res.DelegatorAddress
+ ro.Redelegation.ValidatorSrcAddress = res.ValidatorSrcAddress
+ ro.Redelegation.ValidatorDstAddress = res.ValidatorDstAddress
+ for i, entry := range res.Entries {
+ ro.Redelegation.Entries[i] = RedelegationEntry{
+ CreationHeight: entry.CreationHeight,
+ CompletionTime: entry.CompletionTime.UTC().Unix(),
+ InitialBalance: entry.InitialBalance.BigInt(),
+ SharesDst: entry.SharesDst.BigInt(),
+ }
+ }
+ return ro
+}
+
+// RedelegationEntryResponse is equivalent to a RedelegationEntry except that it
+// contains a balance in addition to shares which is more suitable for client
+// responses.
+type RedelegationEntryResponse struct {
+ RedelegationEntry RedelegationEntry
+ Balance *big.Int
+}
+
+// Redelegation contains the list of a particular delegator's redelegating bonds
+// from a particular source validator to a particular destination validator.
+type Redelegation struct {
+ DelegatorAddress string
+ ValidatorSrcAddress string
+ ValidatorDstAddress string
+ Entries []RedelegationEntry
+}
+
+// RedelegationResponse is equivalent to a Redelegation except that its entries
+// contain a balance in addition to shares which is more suitable for client
+// responses.
+type RedelegationResponse struct {
+ Redelegation Redelegation
+ Entries []RedelegationEntryResponse
+}
+
+// RedelegationsInput is a struct to represent the input information for
+// the redelegations query. Needed to unpack arguments into the PageRequest struct.
+type RedelegationsInput struct {
+ DelegatorAddress common.Address
+ SrcValidatorAddress string
+ DstValidatorAddress string
+ PageRequest query.PageRequest
+}
+
+// RedelegationsOutput is a struct to represent the key information from
+// a redelegations response.
+type RedelegationsOutput struct {
+ Response []RedelegationResponse
+ PageResponse query.PageResponse
+}
+
+// FromResponse populates the RedelgationsOutput from a QueryRedelegationsResponse.
+func (ro *RedelegationsOutput) FromResponse(res *stakingtypes.QueryRedelegationsResponse) *RedelegationsOutput {
+ ro.Response = make([]RedelegationResponse, len(res.RedelegationResponses))
+ for i, resp := range res.RedelegationResponses {
+ // for each RedelegationResponse
+ // there's a RedelegationEntryResponse array ('Entries' field)
+ entries := make([]RedelegationEntryResponse, len(resp.Entries))
+ for j, e := range resp.Entries {
+ entries[j] = RedelegationEntryResponse{
+ RedelegationEntry: RedelegationEntry{
+ CreationHeight: e.RedelegationEntry.CreationHeight,
+ CompletionTime: e.RedelegationEntry.CompletionTime.Unix(),
+ InitialBalance: e.RedelegationEntry.InitialBalance.BigInt(),
+ SharesDst: e.RedelegationEntry.SharesDst.BigInt(),
+ },
+ Balance: e.Balance.BigInt(),
+ }
+ }
+
+ // the Redelegation field has also an 'Entries' field of type RedelegationEntry
+ redelEntries := make([]RedelegationEntry, len(resp.Redelegation.Entries))
+ for j, e := range resp.Redelegation.Entries {
+ redelEntries[j] = RedelegationEntry{
+ CreationHeight: e.CreationHeight,
+ CompletionTime: e.CompletionTime.Unix(),
+ InitialBalance: e.InitialBalance.BigInt(),
+ SharesDst: e.SharesDst.BigInt(),
+ }
+ }
+
+ ro.Response[i] = RedelegationResponse{
+ Entries: entries,
+ Redelegation: Redelegation{
+ DelegatorAddress: resp.Redelegation.DelegatorAddress,
+ ValidatorSrcAddress: resp.Redelegation.ValidatorSrcAddress,
+ ValidatorDstAddress: resp.Redelegation.ValidatorDstAddress,
+ Entries: redelEntries,
+ },
+ }
+ }
+
+ if res.Pagination != nil {
+ ro.PageResponse.Total = res.Pagination.Total
+ ro.PageResponse.NextKey = res.Pagination.NextKey
+ }
+
+ return ro
+}
+
+// Pack packs a given slice of abi arguments into a byte array.
+func (ro *RedelegationsOutput) Pack(args abi.Arguments) ([]byte, error) {
+ return args.Pack(ro.Response, ro.PageResponse)
+}
+
+// NewUnbondingDelegationRequest creates a new QueryUnbondingDelegationRequest instance and does sanity checks
+// on the given arguments before populating the request.
+func NewUnbondingDelegationRequest(args []interface{}) (*stakingtypes.QueryUnbondingDelegationRequest, error) {
+ if len(args) != 2 {
+ return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
+ }
+
+ delegatorAddr, ok := args[0].(common.Address)
+ if !ok || delegatorAddr == (common.Address{}) {
+ return nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorAddress, ok := args[1].(string)
+ if !ok {
+ return nil, fmt.Errorf(cmn.ErrInvalidType, "validatorAddress", "string", args[1])
+ }
+
+ return &stakingtypes.QueryUnbondingDelegationRequest{
+ DelegatorAddr: sdk.AccAddress(delegatorAddr.Bytes()).String(), // bech32 formatted
+ ValidatorAddr: validatorAddress,
+ }, nil
+}
+
+// checkDelegationUndelegationArgs checks the arguments for the delegation and undelegation functions.
+func checkDelegationUndelegationArgs(args []interface{}) (common.Address, string, *big.Int, error) {
+ if len(args) != 3 {
+ return common.Address{}, "", nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
+ }
+
+ delegatorAddr, ok := args[0].(common.Address)
+ if !ok || delegatorAddr == (common.Address{}) {
+ return common.Address{}, "", nil, fmt.Errorf(cmn.ErrInvalidDelegator, args[0])
+ }
+
+ validatorAddress, ok := args[1].(string)
+ if !ok {
+ return common.Address{}, "", nil, fmt.Errorf(cmn.ErrInvalidType, "validatorAddress", "string", args[1])
+ }
+
+ amount, ok := args[2].(*big.Int)
+ if !ok {
+ return common.Address{}, "", nil, fmt.Errorf(cmn.ErrInvalidAmount, args[2])
+ }
+
+ return delegatorAddr, validatorAddress, amount, nil
+}
+
+// FormatConsensusPubkey format ConsensusPubkey into a base64 string
+func FormatConsensusPubkey(consensusPubkey *codectypes.Any) string {
+ ed25519pk, ok := consensusPubkey.GetCachedValue().(cryptotypes.PubKey)
+ if ok {
+ return base64.StdEncoding.EncodeToString(ed25519pk.Bytes())
+ }
+ return consensusPubkey.String()
+}
diff --git a/precompiles/staking/utils_test.go b/precompiles/staking/utils_test.go
new file mode 100644
index 00000000..df169c1f
--- /dev/null
+++ b/precompiles/staking/utils_test.go
@@ -0,0 +1,579 @@
+package staking_test
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "slices"
+ "time"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "cosmossdk.io/math"
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/cometbft/cometbft/crypto/tmhash"
+ tmtypes "github.com/cometbft/cometbft/types"
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
+ "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
+ "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/testutil/mock"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ evmosapp "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/crypto/ethsecp256k1"
+ "github.com/evmos/evmos/v19/precompiles/authorization"
+ cmn "github.com/evmos/evmos/v19/precompiles/common"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/precompiles/testutil"
+ "github.com/evmos/evmos/v19/precompiles/testutil/contracts"
+ evmosutil "github.com/evmos/evmos/v19/testutil"
+ testutiltx "github.com/evmos/evmos/v19/testutil/tx"
+ evmostypes "github.com/evmos/evmos/v19/types"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ inflationtypes "github.com/evmos/evmos/v19/x/inflation/v1/types"
+ stakingkeeper "github.com/evmos/evmos/v19/x/staking/keeper"
+ vestingtypes "github.com/evmos/evmos/v19/x/vesting/types"
+)
+
+// stipend to pay EVM tx fees
+var accountGasCoverage = sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(1e16)))
+
+// SetupWithGenesisValSet initializes a new EvmosApp with a validator set and genesis accounts
+// that also act as delegators. For simplicity, each validator is bonded with a delegation
+// of one consensus engine unit (10^6) in the default token of the simapp from first genesis
+// account. A Nop logger is set in SimApp.
+func (s *PrecompileTestSuite) SetupWithGenesisValSet(valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) {
+ appI, genesisState := evmosapp.SetupTestingApp(cmn.DefaultChainID)()
+ app, ok := appI.(*evmosapp.Evmos)
+ s.Require().True(ok)
+
+ // set genesis accounts
+ authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
+ genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
+
+ validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
+ delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
+
+ bondAmt := sdk.TokensFromConsensusPower(1, evmostypes.PowerReduction)
+
+ for _, val := range valSet.Validators {
+ pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
+ s.Require().NoError(err)
+ pkAny, err := codectypes.NewAnyWithValue(pk)
+ s.Require().NoError(err)
+ validator := stakingtypes.Validator{
+ OperatorAddress: sdk.ValAddress(val.Address).String(),
+ ConsensusPubkey: pkAny,
+ Jailed: false,
+ Status: stakingtypes.Bonded,
+ Tokens: bondAmt,
+ DelegatorShares: math.LegacyOneDec(),
+ Description: stakingtypes.Description{},
+ UnbondingHeight: int64(0),
+ UnbondingTime: time.Unix(0, 0).UTC(),
+ Commission: stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 2)),
+ MinSelfDelegation: math.ZeroInt(),
+ }
+ validators = append(validators, validator)
+ delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), math.LegacyOneDec()))
+ }
+ s.validators = validators
+
+ // set validators and delegations
+ stakingParams := stakingtypes.DefaultParams()
+ // set bond demon to be aevmos
+ stakingParams.BondDenom = utils.BaseDenom
+ stakingGenesis := stakingtypes.NewGenesisState(stakingParams, validators, delegations)
+ genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
+
+ totalBondAmt := math.ZeroInt()
+ for range validators {
+ totalBondAmt = totalBondAmt.Add(bondAmt)
+ }
+ totalSupply := sdk.NewCoins()
+ for _, b := range balances {
+ // add genesis acc tokens and delegated tokens to total supply
+ totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(utils.BaseDenom, totalBondAmt))...)
+ }
+
+ // add bonded amount to bonded pool module account
+ balances = append(balances, banktypes.Balance{
+ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
+ Coins: sdk.Coins{sdk.NewCoin(utils.BaseDenom, totalBondAmt)},
+ })
+
+ // update total supply
+ bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{})
+ genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
+
+ stateBytes, err := json.MarshalIndent(genesisState, "", " ")
+ s.Require().NoError(err)
+
+ header := evmosutil.NewHeader(
+ 2,
+ time.Now().UTC(),
+ cmn.DefaultChainID,
+ sdk.ConsAddress(validators[0].GetOperator()),
+ tmhash.Sum([]byte("app")),
+ tmhash.Sum([]byte("validators")),
+ )
+
+ // init chain will set the validator set and initialize the genesis accounts
+ app.InitChain(
+ abci.RequestInitChain{
+ ChainId: cmn.DefaultChainID,
+ Validators: []abci.ValidatorUpdate{},
+ ConsensusParams: evmosapp.DefaultConsensusParams,
+ AppStateBytes: stateBytes,
+ },
+ )
+
+ // create Context
+ s.ctx = app.BaseApp.NewContext(false, header)
+
+ // commit genesis changes
+ app.Commit()
+ app.BeginBlock(abci.RequestBeginBlock{Header: header})
+
+ s.app = app
+}
+
+func (s *PrecompileTestSuite) DoSetupTest() {
+ nValidators := 3
+ signers := make(map[string]tmtypes.PrivValidator, nValidators)
+ validators := make([]*tmtypes.Validator, 0, nValidators)
+
+ for i := 0; i < nValidators; i++ {
+ privVal := mock.NewPV()
+ pubKey, err := privVal.GetPubKey()
+ s.Require().NoError(err)
+ signers[pubKey.Address().String()] = privVal
+ validator := tmtypes.NewValidator(pubKey, 1)
+ validators = append(validators, validator)
+ }
+
+ valSet := tmtypes.NewValidatorSet(validators)
+
+ // generate genesis account
+ addr, priv := testutiltx.NewAddrKey()
+ s.privKey = priv
+ s.address = addr
+ s.signer = testutiltx.NewSigner(priv)
+
+ baseAcc := authtypes.NewBaseAccount(priv.PubKey().Address().Bytes(), priv.PubKey(), 0, 0)
+
+ amount := sdk.TokensFromConsensusPower(5, evmostypes.PowerReduction)
+
+ balance := banktypes.Balance{
+ Address: baseAcc.GetAddress().String(),
+ Coins: sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, amount)),
+ }
+
+ s.SetupWithGenesisValSet(valSet, []authtypes.GenesisAccount{baseAcc}, balance)
+
+ // Create StateDB
+ s.stateDB = statedb.New(s.ctx, s.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.ctx.HeaderHash().Bytes())))
+
+ // bond denom
+ stakingParams := s.app.StakingKeeper.GetParams(s.ctx)
+ stakingParams.BondDenom = utils.BaseDenom
+ s.bondDenom = stakingParams.BondDenom
+ err := s.app.StakingKeeper.SetParams(s.ctx, stakingParams)
+ s.Require().NoError(err)
+
+ s.ethSigner = ethtypes.LatestSignerForChainID(s.app.EvmKeeper.ChainID())
+
+ precompile, err := staking.NewPrecompile(s.app.StakingKeeper, s.app.AuthzKeeper)
+ s.Require().NoError(err)
+ s.precompile = precompile
+
+ coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(5000000000000000000)))
+ distrCoins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, math.NewInt(2000000000000000000)))
+ err = s.app.BankKeeper.MintCoins(s.ctx, inflationtypes.ModuleName, coins)
+ s.Require().NoError(err)
+ err = s.app.BankKeeper.SendCoinsFromModuleToModule(s.ctx, inflationtypes.ModuleName, authtypes.FeeCollectorName, distrCoins)
+ s.Require().NoError(err)
+
+ queryHelperEvm := baseapp.NewQueryServerTestHelper(s.ctx, s.app.InterfaceRegistry())
+ evmtypes.RegisterQueryServer(queryHelperEvm, s.app.EvmKeeper)
+ s.queryClientEVM = evmtypes.NewQueryClient(queryHelperEvm)
+}
+
+// ApproveAndCheckAuthz is a helper function to approve a given authorization method and check if the authorization was created.
+func (s *PrecompileTestSuite) ApproveAndCheckAuthz(method abi.Method, msgType string, amount *big.Int) {
+ approveArgs := []interface{}{
+ s.address,
+ amount,
+ []string{msgType},
+ }
+ resp, err := s.precompile.Approve(s.ctx, s.address, s.stateDB, &method, approveArgs)
+ s.Require().NoError(err)
+ s.Require().Equal(resp, cmn.TrueValue)
+
+ auth, _ := s.CheckAuthorization(staking.DelegateAuthz, s.address, s.address)
+ s.Require().NotNil(auth)
+ s.Require().Equal(auth.AuthorizationType, staking.DelegateAuthz)
+ s.Require().Equal(auth.MaxTokens, &sdk.Coin{Denom: s.bondDenom, Amount: math.NewIntFromBigInt(amount)})
+}
+
+// CheckAuthorization is a helper function to check if the authorization is set and if it is the correct type.
+func (s *PrecompileTestSuite) CheckAuthorization(authorizationType stakingtypes.AuthorizationType, grantee, granter common.Address) (*stakingtypes.StakeAuthorization, *time.Time) {
+ stakingAuthz := stakingtypes.StakeAuthorization{AuthorizationType: authorizationType}
+ auth, expirationTime := s.app.AuthzKeeper.GetAuthorization(s.ctx, grantee.Bytes(), granter.Bytes(), stakingAuthz.MsgTypeURL())
+
+ stakeAuthorization, ok := auth.(*stakingtypes.StakeAuthorization)
+ if !ok {
+ return nil, expirationTime
+ }
+
+ return stakeAuthorization, expirationTime
+}
+
+// CreateAuthorization is a helper function to create a new authorization of the given type for a spender address
+// (=grantee).
+// The authorization will be created to spend the given Coin.
+// For testing purposes, this function will create a new authorization for all available validators,
+// that are not jailed.
+func (s *PrecompileTestSuite) CreateAuthorization(grantee common.Address, authzType stakingtypes.AuthorizationType, coin *sdk.Coin) error {
+ // Get all available validators and filter out jailed validators
+ validators := make([]sdk.ValAddress, 0)
+ s.app.StakingKeeper.IterateValidators(
+ s.ctx, func(_ int64, validator stakingtypes.ValidatorI) (stop bool) {
+ if validator.IsJailed() {
+ return
+ }
+ validators = append(validators, validator.GetOperator())
+ return
+ },
+ )
+
+ stakingAuthz, err := stakingtypes.NewStakeAuthorization(validators, nil, authzType, coin)
+ if err != nil {
+ return err
+ }
+
+ expiration := time.Now().Add(cmn.DefaultExpirationDuration).UTC()
+ err = s.app.AuthzKeeper.SaveGrant(s.ctx, grantee.Bytes(), s.address.Bytes(), stakingAuthz, &expiration)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// SetupApproval sets up an approval, that authorizes the grantee to spend the given amount for the granter
+// in transactions, that target the specified message types.
+func (s *PrecompileTestSuite) SetupApproval(
+ granterPriv types.PrivKey,
+ grantee common.Address,
+ amount *big.Int,
+ msgTypes []string,
+) {
+ approveArgs := contracts.CallArgs{
+ ContractAddr: s.precompile.Address(),
+ ContractABI: s.precompile.ABI,
+ PrivKey: granterPriv,
+ MethodName: authorization.ApproveMethod,
+ Args: []interface{}{
+ grantee, amount, msgTypes,
+ },
+ }
+
+ logCheckArgs := testutil.LogCheckArgs{
+ ABIEvents: s.precompile.Events,
+ ExpEvents: []string{authorization.EventTypeApproval},
+ ExpPass: true,
+ }
+
+ res, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, approveArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while calling the contract to approve")
+
+ s.NextBlock()
+
+ // Check if the approval event is emitted
+ granterAddr := common.BytesToAddress(granterPriv.PubKey().Address().Bytes())
+ testutil.CheckAuthorizationEvents(
+ s.precompile.Events[authorization.EventTypeApproval],
+ s.precompile.Address(),
+ granterAddr,
+ grantee,
+ res,
+ s.ctx.BlockHeight()-1,
+ msgTypes,
+ amount,
+ )
+}
+
+// SetupApprovalWithContractCalls is a helper function used to setup the allowance for the given spender.
+func (s *PrecompileTestSuite) SetupApprovalWithContractCalls(approvalArgs contracts.CallArgs) {
+ msgTypes, ok := approvalArgs.Args[1].([]string)
+ Expect(ok).To(BeTrue(), "failed to convert msgTypes to []string")
+ expAmount, ok := approvalArgs.Args[2].(*big.Int)
+ Expect(ok).To(BeTrue(), "failed to convert amount to big.Int")
+
+ logCheckArgs := testutil.LogCheckArgs{
+ ABIEvents: s.precompile.Events,
+ ExpEvents: []string{authorization.EventTypeApproval},
+ ExpPass: true,
+ }
+
+ _, _, err := contracts.CallContractAndCheckLogs(s.ctx, s.app, approvalArgs, logCheckArgs)
+ Expect(err).To(BeNil(), "error while approving: %v", err)
+
+ // get granter address from private key provided
+ pk, ok := approvalArgs.PrivKey.(*ethsecp256k1.PrivKey)
+ Expect(ok).To(BeTrue(), fmt.Sprintf("expected a ethsecp256k1.PrivKey, but got %T", approvalArgs.PrivKey))
+ key, err := pk.ToECDSA()
+ Expect(err).To(BeNil())
+ granter := crypto.PubkeyToAddress(key.PublicKey)
+
+ // iterate over args
+ var expectedAuthz stakingtypes.AuthorizationType
+ for _, msgType := range msgTypes {
+ switch msgType {
+ case staking.DelegateMsg:
+ expectedAuthz = staking.DelegateAuthz
+ case staking.UndelegateMsg:
+ expectedAuthz = staking.UndelegateAuthz
+ case staking.RedelegateMsg:
+ expectedAuthz = staking.RedelegateAuthz
+ case staking.CancelUnbondingDelegationMsg:
+ expectedAuthz = staking.CancelUnbondingDelegationAuthz
+ }
+ authz, expirationTime := s.CheckAuthorization(expectedAuthz, approvalArgs.ContractAddr, granter)
+ Expect(authz).ToNot(BeNil(), "expected authorization to be set")
+ Expect(authz.MaxTokens.Amount).To(Equal(math.NewInt(expAmount.Int64())), "expected different allowance")
+ Expect(authz.MsgTypeURL()).To(Equal(msgType), "expected different message type")
+ Expect(expirationTime).ToNot(BeNil(), "expected expiration time to not be nil")
+ }
+}
+
+// DeployContract deploys a contract that calls the staking precompile's methods for testing purposes.
+func (s *PrecompileTestSuite) DeployContract(contract evmtypes.CompiledContract) (addr common.Address, err error) {
+ addr, err = evmosutil.DeployContract(
+ s.ctx,
+ s.app,
+ s.privKey,
+ s.queryClientEVM,
+ contract,
+ )
+ return
+}
+
+// NextBlock commits the current block and sets up the next block.
+func (s *PrecompileTestSuite) NextBlock() {
+ s.NextBlockAfter(time.Second)
+}
+
+// NextBlock commits the current block and sets up the next block.
+func (s *PrecompileTestSuite) NextBlockAfter(t time.Duration) {
+ var err error
+ s.ctx, err = evmosutil.CommitAndCreateNewCtx(s.ctx, s.app, t, nil)
+ Expect(err).To(BeNil(), "failed to commit block")
+}
+
+// CheckAllowanceChangeEvent is a helper function used to check the allowance change event arguments.
+func (s *PrecompileTestSuite) CheckAllowanceChangeEvent(log *ethtypes.Log, methods []string, amounts []*big.Int) {
+ s.Require().Equal(log.Address, s.precompile.Address())
+ // Check event signature matches the one emitted
+ event := s.precompile.ABI.Events[authorization.EventTypeAllowanceChange]
+ s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
+ s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))
+
+ var approvalEvent authorization.EventAllowanceChange
+ err := cmn.UnpackLog(s.precompile.ABI, &approvalEvent, authorization.EventTypeAllowanceChange, *log)
+ s.Require().NoError(err)
+ s.Require().Equal(s.address, approvalEvent.Grantee)
+ s.Require().Equal(s.address, approvalEvent.Granter)
+ s.Require().Equal(len(methods), len(approvalEvent.Methods))
+
+ for i, method := range methods {
+ s.Require().Equal(method, approvalEvent.Methods[i])
+ s.Require().Equal(amounts[i], approvalEvent.Values[i])
+ }
+}
+
+// ExpectAuthorization is a helper function for tests using the Ginkgo BDD style tests, to check that the
+// authorization is correctly set.
+func (s *PrecompileTestSuite) ExpectAuthorization(authorizationType stakingtypes.AuthorizationType, grantee, granter common.Address, maxTokens *sdk.Coin) {
+ authz, expirationTime := s.CheckAuthorization(authorizationType, grantee, granter)
+ Expect(authz).ToNot(BeNil(), "expected authorization to be set")
+ Expect(authz.AuthorizationType).To(Equal(authorizationType), "expected different authorization type")
+ Expect(authz.MaxTokens).To(Equal(maxTokens), "expected different max tokens")
+ Expect(expirationTime).ToNot(BeNil(), "expected expiration time to be not be nil")
+}
+
+// assertValidatorsResponse asserts all the fields on the validators response
+func (s *PrecompileTestSuite) assertValidatorsResponse(validators []staking.ValidatorInfo, expLen int) {
+ // returning order can change
+ valOrder := []int{0, 1}
+ varAddr := sdk.ValAddress(common.HexToAddress(validators[0].OperatorAddress).Bytes()).String()
+ if varAddr != s.validators[0].OperatorAddress {
+ valOrder = []int{1, 0}
+ }
+ for i := 0; i < expLen; i++ {
+ j := valOrder[i]
+
+ s.Require().Equal(s.validators[j].OperatorAddress, sdk.ValAddress(common.HexToAddress(validators[i].OperatorAddress).Bytes()).String())
+ s.Require().Equal(uint8(s.validators[j].Status), validators[i].Status)
+ s.Require().Equal(s.validators[j].Tokens.Uint64(), validators[i].Tokens.Uint64())
+ s.Require().Equal(s.validators[j].DelegatorShares.BigInt(), validators[i].DelegatorShares)
+ s.Require().Equal(s.validators[j].Jailed, validators[i].Jailed)
+ s.Require().Equal(s.validators[j].UnbondingHeight, validators[i].UnbondingHeight)
+ s.Require().Equal(int64(0), validators[i].UnbondingTime)
+ s.Require().Equal(int64(0), validators[i].Commission.Int64())
+ s.Require().Equal(int64(0), validators[i].MinSelfDelegation.Int64())
+ s.Require().Equal(validators[i].ConsensusPubkey, staking.FormatConsensusPubkey(s.validators[j].ConsensusPubkey))
+ }
+}
+
+// assertRedelegation asserts the redelegationOutput struct and its fields
+func (s *PrecompileTestSuite) assertRedelegationsOutput(data []byte, redelTotalCount uint64, expAmt *big.Int, expCreationHeight int64, hasPagination bool) {
+ var redOut staking.RedelegationsOutput
+ err := s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationsMethod, data)
+ s.Require().NoError(err, "failed to unpack output")
+
+ s.Require().Len(redOut.Response, 1)
+ // check pagination - total count should be 2
+ s.Require().Equal(redelTotalCount, redOut.PageResponse.Total)
+ if hasPagination {
+ s.Require().NotEmpty(redOut.PageResponse.NextKey)
+ } else {
+ s.Require().Empty(redOut.PageResponse.NextKey)
+ }
+ // check redelegation entry
+ // order may change, one redelegation has 2 entries
+ // and the other has one
+ if len(redOut.Response[0].Entries) == 2 {
+ s.assertRedelegation(redOut.Response[0],
+ 2,
+ s.validators[0].OperatorAddress,
+ s.validators[1].OperatorAddress,
+ expAmt,
+ expCreationHeight,
+ )
+ } else {
+ s.assertRedelegation(redOut.Response[0],
+ 1,
+ s.validators[0].OperatorAddress,
+ sdk.ValAddress(s.address.Bytes()).String(),
+ expAmt,
+ expCreationHeight,
+ )
+ }
+}
+
+// assertRedelegation asserts all the fields on the redelegations response
+// should specify the amount of entries expected and the expected amount for this
+// the same amount is considered for all entries
+func (s *PrecompileTestSuite) assertRedelegation(res staking.RedelegationResponse, entriesCount int, expValSrcAddr, expValDstAddr string, expAmt *big.Int, expCreationHeight int64) {
+ // check response
+ s.Require().Equal(res.Redelegation.DelegatorAddress, sdk.AccAddress(s.address.Bytes()).String())
+ s.Require().Equal(res.Redelegation.ValidatorSrcAddress, expValSrcAddr)
+ s.Require().Equal(res.Redelegation.ValidatorDstAddress, expValDstAddr)
+ // check redelegation entries - should be empty
+ s.Require().Empty(res.Redelegation.Entries)
+ // check response entries, should be 2
+ s.Require().Len(res.Entries, entriesCount)
+ // check redelegation entries
+ for _, e := range res.Entries {
+ s.Require().Equal(e.Balance, expAmt)
+ s.Require().True(e.RedelegationEntry.CompletionTime > 1600000000)
+ s.Require().Equal(expCreationHeight, e.RedelegationEntry.CreationHeight)
+ s.Require().Equal(e.RedelegationEntry.InitialBalance, expAmt)
+ }
+}
+
+// setupRedelegations setups 2 entries for redelegation from validator[0]
+// to validator[1], creates a validator using s.address
+// and creates a redelegation from validator[0] to the new validator
+func (s *PrecompileTestSuite) setupRedelegations(redelAmt *big.Int) error {
+ msg := stakingtypes.MsgBeginRedelegate{
+ DelegatorAddress: sdk.AccAddress(s.address.Bytes()).String(),
+ ValidatorSrcAddress: s.validators[0].OperatorAddress,
+ ValidatorDstAddress: s.validators[1].OperatorAddress,
+ Amount: sdk.NewCoin(s.bondDenom, math.NewIntFromBigInt(redelAmt)),
+ }
+
+ msgSrv := stakingkeeper.NewMsgServerImpl(&s.app.StakingKeeper)
+ // create 2 entries for same redelegation
+ for i := 0; i < 2; i++ {
+ if _, err := msgSrv.BeginRedelegate(s.ctx, &msg); err != nil {
+ return err
+ }
+ }
+
+ // create a validator with s.address and s.privKey
+ // then create a redelegation from validator[0] to this new validator
+ testutil.CreateValidator(s.ctx, s.T(), s.privKey.PubKey(), *s.app.StakingKeeper.Keeper, math.NewInt(100))
+ msg.ValidatorDstAddress = sdk.ValAddress(s.address.Bytes()).String()
+ _, err := msgSrv.BeginRedelegate(s.ctx, &msg)
+ return err
+}
+
+// CheckValidatorOutput checks that the given validator output
+func (s *PrecompileTestSuite) CheckValidatorOutput(valOut staking.ValidatorInfo) {
+ validatorAddrs := make([]string, len(s.validators))
+ for i, v := range s.validators {
+ validatorAddrs[i] = v.OperatorAddress
+ }
+
+ operatorAddress := sdk.ValAddress(common.HexToAddress(valOut.OperatorAddress).Bytes()).String()
+
+ Expect(slices.Contains(validatorAddrs, operatorAddress)).To(BeTrue(), "operator address not found in test suite validators")
+ Expect(valOut.DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares")
+}
+
+// setupVestingAccount is a helper function used in integraiton tests to setup a vesting account
+// using the TestVestingSchedule. Also, funds the account with extra funds to pay for transaction fees
+func (s *PrecompileTestSuite) setupVestingAccount(funder, vestAcc sdk.AccAddress) *vestingtypes.ClawbackVestingAccount {
+ vestingAmtTotal := evmosutil.TestVestingSchedule.TotalVestingCoins
+
+ vestingStart := s.ctx.BlockTime()
+ baseAccount := authtypes.NewBaseAccountWithAddress(vestAcc.Bytes())
+ clawbackAccount := vestingtypes.NewClawbackVestingAccount(
+ baseAccount,
+ funder,
+ vestingAmtTotal,
+ vestingStart,
+ evmosutil.TestVestingSchedule.LockupPeriods,
+ evmosutil.TestVestingSchedule.VestingPeriods,
+ )
+
+ err := evmosutil.FundAccount(s.ctx, s.app.BankKeeper, clawbackAccount.GetAddress(), vestingAmtTotal)
+ Expect(err).To(BeNil())
+ acc := s.app.AccountKeeper.NewAccount(s.ctx, clawbackAccount)
+ s.app.AccountKeeper.SetAccount(s.ctx, acc)
+
+ // Check all coins are locked up
+ lockedUp := clawbackAccount.GetLockedUpCoins(s.ctx.BlockTime())
+ Expect(vestingAmtTotal).To(Equal(lockedUp))
+
+ // Grant gas stipend to cover EVM fees
+ err = evmosutil.FundAccount(s.ctx, s.app.BankKeeper, clawbackAccount.GetAddress(), accountGasCoverage)
+ Expect(err).To(BeNil())
+ granteeBalance := s.app.BankKeeper.GetBalance(s.ctx, clawbackAccount.GetAddress(), s.bondDenom)
+ Expect(granteeBalance).To(Equal(accountGasCoverage[0].Add(vestingAmtTotal[0])))
+
+ return clawbackAccount
+}
+
+// Generate the Base64 encoded PubKey associated with a PrivKey generated with
+// the ed25519 algorithm used in Tendermint nodes.
+func GenerateBase64PubKey() string {
+ privKey := ed25519.GenPrivKey()
+ pubKey := privKey.PubKey().(*ed25519.PubKey)
+ return base64.StdEncoding.EncodeToString(pubKey.Bytes())
+}
diff --git a/precompiles/testutil/abci.go b/precompiles/testutil/abci.go
new file mode 100644
index 00000000..aee0ec4c
--- /dev/null
+++ b/precompiles/testutil/abci.go
@@ -0,0 +1,259 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package testutil
+
+import (
+ "time"
+
+ errorsmod "cosmossdk.io/errors"
+ sdkmath "cosmossdk.io/math"
+ abci "github.com/cometbft/cometbft/abci/types"
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ tmtypes "github.com/cometbft/cometbft/types"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+ "github.com/evmos/os/testutil/tx"
+)
+
+// Commit commits a block at a given time. Reminder: At the end of each
+// Tendermint Consensus round the following methods are run
+// 1. BeginBlock
+// 2. DeliverTx
+// 3. EndBlock
+// 4. Commit
+func Commit(ctx sdk.Context, app *example_app.ExampleChain, t time.Duration, vs *tmtypes.ValidatorSet) (sdk.Context, error) {
+ header, err := commit(ctx, app, t, vs)
+ if err != nil {
+ return ctx, err
+ }
+
+ return ctx.WithBlockHeader(header), nil
+}
+
+// CommitAndCreateNewCtx commits a block at a given time creating a ctx with the current settings
+// This is useful to keep test settings that could be affected by EndBlockers, e.g.
+// setting a baseFee == 0 and expecting this condition to continue after commit
+func CommitAndCreateNewCtx(ctx sdk.Context, app *example_app.ExampleChain, t time.Duration, vs *tmtypes.ValidatorSet) (sdk.Context, error) {
+ header, err := commit(ctx, app, t, vs)
+ if err != nil {
+ return ctx, err
+ }
+
+ // NewContext function keeps the multistore
+ // but resets other context fields
+ // GasMeter is set as InfiniteGasMeter
+ newCtx := app.BaseApp.NewContext(false, header)
+ // set the reseted fields to keep the current ctx settings
+ newCtx = newCtx.WithMinGasPrices(ctx.MinGasPrices())
+ newCtx = newCtx.WithEventManager(ctx.EventManager())
+ newCtx = newCtx.WithKVGasConfig(ctx.KVGasConfig())
+ newCtx = newCtx.WithTransientKVGasConfig(ctx.TransientKVGasConfig())
+
+ return newCtx, nil
+}
+
+// DeliverTx delivers a cosmos tx for a given set of msgs
+func DeliverTx(
+ ctx sdk.Context,
+ appEvmos *example_app.ExampleChain,
+ priv cryptotypes.PrivKey,
+ gasPrice *sdkmath.Int,
+ msgs ...sdk.Msg,
+) (abci.ResponseDeliverTx, error) {
+ txConfig := encoding.MakeConfig(example_app.ModuleBasics).TxConfig
+ tx, err := tx.PrepareCosmosTx(
+ ctx,
+ appEvmos,
+ tx.CosmosTxArgs{
+ TxCfg: txConfig,
+ Priv: priv,
+ ChainID: ctx.ChainID(),
+ Gas: 10_000_000,
+ GasPrice: gasPrice,
+ Msgs: msgs,
+ },
+ )
+ if err != nil {
+ return abci.ResponseDeliverTx{}, err
+ }
+ return BroadcastTxBytes(appEvmos, txConfig.TxEncoder(), tx)
+}
+
+// DeliverEthTx generates and broadcasts a Cosmos Tx populated with MsgEthereumTx messages.
+// If a private key is provided, it will attempt to sign all messages with the given private key,
+// otherwise, it will assume the messages have already been signed.
+func DeliverEthTx(
+ appEvmos *example_app.ExampleChain,
+ priv cryptotypes.PrivKey,
+ msgs ...sdk.Msg,
+) (abci.ResponseDeliverTx, error) {
+ txConfig := encoding.MakeConfig(example_app.ModuleBasics).TxConfig
+
+ tx, err := tx.PrepareEthTx(txConfig, appEvmos, priv, msgs...)
+ if err != nil {
+ return abci.ResponseDeliverTx{}, err
+ }
+ res, err := BroadcastTxBytes(appEvmos, txConfig.TxEncoder(), tx)
+ if err != nil {
+ return res, err
+ }
+
+ codec := encoding.MakeConfig(example_app.ModuleBasics).Codec
+ if _, err := CheckEthTxResponse(res, codec); err != nil {
+ return res, err
+ }
+ return res, nil
+}
+
+// DeliverEthTxWithoutCheck generates and broadcasts a Cosmos Tx populated with MsgEthereumTx messages.
+// If a private key is provided, it will attempt to sign all messages with the given private key,
+// otherwise, it will assume the messages have already been signed. It does not check if the Eth tx is
+// successful or not.
+func DeliverEthTxWithoutCheck(
+ appEvmos *example_app.ExampleChain,
+ priv cryptotypes.PrivKey,
+ msgs ...sdk.Msg,
+) (abci.ResponseDeliverTx, error) {
+ txConfig := encoding.MakeConfig(example_app.ModuleBasics).TxConfig
+
+ tx, err := tx.PrepareEthTx(txConfig, appEvmos, priv, msgs...)
+ if err != nil {
+ return abci.ResponseDeliverTx{}, err
+ }
+
+ res, err := BroadcastTxBytes(appEvmos, txConfig.TxEncoder(), tx)
+ if err != nil {
+ return abci.ResponseDeliverTx{}, err
+ }
+
+ return res, nil
+}
+
+// CheckTx checks a cosmos tx for a given set of msgs
+func CheckTx(
+ ctx sdk.Context,
+ appEvmos *example_app.ExampleChain,
+ priv cryptotypes.PrivKey,
+ gasPrice *sdkmath.Int,
+ msgs ...sdk.Msg,
+) (abci.ResponseCheckTx, error) {
+ txConfig := encoding.MakeConfig(example_app.ModuleBasics).TxConfig
+
+ tx, err := tx.PrepareCosmosTx(
+ ctx,
+ appEvmos,
+ tx.CosmosTxArgs{
+ TxCfg: txConfig,
+ Priv: priv,
+ ChainID: ctx.ChainID(),
+ GasPrice: gasPrice,
+ Gas: 10_000_000,
+ Msgs: msgs,
+ },
+ )
+ if err != nil {
+ return abci.ResponseCheckTx{}, err
+ }
+ return checkTxBytes(appEvmos, txConfig.TxEncoder(), tx)
+}
+
+// CheckEthTx checks a Ethereum tx for a given set of msgs
+func CheckEthTx(
+ appEvmos *example_app.ExampleChain,
+ priv cryptotypes.PrivKey,
+ msgs ...sdk.Msg,
+) (abci.ResponseCheckTx, error) {
+ txConfig := encoding.MakeConfig(example_app.ModuleBasics).TxConfig
+
+ tx, err := tx.PrepareEthTx(txConfig, appEvmos, priv, msgs...)
+ if err != nil {
+ return abci.ResponseCheckTx{}, err
+ }
+ return checkTxBytes(appEvmos, txConfig.TxEncoder(), tx)
+}
+
+// BroadcastTxBytes encodes a transaction and calls DeliverTx on the app.
+func BroadcastTxBytes(app *example_app.ExampleChain, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.ResponseDeliverTx, error) {
+ // bz are bytes to be broadcasted over the network
+ bz, err := txEncoder(tx)
+ if err != nil {
+ return abci.ResponseDeliverTx{}, err
+ }
+
+ req := abci.RequestDeliverTx{Tx: bz}
+ res := app.BaseApp.DeliverTx(req)
+ if res.Code != 0 {
+ return abci.ResponseDeliverTx{}, errorsmod.Wrapf(errortypes.ErrInvalidRequest, res.Log)
+ }
+
+ return res, nil
+}
+
+// commit is a private helper function that runs the EndBlocker logic, commits the changes,
+// updates the header, runs the BeginBlocker function and returns the updated header
+func commit(ctx sdk.Context, app *example_app.ExampleChain, t time.Duration, vs *tmtypes.ValidatorSet) (tmproto.Header, error) {
+ header := ctx.BlockHeader()
+
+ if vs != nil {
+ res := app.EndBlock(abci.RequestEndBlock{Height: header.Height})
+
+ nextVals, err := applyValSetChanges(vs, res.ValidatorUpdates)
+ if err != nil {
+ return header, err
+ }
+ header.ValidatorsHash = vs.Hash()
+ header.NextValidatorsHash = nextVals.Hash()
+ } else {
+ app.EndBlocker(ctx, abci.RequestEndBlock{Height: header.Height})
+ }
+
+ _ = app.Commit()
+
+ header.Height++
+ header.Time = header.Time.Add(t)
+ header.AppHash = app.LastCommitID().Hash
+
+ app.BeginBlock(abci.RequestBeginBlock{
+ Header: header,
+ })
+
+ return header, nil
+}
+
+// checkTxBytes encodes a transaction and calls checkTx on the app.
+func checkTxBytes(app *example_app.ExampleChain, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.ResponseCheckTx, error) {
+ bz, err := txEncoder(tx)
+ if err != nil {
+ return abci.ResponseCheckTx{}, err
+ }
+
+ req := abci.RequestCheckTx{Tx: bz}
+ res := app.BaseApp.CheckTx(req)
+ if res.Code != 0 {
+ return abci.ResponseCheckTx{}, errorsmod.Wrapf(errortypes.ErrInvalidRequest, res.Log)
+ }
+
+ return res, nil
+}
+
+// applyValSetChanges takes in tmtypes.ValidatorSet and []abci.ValidatorUpdate and will return a new tmtypes.ValidatorSet which has the
+// provided validator updates applied to the provided validator set.
+func applyValSetChanges(valSet *tmtypes.ValidatorSet, valUpdates []abci.ValidatorUpdate) (*tmtypes.ValidatorSet, error) {
+ updates, err := tmtypes.PB2TM.ValidatorUpdates(valUpdates)
+ if err != nil {
+ return nil, err
+ }
+
+ // must copy since validator set will mutate with UpdateWithChangeSet
+ newVals := valSet.Copy()
+ err = newVals.UpdateWithChangeSet(updates)
+ if err != nil {
+ return nil, err
+ }
+
+ return newVals, nil
+}
diff --git a/precompiles/testutil/ante.go b/precompiles/testutil/ante.go
new file mode 100644
index 00000000..846520b1
--- /dev/null
+++ b/precompiles/testutil/ante.go
@@ -0,0 +1,36 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package testutil
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+)
+
+// NextFn is a no-op function that returns the context and no error in order to mock
+// the next function in the AnteHandler chain.
+//
+// It can be used in unit tests when calling a decorator's AnteHandle method, e.g.
+// `dec.AnteHandle(ctx, tx, false, NextFn)`
+func NextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
+ return ctx, nil
+}
+
+// ValidateAnteForMsgs is a helper function, which takes in an AnteDecorator as well as 1 or
+// more messages, builds a transaction containing these messages, and returns any error that
+// the AnteHandler might return.
+func ValidateAnteForMsgs(ctx sdk.Context, dec sdk.AnteDecorator, msgs ...sdk.Msg) error {
+ encodingConfig := encoding.MakeConfig(example_app.ModuleBasics)
+ txBuilder := encodingConfig.TxConfig.NewTxBuilder()
+ err := txBuilder.SetMsgs(msgs...)
+ if err != nil {
+ return err
+ }
+
+ tx := txBuilder.GetTx()
+
+ // Call Ante decorator
+ _, err = dec.AnteHandle(ctx, tx, false, NextFn)
+ return err
+}
diff --git a/precompiles/testutil/contract.go b/precompiles/testutil/contract.go
new file mode 100644
index 00000000..f425169a
--- /dev/null
+++ b/precompiles/testutil/contract.go
@@ -0,0 +1,161 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package testutil
+
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/cosmos/gogoproto/proto"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/cosmos/cosmos-sdk/codec"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ example_app "github.com/evmos/os/example_chain"
+ "github.com/evmos/os/testutil/tx"
+ evm "github.com/evmos/os/x/evm/types"
+)
+
+// ContractArgs are the params used for calling a smart contract.
+type ContractArgs struct {
+ // Addr is the address of the contract to call.
+ Addr common.Address
+ // ABI is the ABI of the contract to call.
+ ABI abi.ABI
+ // MethodName is the name of the method to call.
+ MethodName string
+ // Args are the arguments to pass to the method.
+ Args []interface{}
+}
+
+// ContractCallArgs is the arguments for calling a smart contract.
+type ContractCallArgs struct {
+ // Contract are the contract-specific arguments required for the contract call.
+ Contract ContractArgs
+ // Nonce is the nonce to use for the transaction.
+ Nonce *big.Int
+ // Amount is the aevmos amount to send in the transaction.
+ Amount *big.Int
+ // GasLimit to use for the transaction
+ GasLimit uint64
+ // PrivKey is the private key to be used for the transaction.
+ PrivKey cryptotypes.PrivKey
+}
+
+// DeployContract deploys a contract with the provided private key,
+// compiled contract data and constructor arguments
+func DeployContract(
+ ctx sdk.Context,
+ evmosApp *example_app.ExampleChain,
+ priv cryptotypes.PrivKey,
+ queryClientEvm evm.QueryClient,
+ contract evm.CompiledContract,
+ constructorArgs ...interface{},
+) (common.Address, error) {
+ chainID := evmosApp.EVMKeeper.ChainID()
+ from := common.BytesToAddress(priv.PubKey().Address().Bytes())
+ nonce := evmosApp.EVMKeeper.GetNonce(ctx, from)
+
+ ctorArgs, err := contract.ABI.Pack("", constructorArgs...)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ data := append(contract.Bin, ctorArgs...) //nolint:gocritic
+ gas, err := tx.GasLimit(ctx, from, data, queryClientEvm)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ msgEthereumTx := evm.NewTx(&evm.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ GasLimit: gas,
+ GasFeeCap: evmosApp.FeeMarketKeeper.GetBaseFee(ctx),
+ GasTipCap: big.NewInt(1),
+ Input: data,
+ Accesses: ðtypes.AccessList{},
+ })
+ msgEthereumTx.From = from.String()
+
+ res, err := DeliverEthTx(evmosApp, priv, msgEthereumTx)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ if _, err := CheckEthTxResponse(res, evmosApp.AppCodec()); err != nil {
+ return common.Address{}, err
+ }
+
+ return crypto.CreateAddress(from, nonce), nil
+}
+
+// DeployContractWithFactory deploys a contract using a contract factory
+// with the provided factoryAddress
+func DeployContractWithFactory(
+ ctx sdk.Context,
+ evmosApp *example_app.ExampleChain,
+ priv cryptotypes.PrivKey,
+ factoryAddress common.Address,
+) (common.Address, abci.ResponseDeliverTx, error) {
+ chainID := evmosApp.EVMKeeper.ChainID()
+ from := common.BytesToAddress(priv.PubKey().Address().Bytes())
+ factoryNonce := evmosApp.EVMKeeper.GetNonce(ctx, factoryAddress)
+ nonce := evmosApp.EVMKeeper.GetNonce(ctx, from)
+
+ msgEthereumTx := evm.NewTx(&evm.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ To: &factoryAddress,
+ GasLimit: uint64(100000),
+ GasPrice: big.NewInt(1000000000),
+ })
+ msgEthereumTx.From = from.String()
+
+ res, err := DeliverEthTx(evmosApp, priv, msgEthereumTx)
+ if err != nil {
+ return common.Address{}, abci.ResponseDeliverTx{}, err
+ }
+
+ if _, err := CheckEthTxResponse(res, evmosApp.AppCodec()); err != nil {
+ return common.Address{}, abci.ResponseDeliverTx{}, err
+ }
+
+ return crypto.CreateAddress(factoryAddress, factoryNonce), res, err
+}
+
+// CheckEthTxResponse checks that the transaction was executed successfully
+func CheckEthTxResponse(r abci.ResponseDeliverTx, cdc codec.Codec) ([]*evm.MsgEthereumTxResponse, error) {
+ if !r.IsOK() {
+ return nil, fmt.Errorf("tx failed. Code: %d, Logs: %s", r.Code, r.Log)
+ }
+
+ var txData sdk.TxMsgData
+ if err := cdc.Unmarshal(r.Data, &txData); err != nil {
+ return nil, err
+ }
+
+ if len(txData.MsgResponses) == 0 {
+ return nil, fmt.Errorf("no message responses found")
+ }
+
+ responses := make([]*evm.MsgEthereumTxResponse, 0, len(txData.MsgResponses))
+ for i := range txData.MsgResponses {
+ var res evm.MsgEthereumTxResponse
+ if err := proto.Unmarshal(txData.MsgResponses[i].Value, &res); err != nil {
+ return nil, err
+ }
+
+ if res.Failed() {
+ return nil, fmt.Errorf("tx failed. VmError: %s", res.VmError)
+ }
+ responses = append(responses, &res)
+ }
+
+ return responses, nil
+}
diff --git a/precompiles/testutil/contracts/Counter.json b/precompiles/testutil/contracts/Counter.json
new file mode 100644
index 00000000..597e282a
--- /dev/null
+++ b/precompiles/testutil/contracts/Counter.json
@@ -0,0 +1,64 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "Counter",
+ "sourceName": "solidity/precompiles/testutil/contracts/Counter.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ }
+ ],
+ "name": "Added",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ }
+ ],
+ "name": "Changed",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "add",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getCounter",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "subtract",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x60806040526000805534801561001457600080fd5b50610397806100246000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80634f2be91f146100465780636deebae3146100505780638ada066e1461005a575b600080fd5b61004e610078565b005b610058610103565b005b6100626101d2565b60405161006f91906101f4565b60405180910390f35b60008081548092919061008a9061023e565b91905055507f64a55044d1f2eddebe1b90e8e2853e8e96931cefadbfa0b2ceb34bee360619416000546040516100c091906101f4565b60405180910390a17f938d2ee5be9cfb0f7270ee2eff90507e94b37625d9d2b3a61c97d30a4560b8296000546040516100f991906101f4565b60405180910390a1565b60008054116040518060400160405280600f81526020017f434f554e5445525f544f4f5f4c4f5700000000000000000000000000000000008152509061017f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101769190610316565b60405180910390fd5b5060008081548092919061019290610338565b91905055507f938d2ee5be9cfb0f7270ee2eff90507e94b37625d9d2b3a61c97d30a4560b8296000546040516101c891906101f4565b60405180910390a1565b60008054905090565b6000819050919050565b6101ee816101db565b82525050565b600060208201905061020960008301846101e5565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610249826101db565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361027b5761027a61020f565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b60005b838110156102c05780820151818401526020810190506102a5565b60008484015250505050565b6000601f19601f8301169050919050565b60006102e882610286565b6102f28185610291565b93506103028185602086016102a2565b61030b816102cc565b840191505092915050565b6000602082019050818103600083015261033081846102dd565b905092915050565b6000610343826101db565b9150600082036103565761035561020f565b5b60018203905091905056fea26469706673582212202870b2d78304eb0ec6b95f72bacf96e449481ecaa4d58a3ce786c1cba532075d64736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80634f2be91f146100465780636deebae3146100505780638ada066e1461005a575b600080fd5b61004e610078565b005b610058610103565b005b6100626101d2565b60405161006f91906101f4565b60405180910390f35b60008081548092919061008a9061023e565b91905055507f64a55044d1f2eddebe1b90e8e2853e8e96931cefadbfa0b2ceb34bee360619416000546040516100c091906101f4565b60405180910390a17f938d2ee5be9cfb0f7270ee2eff90507e94b37625d9d2b3a61c97d30a4560b8296000546040516100f991906101f4565b60405180910390a1565b60008054116040518060400160405280600f81526020017f434f554e5445525f544f4f5f4c4f5700000000000000000000000000000000008152509061017f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101769190610316565b60405180910390fd5b5060008081548092919061019290610338565b91905055507f938d2ee5be9cfb0f7270ee2eff90507e94b37625d9d2b3a61c97d30a4560b8296000546040516101c891906101f4565b60405180910390a1565b60008054905090565b6000819050919050565b6101ee816101db565b82525050565b600060208201905061020960008301846101e5565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610249826101db565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361027b5761027a61020f565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b60005b838110156102c05780820151818401526020810190506102a5565b60008484015250505050565b6000601f19601f8301169050919050565b60006102e882610286565b6102f28185610291565b93506103028185602086016102a2565b61030b816102cc565b840191505092915050565b6000602082019050818103600083015261033081846102dd565b905092915050565b6000610343826101db565b9150600082036103565761035561020f565b5b60018203905091905056fea26469706673582212202870b2d78304eb0ec6b95f72bacf96e449481ecaa4d58a3ce786c1cba532075d64736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/testutil/contracts/Counter.sol b/precompiles/testutil/contracts/Counter.sol
new file mode 100644
index 00000000..0025c5e2
--- /dev/null
+++ b/precompiles/testutil/contracts/Counter.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0
+
+pragma solidity >=0.7.0 <0.9.0;
+
+contract Counter {
+ uint256 counter = 0;
+ string internal constant ERROR_TOO_LOW = "COUNTER_TOO_LOW";
+ event Changed(uint256 counter);
+ event Added(uint256 counter);
+
+ function add() public {
+ counter++;
+ emit Added(counter);
+ emit Changed(counter);
+ }
+
+ function subtract() public {
+ require(counter > 0, ERROR_TOO_LOW);
+ counter--;
+ emit Changed(counter);
+ }
+
+ function getCounter() public view returns (uint256) {
+ return counter;
+ }
+}
diff --git a/precompiles/testutil/contracts/DistributionCaller.json b/precompiles/testutil/contracts/DistributionCaller.json
new file mode 100644
index 00000000..3b67a175
--- /dev/null
+++ b/precompiles/testutil/contracts/DistributionCaller.json
@@ -0,0 +1,921 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "DistributionCaller",
+ "sourceName": "solidity/precompiles/testutil/contracts/DistributionCaller.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "name": "counter",
+ "outputs": [
+ {
+ "internalType": "int64",
+ "name": "",
+ "type": "int64"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_withdrawAddr",
+ "type": "string"
+ }
+ ],
+ "name": "delegateCallSetWithdrawAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "deposit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "getDelegationRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ }
+ ],
+ "name": "getDelegationTotalRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "reward",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct DelegationDelegatorReward[]",
+ "name": "rewards",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "total",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ }
+ ],
+ "name": "getDelegatorValidators",
+ "outputs": [
+ {
+ "internalType": "string[]",
+ "name": "",
+ "type": "string[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ }
+ ],
+ "name": "getDelegatorWithdrawAddress",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "getValidatorCommission",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "getValidatorDistributionInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "operatorAddress",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "selfBondRewards",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "commission",
+ "type": "tuple[]"
+ }
+ ],
+ "internalType": "struct ValidatorDistributionInfo",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "getValidatorOutstandingRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct DecCoin[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "uint64",
+ "name": "_startingHeight",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "_endingHeight",
+ "type": "uint64"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "getValidatorSlashes",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint64",
+ "name": "validatorPeriod",
+ "type": "uint64"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "precision",
+ "type": "uint8"
+ }
+ ],
+ "internalType": "struct Dec",
+ "name": "fraction",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct ValidatorSlashEvent[]",
+ "name": "",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "address payable",
+ "name": "_withdrawer",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "revertWithdrawRewardsAndTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ }
+ ],
+ "name": "staticCallGetWithdrawAddress",
+ "outputs": [
+ {
+ "internalType": "bytes",
+ "name": "",
+ "type": "bytes"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_withdrawAddr",
+ "type": "string"
+ }
+ ],
+ "name": "staticCallSetWithdrawAddress",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "uint32",
+ "name": "_maxRetrieve",
+ "type": "uint32"
+ }
+ ],
+ "name": "testClaimRewards",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "uint32",
+ "name": "_maxRetrieve",
+ "type": "uint32"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testClaimRewardsWithTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "depositor",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testFundCommunityPool",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "depositor",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testFundCommunityPoolWithTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_withdrawAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "testRevertState",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_withdrawAddr",
+ "type": "string"
+ }
+ ],
+ "name": "testSetWithdrawAddress",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_withdrawAddr",
+ "type": "string"
+ }
+ ],
+ "name": "testSetWithdrawAddressFromContract",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "testWithdrawDelegatorRewards",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "testWithdrawDelegatorRewardsFromContract",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testWithdrawDelegatorRewardsWithTransfer",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "coins",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "testWithdrawValidatorCommission",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ },
+ {
+ "internalType": "address payable",
+ "name": "_withdrawer",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testWithdrawValidatorCommissionWithTransfer",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "coins",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delAddr",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_valAddr",
+ "type": "string"
+ }
+ ],
+ "name": "withdrawDelegatorRewardsAndRevert",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "coins",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b5061477b806100206000396000f3fe60806040526004361061019c5760003560e01c80637c9db0bb116100ec578063b6a216ae1161008a578063d0e30db011610064578063d0e30db0146106a7578063d3f831be146106b1578063e0421e39146106ee578063e236c7a61461072b5761019c565b8063b6a216ae146105f0578063c7804bb51461062d578063cb85aa0a1461066a5761019c565b806398194593116100c657806398194593146104fc578063ad5c4cdd14610539578063adb2378514610576578063b2d17883146105b35761019c565b80637c9db0bb1461044457806388b2d58114610481578063963516e4146104bf5761019c565b806346e16d34116101595780636cc9ac8a116101335780636cc9ac8a146103785780636f669da4146103a157806378a5dfd1146103de578063796b96d21461041b5761019c565b806346e16d34146102d3578063613d4de81461031057806361bc221a1461034d5761019c565b80630183e4b4146101a157806301b68000146101ca5780630c05e9e4146102075780631b05020714610244578063296c60aa1461026d5780632d0ee16a14610296575b600080fd5b3480156101ad57600080fd5b506101c860048036038101906101c391906123de565b610769565b005b3480156101d657600080fd5b506101f160048036038101906101ec9190612483565b610a96565b6040516101fe9190612540565b60405180910390f35b34801561021357600080fd5b5061022e60048036038101906102299190612697565b610bde565b60405161023b91906128da565b60405180910390f35b34801561025057600080fd5b5061026b600480360381019061026691906128fc565b610c6e565b005b34801561027957600080fd5b50610294600480360381019061028f919061297f565b610df4565b005b3480156102a257600080fd5b506102bd60048036038101906102b89190612697565b610f35565b6040516102ca9190612ada565b60405180910390f35b3480156102df57600080fd5b506102fa60048036038101906102f5919061297f565b610fc3565b6040516103079190612b0b565b60405180910390f35b34801561031c57600080fd5b5061033760048036038101906103329190612b26565b61104d565b6040516103449190612ada565b60405180910390f35b34801561035957600080fd5b5061036261133e565b60405161036f9190612bc5565b60405180910390f35b34801561038457600080fd5b5061039f600480360381019061039a9190612c0c565b61134f565b005b3480156103ad57600080fd5b506103c860048036038101906103c39190612c73565b6115de565b6040516103d59190612b0b565b60405180910390f35b3480156103ea57600080fd5b506104056004803603810190610400919061297f565b611668565b6040516104129190612d39565b60405180910390f35b34801561042757600080fd5b50610442600480360381019061043d919061297f565b6116f5565b005b34801561045057600080fd5b5061046b60048036038101906104669190612697565b611836565b6040516104789190612d39565b60405180910390f35b34801561048d57600080fd5b506104a860048036038101906104a39190612dbf565b6118c0565b6040516104b6929190613001565b60405180910390f35b3480156104cb57600080fd5b506104e660048036038101906104e19190612697565b61195e565b6040516104f39190612b0b565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e919061297f565b6119e7565b6040516105309190612ada565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b919061297f565b611a76565b60405161056d9190612ada565b60405180910390f35b34801561058257600080fd5b5061059d60048036038101906105989190613038565b611b02565b6040516105aa9190612ada565b60405180910390f35b3480156105bf57600080fd5b506105da60048036038101906105d591906130bb565b611d8d565b6040516105e79190612ada565b60405180910390f35b3480156105fc57600080fd5b5061061760048036038101906106129190612483565b611ee2565b6040516106249190613208565b60405180910390f35b34801561063957600080fd5b50610654600480360381019061064f919061322a565b611f6c565b6040516106619190612b0b565b60405180910390f35b34801561067657600080fd5b50610691600480360381019061068c9190612483565b612084565b60405161069e91906132b4565b60405180910390f35b6106af61210e565b005b3480156106bd57600080fd5b506106d860048036038101906106d39190612697565b612110565b6040516106e59190612d39565b60405180910390f35b3480156106fa57600080fd5b5061071560048036038101906107109190612697565b61219a565b6040516107229190612ada565b60405180910390f35b34801561073757600080fd5b50610752600480360381019061074d9190612483565b612226565b6040516107609291906133dc565b60405180910390f35b811561089a5760008081819054906101000a900460070b8092919061078d90613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146108995760008473ffffffffffffffffffffffffffffffffffffffff16600f604051610811906134a3565b60006040518083038185875af1925050503d806000811461084e576040519150601f19603f3d011682016040523d82523d6000602084013e610853565b606091505b5050905080610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088e9061352a565b60405180910390fd5b505b5b600061080173ffffffffffffffffffffffffffffffffffffffff16632efe8a5f86866040518363ffffffff1660e01b81526004016108d99291906135b8565b6020604051808303816000875af11580156108f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091c91906135f6565b90508061095e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109559061366f565b60405180910390fd5b8115610a8f5760008081819054906101000a900460070b8092919061098290613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614610a8e5760008573ffffffffffffffffffffffffffffffffffffffff16600f604051610a06906134a3565b60006040518083038185875af1925050503d8060008114610a43576040519150601f19603f3d011682016040523d82523d6000602084013e610a48565b606091505b5050905080610a8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a839061352a565b60405180910390fd5b505b5b5050505050565b606060008061080173ffffffffffffffffffffffffffffffffffffffff1684604051602401610ac5919061369e565b6040516020818303038152906040527f5431f450000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610b4f91906136ea565b600060405180830381855afa9150503d8060008114610b8a576040519150601f19603f3d011682016040523d82523d6000602084013e610b8f565b606091505b509150915081610bd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bcb9061374d565b60405180910390fd5b8092505050919050565b610be66122b3565b61080173ffffffffffffffffffffffffffffffffffffffff166354212a89836040518263ffffffff1660e01b8152600401610c2191906132b4565b600060405180830381865afa158015610c3e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c679190613a46565b9050919050565b3073ffffffffffffffffffffffffffffffffffffffff1663ad5c4cdd85846040518363ffffffff1660e01b8152600401610ca9929190613a8f565b6000604051808303816000875af1925050508015610cea57506040513d6000823e3d601f19601f82011682018060405250810190610ce79190613c0c565b60015b15610cf157505b8015610dee5760008081819054906101000a900460070b80929190610d1590613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008373ffffffffffffffffffffffffffffffffffffffff16600f604051610d66906134a3565b60006040518083038185875af1925050503d8060008114610da3576040519150601f19603f3d011682016040523d82523d6000602084013e610da8565b606091505b5050905080610dec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610de39061352a565b60405180910390fd5b505b50505050565b600061080173ffffffffffffffffffffffffffffffffffffffff168383604051602401610e22929190613c55565b6040516020818303038152906040527f5a9d9a96000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610eac91906136ea565b600060405180830381855af49150503d8060008114610ee7576040519150601f19603f3d011682016040523d82523d6000602084013e610eec565b606091505b5050905080610f30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2790613cf7565b60405180910390fd5b505050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6130846040518363ffffffff1660e01b8152600401610f74929190613c55565b6000604051808303816000875af1158015610f93573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610fbc9190613c0c565b9050919050565b600061080173ffffffffffffffffffffffffffffffffffffffff16635a9d9a9684846040518363ffffffff1660e01b8152600401611002929190613c55565b6020604051808303816000875af1158015611021573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104591906135f6565b905092915050565b606082156111805760008081819054906101000a900460070b8092919061107390613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461117f5760008473ffffffffffffffffffffffffffffffffffffffff16600f6040516110f7906134a3565b60006040518083038185875af1925050503d8060008114611134576040519150601f19603f3d011682016040523d82523d6000602084013e611139565b606091505b505090508061117d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111749061352a565b60405180910390fd5b505b5b61080173ffffffffffffffffffffffffffffffffffffffff16633ce4e3be866040518263ffffffff1660e01b81526004016111bb91906132b4565b6000604051808303816000875af11580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906112039190613c0c565b905081156113365760008081819054906101000a900460070b8092919061122990613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146113355760008473ffffffffffffffffffffffffffffffffffffffff16600f6040516112ad906134a3565b60006040518083038185875af1925050503d80600081146112ea576040519150601f19603f3d011682016040523d82523d6000602084013e6112ef565b606091505b5050905080611333576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132a9061352a565b60405180910390fd5b505b5b949350505050565b60008054906101000a900460070b81565b811561144c5760008081819054906101000a900460070b8092919061137390613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008473ffffffffffffffffffffffffffffffffffffffff16600f6040516113c4906134a3565b60006040518083038185875af1925050503d8060008114611401576040519150601f19603f3d011682016040523d82523d6000602084013e611406565b606091505b505090508061144a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114419061352a565b60405180910390fd5b505b600061080173ffffffffffffffffffffffffffffffffffffffff1663ed41d0b686866040518363ffffffff1660e01b815260040161148b929190613d26565b6020604051808303816000875af11580156114aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ce91906135f6565b9050806114da57600080fd5b81156115d75760008081819054906101000a900460070b809291906114fe90613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008573ffffffffffffffffffffffffffffffffffffffff16600f60405161154f906134a3565b60006040518083038185875af1925050503d806000811461158c576040519150601f19603f3d011682016040523d82523d6000602084013e611591565b606091505b50509050806115d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115cc9061352a565b60405180910390fd5b505b5050505050565b600061080173ffffffffffffffffffffffffffffffffffffffff16632efe8a5f84846040518363ffffffff1660e01b815260040161161d929190613d4f565b6020604051808303816000875af115801561163c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166091906135f6565b905092915050565b606061080173ffffffffffffffffffffffffffffffffffffffff16639ad563b484846040518363ffffffff1660e01b81526004016116a7929190613c55565b600060405180830381865afa1580156116c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116ed9190613d78565b905092915050565b600061080173ffffffffffffffffffffffffffffffffffffffff168383604051602401611723929190613c55565b6040516020818303038152906040527f5a9d9a96000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516117ad91906136ea565b600060405180830381855afa9150503d80600081146117e8576040519150601f19603f3d011682016040523d82523d6000602084013e6117ed565b606091505b5050905080611831576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118289061374d565b60405180910390fd5b505050565b606061080173ffffffffffffffffffffffffffffffffffffffff16633dd40f78836040518263ffffffff1660e01b815260040161187391906132b4565b600060405180830381865afa158015611890573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906118b99190613d78565b9050919050565b60606118ca6122d4565b61080173ffffffffffffffffffffffffffffffffffffffff16638f2473ce878787876040518563ffffffff1660e01b815260040161190b9493929190613f4c565b600060405180830381865afa158015611928573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906119519190614224565b9150915094509492505050565b600061080173ffffffffffffffffffffffffffffffffffffffff16635a9d9a9630846040518363ffffffff1660e01b815260040161199d929190613c55565b6020604051808303816000875af11580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e091906135f6565b9050919050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6184846040518363ffffffff1660e01b8152600401611a26929190613c55565b6000604051808303816000875af1158015611a45573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a6e9190613c0c565b905092915050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6184846040518363ffffffff1660e01b8152600401611ab5929190613c55565b6000604051808303816000875af1158015611ad4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611afd9190613c0c565b600080fd5b60608215611c015760008081819054906101000a900460070b80929190611b2890613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008573ffffffffffffffffffffffffffffffffffffffff16600f604051611b79906134a3565b60006040518083038185875af1925050503d8060008114611bb6576040519150601f19603f3d011682016040523d82523d6000602084013e611bbb565b606091505b5050905080611bff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf69061352a565b60405180910390fd5b505b61080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6186866040518363ffffffff1660e01b8152600401611c3e929190613a8f565b6000604051808303816000875af1158015611c5d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611c869190613c0c565b90508115611d855760008081819054906101000a900460070b80929190611cac90613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008573ffffffffffffffffffffffffffffffffffffffff16600f604051611cfd906134a3565b60006040518083038185875af1925050503d8060008114611d3a576040519150601f19603f3d011682016040523d82523d6000602084013e611d3f565b606091505b5050905080611d83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7a9061352a565b60405180910390fd5b505b949350505050565b6060600061080173ffffffffffffffffffffffffffffffffffffffff16635a9d9a9633876040518363ffffffff1660e01b8152600401611dce929190613c55565b6020604051808303816000875af1158015611ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1191906135f6565b905080611e53576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4a906142e8565b60405180910390fd5b61080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6185856040518363ffffffff1660e01b8152600401611e90929190613c55565b6000604051808303816000875af1158015611eaf573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611ed89190613c0c565b9150509392505050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663a66cb605836040518263ffffffff1660e01b8152600401611f1f919061369e565b600060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611f6591906143e9565b9050919050565b600060016000808282829054906101000a900460070b611f8c9190614432565b92506101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555061080173ffffffffffffffffffffffffffffffffffffffff1663ed41d0b684846040518363ffffffff1660e01b8152600401611ff2929190614492565b6020604051808303816000875af1158015612011573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061203591906135f6565b905060016000808282829054906101000a900460070b61205591906144bb565b92506101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555092915050565b606061080173ffffffffffffffffffffffffffffffffffffffff16635431f450836040518263ffffffff1660e01b81526004016120c1919061369e565b600060405180830381865afa1580156120de573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612107919061451b565b9050919050565b565b606061080173ffffffffffffffffffffffffffffffffffffffff166385b2d2da836040518263ffffffff1660e01b815260040161214d91906132b4565b600060405180830381865afa15801561216a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121939190613d78565b9050919050565b606061080173ffffffffffffffffffffffffffffffffffffffff16633ce4e3be836040518263ffffffff1660e01b81526004016121d791906132b4565b6000604051808303816000875af11580156121f6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061221f9190613c0c565b9050919050565b60608061080173ffffffffffffffffffffffffffffffffffffffff166354be1a28846040518263ffffffff1660e01b8152600401612264919061369e565b600060405180830381865afa158015612281573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906122aa91906146cd565b91509150915091565b60405180606001604052806060815260200160608152602001606081525090565b604051806040016040528060608152602001600067ffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123378261230c565b9050919050565b6123478161232c565b811461235257600080fd5b50565b6000813590506123648161233e565b92915050565b600063ffffffff82169050919050565b6123838161236a565b811461238e57600080fd5b50565b6000813590506123a08161237a565b92915050565b60008115159050919050565b6123bb816123a6565b81146123c657600080fd5b50565b6000813590506123d8816123b2565b92915050565b600080600080608085870312156123f8576123f7612302565b5b600061240687828801612355565b945050602061241787828801612391565b9350506040612428878288016123c9565b9250506060612439878288016123c9565b91505092959194509250565b60006124508261230c565b9050919050565b61246081612445565b811461246b57600080fd5b50565b60008135905061247d81612457565b92915050565b60006020828403121561249957612498612302565b5b60006124a78482850161246e565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156124ea5780820151818401526020810190506124cf565b60008484015250505050565b6000601f19601f8301169050919050565b6000612512826124b0565b61251c81856124bb565b935061252c8185602086016124cc565b612535816124f6565b840191505092915050565b6000602082019050818103600083015261255a8184612507565b905092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6125a4826124f6565b810181811067ffffffffffffffff821117156125c3576125c261256c565b5b80604052505050565b60006125d66122f8565b90506125e2828261259b565b919050565b600067ffffffffffffffff8211156126025761260161256c565b5b61260b826124f6565b9050602081019050919050565b82818337600083830152505050565b600061263a612635846125e7565b6125cc565b90508281526020810184848401111561265657612655612567565b5b612661848285612618565b509392505050565b600082601f83011261267e5761267d612562565b5b813561268e848260208601612627565b91505092915050565b6000602082840312156126ad576126ac612302565b5b600082013567ffffffffffffffff8111156126cb576126ca612307565b5b6126d784828501612669565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000612707826126e0565b61271181856126eb565b93506127218185602086016124cc565b61272a816124f6565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b61277481612761565b82525050565b600060ff82169050919050565b6127908161277a565b82525050565b600060608301600083015184820360008601526127b382826126fc565b91505060208301516127c8602086018261276b565b5060408301516127db6040860182612787565b508091505092915050565b60006127f28383612796565b905092915050565b6000602082019050919050565b600061281282612735565b61281c8185612740565b93508360208202850161282e85612751565b8060005b8581101561286a578484038952815161284b85826127e6565b9450612856836127fa565b925060208a01995050600181019050612832565b50829750879550505050505092915050565b6000606083016000830151848203600086015261289982826126fc565b915050602083015184820360208601526128b38282612807565b915050604083015184820360408601526128cd8282612807565b9150508091505092915050565b600060208201905081810360008301526128f4818461287c565b905092915050565b6000806000806080858703121561291657612915612302565b5b600061292487828801612355565b945050602061293587828801612355565b935050604085013567ffffffffffffffff81111561295657612955612307565b5b61296287828801612669565b9250506060612973878288016123c9565b91505092959194509250565b6000806040838503121561299657612995612302565b5b60006129a48582860161246e565b925050602083013567ffffffffffffffff8111156129c5576129c4612307565b5b6129d185828601612669565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152612a2482826126fc565b9150506020830151612a39602086018261276b565b508091505092915050565b6000612a508383612a07565b905092915050565b6000602082019050919050565b6000612a70826129db565b612a7a81856129e6565b935083602082028501612a8c856129f7565b8060005b85811015612ac85784840389528151612aa98582612a44565b9450612ab483612a58565b925060208a01995050600181019050612a90565b50829750879550505050505092915050565b60006020820190508181036000830152612af48184612a65565b905092915050565b612b05816123a6565b82525050565b6000602082019050612b206000830184612afc565b92915050565b60008060008060808587031215612b4057612b3f612302565b5b600085013567ffffffffffffffff811115612b5e57612b5d612307565b5b612b6a87828801612669565b9450506020612b7b87828801612355565b9350506040612b8c878288016123c9565b9250506060612b9d878288016123c9565b91505092959194509250565b60008160070b9050919050565b612bbf81612ba9565b82525050565b6000602082019050612bda6000830184612bb6565b92915050565b612be981612761565b8114612bf457600080fd5b50565b600081359050612c0681612be0565b92915050565b60008060008060808587031215612c2657612c25612302565b5b6000612c3487828801612355565b9450506020612c4587828801612bf7565b9350506040612c56878288016123c9565b9250506060612c67878288016123c9565b91505092959194509250565b60008060408385031215612c8a57612c89612302565b5b6000612c988582860161246e565b9250506020612ca985828601612391565b9150509250929050565b600082825260208201905092915050565b6000612ccf82612735565b612cd98185612cb3565b935083602082028501612ceb85612751565b8060005b85811015612d275784840389528151612d0885826127e6565b9450612d13836127fa565b925060208a01995050600181019050612cef565b50829750879550505050505092915050565b60006020820190508181036000830152612d538184612cc4565b905092915050565b600067ffffffffffffffff82169050919050565b612d7881612d5b565b8114612d8357600080fd5b50565b600081359050612d9581612d6f565b92915050565b600080fd5b600060a08284031215612db657612db5612d9b565b5b81905092915050565b60008060008060808587031215612dd957612dd8612302565b5b600085013567ffffffffffffffff811115612df757612df6612307565b5b612e0387828801612669565b9450506020612e1487828801612d86565b9350506040612e2587828801612d86565b925050606085013567ffffffffffffffff811115612e4657612e45612307565b5b612e5287828801612da0565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612e9381612d5b565b82525050565b604082016000820151612eaf600085018261276b565b506020820151612ec26020850182612787565b50505050565b606082016000820151612ede6000850182612e8a565b506020820151612ef16020850182612e99565b50505050565b6000612f038383612ec8565b60608301905092915050565b6000602082019050919050565b6000612f2782612e5e565b612f318185612e69565b9350612f3c83612e7a565b8060005b83811015612f6d578151612f548882612ef7565b9750612f5f83612f0f565b925050600181019050612f40565b5085935050505092915050565b600082825260208201905092915050565b6000612f96826124b0565b612fa08185612f7a565b9350612fb08185602086016124cc565b612fb9816124f6565b840191505092915050565b60006040830160008301518482036000860152612fe18282612f8b565b9150506020830151612ff66020860182612e8a565b508091505092915050565b6000604082019050818103600083015261301b8185612f1c565b9050818103602083015261302f8184612fc4565b90509392505050565b6000806000806080858703121561305257613051612302565b5b600061306087828801612355565b945050602085013567ffffffffffffffff81111561308157613080612307565b5b61308d87828801612669565b935050604061309e878288016123c9565b92505060606130af878288016123c9565b91505092959194509250565b6000806000606084860312156130d4576130d3612302565b5b600084013567ffffffffffffffff8111156130f2576130f1612307565b5b6130fe86828701612669565b935050602061310f8682870161246e565b925050604084013567ffffffffffffffff8111156131305761312f612307565b5b61313c86828701612669565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061317e83836126fc565b905092915050565b6000602082019050919050565b600061319e82613146565b6131a88185613151565b9350836020820285016131ba85613162565b8060005b858110156131f657848403895281516131d78582613172565b94506131e283613186565b925060208a019950506001810190506131be565b50829750879550505050505092915050565b600060208201905081810360008301526132228184613193565b905092915050565b6000806040838503121561324157613240612302565b5b600061324f8582860161246e565b925050602061326085828601612bf7565b9150509250929050565b600082825260208201905092915050565b6000613286826126e0565b613290818561326a565b93506132a08185602086016124cc565b6132a9816124f6565b840191505092915050565b600060208201905081810360008301526132ce818461327b565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000604083016000830151848203600086015261331f82826126fc565b915050602083015184820360208601526133398282612807565b9150508091505092915050565b60006133528383613302565b905092915050565b6000602082019050919050565b6000613372826132d6565b61337c81856132e1565b93508360208202850161338e856132f2565b8060005b858110156133ca57848403895281516133ab8582613346565b94506133b68361335a565b925060208a01995050600181019050613392565b50829750879550505050505092915050565b600060408201905081810360008301526133f68185613367565b9050818103602083015261340a8184612cc4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061344d82612ba9565b9150677fffffffffffffff820361346757613466613413565b5b600182019050919050565b600081905092915050565b50565b600061348d600083613472565b91506134988261347d565b600082019050919050565b60006134ae82613480565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061351460218361326a565b915061351f826134b8565b604082019050919050565b6000602082019050818103600083015261354381613507565b9050919050565b6000819050919050565b600061356f61356a6135658461230c565b61354a565b61230c565b9050919050565b600061358182613554565b9050919050565b600061359382613576565b9050919050565b6135a381613588565b82525050565b6135b28161236a565b82525050565b60006040820190506135cd600083018561359a565b6135da60208301846135a9565b9392505050565b6000815190506135f0816123b2565b92915050565b60006020828403121561360c5761360b612302565b5b600061361a848285016135e1565b91505092915050565b7f6661696c656420746f20636c61696d2072657761726473000000000000000000600082015250565b600061365960178361326a565b915061366482613623565b602082019050919050565b600060208201905081810360008301526136888161364c565b9050919050565b61369881612445565b82525050565b60006020820190506136b3600083018461368f565b92915050565b60006136c4826124b0565b6136ce8185613472565b93506136de8185602086016124cc565b80840191505092915050565b60006136f682846136b9565b915081905092915050565b7f6661696c65642073746174696343616c6c20746f20707265636f6d70696c6500600082015250565b6000613737601f8361326a565b915061374282613701565b602082019050919050565b600060208201905081810360008301526137668161372a565b9050919050565b600080fd5b600080fd5b600061378a613785846125e7565b6125cc565b9050828152602081018484840111156137a6576137a5612567565b5b6137b18482856124cc565b509392505050565b600082601f8301126137ce576137cd612562565b5b81516137de848260208601613777565b91505092915050565b600067ffffffffffffffff8211156138025761380161256c565b5b602082029050602081019050919050565b600080fd5b60008151905061382781612be0565b92915050565b6138368161277a565b811461384157600080fd5b50565b6000815190506138538161382d565b92915050565b60006060828403121561386f5761386e61376d565b5b61387960606125cc565b9050600082015167ffffffffffffffff81111561389957613898613772565b5b6138a5848285016137b9565b60008301525060206138b984828501613818565b60208301525060406138cd84828501613844565b60408301525092915050565b60006138ec6138e7846137e7565b6125cc565b9050808382526020820190506020840283018581111561390f5761390e613813565b5b835b8181101561395657805167ffffffffffffffff81111561393457613933612562565b5b8086016139418982613859565b85526020850194505050602081019050613911565b5050509392505050565b600082601f83011261397557613974612562565b5b81516139858482602086016138d9565b91505092915050565b6000606082840312156139a4576139a361376d565b5b6139ae60606125cc565b9050600082015167ffffffffffffffff8111156139ce576139cd613772565b5b6139da848285016137b9565b600083015250602082015167ffffffffffffffff8111156139fe576139fd613772565b5b613a0a84828501613960565b602083015250604082015167ffffffffffffffff811115613a2e57613a2d613772565b5b613a3a84828501613960565b60408301525092915050565b600060208284031215613a5c57613a5b612302565b5b600082015167ffffffffffffffff811115613a7a57613a79612307565b5b613a868482850161398e565b91505092915050565b6000604082019050613aa4600083018561359a565b8181036020830152613ab6818461327b565b90509392505050565b600067ffffffffffffffff821115613ada57613ad961256c565b5b602082029050602081019050919050565b600060408284031215613b0157613b0061376d565b5b613b0b60406125cc565b9050600082015167ffffffffffffffff811115613b2b57613b2a613772565b5b613b37848285016137b9565b6000830152506020613b4b84828501613818565b60208301525092915050565b6000613b6a613b6584613abf565b6125cc565b90508083825260208201905060208402830185811115613b8d57613b8c613813565b5b835b81811015613bd457805167ffffffffffffffff811115613bb257613bb1612562565b5b808601613bbf8982613aeb565b85526020850194505050602081019050613b8f565b5050509392505050565b600082601f830112613bf357613bf2612562565b5b8151613c03848260208601613b57565b91505092915050565b600060208284031215613c2257613c21612302565b5b600082015167ffffffffffffffff811115613c4057613c3f612307565b5b613c4c84828501613bde565b91505092915050565b6000604082019050613c6a600083018561368f565b8181036020830152613c7c818461327b565b90509392505050565b7f6661696c65642064656c656761746543616c6c20746f20707265636f6d70696c60008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ce160218361326a565b9150613cec82613c85565b604082019050919050565b60006020820190508181036000830152613d1081613cd4565b9050919050565b613d2081612761565b82525050565b6000604082019050613d3b600083018561359a565b613d486020830184613d17565b9392505050565b6000604082019050613d64600083018561368f565b613d7160208301846135a9565b9392505050565b600060208284031215613d8e57613d8d612302565b5b600082015167ffffffffffffffff811115613dac57613dab612307565b5b613db884828501613960565b91505092915050565b613dca81612d5b565b82525050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613dfc57613dfb613dda565b5b83810192508235915060208301925067ffffffffffffffff821115613e2457613e23613dd0565b5b600182023603831315613e3a57613e39613dd5565b5b509250929050565b6000613e4e8385612f7a565b9350613e5b838584612618565b613e64836124f6565b840190509392505050565b6000613e7e6020840184612d86565b905092915050565b6000613e9560208401846123c9565b905092915050565b613ea6816123a6565b82525050565b600060a08301613ebf6000840184613ddf565b8583036000870152613ed2838284613e42565b92505050613ee36020840184613e6f565b613ef06020860182612e8a565b50613efe6040840184613e6f565b613f0b6040860182612e8a565b50613f196060840184613e86565b613f266060860182613e9d565b50613f346080840184613e86565b613f416080860182613e9d565b508091505092915050565b60006080820190508181036000830152613f66818761327b565b9050613f756020830186613dc1565b613f826040830185613dc1565b8181036060830152613f948184613eac565b905095945050505050565b600067ffffffffffffffff821115613fba57613fb961256c565b5b602082029050602081019050919050565b600081519050613fda81612d6f565b92915050565b600060408284031215613ff657613ff561376d565b5b61400060406125cc565b9050600061401084828501613818565b600083015250602061402484828501613844565b60208301525092915050565b6000606082840312156140465761404561376d565b5b61405060406125cc565b9050600061406084828501613fcb565b600083015250602061407484828501613fe0565b60208301525092915050565b600061409361408e84613f9f565b6125cc565b905080838252602082019050606084028301858111156140b6576140b5613813565b5b835b818110156140df57806140cb8882614030565b8452602084019350506060810190506140b8565b5050509392505050565b600082601f8301126140fe576140fd612562565b5b815161410e848260208601614080565b91505092915050565b600067ffffffffffffffff8211156141325761413161256c565b5b61413b826124f6565b9050602081019050919050565b600061415b61415684614117565b6125cc565b90508281526020810184848401111561417757614176612567565b5b6141828482856124cc565b509392505050565b600082601f83011261419f5761419e612562565b5b81516141af848260208601614148565b91505092915050565b6000604082840312156141ce576141cd61376d565b5b6141d860406125cc565b9050600082015167ffffffffffffffff8111156141f8576141f7613772565b5b6142048482850161418a565b600083015250602061421884828501613fcb565b60208301525092915050565b6000806040838503121561423b5761423a612302565b5b600083015167ffffffffffffffff81111561425957614258612307565b5b614265858286016140e9565b925050602083015167ffffffffffffffff81111561428657614285612307565b5b614292858286016141b8565b9150509250929050565b7f6661696c656420746f2073657420776974686472617720616464726573730000600082015250565b60006142d2601e8361326a565b91506142dd8261429c565b602082019050919050565b60006020820190508181036000830152614301816142c5565b9050919050565b600067ffffffffffffffff8211156143235761432261256c565b5b602082029050602081019050919050565b600061434761434284614308565b6125cc565b9050808382526020820190506020840283018581111561436a57614369613813565b5b835b818110156143b157805167ffffffffffffffff81111561438f5761438e612562565b5b80860161439c89826137b9565b8552602085019450505060208101905061436c565b5050509392505050565b600082601f8301126143d0576143cf612562565b5b81516143e0848260208601614334565b91505092915050565b6000602082840312156143ff576143fe612302565b5b600082015167ffffffffffffffff81111561441d5761441c612307565b5b614429848285016143bb565b91505092915050565b600061443d82612ba9565b915061444883612ba9565b925082820190507fffffffffffffffffffffffffffffffffffffffffffffffff80000000000000008112677fffffffffffffff8213171561448c5761448b613413565b5b92915050565b60006040820190506144a7600083018561368f565b6144b46020830184613d17565b9392505050565b60006144c682612ba9565b91506144d183612ba9565b92508282039050677fffffffffffffff81137fffffffffffffffffffffffffffffffffffffffffffffffff80000000000000008212171561451557614514613413565b5b92915050565b60006020828403121561453157614530612302565b5b600082015167ffffffffffffffff81111561454f5761454e612307565b5b61455b848285016137b9565b91505092915050565b600067ffffffffffffffff82111561457f5761457e61256c565b5b602082029050602081019050919050565b6000604082840312156145a6576145a561376d565b5b6145b060406125cc565b9050600082015167ffffffffffffffff8111156145d0576145cf613772565b5b6145dc848285016137b9565b600083015250602082015167ffffffffffffffff811115614600576145ff613772565b5b61460c84828501613960565b60208301525092915050565b600061462b61462684614564565b6125cc565b9050808382526020820190506020840283018581111561464e5761464d613813565b5b835b8181101561469557805167ffffffffffffffff81111561467357614672612562565b5b8086016146808982614590565b85526020850194505050602081019050614650565b5050509392505050565b600082601f8301126146b4576146b3612562565b5b81516146c4848260208601614618565b91505092915050565b600080604083850312156146e4576146e3612302565b5b600083015167ffffffffffffffff81111561470257614701612307565b5b61470e8582860161469f565b925050602083015167ffffffffffffffff81111561472f5761472e612307565b5b61473b85828601613960565b915050925092905056fea2646970667358221220a8fdbc3760bca6bed7c0d0a8bfa4c3e75e199774f0a60a0a34530a58ee2456ed64736f6c63430008130033",
+ "deployedBytecode": "0x60806040526004361061019c5760003560e01c80637c9db0bb116100ec578063b6a216ae1161008a578063d0e30db011610064578063d0e30db0146106a7578063d3f831be146106b1578063e0421e39146106ee578063e236c7a61461072b5761019c565b8063b6a216ae146105f0578063c7804bb51461062d578063cb85aa0a1461066a5761019c565b806398194593116100c657806398194593146104fc578063ad5c4cdd14610539578063adb2378514610576578063b2d17883146105b35761019c565b80637c9db0bb1461044457806388b2d58114610481578063963516e4146104bf5761019c565b806346e16d34116101595780636cc9ac8a116101335780636cc9ac8a146103785780636f669da4146103a157806378a5dfd1146103de578063796b96d21461041b5761019c565b806346e16d34146102d3578063613d4de81461031057806361bc221a1461034d5761019c565b80630183e4b4146101a157806301b68000146101ca5780630c05e9e4146102075780631b05020714610244578063296c60aa1461026d5780632d0ee16a14610296575b600080fd5b3480156101ad57600080fd5b506101c860048036038101906101c391906123de565b610769565b005b3480156101d657600080fd5b506101f160048036038101906101ec9190612483565b610a96565b6040516101fe9190612540565b60405180910390f35b34801561021357600080fd5b5061022e60048036038101906102299190612697565b610bde565b60405161023b91906128da565b60405180910390f35b34801561025057600080fd5b5061026b600480360381019061026691906128fc565b610c6e565b005b34801561027957600080fd5b50610294600480360381019061028f919061297f565b610df4565b005b3480156102a257600080fd5b506102bd60048036038101906102b89190612697565b610f35565b6040516102ca9190612ada565b60405180910390f35b3480156102df57600080fd5b506102fa60048036038101906102f5919061297f565b610fc3565b6040516103079190612b0b565b60405180910390f35b34801561031c57600080fd5b5061033760048036038101906103329190612b26565b61104d565b6040516103449190612ada565b60405180910390f35b34801561035957600080fd5b5061036261133e565b60405161036f9190612bc5565b60405180910390f35b34801561038457600080fd5b5061039f600480360381019061039a9190612c0c565b61134f565b005b3480156103ad57600080fd5b506103c860048036038101906103c39190612c73565b6115de565b6040516103d59190612b0b565b60405180910390f35b3480156103ea57600080fd5b506104056004803603810190610400919061297f565b611668565b6040516104129190612d39565b60405180910390f35b34801561042757600080fd5b50610442600480360381019061043d919061297f565b6116f5565b005b34801561045057600080fd5b5061046b60048036038101906104669190612697565b611836565b6040516104789190612d39565b60405180910390f35b34801561048d57600080fd5b506104a860048036038101906104a39190612dbf565b6118c0565b6040516104b6929190613001565b60405180910390f35b3480156104cb57600080fd5b506104e660048036038101906104e19190612697565b61195e565b6040516104f39190612b0b565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e919061297f565b6119e7565b6040516105309190612ada565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b919061297f565b611a76565b60405161056d9190612ada565b60405180910390f35b34801561058257600080fd5b5061059d60048036038101906105989190613038565b611b02565b6040516105aa9190612ada565b60405180910390f35b3480156105bf57600080fd5b506105da60048036038101906105d591906130bb565b611d8d565b6040516105e79190612ada565b60405180910390f35b3480156105fc57600080fd5b5061061760048036038101906106129190612483565b611ee2565b6040516106249190613208565b60405180910390f35b34801561063957600080fd5b50610654600480360381019061064f919061322a565b611f6c565b6040516106619190612b0b565b60405180910390f35b34801561067657600080fd5b50610691600480360381019061068c9190612483565b612084565b60405161069e91906132b4565b60405180910390f35b6106af61210e565b005b3480156106bd57600080fd5b506106d860048036038101906106d39190612697565b612110565b6040516106e59190612d39565b60405180910390f35b3480156106fa57600080fd5b5061071560048036038101906107109190612697565b61219a565b6040516107229190612ada565b60405180910390f35b34801561073757600080fd5b50610752600480360381019061074d9190612483565b612226565b6040516107609291906133dc565b60405180910390f35b811561089a5760008081819054906101000a900460070b8092919061078d90613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146108995760008473ffffffffffffffffffffffffffffffffffffffff16600f604051610811906134a3565b60006040518083038185875af1925050503d806000811461084e576040519150601f19603f3d011682016040523d82523d6000602084013e610853565b606091505b5050905080610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088e9061352a565b60405180910390fd5b505b5b600061080173ffffffffffffffffffffffffffffffffffffffff16632efe8a5f86866040518363ffffffff1660e01b81526004016108d99291906135b8565b6020604051808303816000875af11580156108f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091c91906135f6565b90508061095e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109559061366f565b60405180910390fd5b8115610a8f5760008081819054906101000a900460070b8092919061098290613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614610a8e5760008573ffffffffffffffffffffffffffffffffffffffff16600f604051610a06906134a3565b60006040518083038185875af1925050503d8060008114610a43576040519150601f19603f3d011682016040523d82523d6000602084013e610a48565b606091505b5050905080610a8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a839061352a565b60405180910390fd5b505b5b5050505050565b606060008061080173ffffffffffffffffffffffffffffffffffffffff1684604051602401610ac5919061369e565b6040516020818303038152906040527f5431f450000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610b4f91906136ea565b600060405180830381855afa9150503d8060008114610b8a576040519150601f19603f3d011682016040523d82523d6000602084013e610b8f565b606091505b509150915081610bd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bcb9061374d565b60405180910390fd5b8092505050919050565b610be66122b3565b61080173ffffffffffffffffffffffffffffffffffffffff166354212a89836040518263ffffffff1660e01b8152600401610c2191906132b4565b600060405180830381865afa158015610c3e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c679190613a46565b9050919050565b3073ffffffffffffffffffffffffffffffffffffffff1663ad5c4cdd85846040518363ffffffff1660e01b8152600401610ca9929190613a8f565b6000604051808303816000875af1925050508015610cea57506040513d6000823e3d601f19601f82011682018060405250810190610ce79190613c0c565b60015b15610cf157505b8015610dee5760008081819054906101000a900460070b80929190610d1590613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008373ffffffffffffffffffffffffffffffffffffffff16600f604051610d66906134a3565b60006040518083038185875af1925050503d8060008114610da3576040519150601f19603f3d011682016040523d82523d6000602084013e610da8565b606091505b5050905080610dec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610de39061352a565b60405180910390fd5b505b50505050565b600061080173ffffffffffffffffffffffffffffffffffffffff168383604051602401610e22929190613c55565b6040516020818303038152906040527f5a9d9a96000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610eac91906136ea565b600060405180830381855af49150503d8060008114610ee7576040519150601f19603f3d011682016040523d82523d6000602084013e610eec565b606091505b5050905080610f30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2790613cf7565b60405180910390fd5b505050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6130846040518363ffffffff1660e01b8152600401610f74929190613c55565b6000604051808303816000875af1158015610f93573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610fbc9190613c0c565b9050919050565b600061080173ffffffffffffffffffffffffffffffffffffffff16635a9d9a9684846040518363ffffffff1660e01b8152600401611002929190613c55565b6020604051808303816000875af1158015611021573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104591906135f6565b905092915050565b606082156111805760008081819054906101000a900460070b8092919061107390613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461117f5760008473ffffffffffffffffffffffffffffffffffffffff16600f6040516110f7906134a3565b60006040518083038185875af1925050503d8060008114611134576040519150601f19603f3d011682016040523d82523d6000602084013e611139565b606091505b505090508061117d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111749061352a565b60405180910390fd5b505b5b61080173ffffffffffffffffffffffffffffffffffffffff16633ce4e3be866040518263ffffffff1660e01b81526004016111bb91906132b4565b6000604051808303816000875af11580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906112039190613c0c565b905081156113365760008081819054906101000a900460070b8092919061122990613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146113355760008473ffffffffffffffffffffffffffffffffffffffff16600f6040516112ad906134a3565b60006040518083038185875af1925050503d80600081146112ea576040519150601f19603f3d011682016040523d82523d6000602084013e6112ef565b606091505b5050905080611333576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132a9061352a565b60405180910390fd5b505b5b949350505050565b60008054906101000a900460070b81565b811561144c5760008081819054906101000a900460070b8092919061137390613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008473ffffffffffffffffffffffffffffffffffffffff16600f6040516113c4906134a3565b60006040518083038185875af1925050503d8060008114611401576040519150601f19603f3d011682016040523d82523d6000602084013e611406565b606091505b505090508061144a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114419061352a565b60405180910390fd5b505b600061080173ffffffffffffffffffffffffffffffffffffffff1663ed41d0b686866040518363ffffffff1660e01b815260040161148b929190613d26565b6020604051808303816000875af11580156114aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ce91906135f6565b9050806114da57600080fd5b81156115d75760008081819054906101000a900460070b809291906114fe90613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008573ffffffffffffffffffffffffffffffffffffffff16600f60405161154f906134a3565b60006040518083038185875af1925050503d806000811461158c576040519150601f19603f3d011682016040523d82523d6000602084013e611591565b606091505b50509050806115d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115cc9061352a565b60405180910390fd5b505b5050505050565b600061080173ffffffffffffffffffffffffffffffffffffffff16632efe8a5f84846040518363ffffffff1660e01b815260040161161d929190613d4f565b6020604051808303816000875af115801561163c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166091906135f6565b905092915050565b606061080173ffffffffffffffffffffffffffffffffffffffff16639ad563b484846040518363ffffffff1660e01b81526004016116a7929190613c55565b600060405180830381865afa1580156116c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116ed9190613d78565b905092915050565b600061080173ffffffffffffffffffffffffffffffffffffffff168383604051602401611723929190613c55565b6040516020818303038152906040527f5a9d9a96000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516117ad91906136ea565b600060405180830381855afa9150503d80600081146117e8576040519150601f19603f3d011682016040523d82523d6000602084013e6117ed565b606091505b5050905080611831576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118289061374d565b60405180910390fd5b505050565b606061080173ffffffffffffffffffffffffffffffffffffffff16633dd40f78836040518263ffffffff1660e01b815260040161187391906132b4565b600060405180830381865afa158015611890573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906118b99190613d78565b9050919050565b60606118ca6122d4565b61080173ffffffffffffffffffffffffffffffffffffffff16638f2473ce878787876040518563ffffffff1660e01b815260040161190b9493929190613f4c565b600060405180830381865afa158015611928573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906119519190614224565b9150915094509492505050565b600061080173ffffffffffffffffffffffffffffffffffffffff16635a9d9a9630846040518363ffffffff1660e01b815260040161199d929190613c55565b6020604051808303816000875af11580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e091906135f6565b9050919050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6184846040518363ffffffff1660e01b8152600401611a26929190613c55565b6000604051808303816000875af1158015611a45573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a6e9190613c0c565b905092915050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6184846040518363ffffffff1660e01b8152600401611ab5929190613c55565b6000604051808303816000875af1158015611ad4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611afd9190613c0c565b600080fd5b60608215611c015760008081819054906101000a900460070b80929190611b2890613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008573ffffffffffffffffffffffffffffffffffffffff16600f604051611b79906134a3565b60006040518083038185875af1925050503d8060008114611bb6576040519150601f19603f3d011682016040523d82523d6000602084013e611bbb565b606091505b5050905080611bff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf69061352a565b60405180910390fd5b505b61080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6186866040518363ffffffff1660e01b8152600401611c3e929190613a8f565b6000604051808303816000875af1158015611c5d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611c869190613c0c565b90508115611d855760008081819054906101000a900460070b80929190611cac90613442565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008573ffffffffffffffffffffffffffffffffffffffff16600f604051611cfd906134a3565b60006040518083038185875af1925050503d8060008114611d3a576040519150601f19603f3d011682016040523d82523d6000602084013e611d3f565b606091505b5050905080611d83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7a9061352a565b60405180910390fd5b505b949350505050565b6060600061080173ffffffffffffffffffffffffffffffffffffffff16635a9d9a9633876040518363ffffffff1660e01b8152600401611dce929190613c55565b6020604051808303816000875af1158015611ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1191906135f6565b905080611e53576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4a906142e8565b60405180910390fd5b61080173ffffffffffffffffffffffffffffffffffffffff1663b46a8d6185856040518363ffffffff1660e01b8152600401611e90929190613c55565b6000604051808303816000875af1158015611eaf573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611ed89190613c0c565b9150509392505050565b606061080173ffffffffffffffffffffffffffffffffffffffff1663a66cb605836040518263ffffffff1660e01b8152600401611f1f919061369e565b600060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611f6591906143e9565b9050919050565b600060016000808282829054906101000a900460070b611f8c9190614432565b92506101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555061080173ffffffffffffffffffffffffffffffffffffffff1663ed41d0b684846040518363ffffffff1660e01b8152600401611ff2929190614492565b6020604051808303816000875af1158015612011573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061203591906135f6565b905060016000808282829054906101000a900460070b61205591906144bb565b92506101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555092915050565b606061080173ffffffffffffffffffffffffffffffffffffffff16635431f450836040518263ffffffff1660e01b81526004016120c1919061369e565b600060405180830381865afa1580156120de573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612107919061451b565b9050919050565b565b606061080173ffffffffffffffffffffffffffffffffffffffff166385b2d2da836040518263ffffffff1660e01b815260040161214d91906132b4565b600060405180830381865afa15801561216a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121939190613d78565b9050919050565b606061080173ffffffffffffffffffffffffffffffffffffffff16633ce4e3be836040518263ffffffff1660e01b81526004016121d791906132b4565b6000604051808303816000875af11580156121f6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061221f9190613c0c565b9050919050565b60608061080173ffffffffffffffffffffffffffffffffffffffff166354be1a28846040518263ffffffff1660e01b8152600401612264919061369e565b600060405180830381865afa158015612281573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906122aa91906146cd565b91509150915091565b60405180606001604052806060815260200160608152602001606081525090565b604051806040016040528060608152602001600067ffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123378261230c565b9050919050565b6123478161232c565b811461235257600080fd5b50565b6000813590506123648161233e565b92915050565b600063ffffffff82169050919050565b6123838161236a565b811461238e57600080fd5b50565b6000813590506123a08161237a565b92915050565b60008115159050919050565b6123bb816123a6565b81146123c657600080fd5b50565b6000813590506123d8816123b2565b92915050565b600080600080608085870312156123f8576123f7612302565b5b600061240687828801612355565b945050602061241787828801612391565b9350506040612428878288016123c9565b9250506060612439878288016123c9565b91505092959194509250565b60006124508261230c565b9050919050565b61246081612445565b811461246b57600080fd5b50565b60008135905061247d81612457565b92915050565b60006020828403121561249957612498612302565b5b60006124a78482850161246e565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156124ea5780820151818401526020810190506124cf565b60008484015250505050565b6000601f19601f8301169050919050565b6000612512826124b0565b61251c81856124bb565b935061252c8185602086016124cc565b612535816124f6565b840191505092915050565b6000602082019050818103600083015261255a8184612507565b905092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6125a4826124f6565b810181811067ffffffffffffffff821117156125c3576125c261256c565b5b80604052505050565b60006125d66122f8565b90506125e2828261259b565b919050565b600067ffffffffffffffff8211156126025761260161256c565b5b61260b826124f6565b9050602081019050919050565b82818337600083830152505050565b600061263a612635846125e7565b6125cc565b90508281526020810184848401111561265657612655612567565b5b612661848285612618565b509392505050565b600082601f83011261267e5761267d612562565b5b813561268e848260208601612627565b91505092915050565b6000602082840312156126ad576126ac612302565b5b600082013567ffffffffffffffff8111156126cb576126ca612307565b5b6126d784828501612669565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000612707826126e0565b61271181856126eb565b93506127218185602086016124cc565b61272a816124f6565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b61277481612761565b82525050565b600060ff82169050919050565b6127908161277a565b82525050565b600060608301600083015184820360008601526127b382826126fc565b91505060208301516127c8602086018261276b565b5060408301516127db6040860182612787565b508091505092915050565b60006127f28383612796565b905092915050565b6000602082019050919050565b600061281282612735565b61281c8185612740565b93508360208202850161282e85612751565b8060005b8581101561286a578484038952815161284b85826127e6565b9450612856836127fa565b925060208a01995050600181019050612832565b50829750879550505050505092915050565b6000606083016000830151848203600086015261289982826126fc565b915050602083015184820360208601526128b38282612807565b915050604083015184820360408601526128cd8282612807565b9150508091505092915050565b600060208201905081810360008301526128f4818461287c565b905092915050565b6000806000806080858703121561291657612915612302565b5b600061292487828801612355565b945050602061293587828801612355565b935050604085013567ffffffffffffffff81111561295657612955612307565b5b61296287828801612669565b9250506060612973878288016123c9565b91505092959194509250565b6000806040838503121561299657612995612302565b5b60006129a48582860161246e565b925050602083013567ffffffffffffffff8111156129c5576129c4612307565b5b6129d185828601612669565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152612a2482826126fc565b9150506020830151612a39602086018261276b565b508091505092915050565b6000612a508383612a07565b905092915050565b6000602082019050919050565b6000612a70826129db565b612a7a81856129e6565b935083602082028501612a8c856129f7565b8060005b85811015612ac85784840389528151612aa98582612a44565b9450612ab483612a58565b925060208a01995050600181019050612a90565b50829750879550505050505092915050565b60006020820190508181036000830152612af48184612a65565b905092915050565b612b05816123a6565b82525050565b6000602082019050612b206000830184612afc565b92915050565b60008060008060808587031215612b4057612b3f612302565b5b600085013567ffffffffffffffff811115612b5e57612b5d612307565b5b612b6a87828801612669565b9450506020612b7b87828801612355565b9350506040612b8c878288016123c9565b9250506060612b9d878288016123c9565b91505092959194509250565b60008160070b9050919050565b612bbf81612ba9565b82525050565b6000602082019050612bda6000830184612bb6565b92915050565b612be981612761565b8114612bf457600080fd5b50565b600081359050612c0681612be0565b92915050565b60008060008060808587031215612c2657612c25612302565b5b6000612c3487828801612355565b9450506020612c4587828801612bf7565b9350506040612c56878288016123c9565b9250506060612c67878288016123c9565b91505092959194509250565b60008060408385031215612c8a57612c89612302565b5b6000612c988582860161246e565b9250506020612ca985828601612391565b9150509250929050565b600082825260208201905092915050565b6000612ccf82612735565b612cd98185612cb3565b935083602082028501612ceb85612751565b8060005b85811015612d275784840389528151612d0885826127e6565b9450612d13836127fa565b925060208a01995050600181019050612cef565b50829750879550505050505092915050565b60006020820190508181036000830152612d538184612cc4565b905092915050565b600067ffffffffffffffff82169050919050565b612d7881612d5b565b8114612d8357600080fd5b50565b600081359050612d9581612d6f565b92915050565b600080fd5b600060a08284031215612db657612db5612d9b565b5b81905092915050565b60008060008060808587031215612dd957612dd8612302565b5b600085013567ffffffffffffffff811115612df757612df6612307565b5b612e0387828801612669565b9450506020612e1487828801612d86565b9350506040612e2587828801612d86565b925050606085013567ffffffffffffffff811115612e4657612e45612307565b5b612e5287828801612da0565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612e9381612d5b565b82525050565b604082016000820151612eaf600085018261276b565b506020820151612ec26020850182612787565b50505050565b606082016000820151612ede6000850182612e8a565b506020820151612ef16020850182612e99565b50505050565b6000612f038383612ec8565b60608301905092915050565b6000602082019050919050565b6000612f2782612e5e565b612f318185612e69565b9350612f3c83612e7a565b8060005b83811015612f6d578151612f548882612ef7565b9750612f5f83612f0f565b925050600181019050612f40565b5085935050505092915050565b600082825260208201905092915050565b6000612f96826124b0565b612fa08185612f7a565b9350612fb08185602086016124cc565b612fb9816124f6565b840191505092915050565b60006040830160008301518482036000860152612fe18282612f8b565b9150506020830151612ff66020860182612e8a565b508091505092915050565b6000604082019050818103600083015261301b8185612f1c565b9050818103602083015261302f8184612fc4565b90509392505050565b6000806000806080858703121561305257613051612302565b5b600061306087828801612355565b945050602085013567ffffffffffffffff81111561308157613080612307565b5b61308d87828801612669565b935050604061309e878288016123c9565b92505060606130af878288016123c9565b91505092959194509250565b6000806000606084860312156130d4576130d3612302565b5b600084013567ffffffffffffffff8111156130f2576130f1612307565b5b6130fe86828701612669565b935050602061310f8682870161246e565b925050604084013567ffffffffffffffff8111156131305761312f612307565b5b61313c86828701612669565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061317e83836126fc565b905092915050565b6000602082019050919050565b600061319e82613146565b6131a88185613151565b9350836020820285016131ba85613162565b8060005b858110156131f657848403895281516131d78582613172565b94506131e283613186565b925060208a019950506001810190506131be565b50829750879550505050505092915050565b600060208201905081810360008301526132228184613193565b905092915050565b6000806040838503121561324157613240612302565b5b600061324f8582860161246e565b925050602061326085828601612bf7565b9150509250929050565b600082825260208201905092915050565b6000613286826126e0565b613290818561326a565b93506132a08185602086016124cc565b6132a9816124f6565b840191505092915050565b600060208201905081810360008301526132ce818461327b565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000604083016000830151848203600086015261331f82826126fc565b915050602083015184820360208601526133398282612807565b9150508091505092915050565b60006133528383613302565b905092915050565b6000602082019050919050565b6000613372826132d6565b61337c81856132e1565b93508360208202850161338e856132f2565b8060005b858110156133ca57848403895281516133ab8582613346565b94506133b68361335a565b925060208a01995050600181019050613392565b50829750879550505050505092915050565b600060408201905081810360008301526133f68185613367565b9050818103602083015261340a8184612cc4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061344d82612ba9565b9150677fffffffffffffff820361346757613466613413565b5b600182019050919050565b600081905092915050565b50565b600061348d600083613472565b91506134988261347d565b600082019050919050565b60006134ae82613480565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061351460218361326a565b915061351f826134b8565b604082019050919050565b6000602082019050818103600083015261354381613507565b9050919050565b6000819050919050565b600061356f61356a6135658461230c565b61354a565b61230c565b9050919050565b600061358182613554565b9050919050565b600061359382613576565b9050919050565b6135a381613588565b82525050565b6135b28161236a565b82525050565b60006040820190506135cd600083018561359a565b6135da60208301846135a9565b9392505050565b6000815190506135f0816123b2565b92915050565b60006020828403121561360c5761360b612302565b5b600061361a848285016135e1565b91505092915050565b7f6661696c656420746f20636c61696d2072657761726473000000000000000000600082015250565b600061365960178361326a565b915061366482613623565b602082019050919050565b600060208201905081810360008301526136888161364c565b9050919050565b61369881612445565b82525050565b60006020820190506136b3600083018461368f565b92915050565b60006136c4826124b0565b6136ce8185613472565b93506136de8185602086016124cc565b80840191505092915050565b60006136f682846136b9565b915081905092915050565b7f6661696c65642073746174696343616c6c20746f20707265636f6d70696c6500600082015250565b6000613737601f8361326a565b915061374282613701565b602082019050919050565b600060208201905081810360008301526137668161372a565b9050919050565b600080fd5b600080fd5b600061378a613785846125e7565b6125cc565b9050828152602081018484840111156137a6576137a5612567565b5b6137b18482856124cc565b509392505050565b600082601f8301126137ce576137cd612562565b5b81516137de848260208601613777565b91505092915050565b600067ffffffffffffffff8211156138025761380161256c565b5b602082029050602081019050919050565b600080fd5b60008151905061382781612be0565b92915050565b6138368161277a565b811461384157600080fd5b50565b6000815190506138538161382d565b92915050565b60006060828403121561386f5761386e61376d565b5b61387960606125cc565b9050600082015167ffffffffffffffff81111561389957613898613772565b5b6138a5848285016137b9565b60008301525060206138b984828501613818565b60208301525060406138cd84828501613844565b60408301525092915050565b60006138ec6138e7846137e7565b6125cc565b9050808382526020820190506020840283018581111561390f5761390e613813565b5b835b8181101561395657805167ffffffffffffffff81111561393457613933612562565b5b8086016139418982613859565b85526020850194505050602081019050613911565b5050509392505050565b600082601f83011261397557613974612562565b5b81516139858482602086016138d9565b91505092915050565b6000606082840312156139a4576139a361376d565b5b6139ae60606125cc565b9050600082015167ffffffffffffffff8111156139ce576139cd613772565b5b6139da848285016137b9565b600083015250602082015167ffffffffffffffff8111156139fe576139fd613772565b5b613a0a84828501613960565b602083015250604082015167ffffffffffffffff811115613a2e57613a2d613772565b5b613a3a84828501613960565b60408301525092915050565b600060208284031215613a5c57613a5b612302565b5b600082015167ffffffffffffffff811115613a7a57613a79612307565b5b613a868482850161398e565b91505092915050565b6000604082019050613aa4600083018561359a565b8181036020830152613ab6818461327b565b90509392505050565b600067ffffffffffffffff821115613ada57613ad961256c565b5b602082029050602081019050919050565b600060408284031215613b0157613b0061376d565b5b613b0b60406125cc565b9050600082015167ffffffffffffffff811115613b2b57613b2a613772565b5b613b37848285016137b9565b6000830152506020613b4b84828501613818565b60208301525092915050565b6000613b6a613b6584613abf565b6125cc565b90508083825260208201905060208402830185811115613b8d57613b8c613813565b5b835b81811015613bd457805167ffffffffffffffff811115613bb257613bb1612562565b5b808601613bbf8982613aeb565b85526020850194505050602081019050613b8f565b5050509392505050565b600082601f830112613bf357613bf2612562565b5b8151613c03848260208601613b57565b91505092915050565b600060208284031215613c2257613c21612302565b5b600082015167ffffffffffffffff811115613c4057613c3f612307565b5b613c4c84828501613bde565b91505092915050565b6000604082019050613c6a600083018561368f565b8181036020830152613c7c818461327b565b90509392505050565b7f6661696c65642064656c656761746543616c6c20746f20707265636f6d70696c60008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ce160218361326a565b9150613cec82613c85565b604082019050919050565b60006020820190508181036000830152613d1081613cd4565b9050919050565b613d2081612761565b82525050565b6000604082019050613d3b600083018561359a565b613d486020830184613d17565b9392505050565b6000604082019050613d64600083018561368f565b613d7160208301846135a9565b9392505050565b600060208284031215613d8e57613d8d612302565b5b600082015167ffffffffffffffff811115613dac57613dab612307565b5b613db884828501613960565b91505092915050565b613dca81612d5b565b82525050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613dfc57613dfb613dda565b5b83810192508235915060208301925067ffffffffffffffff821115613e2457613e23613dd0565b5b600182023603831315613e3a57613e39613dd5565b5b509250929050565b6000613e4e8385612f7a565b9350613e5b838584612618565b613e64836124f6565b840190509392505050565b6000613e7e6020840184612d86565b905092915050565b6000613e9560208401846123c9565b905092915050565b613ea6816123a6565b82525050565b600060a08301613ebf6000840184613ddf565b8583036000870152613ed2838284613e42565b92505050613ee36020840184613e6f565b613ef06020860182612e8a565b50613efe6040840184613e6f565b613f0b6040860182612e8a565b50613f196060840184613e86565b613f266060860182613e9d565b50613f346080840184613e86565b613f416080860182613e9d565b508091505092915050565b60006080820190508181036000830152613f66818761327b565b9050613f756020830186613dc1565b613f826040830185613dc1565b8181036060830152613f948184613eac565b905095945050505050565b600067ffffffffffffffff821115613fba57613fb961256c565b5b602082029050602081019050919050565b600081519050613fda81612d6f565b92915050565b600060408284031215613ff657613ff561376d565b5b61400060406125cc565b9050600061401084828501613818565b600083015250602061402484828501613844565b60208301525092915050565b6000606082840312156140465761404561376d565b5b61405060406125cc565b9050600061406084828501613fcb565b600083015250602061407484828501613fe0565b60208301525092915050565b600061409361408e84613f9f565b6125cc565b905080838252602082019050606084028301858111156140b6576140b5613813565b5b835b818110156140df57806140cb8882614030565b8452602084019350506060810190506140b8565b5050509392505050565b600082601f8301126140fe576140fd612562565b5b815161410e848260208601614080565b91505092915050565b600067ffffffffffffffff8211156141325761413161256c565b5b61413b826124f6565b9050602081019050919050565b600061415b61415684614117565b6125cc565b90508281526020810184848401111561417757614176612567565b5b6141828482856124cc565b509392505050565b600082601f83011261419f5761419e612562565b5b81516141af848260208601614148565b91505092915050565b6000604082840312156141ce576141cd61376d565b5b6141d860406125cc565b9050600082015167ffffffffffffffff8111156141f8576141f7613772565b5b6142048482850161418a565b600083015250602061421884828501613fcb565b60208301525092915050565b6000806040838503121561423b5761423a612302565b5b600083015167ffffffffffffffff81111561425957614258612307565b5b614265858286016140e9565b925050602083015167ffffffffffffffff81111561428657614285612307565b5b614292858286016141b8565b9150509250929050565b7f6661696c656420746f2073657420776974686472617720616464726573730000600082015250565b60006142d2601e8361326a565b91506142dd8261429c565b602082019050919050565b60006020820190508181036000830152614301816142c5565b9050919050565b600067ffffffffffffffff8211156143235761432261256c565b5b602082029050602081019050919050565b600061434761434284614308565b6125cc565b9050808382526020820190506020840283018581111561436a57614369613813565b5b835b818110156143b157805167ffffffffffffffff81111561438f5761438e612562565b5b80860161439c89826137b9565b8552602085019450505060208101905061436c565b5050509392505050565b600082601f8301126143d0576143cf612562565b5b81516143e0848260208601614334565b91505092915050565b6000602082840312156143ff576143fe612302565b5b600082015167ffffffffffffffff81111561441d5761441c612307565b5b614429848285016143bb565b91505092915050565b600061443d82612ba9565b915061444883612ba9565b925082820190507fffffffffffffffffffffffffffffffffffffffffffffffff80000000000000008112677fffffffffffffff8213171561448c5761448b613413565b5b92915050565b60006040820190506144a7600083018561368f565b6144b46020830184613d17565b9392505050565b60006144c682612ba9565b91506144d183612ba9565b92508282039050677fffffffffffffff81137fffffffffffffffffffffffffffffffffffffffffffffffff80000000000000008212171561451557614514613413565b5b92915050565b60006020828403121561453157614530612302565b5b600082015167ffffffffffffffff81111561454f5761454e612307565b5b61455b848285016137b9565b91505092915050565b600067ffffffffffffffff82111561457f5761457e61256c565b5b602082029050602081019050919050565b6000604082840312156145a6576145a561376d565b5b6145b060406125cc565b9050600082015167ffffffffffffffff8111156145d0576145cf613772565b5b6145dc848285016137b9565b600083015250602082015167ffffffffffffffff811115614600576145ff613772565b5b61460c84828501613960565b60208301525092915050565b600061462b61462684614564565b6125cc565b9050808382526020820190506020840283018581111561464e5761464d613813565b5b835b8181101561469557805167ffffffffffffffff81111561467357614672612562565b5b8086016146808982614590565b85526020850194505050602081019050614650565b5050509392505050565b600082601f8301126146b4576146b3612562565b5b81516146c4848260208601614618565b91505092915050565b600080604083850312156146e4576146e3612302565b5b600083015167ffffffffffffffff81111561470257614701612307565b5b61470e8582860161469f565b925050602083015167ffffffffffffffff81111561472f5761472e612307565b5b61473b85828601613960565b915050925092905056fea2646970667358221220a8fdbc3760bca6bed7c0d0a8bfa4c3e75e199774f0a60a0a34530a58ee2456ed64736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/testutil/contracts/DistributionCaller.sol b/precompiles/testutil/contracts/DistributionCaller.sol
new file mode 100644
index 00000000..a3f55076
--- /dev/null
+++ b/precompiles/testutil/contracts/DistributionCaller.sol
@@ -0,0 +1,379 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity >=0.8.17;
+
+import "../../distribution/DistributionI.sol" as distribution;
+import "../../common/Types.sol" as types;
+
+contract DistributionCaller {
+ int64 public counter;
+
+ function testSetWithdrawAddressFromContract(
+ string memory _withdrawAddr
+ ) public returns (bool) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.setWithdrawAddress(
+ address(this),
+ _withdrawAddr
+ );
+ }
+
+ function testWithdrawDelegatorRewardsFromContract(
+ string memory _valAddr
+ ) public returns (types.Coin[] memory) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(
+ address(this),
+ _valAddr
+ );
+ }
+
+ function testSetWithdrawAddress(
+ address _delAddr,
+ string memory _withdrawAddr
+ ) public returns (bool) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.setWithdrawAddress(
+ _delAddr,
+ _withdrawAddr
+ );
+ }
+
+ function testWithdrawDelegatorRewardsWithTransfer(
+ address payable _delAddr,
+ string memory _valAddr,
+ bool _before,
+ bool _after
+ ) public returns (types.Coin[] memory coins) {
+ if (_before) {
+ counter++;
+ (bool sent, ) = _delAddr.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ coins = distribution.DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(
+ _delAddr,
+ _valAddr
+ );
+ if (_after) {
+ counter++;
+ (bool sent, ) = _delAddr.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ return coins;
+ }
+
+ function revertWithdrawRewardsAndTransfer(
+ address payable _delAddr,
+ address payable _withdrawer,
+ string memory _valAddr,
+ bool _after
+ ) public {
+ try
+ DistributionCaller(address(this)).withdrawDelegatorRewardsAndRevert(
+ _delAddr,
+ _valAddr
+ )
+ {} catch {}
+ if (_after) {
+ counter++;
+ (bool sent, ) = _withdrawer.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+
+ function testWithdrawDelegatorRewards(
+ address _delAddr,
+ string memory _valAddr
+ ) public returns (types.Coin[] memory) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(
+ _delAddr,
+ _valAddr
+ );
+ }
+
+ function withdrawDelegatorRewardsAndRevert(
+ address _delAddr,
+ string memory _valAddr
+ ) external returns (types.Coin[] memory coins) {
+ coins = distribution.DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(
+ _delAddr,
+ _valAddr
+ );
+ revert();
+ }
+
+ function testWithdrawValidatorCommission(
+ string memory _valAddr
+ ) public returns (types.Coin[] memory) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.withdrawValidatorCommission(
+ _valAddr
+ );
+ }
+
+ function testWithdrawValidatorCommissionWithTransfer(
+ string memory _valAddr,
+ address payable _withdrawer,
+ bool _before,
+ bool _after
+ ) public returns (types.Coin[] memory coins) {
+ if (_before) {
+ counter++;
+ if (_withdrawer != address(this)) {
+ (bool sent, ) = _withdrawer.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+ coins = distribution.DISTRIBUTION_CONTRACT.withdrawValidatorCommission(
+ _valAddr
+ );
+ if (_after) {
+ counter++;
+ if (_withdrawer != address(this)) {
+ (bool sent, ) = _withdrawer.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+ return coins;
+ }
+
+ function testClaimRewards(
+ address _delAddr,
+ uint32 _maxRetrieve
+ ) public returns (bool success) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.claimRewards(
+ _delAddr,
+ _maxRetrieve
+ );
+ }
+
+ /// @dev testFundCommunityPool defines a method to allow an account to directly
+ /// fund the community pool.
+ /// @param depositor The address of the depositor
+ /// @param amount The amount of coin fund community pool
+ /// @return success Whether the transaction was successful or not
+ function testFundCommunityPool(
+ address depositor,
+ uint256 amount
+ ) public returns (bool success) {
+ counter += 1;
+ success = distribution.DISTRIBUTION_CONTRACT.fundCommunityPool(
+ depositor,
+ amount
+ );
+ counter -= 1;
+ return success;
+ }
+
+ function testClaimRewardsWithTransfer(
+ address payable _delAddr,
+ uint32 _maxRetrieve,
+ bool _before,
+ bool _after
+ ) public {
+ if (_before) {
+ counter++;
+ if (_delAddr != address(this)) {
+ (bool sent, ) = _delAddr.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+ bool success = distribution.DISTRIBUTION_CONTRACT.claimRewards(
+ _delAddr,
+ _maxRetrieve
+ );
+ require(success, "failed to claim rewards");
+ if (_after) {
+ counter++;
+ if (_delAddr != address(this)) {
+ (bool sent, ) = _delAddr.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+ }
+
+ /// @dev testFundCommunityPoolWithTransfer defines a method to allow an account to directly
+ /// fund the community pool and performs a transfer to the deposit.
+ /// @param depositor The address of the depositor
+ /// @param amount The amount of coin fund community pool
+ /// @param _before Boolean to specify if funds should be transferred to delegator before the precompile call
+ /// @param _after Boolean to specify if funds should be transferred to delegator after the precompile call
+ function testFundCommunityPoolWithTransfer(
+ address payable depositor,
+ uint256 amount,
+ bool _before,
+ bool _after
+ ) public {
+ if (_before) {
+ counter++;
+ (bool sent, ) = depositor.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ bool success = distribution.DISTRIBUTION_CONTRACT.fundCommunityPool(
+ depositor,
+ amount
+ );
+ require(success);
+ if (_after) {
+ counter++;
+ (bool sent, ) = depositor.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+
+ function getValidatorDistributionInfo(
+ string memory _valAddr
+ ) public view returns (distribution.ValidatorDistributionInfo memory) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.validatorDistributionInfo(
+ _valAddr
+ );
+ }
+
+ function getValidatorOutstandingRewards(
+ string memory _valAddr
+ ) public view returns (types.DecCoin[] memory) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.validatorOutstandingRewards(
+ _valAddr
+ );
+ }
+
+ function getValidatorCommission(
+ string memory _valAddr
+ ) public view returns (types.DecCoin[] memory) {
+ return distribution.DISTRIBUTION_CONTRACT.validatorCommission(_valAddr);
+ }
+
+ function getValidatorSlashes(
+ string memory _valAddr,
+ uint64 _startingHeight,
+ uint64 _endingHeight,
+ types.PageRequest calldata pageRequest
+ )
+ public
+ view
+ returns (
+ distribution.ValidatorSlashEvent[] memory,
+ distribution.PageResponse memory
+ )
+ {
+ return
+ distribution.DISTRIBUTION_CONTRACT.validatorSlashes(
+ _valAddr,
+ _startingHeight,
+ _endingHeight,
+ pageRequest
+ );
+ }
+
+ function getDelegationRewards(
+ address _delAddr,
+ string memory _valAddr
+ ) public view returns (types.DecCoin[] memory) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.delegationRewards(
+ _delAddr,
+ _valAddr
+ );
+ }
+
+ function getDelegationTotalRewards(
+ address _delAddr
+ )
+ public
+ view
+ returns (
+ distribution.DelegationDelegatorReward[] memory rewards,
+ types.DecCoin[] memory total
+ )
+ {
+ return
+ distribution.DISTRIBUTION_CONTRACT.delegationTotalRewards(_delAddr);
+ }
+
+ function getDelegatorValidators(
+ address _delAddr
+ ) public view returns (string[] memory) {
+ return distribution.DISTRIBUTION_CONTRACT.delegatorValidators(_delAddr);
+ }
+
+ function getDelegatorWithdrawAddress(
+ address _delAddr
+ ) public view returns (string memory) {
+ return
+ distribution.DISTRIBUTION_CONTRACT.delegatorWithdrawAddress(
+ _delAddr
+ );
+ }
+
+ // testRevertState allows sender to change the withdraw address
+ // and then tries to withdraw other user delegation rewards
+ function testRevertState(
+ string memory _withdrawAddr,
+ address _delAddr,
+ string memory _valAddr
+ ) public returns (types.Coin[] memory) {
+ bool success = distribution.DISTRIBUTION_CONTRACT.setWithdrawAddress(
+ msg.sender,
+ _withdrawAddr
+ );
+ require(success, "failed to set withdraw address");
+
+ return
+ distribution.DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(
+ _delAddr,
+ _valAddr
+ );
+ }
+
+ function delegateCallSetWithdrawAddress(
+ address _delAddr,
+ string memory _withdrawAddr
+ ) public {
+ (bool success, ) = distribution
+ .DISTRIBUTION_PRECOMPILE_ADDRESS
+ .delegatecall(
+ abi.encodeWithSignature(
+ "setWithdrawAddress(address,string)",
+ _delAddr,
+ _withdrawAddr
+ )
+ );
+ require(success, "failed delegateCall to precompile");
+ }
+
+ function staticCallSetWithdrawAddress(
+ address _delAddr,
+ string memory _withdrawAddr
+ ) public view {
+ (bool success, ) = distribution
+ .DISTRIBUTION_PRECOMPILE_ADDRESS
+ .staticcall(
+ abi.encodeWithSignature(
+ "setWithdrawAddress(address,string)",
+ _delAddr,
+ _withdrawAddr
+ )
+ );
+ require(success, "failed staticCall to precompile");
+ }
+
+ function staticCallGetWithdrawAddress(
+ address _delAddr
+ ) public view returns (bytes memory) {
+ (bool success, bytes memory data) = distribution
+ .DISTRIBUTION_PRECOMPILE_ADDRESS
+ .staticcall(
+ abi.encodeWithSignature(
+ "delegatorWithdrawAddress(address)",
+ _delAddr
+ )
+ );
+ require(success, "failed staticCall to precompile");
+ return data;
+ }
+
+ function deposit() public payable {}
+}
diff --git a/precompiles/testutil/contracts/FlashLoan.json b/precompiles/testutil/contracts/FlashLoan.json
new file mode 100644
index 00000000..383dc5f9
--- /dev/null
+++ b/precompiles/testutil/contracts/FlashLoan.json
@@ -0,0 +1,110 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "FlashLoan",
+ "sourceName": "solidity/precompiles/testutil/contracts/FlashLoan.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_delegator",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validator",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "delegateWithRevert",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validator",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "flashLoan",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_validator",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "flashLoanWithRevert",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506113ea806100606000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80638da5cb5b146100515780638f5184301461006f578063ee52ad711461008b578063f12fae93146100bb575b600080fd5b6100596100eb565b6040516100669190610bdd565b60405180910390f35b61008960048036038101906100849190610db4565b61010f565b005b6100a560048036038101906100a09190610db4565b6101da565b6040516100b29190610e3e565b60405180910390f35b6100d560048036038101906100d09190610db4565b6107c9565b6040516100e29190610e3e565b60405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8585856040518463ffffffff1660e01b815260040161015093929190610ee7565b6020604051808303816000875af115801561016f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101939190610f51565b9050806101d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101cc90610fca565b60405180910390fd5b600080fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461026b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102629061105c565b60405180910390fd5b6000849050828173ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b81526004016102ac92919061107c565b602060405180830381865afa1580156102c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ed91906110ba565b101561032e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032590611133565b60405180910390fd5b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016103699190610bdd565b602060405180830381865afa158015610386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103aa91906110ba565b905060008273ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b81526004016103eb93929190611153565b6020604051808303816000875af115801561040a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042e9190610f51565b905080610470576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610467906111fc565b60405180910390fd5b848261047c919061124b565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016104b59190610bdd565b602060405180830381865afa1580156104d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f691906110ba565b14610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d906112cb565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3388886040518463ffffffff1660e01b815260040161057593929190610ee7565b6020604051808303816000875af1158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190610f51565b9050806105fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105f190610fca565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016106339190610bdd565b602060405180830381865afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067491906110ba565b91508273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33876040518363ffffffff1660e01b81526004016106b19291906112eb565b6020604051808303816000875af11580156106d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f49190610f51565b5084826107019190611314565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161073a9190610bdd565b602060405180830381865afa158015610757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077b91906110ba565b146107bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b290611394565b60405180910390fd5b600193505050509392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461085a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108519061105c565b60405180910390fd5b6000849050828173ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b815260040161089b92919061107c565b602060405180830381865afa1580156108b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dc91906110ba565b101561091d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091490611133565b60405180910390fd5b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109589190610bdd565b602060405180830381865afa158015610975573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099991906110ba565b905060008273ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b81526004016109da93929190611153565b6020604051808303816000875af11580156109f9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1d9190610f51565b905080610a5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a56906111fc565b60405180910390fd5b8482610a6b919061124b565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610aa49190610bdd565b602060405180830381865afa158015610ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae591906110ba565b14610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c906112cb565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16638f5184303388886040518463ffffffff1660e01b8152600401610b6293929190610ee7565b600060405180830381600087803b158015610b7c57600080fd5b505af1925050508015610b8d575060015b50600193505050509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610bc782610b9c565b9050919050565b610bd781610bbc565b82525050565b6000602082019050610bf26000830184610bce565b92915050565b6000604051905090565b600080fd5b600080fd5b610c1581610bbc565b8114610c2057600080fd5b50565b600081359050610c3281610c0c565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610c8b82610c42565b810181811067ffffffffffffffff82111715610caa57610ca9610c53565b5b80604052505050565b6000610cbd610bf8565b9050610cc98282610c82565b919050565b600067ffffffffffffffff821115610ce957610ce8610c53565b5b610cf282610c42565b9050602081019050919050565b82818337600083830152505050565b6000610d21610d1c84610cce565b610cb3565b905082815260208101848484011115610d3d57610d3c610c3d565b5b610d48848285610cff565b509392505050565b600082601f830112610d6557610d64610c38565b5b8135610d75848260208601610d0e565b91505092915050565b6000819050919050565b610d9181610d7e565b8114610d9c57600080fd5b50565b600081359050610dae81610d88565b92915050565b600080600060608486031215610dcd57610dcc610c02565b5b6000610ddb86828701610c23565b935050602084013567ffffffffffffffff811115610dfc57610dfb610c07565b5b610e0886828701610d50565b9250506040610e1986828701610d9f565b9150509250925092565b60008115159050919050565b610e3881610e23565b82525050565b6000602082019050610e536000830184610e2f565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610e93578082015181840152602081019050610e78565b60008484015250505050565b6000610eaa82610e59565b610eb48185610e64565b9350610ec4818560208601610e75565b610ecd81610c42565b840191505092915050565b610ee181610d7e565b82525050565b6000606082019050610efc6000830186610bce565b8181036020830152610f0e8185610e9f565b9050610f1d6040830184610ed8565b949350505050565b610f2e81610e23565b8114610f3957600080fd5b50565b600081519050610f4b81610f25565b92915050565b600060208284031215610f6757610f66610c02565b5b6000610f7584828501610f3c565b91505092915050565b7f6661696c656420746f2064656c65676174650000000000000000000000000000600082015250565b6000610fb4601283610e64565b9150610fbf82610f7e565b602082019050919050565b60006020820190508181036000830152610fe381610fa7565b9050919050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f60008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000611046602183610e64565b915061105182610fea565b604082019050919050565b6000602082019050818103600083015261107581611039565b9050919050565b60006040820190506110916000830185610bce565b61109e6020830184610bce565b9392505050565b6000815190506110b481610d88565b92915050565b6000602082840312156110d0576110cf610c02565b5b60006110de848285016110a5565b91505092915050565b7f496e73756666696369656e7420616c6c6f77616e636500000000000000000000600082015250565b600061111d601683610e64565b9150611128826110e7565b602082019050919050565b6000602082019050818103600083015261114c81611110565b9050919050565b60006060820190506111686000830186610bce565b6111756020830185610bce565b6111826040830184610ed8565b949350505050565b7f4661696c656420746f207472616e7366657220746f6b656e7320666f7220666c60008201527f617368206c6f616e000000000000000000000000000000000000000000000000602082015250565b60006111e6602883610e64565b91506111f18261118a565b604082019050919050565b60006020820190508181036000830152611215816111d9565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061125682610d7e565b915061126183610d7e565b92508282019050808211156112795761127861121c565b5b92915050565b7f466c617368206c6f616e206661696c6564000000000000000000000000000000600082015250565b60006112b5601183610e64565b91506112c08261127f565b602082019050919050565b600060208201905081810360008301526112e4816112a8565b9050919050565b60006040820190506113006000830185610bce565b61130d6020830184610ed8565b9392505050565b600061131f82610d7e565b915061132a83610d7e565b92508282039050818111156113425761134161121c565b5b92915050565b7f466c617368206c6f616e2072657061796d656e74206661696c65640000000000600082015250565b600061137e601b83610e64565b915061138982611348565b602082019050919050565b600060208201905081810360008301526113ad81611371565b905091905056fea26469706673582212208e1d52c36a32622af075b98cf15a237fb7323d1e2ace6e9cb8d762d107b21e9864736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80638da5cb5b146100515780638f5184301461006f578063ee52ad711461008b578063f12fae93146100bb575b600080fd5b6100596100eb565b6040516100669190610bdd565b60405180910390f35b61008960048036038101906100849190610db4565b61010f565b005b6100a560048036038101906100a09190610db4565b6101da565b6040516100b29190610e3e565b60405180910390f35b6100d560048036038101906100d09190610db4565b6107c9565b6040516100e29190610e3e565b60405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb8585856040518463ffffffff1660e01b815260040161015093929190610ee7565b6020604051808303816000875af115801561016f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101939190610f51565b9050806101d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101cc90610fca565b60405180910390fd5b600080fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461026b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102629061105c565b60405180910390fd5b6000849050828173ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b81526004016102ac92919061107c565b602060405180830381865afa1580156102c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ed91906110ba565b101561032e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032590611133565b60405180910390fd5b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016103699190610bdd565b602060405180830381865afa158015610386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103aa91906110ba565b905060008273ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b81526004016103eb93929190611153565b6020604051808303816000875af115801561040a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042e9190610f51565b905080610470576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610467906111fc565b60405180910390fd5b848261047c919061124b565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016104b59190610bdd565b602060405180830381865afa1580156104d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f691906110ba565b14610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d906112cb565b60405180910390fd5b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb3388886040518463ffffffff1660e01b815260040161057593929190610ee7565b6020604051808303816000875af1158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190610f51565b9050806105fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105f190610fca565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016106339190610bdd565b602060405180830381865afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067491906110ba565b91508273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33876040518363ffffffff1660e01b81526004016106b19291906112eb565b6020604051808303816000875af11580156106d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f49190610f51565b5084826107019190611314565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161073a9190610bdd565b602060405180830381865afa158015610757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077b91906110ba565b146107bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b290611394565b60405180910390fd5b600193505050509392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461085a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108519061105c565b60405180910390fd5b6000849050828173ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b815260040161089b92919061107c565b602060405180830381865afa1580156108b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dc91906110ba565b101561091d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091490611133565b60405180910390fd5b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109589190610bdd565b602060405180830381865afa158015610975573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099991906110ba565b905060008273ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b81526004016109da93929190611153565b6020604051808303816000875af11580156109f9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1d9190610f51565b905080610a5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a56906111fc565b60405180910390fd5b8482610a6b919061124b565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610aa49190610bdd565b602060405180830381865afa158015610ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae591906110ba565b14610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c906112cb565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16638f5184303388886040518463ffffffff1660e01b8152600401610b6293929190610ee7565b600060405180830381600087803b158015610b7c57600080fd5b505af1925050508015610b8d575060015b50600193505050509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610bc782610b9c565b9050919050565b610bd781610bbc565b82525050565b6000602082019050610bf26000830184610bce565b92915050565b6000604051905090565b600080fd5b600080fd5b610c1581610bbc565b8114610c2057600080fd5b50565b600081359050610c3281610c0c565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610c8b82610c42565b810181811067ffffffffffffffff82111715610caa57610ca9610c53565b5b80604052505050565b6000610cbd610bf8565b9050610cc98282610c82565b919050565b600067ffffffffffffffff821115610ce957610ce8610c53565b5b610cf282610c42565b9050602081019050919050565b82818337600083830152505050565b6000610d21610d1c84610cce565b610cb3565b905082815260208101848484011115610d3d57610d3c610c3d565b5b610d48848285610cff565b509392505050565b600082601f830112610d6557610d64610c38565b5b8135610d75848260208601610d0e565b91505092915050565b6000819050919050565b610d9181610d7e565b8114610d9c57600080fd5b50565b600081359050610dae81610d88565b92915050565b600080600060608486031215610dcd57610dcc610c02565b5b6000610ddb86828701610c23565b935050602084013567ffffffffffffffff811115610dfc57610dfb610c07565b5b610e0886828701610d50565b9250506040610e1986828701610d9f565b9150509250925092565b60008115159050919050565b610e3881610e23565b82525050565b6000602082019050610e536000830184610e2f565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610e93578082015181840152602081019050610e78565b60008484015250505050565b6000610eaa82610e59565b610eb48185610e64565b9350610ec4818560208601610e75565b610ecd81610c42565b840191505092915050565b610ee181610d7e565b82525050565b6000606082019050610efc6000830186610bce565b8181036020830152610f0e8185610e9f565b9050610f1d6040830184610ed8565b949350505050565b610f2e81610e23565b8114610f3957600080fd5b50565b600081519050610f4b81610f25565b92915050565b600060208284031215610f6757610f66610c02565b5b6000610f7584828501610f3c565b91505092915050565b7f6661696c656420746f2064656c65676174650000000000000000000000000000600082015250565b6000610fb4601283610e64565b9150610fbf82610f7e565b602082019050919050565b60006020820190508181036000830152610fe381610fa7565b9050919050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f60008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000611046602183610e64565b915061105182610fea565b604082019050919050565b6000602082019050818103600083015261107581611039565b9050919050565b60006040820190506110916000830185610bce565b61109e6020830184610bce565b9392505050565b6000815190506110b481610d88565b92915050565b6000602082840312156110d0576110cf610c02565b5b60006110de848285016110a5565b91505092915050565b7f496e73756666696369656e7420616c6c6f77616e636500000000000000000000600082015250565b600061111d601683610e64565b9150611128826110e7565b602082019050919050565b6000602082019050818103600083015261114c81611110565b9050919050565b60006060820190506111686000830186610bce565b6111756020830185610bce565b6111826040830184610ed8565b949350505050565b7f4661696c656420746f207472616e7366657220746f6b656e7320666f7220666c60008201527f617368206c6f616e000000000000000000000000000000000000000000000000602082015250565b60006111e6602883610e64565b91506111f18261118a565b604082019050919050565b60006020820190508181036000830152611215816111d9565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061125682610d7e565b915061126183610d7e565b92508282019050808211156112795761127861121c565b5b92915050565b7f466c617368206c6f616e206661696c6564000000000000000000000000000000600082015250565b60006112b5601183610e64565b91506112c08261127f565b602082019050919050565b600060208201905081810360008301526112e4816112a8565b9050919050565b60006040820190506113006000830185610bce565b61130d6020830184610ed8565b9392505050565b600061131f82610d7e565b915061132a83610d7e565b92508282039050818111156113425761134161121c565b5b92915050565b7f466c617368206c6f616e2072657061796d656e74206661696c65640000000000600082015250565b600061137e601b83610e64565b915061138982611348565b602082019050919050565b600060208201905081810360008301526113ad81611371565b905091905056fea26469706673582212208e1d52c36a32622af075b98cf15a237fb7323d1e2ace6e9cb8d762d107b21e9864736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/testutil/contracts/FlashLoan.sol b/precompiles/testutil/contracts/FlashLoan.sol
new file mode 100644
index 00000000..177cdd3e
--- /dev/null
+++ b/precompiles/testutil/contracts/FlashLoan.sol
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity ^0.8.17;
+
+import "../../staking/StakingI.sol" as staking;
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+
+contract FlashLoan {
+ address public owner;
+
+ constructor() {
+ owner = msg.sender;
+ }
+
+ function flashLoan(
+ address _token,
+ string memory _validator,
+ uint256 _amount
+ ) public returns (bool) {
+ require(msg.sender == owner, "Only owner can call this function");
+
+ // Get some tokens to initiate the flash loan
+ IERC20 token = IERC20(_token);
+ require(
+ token.allowance(msg.sender, address(this)) >= _amount,
+ "Insufficient allowance"
+ );
+
+ uint256 balancePre = token.balanceOf(address(this));
+ bool success = token.transferFrom(msg.sender, address(this), _amount);
+ require(success, "Failed to transfer tokens for flash loan");
+ require(
+ token.balanceOf(address(this)) == balancePre + _amount,
+ "Flash loan failed"
+ );
+
+ // Execute some precompile logic (e.g. staking)
+ success = staking.STAKING_CONTRACT.delegate(
+ msg.sender,
+ _validator,
+ _amount
+ );
+ require(success, "failed to delegate");
+
+ // Transfer tokens back to end the flash loan
+ balancePre = token.balanceOf(address(this));
+ token.transfer(msg.sender, _amount);
+ require(
+ token.balanceOf(address(this)) == balancePre - _amount,
+ "Flash loan repayment failed"
+ );
+
+ return true;
+ }
+
+ function flashLoanWithRevert(
+ address _token,
+ string memory _validator,
+ uint256 _amount
+ ) public returns (bool) {
+ require(msg.sender == owner, "Only owner can call this function");
+
+ // Get some tokens to initiate the flash loan
+ IERC20 token = IERC20(_token);
+ require(
+ token.allowance(msg.sender, address(this)) >= _amount,
+ "Insufficient allowance"
+ );
+
+ uint256 balancePre = token.balanceOf(address(this));
+ bool success = token.transferFrom(msg.sender, address(this), _amount);
+ require(success, "Failed to transfer tokens for flash loan");
+ require(
+ token.balanceOf(address(this)) == balancePre + _amount,
+ "Flash loan failed"
+ );
+
+ try
+ FlashLoan(address(this)).delegateWithRevert(
+ msg.sender,
+ _validator,
+ _amount
+ )
+ {} catch {}
+
+ return true;
+ }
+
+ function delegateWithRevert(
+ address _delegator,
+ string memory _validator,
+ uint256 _amount
+ ) external {
+ // Execute some precompile logic and revert (e.g. staking)
+ bool success = staking.STAKING_CONTRACT.delegate(
+ _delegator,
+ _validator,
+ _amount
+ );
+ require(success, "failed to delegate");
+ revert();
+ }
+}
diff --git a/precompiles/testutil/contracts/ICounter.sol b/precompiles/testutil/contracts/ICounter.sol
new file mode 100644
index 00000000..604ffece
--- /dev/null
+++ b/precompiles/testutil/contracts/ICounter.sol
@@ -0,0 +1,9 @@
+pragma solidity ^0.8.17;
+
+interface ICounter {
+ function add() external;
+ function subtract() external;
+ function getCounter() external view returns (uint256);
+ event Changed(uint256 counter);
+ event Added(uint256 counter);
+}
diff --git a/precompiles/testutil/contracts/InterchainSender.json b/precompiles/testutil/contracts/InterchainSender.json
new file mode 100644
index 00000000..b07d6123
--- /dev/null
+++ b/precompiles/testutil/contracts/InterchainSender.json
@@ -0,0 +1,565 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "InterchainSender",
+ "sourceName": "solidity/precompiles/testutil/contracts/InterchainSender.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "name": "counter",
+ "outputs": [
+ {
+ "internalType": "int64",
+ "name": "",
+ "type": "int64"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ }
+ ],
+ "name": "testAllowance",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "spendLimit",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowList",
+ "type": "string[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowedPacketData",
+ "type": "string[]"
+ }
+ ],
+ "internalType": "struct ICS20Allocation[]",
+ "name": "allocations",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin[]",
+ "name": "spendLimit",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowList",
+ "type": "string[]"
+ },
+ {
+ "internalType": "string[]",
+ "name": "allowedPacketData",
+ "type": "string[]"
+ }
+ ],
+ "internalType": "struct ICS20Allocation[]",
+ "name": "allocs",
+ "type": "tuple[]"
+ }
+ ],
+ "name": "testApprove",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testDecreaseAllowance",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "trace",
+ "type": "string"
+ }
+ ],
+ "name": "testDenomHash",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "hash",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "hash",
+ "type": "string"
+ }
+ ],
+ "name": "testDenomTrace",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "path",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "baseDenom",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct DenomTrace",
+ "name": "denomTrace",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "key",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "offset",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "limit",
+ "type": "uint64"
+ },
+ {
+ "internalType": "bool",
+ "name": "countTotal",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "reverse",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct PageRequest",
+ "name": "pageRequest",
+ "type": "tuple"
+ }
+ ],
+ "name": "testDenomTraces",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "path",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "baseDenom",
+ "type": "string"
+ }
+ ],
+ "internalType": "struct DenomTrace[]",
+ "name": "denomTraces",
+ "type": "tuple[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "bytes",
+ "name": "nextKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint64",
+ "name": "total",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct PageResponse",
+ "name": "pageResponse",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "testIncreaseAllowance",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_between",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testMultiTransferWithInternalTransfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "testRevoke",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint64",
+ "name": "revisionNumber",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "revisionHeight",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct Height",
+ "name": "timeoutHeight",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint64",
+ "name": "timeoutTimestamp",
+ "type": "uint64"
+ },
+ {
+ "internalType": "string",
+ "name": "memo",
+ "type": "string"
+ }
+ ],
+ "name": "testTransferContractFunds",
+ "outputs": [
+ {
+ "internalType": "uint64",
+ "name": "nextSequence",
+ "type": "uint64"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_otherAcc",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "_before",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_after",
+ "type": "bool"
+ }
+ ],
+ "name": "testTransferFundsWithTransferToOtherAcc",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint64",
+ "name": "revisionNumber",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "revisionHeight",
+ "type": "uint64"
+ }
+ ],
+ "internalType": "struct Height",
+ "name": "timeoutHeight",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint64",
+ "name": "timeoutTimestamp",
+ "type": "uint64"
+ },
+ {
+ "internalType": "string",
+ "name": "memo",
+ "type": "string"
+ }
+ ],
+ "name": "testTransferUserFunds",
+ "outputs": [
+ {
+ "internalType": "uint64",
+ "name": "nextSequence",
+ "type": "uint64"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b50613818806100206000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063a363df841161008c578063dfa10f3911610066578063dfa10f3914610210578063ee5766d914610241578063f298e7a814610271578063f3675f081461028d576100cf565b8063a363df8414610194578063b9672879146101c4578063c595699a146101e0576100cf565b80631dba685b146100d4578063424af9f6146100f057806361bc221a1461010c5780636fdf23cc1461012a5780637492bdd81461015a5780637a6185e11461018a575b600080fd5b6100ee60048036038101906100e99190611302565b6102a9565b005b61010a6004803603810190610105919061149c565b61070f565b005b6101146107e9565b6040516101219190611581565b60405180910390f35b610144600480360381019061013f9190611636565b6107fa565b6040516101519190611788565b60405180910390f35b610174600480360381019061016f9190611636565b610898565b6040516101819190611788565b60405180910390f35b610192610936565b005b6101ae60048036038101906101a991906117e1565b6109fb565b6040516101bb9190611bc4565b60405180910390f35b6101de60048036038101906101d99190611be6565b610a88565b005b6101fa60048036038101906101f59190611d20565b610d4b565b6040516102079190611db3565b60405180910390f35b61022a60048036038101906102259190611df9565b610dd5565b604051610238929190611fe9565b60405180910390f35b61025b60048036038101906102569190611d20565b610e69565b6040516102689190612064565b60405180910390f35b61028b6004803603810190610286919061149c565b610ef9565b005b6102a760048036038101906102a291906120dc565b610fd3565b005b82156103a65760008081819054906101000a900460070b809291906102cd90612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008973ffffffffffffffffffffffffffffffffffffffff16600f60405161031e906121b9565b60006040518083038185875af1925050503d806000811461035b576040519150601f19603f3d011682016040523d82523d6000602084013e610360565b606091505b50509050806103a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039b90612240565b60405180910390fd5b505b60006040518060400160405280606467ffffffffffffffff168152602001606467ffffffffffffffff16815250905061080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a60028b610403919061228f565b8f8b8860006040518963ffffffff1660e01b815260040161042b9897969594939291906123bb565b6020604051808303816000875af115801561044a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046e919061247f565b50821561056c5760008081819054906101000a900460070b8092919061049390612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008a73ffffffffffffffffffffffffffffffffffffffff16600f6040516104e4906121b9565b60006040518083038185875af1925050503d8060008114610521576040519150601f19603f3d011682016040523d82523d6000602084013e610526565b606091505b505090508061056a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056190612240565b60405180910390fd5b505b61080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a60028b61059a919061228f565b8f8b8860006040518963ffffffff1660e01b81526004016105c29897969594939291906123bb565b6020604051808303816000875af11580156105e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610605919061247f565b5081156107035760008081819054906101000a900460070b8092919061062a90612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008a73ffffffffffffffffffffffffffffffffffffffff16600f60405161067b906121b9565b60006040518083038185875af1925050503d80600081146106b8576040519150601f19603f3d011682016040523d82523d6000602084013e6106bd565b606091505b5050905080610701576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106f890612240565b60405180910390fd5b505b50505050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff166354de647b308a8a8a8a8a8a8a6040518963ffffffff1660e01b815260040161075a9897969594939291906124e8565b6020604051808303816000875af1158015610779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079d919061256b565b9050806107df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107d6906125e4565b60405180910390fd5b5050505050505050565b60008054906101000a900460070b81565b600061080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a8a308b8b8b8b6040518a63ffffffff1660e01b815260040161084799989796959493929190612604565b6020604051808303816000875af1158015610866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088a919061247f565b905098975050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a8a338b8b8b8b6040518a63ffffffff1660e01b81526004016108e599989796959493929190612604565b6020604051808303816000875af1158015610904573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610928919061247f565b905098975050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff166374a8f103306040518263ffffffff1660e01b815260040161097391906126b5565b6020604051808303816000875af1158015610992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b6919061256b565b9050806109f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ef9061271c565b60405180910390fd5b50565b606061080273ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e84846040518363ffffffff1660e01b8152600401610a3a92919061273c565b600060405180830381865afa158015610a57573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a809190612c11565b905092915050565b8115610b855760008081819054906101000a900460070b80929190610aac90612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008973ffffffffffffffffffffffffffffffffffffffff16600f604051610afd906121b9565b60006040518083038185875af1925050503d8060008114610b3a576040519150601f19603f3d011682016040523d82523d6000602084013e610b3f565b606091505b5050905080610b83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7a90612240565b60405180910390fd5b505b60006040518060400160405280606467ffffffffffffffff168152602001606467ffffffffffffffff16815250905061080273ffffffffffffffffffffffffffffffffffffffff1663632535b9898989898e8a8860006040518963ffffffff1660e01b8152600401610bfe989796959493929190612c5a565b6020604051808303816000875af1158015610c1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c41919061247f565b508115610d3f5760008081819054906101000a900460070b80929190610c6690612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008a73ffffffffffffffffffffffffffffffffffffffff16600f604051610cb7906121b9565b60006040518083038185875af1925050503d8060008114610cf4576040519150601f19603f3d011682016040523d82523d6000602084013e610cf9565b606091505b5050905080610d3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3490612240565b60405180910390fd5b505b50505050505050505050565b606061080273ffffffffffffffffffffffffffffffffffffffff1663b5cb6e7d836040518263ffffffff1660e01b8152600401610d889190611db3565b600060405180830381865afa158015610da5573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610dce9190612d09565b9050919050565b6060610ddf61109e565b61080273ffffffffffffffffffffffffffffffffffffffff166322b6fad6846040518263ffffffff1660e01b8152600401610e1a9190612ece565b600060405180830381865afa158015610e37573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610e609190613166565b91509150915091565b610e716110c2565b61080273ffffffffffffffffffffffffffffffffffffffff1663a815cdd9836040518263ffffffff1660e01b8152600401610eac9190611db3565b600060405180830381865afa158015610ec9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610ef291906131de565b9050919050565b600061080273ffffffffffffffffffffffffffffffffffffffff1663b3f536ec308a8a8a8a8a8a8a6040518963ffffffff1660e01b8152600401610f449897969594939291906124e8565b6020604051808303816000875af1158015610f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f87919061256b565b905080610fc9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc090613273565b60405180910390fd5b5050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff1663473c90c73085856040518463ffffffff1660e01b815260040161101493929190613744565b6020604051808303816000875af1158015611033573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611057919061256b565b905080611099576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611090906137c2565b60405180910390fd5b505050565b604051806040016040528060608152602001600067ffffffffffffffff1681525090565b604051806040016040528060608152602001606081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061111b826110f0565b9050919050565b61112b81611110565b811461113657600080fd5b50565b60008135905061114881611122565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6111a182611158565b810181811067ffffffffffffffff821117156111c0576111bf611169565b5b80604052505050565b60006111d36110dc565b90506111df8282611198565b919050565b600067ffffffffffffffff8211156111ff576111fe611169565b5b61120882611158565b9050602081019050919050565b82818337600083830152505050565b6000611237611232846111e4565b6111c9565b90508281526020810184848401111561125357611252611153565b5b61125e848285611215565b509392505050565b600082601f83011261127b5761127a61114e565b5b813561128b848260208601611224565b91505092915050565b6000819050919050565b6112a781611294565b81146112b257600080fd5b50565b6000813590506112c48161129e565b92915050565b60008115159050919050565b6112df816112ca565b81146112ea57600080fd5b50565b6000813590506112fc816112d6565b92915050565b60008060008060008060008060006101208a8c031215611325576113246110e6565b5b60006113338c828d01611139565b99505060208a013567ffffffffffffffff811115611354576113536110eb565b5b6113608c828d01611266565b98505060408a013567ffffffffffffffff811115611381576113806110eb565b5b61138d8c828d01611266565b97505060608a013567ffffffffffffffff8111156113ae576113ad6110eb565b5b6113ba8c828d01611266565b96505060806113cb8c828d016112b5565b95505060a08a013567ffffffffffffffff8111156113ec576113eb6110eb565b5b6113f88c828d01611266565b94505060c06114098c828d016112ed565b93505060e061141a8c828d016112ed565b92505061010061142c8c828d016112ed565b9150509295985092959850929598565b600080fd5b600080fd5b60008083601f84011261145c5761145b61114e565b5b8235905067ffffffffffffffff8111156114795761147861143c565b5b60208301915083600182028301111561149557611494611441565b5b9250929050565b60008060008060008060006080888a0312156114bb576114ba6110e6565b5b600088013567ffffffffffffffff8111156114d9576114d86110eb565b5b6114e58a828b01611446565b9750975050602088013567ffffffffffffffff811115611508576115076110eb565b5b6115148a828b01611446565b9550955050604088013567ffffffffffffffff811115611537576115366110eb565b5b6115438a828b01611446565b935093505060606115568a828b016112b5565b91505092959891949750929550565b60008160070b9050919050565b61157b81611565565b82525050565b60006020820190506115966000830184611572565b92915050565b600080fd5b600080fd5b600067ffffffffffffffff82169050919050565b6115c3816115a6565b81146115ce57600080fd5b50565b6000813590506115e0816115ba565b92915050565b6000604082840312156115fc576115fb61159c565b5b61160660406111c9565b90506000611616848285016115d1565b600083015250602061162a848285016115d1565b60208301525092915050565b600080600080600080600080610120898b031215611657576116566110e6565b5b600089013567ffffffffffffffff811115611675576116746110eb565b5b6116818b828c01611266565b985050602089013567ffffffffffffffff8111156116a2576116a16110eb565b5b6116ae8b828c01611266565b975050604089013567ffffffffffffffff8111156116cf576116ce6110eb565b5b6116db8b828c01611266565b96505060606116ec8b828c016112b5565b955050608089013567ffffffffffffffff81111561170d5761170c6110eb565b5b6117198b828c01611266565b94505060a061172a8b828c016115e6565b93505060e061173b8b828c016115d1565b92505061010089013567ffffffffffffffff81111561175d5761175c6110eb565b5b6117698b828c01611266565b9150509295985092959890939650565b611782816115a6565b82525050565b600060208201905061179d6000830184611779565b92915050565b60006117ae826110f0565b9050919050565b6117be816117a3565b81146117c957600080fd5b50565b6000813590506117db816117b5565b92915050565b600080604083850312156117f8576117f76110e6565b5b6000611806858286016117cc565b9250506020611817858286016117cc565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561188757808201518184015260208101905061186c565b60008484015250505050565b600061189e8261184d565b6118a88185611858565b93506118b8818560208601611869565b6118c181611158565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61190181611294565b82525050565b600060408301600083015184820360008601526119248282611893565b915050602083015161193960208601826118f8565b508091505092915050565b60006119508383611907565b905092915050565b6000602082019050919050565b6000611970826118cc565b61197a81856118d7565b93508360208202850161198c856118e8565b8060005b858110156119c857848403895281516119a98582611944565b94506119b483611958565b925060208a01995050600181019050611990565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611a128383611893565b905092915050565b6000602082019050919050565b6000611a32826119da565b611a3c81856119e5565b935083602082028501611a4e856119f6565b8060005b85811015611a8a5784840389528151611a6b8582611a06565b9450611a7683611a1a565b925060208a01995050600181019050611a52565b50829750879550505050505092915050565b600060a0830160008301518482036000860152611ab98282611893565b91505060208301518482036020860152611ad38282611893565b91505060408301518482036040860152611aed8282611965565b91505060608301518482036060860152611b078282611a27565b91505060808301518482036080860152611b218282611a27565b9150508091505092915050565b6000611b3a8383611a9c565b905092915050565b6000602082019050919050565b6000611b5a82611821565b611b64818561182c565b935083602082028501611b768561183d565b8060005b85811015611bb25784840389528151611b938582611b2e565b9450611b9e83611b42565b925060208a01995050600181019050611b7a565b50829750879550505050505092915050565b60006020820190508181036000830152611bde8184611b4f565b905092915050565b60008060008060008060008060006101208a8c031215611c0957611c086110e6565b5b6000611c178c828d01611139565b9950506020611c288c828d016117cc565b98505060408a013567ffffffffffffffff811115611c4957611c486110eb565b5b611c558c828d01611266565b97505060608a013567ffffffffffffffff811115611c7657611c756110eb565b5b611c828c828d01611266565b96505060808a013567ffffffffffffffff811115611ca357611ca26110eb565b5b611caf8c828d01611266565b95505060a0611cc08c828d016112b5565b94505060c08a013567ffffffffffffffff811115611ce157611ce06110eb565b5b611ced8c828d01611266565b93505060e0611cfe8c828d016112ed565b925050610100611d108c828d016112ed565b9150509295985092959850929598565b600060208284031215611d3657611d356110e6565b5b600082013567ffffffffffffffff811115611d5457611d536110eb565b5b611d6084828501611266565b91505092915050565b600082825260208201905092915050565b6000611d858261184d565b611d8f8185611d69565b9350611d9f818560208601611869565b611da881611158565b840191505092915050565b60006020820190508181036000830152611dcd8184611d7a565b905092915050565b600080fd5b600060a08284031215611df057611def611dd5565b5b81905092915050565b600060208284031215611e0f57611e0e6110e6565b5b600082013567ffffffffffffffff811115611e2d57611e2c6110eb565b5b611e3984828501611dda565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152611e8b8282611893565b91505060208301518482036020860152611ea58282611893565b9150508091505092915050565b6000611ebe8383611e6e565b905092915050565b6000602082019050919050565b6000611ede82611e42565b611ee88185611e4d565b935083602082028501611efa85611e5e565b8060005b85811015611f365784840389528151611f178582611eb2565b9450611f2283611ec6565b925060208a01995050600181019050611efe565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000611f6f82611f48565b611f798185611f53565b9350611f89818560208601611869565b611f9281611158565b840191505092915050565b611fa6816115a6565b82525050565b60006040830160008301518482036000860152611fc98282611f64565b9150506020830151611fde6020860182611f9d565b508091505092915050565b600060408201905081810360008301526120038185611ed3565b905081810360208301526120178184611fac565b90509392505050565b6000604083016000830151848203600086015261203d8282611893565b915050602083015184820360208601526120578282611893565b9150508091505092915050565b6000602082019050818103600083015261207e8184612020565b905092915050565b60008083601f84011261209c5761209b61114e565b5b8235905067ffffffffffffffff8111156120b9576120b861143c565b5b6020830191508360208202830111156120d5576120d4611441565b5b9250929050565b600080602083850312156120f3576120f26110e6565b5b600083013567ffffffffffffffff811115612111576121106110eb565b5b61211d85828601612086565b92509250509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061216382611565565b9150677fffffffffffffff820361217d5761217c612129565b5b600182019050919050565b600081905092915050565b50565b60006121a3600083612188565b91506121ae82612193565b600082019050919050565b60006121c482612196565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061222a602183611d69565b9150612235826121ce565b604082019050919050565b600060208201905081810360008301526122598161221d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061229a82611294565b91506122a583611294565b9250826122b5576122b4612260565b5b828204905092915050565b6122c981611294565b82525050565b6000819050919050565b60006122f46122ef6122ea846110f0565b6122cf565b6110f0565b9050919050565b6000612306826122d9565b9050919050565b6000612318826122fb565b9050919050565b6123288161230d565b82525050565b6040820160008201516123446000850182611f9d565b5060208201516123576020850182611f9d565b50505050565b6000819050919050565b600061238261237d6123788461235d565b6122cf565b6115a6565b9050919050565b61239281612367565b82525050565b60006123a5600083611d69565b91506123b082612193565b600082019050919050565b60006101408201905081810360008301526123d6818b611d7a565b905081810360208301526123ea818a611d7a565b905081810360408301526123fe8189611d7a565b905061240d60608301886122c0565b61241a608083018761231f565b81810360a083015261242c8186611d7a565b905061243b60c083018561232e565b612449610100830184612389565b81810361012083015261245b81612398565b90509998505050505050505050565b600081519050612479816115ba565b92915050565b600060208284031215612495576124946110e6565b5b60006124a38482850161246a565b91505092915050565b6124b5816117a3565b82525050565b60006124c78385611d69565b93506124d4838584611215565b6124dd83611158565b840190509392505050565b600060a0820190506124fd600083018b6124ac565b818103602083015261251081898b6124bb565b905081810360408301526125258187896124bb565b9050818103606083015261253a8185876124bb565b905061254960808301846122c0565b9998505050505050505050565b600081519050612565816112d6565b92915050565b600060208284031215612581576125806110e6565b5b600061258f84828501612556565b91505092915050565b7f4661696c656420746f20696e63726561736520616c6c6f77616e636500000000600082015250565b60006125ce601c83611d69565b91506125d982612598565b602082019050919050565b600060208201905081810360008301526125fd816125c1565b9050919050565b600061014082019050818103600083015261261f818c611d7a565b90508181036020830152612633818b611d7a565b90508181036040830152612647818a611d7a565b905061265660608301896122c0565b61266360808301886124ac565b81810360a08301526126758187611d7a565b905061268460c083018661232e565b612692610100830185611779565b8181036101208301526126a58184611d7a565b90509a9950505050505050505050565b60006020820190506126ca60008301846124ac565b92915050565b7f4661696c656420746f207265766f6b6520617070726f76616c00000000000000600082015250565b6000612706601983611d69565b9150612711826126d0565b602082019050919050565b60006020820190508181036000830152612735816126f9565b9050919050565b600060408201905061275160008301856124ac565b61275e60208301846124ac565b9392505050565b600067ffffffffffffffff8211156127805761277f611169565b5b602082029050602081019050919050565b60006127a461279f846111e4565b6111c9565b9050828152602081018484840111156127c0576127bf611153565b5b6127cb848285611869565b509392505050565b600082601f8301126127e8576127e761114e565b5b81516127f8848260208601612791565b91505092915050565b600067ffffffffffffffff82111561281c5761281b611169565b5b602082029050602081019050919050565b60008151905061283c8161129e565b92915050565b6000604082840312156128585761285761159c565b5b61286260406111c9565b9050600082015167ffffffffffffffff811115612882576128816115a1565b5b61288e848285016127d3565b60008301525060206128a28482850161282d565b60208301525092915050565b60006128c16128bc84612801565b6111c9565b905080838252602082019050602084028301858111156128e4576128e3611441565b5b835b8181101561292b57805167ffffffffffffffff8111156129095761290861114e565b5b8086016129168982612842565b855260208501945050506020810190506128e6565b5050509392505050565b600082601f83011261294a5761294961114e565b5b815161295a8482602086016128ae565b91505092915050565b600067ffffffffffffffff82111561297e5761297d611169565b5b602082029050602081019050919050565b60006129a261299d84612963565b6111c9565b905080838252602082019050602084028301858111156129c5576129c4611441565b5b835b81811015612a0c57805167ffffffffffffffff8111156129ea576129e961114e565b5b8086016129f789826127d3565b855260208501945050506020810190506129c7565b5050509392505050565b600082601f830112612a2b57612a2a61114e565b5b8151612a3b84826020860161298f565b91505092915050565b600060a08284031215612a5a57612a5961159c565b5b612a6460a06111c9565b9050600082015167ffffffffffffffff811115612a8457612a836115a1565b5b612a90848285016127d3565b600083015250602082015167ffffffffffffffff811115612ab457612ab36115a1565b5b612ac0848285016127d3565b602083015250604082015167ffffffffffffffff811115612ae457612ae36115a1565b5b612af084828501612935565b604083015250606082015167ffffffffffffffff811115612b1457612b136115a1565b5b612b2084828501612a16565b606083015250608082015167ffffffffffffffff811115612b4457612b436115a1565b5b612b5084828501612a16565b60808301525092915050565b6000612b6f612b6a84612765565b6111c9565b90508083825260208201905060208402830185811115612b9257612b91611441565b5b835b81811015612bd957805167ffffffffffffffff811115612bb757612bb661114e565b5b808601612bc48982612a44565b85526020850194505050602081019050612b94565b5050509392505050565b600082601f830112612bf857612bf761114e565b5b8151612c08848260208601612b5c565b91505092915050565b600060208284031215612c2757612c266110e6565b5b600082015167ffffffffffffffff811115612c4557612c446110eb565b5b612c5184828501612be3565b91505092915050565b6000610140820190508181036000830152612c75818b611d7a565b90508181036020830152612c89818a611d7a565b90508181036040830152612c9d8189611d7a565b9050612cac60608301886122c0565b612cb960808301876124ac565b81810360a0830152612ccb8186611d7a565b9050612cda60c083018561232e565b612ce8610100830184612389565b818103610120830152612cfa81612398565b90509998505050505050505050565b600060208284031215612d1f57612d1e6110e6565b5b600082015167ffffffffffffffff811115612d3d57612d3c6110eb565b5b612d49848285016127d3565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112612d7e57612d7d612d5c565b5b83810192508235915060208301925067ffffffffffffffff821115612da657612da5612d52565b5b600182023603831315612dbc57612dbb612d57565b5b509250929050565b6000612dd08385611f53565b9350612ddd838584611215565b612de683611158565b840190509392505050565b6000612e0060208401846115d1565b905092915050565b6000612e1760208401846112ed565b905092915050565b612e28816112ca565b82525050565b600060a08301612e416000840184612d61565b8583036000870152612e54838284612dc4565b92505050612e656020840184612df1565b612e726020860182611f9d565b50612e806040840184612df1565b612e8d6040860182611f9d565b50612e9b6060840184612e08565b612ea86060860182612e1f565b50612eb66080840184612e08565b612ec36080860182612e1f565b508091505092915050565b60006020820190508181036000830152612ee88184612e2e565b905092915050565b600067ffffffffffffffff821115612f0b57612f0a611169565b5b602082029050602081019050919050565b600060408284031215612f3257612f3161159c565b5b612f3c60406111c9565b9050600082015167ffffffffffffffff811115612f5c57612f5b6115a1565b5b612f68848285016127d3565b600083015250602082015167ffffffffffffffff811115612f8c57612f8b6115a1565b5b612f98848285016127d3565b60208301525092915050565b6000612fb7612fb284612ef0565b6111c9565b90508083825260208201905060208402830185811115612fda57612fd9611441565b5b835b8181101561302157805167ffffffffffffffff811115612fff57612ffe61114e565b5b80860161300c8982612f1c565b85526020850194505050602081019050612fdc565b5050509392505050565b600082601f8301126130405761303f61114e565b5b8151613050848260208601612fa4565b91505092915050565b600067ffffffffffffffff82111561307457613073611169565b5b61307d82611158565b9050602081019050919050565b600061309d61309884613059565b6111c9565b9050828152602081018484840111156130b9576130b8611153565b5b6130c4848285611869565b509392505050565b600082601f8301126130e1576130e061114e565b5b81516130f184826020860161308a565b91505092915050565b6000604082840312156131105761310f61159c565b5b61311a60406111c9565b9050600082015167ffffffffffffffff81111561313a576131396115a1565b5b613146848285016130cc565b600083015250602061315a8482850161246a565b60208301525092915050565b6000806040838503121561317d5761317c6110e6565b5b600083015167ffffffffffffffff81111561319b5761319a6110eb565b5b6131a78582860161302b565b925050602083015167ffffffffffffffff8111156131c8576131c76110eb565b5b6131d4858286016130fa565b9150509250929050565b6000602082840312156131f4576131f36110e6565b5b600082015167ffffffffffffffff811115613212576132116110eb565b5b61321e84828501612f1c565b91505092915050565b7f4661696c656420746f20646563726561736520616c6c6f77616e636500000000600082015250565b600061325d601c83611d69565b915061326882613227565b602082019050919050565b6000602082019050818103600083015261328c81613250565b9050919050565b6000819050919050565b600080833560016020038436030381126132ba576132b9612d5c565b5b83810192508235915060208301925067ffffffffffffffff8211156132e2576132e1612d52565b5b6001820236038313156132f8576132f7612d57565b5b509250929050565b600061330c8385611858565b9350613319838584611215565b61332283611158565b840190509392505050565b6000808335600160200384360303811261334a57613349612d5c565b5b83810192508235915060208301925067ffffffffffffffff82111561337257613371612d52565b5b60208202360383131561338857613387612d57565b5b509250929050565b6000819050919050565b60006133a960208401846112b5565b905092915050565b6000604083016133c4600084018461329d565b85830360008701526133d7838284613300565b925050506133e8602084018461339a565b6133f560208601826118f8565b508091505092915050565b600061340c83836133b1565b905092915050565b6000823560016040038336030381126134305761342f612d5c565b5b82810191505092915050565b6000602082019050919050565b600061345583856118d7565b93508360208402850161346784613390565b8060005b878110156134ab5784840389526134828284613414565b61348c8582613400565b94506134978361343c565b925060208a0199505060018101905061346b565b50829750879450505050509392505050565b600080833560016020038436030381126134da576134d9612d5c565b5b83810192508235915060208301925067ffffffffffffffff82111561350257613501612d52565b5b60208202360383131561351857613517612d57565b5b509250929050565b6000819050919050565b6000613537848484613300565b90509392505050565b6000602082019050919050565b600061355983856119e5565b93508360208402850161356b84613520565b8060005b878110156135b1578484038952613586828461329d565b61359186828461352a565b955061359c84613540565b935060208b019a50505060018101905061356f565b50829750879450505050509392505050565b600060a083016135d6600084018461329d565b85830360008701526135e9838284613300565b925050506135fa602084018461329d565b858303602087015261360d838284613300565b9250505061361e604084018461332d565b8583036040870152613631838284613449565b9250505061364260608401846134bd565b858303606087015261365583828461354d565b9250505061366660808401846134bd565b858303608087015261367983828461354d565b925050508091505092915050565b600061369383836135c3565b905092915050565b60008235600160a0038336030381126136b7576136b6612d5c565b5b82810191505092915050565b6000602082019050919050565b60006136dc838561182c565b9350836020840285016136ee84613293565b8060005b87811015613732578484038952613709828461369b565b6137138582613687565b945061371e836136c3565b925060208a019950506001810190506136f2565b50829750879450505050509392505050565b600060408201905061375960008301866124ac565b818103602083015261376c8184866136d0565b9050949350505050565b7f4661696c656420746f20706572666f726d20617070726f76616c000000000000600082015250565b60006137ac601a83611d69565b91506137b782613776565b602082019050919050565b600060208201905081810360008301526137db8161379f565b905091905056fea2646970667358221220bcb453fc471282c5300ef2cce92af3966ecb2c9f9fc8ddec271f9520efa16a1164736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063a363df841161008c578063dfa10f3911610066578063dfa10f3914610210578063ee5766d914610241578063f298e7a814610271578063f3675f081461028d576100cf565b8063a363df8414610194578063b9672879146101c4578063c595699a146101e0576100cf565b80631dba685b146100d4578063424af9f6146100f057806361bc221a1461010c5780636fdf23cc1461012a5780637492bdd81461015a5780637a6185e11461018a575b600080fd5b6100ee60048036038101906100e99190611302565b6102a9565b005b61010a6004803603810190610105919061149c565b61070f565b005b6101146107e9565b6040516101219190611581565b60405180910390f35b610144600480360381019061013f9190611636565b6107fa565b6040516101519190611788565b60405180910390f35b610174600480360381019061016f9190611636565b610898565b6040516101819190611788565b60405180910390f35b610192610936565b005b6101ae60048036038101906101a991906117e1565b6109fb565b6040516101bb9190611bc4565b60405180910390f35b6101de60048036038101906101d99190611be6565b610a88565b005b6101fa60048036038101906101f59190611d20565b610d4b565b6040516102079190611db3565b60405180910390f35b61022a60048036038101906102259190611df9565b610dd5565b604051610238929190611fe9565b60405180910390f35b61025b60048036038101906102569190611d20565b610e69565b6040516102689190612064565b60405180910390f35b61028b6004803603810190610286919061149c565b610ef9565b005b6102a760048036038101906102a291906120dc565b610fd3565b005b82156103a65760008081819054906101000a900460070b809291906102cd90612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008973ffffffffffffffffffffffffffffffffffffffff16600f60405161031e906121b9565b60006040518083038185875af1925050503d806000811461035b576040519150601f19603f3d011682016040523d82523d6000602084013e610360565b606091505b50509050806103a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039b90612240565b60405180910390fd5b505b60006040518060400160405280606467ffffffffffffffff168152602001606467ffffffffffffffff16815250905061080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a60028b610403919061228f565b8f8b8860006040518963ffffffff1660e01b815260040161042b9897969594939291906123bb565b6020604051808303816000875af115801561044a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046e919061247f565b50821561056c5760008081819054906101000a900460070b8092919061049390612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008a73ffffffffffffffffffffffffffffffffffffffff16600f6040516104e4906121b9565b60006040518083038185875af1925050503d8060008114610521576040519150601f19603f3d011682016040523d82523d6000602084013e610526565b606091505b505090508061056a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056190612240565b60405180910390fd5b505b61080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a60028b61059a919061228f565b8f8b8860006040518963ffffffff1660e01b81526004016105c29897969594939291906123bb565b6020604051808303816000875af11580156105e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610605919061247f565b5081156107035760008081819054906101000a900460070b8092919061062a90612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008a73ffffffffffffffffffffffffffffffffffffffff16600f60405161067b906121b9565b60006040518083038185875af1925050503d80600081146106b8576040519150601f19603f3d011682016040523d82523d6000602084013e6106bd565b606091505b5050905080610701576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106f890612240565b60405180910390fd5b505b50505050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff166354de647b308a8a8a8a8a8a8a6040518963ffffffff1660e01b815260040161075a9897969594939291906124e8565b6020604051808303816000875af1158015610779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079d919061256b565b9050806107df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107d6906125e4565b60405180910390fd5b5050505050505050565b60008054906101000a900460070b81565b600061080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a8a308b8b8b8b6040518a63ffffffff1660e01b815260040161084799989796959493929190612604565b6020604051808303816000875af1158015610866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088a919061247f565b905098975050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff1663632535b98a8a8a8a338b8b8b8b6040518a63ffffffff1660e01b81526004016108e599989796959493929190612604565b6020604051808303816000875af1158015610904573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610928919061247f565b905098975050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff166374a8f103306040518263ffffffff1660e01b815260040161097391906126b5565b6020604051808303816000875af1158015610992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b6919061256b565b9050806109f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ef9061271c565b60405180910390fd5b50565b606061080273ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e84846040518363ffffffff1660e01b8152600401610a3a92919061273c565b600060405180830381865afa158015610a57573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a809190612c11565b905092915050565b8115610b855760008081819054906101000a900460070b80929190610aac90612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008973ffffffffffffffffffffffffffffffffffffffff16600f604051610afd906121b9565b60006040518083038185875af1925050503d8060008114610b3a576040519150601f19603f3d011682016040523d82523d6000602084013e610b3f565b606091505b5050905080610b83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7a90612240565b60405180910390fd5b505b60006040518060400160405280606467ffffffffffffffff168152602001606467ffffffffffffffff16815250905061080273ffffffffffffffffffffffffffffffffffffffff1663632535b9898989898e8a8860006040518963ffffffff1660e01b8152600401610bfe989796959493929190612c5a565b6020604051808303816000875af1158015610c1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c41919061247f565b508115610d3f5760008081819054906101000a900460070b80929190610c6690612158565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff1602179055505060008a73ffffffffffffffffffffffffffffffffffffffff16600f604051610cb7906121b9565b60006040518083038185875af1925050503d8060008114610cf4576040519150601f19603f3d011682016040523d82523d6000602084013e610cf9565b606091505b5050905080610d3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3490612240565b60405180910390fd5b505b50505050505050505050565b606061080273ffffffffffffffffffffffffffffffffffffffff1663b5cb6e7d836040518263ffffffff1660e01b8152600401610d889190611db3565b600060405180830381865afa158015610da5573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610dce9190612d09565b9050919050565b6060610ddf61109e565b61080273ffffffffffffffffffffffffffffffffffffffff166322b6fad6846040518263ffffffff1660e01b8152600401610e1a9190612ece565b600060405180830381865afa158015610e37573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610e609190613166565b91509150915091565b610e716110c2565b61080273ffffffffffffffffffffffffffffffffffffffff1663a815cdd9836040518263ffffffff1660e01b8152600401610eac9190611db3565b600060405180830381865afa158015610ec9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610ef291906131de565b9050919050565b600061080273ffffffffffffffffffffffffffffffffffffffff1663b3f536ec308a8a8a8a8a8a8a6040518963ffffffff1660e01b8152600401610f449897969594939291906124e8565b6020604051808303816000875af1158015610f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f87919061256b565b905080610fc9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc090613273565b60405180910390fd5b5050505050505050565b600061080273ffffffffffffffffffffffffffffffffffffffff1663473c90c73085856040518463ffffffff1660e01b815260040161101493929190613744565b6020604051808303816000875af1158015611033573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611057919061256b565b905080611099576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611090906137c2565b60405180910390fd5b505050565b604051806040016040528060608152602001600067ffffffffffffffff1681525090565b604051806040016040528060608152602001606081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061111b826110f0565b9050919050565b61112b81611110565b811461113657600080fd5b50565b60008135905061114881611122565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6111a182611158565b810181811067ffffffffffffffff821117156111c0576111bf611169565b5b80604052505050565b60006111d36110dc565b90506111df8282611198565b919050565b600067ffffffffffffffff8211156111ff576111fe611169565b5b61120882611158565b9050602081019050919050565b82818337600083830152505050565b6000611237611232846111e4565b6111c9565b90508281526020810184848401111561125357611252611153565b5b61125e848285611215565b509392505050565b600082601f83011261127b5761127a61114e565b5b813561128b848260208601611224565b91505092915050565b6000819050919050565b6112a781611294565b81146112b257600080fd5b50565b6000813590506112c48161129e565b92915050565b60008115159050919050565b6112df816112ca565b81146112ea57600080fd5b50565b6000813590506112fc816112d6565b92915050565b60008060008060008060008060006101208a8c031215611325576113246110e6565b5b60006113338c828d01611139565b99505060208a013567ffffffffffffffff811115611354576113536110eb565b5b6113608c828d01611266565b98505060408a013567ffffffffffffffff811115611381576113806110eb565b5b61138d8c828d01611266565b97505060608a013567ffffffffffffffff8111156113ae576113ad6110eb565b5b6113ba8c828d01611266565b96505060806113cb8c828d016112b5565b95505060a08a013567ffffffffffffffff8111156113ec576113eb6110eb565b5b6113f88c828d01611266565b94505060c06114098c828d016112ed565b93505060e061141a8c828d016112ed565b92505061010061142c8c828d016112ed565b9150509295985092959850929598565b600080fd5b600080fd5b60008083601f84011261145c5761145b61114e565b5b8235905067ffffffffffffffff8111156114795761147861143c565b5b60208301915083600182028301111561149557611494611441565b5b9250929050565b60008060008060008060006080888a0312156114bb576114ba6110e6565b5b600088013567ffffffffffffffff8111156114d9576114d86110eb565b5b6114e58a828b01611446565b9750975050602088013567ffffffffffffffff811115611508576115076110eb565b5b6115148a828b01611446565b9550955050604088013567ffffffffffffffff811115611537576115366110eb565b5b6115438a828b01611446565b935093505060606115568a828b016112b5565b91505092959891949750929550565b60008160070b9050919050565b61157b81611565565b82525050565b60006020820190506115966000830184611572565b92915050565b600080fd5b600080fd5b600067ffffffffffffffff82169050919050565b6115c3816115a6565b81146115ce57600080fd5b50565b6000813590506115e0816115ba565b92915050565b6000604082840312156115fc576115fb61159c565b5b61160660406111c9565b90506000611616848285016115d1565b600083015250602061162a848285016115d1565b60208301525092915050565b600080600080600080600080610120898b031215611657576116566110e6565b5b600089013567ffffffffffffffff811115611675576116746110eb565b5b6116818b828c01611266565b985050602089013567ffffffffffffffff8111156116a2576116a16110eb565b5b6116ae8b828c01611266565b975050604089013567ffffffffffffffff8111156116cf576116ce6110eb565b5b6116db8b828c01611266565b96505060606116ec8b828c016112b5565b955050608089013567ffffffffffffffff81111561170d5761170c6110eb565b5b6117198b828c01611266565b94505060a061172a8b828c016115e6565b93505060e061173b8b828c016115d1565b92505061010089013567ffffffffffffffff81111561175d5761175c6110eb565b5b6117698b828c01611266565b9150509295985092959890939650565b611782816115a6565b82525050565b600060208201905061179d6000830184611779565b92915050565b60006117ae826110f0565b9050919050565b6117be816117a3565b81146117c957600080fd5b50565b6000813590506117db816117b5565b92915050565b600080604083850312156117f8576117f76110e6565b5b6000611806858286016117cc565b9250506020611817858286016117cc565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561188757808201518184015260208101905061186c565b60008484015250505050565b600061189e8261184d565b6118a88185611858565b93506118b8818560208601611869565b6118c181611158565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61190181611294565b82525050565b600060408301600083015184820360008601526119248282611893565b915050602083015161193960208601826118f8565b508091505092915050565b60006119508383611907565b905092915050565b6000602082019050919050565b6000611970826118cc565b61197a81856118d7565b93508360208202850161198c856118e8565b8060005b858110156119c857848403895281516119a98582611944565b94506119b483611958565b925060208a01995050600181019050611990565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611a128383611893565b905092915050565b6000602082019050919050565b6000611a32826119da565b611a3c81856119e5565b935083602082028501611a4e856119f6565b8060005b85811015611a8a5784840389528151611a6b8582611a06565b9450611a7683611a1a565b925060208a01995050600181019050611a52565b50829750879550505050505092915050565b600060a0830160008301518482036000860152611ab98282611893565b91505060208301518482036020860152611ad38282611893565b91505060408301518482036040860152611aed8282611965565b91505060608301518482036060860152611b078282611a27565b91505060808301518482036080860152611b218282611a27565b9150508091505092915050565b6000611b3a8383611a9c565b905092915050565b6000602082019050919050565b6000611b5a82611821565b611b64818561182c565b935083602082028501611b768561183d565b8060005b85811015611bb25784840389528151611b938582611b2e565b9450611b9e83611b42565b925060208a01995050600181019050611b7a565b50829750879550505050505092915050565b60006020820190508181036000830152611bde8184611b4f565b905092915050565b60008060008060008060008060006101208a8c031215611c0957611c086110e6565b5b6000611c178c828d01611139565b9950506020611c288c828d016117cc565b98505060408a013567ffffffffffffffff811115611c4957611c486110eb565b5b611c558c828d01611266565b97505060608a013567ffffffffffffffff811115611c7657611c756110eb565b5b611c828c828d01611266565b96505060808a013567ffffffffffffffff811115611ca357611ca26110eb565b5b611caf8c828d01611266565b95505060a0611cc08c828d016112b5565b94505060c08a013567ffffffffffffffff811115611ce157611ce06110eb565b5b611ced8c828d01611266565b93505060e0611cfe8c828d016112ed565b925050610100611d108c828d016112ed565b9150509295985092959850929598565b600060208284031215611d3657611d356110e6565b5b600082013567ffffffffffffffff811115611d5457611d536110eb565b5b611d6084828501611266565b91505092915050565b600082825260208201905092915050565b6000611d858261184d565b611d8f8185611d69565b9350611d9f818560208601611869565b611da881611158565b840191505092915050565b60006020820190508181036000830152611dcd8184611d7a565b905092915050565b600080fd5b600060a08284031215611df057611def611dd5565b5b81905092915050565b600060208284031215611e0f57611e0e6110e6565b5b600082013567ffffffffffffffff811115611e2d57611e2c6110eb565b5b611e3984828501611dda565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152611e8b8282611893565b91505060208301518482036020860152611ea58282611893565b9150508091505092915050565b6000611ebe8383611e6e565b905092915050565b6000602082019050919050565b6000611ede82611e42565b611ee88185611e4d565b935083602082028501611efa85611e5e565b8060005b85811015611f365784840389528151611f178582611eb2565b9450611f2283611ec6565b925060208a01995050600181019050611efe565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000611f6f82611f48565b611f798185611f53565b9350611f89818560208601611869565b611f9281611158565b840191505092915050565b611fa6816115a6565b82525050565b60006040830160008301518482036000860152611fc98282611f64565b9150506020830151611fde6020860182611f9d565b508091505092915050565b600060408201905081810360008301526120038185611ed3565b905081810360208301526120178184611fac565b90509392505050565b6000604083016000830151848203600086015261203d8282611893565b915050602083015184820360208601526120578282611893565b9150508091505092915050565b6000602082019050818103600083015261207e8184612020565b905092915050565b60008083601f84011261209c5761209b61114e565b5b8235905067ffffffffffffffff8111156120b9576120b861143c565b5b6020830191508360208202830111156120d5576120d4611441565b5b9250929050565b600080602083850312156120f3576120f26110e6565b5b600083013567ffffffffffffffff811115612111576121106110eb565b5b61211d85828601612086565b92509250509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061216382611565565b9150677fffffffffffffff820361217d5761217c612129565b5b600182019050919050565b600081905092915050565b50565b60006121a3600083612188565b91506121ae82612193565b600082019050919050565b60006121c482612196565b9150819050919050565b7f4661696c656420746f2073656e6420457468657220746f2064656c656761746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061222a602183611d69565b9150612235826121ce565b604082019050919050565b600060208201905081810360008301526122598161221d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061229a82611294565b91506122a583611294565b9250826122b5576122b4612260565b5b828204905092915050565b6122c981611294565b82525050565b6000819050919050565b60006122f46122ef6122ea846110f0565b6122cf565b6110f0565b9050919050565b6000612306826122d9565b9050919050565b6000612318826122fb565b9050919050565b6123288161230d565b82525050565b6040820160008201516123446000850182611f9d565b5060208201516123576020850182611f9d565b50505050565b6000819050919050565b600061238261237d6123788461235d565b6122cf565b6115a6565b9050919050565b61239281612367565b82525050565b60006123a5600083611d69565b91506123b082612193565b600082019050919050565b60006101408201905081810360008301526123d6818b611d7a565b905081810360208301526123ea818a611d7a565b905081810360408301526123fe8189611d7a565b905061240d60608301886122c0565b61241a608083018761231f565b81810360a083015261242c8186611d7a565b905061243b60c083018561232e565b612449610100830184612389565b81810361012083015261245b81612398565b90509998505050505050505050565b600081519050612479816115ba565b92915050565b600060208284031215612495576124946110e6565b5b60006124a38482850161246a565b91505092915050565b6124b5816117a3565b82525050565b60006124c78385611d69565b93506124d4838584611215565b6124dd83611158565b840190509392505050565b600060a0820190506124fd600083018b6124ac565b818103602083015261251081898b6124bb565b905081810360408301526125258187896124bb565b9050818103606083015261253a8185876124bb565b905061254960808301846122c0565b9998505050505050505050565b600081519050612565816112d6565b92915050565b600060208284031215612581576125806110e6565b5b600061258f84828501612556565b91505092915050565b7f4661696c656420746f20696e63726561736520616c6c6f77616e636500000000600082015250565b60006125ce601c83611d69565b91506125d982612598565b602082019050919050565b600060208201905081810360008301526125fd816125c1565b9050919050565b600061014082019050818103600083015261261f818c611d7a565b90508181036020830152612633818b611d7a565b90508181036040830152612647818a611d7a565b905061265660608301896122c0565b61266360808301886124ac565b81810360a08301526126758187611d7a565b905061268460c083018661232e565b612692610100830185611779565b8181036101208301526126a58184611d7a565b90509a9950505050505050505050565b60006020820190506126ca60008301846124ac565b92915050565b7f4661696c656420746f207265766f6b6520617070726f76616c00000000000000600082015250565b6000612706601983611d69565b9150612711826126d0565b602082019050919050565b60006020820190508181036000830152612735816126f9565b9050919050565b600060408201905061275160008301856124ac565b61275e60208301846124ac565b9392505050565b600067ffffffffffffffff8211156127805761277f611169565b5b602082029050602081019050919050565b60006127a461279f846111e4565b6111c9565b9050828152602081018484840111156127c0576127bf611153565b5b6127cb848285611869565b509392505050565b600082601f8301126127e8576127e761114e565b5b81516127f8848260208601612791565b91505092915050565b600067ffffffffffffffff82111561281c5761281b611169565b5b602082029050602081019050919050565b60008151905061283c8161129e565b92915050565b6000604082840312156128585761285761159c565b5b61286260406111c9565b9050600082015167ffffffffffffffff811115612882576128816115a1565b5b61288e848285016127d3565b60008301525060206128a28482850161282d565b60208301525092915050565b60006128c16128bc84612801565b6111c9565b905080838252602082019050602084028301858111156128e4576128e3611441565b5b835b8181101561292b57805167ffffffffffffffff8111156129095761290861114e565b5b8086016129168982612842565b855260208501945050506020810190506128e6565b5050509392505050565b600082601f83011261294a5761294961114e565b5b815161295a8482602086016128ae565b91505092915050565b600067ffffffffffffffff82111561297e5761297d611169565b5b602082029050602081019050919050565b60006129a261299d84612963565b6111c9565b905080838252602082019050602084028301858111156129c5576129c4611441565b5b835b81811015612a0c57805167ffffffffffffffff8111156129ea576129e961114e565b5b8086016129f789826127d3565b855260208501945050506020810190506129c7565b5050509392505050565b600082601f830112612a2b57612a2a61114e565b5b8151612a3b84826020860161298f565b91505092915050565b600060a08284031215612a5a57612a5961159c565b5b612a6460a06111c9565b9050600082015167ffffffffffffffff811115612a8457612a836115a1565b5b612a90848285016127d3565b600083015250602082015167ffffffffffffffff811115612ab457612ab36115a1565b5b612ac0848285016127d3565b602083015250604082015167ffffffffffffffff811115612ae457612ae36115a1565b5b612af084828501612935565b604083015250606082015167ffffffffffffffff811115612b1457612b136115a1565b5b612b2084828501612a16565b606083015250608082015167ffffffffffffffff811115612b4457612b436115a1565b5b612b5084828501612a16565b60808301525092915050565b6000612b6f612b6a84612765565b6111c9565b90508083825260208201905060208402830185811115612b9257612b91611441565b5b835b81811015612bd957805167ffffffffffffffff811115612bb757612bb661114e565b5b808601612bc48982612a44565b85526020850194505050602081019050612b94565b5050509392505050565b600082601f830112612bf857612bf761114e565b5b8151612c08848260208601612b5c565b91505092915050565b600060208284031215612c2757612c266110e6565b5b600082015167ffffffffffffffff811115612c4557612c446110eb565b5b612c5184828501612be3565b91505092915050565b6000610140820190508181036000830152612c75818b611d7a565b90508181036020830152612c89818a611d7a565b90508181036040830152612c9d8189611d7a565b9050612cac60608301886122c0565b612cb960808301876124ac565b81810360a0830152612ccb8186611d7a565b9050612cda60c083018561232e565b612ce8610100830184612389565b818103610120830152612cfa81612398565b90509998505050505050505050565b600060208284031215612d1f57612d1e6110e6565b5b600082015167ffffffffffffffff811115612d3d57612d3c6110eb565b5b612d49848285016127d3565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112612d7e57612d7d612d5c565b5b83810192508235915060208301925067ffffffffffffffff821115612da657612da5612d52565b5b600182023603831315612dbc57612dbb612d57565b5b509250929050565b6000612dd08385611f53565b9350612ddd838584611215565b612de683611158565b840190509392505050565b6000612e0060208401846115d1565b905092915050565b6000612e1760208401846112ed565b905092915050565b612e28816112ca565b82525050565b600060a08301612e416000840184612d61565b8583036000870152612e54838284612dc4565b92505050612e656020840184612df1565b612e726020860182611f9d565b50612e806040840184612df1565b612e8d6040860182611f9d565b50612e9b6060840184612e08565b612ea86060860182612e1f565b50612eb66080840184612e08565b612ec36080860182612e1f565b508091505092915050565b60006020820190508181036000830152612ee88184612e2e565b905092915050565b600067ffffffffffffffff821115612f0b57612f0a611169565b5b602082029050602081019050919050565b600060408284031215612f3257612f3161159c565b5b612f3c60406111c9565b9050600082015167ffffffffffffffff811115612f5c57612f5b6115a1565b5b612f68848285016127d3565b600083015250602082015167ffffffffffffffff811115612f8c57612f8b6115a1565b5b612f98848285016127d3565b60208301525092915050565b6000612fb7612fb284612ef0565b6111c9565b90508083825260208201905060208402830185811115612fda57612fd9611441565b5b835b8181101561302157805167ffffffffffffffff811115612fff57612ffe61114e565b5b80860161300c8982612f1c565b85526020850194505050602081019050612fdc565b5050509392505050565b600082601f8301126130405761303f61114e565b5b8151613050848260208601612fa4565b91505092915050565b600067ffffffffffffffff82111561307457613073611169565b5b61307d82611158565b9050602081019050919050565b600061309d61309884613059565b6111c9565b9050828152602081018484840111156130b9576130b8611153565b5b6130c4848285611869565b509392505050565b600082601f8301126130e1576130e061114e565b5b81516130f184826020860161308a565b91505092915050565b6000604082840312156131105761310f61159c565b5b61311a60406111c9565b9050600082015167ffffffffffffffff81111561313a576131396115a1565b5b613146848285016130cc565b600083015250602061315a8482850161246a565b60208301525092915050565b6000806040838503121561317d5761317c6110e6565b5b600083015167ffffffffffffffff81111561319b5761319a6110eb565b5b6131a78582860161302b565b925050602083015167ffffffffffffffff8111156131c8576131c76110eb565b5b6131d4858286016130fa565b9150509250929050565b6000602082840312156131f4576131f36110e6565b5b600082015167ffffffffffffffff811115613212576132116110eb565b5b61321e84828501612f1c565b91505092915050565b7f4661696c656420746f20646563726561736520616c6c6f77616e636500000000600082015250565b600061325d601c83611d69565b915061326882613227565b602082019050919050565b6000602082019050818103600083015261328c81613250565b9050919050565b6000819050919050565b600080833560016020038436030381126132ba576132b9612d5c565b5b83810192508235915060208301925067ffffffffffffffff8211156132e2576132e1612d52565b5b6001820236038313156132f8576132f7612d57565b5b509250929050565b600061330c8385611858565b9350613319838584611215565b61332283611158565b840190509392505050565b6000808335600160200384360303811261334a57613349612d5c565b5b83810192508235915060208301925067ffffffffffffffff82111561337257613371612d52565b5b60208202360383131561338857613387612d57565b5b509250929050565b6000819050919050565b60006133a960208401846112b5565b905092915050565b6000604083016133c4600084018461329d565b85830360008701526133d7838284613300565b925050506133e8602084018461339a565b6133f560208601826118f8565b508091505092915050565b600061340c83836133b1565b905092915050565b6000823560016040038336030381126134305761342f612d5c565b5b82810191505092915050565b6000602082019050919050565b600061345583856118d7565b93508360208402850161346784613390565b8060005b878110156134ab5784840389526134828284613414565b61348c8582613400565b94506134978361343c565b925060208a0199505060018101905061346b565b50829750879450505050509392505050565b600080833560016020038436030381126134da576134d9612d5c565b5b83810192508235915060208301925067ffffffffffffffff82111561350257613501612d52565b5b60208202360383131561351857613517612d57565b5b509250929050565b6000819050919050565b6000613537848484613300565b90509392505050565b6000602082019050919050565b600061355983856119e5565b93508360208402850161356b84613520565b8060005b878110156135b1578484038952613586828461329d565b61359186828461352a565b955061359c84613540565b935060208b019a50505060018101905061356f565b50829750879450505050509392505050565b600060a083016135d6600084018461329d565b85830360008701526135e9838284613300565b925050506135fa602084018461329d565b858303602087015261360d838284613300565b9250505061361e604084018461332d565b8583036040870152613631838284613449565b9250505061364260608401846134bd565b858303606087015261365583828461354d565b9250505061366660808401846134bd565b858303608087015261367983828461354d565b925050508091505092915050565b600061369383836135c3565b905092915050565b60008235600160a0038336030381126136b7576136b6612d5c565b5b82810191505092915050565b6000602082019050919050565b60006136dc838561182c565b9350836020840285016136ee84613293565b8060005b87811015613732578484038952613709828461369b565b6137138582613687565b945061371e836136c3565b925060208a019950506001810190506136f2565b50829750879450505050509392505050565b600060408201905061375960008301866124ac565b818103602083015261376c8184866136d0565b9050949350505050565b7f4661696c656420746f20706572666f726d20617070726f76616c000000000000600082015250565b60006137ac601a83611d69565b91506137b782613776565b602082019050919050565b600060208201905081810360008301526137db8161379f565b905091905056fea2646970667358221220bcb453fc471282c5300ef2cce92af3966ecb2c9f9fc8ddec271f9520efa16a1164736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/testutil/contracts/InterchainSender.sol b/precompiles/testutil/contracts/InterchainSender.sol
new file mode 100644
index 00000000..f71f4f33
--- /dev/null
+++ b/precompiles/testutil/contracts/InterchainSender.sol
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: LGPL-v3
+pragma solidity >=0.8.17;
+
+import "./../../ics20/ICS20I.sol";
+import "./../../common/Types.sol";
+
+contract InterchainSender {
+ int64 public counter;
+ /// @dev Approves the required spend limits for IBC transactions.
+ /// @dev This creates a Cosmos Authorization Grants for the given methods.
+ /// @dev This emits an Approval event.
+ function testApprove(ICS20Allocation[] calldata allocs) public {
+ bool success = ICS20_CONTRACT.approve(address(this), allocs);
+ require(success, "Failed to perform approval");
+ }
+
+ function testRevoke() external {
+ bool success = ICS20_CONTRACT.revoke(address(this));
+ require(success, "Failed to revoke approval");
+ }
+
+ function testIncreaseAllowance(
+ string calldata sourcePort,
+ string calldata sourceChannel,
+ string calldata denom,
+ uint256 amount
+ ) public {
+ bool success = ICS20_CONTRACT.increaseAllowance(
+ address(this),
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount
+ );
+ require(success, "Failed to increase allowance");
+ }
+
+ function testDecreaseAllowance(
+ string calldata sourcePort,
+ string calldata sourceChannel,
+ string calldata denom,
+ uint256 amount
+ ) public {
+ bool success = ICS20_CONTRACT.decreaseAllowance(
+ address(this),
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount
+ );
+ require(success, "Failed to decrease allowance");
+ }
+
+ /// @dev transfer a given amount of tokens. Returns the IBC packet sequence of the IBC transaction.
+ /// @dev This emits a IBCTransfer event.
+ /// @param sourcePort The source port of the IBC transfer.
+ /// @param sourceChannel The source channel of the IBC transfer.
+ /// @param denom The denomination of the tokens to transfer.
+ /// @param receiver The receiver address on the receiving chain.
+ /// @param timeoutHeight The timeout height for the IBC packet.
+ /// @param timeoutTimestamp The timeout timestamp of the IBC packet.
+ /// @param memo The IBC transaction memo.
+ /// @param amount The amount of tokens to transfer to another chain.
+ /// @return nextSequence The IBC transaction sequence number.
+ function testTransferUserFunds(
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver,
+ Height memory timeoutHeight,
+ uint64 timeoutTimestamp,
+ string memory memo
+ ) public returns (uint64 nextSequence) {
+ return
+ ICS20_CONTRACT.transfer(
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ msg.sender,
+ receiver,
+ timeoutHeight,
+ timeoutTimestamp,
+ memo
+ );
+ }
+
+ function testTransferContractFunds(
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver,
+ Height memory timeoutHeight,
+ uint64 timeoutTimestamp,
+ string memory memo
+ ) public returns (uint64 nextSequence) {
+ return
+ ICS20_CONTRACT.transfer(
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ address(this),
+ receiver,
+ timeoutHeight,
+ timeoutTimestamp,
+ memo
+ );
+ }
+
+
+ function testMultiTransferWithInternalTransfer(
+ address payable _source,
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver,
+ bool _before,
+ bool _between,
+ bool _after
+ ) public {
+ if (_before) {
+ counter++;
+ (bool sent, ) = _source.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ Height memory timeoutHeight = Height(100, 100);
+ ICS20_CONTRACT.transfer(
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount / 2,
+ _source,
+ receiver,
+ timeoutHeight,
+ 0,
+ ""
+ );
+ if (_between) {
+ counter++;
+ (bool sent, ) = _source.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ ICS20_CONTRACT.transfer(
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount / 2,
+ _source,
+ receiver,
+ timeoutHeight,
+ 0,
+ ""
+ );
+ if (_after) {
+ counter++;
+ (bool sent, ) = _source.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+
+
+ function testTransferFundsWithTransferToOtherAcc(
+ address payable _otherAcc,
+ address _source,
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver,
+ bool _before,
+ bool _after
+ ) public {
+ if (_before) {
+ counter++;
+ (bool sent, ) = _otherAcc.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ Height memory timeoutHeight = Height(100, 100);
+ ICS20_CONTRACT.transfer(
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ _source,
+ receiver,
+ timeoutHeight,
+ 0,
+ ""
+ );
+ if (_after) {
+ counter++;
+ (bool sent, ) = _otherAcc.call{value: 15}("");
+ require(sent, "Failed to send Ether to delegator");
+ }
+ }
+
+ // QUERIES
+ function testDenomTraces(
+ PageRequest calldata pageRequest
+ )
+ public
+ view
+ returns (
+ DenomTrace[] memory denomTraces,
+ PageResponse memory pageResponse
+ )
+ {
+ return ICS20_CONTRACT.denomTraces(pageRequest);
+ }
+
+ function testDenomTrace(
+ string memory hash
+ ) public view returns (DenomTrace memory denomTrace) {
+ return ICS20_CONTRACT.denomTrace(hash);
+ }
+
+ function testDenomHash(
+ string memory trace
+ ) public view returns (string memory hash) {
+ return ICS20_CONTRACT.denomHash(trace);
+ }
+
+ function testAllowance(
+ address owner,
+ address spender
+ ) public view returns (ICS20Allocation[] memory allocations) {
+ return ICS20_CONTRACT.allowance(owner, spender);
+ }
+}
diff --git a/precompiles/testutil/contracts/InterchainSenderCaller.json b/precompiles/testutil/contracts/InterchainSenderCaller.json
new file mode 100644
index 00000000..83b75ba8
--- /dev/null
+++ b/precompiles/testutil/contracts/InterchainSenderCaller.json
@@ -0,0 +1,187 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "InterchainSenderCaller",
+ "sourceName": "solidity/precompiles/testutil/contracts/InterchainSenderCaller.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_interchainSender",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "counter",
+ "outputs": [
+ {
+ "internalType": "int64",
+ "name": "",
+ "type": "int64"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ }
+ ],
+ "name": "performMultiTransferWithRevert",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ }
+ ],
+ "name": "performNestedTransfers",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ }
+ ],
+ "name": "transfersWithNestedRevert",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "_source",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "sourcePort",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "sourceChannel",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "receiver",
+ "type": "string"
+ }
+ ],
+ "name": "transfersWithRevert",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x6080604052604051610c04380380610c04833981810160405281019061002591906100cf565b80600060086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506100fc565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061009c82610071565b9050919050565b6100ac81610091565b81146100b757600080fd5b50565b6000815190506100c9816100a3565b92915050565b6000602082840312156100e5576100e461006c565b5b60006100f3848285016100ba565b91505092915050565b610af98061010b6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063073989ff1461005c578063427c1cb61461007857806361bc221a1461009457806369a98b2b146100b2578063ec3c5a14146100ce575b600080fd5b61007660048036038101906100719190610752565b6100ea565b005b610092600480360381019061008d9190610752565b6101f1565b005b61009c61030d565b6040516100a9919061086b565b60405180910390f35b6100cc60048036038101906100c79190610752565b61031e565b005b6100e860048036038101906100e39190610752565b6104c4565b005b60008081819054906101000a900460070b80929190610108906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff1663427c1cb68787878787876040518763ffffffff1660e01b815260040161017596959493929190610982565b600060405180830381600087803b15801561018f57600080fd5b505af19250505080156101a0575060015b5060008081819054906101000a900460070b809291906101bf906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555050505050505050565b600060089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631dba685b87878787878760018060016040518a63ffffffff1660e01b815260040161025e99989796959493929190610a1a565b600060405180830381600087803b15801561027857600080fd5b505af115801561028c573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663ec3c5a148787878787876040518763ffffffff1660e01b81526004016102d396959493929190610982565b600060405180830381600087803b1580156102ed57600080fd5b505af1158015610301573d6000803e3d6000fd5b50505050505050505050565b60008054906101000a900460070b81565b60008081819054906101000a900460070b8092919061033c906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555050600060089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631dba685b87878787878760018060016040518a63ffffffff1660e01b81526004016103d399989796959493929190610a1a565b600060405180830381600087803b1580156103ed57600080fd5b505af1158015610401573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663ec3c5a148787878787876040518763ffffffff1660e01b815260040161044896959493929190610982565b600060405180830381600087803b15801561046257600080fd5b505af1925050508015610473575060015b5060008081819054906101000a900460070b80929190610492906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555050505050505050565b600060089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631dba685b87878787878760018060016040518a63ffffffff1660e01b815260040161053199989796959493929190610a1a565b600060405180830381600087803b15801561054b57600080fd5b505af115801561055f573d6000803e3d6000fd5b600080fd5b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006105a382610578565b9050919050565b6105b381610598565b81146105be57600080fd5b50565b6000813590506105d0816105aa565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610629826105e0565b810181811067ffffffffffffffff82111715610648576106476105f1565b5b80604052505050565b600061065b610564565b90506106678282610620565b919050565b600067ffffffffffffffff821115610687576106866105f1565b5b610690826105e0565b9050602081019050919050565b82818337600083830152505050565b60006106bf6106ba8461066c565b610651565b9050828152602081018484840111156106db576106da6105db565b5b6106e684828561069d565b509392505050565b600082601f830112610703576107026105d6565b5b81356107138482602086016106ac565b91505092915050565b6000819050919050565b61072f8161071c565b811461073a57600080fd5b50565b60008135905061074c81610726565b92915050565b60008060008060008060c0878903121561076f5761076e61056e565b5b600061077d89828a016105c1565b965050602087013567ffffffffffffffff81111561079e5761079d610573565b5b6107aa89828a016106ee565b955050604087013567ffffffffffffffff8111156107cb576107ca610573565b5b6107d789828a016106ee565b945050606087013567ffffffffffffffff8111156107f8576107f7610573565b5b61080489828a016106ee565b935050608061081589828a0161073d565b92505060a087013567ffffffffffffffff81111561083657610835610573565b5b61084289828a016106ee565b9150509295509295509295565b60008160070b9050919050565b6108658161084f565b82525050565b6000602082019050610880600083018461085c565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006108c08261084f565b9150677fffffffffffffff82036108da576108d9610886565b5b600182019050919050565b6108ee81610598565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561092e578082015181840152602081019050610913565b60008484015250505050565b6000610945826108f4565b61094f81856108ff565b935061095f818560208601610910565b610968816105e0565b840191505092915050565b61097c8161071c565b82525050565b600060c08201905061099760008301896108e5565b81810360208301526109a9818861093a565b905081810360408301526109bd818761093a565b905081810360608301526109d1818661093a565b90506109e06080830185610973565b81810360a08301526109f2818461093a565b9050979650505050505050565b60008115159050919050565b610a14816109ff565b82525050565b600061012082019050610a30600083018c6108e5565b8181036020830152610a42818b61093a565b90508181036040830152610a56818a61093a565b90508181036060830152610a6a818961093a565b9050610a796080830188610973565b81810360a0830152610a8b818761093a565b9050610a9a60c0830186610a0b565b610aa760e0830185610a0b565b610ab5610100830184610a0b565b9a995050505050505050505056fea26469706673582212204a432452bb0bd915f708a0a4612563309d280b35f9edfe9f1f0be2ed5db8033464736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063073989ff1461005c578063427c1cb61461007857806361bc221a1461009457806369a98b2b146100b2578063ec3c5a14146100ce575b600080fd5b61007660048036038101906100719190610752565b6100ea565b005b610092600480360381019061008d9190610752565b6101f1565b005b61009c61030d565b6040516100a9919061086b565b60405180910390f35b6100cc60048036038101906100c79190610752565b61031e565b005b6100e860048036038101906100e39190610752565b6104c4565b005b60008081819054906101000a900460070b80929190610108906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff160217905550503073ffffffffffffffffffffffffffffffffffffffff1663427c1cb68787878787876040518763ffffffff1660e01b815260040161017596959493929190610982565b600060405180830381600087803b15801561018f57600080fd5b505af19250505080156101a0575060015b5060008081819054906101000a900460070b809291906101bf906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555050505050505050565b600060089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631dba685b87878787878760018060016040518a63ffffffff1660e01b815260040161025e99989796959493929190610a1a565b600060405180830381600087803b15801561027857600080fd5b505af115801561028c573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663ec3c5a148787878787876040518763ffffffff1660e01b81526004016102d396959493929190610982565b600060405180830381600087803b1580156102ed57600080fd5b505af1158015610301573d6000803e3d6000fd5b50505050505050505050565b60008054906101000a900460070b81565b60008081819054906101000a900460070b8092919061033c906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555050600060089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631dba685b87878787878760018060016040518a63ffffffff1660e01b81526004016103d399989796959493929190610a1a565b600060405180830381600087803b1580156103ed57600080fd5b505af1158015610401573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663ec3c5a148787878787876040518763ffffffff1660e01b815260040161044896959493929190610982565b600060405180830381600087803b15801561046257600080fd5b505af1925050508015610473575060015b5060008081819054906101000a900460070b80929190610492906108b5565b91906101000a81548167ffffffffffffffff021916908360070b67ffffffffffffffff16021790555050505050505050565b600060089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631dba685b87878787878760018060016040518a63ffffffff1660e01b815260040161053199989796959493929190610a1a565b600060405180830381600087803b15801561054b57600080fd5b505af115801561055f573d6000803e3d6000fd5b600080fd5b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006105a382610578565b9050919050565b6105b381610598565b81146105be57600080fd5b50565b6000813590506105d0816105aa565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610629826105e0565b810181811067ffffffffffffffff82111715610648576106476105f1565b5b80604052505050565b600061065b610564565b90506106678282610620565b919050565b600067ffffffffffffffff821115610687576106866105f1565b5b610690826105e0565b9050602081019050919050565b82818337600083830152505050565b60006106bf6106ba8461066c565b610651565b9050828152602081018484840111156106db576106da6105db565b5b6106e684828561069d565b509392505050565b600082601f830112610703576107026105d6565b5b81356107138482602086016106ac565b91505092915050565b6000819050919050565b61072f8161071c565b811461073a57600080fd5b50565b60008135905061074c81610726565b92915050565b60008060008060008060c0878903121561076f5761076e61056e565b5b600061077d89828a016105c1565b965050602087013567ffffffffffffffff81111561079e5761079d610573565b5b6107aa89828a016106ee565b955050604087013567ffffffffffffffff8111156107cb576107ca610573565b5b6107d789828a016106ee565b945050606087013567ffffffffffffffff8111156107f8576107f7610573565b5b61080489828a016106ee565b935050608061081589828a0161073d565b92505060a087013567ffffffffffffffff81111561083657610835610573565b5b61084289828a016106ee565b9150509295509295509295565b60008160070b9050919050565b6108658161084f565b82525050565b6000602082019050610880600083018461085c565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006108c08261084f565b9150677fffffffffffffff82036108da576108d9610886565b5b600182019050919050565b6108ee81610598565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561092e578082015181840152602081019050610913565b60008484015250505050565b6000610945826108f4565b61094f81856108ff565b935061095f818560208601610910565b610968816105e0565b840191505092915050565b61097c8161071c565b82525050565b600060c08201905061099760008301896108e5565b81810360208301526109a9818861093a565b905081810360408301526109bd818761093a565b905081810360608301526109d1818661093a565b90506109e06080830185610973565b81810360a08301526109f2818461093a565b9050979650505050505050565b60008115159050919050565b610a14816109ff565b82525050565b600061012082019050610a30600083018c6108e5565b8181036020830152610a42818b61093a565b90508181036040830152610a56818a61093a565b90508181036060830152610a6a818961093a565b9050610a796080830188610973565b81810360a0830152610a8b818761093a565b9050610a9a60c0830186610a0b565b610aa760e0830185610a0b565b610ab5610100830184610a0b565b9a995050505050505050505056fea26469706673582212204a432452bb0bd915f708a0a4612563309d280b35f9edfe9f1f0be2ed5db8033464736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/testutil/contracts/InterchainSenderCaller.sol b/precompiles/testutil/contracts/InterchainSenderCaller.sol
new file mode 100644
index 00000000..c907dd31
--- /dev/null
+++ b/precompiles/testutil/contracts/InterchainSenderCaller.sol
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: LGPL-v3
+pragma solidity >=0.8.17;
+
+import "./InterchainSender.sol";
+import "./../../ics20/ICS20I.sol";
+import "./../../common/Types.sol";
+
+contract InterchainSenderCaller {
+ int64 public counter;
+ InterchainSender interchainSender;
+
+ constructor(address _interchainSender) payable {
+ interchainSender = InterchainSender(_interchainSender);
+ }
+
+ /// @dev This function will perform 2 calls to the testMultiTransferWithInternalTransfer
+ /// @dev function of the InterchainSender contract
+ /// @dev However, the second call will be reverted,
+ /// @dev so in total should perform 2 IBC transfers
+ function transfersWithRevert(
+ address payable _source,
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver
+ ) external {
+ counter++;
+ interchainSender.testMultiTransferWithInternalTransfer(
+ _source,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ receiver,
+ true,
+ true,
+ true
+ );
+ try
+ InterchainSenderCaller(address(this))
+ .performMultiTransferWithRevert(
+ _source,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ receiver
+ )
+ {} catch {}
+ counter++;
+ }
+
+ /// @dev This function will perform 2 calls to the testMultiTransferWithInternalTransfer
+ /// @dev function of the InterchainSender contract
+ /// @dev However, the second call will be reverted,
+ /// @dev and this should revert all 4 IBC transfers
+ function transfersWithNestedRevert(
+ address payable _source,
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver
+ ) external {
+ counter++;
+ try
+ InterchainSenderCaller(address(this)).performNestedTransfers(
+ _source,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ receiver
+ )
+ {} catch {}
+ counter++;
+ }
+
+ function performNestedTransfers(
+ address payable _source,
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver
+ ) external {
+ interchainSender.testMultiTransferWithInternalTransfer(
+ _source,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ receiver,
+ true,
+ true,
+ true
+ );
+ InterchainSenderCaller(address(this)).performMultiTransferWithRevert(
+ _source,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ receiver
+ );
+ }
+
+ function performMultiTransferWithRevert(
+ address payable _source,
+ string memory sourcePort,
+ string memory sourceChannel,
+ string memory denom,
+ uint256 amount,
+ string memory receiver
+ ) external {
+ interchainSender.testMultiTransferWithInternalTransfer(
+ _source,
+ sourcePort,
+ sourceChannel,
+ denom,
+ amount,
+ receiver,
+ true,
+ true,
+ true
+ );
+ revert();
+ }
+}
diff --git a/precompiles/testutil/contracts/Reverter.json b/precompiles/testutil/contracts/Reverter.json
new file mode 100644
index 00000000..d112a79c
--- /dev/null
+++ b/precompiles/testutil/contracts/Reverter.json
@@ -0,0 +1,45 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "Reverter",
+ "sourceName": "solidity/precompiles/testutil/contracts/Reverter.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "payable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "run",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "salt",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "v",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFunds",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "bytecode": "0x608060405260008055610c17806100176000396000f3fe60806040526004361061002d5760003560e01c806379388e9414610039578063c04062261461006257610034565b3661003457005b600080fd5b34801561004557600080fd5b50610060600480360381019061005b9190610360565b610079565b005b34801561006e57600080fd5b50610077610131565b005b808290604051610088906102d4565b82906040518091039083f590509050801580156100a9573d6000803e3d6000fd5b505061080173ffffffffffffffffffffffffffffffffffffffff166354be1a28306040518263ffffffff1660e01b81526004016100e691906103e1565b600060405180830381865afa158015610103573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061012c9190610884565b600080fd5b6000808154809291906101439061092b565b91905055503073ffffffffffffffffffffffffffffffffffffffff166379388e9460005460001b476040518363ffffffff1660e01b8152600401610188929190610991565b600060405180830381600087803b1580156101a257600080fd5b505af19250505080156101b3575060015b61022f5760006101c760005460001b610249565b90508073ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561021157600080fd5b505af1158015610225573d6000803e3d6000fd5b5050505050610230565b5b6000808154809291906102429061092b565b9190505550565b60008060ff60f81b308460405180602001610263906102d4565b6020820181038252601f19601f820116604052506040516020016102879190610a01565b604051602081830303815290604052805190602001206040516020016102b09493929190610ace565b6040516020818303038152906040528051906020012060001c905080915050919050565b60c580610b1d83390190565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b610307816102f4565b811461031257600080fd5b50565b600081359050610324816102fe565b92915050565b6000819050919050565b61033d8161032a565b811461034857600080fd5b50565b60008135905061035a81610334565b92915050565b60008060408385031215610377576103766102ea565b5b600061038585828601610315565b92505060206103968582860161034b565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103cb826103a0565b9050919050565b6103db816103c0565b82525050565b60006020820190506103f660008301846103d2565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61044a82610401565b810181811067ffffffffffffffff8211171561046957610468610412565b5b80604052505050565b600061047c6102e0565b90506104888282610441565b919050565b600067ffffffffffffffff8211156104a8576104a7610412565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff8211156104e8576104e7610412565b5b6104f182610401565b9050602081019050919050565b60005b8381101561051c578082015181840152602081019050610501565b60008484015250505050565b600061053b610536846104cd565b610472565b905082815260208101848484011115610557576105566104c8565b5b6105628482856104fe565b509392505050565b600082601f83011261057f5761057e6103fc565b5b815161058f848260208601610528565b91505092915050565b600067ffffffffffffffff8211156105b3576105b2610412565b5b602082029050602081019050919050565b6000815190506105d381610334565b92915050565b600060ff82169050919050565b6105ef816105d9565b81146105fa57600080fd5b50565b60008151905061060c816105e6565b92915050565b600060608284031215610628576106276104be565b5b6106326060610472565b9050600082015167ffffffffffffffff811115610652576106516104c3565b5b61065e8482850161056a565b6000830152506020610672848285016105c4565b6020830152506040610686848285016105fd565b60408301525092915050565b60006106a56106a084610598565b610472565b905080838252602082019050602084028301858111156106c8576106c76104b9565b5b835b8181101561070f57805167ffffffffffffffff8111156106ed576106ec6103fc565b5b8086016106fa8982610612565b855260208501945050506020810190506106ca565b5050509392505050565b600082601f83011261072e5761072d6103fc565b5b815161073e848260208601610692565b91505092915050565b60006040828403121561075d5761075c6104be565b5b6107676040610472565b9050600082015167ffffffffffffffff811115610787576107866104c3565b5b6107938482850161056a565b600083015250602082015167ffffffffffffffff8111156107b7576107b66104c3565b5b6107c384828501610719565b60208301525092915050565b60006107e26107dd8461048d565b610472565b90508083825260208201905060208402830185811115610805576108046104b9565b5b835b8181101561084c57805167ffffffffffffffff81111561082a576108296103fc565b5b8086016108378982610747565b85526020850194505050602081019050610807565b5050509392505050565b600082601f83011261086b5761086a6103fc565b5b815161087b8482602086016107cf565b91505092915050565b6000806040838503121561089b5761089a6102ea565b5b600083015167ffffffffffffffff8111156108b9576108b86102ef565b5b6108c585828601610856565b925050602083015167ffffffffffffffff8111156108e6576108e56102ef565b5b6108f285828601610719565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006109368261032a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610968576109676108fc565b5b600182019050919050565b61097c816102f4565b82525050565b61098b8161032a565b82525050565b60006040820190506109a66000830185610973565b6109b36020830184610982565b9392505050565b600081519050919050565b600081905092915050565b60006109db826109ba565b6109e581856109c5565b93506109f58185602086016104fe565b80840191505092915050565b6000610a0d82846109d0565b915081905092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610a5f610a5a82610a18565b610a44565b82525050565b60008160601b9050919050565b6000610a7d82610a65565b9050919050565b6000610a8f82610a72565b9050919050565b610aa7610aa2826103c0565b610a84565b82525050565b6000819050919050565b610ac8610ac3826102f4565b610aad565b82525050565b6000610ada8287610a4e565b600182019150610aea8286610a96565b601482019150610afa8285610ab7565b602082019150610b0a8284610ab7565b6020820191508190509594505050505056fe608060405260b3806100126000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633ccfd60b14602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015607a573d6000803e3d6000fd5b5056fea26469706673582212200cca7e94767cc41a8eff494693f692a362784efcf8724ef105e5c5948d07a98a64736f6c63430008130033a26469706673582212209eedc0bf8ca98ddf4547c45c1938b3294a8c876293b916e6991af709591c556764736f6c63430008130033",
+ "deployedBytecode": "0x60806040526004361061002d5760003560e01c806379388e9414610039578063c04062261461006257610034565b3661003457005b600080fd5b34801561004557600080fd5b50610060600480360381019061005b9190610360565b610079565b005b34801561006e57600080fd5b50610077610131565b005b808290604051610088906102d4565b82906040518091039083f590509050801580156100a9573d6000803e3d6000fd5b505061080173ffffffffffffffffffffffffffffffffffffffff166354be1a28306040518263ffffffff1660e01b81526004016100e691906103e1565b600060405180830381865afa158015610103573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061012c9190610884565b600080fd5b6000808154809291906101439061092b565b91905055503073ffffffffffffffffffffffffffffffffffffffff166379388e9460005460001b476040518363ffffffff1660e01b8152600401610188929190610991565b600060405180830381600087803b1580156101a257600080fd5b505af19250505080156101b3575060015b61022f5760006101c760005460001b610249565b90508073ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561021157600080fd5b505af1158015610225573d6000803e3d6000fd5b5050505050610230565b5b6000808154809291906102429061092b565b9190505550565b60008060ff60f81b308460405180602001610263906102d4565b6020820181038252601f19601f820116604052506040516020016102879190610a01565b604051602081830303815290604052805190602001206040516020016102b09493929190610ace565b6040516020818303038152906040528051906020012060001c905080915050919050565b60c580610b1d83390190565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b610307816102f4565b811461031257600080fd5b50565b600081359050610324816102fe565b92915050565b6000819050919050565b61033d8161032a565b811461034857600080fd5b50565b60008135905061035a81610334565b92915050565b60008060408385031215610377576103766102ea565b5b600061038585828601610315565b92505060206103968582860161034b565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103cb826103a0565b9050919050565b6103db816103c0565b82525050565b60006020820190506103f660008301846103d2565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61044a82610401565b810181811067ffffffffffffffff8211171561046957610468610412565b5b80604052505050565b600061047c6102e0565b90506104888282610441565b919050565b600067ffffffffffffffff8211156104a8576104a7610412565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff8211156104e8576104e7610412565b5b6104f182610401565b9050602081019050919050565b60005b8381101561051c578082015181840152602081019050610501565b60008484015250505050565b600061053b610536846104cd565b610472565b905082815260208101848484011115610557576105566104c8565b5b6105628482856104fe565b509392505050565b600082601f83011261057f5761057e6103fc565b5b815161058f848260208601610528565b91505092915050565b600067ffffffffffffffff8211156105b3576105b2610412565b5b602082029050602081019050919050565b6000815190506105d381610334565b92915050565b600060ff82169050919050565b6105ef816105d9565b81146105fa57600080fd5b50565b60008151905061060c816105e6565b92915050565b600060608284031215610628576106276104be565b5b6106326060610472565b9050600082015167ffffffffffffffff811115610652576106516104c3565b5b61065e8482850161056a565b6000830152506020610672848285016105c4565b6020830152506040610686848285016105fd565b60408301525092915050565b60006106a56106a084610598565b610472565b905080838252602082019050602084028301858111156106c8576106c76104b9565b5b835b8181101561070f57805167ffffffffffffffff8111156106ed576106ec6103fc565b5b8086016106fa8982610612565b855260208501945050506020810190506106ca565b5050509392505050565b600082601f83011261072e5761072d6103fc565b5b815161073e848260208601610692565b91505092915050565b60006040828403121561075d5761075c6104be565b5b6107676040610472565b9050600082015167ffffffffffffffff811115610787576107866104c3565b5b6107938482850161056a565b600083015250602082015167ffffffffffffffff8111156107b7576107b66104c3565b5b6107c384828501610719565b60208301525092915050565b60006107e26107dd8461048d565b610472565b90508083825260208201905060208402830185811115610805576108046104b9565b5b835b8181101561084c57805167ffffffffffffffff81111561082a576108296103fc565b5b8086016108378982610747565b85526020850194505050602081019050610807565b5050509392505050565b600082601f83011261086b5761086a6103fc565b5b815161087b8482602086016107cf565b91505092915050565b6000806040838503121561089b5761089a6102ea565b5b600083015167ffffffffffffffff8111156108b9576108b86102ef565b5b6108c585828601610856565b925050602083015167ffffffffffffffff8111156108e6576108e56102ef565b5b6108f285828601610719565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006109368261032a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610968576109676108fc565b5b600182019050919050565b61097c816102f4565b82525050565b61098b8161032a565b82525050565b60006040820190506109a66000830185610973565b6109b36020830184610982565b9392505050565b600081519050919050565b600081905092915050565b60006109db826109ba565b6109e581856109c5565b93506109f58185602086016104fe565b80840191505092915050565b6000610a0d82846109d0565b915081905092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610a5f610a5a82610a18565b610a44565b82525050565b60008160601b9050919050565b6000610a7d82610a65565b9050919050565b6000610a8f82610a72565b9050919050565b610aa7610aa2826103c0565b610a84565b82525050565b6000819050919050565b610ac8610ac3826102f4565b610aad565b82525050565b6000610ada8287610a4e565b600182019150610aea8286610a96565b601482019150610afa8285610ab7565b602082019150610b0a8284610ab7565b6020820191508190509594505050505056fe608060405260b3806100126000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633ccfd60b14602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015607a573d6000803e3d6000fd5b5056fea26469706673582212200cca7e94767cc41a8eff494693f692a362784efcf8724ef105e5c5948d07a98a64736f6c63430008130033a26469706673582212209eedc0bf8ca98ddf4547c45c1938b3294a8c876293b916e6991af709591c556764736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/testutil/contracts/Reverter.sol b/precompiles/testutil/contracts/Reverter.sol
new file mode 100644
index 00000000..1e22df42
--- /dev/null
+++ b/precompiles/testutil/contracts/Reverter.sol
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "../../distribution/DistributionI.sol";
+
+contract Reverter {
+ uint counter = 0;
+
+ constructor() payable {}
+
+ function run() external {
+ counter++;
+
+ // call Reverter::transferFunds() externally to create new context, sending this contract's full balance.
+ try
+ Reverter(payable(address(this))).transferFunds(
+ bytes32(counter),
+ address(this).balance
+ )
+ {} catch {
+ // Transferer created by the call to Reverter::transferFunds(), as well as the funds sent
+ // to it, should not exist. Changes should be reverted
+ // and trying to call the Transferer(t).withdraw() should make the tx fail
+ address t = predictAddress(bytes32(counter));
+ Transferer(t).withdraw();
+ }
+ // increment the salt
+ counter++;
+ }
+
+ function transferFunds(bytes32 salt, uint v) external {
+ // create Transferer, and send it v native tokens
+ new Transferer{value: v, salt: salt}();
+
+ // call the distribution precompile
+ DISTRIBUTION_CONTRACT.delegationTotalRewards(address(this));
+
+ // newly-created Transferer is removed from the journal, and the native tokens are returned to this
+ // contract.
+ revert();
+ }
+
+ // calculates the CREATE2 address of deploying Transferer with some salt
+ function predictAddress(bytes32 salt) internal view returns (address) {
+ address predictedAddress = address(
+ uint160(
+ uint(
+ keccak256(
+ abi.encodePacked(
+ bytes1(0xff),
+ address(this),
+ salt,
+ keccak256(
+ abi.encodePacked(type(Transferer).creationCode)
+ )
+ )
+ )
+ )
+ )
+ );
+
+ return predictedAddress;
+ }
+
+ // receive native tokens
+ receive() external payable {}
+}
+
+contract Transferer {
+ constructor() payable {}
+
+ function withdraw() external {
+ payable(msg.sender).transfer(address(this).balance);
+ }
+}
diff --git a/precompiles/testutil/contracts/StakingReverter.json b/precompiles/testutil/contracts/StakingReverter.json
new file mode 100644
index 00000000..1b593074
--- /dev/null
+++ b/precompiles/testutil/contracts/StakingReverter.json
@@ -0,0 +1,164 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "StakingReverter",
+ "sourceName": "solidity/precompiles/testutil/contracts/StakingReverter.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "payable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "getCurrentStake",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "shares",
+ "type": "uint256"
+ },
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "denom",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Coin",
+ "name": "balance",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "numTimes",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "validatorAddress",
+ "type": "address"
+ }
+ ],
+ "name": "multipleQueries",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "string",
+ "name": "operatorAddress",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "consensusPubkey",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "jailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "enum BondStatus",
+ "name": "status",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokens",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatorShares",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "description",
+ "type": "string"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingHeight",
+ "type": "int64"
+ },
+ {
+ "internalType": "int64",
+ "name": "unbondingTime",
+ "type": "int64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "commission",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minSelfDelegation",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct Validator",
+ "name": "validator",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "performDelegation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "numTimes",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "validatorAddress",
+ "type": "string"
+ }
+ ],
+ "name": "run",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405260008055610f2a806100176000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634e5a8fe514610051578063668f452b1461006d578063cbc367d41461009e578063f66013d7146100ce575b600080fd5b61006b6004803603810190610066919061049d565b6100ea565b005b610087600480360381019061008291906104fd565b61018c565b604051610095929190610635565b60405180910390f35b6100b860048036038101906100b391906106c3565b610226565b6040516100c591906108ae565b60405180910390f35b6100e860048036038101906100e391906104fd565b6102d6565b005b6000808154809291906100fc906108ff565b919050555060005b83811015610186573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610147929190610994565b600060405180830381600087803b15801561016157600080fd5b505af1925050508015610172575060015b50808061017e906108ff565b915050610104565b50505050565b6000610196610360565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e63086866040518463ffffffff1660e01b81526004016101d5939291906109c7565b600060405180830381865afa1580156101f2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061021b9190610ba5565b915091509250929050565b61022e61037a565b60005b838110156102cf5761080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a846040518263ffffffff1660e01b81526004016102749190610c01565b600060405180830381865afa158015610291573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906102ba9190610df9565b915080806102c7906108ff565b915050610231565b5092915050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016103189493929190610e87565b6020604051808303816000875af1158015610337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035b9190610ec7565b600080fd5b604051806040016040528060608152602001600081525090565b6040518061016001604052806060815260200160608152602001600015158152602001600060038111156103b1576103b061071e565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61041581610402565b811461042057600080fd5b50565b6000813590506104328161040c565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261045d5761045c610438565b5b8235905067ffffffffffffffff81111561047a5761047961043d565b5b60208301915083600182028301111561049657610495610442565b5b9250929050565b6000806000604084860312156104b6576104b56103f8565b5b60006104c486828701610423565b935050602084013567ffffffffffffffff8111156104e5576104e46103fd565b5b6104f186828701610447565b92509250509250925092565b60008060208385031215610514576105136103f8565b5b600083013567ffffffffffffffff811115610532576105316103fd565b5b61053e85828601610447565b92509250509250929050565b61055381610402565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610593578082015181840152602081019050610578565b60008484015250505050565b6000601f19601f8301169050919050565b60006105bb82610559565b6105c58185610564565b93506105d5818560208601610575565b6105de8161059f565b840191505092915050565b6105f281610402565b82525050565b6000604083016000830151848203600086015261061582826105b0565b915050602083015161062a60208601826105e9565b508091505092915050565b600060408201905061064a600083018561054a565b818103602083015261065c81846105f8565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061069082610665565b9050919050565b6106a081610685565b81146106ab57600080fd5b50565b6000813590506106bd81610697565b92915050565b600080604083850312156106da576106d96103f8565b5b60006106e885828601610423565b92505060206106f9858286016106ae565b9150509250929050565b60008115159050919050565b61071881610703565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061075e5761075d61071e565b5b50565b600081905061076f8261074d565b919050565b600061077f82610761565b9050919050565b61078f81610774565b82525050565b60008160070b9050919050565b6107ab81610795565b82525050565b60006101608301600083015184820360008601526107cf82826105b0565b915050602083015184820360208601526107e982826105b0565b91505060408301516107fe604086018261070f565b5060608301516108116060860182610786565b50608083015161082460808601826105e9565b5060a083015161083760a08601826105e9565b5060c083015184820360c086015261084f82826105b0565b91505060e083015161086460e08601826107a2565b506101008301516108796101008601826107a2565b5061012083015161088e6101208601826105e9565b506101408301516108a36101408601826105e9565b508091505092915050565b600060208201905081810360008301526108c881846107b1565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061090a82610402565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361093c5761093b6108d0565b5b600182019050919050565b600082825260208201905092915050565b82818337600083830152505050565b60006109738385610947565b9350610980838584610958565b6109898361059f565b840190509392505050565b600060208201905081810360008301526109af818486610967565b90509392505050565b6109c181610685565b82525050565b60006040820190506109dc60008301866109b8565b81810360208301526109ef818486610967565b9050949350505050565b600081519050610a088161040c565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610a4b8261059f565b810181811067ffffffffffffffff82111715610a6a57610a69610a13565b5b80604052505050565b6000610a7d6103ee565b9050610a898282610a42565b919050565b600080fd5b600080fd5b600067ffffffffffffffff821115610ab357610ab2610a13565b5b610abc8261059f565b9050602081019050919050565b6000610adc610ad784610a98565b610a73565b905082815260208101848484011115610af857610af7610a93565b5b610b03848285610575565b509392505050565b600082601f830112610b2057610b1f610438565b5b8151610b30848260208601610ac9565b91505092915050565b600060408284031215610b4f57610b4e610a0e565b5b610b596040610a73565b9050600082015167ffffffffffffffff811115610b7957610b78610a8e565b5b610b8584828501610b0b565b6000830152506020610b99848285016109f9565b60208301525092915050565b60008060408385031215610bbc57610bbb6103f8565b5b6000610bca858286016109f9565b925050602083015167ffffffffffffffff811115610beb57610bea6103fd565b5b610bf785828601610b39565b9150509250929050565b6000602082019050610c1660008301846109b8565b92915050565b610c2581610703565b8114610c3057600080fd5b50565b600081519050610c4281610c1c565b92915050565b60048110610c5557600080fd5b50565b600081519050610c6781610c48565b92915050565b610c7681610795565b8114610c8157600080fd5b50565b600081519050610c9381610c6d565b92915050565b60006101608284031215610cb057610caf610a0e565b5b610cbb610160610a73565b9050600082015167ffffffffffffffff811115610cdb57610cda610a8e565b5b610ce784828501610b0b565b600083015250602082015167ffffffffffffffff811115610d0b57610d0a610a8e565b5b610d1784828501610b0b565b6020830152506040610d2b84828501610c33565b6040830152506060610d3f84828501610c58565b6060830152506080610d53848285016109f9565b60808301525060a0610d67848285016109f9565b60a08301525060c082015167ffffffffffffffff811115610d8b57610d8a610a8e565b5b610d9784828501610b0b565b60c08301525060e0610dab84828501610c84565b60e083015250610100610dc084828501610c84565b61010083015250610120610dd6848285016109f9565b61012083015250610140610dec848285016109f9565b6101408301525092915050565b600060208284031215610e0f57610e0e6103f8565b5b600082015167ffffffffffffffff811115610e2d57610e2c6103fd565b5b610e3984828501610c99565b91505092915050565b6000819050919050565b6000819050919050565b6000610e71610e6c610e6784610e42565b610e4c565b610402565b9050919050565b610e8181610e56565b82525050565b6000606082019050610e9c60008301876109b8565b8181036020830152610eaf818587610967565b9050610ebe6040830184610e78565b95945050505050565b600060208284031215610edd57610edc6103f8565b5b6000610eeb84828501610c33565b9150509291505056fea264697066735822122065bd7ead5aeed227652c5f7a1cd2f7e458fbac5943bc70b2e7e985c82969ffac64736f6c63430008130033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634e5a8fe514610051578063668f452b1461006d578063cbc367d41461009e578063f66013d7146100ce575b600080fd5b61006b6004803603810190610066919061049d565b6100ea565b005b610087600480360381019061008291906104fd565b61018c565b604051610095929190610635565b60405180910390f35b6100b860048036038101906100b391906106c3565b610226565b6040516100c591906108ae565b60405180910390f35b6100e860048036038101906100e391906104fd565b6102d6565b005b6000808154809291906100fc906108ff565b919050555060005b83811015610186573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610147929190610994565b600060405180830381600087803b15801561016157600080fd5b505af1925050508015610172575060015b50808061017e906108ff565b915050610104565b50505050565b6000610196610360565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e63086866040518463ffffffff1660e01b81526004016101d5939291906109c7565b600060405180830381865afa1580156101f2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061021b9190610ba5565b915091509250929050565b61022e61037a565b60005b838110156102cf5761080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a846040518263ffffffff1660e01b81526004016102749190610c01565b600060405180830381865afa158015610291573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906102ba9190610df9565b915080806102c7906108ff565b915050610231565b5092915050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016103189493929190610e87565b6020604051808303816000875af1158015610337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035b9190610ec7565b600080fd5b604051806040016040528060608152602001600081525090565b6040518061016001604052806060815260200160608152602001600015158152602001600060038111156103b1576103b061071e565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61041581610402565b811461042057600080fd5b50565b6000813590506104328161040c565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261045d5761045c610438565b5b8235905067ffffffffffffffff81111561047a5761047961043d565b5b60208301915083600182028301111561049657610495610442565b5b9250929050565b6000806000604084860312156104b6576104b56103f8565b5b60006104c486828701610423565b935050602084013567ffffffffffffffff8111156104e5576104e46103fd565b5b6104f186828701610447565b92509250509250925092565b60008060208385031215610514576105136103f8565b5b600083013567ffffffffffffffff811115610532576105316103fd565b5b61053e85828601610447565b92509250509250929050565b61055381610402565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610593578082015181840152602081019050610578565b60008484015250505050565b6000601f19601f8301169050919050565b60006105bb82610559565b6105c58185610564565b93506105d5818560208601610575565b6105de8161059f565b840191505092915050565b6105f281610402565b82525050565b6000604083016000830151848203600086015261061582826105b0565b915050602083015161062a60208601826105e9565b508091505092915050565b600060408201905061064a600083018561054a565b818103602083015261065c81846105f8565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061069082610665565b9050919050565b6106a081610685565b81146106ab57600080fd5b50565b6000813590506106bd81610697565b92915050565b600080604083850312156106da576106d96103f8565b5b60006106e885828601610423565b92505060206106f9858286016106ae565b9150509250929050565b60008115159050919050565b61071881610703565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061075e5761075d61071e565b5b50565b600081905061076f8261074d565b919050565b600061077f82610761565b9050919050565b61078f81610774565b82525050565b60008160070b9050919050565b6107ab81610795565b82525050565b60006101608301600083015184820360008601526107cf82826105b0565b915050602083015184820360208601526107e982826105b0565b91505060408301516107fe604086018261070f565b5060608301516108116060860182610786565b50608083015161082460808601826105e9565b5060a083015161083760a08601826105e9565b5060c083015184820360c086015261084f82826105b0565b91505060e083015161086460e08601826107a2565b506101008301516108796101008601826107a2565b5061012083015161088e6101208601826105e9565b506101408301516108a36101408601826105e9565b508091505092915050565b600060208201905081810360008301526108c881846107b1565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061090a82610402565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361093c5761093b6108d0565b5b600182019050919050565b600082825260208201905092915050565b82818337600083830152505050565b60006109738385610947565b9350610980838584610958565b6109898361059f565b840190509392505050565b600060208201905081810360008301526109af818486610967565b90509392505050565b6109c181610685565b82525050565b60006040820190506109dc60008301866109b8565b81810360208301526109ef818486610967565b9050949350505050565b600081519050610a088161040c565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610a4b8261059f565b810181811067ffffffffffffffff82111715610a6a57610a69610a13565b5b80604052505050565b6000610a7d6103ee565b9050610a898282610a42565b919050565b600080fd5b600080fd5b600067ffffffffffffffff821115610ab357610ab2610a13565b5b610abc8261059f565b9050602081019050919050565b6000610adc610ad784610a98565b610a73565b905082815260208101848484011115610af857610af7610a93565b5b610b03848285610575565b509392505050565b600082601f830112610b2057610b1f610438565b5b8151610b30848260208601610ac9565b91505092915050565b600060408284031215610b4f57610b4e610a0e565b5b610b596040610a73565b9050600082015167ffffffffffffffff811115610b7957610b78610a8e565b5b610b8584828501610b0b565b6000830152506020610b99848285016109f9565b60208301525092915050565b60008060408385031215610bbc57610bbb6103f8565b5b6000610bca858286016109f9565b925050602083015167ffffffffffffffff811115610beb57610bea6103fd565b5b610bf785828601610b39565b9150509250929050565b6000602082019050610c1660008301846109b8565b92915050565b610c2581610703565b8114610c3057600080fd5b50565b600081519050610c4281610c1c565b92915050565b60048110610c5557600080fd5b50565b600081519050610c6781610c48565b92915050565b610c7681610795565b8114610c8157600080fd5b50565b600081519050610c9381610c6d565b92915050565b60006101608284031215610cb057610caf610a0e565b5b610cbb610160610a73565b9050600082015167ffffffffffffffff811115610cdb57610cda610a8e565b5b610ce784828501610b0b565b600083015250602082015167ffffffffffffffff811115610d0b57610d0a610a8e565b5b610d1784828501610b0b565b6020830152506040610d2b84828501610c33565b6040830152506060610d3f84828501610c58565b6060830152506080610d53848285016109f9565b60808301525060a0610d67848285016109f9565b60a08301525060c082015167ffffffffffffffff811115610d8b57610d8a610a8e565b5b610d9784828501610b0b565b60c08301525060e0610dab84828501610c84565b60e083015250610100610dc084828501610c84565b61010083015250610120610dd6848285016109f9565b61012083015250610140610dec848285016109f9565b6101408301525092915050565b600060208284031215610e0f57610e0e6103f8565b5b600082015167ffffffffffffffff811115610e2d57610e2c6103fd565b5b610e3984828501610c99565b91505092915050565b6000819050919050565b6000819050919050565b6000610e71610e6c610e6784610e42565b610e4c565b610402565b9050919050565b610e8181610e56565b82525050565b6000606082019050610e9c60008301876109b8565b8181036020830152610eaf818587610967565b9050610ebe6040830184610e78565b95945050505050565b600060208284031215610edd57610edc6103f8565b5b6000610eeb84828501610c33565b9150509291505056fea264697066735822122065bd7ead5aeed227652c5f7a1cd2f7e458fbac5943bc70b2e7e985c82969ffac64736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/precompiles/testutil/contracts/StakingReverter.sol b/precompiles/testutil/contracts/StakingReverter.sol
new file mode 100644
index 00000000..e287d470
--- /dev/null
+++ b/precompiles/testutil/contracts/StakingReverter.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "../../staking/StakingI.sol";
+
+contract StakingReverter {
+ uint counter = 0;
+
+ constructor() payable {}
+
+ function run(uint numTimes, string calldata validatorAddress) external {
+ counter++;
+
+ for (uint i = 0; i < numTimes; i++) {
+ try
+ StakingReverter(address(this)).performDelegation(
+ validatorAddress
+ )
+ {} catch {}
+ }
+ }
+
+ function performDelegation(string calldata validatorAddress) external {
+ STAKING_CONTRACT.delegate(address(this), validatorAddress, 10);
+ revert();
+ }
+
+ function getCurrentStake(
+ string calldata validatorAddress
+ ) external view returns (uint256 shares, Coin memory balance) {
+ return STAKING_CONTRACT.delegation(address(this), validatorAddress);
+ }
+
+ function multipleQueries(
+ uint numTimes,
+ address validatorAddress
+ ) external view returns (Validator memory validator) {
+ for (uint i = 0; i < numTimes; i++) {
+ validator = STAKING_CONTRACT.validator(validatorAddress);
+ }
+ return validator;
+ }
+}
diff --git a/precompiles/testutil/contracts/contracts.go b/precompiles/testutil/contracts/contracts.go
new file mode 100644
index 00000000..9fa518ad
--- /dev/null
+++ b/precompiles/testutil/contracts/contracts.go
@@ -0,0 +1,111 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/os/crypto/ethsecp256k1"
+ example_app "github.com/evmos/os/example_chain"
+ precompiletestutil "github.com/evmos/os/precompiles/testutil"
+ evmosutil "github.com/evmos/os/testutil"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// Call is a helper function to call any arbitrary smart contract.
+func Call(ctx sdk.Context, app *example_app.ExampleChain, args CallArgs) (res abci.ResponseDeliverTx, ethRes *evmtypes.MsgEthereumTxResponse, err error) {
+ var (
+ nonce uint64
+ gasLimit = args.GasLimit
+ )
+
+ if args.PrivKey == nil {
+ return abci.ResponseDeliverTx{}, nil, fmt.Errorf("private key is required; got: %v", args.PrivKey)
+ }
+
+ pk, ok := args.PrivKey.(*ethsecp256k1.PrivKey)
+ if !ok {
+ return abci.ResponseDeliverTx{}, nil, errors.New("error while casting type ethsecp256k1.PrivKey on provided private key")
+ }
+
+ key, err := pk.ToECDSA()
+ if err != nil {
+ return abci.ResponseDeliverTx{}, nil, fmt.Errorf("error while converting private key to ecdsa: %v", err)
+ }
+
+ addr := crypto.PubkeyToAddress(key.PublicKey)
+
+ if args.Nonce == nil {
+ nonce = app.EVMKeeper.GetNonce(ctx, addr)
+ } else {
+ nonce = args.Nonce.Uint64()
+ }
+
+ // if gas limit not provided
+ // use default
+ if args.GasLimit == 0 {
+ gasLimit = 1000000
+ }
+
+ // if gas price not provided
+ var gasPrice *big.Int
+ if args.GasPrice == nil {
+ gasPrice = app.FeeMarketKeeper.GetBaseFee(ctx) // default gas price == block base fee
+ } else {
+ gasPrice = args.GasPrice
+ }
+
+ // Create MsgEthereumTx that calls the contract
+ input, err := args.ContractABI.Pack(args.MethodName, args.Args...)
+ if err != nil {
+ return abci.ResponseDeliverTx{}, nil, fmt.Errorf("error while packing the input: %v", err)
+ }
+
+ // Create MsgEthereumTx that calls the contract
+ msg := evmtypes.NewTx(&evmtypes.EvmTxArgs{
+ ChainID: app.EVMKeeper.ChainID(),
+ Nonce: nonce,
+ To: &args.ContractAddr,
+ Amount: args.Amount,
+ GasLimit: gasLimit,
+ GasPrice: gasPrice,
+ GasFeeCap: args.GasFeeCap,
+ GasTipCap: args.GasTipCap,
+ Input: input,
+ Accesses: args.AccessList,
+ })
+ msg.From = addr.Hex()
+
+ res, err = evmosutil.DeliverEthTx(app, args.PrivKey, msg)
+ if err != nil {
+ return res, nil, fmt.Errorf("error during deliver tx: %s", err)
+ }
+ if !res.IsOK() {
+ return res, nil, fmt.Errorf("error during deliver tx: %v", res.Log)
+ }
+
+ ethRes, err = evmtypes.DecodeTxResponse(res.Data)
+ if err != nil {
+ return res, nil, fmt.Errorf("error while decoding tx response: %v", err)
+ }
+
+ return res, ethRes, nil
+}
+
+// CallContractAndCheckLogs is a helper function to call any arbitrary smart contract and check that the logs
+// contain the expected events.
+func CallContractAndCheckLogs(ctx sdk.Context, app *example_app.ExampleChain, cArgs CallArgs, logCheckArgs precompiletestutil.LogCheckArgs) (abci.ResponseDeliverTx, *evmtypes.MsgEthereumTxResponse, error) {
+ res, ethRes, err := Call(ctx, app, cArgs)
+ if err != nil {
+ return res, nil, err
+ }
+
+ logCheckArgs.Res = res
+ return res, ethRes, precompiletestutil.CheckLogs(logCheckArgs)
+}
diff --git a/precompiles/testutil/contracts/counter.go b/precompiles/testutil/contracts/counter.go
new file mode 100644
index 00000000..49c503be
--- /dev/null
+++ b/precompiles/testutil/contracts/counter.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ contractutils "github.com/evmos/os/contracts/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func LoadCounterContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("Counter.json")
+}
diff --git a/precompiles/testutil/contracts/distribution_caller.go b/precompiles/testutil/contracts/distribution_caller.go
new file mode 100644
index 00000000..8f46c663
--- /dev/null
+++ b/precompiles/testutil/contracts/distribution_caller.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ contractutils "github.com/evmos/os/contracts/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func LoadDistributionCallerContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("DistributionCaller.json")
+}
diff --git a/precompiles/testutil/contracts/flash_loan.go b/precompiles/testutil/contracts/flash_loan.go
new file mode 100644
index 00000000..fc0d41a0
--- /dev/null
+++ b/precompiles/testutil/contracts/flash_loan.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ contractutils "github.com/evmos/os/contracts/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func LoadFlashLoanContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("FlashLoan.json")
+}
diff --git a/precompiles/testutil/contracts/interchain_sender.go b/precompiles/testutil/contracts/interchain_sender.go
new file mode 100644
index 00000000..c7d33281
--- /dev/null
+++ b/precompiles/testutil/contracts/interchain_sender.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ contractutils "github.com/evmos/os/contracts/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func LoadInterchainSenderContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("InterchainSender.json")
+}
diff --git a/precompiles/testutil/contracts/interchain_sender_caller.go b/precompiles/testutil/contracts/interchain_sender_caller.go
new file mode 100644
index 00000000..66ba1594
--- /dev/null
+++ b/precompiles/testutil/contracts/interchain_sender_caller.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ contractutils "github.com/evmos/os/contracts/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func LoadInterchainSenderCallerContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("InterchainSenderCaller.json")
+}
diff --git a/precompiles/testutil/contracts/reverter.go b/precompiles/testutil/contracts/reverter.go
new file mode 100644
index 00000000..e8ae95cd
--- /dev/null
+++ b/precompiles/testutil/contracts/reverter.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ contractutils "github.com/evmos/os/contracts/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func LoadReverterContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("Reverter.json")
+}
diff --git a/precompiles/testutil/contracts/staking_reverter.go b/precompiles/testutil/contracts/staking_reverter.go
new file mode 100644
index 00000000..8c794f8d
--- /dev/null
+++ b/precompiles/testutil/contracts/staking_reverter.go
@@ -0,0 +1,13 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ contractutils "github.com/evmos/os/contracts/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func LoadStakingReverterContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LoadContractFromJSONFile("StakingReverter.json")
+}
diff --git a/precompiles/testutil/contracts/types.go b/precompiles/testutil/contracts/types.go
new file mode 100644
index 00000000..bea3d71e
--- /dev/null
+++ b/precompiles/testutil/contracts/types.go
@@ -0,0 +1,115 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package contracts
+
+import (
+ "math/big"
+
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+)
+
+// CallArgs is a struct to define all relevant data to call a smart contract.
+type CallArgs struct {
+ // Amount is the msg.value sent with the transaction.
+ Amount *big.Int
+ // AccessList is the access list to use for the transaction. If not empty, the transaction will be an EIP-2930 transaction (AccessListTx).
+ AccessList *ethtypes.AccessList
+ // ContractAddr is the address of the contract to call.
+ ContractAddr common.Address
+ // ContractABI is the ABI of the contract to call.
+ ContractABI abi.ABI
+ // MethodName is the name of the method to call.
+ MethodName string
+ // Nonce is the nonce to use for the transaction.
+ Nonce *big.Int
+ // GasLimit to use for the transaction
+ GasLimit uint64
+ // GasPrice is the gas price to use. If left empty, the base fee for the current block will be used.
+ GasPrice *big.Int
+ // GasFeeCap is the gas fee cap to use. If not empty, the transaction will be an EIP-1559 transaction (DynamicFeeTx).
+ GasFeeCap *big.Int
+ // GasTipCap is the gas tip cap to use. If not empty, the transaction will be an EIP-1559 transaction (DynamicFeeTx).
+ GasTipCap *big.Int
+ // PrivKey is the private key to be used for the transaction.
+ PrivKey cryptotypes.PrivKey
+ // Args are the arguments to pass to the method.
+ Args []interface{}
+}
+
+// WithAddress returns the CallArgs with the given address.
+func (c CallArgs) WithAddress(addr common.Address) CallArgs {
+ c.ContractAddr = addr
+ return c
+}
+
+// WithABI returns the CallArgs with the given contract ABI.
+func (c CallArgs) WithABI(abi abi.ABI) CallArgs {
+ c.ContractABI = abi
+ return c
+}
+
+// WithMethodName returns the CallArgs with the given method name.
+func (c CallArgs) WithMethodName(methodName string) CallArgs {
+ c.MethodName = methodName
+ return c
+}
+
+// WithNonce returns the CallArgs with the given nonce.
+func (c CallArgs) WithNonce(nonce *big.Int) CallArgs {
+ c.Nonce = nonce
+ return c
+}
+
+// WithGasLimit returns the CallArgs with the given gas limit.
+func (c CallArgs) WithGasLimit(gasLimit uint64) CallArgs {
+ c.GasLimit = gasLimit
+ return c
+}
+
+// WithPrivKey returns the CallArgs with the given private key.
+func (c CallArgs) WithPrivKey(privKey cryptotypes.PrivKey) CallArgs {
+ c.PrivKey = privKey
+ return c
+}
+
+// WithArgs populates the CallArgs struct's Args field with the given list of arguments.
+// These are the arguments that will be packed into the contract call input.
+func (c CallArgs) WithArgs(args ...interface{}) CallArgs {
+ c.Args = append([]interface{}{}, args...)
+ return c
+}
+
+// WithAmount populates the CallArgs struct's Amount field with the given amount.
+// This is the amount of Evmos that will be sent with the contract call.
+func (c CallArgs) WithAmount(amount *big.Int) CallArgs {
+ c.Amount = amount
+ return c
+}
+
+// WithGasPrice returns the CallArgs with the given gas price.
+func (c CallArgs) WithGasPrice(gasPrice *big.Int) CallArgs {
+ c.GasPrice = gasPrice
+ return c
+}
+
+// WithGasFeeCap returns the CallArgs with the given gas fee cap.
+func (c CallArgs) WithGasFeeCap(gasFeeCap *big.Int) CallArgs {
+ c.GasFeeCap = gasFeeCap
+ return c
+}
+
+// WithGasTipCap returns the CallArgs with the given gas tip cap.
+func (c CallArgs) WithGasTipCap(gasTipCap *big.Int) CallArgs {
+ c.GasTipCap = gasTipCap
+ return c
+}
+
+// WithAccessList returns the CallArgs with the given access list.
+func (c CallArgs) WithAccessList(accessList *ethtypes.AccessList) CallArgs {
+ c.AccessList = accessList
+ return c
+}
diff --git a/precompiles/testutil/errors.go b/precompiles/testutil/errors.go
new file mode 100644
index 00000000..e5244996
--- /dev/null
+++ b/precompiles/testutil/errors.go
@@ -0,0 +1,35 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testutil
+
+import (
+ "fmt"
+ "strings"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// CheckVMError is a helper function used to check if the transaction is reverted with the expected error message
+// in the VmError field of the MsgEthereumResponse struct.
+func CheckVMError(res abci.ResponseDeliverTx, expErrMsg string, args ...interface{}) error {
+ if !res.IsOK() {
+ return fmt.Errorf("code 0 was expected on response but got code %d", res.Code)
+ }
+ ethRes, err := evmtypes.DecodeTxResponse(res.Data)
+ if err != nil {
+ return fmt.Errorf("error occurred while decoding the TxResponse. %s", err)
+ }
+ expMsg := fmt.Sprintf(expErrMsg, args...)
+ if !strings.Contains(ethRes.VmError, expMsg) {
+ return fmt.Errorf("unexpected VmError on response. expected error to contain: %s, received: %s", expMsg, ethRes.VmError)
+ }
+ return nil
+}
+
+// CheckEthereumTxFailed checks if there is a VM error in the transaction response and returns the reason.
+func CheckEthereumTxFailed(ethRes *evmtypes.MsgEthereumTxResponse) (string, bool) {
+ reason := ethRes.VmError
+ return reason, reason != ""
+}
diff --git a/precompiles/testutil/events.go b/precompiles/testutil/events.go
new file mode 100644
index 00000000..9e8bc5c6
--- /dev/null
+++ b/precompiles/testutil/events.go
@@ -0,0 +1,72 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testutil
+
+import (
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "strings"
+
+ //nolint:stylecheck,revive // it's common practice to use the global imports for Ginkgo and Gomega
+ . "github.com/onsi/gomega"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// CheckAuthorizationEvents is a helper function used in the integration tests and checks if the approval event is emitted.
+//
+// If the amount is nil, it will not check for the amount in the event, which should be used for any generic approvals.
+func CheckAuthorizationEvents(event abi.Event, precompileAddr, granter, grantee common.Address, res abci.ResponseDeliverTx, height int64, msgTypes []string, amount *big.Int) {
+ var log evmtypes.Log
+ // Tx log is always the second last event
+ txLogAttributes := res.Events[len(res.Events)-2].Attributes
+ attr := txLogAttributes[0]
+
+ err := json.Unmarshal([]byte(attr.Value), &log)
+ Expect(err).To(BeNil(), "failed to unmarshal log")
+
+ // Check the key of the log is the expected one
+ Expect(attr.Key).To(Equal(evmtypes.AttributeKeyTxLog), "expected different key for log")
+
+ // Check if the log has the expected indexed fields and data
+ Expect(log.Address).To(Equal(precompileAddr.String()), "expected different address in event")
+ Expect(log.BlockNumber).To(Equal(uint64(height)), "expected different block number in event")
+ Expect(log.Topics[0]).To(Equal(event.ID.String()), "expected different event ID")
+ Expect(common.HexToAddress(log.Topics[1])).To(Equal(grantee), "expected different grantee in event")
+ Expect(common.HexToAddress(log.Topics[2])).To(Equal(granter), "expected different granter in event")
+
+ // Unpack the arguments from the Data field
+ arguments := make(abi.Arguments, 0, len(event.Inputs))
+ arguments = append(arguments, event.Inputs...)
+ unpackedData, err := arguments.Unpack(log.Data)
+ Expect(err).To(BeNil(), "failed to unpack log data")
+
+ Expect(unpackedData[0]).To(Equal(msgTypes), "expected different message types in event")
+ if amount != nil {
+ Expect(len(unpackedData)).To(Equal(2), "expected different number of arguments in event")
+ Expect(unpackedData[1]).To(Equal(amount), "expected different amount in event")
+ }
+}
+
+// validateEvents checks if the provided event names are included as keys in the contract events.
+func validateEvents(contractEvents map[string]abi.Event, events []string) ([]abi.Event, error) {
+ expEvents := make([]abi.Event, 0, len(events))
+ for _, eventStr := range events {
+ event, found := contractEvents[eventStr]
+ if !found {
+ availableABIEvents := make([]string, 0, len(contractEvents))
+ for event := range contractEvents {
+ availableABIEvents = append(availableABIEvents, event)
+ }
+ availableABIEventsStr := strings.Join(availableABIEvents, ", ")
+ return nil, fmt.Errorf("unknown event %q is not contained in given ABI events:\n%s", eventStr, availableABIEventsStr)
+ }
+ expEvents = append(expEvents, event)
+ }
+ return expEvents, nil
+}
diff --git a/precompiles/testutil/fund.go b/precompiles/testutil/fund.go
new file mode 100644
index 00000000..590025ce
--- /dev/null
+++ b/precompiles/testutil/fund.go
@@ -0,0 +1,42 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testutil
+
+import (
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
+ "github.com/evmos/os/utils"
+ inflationtypes "github.com/evmos/os/x/inflation/v1/types"
+)
+
+// FundAccount is a utility function that funds an account by minting and
+// sending the coins to the address.
+func FundAccount(ctx sdk.Context, bankKeeper bankkeeper.Keeper, addr sdk.AccAddress, amounts sdk.Coins) error {
+ // TODO: remove outdated Evmos namespaces (inflationtypes)
+ if err := bankKeeper.MintCoins(ctx, inflationtypes.ModuleName, amounts); err != nil {
+ return err
+ }
+
+ return bankKeeper.SendCoinsFromModuleToAccount(ctx, inflationtypes.ModuleName, addr, amounts)
+}
+
+// FundAccountWithBaseDenom is a utility function that uses the FundAccount function
+// to fund an account with the default Evmos denomination.
+func FundAccountWithBaseDenom(ctx sdk.Context, bankKeeper bankkeeper.Keeper, addr sdk.AccAddress, amount int64) error {
+ coins := sdk.NewCoins(
+ sdk.NewCoin(utils.BaseDenom, math.NewInt(amount)),
+ )
+ return FundAccount(ctx, bankKeeper, addr, coins)
+}
+
+// FundModuleAccount is a utility function that funds a module account by
+// minting and sending the coins to the address.
+func FundModuleAccount(ctx sdk.Context, bankKeeper bankkeeper.Keeper, recipientMod string, amounts sdk.Coins) error {
+ if err := bankKeeper.MintCoins(ctx, inflationtypes.ModuleName, amounts); err != nil {
+ return err
+ }
+
+ return bankKeeper.SendCoinsFromModuleToModule(ctx, inflationtypes.ModuleName, recipientMod, amounts)
+}
diff --git a/precompiles/testutil/integration.go b/precompiles/testutil/integration.go
new file mode 100644
index 00000000..6eb0b98c
--- /dev/null
+++ b/precompiles/testutil/integration.go
@@ -0,0 +1,81 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testutil
+
+import (
+ "strconv"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ abci "github.com/cometbft/cometbft/abci/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/evmos/os/crypto/ethsecp256k1"
+ example_app "github.com/evmos/os/example_chain"
+)
+
+// SubmitProposal delivers a submit proposal tx for a given gov content.
+// Depending on the content type, the eventNum needs to specify submit_proposal
+// event.
+func SubmitProposal(
+ ctx sdk.Context,
+ appEvmos *example_app.ExampleChain,
+ pk *ethsecp256k1.PrivKey,
+ content govv1beta1.Content,
+ eventNum int,
+) (id uint64, err error) {
+ accountAddress := sdk.AccAddress(pk.PubKey().Address().Bytes())
+ stakeDenom := stakingtypes.DefaultParams().BondDenom
+
+ deposit := sdk.NewCoins(sdk.NewCoin(stakeDenom, math.NewInt(100000000)))
+ msg, err := govv1beta1.NewMsgSubmitProposal(content, deposit, accountAddress)
+ if err != nil {
+ return id, err
+ }
+ res, err := DeliverTx(ctx, appEvmos, pk, nil, msg)
+ if err != nil {
+ return id, err
+ }
+
+ submitEvent := res.GetEvents()[eventNum]
+ if submitEvent.Type != "submit_proposal" || submitEvent.Attributes[0].Key != "proposal_id" {
+ return id, errorsmod.Wrapf(errorsmod.Error{}, "eventNumber %d in SubmitProposal calls %s instead of submit_proposal", eventNum, submitEvent.Type)
+ }
+
+ return strconv.ParseUint(submitEvent.Attributes[0].Value, 10, 64)
+}
+
+// Delegate delivers a delegate tx
+func Delegate(
+ ctx sdk.Context,
+ appEvmos *example_app.ExampleChain,
+ priv *ethsecp256k1.PrivKey,
+ delegateAmount sdk.Coin,
+ validator stakingtypes.Validator,
+) (abci.ResponseDeliverTx, error) {
+ accountAddress := sdk.AccAddress(priv.PubKey().Address().Bytes())
+
+ val, err := sdk.ValAddressFromBech32(validator.OperatorAddress)
+ if err != nil {
+ return abci.ResponseDeliverTx{}, err
+ }
+
+ delegateMsg := stakingtypes.NewMsgDelegate(accountAddress, val, delegateAmount)
+ return DeliverTx(ctx, appEvmos, priv, nil, delegateMsg)
+}
+
+// Vote delivers a vote tx with the VoteOption "yes"
+func Vote(
+ ctx sdk.Context,
+ appEvmos *example_app.ExampleChain,
+ priv *ethsecp256k1.PrivKey,
+ proposalID uint64,
+ voteOption govv1beta1.VoteOption,
+) (abci.ResponseDeliverTx, error) {
+ accountAddress := sdk.AccAddress(priv.PubKey().Address().Bytes())
+
+ voteMsg := govv1beta1.NewMsgVote(accountAddress, proposalID, voteOption)
+ return DeliverTx(ctx, appEvmos, priv, nil, voteMsg)
+}
diff --git a/precompiles/testutil/logs.go b/precompiles/testutil/logs.go
new file mode 100644
index 00000000..db280e38
--- /dev/null
+++ b/precompiles/testutil/logs.go
@@ -0,0 +1,120 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package testutil
+
+import (
+ "fmt"
+ "slices"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// CheckLogs checks the logs for the given events and whether the transaction was successful or not.
+func CheckLogs(logArgs LogCheckArgs) error {
+ if len(logArgs.ExpEvents) != 0 && len(logArgs.ABIEvents) == 0 {
+ return fmt.Errorf("no ABI events provided in log check arguments, but expected events are present")
+ }
+
+ expABIEvents, err := validateEvents(logArgs.ABIEvents, logArgs.ExpEvents)
+ if err != nil {
+ return err
+ }
+
+ ethRes, err := evmtypes.DecodeTxResponse(logArgs.Res.Data)
+ if err != nil {
+ return fmt.Errorf("error while decoding ethereum tx response: %v", err)
+ }
+
+ reason, failed := CheckEthereumTxFailed(ethRes)
+ if failed != !logArgs.ExpPass {
+ return fmt.Errorf(
+ "expected vm error found to be %t; got: %t (reason: %s)\nGas usage: %d/%d (~%d %%)",
+ !logArgs.ExpPass,
+ failed,
+ reason,
+ logArgs.Res.GasUsed,
+ logArgs.Res.GasWanted,
+ int64(float64(logArgs.Res.GasUsed)/float64(logArgs.Res.GasWanted)*100),
+ )
+ }
+
+ if err := CheckVMError(logArgs.Res, logArgs.ErrContains); err != nil {
+ return err
+ }
+
+ if len(ethRes.Logs) != len(logArgs.ExpEvents) {
+ return fmt.Errorf("expected %d events in Ethereum response; got: %d", len(logArgs.ExpEvents), len(ethRes.Logs))
+ }
+
+ // Check if expected events are present in Ethereum response
+ availableEventIDs := make([]string, 0, len(ethRes.Logs))
+ for _, log := range ethRes.Logs {
+ availableEventIDs = append(availableEventIDs, log.Topics[0])
+ }
+
+ expEventIDs := make([]string, 0, len(expABIEvents))
+ for _, event := range expABIEvents {
+ expEventIDs = append(expEventIDs, event.ID.String())
+ }
+
+ for _, eventID := range expEventIDs {
+ if !slices.Contains(availableEventIDs, eventID) {
+ return fmt.Errorf("expected event with ID %v not found in Ethereum response", eventID)
+ }
+ }
+
+ return nil
+}
+
+// LogCheckArgs is a struct that contains configuration for the log checking.
+type LogCheckArgs struct {
+ // ABIEvents is a map of available abi.Event corresponding to the corresponding event names,
+ // which are available in the contract ABI.
+ ABIEvents map[string]abi.Event
+ // ErrContains is the error message that is expected to be contained in the transaction response.
+ ErrContains string
+ // ExpEvents are the events which are expected to be emitted.
+ ExpEvents []string
+ // ExpPass is whether the transaction is expected to pass or not.
+ ExpPass bool
+ // Res is the response of the transaction.
+ //
+ // NOTE: This does not have to be set when using contracts.CallContractAndCheckLogs.
+ Res abci.ResponseDeliverTx
+}
+
+// WithABIEvents sets the ABIEvents field of LogCheckArgs.
+func (l LogCheckArgs) WithABIEvents(abiEvents map[string]abi.Event) LogCheckArgs {
+ l.ABIEvents = abiEvents
+ return l
+}
+
+// WithErrContains sets the ErrContains field of LogCheckArgs.
+// If any printArgs are provided, they are used to format the error message.
+func (l LogCheckArgs) WithErrContains(errContains string, printArgs ...interface{}) LogCheckArgs {
+ if len(printArgs) > 0 {
+ errContains = fmt.Sprintf(errContains, printArgs...)
+ }
+ l.ErrContains = errContains
+ return l
+}
+
+// WithExpEvents sets the ExpEvents field of LogCheckArgs.
+func (l LogCheckArgs) WithExpEvents(expEvents ...string) LogCheckArgs {
+ l.ExpEvents = expEvents
+ return l
+}
+
+// WithExpPass sets the ExpPass field of LogCheckArgs.
+func (l LogCheckArgs) WithExpPass(expPass bool) LogCheckArgs {
+ l.ExpPass = expPass
+ return l
+}
+
+// WithRes sets the Res field of LogCheckArgs.
+func (l LogCheckArgs) WithRes(res abci.ResponseDeliverTx) LogCheckArgs {
+ l.Res = res
+ return l
+}
diff --git a/precompiles/testutil/setup.go b/precompiles/testutil/setup.go
new file mode 100644
index 00000000..3e153978
--- /dev/null
+++ b/precompiles/testutil/setup.go
@@ -0,0 +1,48 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package testutil
+
+import (
+ "time"
+
+ "github.com/cometbft/cometbft/crypto/tmhash"
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ tmversion "github.com/cometbft/cometbft/proto/tendermint/version"
+ "github.com/cometbft/cometbft/version"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+// NewHeader creates a new Tendermint header for testing purposes.
+func NewHeader(
+ height int64,
+ blockTime time.Time,
+ chainID string,
+ proposer sdk.ConsAddress,
+ appHash,
+ validatorHash []byte,
+) tmproto.Header {
+ return tmproto.Header{
+ ChainID: chainID,
+ Height: height,
+ Time: blockTime,
+ ValidatorsHash: validatorHash,
+ AppHash: appHash,
+ ProposerAddress: proposer.Bytes(),
+ Version: tmversion.Consensus{
+ Block: version.BlockProtocol,
+ },
+ LastBlockId: tmproto.BlockID{
+ Hash: tmhash.Sum([]byte("block_id")),
+ PartSetHeader: tmproto.PartSetHeader{
+ Total: 11,
+ Hash: tmhash.Sum([]byte("partset_header")),
+ },
+ },
+ DataHash: tmhash.Sum([]byte("data")),
+ NextValidatorsHash: tmhash.Sum([]byte("next_validators")),
+ ConsensusHash: tmhash.Sum([]byte("consensus")),
+ LastResultsHash: tmhash.Sum([]byte("last_result")),
+ EvidenceHash: tmhash.Sum([]byte("evidence")),
+ }
+}
diff --git a/precompiles/testutil/staking.go b/precompiles/testutil/staking.go
new file mode 100644
index 00000000..ffc4f71b
--- /dev/null
+++ b/precompiles/testutil/staking.go
@@ -0,0 +1,34 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testutil
+
+import (
+ "testing"
+
+ "cosmossdk.io/math"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
+ teststaking "github.com/cosmos/cosmos-sdk/x/staking/testutil"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/stretchr/testify/require"
+)
+
+// CreateValidator creates a validator with the given amount of staked tokens in the bond denomination set
+// in the staking keeper.
+func CreateValidator(ctx sdk.Context, t *testing.T, pubKey cryptotypes.PubKey, sk stakingkeeper.Keeper, stakeAmt math.Int) {
+ zeroDec := math.LegacyZeroDec()
+ stakingParams := sk.GetParams(ctx)
+ stakingParams.BondDenom = sk.BondDenom(ctx)
+ stakingParams.MinCommissionRate = zeroDec
+ err := sk.SetParams(ctx, stakingParams)
+ require.NoError(t, err)
+
+ stakingHelper := teststaking.NewHelper(t, ctx, &sk)
+ stakingHelper.Commission = stakingtypes.NewCommissionRates(zeroDec, zeroDec, zeroDec)
+ stakingHelper.Denom = sk.BondDenom(ctx)
+
+ valAddr := sdk.ValAddress(pubKey.Address())
+ stakingHelper.CreateValidator(valAddr, pubKey, stakeAmt, true)
+}
diff --git a/precompiles/testutil/statedb.go b/precompiles/testutil/statedb.go
new file mode 100644
index 00000000..5ccdb687
--- /dev/null
+++ b/precompiles/testutil/statedb.go
@@ -0,0 +1,16 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testutil
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ anteinterfaces "github.com/evmos/os/ante/interfaces"
+ "github.com/evmos/os/x/evm/statedb"
+)
+
+// NewStateDB returns a new StateDB for testing purposes.
+func NewStateDB(ctx sdk.Context, evmKeeper anteinterfaces.EVMKeeper) *statedb.StateDB {
+ return statedb.New(ctx, evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())))
+}
diff --git a/precompiles/testutil/testing.go b/precompiles/testutil/testing.go
new file mode 100644
index 00000000..dc678d32
--- /dev/null
+++ b/precompiles/testutil/testing.go
@@ -0,0 +1,22 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package testutil
+
+import (
+ "math/big"
+ "testing"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/os/x/evm/core/vm"
+ "github.com/stretchr/testify/require"
+)
+
+// NewPrecompileContract creates a new precompile contract and sets the gas meter.
+func NewPrecompileContract(t *testing.T, ctx sdk.Context, caller common.Address, precompile vm.ContractRef, gas uint64) (*vm.Contract, sdk.Context) {
+ contract := vm.NewContract(vm.AccountRef(caller), precompile, big.NewInt(0), gas)
+ ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
+ initialGas := ctx.GasMeter().GasConsumed()
+ require.Equal(t, uint64(0), initialGas)
+ return contract, ctx
+}
diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go
index 86196e2e..8b238f0e 100644
--- a/rpc/backend/chain_info.go
+++ b/rpc/backend/chain_info.go
@@ -16,9 +16,9 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
rpctypes "github.com/evmos/os/rpc/types"
"github.com/evmos/os/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
"github.com/pkg/errors"
)
diff --git a/rpc/backend/chain_info_test.go b/rpc/backend/chain_info_test.go
index 0c05e61d..00cd02fd 100644
--- a/rpc/backend/chain_info_test.go
+++ b/rpc/backend/chain_info_test.go
@@ -16,10 +16,10 @@ import (
tmrpctypes "github.com/cometbft/cometbft/rpc/core/types"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
"github.com/evmos/os/rpc/backend/mocks"
rpc "github.com/evmos/os/rpc/types"
utiltx "github.com/evmos/os/testutil/tx"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
)
func (suite *BackendTestSuite) TestBaseFee() {
diff --git a/rpc/backend/feemarket_query_client_test.go b/rpc/backend/feemarket_query_client_test.go
index 00cbbf84..094fce99 100644
--- a/rpc/backend/feemarket_query_client_test.go
+++ b/rpc/backend/feemarket_query_client_test.go
@@ -2,9 +2,9 @@ package backend
import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
"github.com/evmos/os/rpc/backend/mocks"
rpc "github.com/evmos/os/rpc/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
)
var _ feemarkettypes.QueryClient = &mocks.FeeMarketQueryClient{}
diff --git a/rpc/backend/mocks/feemarket_query_client.go b/rpc/backend/mocks/feemarket_query_client.go
index 7920588d..78ba6b27 100644
--- a/rpc/backend/mocks/feemarket_query_client.go
+++ b/rpc/backend/mocks/feemarket_query_client.go
@@ -9,7 +9,7 @@ import (
mock "github.com/stretchr/testify/mock"
- types "github.com/evmos/evmos/v19/x/feemarket/types"
+ types "github.com/evmos/os/x/feemarket/types"
)
// FeeMarketQueryClient is an autogenerated mock type for the QueryClient type
diff --git a/rpc/types/query_client.go b/rpc/types/query_client.go
index 910028cd..91ab9a56 100644
--- a/rpc/types/query_client.go
+++ b/rpc/types/query_client.go
@@ -13,7 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
)
// QueryClient defines a gRPC Client used for:
diff --git a/rpc/types/utils.go b/rpc/types/utils.go
index 6577636c..b749d0be 100644
--- a/rpc/types/utils.go
+++ b/rpc/types/utils.go
@@ -17,7 +17,7 @@ import (
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
evmtypes "github.com/evmos/evmos/v19/x/evm/types"
- feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
diff --git a/testutil/integration/common/factory/factory.go b/testutil/integration/common/factory/factory.go
new file mode 100644
index 00000000..ba51902a
--- /dev/null
+++ b/testutil/integration/common/factory/factory.go
@@ -0,0 +1,74 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package factory
+
+import (
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ testutiltypes "github.com/cosmos/cosmos-sdk/types/module/testutil"
+ "github.com/cosmos/cosmos-sdk/x/auth/signing"
+ "github.com/evmos/os/testutil/integration/os/grpc"
+ "github.com/evmos/os/testutil/integration/os/network"
+
+ errorsmod "cosmossdk.io/errors"
+)
+
+const (
+ GasAdjustment = float64(1.7)
+)
+
+// TxFactory is the interface that wraps the common methods to build and broadcast transactions
+// within cosmos chains
+type TxFactory interface {
+ // BuildCosmosTx builds a Cosmos tx with the provided private key and txArgs
+ BuildCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (signing.Tx, error)
+ // ExecuteCosmosTx builds, signs and broadcasts a Cosmos tx with the provided private key and txArgs
+ ExecuteCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (abcitypes.ResponseDeliverTx, error)
+}
+
+var _ TxFactory = (*IntegrationTxFactory)(nil)
+
+// IntegrationTxFactory is a helper struct to build and broadcast transactions
+// to the network on integration tests. This is to simulate the behavior of a real user.
+type IntegrationTxFactory struct {
+ grpcHandler grpc.Handler
+ network network.Network
+ ec *testutiltypes.TestEncodingConfig
+}
+
+// New creates a new IntegrationTxFactory instance
+func New(
+ network network.Network,
+ grpcHandler grpc.Handler,
+ ec *testutiltypes.TestEncodingConfig,
+) *IntegrationTxFactory {
+ return &IntegrationTxFactory{
+ grpcHandler: grpcHandler,
+ network: network,
+ ec: ec,
+ }
+}
+
+func (tf *IntegrationTxFactory) BuildCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (signing.Tx, error) {
+ txBuilder, err := tf.buildTx(privKey, txArgs)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to build tx")
+ }
+ return txBuilder.GetTx(), nil
+}
+
+// ExecuteCosmosTx creates, signs and broadcasts a Cosmos transaction
+func (tf *IntegrationTxFactory) ExecuteCosmosTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (abcitypes.ResponseDeliverTx, error) {
+ signedTx, err := tf.BuildCosmosTx(privKey, txArgs)
+ if err != nil {
+ return abcitypes.ResponseDeliverTx{}, errorsmod.Wrap(err, "failed to generate tx")
+ }
+
+ txBytes, err := tf.encodeTx(signedTx)
+ if err != nil {
+ return abcitypes.ResponseDeliverTx{}, errorsmod.Wrap(err, "failed to encode tx")
+ }
+
+ return tf.network.BroadcastTxSync(txBytes)
+}
diff --git a/testutil/integration/common/factory/helper.go b/testutil/integration/common/factory/helper.go
new file mode 100644
index 00000000..80b5d0f0
--- /dev/null
+++ b/testutil/integration/common/factory/helper.go
@@ -0,0 +1,146 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package factory
+
+import (
+ "math/big"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ cosmostx "github.com/cosmos/cosmos-sdk/client/tx"
+
+ sdkmath "cosmossdk.io/math"
+
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/types/tx/signing"
+ xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
+
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+
+ errorsmod "cosmossdk.io/errors"
+)
+
+// buildTx builds a tx with the provided private key and txArgs
+func (tf *IntegrationTxFactory) buildTx(privKey cryptotypes.PrivKey, txArgs CosmosTxArgs) (client.TxBuilder, error) {
+ txConfig := tf.ec.TxConfig
+ txBuilder := txConfig.NewTxBuilder()
+
+ if err := txBuilder.SetMsgs(txArgs.Msgs...); err != nil {
+ return nil, errorsmod.Wrap(err, "failed to set tx msgs")
+ }
+
+ if txArgs.FeeGranter != nil {
+ txBuilder.SetFeeGranter(txArgs.FeeGranter)
+ }
+
+ senderAddress := sdktypes.AccAddress(privKey.PubKey().Address().Bytes())
+ account, err := tf.grpcHandler.GetAccount(senderAddress.String())
+ if err != nil {
+ return nil, errorsmod.Wrapf(err, "failed to get account: %s", senderAddress.String())
+ }
+
+ sequence := account.GetSequence()
+ signMode := txConfig.SignModeHandler().DefaultMode()
+ signerData := xauthsigning.SignerData{
+ ChainID: tf.network.GetChainID(),
+ AccountNumber: account.GetAccountNumber(),
+ Sequence: sequence,
+ Address: senderAddress.String(),
+ }
+
+ // sign tx
+ sigsV2 := signing.SignatureV2{
+ PubKey: privKey.PubKey(),
+ Data: &signing.SingleSignatureData{
+ SignMode: signMode,
+ Signature: nil,
+ },
+ Sequence: sequence,
+ }
+
+ err = txBuilder.SetSignatures(sigsV2)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to set tx signatures")
+ }
+
+ if txArgs.FeeGranter != nil {
+ txBuilder.SetFeeGranter(txArgs.FeeGranter)
+ }
+
+ txBuilder.SetFeePayer(senderAddress)
+
+ gasLimit, err := tf.estimateGas(txArgs, txBuilder)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to estimate gas")
+ }
+ txBuilder.SetGasLimit(gasLimit)
+
+ fees, err := tf.calculateFees(txArgs.GasPrice, gasLimit)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to calculate fees")
+ }
+ txBuilder.SetFeeAmount(fees)
+
+ signature, err := cosmostx.SignWithPrivKey(signMode, signerData, txBuilder, privKey, txConfig, sequence)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to sign tx")
+ }
+
+ err = txBuilder.SetSignatures(signature)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to set tx signatures")
+ }
+
+ return txBuilder, nil
+}
+
+// calculateFees calculates the fees for the transaction.
+func (tf *IntegrationTxFactory) calculateFees(gasPrice *sdkmath.Int, gasLimit uint64) (sdktypes.Coins, error) {
+ denom := tf.network.GetDenom()
+ var fees sdktypes.Coins
+ if gasPrice != nil {
+ fees = sdktypes.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(gasLimit))}}
+ } else {
+ baseFee, err := tf.grpcHandler.GetBaseFee()
+ if err != nil {
+ return sdktypes.Coins{}, errorsmod.Wrap(err, "failed to get base fee")
+ }
+ price := baseFee.BaseFee
+ fees = sdktypes.Coins{{Denom: denom, Amount: price.MulRaw(int64(gasLimit))}}
+ }
+ return fees, nil
+}
+
+// estimateGas estimates the gas needed for the transaction.
+func (tf *IntegrationTxFactory) estimateGas(txArgs CosmosTxArgs, txBuilder client.TxBuilder) (uint64, error) {
+ txConfig := tf.ec.TxConfig
+ simulateBytes, err := txConfig.TxEncoder()(txBuilder.GetTx())
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to encode tx")
+ }
+
+ var gasLimit uint64
+ if txArgs.Gas == 0 {
+ simulateRes, err := tf.network.Simulate(simulateBytes)
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to simulate tx")
+ }
+
+ gasAdj := new(big.Float).SetFloat64(GasAdjustment)
+ gasUsed := new(big.Float).SetUint64(simulateRes.GasInfo.GasUsed)
+ gasLimit, _ = gasAdj.Mul(gasAdj, gasUsed).Uint64()
+ } else {
+ gasLimit = txArgs.Gas
+ }
+ return gasLimit, nil
+}
+
+// encodeTx encodes the tx using the txConfig's encoder.
+func (tf *IntegrationTxFactory) encodeTx(tx sdktypes.Tx) ([]byte, error) {
+ txConfig := tf.ec.TxConfig
+ txBytes, err := txConfig.TxEncoder()(tx)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to encode tx")
+ }
+ return txBytes, nil
+}
diff --git a/testutil/integration/common/factory/types.go b/testutil/integration/common/factory/types.go
new file mode 100644
index 00000000..ca13426c
--- /dev/null
+++ b/testutil/integration/common/factory/types.go
@@ -0,0 +1,24 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package factory
+
+import (
+ sdkmath "cosmossdk.io/math"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+)
+
+// CosmosTxArgs contains the params to create a cosmos tx
+type CosmosTxArgs struct {
+ // ChainID is the chain's id in cosmos format, e.g. 'evmos_9000-1'
+ ChainID string
+ // Gas to be used on the tx
+ Gas uint64
+ // GasPrice to use on tx
+ GasPrice *sdkmath.Int
+ // Fees is the fee to be used on the tx (amount and denom)
+ Fees sdktypes.Coins
+ // FeeGranter is the account address of the fee granter
+ FeeGranter sdktypes.AccAddress
+ // Msgs slice of messages to include on the tx
+ Msgs []sdktypes.Msg
+}
diff --git a/testutil/integration/common/grpc/account.go b/testutil/integration/common/grpc/account.go
new file mode 100644
index 00000000..107c293a
--- /dev/null
+++ b/testutil/integration/common/grpc/account.go
@@ -0,0 +1,29 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package grpc
+
+import (
+ "context"
+
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+)
+
+// GetAccount returns the account for the given address.
+func (gqh *IntegrationHandler) GetAccount(address string) (authtypes.AccountI, error) {
+ authClient := gqh.network.GetAuthClient()
+ res, err := authClient.Account(context.Background(), &authtypes.QueryAccountRequest{
+ Address: address,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ encodingCgf := encoding.MakeConfig(example_app.ModuleBasics)
+ var acc authtypes.AccountI
+ if err = encodingCgf.InterfaceRegistry.UnpackAny(res.Account, &acc); err != nil {
+ return nil, err
+ }
+ return acc, nil
+}
diff --git a/testutil/integration/common/grpc/authz.go b/testutil/integration/common/grpc/authz.go
new file mode 100644
index 00000000..156e943f
--- /dev/null
+++ b/testutil/integration/common/grpc/authz.go
@@ -0,0 +1,119 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package grpc
+
+import (
+ "context"
+
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+)
+
+// GetGrants returns the grants for the given grantee and granter combination.
+//
+// NOTE: To extract the concrete authorizations, use the GetAuthorizations method.
+func (gqh *IntegrationHandler) GetGrants(grantee, granter string) ([]*authz.Grant, error) {
+ authzClient := gqh.network.GetAuthzClient()
+ res, err := authzClient.Grants(context.Background(), &authz.QueryGrantsRequest{
+ Grantee: grantee,
+ Granter: granter,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Grants, nil
+}
+
+// GetGrantsByGrantee returns the grants for the given grantee.
+//
+// NOTE: To extract the concrete authorizations, use the GetAuthorizationsByGrantee method.
+func (gqh *IntegrationHandler) GetGrantsByGrantee(grantee string) ([]*authz.GrantAuthorization, error) {
+ authzClient := gqh.network.GetAuthzClient()
+ res, err := authzClient.GranteeGrants(context.Background(), &authz.QueryGranteeGrantsRequest{
+ Grantee: grantee,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Grants, nil
+}
+
+// GetGrantsByGranter returns the grants for the given granter.
+//
+// NOTE: To extract the concrete authorizations, use the GetAuthorizationsByGranter method.
+func (gqh *IntegrationHandler) GetGrantsByGranter(granter string) ([]*authz.GrantAuthorization, error) {
+ authzClient := gqh.network.GetAuthzClient()
+ res, err := authzClient.GranterGrants(context.Background(), &authz.QueryGranterGrantsRequest{
+ Granter: granter,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Grants, nil
+}
+
+// GetAuthorizations returns the concrete authorizations for the given grantee and granter combination.
+func (gqh *IntegrationHandler) GetAuthorizations(grantee, granter string) ([]authz.Authorization, error) {
+ encodingCfg := encoding.MakeConfig(example_app.ModuleBasics)
+
+ grants, err := gqh.GetGrants(grantee, granter)
+ if err != nil {
+ return nil, err
+ }
+
+ auths := make([]authz.Authorization, 0, len(grants))
+ for _, grant := range grants {
+ var auth authz.Authorization
+ err := encodingCfg.InterfaceRegistry.UnpackAny(grant.Authorization, &auth)
+ if err != nil {
+ return nil, err
+ }
+
+ auths = append(auths, auth)
+ }
+
+ return auths, nil
+}
+
+// GetAuthorizationsByGrantee returns the concrete authorizations for the given grantee.
+func (gqh *IntegrationHandler) GetAuthorizationsByGrantee(grantee string) ([]authz.Authorization, error) {
+ grants, err := gqh.GetGrantsByGrantee(grantee)
+ if err != nil {
+ return nil, err
+ }
+
+ return unpackGrantAuthzs(grants)
+}
+
+// GetAuthorizationsByGranter returns the concrete authorizations for the given granter.
+func (gqh *IntegrationHandler) GetAuthorizationsByGranter(granter string) ([]authz.Authorization, error) {
+ grants, err := gqh.GetGrantsByGranter(granter)
+ if err != nil {
+ return nil, err
+ }
+
+ return unpackGrantAuthzs(grants)
+}
+
+// unpackGrantAuthzs unpacks the given grant authorization.
+func unpackGrantAuthzs(grantAuthzs []*authz.GrantAuthorization) ([]authz.Authorization, error) {
+ encodingCfg := encoding.MakeConfig(example_app.ModuleBasics)
+
+ auths := make([]authz.Authorization, 0, len(grantAuthzs))
+ for _, grantAuthz := range grantAuthzs {
+ var auth authz.Authorization
+ err := encodingCfg.InterfaceRegistry.UnpackAny(grantAuthz.Authorization, &auth)
+ if err != nil {
+ return nil, err
+ }
+
+ auths = append(auths, auth)
+ }
+
+ return auths, nil
+}
diff --git a/testutil/integration/common/grpc/bank.go b/testutil/integration/common/grpc/bank.go
new file mode 100644
index 00000000..cc988f85
--- /dev/null
+++ b/testutil/integration/common/grpc/bank.go
@@ -0,0 +1,28 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package grpc
+
+import (
+ "context"
+
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+)
+
+// GetBalance returns the balance for the given address and denom.
+func (gqh *IntegrationHandler) GetBalance(address sdktypes.AccAddress, denom string) (*banktypes.QueryBalanceResponse, error) {
+ bankClient := gqh.network.GetBankClient()
+ return bankClient.Balance(context.Background(), &banktypes.QueryBalanceRequest{
+ Address: address.String(),
+ Denom: denom,
+ })
+}
+
+// GetAllBalances returns all the balances for the given address.
+func (gqh *IntegrationHandler) GetAllBalances(address sdktypes.AccAddress) (*banktypes.QueryAllBalancesResponse, error) {
+ bankClient := gqh.network.GetBankClient()
+ return bankClient.AllBalances(context.Background(), &banktypes.QueryAllBalancesRequest{
+ Address: address.String(),
+ })
+}
diff --git a/testutil/integration/common/grpc/grpc.go b/testutil/integration/common/grpc/grpc.go
new file mode 100644
index 00000000..f2a5eaac
--- /dev/null
+++ b/testutil/integration/common/grpc/grpc.go
@@ -0,0 +1,52 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package grpc
+
+import (
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/evmos/os/testutil/integration/common/network"
+)
+
+// Handler is an interface that defines the common methods that are used to query
+// the network's modules via gRPC.
+type Handler interface {
+ // Account methods
+ GetAccount(address string) (authtypes.AccountI, error)
+
+ // Authz methods
+ GetAuthorizations(grantee, granter string) ([]authz.Authorization, error)
+ GetAuthorizationsByGrantee(grantee string) ([]authz.Authorization, error)
+ GetAuthorizationsByGranter(granter string) ([]authz.Authorization, error)
+ GetGrants(grantee, granter string) ([]*authz.Grant, error)
+ GetGrantsByGrantee(grantee string) ([]*authz.GrantAuthorization, error)
+ GetGrantsByGranter(granter string) ([]*authz.GrantAuthorization, error)
+
+ // Bank methods
+ GetBalance(address sdktypes.AccAddress, denom string) (*banktypes.QueryBalanceResponse, error)
+ GetAllBalances(address sdktypes.AccAddress) (*banktypes.QueryAllBalancesResponse, error)
+
+ // Staking methods
+ GetDelegation(delegatorAddress string, validatorAddress string) (*stakingtypes.QueryDelegationResponse, error)
+ GetBondedValidators() (*stakingtypes.QueryValidatorsResponse, error)
+}
+
+var _ Handler = (*IntegrationHandler)(nil)
+
+// IntegrationHandler is a helper struct to query the network's modules
+// via gRPC. This is to simulate the behavior of a real user and avoid querying
+// the modules directly.
+type IntegrationHandler struct {
+ network network.Network
+}
+
+// NewIntegrationHandler creates a new IntegrationHandler instance.
+func NewIntegrationHandler(network network.Network) *IntegrationHandler {
+ return &IntegrationHandler{
+ network: network,
+ }
+}
diff --git a/testutil/integration/common/grpc/staking.go b/testutil/integration/common/grpc/staking.go
new file mode 100644
index 00000000..003e22bd
--- /dev/null
+++ b/testutil/integration/common/grpc/staking.go
@@ -0,0 +1,26 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package grpc
+
+import (
+ "context"
+
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+)
+
+// GetBalance returns the balance for the given address.
+func (gqh *IntegrationHandler) GetDelegation(delegatorAddress string, validatorAddress string) (*stakingtypes.QueryDelegationResponse, error) {
+ stakingClient := gqh.network.GetStakingClient()
+ return stakingClient.Delegation(context.Background(), &stakingtypes.QueryDelegationRequest{
+ DelegatorAddr: delegatorAddress,
+ ValidatorAddr: validatorAddress,
+ })
+}
+
+// GetValidators returns the list of all bonded validators.
+func (gqh *IntegrationHandler) GetBondedValidators() (*stakingtypes.QueryValidatorsResponse, error) {
+ stakingClient := gqh.network.GetStakingClient()
+ return stakingClient.Validators(context.Background(), &stakingtypes.QueryValidatorsRequest{
+ Status: stakingtypes.BondStatusBonded,
+ })
+}
diff --git a/testutil/integration/common/network/network.go b/testutil/integration/common/network/network.go
new file mode 100644
index 00000000..52c77ba1
--- /dev/null
+++ b/testutil/integration/common/network/network.go
@@ -0,0 +1,46 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network
+
+import (
+ "testing"
+ "time"
+
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ txtypes "github.com/cosmos/cosmos-sdk/types/tx"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+)
+
+// Network is the interface that wraps the common methods to interact with integration test network.
+//
+// It was designed to avoid users to access module's keepers directly and force integration tests
+// to be closer to the real user's behavior.
+type Network interface {
+ GetContext() sdktypes.Context
+ GetChainID() string
+ GetDenom() string
+ GetValidators() []stakingtypes.Validator
+
+ NextBlock() error
+ NextBlockAfter(duration time.Duration) error
+
+ // Clients
+ GetAuthClient() authtypes.QueryClient
+ GetAuthzClient() authz.QueryClient
+ GetBankClient() banktypes.QueryClient
+ GetStakingClient() stakingtypes.QueryClient
+
+ BroadcastTxSync(txBytes []byte) (abcitypes.ResponseDeliverTx, error)
+ Simulate(txBytes []byte) (*txtypes.SimulateResponse, error)
+
+ // GetIBCChain returns the IBC test chain.
+ // NOTE: this is only used for testing IBC related functionality.
+ // The idea is to deprecate this eventually.
+ GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain
+}
diff --git a/testutil/integration/ibc/chain/chain.go b/testutil/integration/ibc/chain/chain.go
new file mode 100644
index 00000000..7f750877
--- /dev/null
+++ b/testutil/integration/ibc/chain/chain.go
@@ -0,0 +1,80 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package chain
+
+import (
+ "time"
+
+ tmtypes "github.com/cometbft/cometbft/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types"
+ "github.com/cosmos/ibc-go/v7/modules/core/exported"
+ ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ "github.com/cosmos/ibc-go/v7/testing/simapp"
+)
+
+// Chain defines the required methods needed for a testing IBC chain that complies
+// with the ibctesting chain struct.
+type Chain interface {
+ // GetContext returns the current context for the application.
+ GetContext() sdktypes.Context
+ // GetSimApp returns the SimApp to allow usage of non-interface fields.
+ GetSimApp() *simapp.SimApp
+ // QueryProof performs an abci query with the given key and returns the proto encoded merkle proof
+ // for the query and the height at which the proof will succeed on a tendermint verifier.
+ QueryProof(key []byte) ([]byte, clienttypes.Height)
+ // QueryProofAtHeight performs an abci query with the given key and returns the proto encoded merkle proof
+ // for the query and the height at which the proof will succeed on a tendermint verifier. Only the IBC
+ // store is supported
+ QueryProofAtHeight(key []byte, height int64) ([]byte, clienttypes.Height)
+ // QueryProofForStore performs an abci query with the given key and returns the proto encoded merkle proof
+ // for the query and the height at which the proof will succeed on a tendermint verifier.
+ QueryProofForStore(storeKey string, key []byte, height int64) ([]byte, clienttypes.Height)
+ // QueryUpgradeProof performs an abci query with the given key and returns the proto encoded merkle proof
+ // for the query and the height at which the proof will succeed on a tendermint verifier.
+ QueryUpgradeProof(key []byte, height uint64) ([]byte, clienttypes.Height)
+ // QueryConsensusStateProof performs an abci query for a consensus state
+ // stored on the given clientID. The proof and consensusHeight are returned.
+ QueryConsensusStateProof(clientID string) ([]byte, clienttypes.Height)
+ // NextBlock sets the last header to the current header and increments the current header to be
+ // at the next block height. It does not update the time as that is handled by the Coordinator.
+ // It will call Endblock and Commit and apply the validator set changes to the next validators
+ // of the next block being created. This follows the Tendermint protocol of applying valset changes
+ // returned on block `n` to the validators of block `n+2`.
+ // It calls BeginBlock with the new block created before returning.
+ NextBlock()
+ // GetClientState retrieves the client state for the provided clientID. The client is
+ // expected to exist otherwise testing will fail.
+ GetClientState(clientID string) exported.ClientState
+ // GetConsensusState retrieves the consensus state for the provided clientID and height.
+ // It will return a success boolean depending on if consensus state exists or not.
+ GetConsensusState(clientID string, height exported.Height) (exported.ConsensusState, bool)
+ // GetValsAtHeight will return the trusted validator set of the chain for the given trusted height. It will return
+ // a success boolean depending on if the validator set exists or not at that height.
+ GetValsAtHeight(trustedHeight int64) (*tmtypes.ValidatorSet, bool)
+ // GetAcknowledgement retrieves an acknowledgement for the provided packet. If the
+ // acknowledgement does not exist then testing will fail.
+ GetAcknowledgement(packet exported.PacketI) []byte
+ // GetPrefix returns the prefix for used by a chain in connection creation
+ GetPrefix() commitmenttypes.MerklePrefix
+ // ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the
+ // light client on the source chain.
+ ConstructUpdateTMClientHeader(counterparty *ibctesting.TestChain, clientID string) (*ibctm.Header, error)
+ // ConstructUpdateTMClientHeaderWithTrustedHeight will construct a valid 07-tendermint Header to update the
+ ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty *ibctesting.TestChain, clientID string, trustedHeight clienttypes.Height) (*ibctm.Header, error) // light client on the source chain.
+ // ExpireClient fast forwards the chain's block time by the provided amount of time which will
+ // expire any clients with a trusting period less than or equal to this amount of time.
+ ExpireClient(amount time.Duration)
+ // CurrentTMClientHeader creates a TM header using the current header parameters
+ // on the chain. The trusted fields in the header are set to nil.
+ CurrentTMClientHeader() *ibctm.Header
+ // GetChannelCapability returns the channel capability for the given portID and channelID.
+ // The capability must exist, otherwise testing will fail.
+ GetChannelCapability(portID, channelID string) *capabilitytypes.Capability
+ // GetTimeoutHeight is a convenience function which returns a IBC packet timeout height
+ // to be used for testing. It returns the current IBC height + 100 blocks
+ GetTimeoutHeight() clienttypes.Height
+}
diff --git a/testutil/integration/ibc/coordinator/coordinator.go b/testutil/integration/ibc/coordinator/coordinator.go
new file mode 100644
index 00000000..227e7e1a
--- /dev/null
+++ b/testutil/integration/ibc/coordinator/coordinator.go
@@ -0,0 +1,154 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package coordinator
+
+import (
+ "testing"
+ "time"
+
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ evmosibc "github.com/evmos/os/ibc/testing"
+ "github.com/evmos/os/testutil/integration/common/network"
+ ibcchain "github.com/evmos/os/testutil/integration/ibc/chain"
+)
+
+// Coordinator is the interface that defines the methods that are used to
+// coordinate the execution of the IBC relayer.
+type Coordinator interface {
+ // IncrementTime iterates through all the TestChain's and increments their current header time
+ // by 5 seconds.
+ IncrementTime()
+ // UpdateTime updates all clocks for the TestChains to the current global time.
+ UpdateTime()
+ // UpdateTimeForChain updates the clock for a specific chain.
+ UpdateTimeForChain(chainID string)
+ // GetChain returns the TestChain for a given chainID.
+ GetChain(chainID string) ibcchain.Chain
+ // GetDummyChainsIDs returns the chainIDs for all dummy chains.
+ GetDummyChainsIDs() []string
+ // SetDefaultSignerForChain sets the default signer for the chain with the given chainID.
+ SetDefaultSignerForChain(chainID string, priv cryptotypes.PrivKey, acc authtypes.AccountI)
+ // Setup constructs a TM client, connection, and channel on both chains provided. It will
+ // fail if any error occurs. The clientID's, TestConnections, and TestChannels are returned
+ // for both chains. The channels created are connected to the ibc-transfer application.
+ Setup(src, dst string) IBCConnection
+ // CommitNBlocks commits n blocks on the chain with the given chainID.
+ CommitNBlocks(chainID string, n uint64) error
+ // CommitAll commits 1 blocks on all chains within the coordinator.
+ CommitAll() error
+}
+
+var AmountOfDummyChains = 2
+
+var _ Coordinator = (*IntegrationCoordinator)(nil)
+
+// IntegrationCoordinator is a testing struct which contains N TestChain's. It handles keeping all chains
+// in sync with regards to time.
+// NOTE: When using the coordinator, it is important to commit blocks through the coordinator and not
+// through the network interface directly. This is because the coordinator does not keep the context in
+// sync with the network interface.
+type IntegrationCoordinator struct {
+ coord *ibctesting.Coordinator
+ dummyChainsIDs []string
+}
+
+// NewIntegrationCoordinator returns a new IntegrationCoordinator with N TestChain's.
+func NewIntegrationCoordinator(t *testing.T, preConfiguredChains []network.Network) *IntegrationCoordinator {
+ coord := &ibctesting.Coordinator{
+ T: t,
+ CurrentTime: time.Now(),
+ }
+ ibcChains := getIBCChains(t, coord, preConfiguredChains)
+ dummyChains, dummyChainsIDs := generateDummyChains(t, coord, AmountOfDummyChains)
+ totalChains := mergeMaps(ibcChains, dummyChains)
+ coord.Chains = totalChains
+ return &IntegrationCoordinator{
+ coord: coord,
+ dummyChainsIDs: dummyChainsIDs,
+ }
+}
+
+// GetChain returns the TestChain for a given chainID but abstracted to our internal chain interface.
+func (c *IntegrationCoordinator) GetChain(chainID string) ibcchain.Chain {
+ return c.coord.Chains[chainID]
+}
+
+// GetTestChain returns the TestChain for a given chainID.
+func (c *IntegrationCoordinator) GetTestChain(chainID string) *ibctesting.TestChain {
+ return c.coord.GetChain(chainID)
+}
+
+// GetDummyChainsIDs returns the chainIDs for all dummy chains.
+func (c *IntegrationCoordinator) GetDummyChainsIDs() []string {
+ return c.dummyChainsIDs
+}
+
+// IncrementTime iterates through all the TestChain's and increments their current header time
+// by 5 seconds.
+func (c *IntegrationCoordinator) IncrementTime() {
+ c.coord.IncrementTime()
+}
+
+// UpdateTime updates all clocks for the TestChains to the current global time.
+func (c *IntegrationCoordinator) UpdateTime() {
+ c.coord.UpdateTime()
+}
+
+// UpdateTimeForChain updates the clock for a specific chain.
+func (c *IntegrationCoordinator) UpdateTimeForChain(chainID string) {
+ chain := c.coord.GetChain(chainID)
+ c.coord.UpdateTimeForChain(chain)
+}
+
+// SetDefaultSignerForChain sets the default signer for the chain with the given chainID.
+func (c *IntegrationCoordinator) SetDefaultSignerForChain(chainID string, priv cryptotypes.PrivKey, acc authtypes.AccountI) {
+ chain := c.coord.GetChain(chainID)
+ chain.SenderPrivKey = priv
+ chain.SenderAccount = acc
+ chain.SenderAccounts = []ibctesting.SenderAccount{{SenderPrivKey: priv, SenderAccount: acc}}
+}
+
+// Setup constructs a TM client, connection, and channel on both chains provided. It will
+// fail if any error occurs. The clientID's, TestConnections, and TestChannels are returned
+// for both chains. The channels created are connected to the ibc-transfer application.
+func (c *IntegrationCoordinator) Setup(a, b string) IBCConnection {
+ chainA := c.coord.GetChain(a)
+ chainB := c.coord.GetChain(b)
+
+ path := evmosibc.NewTransferPath(chainA, chainB)
+ evmosibc.SetupPath(c.coord, path)
+
+ return IBCConnection{
+ EndpointA: Endpoint{
+ ChainID: a,
+ ClientID: path.EndpointA.ClientID,
+ ConnectionID: path.EndpointA.ConnectionID,
+ ChannelID: path.EndpointA.ChannelID,
+ PortID: path.EndpointA.ChannelConfig.PortID,
+ },
+ EndpointB: Endpoint{
+ ChainID: b,
+ ClientID: path.EndpointB.ClientID,
+ ConnectionID: path.EndpointB.ConnectionID,
+ ChannelID: path.EndpointB.ChannelID,
+ PortID: path.EndpointB.ChannelConfig.PortID,
+ },
+ }
+}
+
+// CommitNBlocks commits n blocks on the chain with the given chainID.
+func (c *IntegrationCoordinator) CommitNBlocks(chainID string, n uint64) error {
+ chain := c.coord.GetChain(chainID)
+ c.coord.CommitNBlocks(chain, n)
+ return nil
+}
+
+// CommitAll commits n blocks on the chain with the given chainID.
+func (c *IntegrationCoordinator) CommitAll() error {
+ for _, chain := range c.coord.Chains {
+ c.coord.CommitNBlocks(chain, 1)
+ }
+ return nil
+}
diff --git a/testutil/integration/ibc/coordinator/types.go b/testutil/integration/ibc/coordinator/types.go
new file mode 100644
index 00000000..dd54ad17
--- /dev/null
+++ b/testutil/integration/ibc/coordinator/types.go
@@ -0,0 +1,18 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package coordinator
+
+// Endpoint defines the identifiers for a chain's client, connection, and channel.
+type Endpoint struct {
+ ChainID string
+ ClientID string
+ ConnectionID string
+ ChannelID string
+ PortID string
+}
+
+// IBCConnection defines the connection between two chains.
+type IBCConnection struct {
+ EndpointA Endpoint
+ EndpointB Endpoint
+}
diff --git a/testutil/integration/ibc/coordinator/utils.go b/testutil/integration/ibc/coordinator/utils.go
new file mode 100644
index 00000000..8722be6d
--- /dev/null
+++ b/testutil/integration/ibc/coordinator/utils.go
@@ -0,0 +1,40 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package coordinator
+
+import (
+ "strconv"
+ "testing"
+
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+ "github.com/evmos/os/testutil/integration/common/network"
+)
+
+// getIBCChains returns a map of TestChain's for the given network interface.
+func getIBCChains(t *testing.T, coord *ibctesting.Coordinator, chains []network.Network) map[string]*ibctesting.TestChain {
+ ibcChains := make(map[string]*ibctesting.TestChain)
+ for _, chain := range chains {
+ ibcChains[chain.GetChainID()] = chain.GetIBCChain(t, coord)
+ }
+ return ibcChains
+}
+
+// generateDummyChains returns a map of dummy chains to complement IBC connections for integration tests.
+func generateDummyChains(t *testing.T, coord *ibctesting.Coordinator, numberOfChains int) (map[string]*ibctesting.TestChain, []string) {
+ ibcChains := make(map[string]*ibctesting.TestChain)
+ ids := make([]string, numberOfChains)
+ for i := 1; i <= numberOfChains; i++ {
+ chainID := "dummychain-" + strconv.Itoa(i)
+ ids[i-1] = chainID
+ ibcChains[chainID] = ibctesting.NewTestChain(t, coord, chainID)
+ }
+ return ibcChains, ids
+}
+
+// mergeMaps merges two maps of TestChain's.
+func mergeMaps(m1, m2 map[string]*ibctesting.TestChain) map[string]*ibctesting.TestChain {
+ for k, v := range m2 {
+ m1[k] = v
+ }
+ return m1
+}
diff --git a/testutil/integration/os/factory/broadcast.go b/testutil/integration/os/factory/broadcast.go
new file mode 100644
index 00000000..ea0f30be
--- /dev/null
+++ b/testutil/integration/os/factory/broadcast.go
@@ -0,0 +1,99 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package factory
+
+import (
+ errorsmod "cosmossdk.io/errors"
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/os/precompiles/testutil"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// ExecuteEthTx executes an Ethereum transaction - contract call with the provided private key and txArgs
+// It first builds a MsgEthereumTx and then broadcasts it to the network.
+func (tf *IntegrationTxFactory) ExecuteEthTx(
+ priv cryptotypes.PrivKey,
+ txArgs evmtypes.EvmTxArgs,
+) (abcitypes.ResponseDeliverTx, error) {
+ signedMsg, err := tf.GenerateSignedEthTx(priv, txArgs)
+ if err != nil {
+ return abcitypes.ResponseDeliverTx{}, errorsmod.Wrap(err, "failed to generate signed ethereum tx")
+ }
+
+ txBytes, err := tf.encodeTx(signedMsg)
+ if err != nil {
+ return abcitypes.ResponseDeliverTx{}, errorsmod.Wrap(err, "failed to encode ethereum tx")
+ }
+
+ res, err := tf.network.BroadcastTxSync(txBytes)
+ if err != nil {
+ return abcitypes.ResponseDeliverTx{}, errorsmod.Wrap(err, "failed to broadcast ethereum tx")
+ }
+
+ if err := tf.checkEthTxResponse(&res); err != nil {
+ return res, errorsmod.Wrap(err, "failed ETH tx")
+ }
+ return res, nil
+}
+
+// ExecuteContractCall executes a contract call with the provided private key.
+func (tf *IntegrationTxFactory) ExecuteContractCall(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs CallArgs) (abcitypes.ResponseDeliverTx, error) {
+ completeTxArgs, err := tf.GenerateContractCallArgs(txArgs, callArgs)
+ if err != nil {
+ return abcitypes.ResponseDeliverTx{}, errorsmod.Wrap(err, "failed to generate contract call args")
+ }
+
+ return tf.ExecuteEthTx(privKey, completeTxArgs)
+}
+
+// DeployContract deploys a contract with the provided private key,
+// compiled contract data and constructor arguments.
+// TxArgs Input and Nonce fields are overwritten.
+func (tf *IntegrationTxFactory) DeployContract(
+ priv cryptotypes.PrivKey,
+ txArgs evmtypes.EvmTxArgs,
+ deploymentData ContractDeploymentData,
+) (common.Address, error) {
+ // Get account's nonce to create contract hash
+ from := common.BytesToAddress(priv.PubKey().Address().Bytes())
+ completeTxArgs, err := tf.GenerateDeployContractArgs(from, txArgs, deploymentData)
+ if err != nil {
+ return common.Address{}, errorsmod.Wrap(err, "failed to generate contract call args")
+ }
+
+ res, err := tf.ExecuteEthTx(priv, completeTxArgs)
+ if err != nil || !res.IsOK() {
+ return common.Address{}, errorsmod.Wrap(err, "failed to execute eth tx")
+ }
+ return crypto.CreateAddress(from, completeTxArgs.Nonce), nil
+}
+
+// CallContractAndCheckLogs is a helper function to call a contract and check the logs using
+// the integration test utilities.
+//
+// It returns the Cosmos Tx response, the decoded Ethereum Tx response and an error. This error value
+// is nil, if the expected logs are found and the VM error is the expected one, should one be expected.
+func (tf *IntegrationTxFactory) CallContractAndCheckLogs(
+ priv cryptotypes.PrivKey,
+ txArgs evmtypes.EvmTxArgs,
+ callArgs CallArgs,
+ logCheckArgs testutil.LogCheckArgs,
+) (abcitypes.ResponseDeliverTx, *evmtypes.MsgEthereumTxResponse, error) {
+ res, err := tf.ExecuteContractCall(priv, txArgs, callArgs)
+ logCheckArgs.Res = res
+ if err != nil {
+ // NOTE: here we are still passing the response to the log check function,
+ // because we want to check the logs and expected error in case of a VM error.
+ return abcitypes.ResponseDeliverTx{}, nil, CheckError(err, logCheckArgs)
+ }
+
+ ethRes, err := evmtypes.DecodeTxResponse(res.Data)
+ if err != nil {
+ return abcitypes.ResponseDeliverTx{}, nil, err
+ }
+
+ return res, ethRes, testutil.CheckLogs(logCheckArgs)
+}
diff --git a/testutil/integration/os/factory/build.go b/testutil/integration/os/factory/build.go
new file mode 100644
index 00000000..25558e39
--- /dev/null
+++ b/testutil/integration/os/factory/build.go
@@ -0,0 +1,157 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package factory
+
+import (
+ "encoding/json"
+ "errors"
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/x/auth/signing"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core"
+ gethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/os/server/config"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func (tf *IntegrationTxFactory) GenerateDefaultTxTypeArgs(sender common.Address, txType int) (evmtypes.EvmTxArgs, error) {
+ defaultArgs := evmtypes.EvmTxArgs{}
+ switch txType {
+ case gethtypes.DynamicFeeTxType:
+ return tf.populateEvmTxArgsWithDefault(sender, defaultArgs)
+ case gethtypes.AccessListTxType:
+ defaultArgs.Accesses = &gethtypes.AccessList{{
+ Address: sender,
+ StorageKeys: []common.Hash{{0}},
+ }}
+ defaultArgs.GasPrice = big.NewInt(1e9)
+ return tf.populateEvmTxArgsWithDefault(sender, defaultArgs)
+ case gethtypes.LegacyTxType:
+ defaultArgs.GasPrice = big.NewInt(1e9)
+ return tf.populateEvmTxArgsWithDefault(sender, defaultArgs)
+ default:
+ return evmtypes.EvmTxArgs{}, errors.New("tx type not supported")
+ }
+}
+
+// EstimateGasLimit estimates the gas limit for a tx with the provided address and txArgs
+func (tf *IntegrationTxFactory) EstimateGasLimit(from *common.Address, txArgs *evmtypes.EvmTxArgs) (uint64, error) {
+ args, err := json.Marshal(evmtypes.TransactionArgs{
+ Data: (*hexutil.Bytes)(&txArgs.Input),
+ From: from,
+ To: txArgs.To,
+ AccessList: txArgs.Accesses,
+ })
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to marshal tx args")
+ }
+
+ res, err := tf.grpcHandler.EstimateGas(args, config.DefaultGasCap)
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to estimate gas")
+ }
+ gas := res.Gas
+ return gas, nil
+}
+
+// GenerateSignedEthTx generates an Ethereum tx with the provided private key and txArgs but does not broadcast it.
+func (tf *IntegrationTxFactory) GenerateSignedEthTx(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs) (signing.Tx, error) {
+ msgEthereumTx, err := tf.GenerateMsgEthereumTx(privKey, txArgs)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to create ethereum tx")
+ }
+
+ signedMsg, err := tf.SignMsgEthereumTx(privKey, msgEthereumTx)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to sign ethereum tx")
+ }
+
+ // Validate the transaction to avoid unrealistic behavior
+ if err = signedMsg.ValidateBasic(); err != nil {
+ return nil, errorsmod.Wrap(err, "failed to validate transaction")
+ }
+
+ return tf.buildSignedTx(signedMsg)
+}
+
+// GenerateMsgEthereumTx creates a new MsgEthereumTx with the provided arguments.
+// If any of the arguments are not provided, they will be populated with default values.
+func (tf *IntegrationTxFactory) GenerateMsgEthereumTx(
+ privKey cryptotypes.PrivKey,
+ txArgs evmtypes.EvmTxArgs,
+) (evmtypes.MsgEthereumTx, error) {
+ fromAddr := common.BytesToAddress(privKey.PubKey().Address().Bytes())
+ // Fill TxArgs with default values
+ txArgs, err := tf.populateEvmTxArgsWithDefault(fromAddr, txArgs)
+ if err != nil {
+ return evmtypes.MsgEthereumTx{}, errorsmod.Wrap(err, "failed to populate tx args")
+ }
+ msg := buildMsgEthereumTx(txArgs, fromAddr)
+
+ return msg, nil
+}
+
+// GenerateGethCoreMsg creates a new GethCoreMsg with the provided arguments.
+func (tf *IntegrationTxFactory) GenerateGethCoreMsg(
+ privKey cryptotypes.PrivKey,
+ txArgs evmtypes.EvmTxArgs,
+) (core.Message, error) {
+ msg, err := tf.GenerateMsgEthereumTx(privKey, txArgs)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to generate ethereum tx")
+ }
+
+ signedMsg, err := tf.SignMsgEthereumTx(privKey, msg)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to sign ethereum tx")
+ }
+
+ baseFeeResp, err := tf.grpcHandler.GetBaseFee()
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to get base fee")
+ }
+ signer := gethtypes.LatestSignerForChainID(
+ tf.network.GetEIP155ChainID(),
+ )
+ return signedMsg.AsMessage(signer, baseFeeResp.BaseFee.BigInt())
+}
+
+// GenerateContractCallArgs generates the txArgs for a contract call.
+func (tf *IntegrationTxFactory) GenerateContractCallArgs(
+ txArgs evmtypes.EvmTxArgs,
+ callArgs CallArgs,
+) (evmtypes.EvmTxArgs, error) {
+ input, err := callArgs.ContractABI.Pack(callArgs.MethodName, callArgs.Args...)
+ if err != nil {
+ return evmtypes.EvmTxArgs{}, errorsmod.Wrap(err, "failed to pack contract arguments")
+ }
+ txArgs.Input = input
+ return txArgs, nil
+}
+
+// GenerateDeployContractArgs generates the txArgs for a contract deployment.
+func (tf *IntegrationTxFactory) GenerateDeployContractArgs(
+ from common.Address,
+ txArgs evmtypes.EvmTxArgs,
+ deploymentData ContractDeploymentData,
+) (evmtypes.EvmTxArgs, error) {
+ account, err := tf.grpcHandler.GetEvmAccount(from)
+ if err != nil {
+ return evmtypes.EvmTxArgs{}, errorsmod.Wrapf(err, "failed to get evm account: %s", from.String())
+ }
+ txArgs.Nonce = account.GetNonce()
+
+ ctorArgs, err := deploymentData.Contract.ABI.Pack("", deploymentData.ConstructorArgs...)
+ if err != nil {
+ return evmtypes.EvmTxArgs{}, errorsmod.Wrap(err, "failed to pack constructor arguments")
+ }
+ data := deploymentData.Contract.Bin
+ data = append(data, ctorArgs...)
+
+ txArgs.Input = data
+ return txArgs, nil
+}
diff --git a/testutil/integration/os/factory/factory.go b/testutil/integration/os/factory/factory.go
new file mode 100644
index 00000000..1ba0b7f9
--- /dev/null
+++ b/testutil/integration/os/factory/factory.go
@@ -0,0 +1,192 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package factory
+
+import (
+ "fmt"
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ testutiltypes "github.com/cosmos/cosmos-sdk/types/module/testutil"
+ "github.com/cosmos/cosmos-sdk/x/auth/signing"
+ "github.com/cosmos/gogoproto/proto"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ example_app "github.com/evmos/os/example_chain"
+ "github.com/evmos/os/precompiles/testutil"
+ commonfactory "github.com/evmos/os/testutil/integration/common/factory"
+ "github.com/evmos/os/testutil/integration/os/grpc"
+ "github.com/evmos/os/testutil/integration/os/network"
+ "github.com/evmos/os/types"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// TxFactory defines a struct that can build and broadcast transactions for the Evmos
+// network.
+// Methods are organized by build sign and broadcast type methods.
+type TxFactory interface {
+ commonfactory.TxFactory
+
+ // GenerateDefaultTxTypeArgs generates a default ETH tx args for the desired tx type
+ GenerateDefaultTxTypeArgs(sender common.Address, txType int) (evmtypes.EvmTxArgs, error)
+ // GenerateSignedEthTx generates an Ethereum tx with the provided private key and txArgs but does not broadcast it.
+ GenerateSignedEthTx(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs) (signing.Tx, error)
+
+ // SignMsgEthereumTx signs a MsgEthereumTx with the provided private key.
+ SignMsgEthereumTx(privKey cryptotypes.PrivKey, msgEthereumTx evmtypes.MsgEthereumTx) (evmtypes.MsgEthereumTx, error)
+
+ // ExecuteEthTx builds, signs and broadcasts an Ethereum tx with the provided private key and txArgs.
+ // If the txArgs are not provided, they will be populated with default values or gas estimations.
+ ExecuteEthTx(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs) (abcitypes.ResponseDeliverTx, error)
+ // ExecuteContractCall executes a contract call with the provided private key
+ ExecuteContractCall(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs CallArgs) (abcitypes.ResponseDeliverTx, error)
+ // DeployContract deploys a contract with the provided private key,
+ // compiled contract data and constructor arguments
+ DeployContract(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, deploymentData ContractDeploymentData) (common.Address, error)
+ // CallContractAndCheckLogs is a helper function to call a contract and check the logs using
+ // the integration test utilities.
+ //
+ // It returns the Cosmos Tx response, the decoded Ethereum Tx response and an error. This error value
+ // is nil, if the expected logs are found and the VM error is the expected one, should one be expected.
+ CallContractAndCheckLogs(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs CallArgs, logCheckArgs testutil.LogCheckArgs) (abcitypes.ResponseDeliverTx, *evmtypes.MsgEthereumTxResponse, error)
+ // GenerateDeployContractArgs generates the txArgs for a contract deployment.
+ GenerateDeployContractArgs(from common.Address, txArgs evmtypes.EvmTxArgs, deploymentData ContractDeploymentData) (evmtypes.EvmTxArgs, error)
+ // GenerateContractCallArgs generates the txArgs for a contract call.
+ GenerateContractCallArgs(txArgs evmtypes.EvmTxArgs, callArgs CallArgs) (evmtypes.EvmTxArgs, error)
+ // GenerateMsgEthereumTx creates a new MsgEthereumTx with the provided arguments.
+ GenerateMsgEthereumTx(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs) (evmtypes.MsgEthereumTx, error)
+ // GenerateGethCoreMsg creates a new GethCoreMsg with the provided arguments.
+ GenerateGethCoreMsg(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs) (core.Message, error)
+ // EstimateGasLimit estimates the gas limit for a tx with the provided address and txArgs.
+ EstimateGasLimit(from *common.Address, txArgs *evmtypes.EvmTxArgs) (uint64, error)
+ // GetEvmTxResponseFromTxResult returns the MsgEthereumTxResponse from the provided txResult.
+ GetEvmTxResponseFromTxResult(txResult abcitypes.ResponseDeliverTx) (*evmtypes.MsgEthereumTxResponse, error)
+}
+
+var _ TxFactory = (*IntegrationTxFactory)(nil)
+
+// IntegrationTxFactory is a helper struct to build and broadcast transactions
+// to the network on integration tests. This is to simulate the behavior of a real user.
+type IntegrationTxFactory struct {
+ *commonfactory.IntegrationTxFactory
+ grpcHandler grpc.Handler
+ network network.Network
+ ec *testutiltypes.TestEncodingConfig
+}
+
+// New creates a new IntegrationTxFactory instance
+func New(
+ network network.Network,
+ grpcHandler grpc.Handler,
+) TxFactory {
+ ec := makeConfig(example_app.ModuleBasics)
+ return &IntegrationTxFactory{
+ IntegrationTxFactory: commonfactory.New(network, grpcHandler, &ec),
+ grpcHandler: grpcHandler,
+ network: network,
+ ec: &ec,
+ }
+}
+
+// GetEvmTxResponseFromTxResult returns the MsgEthereumTxResponse from the provided txResult.
+func (tf *IntegrationTxFactory) GetEvmTxResponseFromTxResult(
+ txResult abcitypes.ResponseDeliverTx,
+) (*evmtypes.MsgEthereumTxResponse, error) {
+ return evmtypes.DecodeTxResponse(txResult.Data)
+}
+
+// populateEvmTxArgsWithDefault populates the missing fields in the provided EvmTxArgs with default values.
+// If no GasLimit is present it will estimate the gas needed for the transaction.
+func (tf *IntegrationTxFactory) populateEvmTxArgsWithDefault(
+ fromAddr common.Address,
+ txArgs evmtypes.EvmTxArgs,
+) (evmtypes.EvmTxArgs, error) {
+ if txArgs.ChainID == nil {
+ ethChainID, err := types.ParseChainID(tf.network.GetChainID())
+ if err != nil {
+ return evmtypes.EvmTxArgs{}, errorsmod.Wrapf(err, "failed to parse chain id: %v", tf.network.GetChainID())
+ }
+ txArgs.ChainID = ethChainID
+ }
+
+ if txArgs.Nonce == 0 {
+ accountResp, err := tf.grpcHandler.GetEvmAccount(fromAddr)
+ if err != nil {
+ return evmtypes.EvmTxArgs{}, errorsmod.Wrapf(err, "failed to get evm account: %s", fromAddr.String())
+ }
+ txArgs.Nonce = accountResp.GetNonce()
+ }
+
+ // If there is no GasPrice it is assumed this is a DynamicFeeTx.
+ // If fields are empty they are populated with current dynamic values.
+ if txArgs.GasPrice == nil {
+ if txArgs.GasTipCap == nil {
+ txArgs.GasTipCap = big.NewInt(1)
+ }
+ if txArgs.GasFeeCap == nil {
+ baseFeeResp, err := tf.grpcHandler.GetBaseFee()
+ if err != nil {
+ return evmtypes.EvmTxArgs{}, errorsmod.Wrap(err, "failed to get base fee")
+ }
+ txArgs.GasFeeCap = baseFeeResp.BaseFee.BigInt()
+ }
+ }
+
+ // If the gas limit is not set, estimate it
+ // through the /simulate endpoint.
+ if txArgs.GasLimit == 0 {
+ gasLimit, err := tf.EstimateGasLimit(&fromAddr, &txArgs)
+ if err != nil {
+ return evmtypes.EvmTxArgs{}, errorsmod.Wrap(err, "failed to estimate gas limit")
+ }
+ txArgs.GasLimit = gasLimit
+ }
+
+ return txArgs, nil
+}
+
+func (tf *IntegrationTxFactory) encodeTx(tx sdktypes.Tx) ([]byte, error) {
+ txConfig := tf.ec.TxConfig
+ txBytes, err := txConfig.TxEncoder()(tx)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to encode tx")
+ }
+ return txBytes, nil
+}
+
+func (tf *IntegrationTxFactory) buildSignedTx(msg evmtypes.MsgEthereumTx) (signing.Tx, error) {
+ txConfig := tf.ec.TxConfig
+ txBuilder := txConfig.NewTxBuilder()
+ return msg.BuildTx(txBuilder, tf.network.GetDenom())
+}
+
+// checkEthTxResponse checks if the response is valid and returns the MsgEthereumTxResponse
+func (tf *IntegrationTxFactory) checkEthTxResponse(res *abcitypes.ResponseDeliverTx) error {
+ var txData sdktypes.TxMsgData
+ if !res.IsOK() {
+ return fmt.Errorf("tx failed with Code: %d, Logs: %s", res.Code, res.Log)
+ }
+
+ cdc := tf.ec.Codec
+ if err := cdc.Unmarshal(res.Data, &txData); err != nil {
+ return errorsmod.Wrap(err, "failed to unmarshal tx data")
+ }
+
+ if len(txData.MsgResponses) != 1 {
+ return fmt.Errorf("expected 1 message response, got %d", len(txData.MsgResponses))
+ }
+
+ var evmRes evmtypes.MsgEthereumTxResponse
+ if err := proto.Unmarshal(txData.MsgResponses[0].Value, &evmRes); err != nil {
+ return errorsmod.Wrap(err, "failed to unmarshal evm tx response")
+ }
+
+ if evmRes.Failed() {
+ return fmt.Errorf("tx failed with VmError: %v, Logs: %s", evmRes.VmError, res.GetLog())
+ }
+ return nil
+}
diff --git a/testutil/integration/os/factory/helpers.go b/testutil/integration/os/factory/helpers.go
new file mode 100644
index 00000000..5bcfe74c
--- /dev/null
+++ b/testutil/integration/os/factory/helpers.go
@@ -0,0 +1,65 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package factory
+
+import (
+ "strings"
+
+ "github.com/ethereum/go-ethereum/common"
+ evmtypes "github.com/evmos/os/x/evm/types"
+
+ errorsmod "cosmossdk.io/errors"
+ amino "github.com/cosmos/cosmos-sdk/codec"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ "github.com/cosmos/cosmos-sdk/types/module"
+ testutiltypes "github.com/cosmos/cosmos-sdk/types/module/testutil"
+ authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
+ enccodec "github.com/evmos/os/encoding/codec"
+ "github.com/evmos/os/precompiles/testutil"
+)
+
+// buildMsgEthereumTx builds an Ethereum transaction from the given arguments and populates the From field.
+func buildMsgEthereumTx(txArgs evmtypes.EvmTxArgs, fromAddr common.Address) evmtypes.MsgEthereumTx {
+ msgEthereumTx := evmtypes.NewTx(&txArgs)
+ msgEthereumTx.From = fromAddr.String()
+ return *msgEthereumTx
+}
+
+// makeConfig creates an EncodingConfig for testing
+func makeConfig(mb module.BasicManager) testutiltypes.TestEncodingConfig {
+ cdc := amino.NewLegacyAmino()
+ interfaceRegistry := codectypes.NewInterfaceRegistry()
+ codec := amino.NewProtoCodec(interfaceRegistry)
+
+ encodingConfig := testutiltypes.TestEncodingConfig{
+ InterfaceRegistry: interfaceRegistry,
+ Codec: codec,
+ TxConfig: authtx.NewTxConfig(codec, authtx.DefaultSignModes),
+ Amino: cdc,
+ }
+
+ enccodec.RegisterLegacyAminoCodec(encodingConfig.Amino)
+ mb.RegisterLegacyAminoCodec(encodingConfig.Amino)
+ enccodec.RegisterInterfaces(encodingConfig.InterfaceRegistry)
+ mb.RegisterInterfaces(encodingConfig.InterfaceRegistry)
+ return encodingConfig
+}
+
+// CheckError is a helper function to check if the error is the expected one.
+func CheckError(err error, logCheckArgs testutil.LogCheckArgs) error {
+ switch {
+ case logCheckArgs.ExpPass && err == nil:
+ return nil
+ case !logCheckArgs.ExpPass && err == nil:
+ return errorsmod.Wrap(err, "expected error but got none")
+ case logCheckArgs.ExpPass && err != nil:
+ return errorsmod.Wrap(err, "expected no error but got one")
+ case logCheckArgs.ErrContains == "":
+ // NOTE: if err contains is empty, we return the error as it is
+ return errorsmod.Wrap(err, "ErrContains needs to be filled")
+ case !strings.Contains(err.Error(), logCheckArgs.ErrContains):
+ return errorsmod.Wrapf(err, "expected different error; wanted %q", logCheckArgs.ErrContains)
+ }
+
+ return nil
+}
diff --git a/testutil/integration/os/factory/sign.go b/testutil/integration/os/factory/sign.go
new file mode 100644
index 00000000..45a27b96
--- /dev/null
+++ b/testutil/integration/os/factory/sign.go
@@ -0,0 +1,22 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package factory
+
+import (
+ errorsmod "cosmossdk.io/errors"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ gethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/os/testutil/tx"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// SignMsgEthereumTx signs a MsgEthereumTx with the provided private key and chainID.
+func (tf *IntegrationTxFactory) SignMsgEthereumTx(privKey cryptotypes.PrivKey, msgEthereumTx evmtypes.MsgEthereumTx) (evmtypes.MsgEthereumTx, error) {
+ ethChainID := tf.network.GetEIP155ChainID()
+ signer := gethtypes.LatestSignerForChainID(ethChainID)
+ err := msgEthereumTx.Sign(signer, tx.NewSigner(privKey))
+ if err != nil {
+ return evmtypes.MsgEthereumTx{}, errorsmod.Wrap(err, "failed to sign transaction")
+ }
+ return msgEthereumTx, nil
+}
diff --git a/testutil/integration/os/factory/types.go b/testutil/integration/os/factory/types.go
new file mode 100644
index 00000000..390781bf
--- /dev/null
+++ b/testutil/integration/os/factory/types.go
@@ -0,0 +1,44 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package factory
+
+import (
+ sdkmath "cosmossdk.io/math"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// CosmosTxArgs contains the params to create a cosmos tx
+type CosmosTxArgs struct {
+ // ChainID is the chain's id in cosmos format, e.g. 'evmos_9000-1'
+ ChainID string
+ // Gas to be used on the tx
+ Gas uint64
+ // GasPrice to use on tx
+ GasPrice *sdkmath.Int
+ // Fees is the fee to be used on the tx (amount and denom)
+ Fees sdktypes.Coins
+ // FeeGranter is the account address of the fee granter
+ FeeGranter sdktypes.AccAddress
+ // Msgs slice of messages to include on the tx
+ Msgs []sdktypes.Msg
+}
+
+// CallArgs is a struct to define all relevant data to call a smart contract.
+type CallArgs struct {
+ // ContractABI is the ABI of the contract to call.
+ ContractABI abi.ABI
+ // MethodName is the name of the method to call.
+ MethodName string
+ // Args are the arguments to pass to the method.
+ Args []interface{}
+}
+
+// ContractDeploymentData is a struct to define all relevant data to deploy a smart contract.
+type ContractDeploymentData struct {
+ // Contract is the compiled contract to deploy.
+ Contract evmtypes.CompiledContract
+ // ConstructorArgs are the arguments to pass to the constructor.
+ ConstructorArgs []interface{}
+}
diff --git a/testutil/integration/os/grpc/evm.go b/testutil/integration/os/grpc/evm.go
new file mode 100644
index 00000000..8b041d77
--- /dev/null
+++ b/testutil/integration/os/grpc/evm.go
@@ -0,0 +1,33 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package grpc
+
+import (
+ "context"
+
+ "github.com/ethereum/go-ethereum/common"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// GetEvmAccount returns the EVM account for the given address.
+func (gqh *IntegrationHandler) GetEvmAccount(address common.Address) (*evmtypes.QueryAccountResponse, error) {
+ evmClient := gqh.network.GetEvmClient()
+ return evmClient.Account(context.Background(), &evmtypes.QueryAccountRequest{
+ Address: address.String(),
+ })
+}
+
+// EstimateGas returns the estimated gas for the given call args.
+func (gqh *IntegrationHandler) EstimateGas(args []byte, gasCap uint64) (*evmtypes.EstimateGasResponse, error) {
+ evmClient := gqh.network.GetEvmClient()
+ return evmClient.EstimateGas(context.Background(), &evmtypes.EthCallRequest{
+ Args: args,
+ GasCap: gasCap,
+ })
+}
+
+// GetEvmParams returns the EVM module params.
+func (gqh *IntegrationHandler) GetEvmParams() (*evmtypes.QueryParamsResponse, error) {
+ evmClient := gqh.network.GetEvmClient()
+ return evmClient.Params(context.Background(), &evmtypes.QueryParamsRequest{})
+}
diff --git a/testutil/integration/os/grpc/feemarket.go b/testutil/integration/os/grpc/feemarket.go
new file mode 100644
index 00000000..d5094ba9
--- /dev/null
+++ b/testutil/integration/os/grpc/feemarket.go
@@ -0,0 +1,21 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package grpc
+
+import (
+ "context"
+
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
+)
+
+// GetBaseFee returns the base fee from the feemarket module.
+func (gqh *IntegrationHandler) GetBaseFee() (*feemarkettypes.QueryBaseFeeResponse, error) {
+ feeMarketClient := gqh.network.GetFeeMarketClient()
+ return feeMarketClient.BaseFee(context.Background(), &feemarkettypes.QueryBaseFeeRequest{})
+}
+
+// GetBaseFee returns the base fee from the feemarket module.
+func (gqh *IntegrationHandler) GetFeeMarketParams() (*feemarkettypes.QueryParamsResponse, error) {
+ feeMarketClient := gqh.network.GetFeeMarketClient()
+ return feeMarketClient.Params(context.Background(), &feemarkettypes.QueryParamsRequest{})
+}
diff --git a/testutil/integration/os/grpc/gov.go b/testutil/integration/os/grpc/gov.go
new file mode 100644
index 00000000..e916c7d8
--- /dev/null
+++ b/testutil/integration/os/grpc/gov.go
@@ -0,0 +1,28 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package grpc
+
+import (
+ "fmt"
+ "slices"
+
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+)
+
+// GetGovParams returns the gov params from the gov module.
+func (gqh *IntegrationHandler) GetGovParams(paramsType string) (*govtypes.QueryParamsResponse, error) {
+ possibleTypes := []string{"deposit", "tallying", "voting"}
+ if !slices.Contains(possibleTypes, paramsType) {
+ return nil, fmt.Errorf("invalid params type: %s\npossible types: %s", paramsType, possibleTypes)
+ }
+
+ govClient := gqh.network.GetGovClient()
+ return govClient.Params(gqh.network.GetContext(), &govtypes.QueryParamsRequest{ParamsType: paramsType})
+}
+
+// GetProposal returns the proposal from the gov module.
+func (gqh *IntegrationHandler) GetProposal(proposalID uint64) (*govtypes.QueryProposalResponse, error) {
+ govClient := gqh.network.GetGovClient()
+ return govClient.Proposal(gqh.network.GetContext(), &govtypes.QueryProposalRequest{ProposalId: proposalID})
+}
diff --git a/testutil/integration/os/grpc/grpc.go b/testutil/integration/os/grpc/grpc.go
new file mode 100644
index 00000000..de1ec89f
--- /dev/null
+++ b/testutil/integration/os/grpc/grpc.go
@@ -0,0 +1,52 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package grpc
+
+import (
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ "github.com/ethereum/go-ethereum/common"
+ commongrpc "github.com/evmos/os/testutil/integration/common/grpc"
+ "github.com/evmos/os/testutil/integration/os/network"
+ evmtypes "github.com/evmos/os/x/evm/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
+)
+
+// Handler is an interface that defines the methods that are used to query
+// the network's modules via gRPC.
+type Handler interface {
+ commongrpc.Handler
+
+ // EVM methods
+ GetEvmAccount(address common.Address) (*evmtypes.QueryAccountResponse, error)
+ EstimateGas(args []byte, GasCap uint64) (*evmtypes.EstimateGasResponse, error)
+ GetEvmParams() (*evmtypes.QueryParamsResponse, error)
+
+ // FeeMarket methods
+ GetBaseFee() (*feemarkettypes.QueryBaseFeeResponse, error)
+ GetFeeMarketParams() (*feemarkettypes.QueryParamsResponse, error)
+
+ // Gov methods
+ GetProposal(proposalID uint64) (*govtypes.QueryProposalResponse, error)
+ GetGovParams(paramsType string) (*govtypes.QueryParamsResponse, error)
+}
+
+var _ Handler = (*IntegrationHandler)(nil)
+
+// IntegrationHandler is a helper struct to query the network's modules
+// via gRPC. This is to simulate the behavior of a real user and avoid querying
+// the modules directly.
+type IntegrationHandler struct {
+ // We take the IntegrationHandler from common/grpc to get the common methods.
+ *commongrpc.IntegrationHandler
+ network network.Network
+}
+
+// NewIntegrationHandler creates a new IntegrationHandler instance.
+func NewIntegrationHandler(network network.Network) Handler {
+ return &IntegrationHandler{
+ // Is there a better way to do this?
+ IntegrationHandler: commongrpc.NewIntegrationHandler(network),
+ network: network,
+ }
+}
diff --git a/testutil/integration/os/keyring/keyring.go b/testutil/integration/os/keyring/keyring.go
new file mode 100644
index 00000000..58d1c465
--- /dev/null
+++ b/testutil/integration/os/keyring/keyring.go
@@ -0,0 +1,112 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keyring
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ utiltx "github.com/evmos/os/testutil/tx"
+)
+
+type Key struct {
+ Addr common.Address
+ AccAddr sdktypes.AccAddress
+ Priv cryptotypes.PrivKey
+}
+
+func NewKey() Key {
+ addr, privKey := utiltx.NewAddrKey()
+ return Key{
+ Addr: addr,
+ AccAddr: sdktypes.AccAddress(addr.Bytes()),
+ Priv: privKey,
+ }
+}
+
+type Keyring interface {
+ // GetPrivKey returns the private key of the account at the given keyring index.
+ GetPrivKey(index int) cryptotypes.PrivKey
+ // GetAddr returns the address of the account at the given keyring index.
+ GetAddr(index int) common.Address
+ // GetAccAddr returns the SDK address of the account at the given keyring index.
+ GetAccAddr(index int) sdktypes.AccAddress
+ // GetAllAccAddrs returns all the SDK addresses of the accounts in the keyring.
+ GetAllAccAddrs() []sdktypes.AccAddress
+ // GetKey returns the key at the given keyring index
+ GetKey(index int) Key
+
+ // AddKey adds a new account to the keyring
+ AddKey() int
+
+ // Sign signs message with the specified account.
+ Sign(index int, msg []byte) ([]byte, error)
+}
+
+// IntegrationKeyring is a keyring designed for integration tests.
+type IntegrationKeyring struct {
+ keys []Key
+}
+
+var _ Keyring = (*IntegrationKeyring)(nil)
+
+// New returns a new keyring with nAccs accounts.
+func New(nAccs int) Keyring {
+ accs := make([]Key, 0, nAccs)
+ for i := 0; i < nAccs; i++ {
+ acc := NewKey()
+ accs = append(accs, acc)
+ }
+ return &IntegrationKeyring{
+ keys: accs,
+ }
+}
+
+// GetPrivKey returns the private key of the specified account.
+func (kr *IntegrationKeyring) GetPrivKey(index int) cryptotypes.PrivKey {
+ return kr.keys[index].Priv
+}
+
+// GetAddr returns the address of the specified account.
+func (kr *IntegrationKeyring) GetAddr(index int) common.Address {
+ return kr.keys[index].Addr
+}
+
+// GetAccAddr returns the sdk address of the specified account.
+func (kr *IntegrationKeyring) GetAccAddr(index int) sdktypes.AccAddress {
+ return kr.keys[index].AccAddr
+}
+
+// GetAllAccAddrs returns all the sdk addresses of the accounts in the keyring.
+func (kr *IntegrationKeyring) GetAllAccAddrs() []sdktypes.AccAddress {
+ accs := make([]sdktypes.AccAddress, 0, len(kr.keys))
+ for _, key := range kr.keys {
+ accs = append(accs, key.AccAddr)
+ }
+ return accs
+}
+
+// GetKey returns the key specified by index
+func (kr *IntegrationKeyring) GetKey(index int) Key {
+ return kr.keys[index]
+}
+
+// AddKey adds a new account to the keyring. It returns the index for the key
+func (kr *IntegrationKeyring) AddKey() int {
+ acc := NewKey()
+ index := len(kr.keys)
+ kr.keys = append(kr.keys, acc)
+ return index
+}
+
+// Sign signs message with the specified key.
+func (kr *IntegrationKeyring) Sign(index int, msg []byte) ([]byte, error) {
+ privKey := kr.GetPrivKey(index)
+ if privKey == nil {
+ return nil, fmt.Errorf("no private key for account %d", index)
+ }
+ return privKey.Sign(msg)
+}
diff --git a/testutil/integration/os/network/abci.go b/testutil/integration/os/network/abci.go
new file mode 100644
index 00000000..efca125d
--- /dev/null
+++ b/testutil/integration/os/network/abci.go
@@ -0,0 +1,48 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package network
+
+import (
+ "time"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/store/types"
+)
+
+// NextBlock is a private helper function that runs the EndBlocker logic, commits the changes,
+// updates the header and runs the BeginBlocker
+func (n *IntegrationNetwork) NextBlock() error {
+ return n.NextBlockAfter(time.Second)
+}
+
+// NextBlockAfter is a private helper function that runs the EndBlocker logic, commits the changes,
+// updates the header to have a block time after the given duration and runs the BeginBlocker.
+func (n *IntegrationNetwork) NextBlockAfter(duration time.Duration) error {
+ // End block and commit
+ header := n.ctx.BlockHeader()
+ n.app.EndBlocker(n.ctx, abci.RequestEndBlock{Height: header.Height})
+ n.app.Commit()
+
+ // Calculate new block time after duration
+ newBlockTime := header.Time.Add(duration)
+
+ // Update block header and BeginBlock
+ header.Height++
+ header.AppHash = n.app.LastCommitID().Hash
+ header.Time = newBlockTime
+ n.app.BeginBlock(abci.RequestBeginBlock{
+ Header: header,
+ })
+
+ // Update context header
+ newCtx := n.app.BaseApp.NewContext(false, header)
+ newCtx = newCtx.WithMinGasPrices(n.ctx.MinGasPrices())
+ newCtx = newCtx.WithKVGasConfig(n.ctx.KVGasConfig())
+ newCtx = newCtx.WithTransientKVGasConfig(n.ctx.TransientKVGasConfig())
+ newCtx = newCtx.WithConsensusParams(n.ctx.ConsensusParams())
+ // This might have to be changed with time if we want to test gas limits
+ newCtx = newCtx.WithBlockGasMeter(sdktypes.NewInfiniteGasMeter())
+
+ n.ctx = newCtx
+ return nil
+}
diff --git a/testutil/integration/os/network/clients.go b/testutil/integration/os/network/clients.go
new file mode 100644
index 00000000..57a09016
--- /dev/null
+++ b/testutil/integration/os/network/clients.go
@@ -0,0 +1,85 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package network
+
+import (
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ "github.com/cosmos/cosmos-sdk/x/authz"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+ erc20types "github.com/evmos/os/x/erc20/types"
+ evmtypes "github.com/evmos/os/x/evm/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
+ infltypes "github.com/evmos/os/x/inflation/v1/types"
+)
+
+func getQueryHelper(ctx sdktypes.Context) *baseapp.QueryServiceTestHelper {
+ encCfg := encoding.MakeConfig(example_app.ModuleBasics)
+ interfaceRegistry := encCfg.InterfaceRegistry
+ // This is needed so that state changes are not committed in precompiles
+ // simulations.
+ cacheCtx, _ := ctx.CacheContext()
+ return baseapp.NewQueryServerTestHelper(cacheCtx, interfaceRegistry)
+}
+
+// TODO: remove Evmos specific stuff
+func (n *IntegrationNetwork) GetERC20Client() erc20types.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ erc20types.RegisterQueryServer(queryHelper, n.app.Erc20Keeper)
+ return erc20types.NewQueryClient(queryHelper)
+}
+
+func (n *IntegrationNetwork) GetEvmClient() evmtypes.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ evmtypes.RegisterQueryServer(queryHelper, n.app.EvmKeeper)
+ return evmtypes.NewQueryClient(queryHelper)
+}
+
+func (n *IntegrationNetwork) GetGovClient() govtypes.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ govtypes.RegisterQueryServer(queryHelper, n.app.GovKeeper)
+ return govtypes.NewQueryClient(queryHelper)
+}
+
+func (n *IntegrationNetwork) GetBankClient() banktypes.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ banktypes.RegisterQueryServer(queryHelper, n.app.BankKeeper)
+ return banktypes.NewQueryClient(queryHelper)
+}
+
+func (n *IntegrationNetwork) GetFeeMarketClient() feemarkettypes.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ feemarkettypes.RegisterQueryServer(queryHelper, n.app.FeeMarketKeeper)
+ return feemarkettypes.NewQueryClient(queryHelper)
+}
+
+// TODO: get rid of Evmos native clients
+func (n *IntegrationNetwork) GetInflationClient() infltypes.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ infltypes.RegisterQueryServer(queryHelper, n.app.InflationKeeper)
+ return infltypes.NewQueryClient(queryHelper)
+}
+
+func (n *IntegrationNetwork) GetAuthClient() authtypes.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ authtypes.RegisterQueryServer(queryHelper, n.app.AccountKeeper)
+ return authtypes.NewQueryClient(queryHelper)
+}
+
+func (n *IntegrationNetwork) GetAuthzClient() authz.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ authz.RegisterQueryServer(queryHelper, n.app.AuthzKeeper)
+ return authz.NewQueryClient(queryHelper)
+}
+
+func (n *IntegrationNetwork) GetStakingClient() stakingtypes.QueryClient {
+ queryHelper := getQueryHelper(n.GetContext())
+ stakingtypes.RegisterQueryServer(queryHelper, stakingkeeper.Querier{Keeper: n.app.StakingKeeper.Keeper})
+ return stakingtypes.NewQueryClient(queryHelper)
+}
diff --git a/testutil/integration/os/network/config.go b/testutil/integration/os/network/config.go
new file mode 100644
index 00000000..666543c6
--- /dev/null
+++ b/testutil/integration/os/network/config.go
@@ -0,0 +1,117 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network
+
+import (
+ "math/big"
+
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ testtx "github.com/evmos/os/testutil/tx"
+ evmostypes "github.com/evmos/os/types"
+ "github.com/evmos/os/utils"
+)
+
+// Config defines the configuration for a chain.
+// It allows for customization of the network to adjust to
+// testing needs.
+type Config struct {
+ chainID string
+ eip155ChainID *big.Int
+ amountOfValidators int
+ preFundedAccounts []sdktypes.AccAddress
+ balances []banktypes.Balance
+ denom string
+ customGenesisState CustomGenesisState
+}
+
+type CustomGenesisState map[string]interface{}
+
+// DefaultConfig returns the default configuration for a chain.
+func DefaultConfig() Config {
+ account, _ := testtx.NewAccAddressAndKey()
+ return Config{
+ chainID: utils.MainnetChainID + "-1",
+ eip155ChainID: big.NewInt(9001),
+ amountOfValidators: 3,
+ // No funded accounts besides the validators by default
+ preFundedAccounts: []sdktypes.AccAddress{account},
+ // NOTE: Per default, the balances are left empty, and the pre-funded accounts are used.
+ balances: nil,
+ denom: utils.BaseDenom,
+ customGenesisState: nil,
+ }
+}
+
+// getGenAccountsAndBalances takes the network configuration and returns the used
+// genesis accounts and balances.
+//
+// NOTE: If the balances are set, the pre-funded accounts are ignored.
+func getGenAccountsAndBalances(cfg Config) (genAccounts []authtypes.GenesisAccount, balances []banktypes.Balance) {
+ if len(cfg.balances) > 0 {
+ balances = cfg.balances
+ accounts := getAccAddrsFromBalances(balances)
+ genAccounts = createGenesisAccounts(accounts)
+ } else {
+ coin := sdktypes.NewCoin(cfg.denom, PrefundedAccountInitialBalance)
+ genAccounts = createGenesisAccounts(cfg.preFundedAccounts)
+ balances = createBalances(cfg.preFundedAccounts, coin)
+ }
+
+ return
+}
+
+// ConfigOption defines a function that can modify the NetworkConfig.
+// The purpose of this is to force to be declarative when the default configuration
+// requires to be changed.
+type ConfigOption func(*Config)
+
+// WithChainID sets a custom chainID for the network. It panics if the chainID is invalid.
+func WithChainID(chainID string) ConfigOption {
+ chainIDNum, err := evmostypes.ParseChainID(chainID)
+ if err != nil {
+ panic(err)
+ }
+ return func(cfg *Config) {
+ cfg.chainID = chainID
+ cfg.eip155ChainID = chainIDNum
+ }
+}
+
+// WithAmountOfValidators sets the amount of validators for the network.
+func WithAmountOfValidators(amount int) ConfigOption {
+ return func(cfg *Config) {
+ cfg.amountOfValidators = amount
+ }
+}
+
+// WithPreFundedAccounts sets the pre-funded accounts for the network.
+func WithPreFundedAccounts(accounts ...sdktypes.AccAddress) ConfigOption {
+ return func(cfg *Config) {
+ cfg.preFundedAccounts = accounts
+ }
+}
+
+// WithBalances sets the specific balances for the pre-funded accounts, that
+// are being set up for the network.
+func WithBalances(balances ...banktypes.Balance) ConfigOption {
+ return func(cfg *Config) {
+ cfg.balances = append(cfg.balances, balances...)
+ }
+}
+
+// WithDenom sets the denom for the network.
+func WithDenom(denom string) ConfigOption {
+ return func(cfg *Config) {
+ cfg.denom = denom
+ }
+}
+
+// WithCustomGenesis sets the custom genesis of the network for specific modules.
+func WithCustomGenesis(customGenesis CustomGenesisState) ConfigOption {
+ return func(cfg *Config) {
+ cfg.customGenesisState = customGenesis
+ }
+}
diff --git a/testutil/integration/os/network/config_test.go b/testutil/integration/os/network/config_test.go
new file mode 100644
index 00000000..73034038
--- /dev/null
+++ b/testutil/integration/os/network/config_test.go
@@ -0,0 +1,51 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network_test
+
+import (
+ "testing"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ grpchandler "github.com/evmos/os/testutil/integration/os/grpc"
+ testkeyring "github.com/evmos/os/testutil/integration/os/keyring"
+ "github.com/evmos/os/testutil/integration/os/network"
+ "github.com/evmos/os/utils"
+ "github.com/stretchr/testify/require"
+)
+
+func TestWithBalances(t *testing.T) {
+ key1Balance := sdk.NewCoins(sdk.NewInt64Coin(utils.BaseDenom, 1e18))
+ key2Balance := sdk.NewCoins(
+ sdk.NewInt64Coin(utils.BaseDenom, 2e18),
+ sdk.NewInt64Coin("other", 3e18),
+ )
+
+ // Create a new network with 2 pre-funded accounts
+ keyring := testkeyring.New(2)
+ balances := []banktypes.Balance{
+ {
+ Address: keyring.GetAccAddr(0).String(),
+ Coins: key1Balance,
+ },
+ {
+ Address: keyring.GetAccAddr(1).String(),
+ Coins: key2Balance,
+ },
+ }
+ nw := network.New(
+ network.WithBalances(balances...),
+ )
+ handler := grpchandler.NewIntegrationHandler(nw)
+
+ req, err := handler.GetAllBalances(keyring.GetAccAddr(0))
+ require.NoError(t, err, "error getting balances")
+ require.Len(t, req.Balances, 1, "wrong number of balances")
+ require.Equal(t, balances[0].Coins, req.Balances, "wrong balances")
+
+ req, err = handler.GetAllBalances(keyring.GetAccAddr(1))
+ require.NoError(t, err, "error getting balances")
+ require.Len(t, req.Balances, 2, "wrong number of balances")
+ require.Equal(t, balances[1].Coins, req.Balances, "wrong balances")
+}
diff --git a/testutil/integration/os/network/ibc.go b/testutil/integration/os/network/ibc.go
new file mode 100644
index 00000000..94e2e2d9
--- /dev/null
+++ b/testutil/integration/os/network/ibc.go
@@ -0,0 +1,28 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package network
+
+import (
+ "testing"
+
+ ibctesting "github.com/cosmos/ibc-go/v7/testing"
+)
+
+// GetIBCChain returns a TestChain instance for the given network.
+// Note: the sender accounts are not populated. Do not use this accounts to send transactions during tests.
+// The keyring should be used instead.
+func (n *IntegrationNetwork) GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain {
+ return &ibctesting.TestChain{
+ T: t,
+ Coordinator: coord,
+ ChainID: n.GetChainID(),
+ App: n.app,
+ CurrentHeader: n.ctx.BlockHeader(),
+ QueryServer: n.app.GetIBCKeeper(),
+ TxConfig: n.app.GetTxConfig(),
+ Codec: n.app.AppCodec(),
+ Vals: n.valSet,
+ NextVals: n.valSet,
+ Signers: n.valSigners,
+ }
+}
diff --git a/testutil/integration/os/network/network.go b/testutil/integration/os/network/network.go
new file mode 100644
index 00000000..f97e7881
--- /dev/null
+++ b/testutil/integration/os/network/network.go
@@ -0,0 +1,277 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network
+
+import (
+ "encoding/json"
+ "math"
+ "math/big"
+ "time"
+
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+
+ gethparams "github.com/ethereum/go-ethereum/params"
+ example_app "github.com/evmos/os/example_chain"
+ "github.com/evmos/os/types"
+
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ tmtypes "github.com/cometbft/cometbft/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ txtypes "github.com/cosmos/cosmos-sdk/types/tx"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ commonnetwork "github.com/evmos/os/testutil/integration/common/network"
+ erc20types "github.com/evmos/os/x/erc20/types"
+ evmtypes "github.com/evmos/os/x/evm/types"
+ feemarkettypes "github.com/evmos/os/x/feemarket/types"
+ infltypes "github.com/evmos/os/x/inflation/v1/types"
+)
+
+// Network is the interface that wraps the methods to interact with integration test network.
+//
+// It was designed to avoid users to access module's keepers directly and force integration tests
+// to be closer to the real user's behavior.
+type Network interface {
+ commonnetwork.Network
+
+ GetEIP155ChainID() *big.Int
+ GetEVMChainConfig() *gethparams.ChainConfig
+
+ // Clients
+ GetERC20Client() erc20types.QueryClient
+ GetEvmClient() evmtypes.QueryClient
+ GetGovClient() govtypes.QueryClient
+ GetInflationClient() infltypes.QueryClient
+ GetFeeMarketClient() feemarkettypes.QueryClient
+
+ // Because to update the module params on a conventional manner governance
+ // would be required, we should provide an easier way to update the params
+ UpdateEvmParams(params evmtypes.Params) error
+ UpdateGovParams(params govtypes.Params) error
+ UpdateInflationParams(params infltypes.Params) error
+ UpdateFeeMarketParams(params feemarkettypes.Params) error
+}
+
+var _ Network = (*IntegrationNetwork)(nil)
+
+// IntegrationNetwork is the implementation of the Network interface for integration tests.
+type IntegrationNetwork struct {
+ cfg Config
+ ctx sdktypes.Context
+ validators []stakingtypes.Validator
+ app *example_app.Evmos
+
+ // This is only needed for IBC chain testing setup
+ valSet *tmtypes.ValidatorSet
+ valSigners map[string]tmtypes.PrivValidator
+}
+
+// New configures and initializes a new integration Network instance with
+// the given configuration options. If no configuration options are provided
+// it uses the default configuration.
+//
+// It panics if an error occurs.
+func New(opts ...ConfigOption) *IntegrationNetwork {
+ cfg := DefaultConfig()
+ // Modify the default config with the given options
+ for _, opt := range opts {
+ opt(&cfg)
+ }
+
+ ctx := sdktypes.Context{}
+ network := &IntegrationNetwork{
+ cfg: cfg,
+ ctx: ctx,
+ validators: []stakingtypes.Validator{},
+ }
+
+ err := network.configureAndInitChain()
+ if err != nil {
+ panic(err)
+ }
+ return network
+}
+
+var (
+ // bondedAmt is the amount of tokens that each validator will have initially bonded
+ bondedAmt = sdktypes.TokensFromConsensusPower(1, types.PowerReduction)
+ // PrefundedAccountInitialBalance is the amount of tokens that each prefunded account has at genesis
+ PrefundedAccountInitialBalance = sdktypes.NewInt(int64(math.Pow10(18) * 4))
+)
+
+// configureAndInitChain initializes the network with the given configuration.
+// It creates the genesis state and starts the network.
+func (n *IntegrationNetwork) configureAndInitChain() error {
+ // Create funded accounts based on the config and
+ // create genesis accounts
+ genAccounts, fundedAccountBalances := getGenAccountsAndBalances(n.cfg)
+
+ // Create validator set with the amount of validators specified in the config
+ // with the default power of 1.
+ valSet, valSigners := createValidatorSetAndSigners(n.cfg.amountOfValidators)
+ totalBonded := bondedAmt.Mul(sdktypes.NewInt(int64(n.cfg.amountOfValidators)))
+
+ // Build staking type validators and delegations
+ validators, err := createStakingValidators(valSet.Validators, bondedAmt)
+ if err != nil {
+ return err
+ }
+
+ fundedAccountBalances = addBondedModuleAccountToFundedBalances(
+ fundedAccountBalances,
+ sdktypes.NewCoin(n.cfg.denom, totalBonded),
+ )
+
+ delegations := createDelegations(valSet.Validators, genAccounts[0].GetAddress())
+
+ // Create a new EvmosApp with the following params
+ evmosApp := createEvmosApp(n.cfg.chainID)
+
+ stakingParams := StakingCustomGenesisState{
+ denom: n.cfg.denom,
+ validators: validators,
+ delegations: delegations,
+ }
+
+ totalSupply := calculateTotalSupply(fundedAccountBalances)
+ bankParams := BankCustomGenesisState{
+ totalSupply: totalSupply,
+ balances: fundedAccountBalances,
+ }
+
+ // Configure Genesis state
+ genesisState := newDefaultGenesisState(
+ evmosApp,
+ defaultGenesisParams{
+ genAccounts: genAccounts,
+ staking: stakingParams,
+ bank: bankParams,
+ },
+ )
+
+ // modify genesis state if there're any custom genesis state
+ // for specific modules
+ genesisState, err = customizeGenesis(evmosApp, n.cfg.customGenesisState, genesisState)
+ if err != nil {
+ return err
+ }
+
+ // Init chain
+ stateBytes, err := json.MarshalIndent(genesisState, "", " ")
+ if err != nil {
+ return err
+ }
+
+ consensusParams := example_app.DefaultConsensusParams
+ now := time.Now()
+ evmosApp.InitChain(
+ abcitypes.RequestInitChain{
+ Time: now,
+ ChainId: n.cfg.chainID,
+ Validators: []abcitypes.ValidatorUpdate{},
+ ConsensusParams: consensusParams,
+ AppStateBytes: stateBytes,
+ },
+ )
+ // Commit genesis changes
+ evmosApp.Commit()
+
+ header := tmproto.Header{
+ ChainID: n.cfg.chainID,
+ Height: evmosApp.LastBlockHeight() + 1,
+ Time: now,
+ AppHash: evmosApp.LastCommitID().Hash,
+ ValidatorsHash: valSet.Hash(),
+ NextValidatorsHash: valSet.Hash(),
+ ProposerAddress: valSet.Proposer.Address,
+ }
+ evmosApp.BeginBlock(abcitypes.RequestBeginBlock{Header: header})
+
+ // Set networks global parameters
+ n.app = evmosApp
+ // TODO - this might not be the best way to initialize the context
+ n.ctx = evmosApp.BaseApp.NewContext(false, header)
+ n.ctx = n.ctx.WithConsensusParams(consensusParams)
+ n.ctx = n.ctx.WithBlockGasMeter(sdktypes.NewInfiniteGasMeter())
+
+ n.validators = validators
+ n.valSet = valSet
+ n.valSigners = valSigners
+
+ // Register EVMOS in denom metadata
+ evmosMetadata := banktypes.Metadata{
+ Description: "The native token of Evmos",
+ Base: n.cfg.denom,
+ // NOTE: Denom units MUST be increasing
+ DenomUnits: []*banktypes.DenomUnit{
+ {
+ Denom: n.cfg.denom,
+ Exponent: 0,
+ Aliases: []string{n.cfg.denom},
+ },
+ {
+ Denom: n.cfg.denom,
+ Exponent: 18,
+ },
+ },
+ Name: "Evmos",
+ Symbol: "EVMOS",
+ Display: n.cfg.denom,
+ }
+ evmosApp.BankKeeper.SetDenomMetaData(n.ctx, evmosMetadata)
+
+ return nil
+}
+
+// GetContext returns the network's context
+func (n *IntegrationNetwork) GetContext() sdktypes.Context {
+ return n.ctx
+}
+
+// GetChainID returns the network's chainID
+func (n *IntegrationNetwork) GetChainID() string {
+ return n.cfg.chainID
+}
+
+// GetEIP155ChainID returns the network EIp-155 chainID number
+func (n *IntegrationNetwork) GetEIP155ChainID() *big.Int {
+ return n.cfg.eip155ChainID
+}
+
+// GetChainConfig returns the network's chain config
+func (n *IntegrationNetwork) GetEVMChainConfig() *gethparams.ChainConfig {
+ params := n.app.EvmKeeper.GetParams(n.ctx)
+ return params.ChainConfig.EthereumConfig(n.cfg.eip155ChainID)
+}
+
+// GetDenom returns the network's denom
+func (n *IntegrationNetwork) GetDenom() string {
+ return n.cfg.denom
+}
+
+// GetValidators returns the network's validators
+func (n *IntegrationNetwork) GetValidators() []stakingtypes.Validator {
+ return n.validators
+}
+
+// BroadcastTxSync broadcasts the given txBytes to the network and returns the response.
+// TODO - this should be change to gRPC
+func (n *IntegrationNetwork) BroadcastTxSync(txBytes []byte) (abcitypes.ResponseDeliverTx, error) {
+ req := abcitypes.RequestDeliverTx{Tx: txBytes}
+ return n.app.BaseApp.DeliverTx(req), nil
+}
+
+// Simulate simulates the given txBytes to the network and returns the simulated response.
+// TODO - this should be change to gRPC
+func (n *IntegrationNetwork) Simulate(txBytes []byte) (*txtypes.SimulateResponse, error) {
+ gas, result, err := n.app.BaseApp.Simulate(txBytes)
+ if err != nil {
+ return nil, err
+ }
+ return &txtypes.SimulateResponse{
+ GasInfo: &gas,
+ Result: result,
+ }, nil
+}
diff --git a/testutil/integration/os/network/params.go b/testutil/integration/os/network/params.go
new file mode 100644
index 00000000..56992d23
--- /dev/null
+++ b/testutil/integration/os/network/params.go
@@ -0,0 +1,27 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network
+
+import (
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ evmtypes "github.com/evmos/os/x/evm/types"
+ feemarketypes "github.com/evmos/os/x/feemarket/types"
+ infltypes "github.com/evmos/os/x/inflation/v1/types"
+)
+
+func (n *IntegrationNetwork) UpdateEvmParams(params evmtypes.Params) error {
+ return n.app.EvmKeeper.SetParams(n.ctx, params)
+}
+
+func (n *IntegrationNetwork) UpdateFeeMarketParams(params feemarketypes.Params) error {
+ return n.app.FeeMarketKeeper.SetParams(n.ctx, params)
+}
+
+func (n *IntegrationNetwork) UpdateInflationParams(params infltypes.Params) error {
+ return n.app.InflationKeeper.SetParams(n.ctx, params)
+}
+
+func (n *IntegrationNetwork) UpdateGovParams(params govtypes.Params) error {
+ return n.app.GovKeeper.SetParams(n.ctx, params)
+}
diff --git a/testutil/integration/os/network/setup.go b/testutil/integration/os/network/setup.go
new file mode 100644
index 00000000..7dc8b507
--- /dev/null
+++ b/testutil/integration/os/network/setup.go
@@ -0,0 +1,355 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network
+
+import (
+ "fmt"
+ "time"
+
+ sdkmath "cosmossdk.io/math"
+ "cosmossdk.io/simapp"
+ dbm "github.com/cometbft/cometbft-db"
+ "github.com/cometbft/cometbft/libs/log"
+ tmtypes "github.com/cometbft/cometbft/types"
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
+ "github.com/cosmos/cosmos-sdk/testutil/mock"
+ simutils "github.com/cosmos/cosmos-sdk/testutil/sims"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+ govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/cosmos/gogoproto/proto"
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+ evmosutil "github.com/evmos/os/utils"
+ epochstypes "github.com/evmos/os/x/epochs/types"
+ erc20types "github.com/evmos/os/x/erc20/types"
+ evmtypes "github.com/evmos/os/x/evm/types"
+ infltypes "github.com/evmos/os/x/inflation/v1/types"
+)
+
+// createValidatorSetAndSigners creates validator set with the amount of validators specified
+// with the default power of 1.
+func createValidatorSetAndSigners(numberOfValidators int) (*tmtypes.ValidatorSet, map[string]tmtypes.PrivValidator) {
+ // Create validator set
+ tmValidators := make([]*tmtypes.Validator, 0, numberOfValidators)
+ signers := make(map[string]tmtypes.PrivValidator, numberOfValidators)
+
+ for i := 0; i < numberOfValidators; i++ {
+ privVal := mock.NewPV()
+ pubKey, _ := privVal.GetPubKey()
+ validator := tmtypes.NewValidator(pubKey, 1)
+ tmValidators = append(tmValidators, validator)
+ signers[pubKey.Address().String()] = privVal
+ }
+
+ return tmtypes.NewValidatorSet(tmValidators), signers
+}
+
+// createGenesisAccounts returns a slice of genesis accounts from the given
+// account addresses.
+func createGenesisAccounts(accounts []sdktypes.AccAddress) []authtypes.GenesisAccount {
+ numberOfAccounts := len(accounts)
+ genAccounts := make([]authtypes.GenesisAccount, 0, numberOfAccounts)
+ for _, acc := range accounts {
+ genAccounts = append(genAccounts, authtypes.NewBaseAccount(
+ acc, nil, 0, 0),
+ )
+ }
+ return genAccounts
+}
+
+// getAccAddrsFromBalances returns a slice of genesis accounts from the
+// given balances.
+func getAccAddrsFromBalances(balances []banktypes.Balance) []sdktypes.AccAddress {
+ numberOfBalances := len(balances)
+ genAccounts := make([]sdktypes.AccAddress, 0, numberOfBalances)
+ for _, balance := range balances {
+ genAccounts = append(genAccounts, balance.GetAddress())
+ }
+ return genAccounts
+}
+
+// createBalances creates balances for the given accounts and coin
+func createBalances(accounts []sdktypes.AccAddress, coin sdktypes.Coin) []banktypes.Balance {
+ numberOfAccounts := len(accounts)
+ fundedAccountBalances := make([]banktypes.Balance, 0, numberOfAccounts)
+ for _, acc := range accounts {
+ balance := banktypes.Balance{
+ Address: acc.String(),
+ Coins: sdktypes.NewCoins(coin),
+ }
+
+ fundedAccountBalances = append(fundedAccountBalances, balance)
+ }
+ return fundedAccountBalances
+}
+
+// createEvmosApp creates an evmos app
+func createEvmosApp(chainID string) *example_app.Evmos {
+ // Create evmos app
+ db := dbm.NewMemDB()
+ logger := log.NewNopLogger()
+ loadLatest := true
+ skipUpgradeHeights := map[int64]bool{}
+ homePath := example_app.DefaultNodeHome
+ invCheckPeriod := uint(5)
+ encodingConfig := encoding.MakeConfig(example_app.ModuleBasics)
+ appOptions := simutils.NewAppOptionsWithFlagHome(example_app.DefaultNodeHome)
+ baseAppOptions := []func(*baseapp.BaseApp){baseapp.SetChainID(chainID)}
+
+ return example_app.NewEvmos(
+ logger,
+ db,
+ nil,
+ loadLatest,
+ skipUpgradeHeights,
+ homePath,
+ invCheckPeriod,
+ encodingConfig,
+ appOptions,
+ baseAppOptions...,
+ )
+}
+
+// createStakingValidator creates a staking validator from the given tm validator and bonded
+func createStakingValidator(val *tmtypes.Validator, bondedAmt sdkmath.Int) (stakingtypes.Validator, error) {
+ pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
+ if err != nil {
+ return stakingtypes.Validator{}, err
+ }
+
+ pkAny, err := codectypes.NewAnyWithValue(pk)
+ if err != nil {
+ return stakingtypes.Validator{}, err
+ }
+
+ commission := stakingtypes.NewCommission(sdktypes.ZeroDec(), sdktypes.ZeroDec(), sdktypes.ZeroDec())
+ validator := stakingtypes.Validator{
+ OperatorAddress: sdktypes.ValAddress(val.Address).String(),
+ ConsensusPubkey: pkAny,
+ Jailed: false,
+ Status: stakingtypes.Bonded,
+ Tokens: bondedAmt,
+ DelegatorShares: sdktypes.OneDec(),
+ Description: stakingtypes.Description{},
+ UnbondingHeight: int64(0),
+ UnbondingTime: time.Unix(0, 0).UTC(),
+ Commission: commission,
+ MinSelfDelegation: sdktypes.ZeroInt(),
+ }
+ return validator, nil
+}
+
+// createStakingValidators creates staking validators from the given tm validators and bonded
+// amounts
+func createStakingValidators(tmValidators []*tmtypes.Validator, bondedAmt sdkmath.Int) ([]stakingtypes.Validator, error) {
+ amountOfValidators := len(tmValidators)
+ stakingValidators := make([]stakingtypes.Validator, 0, amountOfValidators)
+ for _, val := range tmValidators {
+ validator, err := createStakingValidator(val, bondedAmt)
+ if err != nil {
+ return nil, err
+ }
+ stakingValidators = append(stakingValidators, validator)
+ }
+ return stakingValidators, nil
+}
+
+// createDelegations creates delegations for the given validators and account
+func createDelegations(tmValidators []*tmtypes.Validator, fromAccount sdktypes.AccAddress) []stakingtypes.Delegation {
+ amountOfValidators := len(tmValidators)
+ delegations := make([]stakingtypes.Delegation, 0, amountOfValidators)
+ for _, val := range tmValidators {
+ delegation := stakingtypes.NewDelegation(fromAccount, val.Address.Bytes(), sdktypes.OneDec())
+ delegations = append(delegations, delegation)
+ }
+ return delegations
+}
+
+// StakingCustomGenesisState defines the staking genesis state
+type StakingCustomGenesisState struct {
+ denom string
+
+ validators []stakingtypes.Validator
+ delegations []stakingtypes.Delegation
+}
+
+// setDefaultStakingGenesisState sets the staking genesis state
+func setDefaultStakingGenesisState(evmosApp *example_app.Evmos, genesisState simapp.GenesisState, overwriteParams StakingCustomGenesisState) simapp.GenesisState {
+ // Set staking params
+ stakingParams := stakingtypes.DefaultParams()
+ stakingParams.BondDenom = overwriteParams.denom
+
+ stakingGenesis := stakingtypes.NewGenesisState(
+ stakingParams,
+ overwriteParams.validators,
+ overwriteParams.delegations,
+ )
+ genesisState[stakingtypes.ModuleName] = evmosApp.AppCodec().MustMarshalJSON(stakingGenesis)
+ return genesisState
+}
+
+// TODO: remove Evmos specific stuff
+// setDefaultInflationGenesisState sets the inflation genesis state
+func setDefaultInflationGenesisState(evmosApp *example_app.Evmos, genesisState simapp.GenesisState) simapp.GenesisState {
+ inflationParams := infltypes.DefaultParams()
+ inflationParams.EnableInflation = false
+
+ inflationGenesis := infltypes.NewGenesisState(inflationParams, uint64(0), epochstypes.DayEpochID, 365, 0)
+ genesisState[infltypes.ModuleName] = evmosApp.AppCodec().MustMarshalJSON(&inflationGenesis)
+ return genesisState
+}
+
+type BankCustomGenesisState struct {
+ totalSupply sdktypes.Coins
+ balances []banktypes.Balance
+}
+
+// setDefaultBankGenesisState sets the bank genesis state
+func setDefaultBankGenesisState(
+ evmosApp *example_app.Evmos,
+ genesisState simapp.GenesisState,
+ overwriteParams BankCustomGenesisState,
+) simapp.GenesisState {
+ bankGenesis := banktypes.NewGenesisState(
+ banktypes.DefaultGenesisState().Params,
+ overwriteParams.balances,
+ overwriteParams.totalSupply,
+ []banktypes.Metadata{},
+ []banktypes.SendEnabled{},
+ )
+ genesisState[banktypes.ModuleName] = evmosApp.AppCodec().MustMarshalJSON(bankGenesis)
+ return genesisState
+}
+
+// genSetupFn is the type for the module genesis setup functions
+type genSetupFn func(
+ evmosApp *example_app.Evmos,
+ genesisState simapp.GenesisState,
+ customGenesis interface{},
+) (simapp.GenesisState, error)
+
+// defaultGenesisParams contains the params that are needed to
+// setup the default genesis for the testing setup
+type defaultGenesisParams struct {
+ genAccounts []authtypes.GenesisAccount
+ staking StakingCustomGenesisState
+ bank BankCustomGenesisState
+}
+
+// genStateSetter is a generic function to set module-specific genesis state
+func genStateSetter[T proto.Message](moduleName string) genSetupFn {
+ return func(
+ evmosApp *example_app.Evmos,
+ genesisState simapp.GenesisState,
+ customGenesis interface{},
+ ) (simapp.GenesisState, error) {
+ moduleGenesis, ok := customGenesis.(T)
+ if !ok {
+ return nil, fmt.Errorf("invalid type %T for %s module genesis state", customGenesis, moduleName)
+ }
+
+ genesisState[moduleName] = evmosApp.AppCodec().MustMarshalJSON(moduleGenesis)
+ return genesisState, nil
+ }
+}
+
+// genesisSetupFunctions contains the available genesis setup functions
+// that can be used to customize the network genesis
+var genesisSetupFunctions = map[string]genSetupFn{
+ authtypes.ModuleName: genStateSetter[*authtypes.GenesisState](authtypes.ModuleName),
+ evmtypes.ModuleName: genStateSetter[*evmtypes.GenesisState](evmtypes.ModuleName),
+ govtypes.ModuleName: genStateSetter[*govtypesv1.GenesisState](govtypes.ModuleName),
+ infltypes.ModuleName: genStateSetter[*infltypes.GenesisState](infltypes.ModuleName),
+ erc20types.ModuleName: genStateSetter[*erc20types.GenesisState](erc20types.ModuleName),
+}
+
+// setDefaultAuthGenesisState sets the default auth genesis state
+func setDefaultAuthGenesisState(
+ evmosApp *example_app.Evmos,
+ genesisState simapp.GenesisState,
+ genAccs []authtypes.GenesisAccount,
+) simapp.GenesisState {
+ defaultAuthGen := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
+ genesisState[authtypes.ModuleName] = evmosApp.AppCodec().MustMarshalJSON(defaultAuthGen)
+ return genesisState
+}
+
+// setDefaultGovGenesisState sets the default gov genesis state
+func setDefaultGovGenesisState(evmosApp *example_app.Evmos, genesisState simapp.GenesisState) simapp.GenesisState {
+ govGen := govtypesv1.DefaultGenesisState()
+ updatedParams := govGen.Params
+ // set 'aevmos' as deposit denom
+ updatedParams.MinDeposit = sdktypes.NewCoins(sdktypes.NewCoin(evmosutil.BaseDenom, sdkmath.NewInt(1e18)))
+ govGen.Params = updatedParams
+ genesisState[govtypes.ModuleName] = evmosApp.AppCodec().MustMarshalJSON(govGen)
+ return genesisState
+}
+
+func setDefaultErc20GenesisState(evmosApp *example_app.Evmos, genesisState simapp.GenesisState) simapp.GenesisState {
+ erc20Gen := erc20types.DefaultGenesisState()
+ genesisState[erc20types.ModuleName] = evmosApp.AppCodec().MustMarshalJSON(erc20Gen)
+ return genesisState
+}
+
+// defaultAuthGenesisState sets the default genesis state
+// for the testing setup
+func newDefaultGenesisState(evmosApp *example_app.Evmos, params defaultGenesisParams) simapp.GenesisState {
+ genesisState := example_app.NewDefaultGenesisState()
+
+ genesisState = setDefaultAuthGenesisState(evmosApp, genesisState, params.genAccounts)
+ genesisState = setDefaultStakingGenesisState(evmosApp, genesisState, params.staking)
+ genesisState = setDefaultBankGenesisState(evmosApp, genesisState, params.bank)
+ genesisState = setDefaultInflationGenesisState(evmosApp, genesisState)
+ genesisState = setDefaultGovGenesisState(evmosApp, genesisState)
+ genesisState = setDefaultErc20GenesisState(evmosApp, genesisState)
+
+ return genesisState
+}
+
+// customizeGenesis modifies genesis state if there're any custom genesis state
+// for specific modules
+func customizeGenesis(
+ evmosApp *example_app.Evmos,
+ customGen CustomGenesisState,
+ genesisState simapp.GenesisState,
+) (simapp.GenesisState, error) {
+ var err error
+ for mod, modGenState := range customGen {
+ if fn, found := genesisSetupFunctions[mod]; found {
+ genesisState, err = fn(evmosApp, genesisState, modGenState)
+ if err != nil {
+ return genesisState, err
+ }
+ } else {
+ panic(fmt.Sprintf("module %s not found in genesis setup functions", mod))
+ }
+ }
+ return genesisState, err
+}
+
+// calculateTotalSupply calculates the total supply from the given balances
+func calculateTotalSupply(fundedAccountsBalances []banktypes.Balance) sdktypes.Coins {
+ totalSupply := sdktypes.NewCoins()
+ for _, balance := range fundedAccountsBalances {
+ totalSupply = totalSupply.Add(balance.Coins...)
+ }
+ return totalSupply
+}
+
+// addBondedModuleAccountToFundedBalances adds bonded amount to bonded pool module account and include it on funded accounts
+func addBondedModuleAccountToFundedBalances(
+ fundedAccountsBalances []banktypes.Balance,
+ totalBonded sdktypes.Coin,
+) []banktypes.Balance {
+ return append(fundedAccountsBalances, banktypes.Balance{
+ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
+ Coins: sdktypes.Coins{totalBonded},
+ })
+}
diff --git a/testutil/integration/os/network/unit_network.go b/testutil/integration/os/network/unit_network.go
new file mode 100644
index 00000000..1d346a9c
--- /dev/null
+++ b/testutil/integration/os/network/unit_network.go
@@ -0,0 +1,57 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package network
+
+import (
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ example_app "github.com/evmos/os/example_chain"
+ "github.com/evmos/os/x/evm/statedb"
+ inflationtypes "github.com/evmos/os/x/inflation/v1/types"
+)
+
+// UnitTestNetwork is the implementation of the Network interface for unit tests.
+// It embeds the IntegrationNetwork struct to reuse its methods and
+// makes the App public for easier testing.
+type UnitTestNetwork struct {
+ IntegrationNetwork
+ App *example_app.ExampleChain
+}
+
+var _ Network = (*UnitTestNetwork)(nil)
+
+// NewUnitTestNetwork configures and initializes a new Evmos Network instance with
+// the given configuration options. If no configuration options are provided
+// it uses the default configuration.
+//
+// It panics if an error occurs.
+// Note: Only uses for Unit Tests
+func NewUnitTestNetwork(opts ...ConfigOption) *UnitTestNetwork {
+ network := New(opts...)
+ return &UnitTestNetwork{
+ IntegrationNetwork: *network,
+ App: network.app,
+ }
+}
+
+// GetStateDB returns the state database for the current block.
+func (n *UnitTestNetwork) GetStateDB() *statedb.StateDB {
+ headerHash := n.GetContext().HeaderHash()
+ return statedb.New(
+ n.GetContext(),
+ n.App.EvmKeeper,
+ statedb.NewEmptyTxConfig(common.BytesToHash(headerHash.Bytes())),
+ )
+}
+
+// FundAccount funds the given account with the given amount of coins.
+func (n *UnitTestNetwork) FundAccount(addr sdktypes.AccAddress, coins sdktypes.Coins) error {
+ ctx := n.GetContext()
+
+ // TODO: remove Evmos native namespaces (inflation)
+ if err := n.app.BankKeeper.MintCoins(ctx, inflationtypes.ModuleName, coins); err != nil {
+ return err
+ }
+
+ return n.app.BankKeeper.SendCoinsFromModuleToAccount(ctx, inflationtypes.ModuleName, addr, coins)
+}
diff --git a/testutil/integration/os/utils/bank.go b/testutil/integration/os/utils/bank.go
new file mode 100644
index 00000000..4768a700
--- /dev/null
+++ b/testutil/integration/os/utils/bank.go
@@ -0,0 +1,34 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package utils
+
+import (
+ "fmt"
+
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/evmos/os/testutil/integration/common/grpc"
+)
+
+// CheckBalances checks that the given accounts have the expected balances and
+// returns an error if that is not the case.
+func CheckBalances(handler grpc.Handler, balances []banktypes.Balance) error {
+ for _, balance := range balances {
+ addr := balance.GetAddress()
+ for _, coin := range balance.GetCoins() {
+ balance, err := handler.GetBalance(addr, coin.Denom)
+ if err != nil {
+ return err
+ }
+
+ if !balance.Balance.IsEqual(coin) {
+ return fmt.Errorf(
+ "expected balance %s, got %s for address %s",
+ coin, balance.Balance, addr,
+ )
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/testutil/integration/os/utils/bank_test.go b/testutil/integration/os/utils/bank_test.go
new file mode 100644
index 00000000..e469fa99
--- /dev/null
+++ b/testutil/integration/os/utils/bank_test.go
@@ -0,0 +1,65 @@
+package utils_test
+
+import (
+ "testing"
+
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ grpchandler "github.com/evmos/os/testutil/integration/os/grpc"
+ testkeyring "github.com/evmos/os/testutil/integration/os/keyring"
+ "github.com/evmos/os/testutil/integration/os/network"
+ "github.com/evmos/os/testutil/integration/os/utils"
+ "github.com/stretchr/testify/require"
+)
+
+func TestCheckBalances(t *testing.T) {
+ testDenom := "atest"
+ keyring := testkeyring.New(1)
+ nw := network.New(
+ network.WithDenom(testDenom),
+ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ handler := grpchandler.NewIntegrationHandler(nw)
+
+ testcases := []struct {
+ name string
+ address string
+ expAmount math.Int
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "pass",
+ address: keyring.GetAccAddr(0).String(),
+ expAmount: network.PrefundedAccountInitialBalance,
+ expPass: true,
+ },
+ {
+ name: "fail - wrong amount",
+ address: keyring.GetAccAddr(0).String(),
+ expAmount: sdk.NewInt(1),
+ errContains: "expected balance",
+ },
+ }
+
+ for _, tc := range testcases {
+ tc := tc
+ t.Run(tc.name, func(t *testing.T) {
+ balances := []banktypes.Balance{{
+ Address: tc.address,
+ Coins: sdk.NewCoins(
+ sdk.NewCoin(testDenom, tc.expAmount),
+ ),
+ }}
+
+ err := utils.CheckBalances(handler, balances)
+ if tc.expPass {
+ require.NoError(t, err, "unexpected error checking balances")
+ } else {
+ require.Error(t, err, "expected error checking balances")
+ require.ErrorContains(t, err, tc.errContains, "expected different error checking balances")
+ }
+ })
+ }
+}
diff --git a/testutil/integration/os/utils/contracts.go b/testutil/integration/os/utils/contracts.go
new file mode 100644
index 00000000..34d67a4e
--- /dev/null
+++ b/testutil/integration/os/utils/contracts.go
@@ -0,0 +1,57 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package utils
+
+import (
+ "fmt"
+ "slices"
+
+ "github.com/evmos/os/testutil/integration/os/factory"
+
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// CheckTxTopics checks if all expected topics are present in the transaction response
+func CheckTxTopics(res abcitypes.ResponseDeliverTx, expectedTopics []string) error {
+ msgEthResponse, err := DecodeResponseDeliverTx(res)
+ if err != nil {
+ return err
+ }
+
+ // Collect all topics within the transaction
+ availableLogs := make([]string, 0, len(msgEthResponse.Logs))
+ for _, log := range msgEthResponse.Logs {
+ availableLogs = append(availableLogs, log.Topics...)
+ }
+
+ // Check if all expected topics are present
+ for _, expectedTopic := range expectedTopics {
+ if !slices.Contains(availableLogs, expectedTopic) {
+ return fmt.Errorf("expected topic %s not found in tx response", expectedTopic)
+ }
+ }
+ return nil
+}
+
+// DecodeContractCallResponse decodes the response of a contract call query
+func DecodeContractCallResponse(response interface{}, callArgs factory.CallArgs, res abcitypes.ResponseDeliverTx) error {
+ msgEthResponse, err := DecodeResponseDeliverTx(res)
+ if err != nil {
+ return err
+ }
+
+ err = callArgs.ContractABI.UnpackIntoInterface(response, callArgs.MethodName, msgEthResponse.Ret)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func DecodeResponseDeliverTx(res abcitypes.ResponseDeliverTx) (*evmtypes.MsgEthereumTxResponse, error) {
+ msgEthResponse, err := evmtypes.DecodeTxResponse(res.Data)
+ if err != nil {
+ return nil, err
+ }
+ return msgEthResponse, nil
+}
diff --git a/testutil/integration/os/utils/erc20.go b/testutil/integration/os/utils/erc20.go
new file mode 100644
index 00000000..f43653fc
--- /dev/null
+++ b/testutil/integration/os/utils/erc20.go
@@ -0,0 +1,114 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package utils
+
+import (
+ "fmt"
+
+ errorsmod "cosmossdk.io/errors"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/os/testutil/integration/os/factory"
+ "github.com/evmos/os/testutil/integration/os/network"
+ erc20types "github.com/evmos/os/x/erc20/types"
+)
+
+// ERC20RegistrationData is the necessary data to provide in order to register an ERC20 token.
+type ERC20RegistrationData struct {
+ // Address is the address of the ERC20 token.
+ Address common.Address
+ // Denom is the ERC20 token denom.
+ Denom string
+ // ProposerPriv is the private key used to sign the proposal and voting transactions.
+ ProposerPriv cryptotypes.PrivKey
+}
+
+// ValidateBasic does stateless validation of the data for the ERC20 registration.
+func (ed ERC20RegistrationData) ValidateBasic() error {
+ emptyAddr := common.Address{}
+ if ed.Address.Hex() == emptyAddr.Hex() {
+ return fmt.Errorf("address cannot be empty")
+ }
+
+ if ed.Denom == "" {
+ return fmt.Errorf("denom cannot be empty")
+ }
+
+ if ed.ProposerPriv == nil {
+ return fmt.Errorf("proposer private key cannot be nil")
+ }
+
+ return nil
+}
+
+// RegisterERC20 is a helper function to register ERC20 token through
+// submitting a governance proposal and having it pass.
+// It returns the registered token pair.
+func RegisterERC20(tf factory.TxFactory, network network.Network, data ERC20RegistrationData) (erc20types.TokenPair, error) {
+ err := data.ValidateBasic()
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to validate erc20 registration data")
+ }
+
+ proposal := erc20types.RegisterERC20Proposal{
+ Title: fmt.Sprintf("Register %s Token", data.Denom),
+ Description: fmt.Sprintf("This proposal registers the ERC20 token at address: %s", data.Address.Hex()),
+ Erc20Addresses: []string{data.Address.Hex()},
+ }
+
+ // Submit the proposal
+ proposalID, err := SubmitProposal(tf, network, data.ProposerPriv, &proposal)
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to submit proposal")
+ }
+
+ err = network.NextBlock()
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to commit block after proposal")
+ }
+
+ // Vote on proposal
+ err = VoteOnProposal(tf, data.ProposerPriv, proposalID, govtypes.OptionYes)
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to vote on proposal")
+ }
+
+ gq := network.GetGovClient()
+ params, err := gq.Params(network.GetContext(), &govtypes.QueryParamsRequest{ParamsType: "voting"})
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to query voting params")
+ }
+
+ err = network.NextBlockAfter(*params.Params.VotingPeriod) // commit after voting period is over
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to commit block after voting period ends")
+ }
+
+ err = network.NextBlock()
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to commit block after votes")
+ }
+
+ // NOTE: it's necessary to instantiate a new gov client here, because the previous one has now an outdated
+ // context.
+ gq = network.GetGovClient()
+ proposalRes, err := gq.Proposal(network.GetContext(), &govtypes.QueryProposalRequest{ProposalId: proposalID})
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to query proposal")
+ }
+
+ if proposalRes.Proposal.Status != govtypes.StatusPassed {
+ return erc20types.TokenPair{}, fmt.Errorf("proposal did not pass; got status: %s", proposalRes.Proposal.Status.String())
+ }
+
+ // Check if token pair is registered
+ eq := network.GetERC20Client()
+ tokenPairRes, err := eq.TokenPair(network.GetContext(), &erc20types.QueryTokenPairRequest{Token: data.Address.Hex()})
+ if err != nil {
+ return erc20types.TokenPair{}, errorsmod.Wrap(err, "failed to query token pair")
+ }
+
+ return tokenPairRes.TokenPair, nil
+}
diff --git a/testutil/integration/os/utils/evm.go b/testutil/integration/os/utils/evm.go
new file mode 100644
index 00000000..234feeda
--- /dev/null
+++ b/testutil/integration/os/utils/evm.go
@@ -0,0 +1,53 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package utils
+
+import (
+ "encoding/json"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/evmos/os/contracts"
+ "github.com/evmos/os/testutil/integration/os/network"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+// GetERC20Balance returns the token balance of a given account address for
+// an ERC-20 token at the given contract address.
+func GetERC20Balance(nw network.Network, tokenAddress, accountAddress common.Address) (*big.Int, error) {
+ input, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack(
+ "balanceOf",
+ accountAddress,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ callData, err := json.Marshal(evmtypes.TransactionArgs{
+ To: &tokenAddress,
+ Input: (*hexutil.Bytes)(&input),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ ethRes, err := nw.GetEvmClient().EthCall(
+ nw.GetContext(),
+ &evmtypes.EthCallRequest{
+ Args: callData,
+ },
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ var balance *big.Int
+ err = contracts.ERC20MinterBurnerDecimalsContract.ABI.UnpackIntoInterface(&balance, "balanceOf", ethRes.Ret)
+ if err != nil {
+ return nil, err
+ }
+
+ return balance, nil
+}
diff --git a/testutil/integration/os/utils/evm_test.go b/testutil/integration/os/utils/evm_test.go
new file mode 100644
index 00000000..14779384
--- /dev/null
+++ b/testutil/integration/os/utils/evm_test.go
@@ -0,0 +1,64 @@
+package utils_test
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/os/contracts"
+ testfactory "github.com/evmos/os/testutil/integration/os/factory"
+ testhandler "github.com/evmos/os/testutil/integration/os/grpc"
+ testkeyring "github.com/evmos/os/testutil/integration/os/keyring"
+ testnetwork "github.com/evmos/os/testutil/integration/os/network"
+ "github.com/evmos/os/testutil/integration/os/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+ "github.com/stretchr/testify/require"
+)
+
+func TestGetERC20Balance(t *testing.T) {
+ keyring := testkeyring.New(1)
+ network := testnetwork.NewUnitTestNetwork(
+ testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ handler := testhandler.NewIntegrationHandler(network)
+ factory := testfactory.New(network, handler)
+
+ sender := keyring.GetKey(0)
+ mintAmount := big.NewInt(100)
+
+ // Deploy an ERC-20 contract
+ erc20Addr, err := factory.DeployContract(
+ sender.Priv,
+ evmtypes.EvmTxArgs{},
+ testfactory.ContractDeploymentData{
+ Contract: contracts.ERC20MinterBurnerDecimalsContract,
+ ConstructorArgs: []interface{}{"TestToken", "TT", uint8(18)},
+ },
+ )
+ require.NoError(t, err, "failed to deploy contract")
+ require.NoError(t, network.NextBlock(), "failed to advance block")
+
+ balance, err := utils.GetERC20Balance(network, erc20Addr, sender.Addr)
+ require.NoError(t, err, "failed to get ERC20 balance")
+ require.Equal(t, common.Big0.Int64(), balance.Int64(), "expected no balance before minting")
+
+ // Mint some tokens
+ _, err = factory.ExecuteContractCall(
+ sender.Priv,
+ evmtypes.EvmTxArgs{
+ To: &erc20Addr,
+ },
+ testfactory.CallArgs{
+ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ MethodName: "mint",
+ Args: []interface{}{sender.Addr, mintAmount},
+ },
+ )
+ require.NoError(t, err, "failed to mint tokens")
+
+ require.NoError(t, network.NextBlock(), "failed to advance block")
+
+ balance, err = utils.GetERC20Balance(network, erc20Addr, sender.Addr)
+ require.NoError(t, err, "failed to get ERC20 balance")
+ require.Equal(t, mintAmount.Int64(), balance.Int64(), "expected different balance after minting")
+}
diff --git a/testutil/integration/os/utils/genesis.go b/testutil/integration/os/utils/genesis.go
new file mode 100644
index 00000000..97cfbc0d
--- /dev/null
+++ b/testutil/integration/os/utils/genesis.go
@@ -0,0 +1,71 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package utils
+
+import (
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ testkeyring "github.com/evmos/os/testutil/integration/os/keyring"
+ "github.com/evmos/os/testutil/integration/os/network"
+ "github.com/evmos/os/utils"
+ erc20types "github.com/evmos/os/x/erc20/types"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+const (
+ // erc20TokenPairHex is the string representation of the ERC-20 token pair address.
+ erc20TokenPairHex = "0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd" //#nosec G101 -- these are not hardcoded credentials #gitleaks:allow
+ // WEVMOSContractTestnet is the WEVMOS contract address for testnet
+ WEVMOSContractTestnet = "0xcc491f589b45d4a3c679016195b3fb87d7848210"
+)
+
+func CreateGenesisWithTokenPairs(keyring testkeyring.Keyring) network.CustomGenesisState {
+ // Add all keys from the keyring to the genesis accounts as well.
+ //
+ // NOTE: This is necessary to enable the account to send EVM transactions,
+ // because the Mono ante handler checks the account balance by querying the
+ // account from the account keeper first. If these accounts are not in the genesis
+ // state, the ante handler finds a zero balance because of the missing account.
+ accs := keyring.GetAllAccAddrs()
+ genesisAccounts := make([]*authtypes.BaseAccount, len(accs))
+ for i, addr := range accs {
+ genesisAccounts[i] = &authtypes.BaseAccount{
+ Address: addr.String(),
+ PubKey: nil,
+ AccountNumber: uint64(i + 1),
+ Sequence: 1,
+ }
+ }
+
+ accGenesisState := authtypes.DefaultGenesisState()
+ for _, genesisAccount := range genesisAccounts {
+ // NOTE: This type requires to be packed into a *types.Any as seen on SDK tests,
+ // e.g. https://github.com/evmos/cosmos-sdk/blob/v0.47.5-evmos.2/x/auth/keeper/keeper_test.go#L193-L223
+ accGenesisState.Accounts = append(accGenesisState.Accounts, codectypes.UnsafePackAny(genesisAccount))
+ }
+
+ // Add token pairs to genesis
+ erc20GenesisState := erc20types.DefaultGenesisState()
+ erc20GenesisState.TokenPairs = []erc20types.TokenPair{{
+ Erc20Address: erc20TokenPairHex,
+ Denom: "xmpl",
+ Enabled: true,
+ ContractOwner: erc20types.OWNER_MODULE, // NOTE: Owner is the module account since it's a native token and was registered through governance
+ }, {
+ Erc20Address: WEVMOSContractTestnet,
+ Denom: utils.BaseDenom,
+ Enabled: true,
+ ContractOwner: erc20types.OWNER_MODULE, // NOTE: Owner is the module account since it's a native token and was registered through governance
+ }}
+
+ // Add the smart contracts to the EVM genesis
+ evmGenesisState := evmtypes.DefaultGenesisState()
+
+ // Combine module genesis states
+ return network.CustomGenesisState{
+ authtypes.ModuleName: accGenesisState,
+ erc20types.ModuleName: erc20GenesisState,
+ evmtypes.ModuleName: evmGenesisState,
+ }
+}
diff --git a/testutil/integration/os/utils/gov.go b/testutil/integration/os/utils/gov.go
new file mode 100644
index 00000000..49e1b1ed
--- /dev/null
+++ b/testutil/integration/os/utils/gov.go
@@ -0,0 +1,127 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package utils
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+ govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
+ commonfactory "github.com/evmos/os/testutil/integration/common/factory"
+ "github.com/evmos/os/testutil/integration/os/factory"
+ "github.com/evmos/os/testutil/integration/os/network"
+)
+
+// SubmitProposal is a helper function to submit a governance proposal and
+// return the proposal ID.
+func SubmitProposal(tf factory.TxFactory, network network.Network, proposerPriv cryptotypes.PrivKey, proposal govv1beta1.Content) (uint64, error) {
+ proposerAccAddr := sdk.AccAddress(proposerPriv.PubKey().Address())
+
+ msgSubmitProposal, err := govv1beta1.NewMsgSubmitProposal(
+ proposal,
+ sdk.NewCoins(sdk.NewCoin(network.GetDenom(), math.NewInt(1e18))),
+ proposerAccAddr,
+ )
+ if err != nil {
+ return 0, err
+ }
+
+ txArgs := commonfactory.CosmosTxArgs{
+ Msgs: []sdk.Msg{msgSubmitProposal},
+ }
+
+ res, err := tf.ExecuteCosmosTx(proposerPriv, txArgs)
+ if err != nil {
+ return 0, err
+ }
+
+ proposalID, err := getProposalIDFromEvents(res.Events)
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to get proposal ID from events")
+ }
+
+ err = network.NextBlock()
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to commit block after proposal")
+ }
+
+ gq := network.GetGovClient()
+ proposalRes, err := gq.Proposal(network.GetContext(), &govv1.QueryProposalRequest{ProposalId: proposalID})
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to query proposal")
+ }
+
+ if proposalRes.Proposal.Status != govv1.StatusVotingPeriod {
+ return 0, fmt.Errorf("expected proposal to be in voting period; got: %s", proposalRes.Proposal.Status.String())
+ }
+
+ return proposalRes.Proposal.GetId(), nil
+}
+
+// VoteOnProposal is a helper function to vote on a governance proposal given the private key of the voter and
+// the option to vote.
+func VoteOnProposal(tf factory.TxFactory, voterPriv cryptotypes.PrivKey, proposalID uint64, option govv1.VoteOption) error {
+ voterAccAddr := sdk.AccAddress(voterPriv.PubKey().Address())
+
+ msgVote := govv1.NewMsgVote(
+ voterAccAddr,
+ proposalID,
+ option,
+ "",
+ )
+
+ _, err := tf.ExecuteCosmosTx(voterPriv, commonfactory.CosmosTxArgs{
+ Msgs: []sdk.Msg{msgVote},
+ })
+
+ return err
+}
+
+// getProposalIDFromEvents returns the proposal ID from the events in
+// the ResponseDeliverTx.
+func getProposalIDFromEvents(events []abcitypes.Event) (uint64, error) {
+ var (
+ err error
+ found bool
+ proposalID uint64
+ )
+
+ for _, event := range events {
+ if event.Type != govtypes.EventTypeProposalDeposit {
+ continue
+ }
+
+ for _, attr := range event.Attributes {
+ if attr.Key != govtypes.AttributeKeyProposalID {
+ continue
+ }
+
+ proposalID, err = strconv.ParseUint(attr.Value, 10, 64)
+ if err != nil {
+ return 0, errorsmod.Wrap(err, "failed to parse proposal ID")
+ }
+
+ found = true
+ break
+ }
+
+ if found {
+ break
+ }
+ }
+
+ if !found {
+ return 0, errors.New("proposal deposit not found")
+ }
+
+ return proposalID, nil
+}
diff --git a/testutil/integration/os/utils/unit.go b/testutil/integration/os/utils/unit.go
new file mode 100644
index 00000000..f404fbc5
--- /dev/null
+++ b/testutil/integration/os/utils/unit.go
@@ -0,0 +1,139 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+//
+// This file contains all utility function that require the access to the unit
+// test network and should only be used in unit tests.
+package utils
+
+import (
+ "fmt"
+
+ "cosmossdk.io/math"
+ "github.com/evmos/os/utils"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ "github.com/evmos/os/testutil/integration/os/network"
+ erc20types "github.com/evmos/os/x/erc20/types"
+ inflationtypes "github.com/evmos/os/x/inflation/v1/types"
+)
+
+const (
+ TokenToMint = 1e18
+)
+
+// RegisterEvmosERC20Coins uses the UnitNetwork to register the evmos token as an
+// ERC20 token. The function performs all the required steps for the registration
+// like registering the denom trace in the transfer keeper and minting the token
+// with the bank. Returns the TokenPair or an error.
+func RegisterEvmosERC20Coins(
+ network network.UnitTestNetwork,
+ tokenReceiver sdk.AccAddress,
+) (erc20types.TokenPair, error) {
+ bondDenom := network.App.StakingKeeper.BondDenom(network.GetContext())
+
+ coin := sdk.NewCoin(utils.BaseDenom, math.NewInt(TokenToMint))
+ err := network.App.BankKeeper.MintCoins(
+ network.GetContext(),
+ inflationtypes.ModuleName,
+ sdk.NewCoins(coin),
+ )
+ if err != nil {
+ return erc20types.TokenPair{}, err
+ }
+ err = network.App.BankKeeper.SendCoinsFromModuleToAccount(
+ network.GetContext(),
+ inflationtypes.ModuleName,
+ tokenReceiver,
+ sdk.NewCoins(coin),
+ )
+ if err != nil {
+ return erc20types.TokenPair{}, err
+ }
+
+ evmosMetadata, found := network.App.BankKeeper.GetDenomMetaData(network.GetContext(), utils.BaseDenom)
+ if !found {
+ return erc20types.TokenPair{}, fmt.Errorf("expected evmos denom metadata")
+ }
+
+ _, err = network.App.Erc20Keeper.RegisterERC20Extension(network.GetContext(), evmosMetadata.Base)
+ if err != nil {
+ return erc20types.TokenPair{}, err
+ }
+
+ evmosDenomID := network.App.Erc20Keeper.GetDenomMap(network.GetContext(), bondDenom)
+ tokenPair, ok := network.App.Erc20Keeper.GetTokenPair(network.GetContext(), evmosDenomID)
+ if !ok {
+ return erc20types.TokenPair{}, fmt.Errorf("expected evmos erc20 token pair")
+ }
+
+ return tokenPair, nil
+}
+
+// RegisterIBCERC20Coins uses the UnitNetwork to register the denomTrace as an
+// ERC20 token. The function performs all the required steps for the registration
+// like registering the denom trace in the transfer keeper and minting the token
+// with the bank. Returns the TokenPair or an error.
+func RegisterIBCERC20Coins(
+ network *network.UnitTestNetwork,
+ tokenReceiver sdk.AccAddress,
+ denomTrace transfertypes.DenomTrace,
+) (erc20types.TokenPair, error) {
+ ibcDenom := denomTrace.IBCDenom()
+ network.App.TransferKeeper.SetDenomTrace(network.GetContext(), denomTrace)
+ ibcMetadata := banktypes.Metadata{
+ Name: "Generic IBC name",
+ Symbol: "IBC",
+ Description: "Generic IBC token description",
+ DenomUnits: []*banktypes.DenomUnit{
+ {
+ Denom: ibcDenom,
+ Exponent: 0,
+ Aliases: []string{ibcDenom},
+ },
+ {
+ Denom: ibcDenom,
+ Exponent: 18,
+ },
+ },
+ Display: ibcDenom,
+ Base: ibcDenom,
+ }
+
+ coin := sdk.NewCoin(ibcMetadata.Base, math.NewInt(TokenToMint))
+ err := network.App.BankKeeper.MintCoins(
+ network.GetContext(),
+ inflationtypes.ModuleName,
+ sdk.NewCoins(coin),
+ )
+ if err != nil {
+ return erc20types.TokenPair{}, err
+ }
+
+ err = network.App.BankKeeper.SendCoinsFromModuleToAccount(
+ network.GetContext(),
+ inflationtypes.ModuleName,
+ tokenReceiver,
+ sdk.NewCoins(coin),
+ )
+ if err != nil {
+ return erc20types.TokenPair{}, err
+ }
+
+ _, err = network.App.Erc20Keeper.RegisterERC20Extension(network.GetContext(), ibcMetadata.Base)
+ if err != nil {
+ return erc20types.TokenPair{}, err
+ }
+
+ ibcDenomID := network.App.Erc20Keeper.GetDenomMap(
+ network.GetContext(),
+ denomTrace.IBCDenom(),
+ )
+ tokenPair, ok := network.App.Erc20Keeper.GetTokenPair(network.GetContext(), ibcDenomID)
+ if !ok {
+ return erc20types.TokenPair{}, fmt.Errorf("expected %s erc20 token pair", ibcDenom)
+ }
+
+ return tokenPair, nil
+}
diff --git a/testutil/network/doc.go b/testutil/network/doc.go
new file mode 100644
index 00000000..6f7e9400
--- /dev/null
+++ b/testutil/network/doc.go
@@ -0,0 +1,68 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+/*
+Package network implements and exposes a fully operational in-process Tendermint
+test network that consists of at least one or potentially many validators. This
+test network can be used primarily for integration tests or unit test suites.
+
+The test network utilizes SimApp as the ABCI application and uses all the modules
+defined in the Cosmos SDK. An in-process test network can be configured with any
+number of validators as well as account funds and even custom genesis state.
+
+When creating a test network, a series of Validator objects are returned. Each
+Validator object has useful information such as their address and public key. A
+Validator will also provide its RPC, P2P, and API addresses that can be useful
+for integration testing. In addition, a Tendermint local RPC client is also provided
+which can be handy for making direct RPC calls to Tendermint.
+
+Note, due to limitations in concurrency and the design of the RPC layer in
+Tendermint, only the first Validator object will have an RPC and API client
+exposed. Due to this exact same limitation, only a single test network can exist
+at a time. A caller must be certain it calls Cleanup after it no longer needs
+the network.
+
+A typical testing flow might look like the following:
+
+ type IntegrationTestSuite struct {
+ suite.Suite
+
+ cfg testutil.Config
+ network *testutil.Network
+ }
+
+ func (s *IntegrationTestSuite) SetupSuite() {
+ s.T().Log("setting up integration test suite")
+
+ cfg := testutil.DefaultConfig()
+ cfg.NumValidators = 1
+
+ s.cfg = cfg
+ s.network = testutil.New(s.T(), cfg)
+
+ _, err := s.network.WaitForHeight(1)
+ s.Require().NoError(err)
+ }
+
+ func (s *IntegrationTestSuite) TearDownSuite() {
+ s.T().Log("tearing down integration test suite")
+
+ // This is important and must be called to ensure other tests can create
+ // a network!
+ s.network.Cleanup()
+ }
+
+ func (s *IntegrationTestSuite) TestQueryBalancesRequestHandlerFn() {
+ val := s.network.Validators[0]
+ baseURL := val.APIAddress
+
+ // Use baseURL to make API HTTP requests or use val.RPCClient to make direct
+ // Tendermint RPC calls.
+ // ...
+ }
+
+ func TestIntegrationTestSuite(t *testing.T) {
+ suite.Run(t, new(IntegrationTestSuite))
+ }
+*/
+package network
diff --git a/testutil/network/network.go b/testutil/network/network.go
new file mode 100644
index 00000000..8a7134a8
--- /dev/null
+++ b/testutil/network/network.go
@@ -0,0 +1,696 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network
+
+import (
+ "bufio"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+
+ "cosmossdk.io/math"
+ dbm "github.com/cometbft/cometbft-db"
+ tmcfg "github.com/cometbft/cometbft/config"
+ tmflags "github.com/cometbft/cometbft/libs/cli/flags"
+ "github.com/cometbft/cometbft/libs/log"
+ tmrand "github.com/cometbft/cometbft/libs/rand"
+ "github.com/cometbft/cometbft/node"
+ tmclient "github.com/cometbft/cometbft/rpc/client"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/spf13/cobra"
+ "google.golang.org/grpc"
+
+ "cosmossdk.io/simapp"
+ "cosmossdk.io/simapp/params"
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/client/tx"
+ "github.com/cosmos/cosmos-sdk/codec"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/server"
+ "github.com/cosmos/cosmos-sdk/server/api"
+ srvconfig "github.com/cosmos/cosmos-sdk/server/config"
+ servertypes "github.com/cosmos/cosmos-sdk/server/types"
+ pruningtypes "github.com/cosmos/cosmos-sdk/store/pruning/types"
+ "github.com/cosmos/cosmos-sdk/testutil"
+ simutils "github.com/cosmos/cosmos-sdk/testutil/sims"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ "github.com/cosmos/cosmos-sdk/x/genutil"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/evmos/os/crypto/hd"
+ example_app "github.com/evmos/os/example_chain"
+
+ "github.com/evmos/os/encoding"
+ "github.com/evmos/os/server/config"
+ evmostypes "github.com/evmos/os/types"
+)
+
+// package-wide network lock to only allow one test network at a time
+var lock = new(sync.Mutex)
+
+// AppConstructor defines a function which accepts a network configuration and
+// creates an ABCI Application to provide to Tendermint.
+type AppConstructor = func(val Validator) servertypes.Application
+
+// Config defines the necessary configuration used to bootstrap and start an
+// in-process local testing network.
+type Config struct {
+ KeyringOptions []keyring.Option // keyring configuration options
+ Codec codec.Codec
+ LegacyAmino *codec.LegacyAmino // TODO: Remove!
+ InterfaceRegistry codectypes.InterfaceRegistry
+ TxConfig client.TxConfig
+ AccountRetriever client.AccountRetriever
+ AppConstructor AppConstructor // the ABCI application constructor
+ GenesisState simapp.GenesisState // custom gensis state to provide
+ TimeoutCommit time.Duration // the consensus commitment timeout
+ AccountTokens math.Int // the amount of unique validator tokens (e.g. 1000node0)
+ StakingTokens math.Int // the amount of tokens each validator has available to stake
+ BondedTokens math.Int // the amount of tokens each validator stakes
+ NumValidators int // the total number of validators to create and bond
+ ChainID string // the network chain-id
+ BondDenom string // the staking bond denomination
+ MinGasPrices string // the minimum gas prices each validator will accept
+ PruningStrategy string // the pruning strategy each validator will have
+ SigningAlgo string // signing algorithm for keys
+ RPCAddress string // RPC listen address (including port)
+ JSONRPCAddress string // JSON-RPC listen address (including port)
+ APIAddress string // REST API listen address (including port)
+ GRPCAddress string // GRPC server listen address (including port)
+ EnableTMLogging bool // enable Tendermint logging to STDOUT
+ CleanupDir bool // remove base temporary directory during cleanup
+ PrintMnemonic bool // print the mnemonic of first validator as log output for testing
+}
+
+// DefaultConfig returns a sane default configuration suitable for nearly all
+// testing requirements.
+func DefaultConfig() Config {
+ encCfg := encoding.MakeConfig(example_app.ModuleBasics)
+ chainID := fmt.Sprintf("evmos_%d-1", tmrand.Int63n(9999999999999)+1)
+ return Config{
+ Codec: encCfg.Codec,
+ TxConfig: encCfg.TxConfig,
+ LegacyAmino: encCfg.Amino,
+ InterfaceRegistry: encCfg.InterfaceRegistry,
+ AccountRetriever: authtypes.AccountRetriever{},
+ AppConstructor: NewAppConstructor(encCfg, chainID),
+ GenesisState: example_app.ModuleBasics.DefaultGenesis(encCfg.Codec),
+ TimeoutCommit: 3 * time.Second,
+ ChainID: chainID,
+ NumValidators: 4,
+ BondDenom: "aevmos",
+ MinGasPrices: fmt.Sprintf("0.000006%s", evmostypes.AttoEvmos),
+ AccountTokens: sdk.TokensFromConsensusPower(1000000000000000000, evmostypes.PowerReduction),
+ StakingTokens: sdk.TokensFromConsensusPower(500000000000000000, evmostypes.PowerReduction),
+ BondedTokens: sdk.TokensFromConsensusPower(100000000000000000, evmostypes.PowerReduction),
+ PruningStrategy: pruningtypes.PruningOptionNothing,
+ CleanupDir: true,
+ SigningAlgo: string(hd.EthSecp256k1Type),
+ KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()},
+ PrintMnemonic: false,
+ }
+}
+
+// NewAppConstructor returns a new Evmos AppConstructor
+func NewAppConstructor(encodingCfg params.EncodingConfig, chainID string) AppConstructor {
+ return func(val Validator) servertypes.Application {
+ return example_app.NewEvmos(
+ val.Ctx.Logger, dbm.NewMemDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0,
+ encodingCfg,
+ simutils.NewAppOptionsWithFlagHome(val.Ctx.Config.RootDir),
+ baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.AppConfig.Pruning)),
+ baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices),
+ baseapp.SetChainID(chainID),
+ )
+ }
+}
+
+type (
+ // Network defines a local in-process testing network using SimApp. It can be
+ // configured to start any number of validators, each with its own RPC and API
+ // clients. Typically, this test network would be used in client and integration
+ // testing where user input is expected.
+ //
+ // Note, due to Tendermint constraints in regards to RPC functionality, there
+ // may only be one test network running at a time. Thus, any caller must be
+ // sure to Cleanup after testing is finished in order to allow other tests
+ // to create networks. In addition, only the first validator will have a valid
+ // RPC and API server/client.
+ Network struct {
+ Logger Logger
+ BaseDir string
+ Validators []*Validator
+
+ Config Config
+ }
+
+ // Validator defines an in-process Tendermint validator node. Through this object,
+ // a client can make RPC and API calls and interact with any client command
+ // or handler.
+ Validator struct {
+ AppConfig *config.Config
+ ClientCtx client.Context
+ Ctx *server.Context
+ Dir string
+ NodeID string
+ PubKey cryptotypes.PubKey
+ Moniker string
+ APIAddress string
+ RPCAddress string
+ P2PAddress string
+ Address sdk.AccAddress
+ ValAddress sdk.ValAddress
+ RPCClient tmclient.Client
+ JSONRPCClient *ethclient.Client
+
+ tmNode *node.Node
+ api *api.Server
+ grpc *grpc.Server
+ grpcWeb *http.Server
+ jsonrpc *http.Server
+ jsonrpcDone chan struct{}
+ }
+)
+
+// Logger is a network logger interface that exposes testnet-level Log() methods for an in-process testing network
+// This is not to be confused with logging that may happen at an individual node or validator level
+type Logger interface {
+ Log(args ...interface{})
+ Logf(format string, args ...interface{})
+}
+
+var (
+ _ Logger = (*testing.T)(nil)
+ _ Logger = (*CLILogger)(nil)
+)
+
+type CLILogger struct {
+ cmd *cobra.Command
+}
+
+func (s CLILogger) Log(args ...interface{}) {
+ s.cmd.Println(args...)
+}
+
+func (s CLILogger) Logf(format string, args ...interface{}) {
+ s.cmd.Printf(format, args...)
+}
+
+func NewCLILogger(cmd *cobra.Command) CLILogger {
+ return CLILogger{cmd}
+}
+
+// New creates a new Network for integration tests or in-process testnets run via the CLI
+func New(l Logger, baseDir string, cfg Config) (*Network, error) {
+ // only one caller/test can create and use a network at a time
+ l.Log("acquiring test network lock")
+ lock.Lock()
+
+ if !evmostypes.IsValidChainID(cfg.ChainID) {
+ return nil, fmt.Errorf("invalid chain-id: %s", cfg.ChainID)
+ }
+
+ network := &Network{
+ Logger: l,
+ BaseDir: baseDir,
+ Validators: make([]*Validator, cfg.NumValidators),
+ Config: cfg,
+ }
+
+ l.Logf("preparing test network with chain-id \"%s\"\n", cfg.ChainID)
+
+ monikers := make([]string, cfg.NumValidators)
+ nodeIDs := make([]string, cfg.NumValidators)
+ valPubKeys := make([]cryptotypes.PubKey, cfg.NumValidators)
+
+ var (
+ genAccounts []authtypes.GenesisAccount
+ genBalances []banktypes.Balance
+ genFiles []string
+ )
+
+ buf := bufio.NewReader(os.Stdin)
+
+ // generate private keys, node IDs, and initial transactions
+ for i := 0; i < cfg.NumValidators; i++ {
+ appCfg := config.DefaultConfig()
+ appCfg.Pruning = cfg.PruningStrategy
+ appCfg.MinGasPrices = cfg.MinGasPrices
+ appCfg.API.Enable = true
+ appCfg.API.Swagger = false
+ appCfg.Telemetry.Enabled = false
+ appCfg.Telemetry.GlobalLabels = [][]string{{"chain_id", cfg.ChainID}}
+
+ ctx := server.NewDefaultContext()
+ tmCfg := ctx.Config
+ tmCfg.Consensus.TimeoutCommit = cfg.TimeoutCommit
+
+ // Only allow the first validator to expose an RPC, API and gRPC
+ // server/client due to Tendermint in-process constraints.
+ apiAddr := ""
+ tmCfg.RPC.ListenAddress = ""
+ appCfg.GRPC.Enable = false
+ appCfg.GRPCWeb.Enable = false
+ appCfg.JSONRPC.Enable = false
+ apiListenAddr := ""
+ if i == 0 {
+ if cfg.APIAddress != "" {
+ apiListenAddr = cfg.APIAddress
+ } else {
+ var err error
+ apiListenAddr, _, err = server.FreeTCPAddr()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ appCfg.API.Address = apiListenAddr
+ apiURL, err := url.Parse(apiListenAddr)
+ if err != nil {
+ return nil, err
+ }
+ apiAddr = fmt.Sprintf("http://%s:%s", apiURL.Hostname(), apiURL.Port())
+
+ if cfg.RPCAddress != "" {
+ tmCfg.RPC.ListenAddress = cfg.RPCAddress
+ } else {
+ rpcAddr, _, err := server.FreeTCPAddr()
+ if err != nil {
+ return nil, err
+ }
+ tmCfg.RPC.ListenAddress = rpcAddr
+ }
+
+ if cfg.GRPCAddress != "" {
+ appCfg.GRPC.Address = cfg.GRPCAddress
+ } else {
+ _, grpcPort, err := server.FreeTCPAddr()
+ if err != nil {
+ return nil, err
+ }
+ appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort)
+ }
+ appCfg.GRPC.Enable = true
+
+ _, grpcWebPort, err := server.FreeTCPAddr()
+ if err != nil {
+ return nil, err
+ }
+ appCfg.GRPCWeb.Address = fmt.Sprintf("0.0.0.0:%s", grpcWebPort)
+ appCfg.GRPCWeb.Enable = true
+
+ if cfg.JSONRPCAddress != "" {
+ appCfg.JSONRPC.Address = cfg.JSONRPCAddress
+ } else {
+ _, jsonRPCPort, err := server.FreeTCPAddr()
+ if err != nil {
+ return nil, err
+ }
+ appCfg.JSONRPC.Address = fmt.Sprintf("0.0.0.0:%s", jsonRPCPort)
+ }
+ appCfg.JSONRPC.Enable = true
+ appCfg.JSONRPC.API = config.GetAPINamespaces()
+ }
+
+ logger := log.NewNopLogger()
+ if cfg.EnableTMLogging {
+ logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
+ logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel)
+ }
+
+ ctx.Logger = logger
+
+ nodeDirName := fmt.Sprintf("node%d", i)
+ nodeDir := filepath.Join(network.BaseDir, nodeDirName, "evmosd")
+ clientDir := filepath.Join(network.BaseDir, nodeDirName, "evmoscli")
+ gentxsDir := filepath.Join(network.BaseDir, "gentxs")
+
+ err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o750)
+ if err != nil {
+ return nil, err
+ }
+
+ err = os.MkdirAll(clientDir, 0o750)
+ if err != nil {
+ return nil, err
+ }
+
+ tmCfg.SetRoot(nodeDir)
+ tmCfg.Moniker = nodeDirName
+ monikers[i] = nodeDirName
+
+ proxyAddr, _, err := server.FreeTCPAddr()
+ if err != nil {
+ return nil, err
+ }
+ tmCfg.ProxyApp = proxyAddr
+
+ p2pAddr, _, err := server.FreeTCPAddr()
+ if err != nil {
+ return nil, err
+ }
+ tmCfg.P2P.ListenAddress = p2pAddr
+ tmCfg.P2P.AddrBookStrict = false
+ tmCfg.P2P.AllowDuplicateIP = true
+
+ nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg)
+ if err != nil {
+ return nil, err
+ }
+ nodeIDs[i] = nodeID
+ valPubKeys[i] = pubKey
+
+ kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...)
+ if err != nil {
+ return nil, err
+ }
+
+ keyringAlgos, _ := kb.SupportedAlgorithms()
+ algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
+ if err != nil {
+ return nil, err
+ }
+
+ addr, secret, err := testutil.GenerateSaveCoinKey(kb, nodeDirName, "", true, algo)
+ if err != nil {
+ return nil, err
+ }
+
+ // if PrintMnemonic is set to true, we print the first validator node's secret to the network's logger
+ // for debugging and manual testing
+ if cfg.PrintMnemonic && i == 0 {
+ printMnemonic(l, secret)
+ }
+
+ info := map[string]string{"secret": secret}
+ infoBz, err := json.Marshal(info)
+ if err != nil {
+ return nil, err
+ }
+
+ // save private key seed words
+ err = WriteFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)
+ if err != nil {
+ return nil, err
+ }
+
+ balances := sdk.NewCoins(
+ sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens),
+ sdk.NewCoin(cfg.BondDenom, cfg.StakingTokens),
+ )
+
+ genFiles = append(genFiles, tmCfg.GenesisFile())
+ genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: balances.Sort()})
+ genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0))
+
+ commission, err := math.LegacyNewDecFromStr("0.5")
+ if err != nil {
+ return nil, err
+ }
+
+ createValMsg, err := stakingtypes.NewMsgCreateValidator(
+ sdk.ValAddress(addr),
+ valPubKeys[i],
+ sdk.NewCoin(cfg.BondDenom, cfg.BondedTokens),
+ stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
+ stakingtypes.NewCommissionRates(commission, math.LegacyOneDec(), math.LegacyOneDec()),
+ math.OneInt(),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ p2pURL, err := url.Parse(p2pAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port())
+ fee := sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, math.NewInt(0)))
+ txBuilder := cfg.TxConfig.NewTxBuilder()
+ err = txBuilder.SetMsgs(createValMsg)
+ if err != nil {
+ return nil, err
+ }
+ txBuilder.SetFeeAmount(fee) // Arbitrary fee
+ txBuilder.SetGasLimit(1000000) // Need at least 100386
+ txBuilder.SetMemo(memo)
+
+ txFactory := tx.Factory{}
+ txFactory = txFactory.
+ WithChainID(cfg.ChainID).
+ WithMemo(memo).
+ WithKeybase(kb).
+ WithTxConfig(cfg.TxConfig)
+
+ if err := tx.Sign(txFactory, nodeDirName, txBuilder, true); err != nil {
+ return nil, err
+ }
+
+ txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
+ if err != nil {
+ return nil, err
+ }
+
+ if err := WriteFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil {
+ return nil, err
+ }
+
+ customAppTemplate, _ := config.AppConfig(evmostypes.AttoEvmos)
+ srvconfig.SetConfigTemplate(customAppTemplate)
+ srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg)
+
+ ctx.Viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
+ ctx.Viper.SetConfigFile(filepath.Join(nodeDir, "config/app.toml"))
+ err = ctx.Viper.ReadInConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ clientCtx := client.Context{}.
+ WithKeyringDir(clientDir).
+ WithKeyring(kb).
+ WithHomeDir(tmCfg.RootDir).
+ WithChainID(cfg.ChainID).
+ WithInterfaceRegistry(cfg.InterfaceRegistry).
+ WithCodec(cfg.Codec).
+ WithLegacyAmino(cfg.LegacyAmino).
+ WithTxConfig(cfg.TxConfig).
+ WithAccountRetriever(cfg.AccountRetriever)
+
+ network.Validators[i] = &Validator{
+ AppConfig: appCfg,
+ ClientCtx: clientCtx,
+ Ctx: ctx,
+ Dir: filepath.Join(network.BaseDir, nodeDirName),
+ NodeID: nodeID,
+ PubKey: pubKey,
+ Moniker: nodeDirName,
+ RPCAddress: tmCfg.RPC.ListenAddress,
+ P2PAddress: tmCfg.P2P.ListenAddress,
+ APIAddress: apiAddr,
+ Address: addr,
+ ValAddress: sdk.ValAddress(addr),
+ }
+ }
+
+ err := initGenFiles(cfg, genAccounts, genBalances, genFiles)
+ if err != nil {
+ return nil, err
+ }
+ err = collectGenFiles(cfg, network.Validators, network.BaseDir)
+ if err != nil {
+ return nil, err
+ }
+
+ l.Log("starting test network...")
+ for _, v := range network.Validators {
+ err := startInProcess(cfg, v)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ l.Log("started test network")
+
+ // Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any
+ // defer in a test would not be called.
+ server.TrapSignal(network.Cleanup)
+
+ return network, nil
+}
+
+// LatestHeight returns the latest height of the network or an error if the
+// query fails or no validators exist.
+func (n *Network) LatestHeight() (int64, error) {
+ if len(n.Validators) == 0 {
+ return 0, errors.New("no validators available")
+ }
+
+ status, err := n.Validators[0].RPCClient.Status(context.Background())
+ if err != nil {
+ return 0, err
+ }
+
+ return status.SyncInfo.LatestBlockHeight, nil
+}
+
+// WaitForHeight performs a blocking check where it waits for a block to be
+// committed after a given block. If that height is not reached within a timeout,
+// an error is returned. Regardless, the latest height queried is returned.
+func (n *Network) WaitForHeight(h int64) (int64, error) {
+ return n.WaitForHeightWithTimeout(h, 10*time.Second)
+}
+
+// WaitForHeightWithTimeout is the same as WaitForHeight except the caller can
+// provide a custom timeout.
+func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, error) {
+ ticker := time.NewTicker(time.Second)
+ timeout := time.After(t)
+
+ if len(n.Validators) == 0 {
+ return 0, errors.New("no validators available")
+ }
+
+ var latestHeight int64
+ val := n.Validators[0]
+
+ for {
+ select {
+ case <-timeout:
+ ticker.Stop()
+ return latestHeight, errors.New("timeout exceeded waiting for block")
+ case <-ticker.C:
+ status, err := val.RPCClient.Status(context.Background())
+ if err == nil && status != nil {
+ latestHeight = status.SyncInfo.LatestBlockHeight
+ if latestHeight >= h {
+ return latestHeight, nil
+ }
+ }
+ }
+ }
+}
+
+// WaitForNextBlock waits for the next block to be committed, returning an error
+// upon failure.
+func (n *Network) WaitForNextBlock() error {
+ lastBlock, err := n.LatestHeight()
+ if err != nil {
+ return err
+ }
+
+ _, err = n.WaitForHeight(lastBlock + 1)
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
+// Cleanup removes the root testing (temporary) directory and stops both the
+// Tendermint and API services. It allows other callers to create and start
+// test networks. This method must be called when a test is finished, typically
+// in a defer.
+func (n *Network) Cleanup() {
+ defer func() {
+ lock.Unlock()
+ n.Logger.Log("released test network lock")
+ }()
+
+ n.Logger.Log("cleaning up test network...")
+
+ for _, v := range n.Validators {
+ if v.tmNode != nil && v.tmNode.IsRunning() {
+ _ = v.tmNode.Stop()
+ }
+
+ if v.api != nil {
+ _ = v.api.Close()
+ }
+
+ if v.grpc != nil {
+ v.grpc.Stop()
+ if v.grpcWeb != nil {
+ _ = v.grpcWeb.Close()
+ }
+ }
+
+ if v.jsonrpc != nil {
+ shutdownCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancelFn()
+
+ if err := v.jsonrpc.Shutdown(shutdownCtx); err != nil {
+ v.tmNode.Logger.Error("HTTP server shutdown produced a warning", "error", err.Error())
+ } else {
+ v.tmNode.Logger.Info("HTTP server shut down, waiting 5 sec")
+ select {
+ case <-time.Tick(5 * time.Second):
+ case <-v.jsonrpcDone:
+ }
+ }
+ }
+ }
+
+ if n.Config.CleanupDir {
+ _ = os.RemoveAll(n.BaseDir)
+ }
+
+ n.Logger.Log("finished cleaning up test network")
+}
+
+// printMnemonic prints a provided mnemonic seed phrase on a network logger
+// for debugging and manual testing
+func printMnemonic(l Logger, secret string) {
+ lines := []string{
+ "THIS MNEMONIC IS FOR TESTING PURPOSES ONLY",
+ "DO NOT USE IN PRODUCTION",
+ "",
+ strings.Join(strings.Fields(secret)[0:8], " "),
+ strings.Join(strings.Fields(secret)[8:16], " "),
+ strings.Join(strings.Fields(secret)[16:24], " "),
+ }
+
+ lineLengths := make([]int, len(lines))
+ for i, line := range lines {
+ lineLengths[i] = len(line)
+ }
+
+ maxLineLength := 0
+ for _, lineLen := range lineLengths {
+ if lineLen > maxLineLength {
+ maxLineLength = lineLen
+ }
+ }
+
+ l.Log("\n")
+ l.Log(strings.Repeat("+", maxLineLength+8))
+ for _, line := range lines {
+ l.Logf("++ %s ++\n", centerText(line, maxLineLength))
+ }
+ l.Log(strings.Repeat("+", maxLineLength+8))
+ l.Log("\n")
+}
+
+// centerText centers text across a fixed width, filling either side with whitespace buffers
+func centerText(text string, width int) string {
+ textLen := len(text)
+ leftBuffer := strings.Repeat(" ", (width-textLen)/2)
+ rightBuffer := strings.Repeat(" ", (width-textLen)/2+(width-textLen)%2)
+
+ return fmt.Sprintf("%s%s%s", leftBuffer, text, rightBuffer)
+}
diff --git a/testutil/network/network_test.go b/testutil/network/network_test.go
new file mode 100644
index 00000000..33efea1c
--- /dev/null
+++ b/testutil/network/network_test.go
@@ -0,0 +1,64 @@
+//go:build norace
+// +build norace
+
+package network_test
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/suite"
+
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/evmos/os/server/config"
+ "github.com/evmos/os/testutil/network"
+
+ evmosnetwork "github.com/evmos/os/testutil/network"
+)
+
+type IntegrationTestSuite struct {
+ suite.Suite
+
+ network *network.Network
+}
+
+func (s *IntegrationTestSuite) SetupSuite() {
+ s.T().Log("setting up integration test suite")
+
+ var err error
+ cfg := evmosnetwork.DefaultConfig()
+ cfg.JSONRPCAddress = config.DefaultJSONRPCAddress
+ cfg.NumValidators = 1
+
+ s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
+ s.Require().NoError(err)
+ s.Require().NotNil(s.network)
+
+ _, err = s.network.WaitForHeight(2)
+ s.Require().NoError(err)
+
+ if s.network.Validators[0].JSONRPCClient == nil {
+ address := fmt.Sprintf("http://%s", s.network.Validators[0].AppConfig.JSONRPC.Address)
+ s.network.Validators[0].JSONRPCClient, err = ethclient.Dial(address)
+ s.Require().NoError(err)
+ }
+}
+
+func (s *IntegrationTestSuite) TearDownSuite() {
+ s.T().Log("tearing down integration test suite")
+ s.network.Cleanup()
+}
+
+func (s *IntegrationTestSuite) TestNetwork_Liveness() {
+ h, err := s.network.WaitForHeightWithTimeout(10, time.Minute)
+ s.Require().NoError(err, "expected to reach 10 blocks; got %d", h)
+
+ latestHeight, err := s.network.LatestHeight()
+ s.Require().NoError(err, "latest height failed")
+ s.Require().GreaterOrEqual(latestHeight, h)
+}
+
+func TestIntegrationTestSuite(t *testing.T) {
+ suite.Run(t, new(IntegrationTestSuite))
+}
diff --git a/testutil/network/util.go b/testutil/network/util.go
new file mode 100644
index 00000000..9b6be6cb
--- /dev/null
+++ b/testutil/network/util.go
@@ -0,0 +1,267 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package network
+
+import (
+ "encoding/json"
+ "fmt"
+ "path/filepath"
+ "time"
+
+ tmos "github.com/cometbft/cometbft/libs/os"
+ "github.com/cometbft/cometbft/node"
+ "github.com/cometbft/cometbft/p2p"
+ pvm "github.com/cometbft/cometbft/privval"
+ "github.com/cometbft/cometbft/proxy"
+ "github.com/cometbft/cometbft/rpc/client/local"
+ "github.com/cometbft/cometbft/types"
+ tmtime "github.com/cometbft/cometbft/types/time"
+ "github.com/ethereum/go-ethereum/ethclient"
+
+ "github.com/cosmos/cosmos-sdk/server/api"
+ servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
+ srvtypes "github.com/cosmos/cosmos-sdk/server/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
+ "github.com/cosmos/cosmos-sdk/x/genutil"
+ genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+ govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ inflationtypes "github.com/evmos/os/x/inflation/v1/types"
+
+ "github.com/evmos/os/server"
+ evmtypes "github.com/evmos/os/x/evm/types"
+)
+
+func startInProcess(cfg Config, val *Validator) error {
+ logger := val.Ctx.Logger
+ tmCfg := val.Ctx.Config
+ tmCfg.Instrumentation.Prometheus = false
+
+ if err := val.AppConfig.ValidateBasic(); err != nil {
+ return err
+ }
+
+ nodeKey, err := p2p.LoadOrGenNodeKey(tmCfg.NodeKeyFile())
+ if err != nil {
+ return err
+ }
+
+ app := cfg.AppConstructor(*val)
+
+ genDocProvider := node.DefaultGenesisDocProviderFunc(tmCfg)
+ tmNode, err := node.NewNode(
+ tmCfg,
+ pvm.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()),
+ nodeKey,
+ proxy.NewLocalClientCreator(app),
+ genDocProvider,
+ node.DefaultDBProvider,
+ node.DefaultMetricsProvider(tmCfg.Instrumentation),
+ logger.With("module", val.Moniker),
+ )
+ if err != nil {
+ return err
+ }
+
+ if err := tmNode.Start(); err != nil {
+ return err
+ }
+
+ val.tmNode = tmNode
+
+ if val.RPCAddress != "" {
+ val.RPCClient = local.New(tmNode)
+ }
+
+ // We'll need a RPC client if the validator exposes a gRPC or REST endpoint.
+ if val.APIAddress != "" || val.AppConfig.GRPC.Enable {
+ val.ClientCtx = val.ClientCtx.
+ WithClient(val.RPCClient)
+
+ // Add the tx service in the gRPC router.
+ app.RegisterTxService(val.ClientCtx)
+
+ // Add the tendermint queries service in the gRPC router.
+ app.RegisterTendermintService(val.ClientCtx)
+ }
+
+ if val.AppConfig.API.Enable && val.APIAddress != "" {
+ apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server"))
+ app.RegisterAPIRoutes(apiSrv, val.AppConfig.API)
+
+ errCh := make(chan error)
+
+ go func() {
+ if err := apiSrv.Start(val.AppConfig.Config); err != nil {
+ errCh <- err
+ }
+ }()
+
+ select {
+ case err := <-errCh:
+ return err
+ case <-time.After(srvtypes.ServerStartTime): // assume server started successfully
+ }
+
+ val.api = apiSrv
+ }
+
+ if val.AppConfig.GRPC.Enable {
+ grpcSrv, err := servergrpc.StartGRPCServer(val.ClientCtx, app, val.AppConfig.GRPC)
+ if err != nil {
+ return err
+ }
+
+ val.grpc = grpcSrv
+
+ if val.AppConfig.GRPCWeb.Enable {
+ val.grpcWeb, err = servergrpc.StartGRPCWeb(grpcSrv, val.AppConfig.Config)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if val.AppConfig.JSONRPC.Enable && val.AppConfig.JSONRPC.Address != "" {
+ if val.Ctx == nil || val.Ctx.Viper == nil {
+ return fmt.Errorf("validator %s context is nil", val.Moniker)
+ }
+
+ tmEndpoint := "/websocket"
+ tmRPCAddr := fmt.Sprintf("tcp://%s", val.AppConfig.GRPC.Address)
+
+ val.jsonrpc, val.jsonrpcDone, err = server.StartJSONRPC(val.Ctx, val.ClientCtx, tmRPCAddr, tmEndpoint, val.AppConfig, nil)
+ if err != nil {
+ return err
+ }
+
+ address := fmt.Sprintf("http://%s", val.AppConfig.JSONRPC.Address)
+
+ val.JSONRPCClient, err = ethclient.Dial(address)
+ if err != nil {
+ return fmt.Errorf("failed to dial JSON-RPC at %s: %w", val.AppConfig.JSONRPC.Address, err)
+ }
+ }
+
+ return nil
+}
+
+func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
+ genTime := tmtime.Now()
+
+ for i := 0; i < cfg.NumValidators; i++ {
+ tmCfg := vals[i].Ctx.Config
+
+ nodeDir := filepath.Join(outputDir, vals[i].Moniker, "evmosd")
+ gentxsDir := filepath.Join(outputDir, "gentxs")
+
+ tmCfg.Moniker = vals[i].Moniker
+ tmCfg.SetRoot(nodeDir)
+
+ initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey)
+
+ genFile := tmCfg.GenesisFile()
+ genDoc, err := types.GenesisDocFromFile(genFile)
+ if err != nil {
+ return err
+ }
+
+ appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig,
+ tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{}, genutiltypes.DefaultMessageValidator)
+ if err != nil {
+ return err
+ }
+
+ // overwrite each validator's genesis file to have a canonical genesis time
+ if err := genutil.ExportGenesisFileWithTime(genFile, cfg.ChainID, nil, appState, genTime); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string) error {
+ // set the accounts in the genesis state
+ var authGenState authtypes.GenesisState
+ cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState)
+
+ accounts, err := authtypes.PackAccounts(genAccounts)
+ if err != nil {
+ return err
+ }
+
+ authGenState.Accounts = append(authGenState.Accounts, accounts...)
+ cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState)
+
+ // set the balances in the genesis state
+ var bankGenState banktypes.GenesisState
+ bankGenState.Balances = genBalances
+ cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState)
+
+ var stakingGenState stakingtypes.GenesisState
+ cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[stakingtypes.ModuleName], &stakingGenState)
+
+ stakingGenState.Params.BondDenom = cfg.BondDenom
+ cfg.GenesisState[stakingtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&stakingGenState)
+
+ var govGenState govv1.GenesisState
+ cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[govtypes.ModuleName], &govGenState)
+
+ govGenState.Params.MinDeposit[0].Denom = cfg.BondDenom
+ cfg.GenesisState[govtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&govGenState)
+
+ // TODO: remove Evmos native implementations
+ var inflationGenState inflationtypes.GenesisState
+ cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[inflationtypes.ModuleName], &inflationGenState)
+
+ inflationGenState.Params.MintDenom = cfg.BondDenom
+ cfg.GenesisState[inflationtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&inflationGenState)
+
+ var crisisGenState crisistypes.GenesisState
+ cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[crisistypes.ModuleName], &crisisGenState)
+
+ crisisGenState.ConstantFee.Denom = cfg.BondDenom
+ cfg.GenesisState[crisistypes.ModuleName] = cfg.Codec.MustMarshalJSON(&crisisGenState)
+
+ var evmGenState evmtypes.GenesisState
+ cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[evmtypes.ModuleName], &evmGenState)
+
+ evmGenState.Params.EvmDenom = cfg.BondDenom
+ cfg.GenesisState[evmtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&evmGenState)
+
+ appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ")
+ if err != nil {
+ return err
+ }
+
+ genDoc := types.GenesisDoc{
+ ChainID: cfg.ChainID,
+ AppState: appGenStateJSON,
+ Validators: nil,
+ }
+
+ // generate empty genesis files for each validator and save
+ for i := 0; i < cfg.NumValidators; i++ {
+ if err := genDoc.SaveAs(genFiles[i]); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func WriteFile(name string, dir string, contents []byte) error {
+ file := filepath.Join(dir, name)
+
+ err := tmos.EnsureDir(dir, 0o755)
+ if err != nil {
+ return err
+ }
+
+ return tmos.WriteFile(file, contents, 0o644)
+}
diff --git a/testutil/tx/eth.go b/testutil/tx/eth.go
index 149ad350..47eb257e 100644
--- a/testutil/tx/eth.go
+++ b/testutil/tx/eth.go
@@ -18,10 +18,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
- evmtypes "github.com/evmos/evmos/v19/x/evm/types"
app "github.com/evmos/os/example_chain"
"github.com/evmos/os/server/config"
"github.com/evmos/os/testutil"
+ evmtypes "github.com/evmos/os/x/evm/types"
)
// PrepareEthTx creates an ethereum tx and signs it with the provided messages and private key.
diff --git a/x/evm/ante/ctx.go b/x/evm/ante/ctx.go
new file mode 100644
index 00000000..b14a917b
--- /dev/null
+++ b/x/evm/ante/ctx.go
@@ -0,0 +1,21 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ante
+
+import (
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+)
+
+// BuildEvmExecutionCtx builds the context needed prior to executing an EVM transaction.
+// It does the following:
+// 1. Sets an empty KV gas config for gas to be calculated by opcodes
+// and not kvstore actions
+// 2. Setup an empty transient KV gas config for transient gas to be
+// calculated by opcodes
+func BuildEvmExecutionCtx(ctx sdktypes.Context) sdktypes.Context {
+ // We need to setup an empty gas config so that the gas is consistent with Ethereum.
+ return ctx.WithKVGasConfig(storetypes.GasConfig{}).
+ WithTransientKVGasConfig(storetypes.GasConfig{})
+}
diff --git a/x/evm/ante/ctx_test.go b/x/evm/ante/ctx_test.go
new file mode 100644
index 00000000..3ea7d3e3
--- /dev/null
+++ b/x/evm/ante/ctx_test.go
@@ -0,0 +1,19 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ante_test
+
+import (
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ evmante "github.com/evmos/evmos/v19/x/evm/ante"
+)
+
+func (suite *EvmAnteTestSuite) TestBuildEvmExecutionCtx() {
+ network := network.New()
+
+ ctx := evmante.BuildEvmExecutionCtx(network.GetContext())
+
+ suite.Equal(storetypes.GasConfig{}, ctx.KVGasConfig())
+ suite.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig())
+}
diff --git a/x/evm/ante/suite_test.go b/x/evm/ante/suite_test.go
new file mode 100644
index 00000000..0fbc229e
--- /dev/null
+++ b/x/evm/ante/suite_test.go
@@ -0,0 +1,18 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package ante_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+)
+
+type EvmAnteTestSuite struct {
+ suite.Suite
+}
+
+func TestEvmAnteTestSuite(t *testing.T) {
+ suite.Run(t, &EvmAnteTestSuite{})
+}
diff --git a/x/evm/client/cli/query.go b/x/evm/client/cli/query.go
new file mode 100644
index 00000000..2b60d184
--- /dev/null
+++ b/x/evm/client/cli/query.go
@@ -0,0 +1,136 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package cli
+
+import (
+ rpctypes "github.com/evmos/evmos/v19/rpc/types"
+ "github.com/spf13/cobra"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/client/flags"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// GetQueryCmd returns the parent command for all x/bank CLi query commands.
+func GetQueryCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: types.ModuleName,
+ Short: "Querying commands for the evm module",
+ DisableFlagParsing: true,
+ SuggestionsMinimumDistance: 2,
+ RunE: client.ValidateCmd,
+ }
+
+ cmd.AddCommand(
+ GetStorageCmd(),
+ GetCodeCmd(),
+ GetParamsCmd(),
+ )
+ return cmd
+}
+
+// GetStorageCmd queries a key in an accounts storage
+func GetStorageCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "storage ADDRESS KEY",
+ Short: "Gets storage for an account with a given key and height",
+ Long: "Gets storage for an account with a given key and height. If the height is not provided, it will use the latest height from context.", //nolint:lll
+ Args: cobra.ExactArgs(2),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ queryClient := types.NewQueryClient(clientCtx)
+
+ address, err := accountToHex(args[0])
+ if err != nil {
+ return err
+ }
+
+ key := formatKeyToHash(args[1])
+
+ req := &types.QueryStorageRequest{
+ Address: address,
+ Key: key,
+ }
+
+ res, err := queryClient.Storage(rpctypes.ContextWithHeight(clientCtx.Height), req)
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+ return cmd
+}
+
+// GetCodeCmd queries the code field of a given address
+func GetCodeCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "code ADDRESS",
+ Short: "Gets code from an account",
+ Long: "Gets code from an account. If the height is not provided, it will use the latest height from context.",
+ Args: cobra.ExactArgs(1),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ queryClient := types.NewQueryClient(clientCtx)
+
+ address, err := accountToHex(args[0])
+ if err != nil {
+ return err
+ }
+
+ req := &types.QueryCodeRequest{
+ Address: address,
+ }
+
+ res, err := queryClient.Code(rpctypes.ContextWithHeight(clientCtx.Height), req)
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+ return cmd
+}
+
+// GetParamsCmd queries the fee market params
+func GetParamsCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "params",
+ Short: "Get the evm params",
+ Long: "Get the evm parameter values.",
+ Args: cobra.NoArgs,
+ RunE: func(cmd *cobra.Command, _ []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ queryClient := types.NewQueryClient(clientCtx)
+
+ res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{})
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+ return cmd
+}
diff --git a/x/evm/client/cli/tx.go b/x/evm/client/cli/tx.go
new file mode 100644
index 00000000..ada021f6
--- /dev/null
+++ b/x/evm/client/cli/tx.go
@@ -0,0 +1,113 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package cli
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/client/flags"
+ "github.com/cosmos/cosmos-sdk/client/input"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+
+ rpctypes "github.com/evmos/evmos/v19/rpc/types"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// GetTxCmd returns the transaction commands for this module
+func GetTxCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: types.ModuleName,
+ Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName),
+ DisableFlagParsing: true,
+ SuggestionsMinimumDistance: 2,
+ RunE: client.ValidateCmd,
+ }
+ cmd.AddCommand(NewRawTxCmd())
+ return cmd
+}
+
+// NewRawTxCmd command build cosmos transaction from raw ethereum transaction
+func NewRawTxCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "raw TX_HEX",
+ Short: "Build cosmos transaction from raw ethereum transaction",
+ Args: cobra.ExactArgs(1),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ data, err := hexutil.Decode(args[0])
+ if err != nil {
+ return errors.Wrap(err, "failed to decode ethereum tx hex bytes")
+ }
+
+ msg := &types.MsgEthereumTx{}
+ if err := msg.UnmarshalBinary(data); err != nil {
+ return err
+ }
+
+ if err := msg.ValidateBasic(); err != nil {
+ return err
+ }
+
+ clientCtx, err := client.GetClientTxContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ rsp, err := rpctypes.NewQueryClient(clientCtx).Params(cmd.Context(), &types.QueryParamsRequest{})
+ if err != nil {
+ return err
+ }
+
+ tx, err := msg.BuildTx(clientCtx.TxConfig.NewTxBuilder(), rsp.Params.EvmDenom)
+ if err != nil {
+ return err
+ }
+
+ if clientCtx.GenerateOnly {
+ json, err := clientCtx.TxConfig.TxJSONEncoder()(tx)
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
+ }
+
+ if !clientCtx.SkipConfirm {
+ out, err := clientCtx.TxConfig.TxJSONEncoder()(tx)
+ if err != nil {
+ return err
+ }
+
+ _, _ = fmt.Fprintf(os.Stderr, "%s\n\n", out)
+
+ buf := bufio.NewReader(os.Stdin)
+ ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf, os.Stderr)
+
+ if err != nil || !ok {
+ _, _ = fmt.Fprintf(os.Stderr, "%s\n", "canceled transaction")
+ return err
+ }
+ }
+
+ txBytes, err := clientCtx.TxConfig.TxEncoder()(tx)
+ if err != nil {
+ return err
+ }
+
+ // broadcast to a Tendermint node
+ res, err := clientCtx.BroadcastTx(txBytes)
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddTxFlagsToCmd(cmd)
+ return cmd
+}
diff --git a/x/evm/client/cli/utils.go b/x/evm/client/cli/utils.go
new file mode 100644
index 00000000..d8aac855
--- /dev/null
+++ b/x/evm/client/cli/utils.go
@@ -0,0 +1,49 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package cli
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/pkg/errors"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+func accountToHex(addr string) (string, error) {
+ if strings.HasPrefix(addr, sdk.GetConfig().GetBech32AccountAddrPrefix()) {
+ // Check to see if address is Cosmos bech32 formatted
+ toAddr, err := sdk.AccAddressFromBech32(addr)
+ if err != nil {
+ return "", errors.Wrap(err, "must provide a valid Bech32 address")
+ }
+ ethAddr := common.BytesToAddress(toAddr.Bytes())
+ return ethAddr.Hex(), nil
+ }
+
+ if !strings.HasPrefix(addr, "0x") {
+ addr = "0x" + addr
+ }
+
+ valid := common.IsHexAddress(addr)
+ if !valid {
+ return "", fmt.Errorf("%s is not a valid Ethereum or Cosmos address", addr)
+ }
+
+ ethAddr := common.HexToAddress(addr)
+
+ return ethAddr.Hex(), nil
+}
+
+func formatKeyToHash(key string) string {
+ if !strings.HasPrefix(key, "0x") {
+ key = "0x" + key
+ }
+
+ ethkey := common.HexToHash(key)
+
+ return ethkey.Hex()
+}
diff --git a/x/evm/client/cli/utils_test.go b/x/evm/client/cli/utils_test.go
new file mode 100644
index 00000000..c6a335a4
--- /dev/null
+++ b/x/evm/client/cli/utils_test.go
@@ -0,0 +1,102 @@
+package cli
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/require"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func cosmosAddressFromArg(addr string) (sdk.AccAddress, error) {
+ if strings.HasPrefix(addr, sdk.GetConfig().GetBech32AccountAddrPrefix()) {
+ // Check to see if address is Cosmos bech32 formatted
+ toAddr, err := sdk.AccAddressFromBech32(addr)
+ if err != nil {
+ return nil, errors.Wrap(err, "invalid bech32 formatted address")
+ }
+ return toAddr, nil
+ }
+
+ // Strip 0x prefix if exists
+ addr = strings.TrimPrefix(addr, "0x")
+
+ return sdk.AccAddressFromHexUnsafe(addr)
+}
+
+func TestAddressFormats(t *testing.T) {
+ testCases := []struct {
+ name string
+ addrString string
+ expectedHex string
+ expectErr bool
+ }{
+ {"Cosmos Address", "cosmos18wvvwfmq77a6d8tza4h5sfuy2yj3jj88yqg82a", "0x3B98c72760f7BBa69D62ED6f48278451251948e7", false},
+ {"hex without 0x", "3B98C72760F7BBA69D62ED6F48278451251948E7", "0x3B98c72760f7BBa69D62ED6f48278451251948e7", false},
+ {"hex with mixed casing", "3b98C72760f7BBA69D62ED6F48278451251948e7", "0x3B98c72760f7BBa69D62ED6f48278451251948e7", false},
+ {"hex with 0x", "0x3B98C72760F7BBA69D62ED6F48278451251948E7", "0x3B98c72760f7BBa69D62ED6f48278451251948e7", false},
+ {"invalid hex ethereum address", "0x3B98C72760F7BBA69D62ED6F48278451251948E", "", true},
+ {"invalid Cosmos address", "cosmos18wvvwfmq77a6d8tza4h5sfuy2yj3jj88", "", true},
+ {"empty string", "", "", true},
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ t.Run(tc.name, func(t *testing.T) {
+ hex, err := accountToHex(tc.addrString)
+ require.Equal(t, tc.expectErr, err != nil, err)
+
+ if !tc.expectErr {
+ require.Equal(t, hex, tc.expectedHex)
+ }
+ })
+ }
+}
+
+func TestCosmosToEthereumTypes(t *testing.T) {
+ hexString := "0x3B98D72760f7bbA69d62Ed6F48278451251948E7"
+ cosmosAddr, err := sdk.AccAddressFromHexUnsafe(hexString[2:])
+ require.NoError(t, err)
+
+ cosmosFormatted := cosmosAddr.String()
+
+ // Test decoding a cosmos formatted address
+ decodedHex, err := accountToHex(cosmosFormatted)
+ require.NoError(t, err)
+ require.Equal(t, hexString, decodedHex)
+
+ // Test converting cosmos address with eth address from hex
+ hexEth := common.HexToAddress(hexString)
+ convertedEth := common.BytesToAddress(cosmosAddr.Bytes())
+ require.Equal(t, hexEth, convertedEth)
+
+ // Test decoding eth hex output against hex string
+ ethDecoded, err := accountToHex(hexEth.Hex())
+ require.NoError(t, err)
+ require.Equal(t, hexString, ethDecoded)
+}
+
+func TestAddressToCosmosAddress(t *testing.T) {
+ baseAddr, err := sdk.AccAddressFromHexUnsafe("6A98D72760f7bbA69d62Ed6F48278451251948E7")
+ require.NoError(t, err)
+
+ // Test cosmos string back to address
+ cosmosFormatted, err := cosmosAddressFromArg(baseAddr.String())
+ require.NoError(t, err)
+ require.Equal(t, baseAddr, cosmosFormatted)
+
+ // Test account address from Ethereum address
+ ethAddr := common.BytesToAddress(baseAddr.Bytes())
+ ethFormatted, err := cosmosAddressFromArg(ethAddr.Hex())
+ require.NoError(t, err)
+ require.Equal(t, baseAddr, ethFormatted)
+
+ // Test encoding without the 0x prefix
+ ethFormatted, err = cosmosAddressFromArg(ethAddr.Hex()[2:])
+ require.NoError(t, err)
+ require.Equal(t, baseAddr, ethFormatted)
+}
diff --git a/x/evm/config/configurator.go b/x/evm/config/configurator.go
new file mode 100644
index 00000000..23e35a26
--- /dev/null
+++ b/x/evm/config/configurator.go
@@ -0,0 +1,75 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+//
+// The config package provides a convinient way to modify x/evm params and values.
+// Its primary purpose is to be used during application initialization.
+
+package config
+
+import (
+ "fmt"
+
+ "golang.org/x/exp/slices"
+
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// EVMConfigurator allows to extend x/evm module configurations. The configurator modifies
+// the EVM before starting the node. This means that all init genesis validations will be
+// applied to each change.
+type EVMConfigurator struct {
+ extendedEIPs map[string]func(*vm.JumpTable)
+ extendedDefaultExtraEIPs []string
+ sealed bool
+}
+
+// NewEVMConfigurator returns a pointer to a new EVMConfigurator object.
+func NewEVMConfigurator() *EVMConfigurator {
+ return &EVMConfigurator{}
+}
+
+// WithExtendedEips allows to add to the go-ethereum activators map the provided
+// EIP activators.
+func (ec *EVMConfigurator) WithExtendedEips(extendedEIPs map[string]func(*vm.JumpTable)) *EVMConfigurator {
+ ec.extendedEIPs = extendedEIPs
+ return ec
+}
+
+// WithExtendedDefaultExtraEIPs update the x/evm DefaultExtraEIPs params
+// by adding provided EIP numbers.
+func (ec *EVMConfigurator) WithExtendedDefaultExtraEIPs(eips ...string) *EVMConfigurator {
+ ec.extendedDefaultExtraEIPs = eips
+ return ec
+}
+
+// Configure apply the changes to the virtual machine configuration.
+func (ec *EVMConfigurator) Configure() error {
+ // If Configure method has been already used in the object, return
+ // an error to avoid overriding configuration.
+ if ec.sealed {
+ return fmt.Errorf("error configuring EVMConfigurator: already sealed and cannot be modified")
+ }
+
+ if err := vm.ExtendActivators(ec.extendedEIPs); err != nil {
+ return err
+ }
+
+ for _, eip := range ec.extendedDefaultExtraEIPs {
+ if slices.Contains(types.DefaultExtraEIPs, eip) {
+ return fmt.Errorf("error configuring EVMConfigurator: EIP %s is already present in the default list: %v", eip, types.DefaultExtraEIPs)
+ }
+
+ if err := vm.ValidateEIPName(eip); err != nil {
+ return fmt.Errorf("error configuring EVMConfigurator: %s", err)
+ }
+
+ types.DefaultExtraEIPs = append(types.DefaultExtraEIPs, eip)
+ }
+
+ // After applying modifier the configurator is sealed. This way, it is not possible
+ // to call the configure method twice.
+ ec.sealed = true
+
+ return nil
+}
diff --git a/x/evm/config/configurator_test.go b/x/evm/config/configurator_test.go
new file mode 100644
index 00000000..18ae698c
--- /dev/null
+++ b/x/evm/config/configurator_test.go
@@ -0,0 +1,154 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package config_test
+
+import (
+ "testing"
+
+ "github.com/evmos/evmos/v19/x/evm/config"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/stretchr/testify/require"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func TestEVMConfigurator(t *testing.T) {
+ evmConfigurator := config.NewEVMConfigurator()
+ err := evmConfigurator.Configure()
+ require.NoError(t, err)
+
+ err = evmConfigurator.Configure()
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "sealed", "expected different error")
+}
+
+func TestExtendedEips(t *testing.T) {
+ testCases := []struct {
+ name string
+ malleate func() *config.EVMConfigurator
+ expPass bool
+ errContains string
+ }{
+ {
+ "fail - eip already present in activators return an error",
+ func() *config.EVMConfigurator {
+ extendedEIPs := map[string]func(*vm.JumpTable){
+ "ethereum_3855": func(_ *vm.JumpTable) {},
+ }
+ ec := config.NewEVMConfigurator().WithExtendedEips(extendedEIPs)
+ return ec
+ },
+ false,
+ "duplicate activation",
+ },
+ {
+ "success - new default extra eips without duplication added",
+ func() *config.EVMConfigurator {
+ extendedEIPs := map[string]func(*vm.JumpTable){
+ "evmos_0": func(_ *vm.JumpTable) {},
+ }
+ ec := config.NewEVMConfigurator().WithExtendedEips(extendedEIPs)
+ return ec
+ },
+ true,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ ec := tc.malleate()
+ err := ec.Configure()
+
+ if tc.expPass {
+ require.NoError(t, err)
+ } else {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), tc.errContains, "expected different error")
+ }
+ }
+}
+
+func TestExtendedDefaultExtraEips(t *testing.T) {
+ defaultExtraEIPsSnapshot := types.DefaultExtraEIPs
+ testCases := []struct {
+ name string
+ malleate func() *config.EVMConfigurator
+ postCheck func()
+ expPass bool
+ errContains string
+ }{
+ {
+ "fail - invalid eip name",
+ func() *config.EVMConfigurator {
+ extendedDefaultExtraEIPs := []string{"os_1_000"}
+ ec := config.NewEVMConfigurator().WithExtendedDefaultExtraEIPs(extendedDefaultExtraEIPs...)
+ return ec
+ },
+ func() {
+ require.ElementsMatch(t, defaultExtraEIPsSnapshot, types.DefaultExtraEIPs)
+ types.DefaultExtraEIPs = defaultExtraEIPsSnapshot
+ },
+ false,
+ "eip name does not conform to structure",
+ },
+ {
+ "fail - duplicate default EIP entiries",
+ func() *config.EVMConfigurator {
+ extendedDefaultExtraEIPs := []string{"os_1000"}
+ types.DefaultExtraEIPs = append(types.DefaultExtraEIPs, "os_1000")
+ ec := config.NewEVMConfigurator().WithExtendedDefaultExtraEIPs(extendedDefaultExtraEIPs...)
+ return ec
+ },
+ func() {
+ require.ElementsMatch(t, append(defaultExtraEIPsSnapshot, "os_1000"), types.DefaultExtraEIPs)
+ types.DefaultExtraEIPs = defaultExtraEIPsSnapshot
+ },
+ false,
+ "EIP os_1000 is already present",
+ },
+ {
+ "success - empty default extra eip",
+ func() *config.EVMConfigurator {
+ var extendedDefaultExtraEIPs []string
+ ec := config.NewEVMConfigurator().WithExtendedDefaultExtraEIPs(extendedDefaultExtraEIPs...)
+ return ec
+ },
+ func() {
+ require.ElementsMatch(t, defaultExtraEIPsSnapshot, types.DefaultExtraEIPs)
+ },
+ true,
+ "",
+ },
+ {
+ "success - extra default eip added",
+ func() *config.EVMConfigurator {
+ extendedDefaultExtraEIPs := []string{"os_1001"}
+ ec := config.NewEVMConfigurator().WithExtendedDefaultExtraEIPs(extendedDefaultExtraEIPs...)
+ return ec
+ },
+ func() {
+ require.ElementsMatch(t, append(defaultExtraEIPsSnapshot, "os_1001"), types.DefaultExtraEIPs)
+ types.DefaultExtraEIPs = defaultExtraEIPsSnapshot
+ },
+ true,
+ "",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ ec := tc.malleate()
+ err := ec.Configure()
+
+ if tc.expPass {
+ require.NoError(t, err)
+ } else {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), tc.errContains, "expected different error")
+ }
+
+ tc.postCheck()
+ })
+ }
+}
diff --git a/x/evm/core/core/utils.go b/x/evm/core/core/utils.go
new file mode 100644
index 00000000..9db7edae
--- /dev/null
+++ b/x/evm/core/core/utils.go
@@ -0,0 +1,46 @@
+package core
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
+// This does not take the necessary gas in to account to make the transfer valid.
+func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
+ return db.GetBalance(addr).Cmp(amount) >= 0
+}
+
+// Transfer subtracts amount from sender and adds amount to recipient using the given Db
+func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
+ db.SubBalance(sender, amount)
+ db.AddBalance(recipient, amount)
+}
+
+// Message represents a message sent to a contract.
+type Message interface {
+ From() common.Address
+ To() *common.Address
+
+ GasPrice() *big.Int
+ GasFeeCap() *big.Int
+ GasTipCap() *big.Int
+ Gas() uint64
+ Value() *big.Int
+
+ Nonce() uint64
+ IsFake() bool
+ Data() []byte
+ AccessList() types.AccessList
+}
+
+// NewEVMTxContext creates a new transaction context for a single transaction.
+func NewEVMTxContext(msg Message) vm.TxContext {
+ return vm.TxContext{
+ Origin: msg.From(),
+ GasPrice: new(big.Int).Set(msg.GasPrice()),
+ }
+}
diff --git a/x/evm/core/logger/access_list_tracer.go b/x/evm/core/logger/access_list_tracer.go
new file mode 100644
index 00000000..b0d34620
--- /dev/null
+++ b/x/evm/core/logger/access_list_tracer.go
@@ -0,0 +1,168 @@
+package logger
+
+import (
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// accessList is an accumulator for the set of accounts and storage slots an EVM
+// contract execution touches.
+type accessList map[common.Address]accessListSlots
+
+// accessListSlots is an accumulator for the set of storage slots within a single
+// contract that an EVM contract execution touches.
+type accessListSlots map[common.Hash]struct{}
+
+// newAccessList creates a new accessList.
+func newAccessList() accessList {
+ return make(map[common.Address]accessListSlots)
+}
+
+// addAddress adds an address to the accesslist.
+func (al accessList) addAddress(address common.Address) {
+ // Set address if not previously present
+ if _, present := al[address]; !present {
+ al[address] = make(map[common.Hash]struct{})
+ }
+}
+
+// addSlot adds a storage slot to the accesslist.
+func (al accessList) addSlot(address common.Address, slot common.Hash) {
+ // Set address if not previously present
+ al.addAddress(address)
+
+ // Set the slot on the surely existent storage set
+ al[address][slot] = struct{}{}
+}
+
+// equal checks if the content of the current access list is the same as the
+// content of the other one.
+func (al accessList) equal(other accessList) bool {
+ // Cross reference the accounts first
+ if len(al) != len(other) {
+ return false
+ }
+ // Given that len(al) == len(other), we only need to check that
+ // all the items from al are in other.
+ for addr := range al {
+ if _, ok := other[addr]; !ok {
+ return false
+ }
+ }
+
+ // Accounts match, cross reference the storage slots too
+ for addr, slots := range al {
+ otherslots := other[addr]
+
+ if len(slots) != len(otherslots) {
+ return false
+ }
+ // Given that len(slots) == len(otherslots), we only need to check that
+ // all the items from slots are in otherslots.
+ for hash := range slots {
+ if _, ok := otherslots[hash]; !ok {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// accesslist converts the accesslist to a types.AccessList.
+func (al accessList) accessList() types.AccessList {
+ acl := make(types.AccessList, 0, len(al))
+ for addr, slots := range al {
+ tuple := types.AccessTuple{Address: addr, StorageKeys: []common.Hash{}}
+ for slot := range slots {
+ tuple.StorageKeys = append(tuple.StorageKeys, slot)
+ }
+ acl = append(acl, tuple)
+ }
+ return acl
+}
+
+// AccessListTracer is a tracer that accumulates touched accounts and storage
+// slots into an internal set.
+type AccessListTracer struct {
+ excl map[common.Address]struct{} // Set of account to exclude from the list
+ list accessList // Set of accounts and storage slots touched
+}
+
+// NewAccessListTracer creates a new tracer that can generate AccessLists.
+// An optional AccessList can be specified to occupy slots and addresses in
+// the resulting accesslist.
+func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompiles []common.Address) *AccessListTracer {
+ excl := map[common.Address]struct{}{
+ from: {}, to: {},
+ }
+ for _, addr := range precompiles {
+ excl[addr] = struct{}{}
+ }
+ list := newAccessList()
+ for _, al := range acl {
+ if _, ok := excl[al.Address]; !ok {
+ list.addAddress(al.Address)
+ }
+ for _, slot := range al.StorageKeys {
+ list.addSlot(al.Address, slot)
+ }
+ }
+ return &AccessListTracer{
+ excl: excl,
+ list: list,
+ }
+}
+
+func (a *AccessListTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+}
+
+// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
+func (a *AccessListTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ stack := scope.Stack
+ stackData := stack.Data
+ stackLen := len(stackData)
+ if (op == vm.SLOAD || op == vm.SSTORE) && stackLen >= 1 {
+ slot := common.Hash(stackData[stackLen-1].Bytes32())
+ a.list.addSlot(scope.Contract.Address(), slot)
+ }
+ if (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT) && stackLen >= 1 {
+ addr := common.Address(stackData[stackLen-1].Bytes20())
+ if _, ok := a.excl[addr]; !ok {
+ a.list.addAddress(addr)
+ }
+ }
+ if (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE) && stackLen >= 5 {
+ addr := common.Address(stackData[stackLen-2].Bytes20())
+ if _, ok := a.excl[addr]; !ok {
+ a.list.addAddress(addr)
+ }
+ }
+}
+
+func (*AccessListTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+}
+
+func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
+
+func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
+
+func (*AccessListTracer) CaptureTxStart(gasLimit uint64) {}
+
+func (*AccessListTracer) CaptureTxEnd(restGas uint64) {}
+
+// AccessList returns the current accesslist maintained by the tracer.
+func (a *AccessListTracer) AccessList() types.AccessList {
+ return a.list.accessList()
+}
+
+// Equal returns if the content of two access list traces are equal.
+func (a *AccessListTracer) Equal(other *AccessListTracer) bool {
+ return a.list.equal(other.list)
+}
diff --git a/x/evm/core/logger/logger.go b/x/evm/core/logger/logger.go
new file mode 100644
index 00000000..bcd1c2a4
--- /dev/null
+++ b/x/evm/core/logger/logger.go
@@ -0,0 +1,448 @@
+package logger
+
+import (
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "io"
+ "math/big"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/holiman/uint256"
+)
+
+// Storage represents a contract's storage.
+type Storage map[common.Hash]common.Hash
+
+// Copy duplicates the current storage.
+func (s Storage) Copy() Storage {
+ cpy := make(Storage, len(s))
+ for key, value := range s {
+ cpy[key] = value
+ }
+ return cpy
+}
+
+// Config are the configuration options for structured logger the EVM
+type Config struct {
+ EnableMemory bool // enable memory capture
+ DisableStack bool // disable stack capture
+ DisableStorage bool // disable storage capture
+ EnableReturnData bool // enable return data capture
+ Debug bool // print output during capture end
+ Limit int // maximum length of output, but zero means unlimited
+ // Chain overrides, can be used to execute a trace using future fork rules
+ Overrides *params.ChainConfig `json:"overrides,omitempty"`
+}
+
+//go:generate go run github.com/fjl/gencodec -type StructLog -field-override structLogMarshaling -out gen_structlog.go
+
+// StructLog is emitted to the EVM each cycle and lists information about the current internal state
+// prior to the execution of the statement.
+type StructLog struct {
+ Pc uint64 `json:"pc"`
+ Op vm.OpCode `json:"op"`
+ Gas uint64 `json:"gas"`
+ GasCost uint64 `json:"gasCost"`
+ Memory []byte `json:"memory,omitempty"`
+ MemorySize int `json:"memSize"`
+ Stack []uint256.Int `json:"stack"`
+ ReturnData []byte `json:"returnData,omitempty"`
+ Storage map[common.Hash]common.Hash `json:"-"`
+ Depth int `json:"depth"`
+ RefundCounter uint64 `json:"refund"`
+ Err error `json:"-"`
+}
+
+// overrides for gencodec
+type structLogMarshaling struct {
+ Gas math.HexOrDecimal64
+ GasCost math.HexOrDecimal64
+ Memory hexutil.Bytes
+ ReturnData hexutil.Bytes
+ OpName string `json:"opName"` // adds call to OpName() in MarshalJSON
+ ErrorString string `json:"error,omitempty"` // adds call to ErrorString() in MarshalJSON
+}
+
+// OpName formats the operand name in a human-readable format.
+func (s *StructLog) OpName() string {
+ return s.Op.String()
+}
+
+// ErrorString formats the log's error as a string.
+func (s *StructLog) ErrorString() string {
+ if s.Err != nil {
+ return s.Err.Error()
+ }
+ return ""
+}
+
+// StructLogger is an EVM state logger and implements EVMLogger.
+//
+// StructLogger can capture state based on the given Log configuration and also keeps
+// a track record of modified storage which is used in reporting snapshots of the
+// contract their storage.
+type StructLogger struct {
+ cfg Config
+ env *vm.EVM
+
+ storage map[common.Address]Storage
+ logs []StructLog
+ output []byte
+ err error
+ gasLimit uint64
+ usedGas uint64
+
+ interrupt uint32 // Atomic flag to signal execution interruption
+ reason error // Textual reason for the interruption
+}
+
+// NewStructLogger returns a new logger
+func NewStructLogger(cfg *Config) *StructLogger {
+ logger := &StructLogger{
+ storage: make(map[common.Address]Storage),
+ }
+ if cfg != nil {
+ logger.cfg = *cfg
+ }
+ return logger
+}
+
+// Reset clears the data held by the logger.
+func (l *StructLogger) Reset() {
+ l.storage = make(map[common.Address]Storage)
+ l.output = make([]byte, 0)
+ l.logs = l.logs[:0]
+ l.err = nil
+}
+
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
+func (l *StructLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ l.env = env
+}
+
+// CaptureState logs a new structured log message and pushes it out to the environment
+//
+// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
+func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ // If tracing was interrupted, set the error and stop
+ if atomic.LoadUint32(&l.interrupt) > 0 {
+ l.env.Cancel()
+ return
+ }
+ // check if already accumulated the specified number of logs
+ if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
+ return
+ }
+
+ memory := scope.Memory
+ stack := scope.Stack
+ contract := scope.Contract
+ // Copy a snapshot of the current memory state to a new buffer
+ var mem []byte
+ if l.cfg.EnableMemory {
+ mem = make([]byte, len(memory.Data()))
+ copy(mem, memory.Data())
+ }
+ // Copy a snapshot of the current stack state to a new buffer
+ var stck []uint256.Int
+ if !l.cfg.DisableStack {
+ stck = make([]uint256.Int, len(stack.Data))
+ for i, item := range stack.Data {
+ stck[i] = item
+ }
+ }
+ stackData := stack.Data
+ stackLen := len(stackData)
+ // Copy a snapshot of the current storage to a new container
+ var storage Storage
+ if !l.cfg.DisableStorage && (op == vm.SLOAD || op == vm.SSTORE) {
+ // initialise new changed values storage container for this contract
+ // if not present.
+ if l.storage[contract.Address()] == nil {
+ l.storage[contract.Address()] = make(Storage)
+ }
+ // capture SLOAD opcodes and record the read entry in the local storage
+ if op == vm.SLOAD && stackLen >= 1 {
+ var (
+ address = common.Hash(stackData[stackLen-1].Bytes32())
+ value = l.env.StateDB.GetState(contract.Address(), address)
+ )
+ l.storage[contract.Address()][address] = value
+ storage = l.storage[contract.Address()].Copy()
+ } else if op == vm.SSTORE && stackLen >= 2 {
+ // capture SSTORE opcodes and record the written entry in the local storage.
+ var (
+ value = common.Hash(stackData[stackLen-2].Bytes32())
+ address = common.Hash(stackData[stackLen-1].Bytes32())
+ )
+ l.storage[contract.Address()][address] = value
+ storage = l.storage[contract.Address()].Copy()
+ }
+ }
+ var rdata []byte
+ if l.cfg.EnableReturnData {
+ rdata = make([]byte, len(rData))
+ copy(rdata, rData)
+ }
+ // create a new snapshot of the EVM.
+ log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, l.env.StateDB.GetRefund(), err}
+ l.logs = append(l.logs, log)
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault
+// while running an opcode.
+func (l *StructLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
+ l.output = output
+ l.err = err
+ if l.cfg.Debug {
+ fmt.Printf("%#x\n", output)
+ if err != nil {
+ fmt.Printf(" error: %v\n", err)
+ }
+ }
+}
+
+func (l *StructLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) {
+}
+
+func (l *StructLogger) GetResult() (json.RawMessage, error) {
+ // Tracing aborted
+ if l.reason != nil {
+ return nil, l.reason
+ }
+ failed := l.err != nil
+ returnData := common.CopyBytes(l.output)
+ // Return data when successful and revert reason when reverted, otherwise empty.
+ returnVal := fmt.Sprintf("%x", returnData)
+ if failed && l.err != vm.ErrExecutionReverted {
+ returnVal = ""
+ }
+ return json.Marshal(&ExecutionResult{
+ Gas: l.usedGas,
+ Failed: failed,
+ ReturnValue: returnVal,
+ StructLogs: formatLogs(l.StructLogs()),
+ })
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (l *StructLogger) Stop(err error) {
+ l.reason = err
+ atomic.StoreUint32(&l.interrupt, 1)
+}
+
+func (l *StructLogger) CaptureTxStart(gasLimit uint64) {
+ l.gasLimit = gasLimit
+}
+
+func (l *StructLogger) CaptureTxEnd(restGas uint64) {
+ l.usedGas = l.gasLimit - restGas
+}
+
+// StructLogs returns the captured log entries.
+func (l *StructLogger) StructLogs() []StructLog { return l.logs }
+
+// Error returns the VM error captured by the trace.
+func (l *StructLogger) Error() error { return l.err }
+
+// Output returns the VM return value captured by the trace.
+func (l *StructLogger) Output() []byte { return l.output }
+
+// WriteTrace writes a formatted trace to the given writer
+func WriteTrace(writer io.Writer, logs []StructLog) {
+ for _, log := range logs {
+ fmt.Fprintf(writer, "%-16spc=%08d gas=%v cost=%v", log.Op, log.Pc, log.Gas, log.GasCost)
+ if log.Err != nil {
+ fmt.Fprintf(writer, " ERROR: %v", log.Err)
+ }
+ fmt.Fprintln(writer)
+
+ if len(log.Stack) > 0 {
+ fmt.Fprintln(writer, "Stack:")
+ for i := len(log.Stack) - 1; i >= 0; i-- {
+ fmt.Fprintf(writer, "%08d %s\n", len(log.Stack)-i-1, log.Stack[i].Hex())
+ }
+ }
+ if len(log.Memory) > 0 {
+ fmt.Fprintln(writer, "Memory:")
+ fmt.Fprint(writer, hex.Dump(log.Memory))
+ }
+ if len(log.Storage) > 0 {
+ fmt.Fprintln(writer, "Storage:")
+ for h, item := range log.Storage {
+ fmt.Fprintf(writer, "%x: %x\n", h, item)
+ }
+ }
+ if len(log.ReturnData) > 0 {
+ fmt.Fprintln(writer, "ReturnData:")
+ fmt.Fprint(writer, hex.Dump(log.ReturnData))
+ }
+ fmt.Fprintln(writer)
+ }
+}
+
+// WriteLogs writes vm logs in a readable format to the given writer
+func WriteLogs(writer io.Writer, logs []*types.Log) {
+ for _, log := range logs {
+ fmt.Fprintf(writer, "LOG%d: %x bn=%d txi=%x\n", len(log.Topics), log.Address, log.BlockNumber, log.TxIndex)
+
+ for i, topic := range log.Topics {
+ fmt.Fprintf(writer, "%08d %x\n", i, topic)
+ }
+
+ fmt.Fprint(writer, hex.Dump(log.Data))
+ fmt.Fprintln(writer)
+ }
+}
+
+type mdLogger struct {
+ out io.Writer
+ cfg *Config
+ env *vm.EVM
+}
+
+// NewMarkdownLogger creates a logger which outputs information in a format adapted
+// for human readability, and is also a valid markdown table
+func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger {
+ l := &mdLogger{out: writer, cfg: cfg}
+ if l.cfg == nil {
+ l.cfg = &Config{}
+ }
+ return l
+}
+
+func (t *mdLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ t.env = env
+ if !create {
+ fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
+ from.String(), to.String(),
+ input, gas, value)
+ } else {
+ fmt.Fprintf(t.out, "From: `%v`\nCreate at: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
+ from.String(), to.String(),
+ input, gas, value)
+ }
+
+ fmt.Fprintf(t.out, `
+| Pc | Op | Cost | Stack | RStack | Refund |
+|-------|-------------|------|-----------|-----------|---------|
+`)
+}
+
+// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
+func (t *mdLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ stack := scope.Stack
+ fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
+
+ if !t.cfg.DisableStack {
+ // format stack
+ var a []string
+ for _, elem := range stack.Data {
+ a = append(a, elem.Hex())
+ }
+ b := fmt.Sprintf("[%v]", strings.Join(a, ","))
+ fmt.Fprintf(t.out, "%10v |", b)
+ }
+ fmt.Fprintf(t.out, "%10v |", t.env.StateDB.GetRefund())
+ fmt.Fprintln(t.out, "")
+ if err != nil {
+ fmt.Fprintf(t.out, "Error: %v\n", err)
+ }
+}
+
+func (t *mdLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+ fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
+}
+
+func (t *mdLogger) CaptureEnd(output []byte, gasUsed uint64, tm time.Duration, err error) {
+ fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n",
+ output, gasUsed, err)
+}
+
+func (t *mdLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
+
+func (*mdLogger) CaptureTxStart(gasLimit uint64) {}
+
+func (*mdLogger) CaptureTxEnd(restGas uint64) {}
+
+// ExecutionResult groups all structured logs emitted by the EVM
+// while replaying a transaction in debug mode as well as transaction
+// execution status, the amount of gas used and the return value
+type ExecutionResult struct {
+ Gas uint64 `json:"gas"`
+ Failed bool `json:"failed"`
+ ReturnValue string `json:"returnValue"`
+ StructLogs []StructLogRes `json:"structLogs"`
+}
+
+// StructLogRes stores a structured log emitted by the EVM while replaying a
+// transaction in debug mode
+type StructLogRes struct {
+ Pc uint64 `json:"pc"`
+ Op string `json:"op"`
+ Gas uint64 `json:"gas"`
+ GasCost uint64 `json:"gasCost"`
+ Depth int `json:"depth"`
+ Error string `json:"error,omitempty"`
+ Stack *[]string `json:"stack,omitempty"`
+ Memory *[]string `json:"memory,omitempty"`
+ Storage *map[string]string `json:"storage,omitempty"`
+ RefundCounter uint64 `json:"refund,omitempty"`
+}
+
+// formatLogs formats EVM returned structured logs for json output
+func formatLogs(logs []StructLog) []StructLogRes {
+ formatted := make([]StructLogRes, len(logs))
+ for index, trace := range logs {
+ formatted[index] = StructLogRes{
+ Pc: trace.Pc,
+ Op: trace.Op.String(),
+ Gas: trace.Gas,
+ GasCost: trace.GasCost,
+ Depth: trace.Depth,
+ Error: trace.ErrorString(),
+ RefundCounter: trace.RefundCounter,
+ }
+ if trace.Stack != nil {
+ stack := make([]string, len(trace.Stack))
+ for i, stackValue := range trace.Stack {
+ stack[i] = stackValue.Hex()
+ }
+ formatted[index].Stack = &stack
+ }
+ if trace.Memory != nil {
+ memory := make([]string, 0, (len(trace.Memory)+31)/32)
+ for i := 0; i+32 <= len(trace.Memory); i += 32 {
+ memory = append(memory, fmt.Sprintf("%x", trace.Memory[i:i+32]))
+ }
+ formatted[index].Memory = &memory
+ }
+ if trace.Storage != nil {
+ storage := make(map[string]string)
+ for i, storageValue := range trace.Storage {
+ storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue)
+ }
+ formatted[index].Storage = &storage
+ }
+ }
+ return formatted
+}
diff --git a/x/evm/core/logger/logger_json.go b/x/evm/core/logger/logger_json.go
new file mode 100644
index 00000000..6b2c96ab
--- /dev/null
+++ b/x/evm/core/logger/logger_json.go
@@ -0,0 +1,88 @@
+package logger
+
+import (
+ "encoding/json"
+ "io"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+type JSONLogger struct {
+ encoder *json.Encoder
+ cfg *Config
+ env *vm.EVM
+}
+
+// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
+// into the provided stream.
+func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger {
+ l := &JSONLogger{encoder: json.NewEncoder(writer), cfg: cfg}
+ if l.cfg == nil {
+ l.cfg = &Config{}
+ }
+ return l
+}
+
+func (l *JSONLogger) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ l.env = env
+}
+
+func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+ // TODO: Add rData to this interface as well
+ l.CaptureState(pc, op, gas, cost, scope, nil, depth, err)
+}
+
+// CaptureState outputs state information on the logger.
+func (l *JSONLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ memory := scope.Memory
+ stack := scope.Stack
+
+ log := StructLog{
+ Pc: pc,
+ Op: op,
+ Gas: gas,
+ GasCost: cost,
+ MemorySize: memory.Len(),
+ Depth: depth,
+ RefundCounter: l.env.StateDB.GetRefund(),
+ Err: err,
+ }
+ if l.cfg.EnableMemory {
+ log.Memory = memory.Data()
+ }
+ if !l.cfg.DisableStack {
+ log.Stack = stack.Data
+ }
+ if l.cfg.EnableReturnData {
+ log.ReturnData = rData
+ }
+ l.encoder.Encode(log)
+}
+
+// CaptureEnd is triggered at end of execution.
+func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
+ type endLog struct {
+ Output string `json:"output"`
+ GasUsed math.HexOrDecimal64 `json:"gasUsed"`
+ Time time.Duration `json:"time"`
+ Err string `json:"error,omitempty"`
+ }
+ var errMsg string
+ if err != nil {
+ errMsg = err.Error()
+ }
+ l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), t, errMsg})
+}
+
+func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
+
+func (l *JSONLogger) CaptureTxStart(gasLimit uint64) {}
+
+func (l *JSONLogger) CaptureTxEnd(restGas uint64) {}
diff --git a/x/evm/core/tracers/js/bigint.go b/x/evm/core/tracers/js/bigint.go
new file mode 100644
index 00000000..9aeb3304
--- /dev/null
+++ b/x/evm/core/tracers/js/bigint.go
@@ -0,0 +1,20 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package js
+
+// bigIntegerJS is the minified version of https://github.com/peterolson/BigInteger.js.
+const bigIntegerJS = `var bigInt=function(undefined){"use strict";var BASE=1e7,LOG_BASE=7,MAX_INT=9007199254740992,MAX_INT_ARR=smallToArray(MAX_INT),LOG_MAX_INT=Math.log(MAX_INT);function Integer(v,radix){if(typeof v==="undefined")return Integer[0];if(typeof radix!=="undefined")return+radix===10?parseValue(v):parseBase(v,radix);return parseValue(v)}function BigInteger(value,sign){this.value=value;this.sign=sign;this.isSmall=false}BigInteger.prototype=Object.create(Integer.prototype);function SmallInteger(value){this.value=value;this.sign=value<0;this.isSmall=true}SmallInteger.prototype=Object.create(Integer.prototype);function isPrecise(n){return-MAX_INT0)return Math.floor(n);return Math.ceil(n)}function add(a,b){var l_a=a.length,l_b=b.length,r=new Array(l_a),carry=0,base=BASE,sum,i;for(i=0;i=base?1:0;r[i]=sum-carry*base}while(i0)r.push(carry);return r}function addAny(a,b){if(a.length>=b.length)return add(a,b);return add(b,a)}function addSmall(a,carry){var l=a.length,r=new Array(l),base=BASE,sum,i;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}BigInteger.prototype.add=function(v){var n=parseValue(v);if(this.sign!==n.sign){return this.subtract(n.negate())}var a=this.value,b=n.value;if(n.isSmall){return new BigInteger(addSmall(a,Math.abs(b)),this.sign)}return new BigInteger(addAny(a,b),this.sign)};BigInteger.prototype.plus=BigInteger.prototype.add;SmallInteger.prototype.add=function(v){var n=parseValue(v);var a=this.value;if(a<0!==n.sign){return this.subtract(n.negate())}var b=n.value;if(n.isSmall){if(isPrecise(a+b))return new SmallInteger(a+b);b=smallToArray(Math.abs(b))}return new BigInteger(addSmall(b,Math.abs(a)),a<0)};SmallInteger.prototype.plus=SmallInteger.prototype.add;function subtract(a,b){var a_l=a.length,b_l=b.length,r=new Array(a_l),borrow=0,base=BASE,i,difference;for(i=0;i=0){value=subtract(a,b)}else{value=subtract(b,a);sign=!sign}value=arrayToSmall(value);if(typeof value==="number"){if(sign)value=-value;return new SmallInteger(value)}return new BigInteger(value,sign)}function subtractSmall(a,b,sign){var l=a.length,r=new Array(l),carry=-b,base=BASE,i,difference;for(i=0;i=0)};SmallInteger.prototype.minus=SmallInteger.prototype.subtract;BigInteger.prototype.negate=function(){return new BigInteger(this.value,!this.sign)};SmallInteger.prototype.negate=function(){var sign=this.sign;var small=new SmallInteger(-this.value);small.sign=!sign;return small};BigInteger.prototype.abs=function(){return new BigInteger(this.value,false)};SmallInteger.prototype.abs=function(){return new SmallInteger(Math.abs(this.value))};function multiplyLong(a,b){var a_l=a.length,b_l=b.length,l=a_l+b_l,r=createArray(l),base=BASE,product,carry,i,a_i,b_j;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}function shiftLeft(x,n){var r=[];while(n-- >0)r.push(0);return r.concat(x)}function multiplyKaratsuba(x,y){var n=Math.max(x.length,y.length);if(n<=30)return multiplyLong(x,y);n=Math.ceil(n/2);var b=x.slice(n),a=x.slice(0,n),d=y.slice(n),c=y.slice(0,n);var ac=multiplyKaratsuba(a,c),bd=multiplyKaratsuba(b,d),abcd=multiplyKaratsuba(addAny(a,b),addAny(c,d));var product=addAny(addAny(ac,shiftLeft(subtract(subtract(abcd,ac),bd),n)),shiftLeft(bd,2*n));trim(product);return product}function useKaratsuba(l1,l2){return-.012*l1-.012*l2+15e-6*l1*l2>0}BigInteger.prototype.multiply=function(v){var n=parseValue(v),a=this.value,b=n.value,sign=this.sign!==n.sign,abs;if(n.isSmall){if(b===0)return Integer[0];if(b===1)return this;if(b===-1)return this.negate();abs=Math.abs(b);if(abs=0;shift--){quotientDigit=base-1;if(remainder[shift+b_l]!==divisorMostSignificantDigit){quotientDigit=Math.floor((remainder[shift+b_l]*base+remainder[shift+b_l-1])/divisorMostSignificantDigit)}carry=0;borrow=0;l=divisor.length;for(i=0;ib_l){highx=(highx+1)*base}guess=Math.ceil(highx/highy);do{check=multiplySmall(b,guess);if(compareAbs(check,part)<=0)break;guess--}while(guess);result.push(guess);part=subtract(part,check)}result.reverse();return[arrayToSmall(result),arrayToSmall(part)]}function divModSmall(value,lambda){var length=value.length,quotient=createArray(length),base=BASE,i,q,remainder,divisor;remainder=0;for(i=length-1;i>=0;--i){divisor=remainder*base+value[i];q=truncate(divisor/lambda);remainder=divisor-q*lambda;quotient[i]=q|0}return[quotient,remainder|0]}function divModAny(self,v){var value,n=parseValue(v);var a=self.value,b=n.value;var quotient;if(b===0)throw new Error("Cannot divide by zero");if(self.isSmall){if(n.isSmall){return[new SmallInteger(truncate(a/b)),new SmallInteger(a%b)]}return[Integer[0],self]}if(n.isSmall){if(b===1)return[self,Integer[0]];if(b==-1)return[self.negate(),Integer[0]];var abs=Math.abs(b);if(absb.length?1:-1}for(var i=a.length-1;i>=0;i--){if(a[i]!==b[i])return a[i]>b[i]?1:-1}return 0}BigInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall)return 1;return compareAbs(a,b)};SmallInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=Math.abs(this.value),b=n.value;if(n.isSmall){b=Math.abs(b);return a===b?0:a>b?1:-1}return-1};BigInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(this.sign!==n.sign){return n.sign?1:-1}if(n.isSmall){return this.sign?-1:1}return compareAbs(a,b)*(this.sign?-1:1)};BigInteger.prototype.compareTo=BigInteger.prototype.compare;SmallInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall){return a==b?0:a>b?1:-1}if(a<0!==n.sign){return a<0?-1:1}return a<0?1:-1};SmallInteger.prototype.compareTo=SmallInteger.prototype.compare;BigInteger.prototype.equals=function(v){return this.compare(v)===0};SmallInteger.prototype.eq=SmallInteger.prototype.equals=BigInteger.prototype.eq=BigInteger.prototype.equals;BigInteger.prototype.notEquals=function(v){return this.compare(v)!==0};SmallInteger.prototype.neq=SmallInteger.prototype.notEquals=BigInteger.prototype.neq=BigInteger.prototype.notEquals;BigInteger.prototype.greater=function(v){return this.compare(v)>0};SmallInteger.prototype.gt=SmallInteger.prototype.greater=BigInteger.prototype.gt=BigInteger.prototype.greater;BigInteger.prototype.lesser=function(v){return this.compare(v)<0};SmallInteger.prototype.lt=SmallInteger.prototype.lesser=BigInteger.prototype.lt=BigInteger.prototype.lesser;BigInteger.prototype.greaterOrEquals=function(v){return this.compare(v)>=0};SmallInteger.prototype.geq=SmallInteger.prototype.greaterOrEquals=BigInteger.prototype.geq=BigInteger.prototype.greaterOrEquals;BigInteger.prototype.lesserOrEquals=function(v){return this.compare(v)<=0};SmallInteger.prototype.leq=SmallInteger.prototype.lesserOrEquals=BigInteger.prototype.leq=BigInteger.prototype.lesserOrEquals;BigInteger.prototype.isEven=function(){return(this.value[0]&1)===0};SmallInteger.prototype.isEven=function(){return(this.value&1)===0};BigInteger.prototype.isOdd=function(){return(this.value[0]&1)===1};SmallInteger.prototype.isOdd=function(){return(this.value&1)===1};BigInteger.prototype.isPositive=function(){return!this.sign};SmallInteger.prototype.isPositive=function(){return this.value>0};BigInteger.prototype.isNegative=function(){return this.sign};SmallInteger.prototype.isNegative=function(){return this.value<0};BigInteger.prototype.isUnit=function(){return false};SmallInteger.prototype.isUnit=function(){return Math.abs(this.value)===1};BigInteger.prototype.isZero=function(){return false};SmallInteger.prototype.isZero=function(){return this.value===0};BigInteger.prototype.isDivisibleBy=function(v){var n=parseValue(v);var value=n.value;if(value===0)return false;if(value===1)return true;if(value===2)return this.isEven();return this.mod(n).equals(Integer[0])};SmallInteger.prototype.isDivisibleBy=BigInteger.prototype.isDivisibleBy;function isBasicPrime(v){var n=v.abs();if(n.isUnit())return false;if(n.equals(2)||n.equals(3)||n.equals(5))return true;if(n.isEven()||n.isDivisibleBy(3)||n.isDivisibleBy(5))return false;if(n.lesser(25))return true}BigInteger.prototype.isPrime=function(){var isPrime=isBasicPrime(this);if(isPrime!==undefined)return isPrime;var n=this.abs(),nPrev=n.prev();var a=[2,3,5,7,11,13,17,19],b=nPrev,d,t,i,x;while(b.isEven())b=b.divide(2);for(i=0;i-MAX_INT)return new SmallInteger(value-1);return new BigInteger(MAX_INT_ARR,true)};var powersOfTwo=[1];while(2*powersOfTwo[powersOfTwo.length-1]<=BASE)powersOfTwo.push(2*powersOfTwo[powersOfTwo.length-1]);var powers2Length=powersOfTwo.length,highestPower2=powersOfTwo[powers2Length-1];function shift_isSmall(n){return(typeof n==="number"||typeof n==="string")&&+Math.abs(n)<=BASE||n instanceof BigInteger&&n.value.length<=1}BigInteger.prototype.shiftLeft=function(n){if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftRight(-n);var result=this;while(n>=powers2Length){result=result.multiply(highestPower2);n-=powers2Length-1}return result.multiply(powersOfTwo[n])};SmallInteger.prototype.shiftLeft=BigInteger.prototype.shiftLeft;BigInteger.prototype.shiftRight=function(n){var remQuo;if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftLeft(-n);var result=this;while(n>=powers2Length){if(result.isZero())return result;remQuo=divModAny(result,highestPower2);result=remQuo[1].isNegative()?remQuo[0].prev():remQuo[0];n-=powers2Length-1}remQuo=divModAny(result,powersOfTwo[n]);return remQuo[1].isNegative()?remQuo[0].prev():remQuo[0]};SmallInteger.prototype.shiftRight=BigInteger.prototype.shiftRight;function bitwise(x,y,fn){y=parseValue(y);var xSign=x.isNegative(),ySign=y.isNegative();var xRem=xSign?x.not():x,yRem=ySign?y.not():y;var xDigit=0,yDigit=0;var xDivMod=null,yDivMod=null;var result=[];while(!xRem.isZero()||!yRem.isZero()){xDivMod=divModAny(xRem,highestPower2);xDigit=xDivMod[1].toJSNumber();if(xSign){xDigit=highestPower2-1-xDigit}yDivMod=divModAny(yRem,highestPower2);yDigit=yDivMod[1].toJSNumber();if(ySign){yDigit=highestPower2-1-yDigit}xRem=xDivMod[0];yRem=yDivMod[0];result.push(fn(xDigit,yDigit))}var sum=fn(xSign?1:0,ySign?1:0)!==0?bigInt(-1):bigInt(0);for(var i=result.length-1;i>=0;i-=1){sum=sum.multiply(highestPower2).add(bigInt(result[i]))}return sum}BigInteger.prototype.not=function(){return this.negate().prev()};SmallInteger.prototype.not=BigInteger.prototype.not;BigInteger.prototype.and=function(n){return bitwise(this,n,function(a,b){return a&b})};SmallInteger.prototype.and=BigInteger.prototype.and;BigInteger.prototype.or=function(n){return bitwise(this,n,function(a,b){return a|b})};SmallInteger.prototype.or=BigInteger.prototype.or;BigInteger.prototype.xor=function(n){return bitwise(this,n,function(a,b){return a^b})};SmallInteger.prototype.xor=BigInteger.prototype.xor;var LOBMASK_I=1<<30,LOBMASK_BI=(BASE&-BASE)*(BASE&-BASE)|LOBMASK_I;function roughLOB(n){var v=n.value,x=typeof v==="number"?v|LOBMASK_I:v[0]+v[1]*BASE|LOBMASK_BI;return x&-x}function max(a,b){a=parseValue(a);b=parseValue(b);return a.greater(b)?a:b}function min(a,b){a=parseValue(a);b=parseValue(b);return a.lesser(b)?a:b}function gcd(a,b){a=parseValue(a).abs();b=parseValue(b).abs();if(a.equals(b))return a;if(a.isZero())return b;if(b.isZero())return a;var c=Integer[1],d,t;while(a.isEven()&&b.isEven()){d=Math.min(roughLOB(a),roughLOB(b));a=a.divide(d);b=b.divide(d);c=c.multiply(d)}while(a.isEven()){a=a.divide(roughLOB(a))}do{while(b.isEven()){b=b.divide(roughLOB(b))}if(a.greater(b)){t=b;b=a;a=t}b=b.subtract(a)}while(!b.isZero());return c.isUnit()?a:a.multiply(c)}function lcm(a,b){a=parseValue(a).abs();b=parseValue(b).abs();return a.divide(gcd(a,b)).multiply(b)}function randBetween(a,b){a=parseValue(a);b=parseValue(b);var low=min(a,b),high=max(a,b);var range=high.subtract(low).add(1);if(range.isSmall)return low.add(Math.floor(Math.random()*range));var length=range.value.length-1;var result=[],restricted=true;for(var i=length;i>=0;i--){var top=restricted?range.value[i]:BASE;var digit=truncate(Math.random()*top);result.unshift(digit);if(digit=absBase){if(c==="1"&&absBase===1)continue;throw new Error(c+" is not a valid digit in base "+base+".")}else if(c.charCodeAt(0)-87>=absBase){throw new Error(c+" is not a valid digit in base "+base+".")}}}if(2<=base&&base<=36){if(length<=LOG_MAX_INT/Math.log(base)){var result=parseInt(text,base);if(isNaN(result)){throw new Error(c+" is not a valid digit in base "+base+".")}return new SmallInteger(parseInt(text,base))}}base=parseValue(base);var digits=[];var isNegative=text[0]==="-";for(i=isNegative?1:0;i");digits.push(parseValue(text.slice(start+1,i)))}else throw new Error(c+" is not a valid character")}return parseBaseFromArray(digits,base,isNegative)};function parseBaseFromArray(digits,base,isNegative){var val=Integer[0],pow=Integer[1],i;for(i=digits.length-1;i>=0;i--){val=val.add(digits[i].times(pow));pow=pow.times(base)}return isNegative?val.negate():val}function stringify(digit){var v=digit.value;if(typeof v==="number")v=[v];if(v.length===1&&v[0]<=35){return"0123456789abcdefghijklmnopqrstuvwxyz".charAt(v[0])}return"<"+v+">"}function toBase(n,base){base=bigInt(base);if(base.isZero()){if(n.isZero())return"0";throw new Error("Cannot convert nonzero numbers to base 0.")}if(base.equals(-1)){if(n.isZero())return"0";if(n.isNegative())return new Array(1-n).join("10");return"1"+new Array(+n).join("01")}var minusSign="";if(n.isNegative()&&base.isPositive()){minusSign="-";n=n.abs()}if(base.equals(1)){if(n.isZero())return"0";return minusSign+new Array(+n+1).join(1)}var out=[];var left=n,divmod;while(left.isNegative()||left.compareAbs(base)>=0){divmod=left.divmod(base);left=divmod.quotient;var digit=divmod.remainder;if(digit.isNegative()){digit=base.minus(digit).abs();left=left.next()}out.push(stringify(digit))}out.push(stringify(left));return minusSign+out.reverse().join("")}BigInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!==10)return toBase(this,radix);var v=this.value,l=v.length,str=String(v[--l]),zeros="0000000",digit;while(--l>=0){digit=String(v[l]);str+=zeros.slice(digit.length)+digit}var sign=this.sign?"-":"";return sign+str};SmallInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!=10)return toBase(this,radix);return String(this.value)};BigInteger.prototype.toJSON=SmallInteger.prototype.toJSON=function(){return this.toString()};BigInteger.prototype.valueOf=function(){return+this.toString()};BigInteger.prototype.toJSNumber=BigInteger.prototype.valueOf;SmallInteger.prototype.valueOf=function(){return this.value};SmallInteger.prototype.toJSNumber=SmallInteger.prototype.valueOf;function parseStringValue(v){if(isPrecise(+v)){var x=+v;if(x===truncate(x))return new SmallInteger(x);throw"Invalid integer: "+v}var sign=v[0]==="-";if(sign)v=v.slice(1);var split=v.split(/e/i);if(split.length>2)throw new Error("Invalid integer: "+split.join("e"));if(split.length===2){var exp=split[1];if(exp[0]==="+")exp=exp.slice(1);exp=+exp;if(exp!==truncate(exp)||!isPrecise(exp))throw new Error("Invalid integer: "+exp+" is not a valid exponent.");var text=split[0];var decimalPlace=text.indexOf(".");if(decimalPlace>=0){exp-=text.length-decimalPlace-1;text=text.slice(0,decimalPlace)+text.slice(decimalPlace+1)}if(exp<0)throw new Error("Cannot include negative exponent part for integers");text+=new Array(exp+1).join("0");v=text}var isValid=/^([0-9][0-9]*)$/.test(v);if(!isValid)throw new Error("Invalid integer: "+v);var r=[],max=v.length,l=LOG_BASE,min=max-l;while(max>0){r.push(+v.slice(min,max));min-=l;if(min<0)min=0;max-=l}trim(r);return new BigInteger(r,sign)}function parseNumberValue(v){if(isPrecise(v)){if(v!==truncate(v))throw new Error(v+" is not an integer.");return new SmallInteger(v)}return parseStringValue(v.toString())}function parseValue(v){if(typeof v==="number"){return parseNumberValue(v)}if(typeof v==="string"){return parseStringValue(v)}return v}for(var i=0;i<1e3;i++){Integer[i]=new SmallInteger(i);if(i>0)Integer[-i]=new SmallInteger(-i)}Integer.one=Integer[1];Integer.zero=Integer[0];Integer.minusOne=Integer[-1];Integer.max=max;Integer.min=min;Integer.gcd=gcd;Integer.lcm=lcm;Integer.isInstance=function(x){return x instanceof BigInteger||x instanceof SmallInteger};Integer.randBetween=randBetween;Integer.fromArray=function(digits,base,isNegative){return parseBaseFromArray(digits.map(parseValue),parseValue(base||10),isNegative)};return Integer}();if(typeof module!=="undefined"&&module.hasOwnProperty("exports")){module.exports=bigInt}if(typeof define==="function"&&define.amd){define("big-integer",[],function(){return bigInt})}; bigInt`
diff --git a/x/evm/core/tracers/js/goja.go b/x/evm/core/tracers/js/goja.go
new file mode 100644
index 00000000..9f97605c
--- /dev/null
+++ b/x/evm/core/tracers/js/goja.go
@@ -0,0 +1,962 @@
+// Copyright 2022 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package js
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math/big"
+ "time"
+
+ "github.com/dop251/goja"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+ jsassets "github.com/evmos/evmos/v19/x/evm/core/tracers/js/internal/tracers"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+var assetTracers = make(map[string]string)
+
+// init retrieves the JavaScript transaction tracers included in go-ethereum.
+func init() {
+ var err error
+ assetTracers, err = jsassets.Load()
+ if err != nil {
+ panic(err)
+ }
+ tracers.RegisterLookup(true, newJsTracer)
+}
+
+// bigIntProgram is compiled once and the exported function mostly invoked to convert
+// hex strings into big ints.
+var bigIntProgram = goja.MustCompile("bigInt", bigIntegerJS, false)
+
+type (
+ toBigFn = func(vm *goja.Runtime, val string) (goja.Value, error)
+ toBufFn = func(vm *goja.Runtime, val []byte) (goja.Value, error)
+ fromBufFn = func(vm *goja.Runtime, buf goja.Value, allowString bool) ([]byte, error)
+)
+
+func toBuf(vm *goja.Runtime, bufType goja.Value, val []byte) (goja.Value, error) {
+ // bufType is usually Uint8Array. This is equivalent to `new Uint8Array(val)` in JS.
+ return vm.New(bufType, vm.ToValue(vm.NewArrayBuffer(val)))
+}
+
+func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString bool) ([]byte, error) {
+ obj := buf.ToObject(vm)
+ switch obj.ClassName() {
+ case "String":
+ if !allowString {
+ break
+ }
+ return common.FromHex(obj.String()), nil
+
+ case "Array":
+ var b []byte
+ if err := vm.ExportTo(buf, &b); err != nil {
+ return nil, err
+ }
+ return b, nil
+
+ case "Object":
+ if !obj.Get("constructor").SameAs(bufType) {
+ break
+ }
+ b := obj.Get("buffer").Export().(goja.ArrayBuffer).Bytes()
+ return b, nil
+ }
+ return nil, fmt.Errorf("invalid buffer type")
+}
+
+// jsTracer is an implementation of the Tracer interface which evaluates
+// JS functions on the relevant EVM hooks. It uses Goja as its JS engine.
+type jsTracer struct {
+ vm *goja.Runtime
+ env *vm.EVM
+ toBig toBigFn // Converts a hex string into a JS bigint
+ toBuf toBufFn // Converts a []byte into a JS buffer
+ fromBuf fromBufFn // Converts an array, hex string or Uint8Array to a []byte
+ ctx map[string]goja.Value // KV-bag passed to JS in `result`
+ activePrecompiles []common.Address // List of active precompiles at current block
+ traceStep bool // True if tracer object exposes a `step()` method
+ traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods
+ gasLimit uint64 // Amount of gas bought for the whole tx
+ err error // Any error that should stop tracing
+ obj *goja.Object // Trace object
+
+ // Methods exposed by tracer
+ result goja.Callable
+ fault goja.Callable
+ step goja.Callable
+ enter goja.Callable
+ exit goja.Callable
+
+ // Underlying structs being passed into JS
+ log *steplog
+ frame *callframe
+ frameResult *callframeResult
+
+ // Goja-wrapping of types prepared for JS consumption
+ logValue goja.Value
+ dbValue goja.Value
+ frameValue goja.Value
+ frameResultValue goja.Value
+}
+
+// newJsTracer instantiates a new JS tracer instance. code is either
+// the name of a built-in JS tracer or a Javascript snippet which
+// evaluates to an expression returning an object with certain methods.
+// The methods `result` and `fault` are required to be present.
+// The methods `step`, `enter`, and `exit` are optional, but note that
+// `enter` and `exit` always go together.
+func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+ if c, ok := assetTracers[code]; ok {
+ code = c
+ }
+ vm := goja.New()
+ // By default field names are exported to JS as is, i.e. capitalized.
+ vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
+ t := &jsTracer{
+ vm: vm,
+ ctx: make(map[string]goja.Value),
+ }
+ if ctx == nil {
+ ctx = new(tracers.Context)
+ }
+ if ctx.BlockHash != (common.Hash{}) {
+ t.ctx["blockHash"] = vm.ToValue(ctx.BlockHash.Bytes())
+ if ctx.TxHash != (common.Hash{}) {
+ t.ctx["txIndex"] = vm.ToValue(ctx.TxIndex)
+ t.ctx["txHash"] = vm.ToValue(ctx.TxHash.Bytes())
+ }
+ }
+
+ t.setTypeConverters()
+ t.setBuiltinFunctions()
+ ret, err := vm.RunString("(" + code + ")")
+ if err != nil {
+ return nil, err
+ }
+ // Check tracer's interface for required and optional methods.
+ obj := ret.ToObject(vm)
+ result, ok := goja.AssertFunction(obj.Get("result"))
+ if !ok {
+ return nil, errors.New("trace object must expose a function result()")
+ }
+ fault, ok := goja.AssertFunction(obj.Get("fault"))
+ if !ok {
+ return nil, errors.New("trace object must expose a function fault()")
+ }
+ step, ok := goja.AssertFunction(obj.Get("step"))
+ t.traceStep = ok
+ enter, hasEnter := goja.AssertFunction(obj.Get("enter"))
+ exit, hasExit := goja.AssertFunction(obj.Get("exit"))
+ if hasEnter != hasExit {
+ return nil, errors.New("trace object must expose either both or none of enter() and exit()")
+ }
+ t.traceFrame = hasEnter
+ t.obj = obj
+ t.step = step
+ t.enter = enter
+ t.exit = exit
+ t.result = result
+ t.fault = fault
+
+ // Pass in config
+ if setup, ok := goja.AssertFunction(obj.Get("setup")); ok {
+ cfgStr := "{}"
+ if cfg != nil {
+ cfgStr = string(cfg)
+ }
+ if _, err := setup(obj, vm.ToValue(cfgStr)); err != nil {
+ return nil, err
+ }
+ }
+ // Setup objects carrying data to JS. These are created once and re-used.
+ t.log = &steplog{
+ vm: vm,
+ op: &opObj{vm: vm},
+ memory: &memoryObj{vm: vm, toBig: t.toBig, toBuf: t.toBuf},
+ stack: &stackObj{vm: vm, toBig: t.toBig},
+ contract: &contractObj{vm: vm, toBig: t.toBig, toBuf: t.toBuf},
+ }
+ t.frame = &callframe{vm: vm, toBig: t.toBig, toBuf: t.toBuf}
+ t.frameResult = &callframeResult{vm: vm, toBuf: t.toBuf}
+ t.frameValue = t.frame.setupObject()
+ t.frameResultValue = t.frameResult.setupObject()
+ t.logValue = t.log.setupObject()
+ return t, nil
+}
+
+// CaptureTxStart implements the Tracer interface and is invoked at the beginning of
+// transaction processing.
+func (t *jsTracer) CaptureTxStart(gasLimit uint64) {
+ t.gasLimit = gasLimit
+}
+
+// CaptureTxStart implements the Tracer interface and is invoked at the end of
+// transaction processing.
+func (t *jsTracer) CaptureTxEnd(restGas uint64) {}
+
+// CaptureStart implements the Tracer interface to initialize the tracing operation.
+func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ t.env = env
+ db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
+ t.dbValue = db.setupObject()
+ if create {
+ t.ctx["type"] = t.vm.ToValue("CREATE")
+ } else {
+ t.ctx["type"] = t.vm.ToValue("CALL")
+ }
+ t.ctx["from"] = t.vm.ToValue(from.Bytes())
+ t.ctx["to"] = t.vm.ToValue(to.Bytes())
+ t.ctx["input"] = t.vm.ToValue(input)
+ t.ctx["gas"] = t.vm.ToValue(gas)
+ t.ctx["gasPrice"] = t.vm.ToValue(env.GasPrice)
+ valueBig, err := t.toBig(t.vm, value.String())
+ if err != nil {
+ t.err = err
+ return
+ }
+ t.ctx["value"] = valueBig
+ t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64())
+ // Update list of precompiles based on current block
+ rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil)
+ t.activePrecompiles = env.ActivePrecompiles(rules)
+ t.ctx["intrinsicGas"] = t.vm.ToValue(t.gasLimit - gas)
+}
+
+// CaptureState implements the Tracer interface to trace a single step of VM execution.
+func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ if !t.traceStep {
+ return
+ }
+ if t.err != nil {
+ return
+ }
+
+ log := t.log
+ log.op.op = op
+ log.memory.memory = scope.Memory
+ log.stack.stack = scope.Stack
+ log.contract.contract = scope.Contract
+ log.pc = uint(pc)
+ log.gas = uint(gas)
+ log.cost = uint(cost)
+ log.depth = uint(depth)
+ log.err = err
+ if _, err := t.step(t.obj, t.logValue, t.dbValue); err != nil {
+ t.onError("step", err)
+ }
+}
+
+// CaptureFault implements the Tracer interface to trace an execution fault
+func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+ if t.err != nil {
+ return
+ }
+ // Other log fields have been already set as part of the last CaptureState.
+ t.log.err = err
+ if _, err := t.fault(t.obj, t.logValue, t.dbValue); err != nil {
+ t.onError("fault", err)
+ }
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, duration time.Duration, err error) {
+ t.ctx["output"] = t.vm.ToValue(output)
+ t.ctx["time"] = t.vm.ToValue(duration.String())
+ t.ctx["gasUsed"] = t.vm.ToValue(gasUsed)
+ if err != nil {
+ t.ctx["error"] = t.vm.ToValue(err.Error())
+ }
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *jsTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ if !t.traceFrame {
+ return
+ }
+ if t.err != nil {
+ return
+ }
+
+ t.frame.typ = typ.String()
+ t.frame.from = from
+ t.frame.to = to
+ t.frame.input = common.CopyBytes(input)
+ t.frame.gas = uint(gas)
+ t.frame.value = nil
+ if value != nil {
+ t.frame.value = new(big.Int).SetBytes(value.Bytes())
+ }
+
+ if _, err := t.enter(t.obj, t.frameValue); err != nil {
+ t.onError("enter", err)
+ }
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+ if !t.traceFrame {
+ return
+ }
+
+ t.frameResult.gasUsed = uint(gasUsed)
+ t.frameResult.output = common.CopyBytes(output)
+ t.frameResult.err = err
+
+ if _, err := t.exit(t.obj, t.frameResultValue); err != nil {
+ t.onError("exit", err)
+ }
+}
+
+// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error
+func (t *jsTracer) GetResult() (json.RawMessage, error) {
+ ctx := t.vm.ToValue(t.ctx)
+ res, err := t.result(t.obj, ctx, t.dbValue)
+ if err != nil {
+ return nil, wrapError("result", err)
+ }
+ encoded, err := json.Marshal(res)
+ if err != nil {
+ return nil, err
+ }
+ return json.RawMessage(encoded), t.err
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *jsTracer) Stop(err error) {
+ t.vm.Interrupt(err)
+}
+
+// onError is called anytime the running JS code is interrupted
+// and returns an error. It in turn pings the EVM to cancel its
+// execution.
+func (t *jsTracer) onError(context string, err error) {
+ t.err = wrapError(context, err)
+ // `env` is set on CaptureStart which comes before any JS execution.
+ // So it should be non-nil.
+ t.env.Cancel()
+}
+
+func wrapError(context string, err error) error {
+ return fmt.Errorf("%v in server-side tracer function '%v'", err, context)
+}
+
+// setBuiltinFunctions injects Go functions which are available to tracers into the environment.
+// It depends on type converters having been set up.
+func (t *jsTracer) setBuiltinFunctions() {
+ vm := t.vm
+ // TODO: load console from goja-nodejs
+ vm.Set("toHex", func(v goja.Value) string {
+ b, err := t.fromBuf(vm, v, false)
+ if err != nil {
+ vm.Interrupt(err)
+ return ""
+ }
+ return hexutil.Encode(b)
+ })
+ vm.Set("toWord", func(v goja.Value) goja.Value {
+ // TODO: add test with []byte len < 32 or > 32
+ b, err := t.fromBuf(vm, v, true)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ b = common.BytesToHash(b).Bytes()
+ res, err := t.toBuf(vm, b)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ return res
+ })
+ vm.Set("toAddress", func(v goja.Value) goja.Value {
+ a, err := t.fromBuf(vm, v, true)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ a = common.BytesToAddress(a).Bytes()
+ res, err := t.toBuf(vm, a)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ return res
+ })
+ vm.Set("toContract", func(from goja.Value, nonce uint) goja.Value {
+ a, err := t.fromBuf(vm, from, true)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ addr := common.BytesToAddress(a)
+ b := crypto.CreateAddress(addr, uint64(nonce)).Bytes()
+ res, err := t.toBuf(vm, b)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ return res
+ })
+ vm.Set("toContract2", func(from goja.Value, salt string, initcode goja.Value) goja.Value {
+ a, err := t.fromBuf(vm, from, true)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ addr := common.BytesToAddress(a)
+ code, err := t.fromBuf(vm, initcode, true)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ code = common.CopyBytes(code)
+ codeHash := crypto.Keccak256(code)
+ b := crypto.CreateAddress2(addr, common.HexToHash(salt), codeHash).Bytes()
+ res, err := t.toBuf(vm, b)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ return res
+ })
+ vm.Set("isPrecompiled", func(v goja.Value) bool {
+ a, err := t.fromBuf(vm, v, true)
+ if err != nil {
+ vm.Interrupt(err)
+ return false
+ }
+ addr := common.BytesToAddress(a)
+ for _, p := range t.activePrecompiles {
+ if p == addr {
+ return true
+ }
+ }
+ return false
+ })
+ vm.Set("slice", func(slice goja.Value, start, end int) goja.Value {
+ b, err := t.fromBuf(vm, slice, false)
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ if start < 0 || start > end || end > len(b) {
+ vm.Interrupt(fmt.Sprintf("Tracer accessed out of bound memory: available %d, offset %d, size %d", len(b), start, end-start))
+ return nil
+ }
+ res, err := t.toBuf(vm, b[start:end])
+ if err != nil {
+ vm.Interrupt(err)
+ return nil
+ }
+ return res
+ })
+}
+
+// setTypeConverters sets up utilities for converting Go types into those
+// suitable for JS consumption.
+func (t *jsTracer) setTypeConverters() error {
+ // Inject bigint logic.
+ // TODO: To be replaced after goja adds support for native JS bigint.
+ toBigCode, err := t.vm.RunProgram(bigIntProgram)
+ if err != nil {
+ return err
+ }
+ // Used to create JS bigint objects from go.
+ toBigFn, ok := goja.AssertFunction(toBigCode)
+ if !ok {
+ return errors.New("failed to bind bigInt func")
+ }
+ toBigWrapper := func(vm *goja.Runtime, val string) (goja.Value, error) {
+ return toBigFn(goja.Undefined(), vm.ToValue(val))
+ }
+ t.toBig = toBigWrapper
+ // NOTE: We need this workaround to create JS buffers because
+ // goja doesn't at the moment expose constructors for typed arrays.
+ //
+ // Cache uint8ArrayType once to be used every time for less overhead.
+ uint8ArrayType := t.vm.Get("Uint8Array")
+ toBufWrapper := func(vm *goja.Runtime, val []byte) (goja.Value, error) {
+ return toBuf(vm, uint8ArrayType, val)
+ }
+ t.toBuf = toBufWrapper
+ fromBufWrapper := func(vm *goja.Runtime, buf goja.Value, allowString bool) ([]byte, error) {
+ return fromBuf(vm, uint8ArrayType, buf, allowString)
+ }
+ t.fromBuf = fromBufWrapper
+ return nil
+}
+
+type opObj struct {
+ vm *goja.Runtime
+ op vm.OpCode
+}
+
+func (o *opObj) ToNumber() int {
+ return int(o.op)
+}
+
+func (o *opObj) ToString() string {
+ return o.op.String()
+}
+
+func (o *opObj) IsPush() bool {
+ return o.op.IsPush()
+}
+
+func (o *opObj) setupObject() *goja.Object {
+ obj := o.vm.NewObject()
+ obj.Set("toNumber", o.vm.ToValue(o.ToNumber))
+ obj.Set("toString", o.vm.ToValue(o.ToString))
+ obj.Set("isPush", o.vm.ToValue(o.IsPush))
+ return obj
+}
+
+type memoryObj struct {
+ memory *vm.Memory
+ vm *goja.Runtime
+ toBig toBigFn
+ toBuf toBufFn
+}
+
+func (mo *memoryObj) Slice(begin, end int64) goja.Value {
+ b, err := mo.slice(begin, end)
+ if err != nil {
+ mo.vm.Interrupt(err)
+ return nil
+ }
+ res, err := mo.toBuf(mo.vm, b)
+ if err != nil {
+ mo.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+// slice returns the requested range of memory as a byte slice.
+func (mo *memoryObj) slice(begin, end int64) ([]byte, error) {
+ if end == begin {
+ return []byte{}, nil
+ }
+ if end < begin || begin < 0 {
+ return nil, fmt.Errorf("tracer accessed out of bound memory: offset %d, end %d", begin, end)
+ }
+ if mo.memory.Len() < int(end) {
+ return nil, fmt.Errorf("tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), begin, end-begin)
+ }
+ return mo.memory.GetCopy(begin, end-begin), nil
+}
+
+func (mo *memoryObj) GetUint(addr int64) goja.Value {
+ value, err := mo.getUint(addr)
+ if err != nil {
+ mo.vm.Interrupt(err)
+ return nil
+ }
+ res, err := mo.toBig(mo.vm, value.String())
+ if err != nil {
+ mo.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+// getUint returns the 32 bytes at the specified address interpreted as a uint.
+func (mo *memoryObj) getUint(addr int64) (*big.Int, error) {
+ if mo.memory.Len() < int(addr)+32 || addr < 0 {
+ return nil, fmt.Errorf("tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), addr, 32)
+ }
+ return new(big.Int).SetBytes(mo.memory.GetPtr(addr, 32)), nil
+}
+
+func (mo *memoryObj) Length() int {
+ return mo.memory.Len()
+}
+
+func (m *memoryObj) setupObject() *goja.Object {
+ o := m.vm.NewObject()
+ o.Set("slice", m.vm.ToValue(m.Slice))
+ o.Set("getUint", m.vm.ToValue(m.GetUint))
+ o.Set("length", m.vm.ToValue(m.Length))
+ return o
+}
+
+type stackObj struct {
+ stack *vm.Stack
+ vm *goja.Runtime
+ toBig toBigFn
+}
+
+func (s *stackObj) Peek(idx int) goja.Value {
+ value, err := s.peek(idx)
+ if err != nil {
+ s.vm.Interrupt(err)
+ return nil
+ }
+ res, err := s.toBig(s.vm, value.String())
+ if err != nil {
+ s.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+// peek returns the nth-from-the-top element of the stack.
+func (s *stackObj) peek(idx int) (*big.Int, error) {
+ if len(s.stack.Data) <= idx || idx < 0 {
+ return nil, fmt.Errorf("tracer accessed out of bound stack: size %d, index %d", len(s.stack.Data), idx)
+ }
+ return s.stack.Back(idx).ToBig(), nil
+}
+
+func (s *stackObj) Length() int {
+ return len(s.stack.Data)
+}
+
+func (s *stackObj) setupObject() *goja.Object {
+ o := s.vm.NewObject()
+ o.Set("peek", s.vm.ToValue(s.Peek))
+ o.Set("length", s.vm.ToValue(s.Length))
+ return o
+}
+
+type dbObj struct {
+ db vm.StateDB
+ vm *goja.Runtime
+ toBig toBigFn
+ toBuf toBufFn
+ fromBuf fromBufFn
+}
+
+func (do *dbObj) GetBalance(addrSlice goja.Value) goja.Value {
+ a, err := do.fromBuf(do.vm, addrSlice, false)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return nil
+ }
+ addr := common.BytesToAddress(a)
+ value := do.db.GetBalance(addr)
+ res, err := do.toBig(do.vm, value.String())
+ if err != nil {
+ do.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (do *dbObj) GetNonce(addrSlice goja.Value) uint64 {
+ a, err := do.fromBuf(do.vm, addrSlice, false)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return 0
+ }
+ addr := common.BytesToAddress(a)
+ return do.db.GetNonce(addr)
+}
+
+func (do *dbObj) GetCode(addrSlice goja.Value) goja.Value {
+ a, err := do.fromBuf(do.vm, addrSlice, false)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return nil
+ }
+ addr := common.BytesToAddress(a)
+ code := do.db.GetCode(addr)
+ res, err := do.toBuf(do.vm, code)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (do *dbObj) GetState(addrSlice goja.Value, hashSlice goja.Value) goja.Value {
+ a, err := do.fromBuf(do.vm, addrSlice, false)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return nil
+ }
+ addr := common.BytesToAddress(a)
+ h, err := do.fromBuf(do.vm, hashSlice, false)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return nil
+ }
+ hash := common.BytesToHash(h)
+ state := do.db.GetState(addr, hash).Bytes()
+ res, err := do.toBuf(do.vm, state)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (do *dbObj) Exists(addrSlice goja.Value) bool {
+ a, err := do.fromBuf(do.vm, addrSlice, false)
+ if err != nil {
+ do.vm.Interrupt(err)
+ return false
+ }
+ addr := common.BytesToAddress(a)
+ return do.db.Exist(addr)
+}
+
+func (do *dbObj) setupObject() *goja.Object {
+ o := do.vm.NewObject()
+ o.Set("getBalance", do.vm.ToValue(do.GetBalance))
+ o.Set("getNonce", do.vm.ToValue(do.GetNonce))
+ o.Set("getCode", do.vm.ToValue(do.GetCode))
+ o.Set("getState", do.vm.ToValue(do.GetState))
+ o.Set("exists", do.vm.ToValue(do.Exists))
+ return o
+}
+
+type contractObj struct {
+ contract *vm.Contract
+ vm *goja.Runtime
+ toBig toBigFn
+ toBuf toBufFn
+}
+
+func (co *contractObj) GetCaller() goja.Value {
+ caller := co.contract.Caller().Bytes()
+ res, err := co.toBuf(co.vm, caller)
+ if err != nil {
+ co.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (co *contractObj) GetAddress() goja.Value {
+ addr := co.contract.Address().Bytes()
+ res, err := co.toBuf(co.vm, addr)
+ if err != nil {
+ co.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (co *contractObj) GetValue() goja.Value {
+ value := co.contract.Value()
+ res, err := co.toBig(co.vm, value.String())
+ if err != nil {
+ co.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (co *contractObj) GetInput() goja.Value {
+ input := common.CopyBytes(co.contract.Input)
+ res, err := co.toBuf(co.vm, input)
+ if err != nil {
+ co.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (c *contractObj) setupObject() *goja.Object {
+ o := c.vm.NewObject()
+ o.Set("getCaller", c.vm.ToValue(c.GetCaller))
+ o.Set("getAddress", c.vm.ToValue(c.GetAddress))
+ o.Set("getValue", c.vm.ToValue(c.GetValue))
+ o.Set("getInput", c.vm.ToValue(c.GetInput))
+ return o
+}
+
+type callframe struct {
+ vm *goja.Runtime
+ toBig toBigFn
+ toBuf toBufFn
+
+ typ string
+ from common.Address
+ to common.Address
+ input []byte
+ gas uint
+ value *big.Int
+}
+
+func (f *callframe) GetType() string {
+ return f.typ
+}
+
+func (f *callframe) GetFrom() goja.Value {
+ from := f.from.Bytes()
+ res, err := f.toBuf(f.vm, from)
+ if err != nil {
+ f.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (f *callframe) GetTo() goja.Value {
+ to := f.to.Bytes()
+ res, err := f.toBuf(f.vm, to)
+ if err != nil {
+ f.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (f *callframe) GetInput() goja.Value {
+ input := f.input
+ res, err := f.toBuf(f.vm, input)
+ if err != nil {
+ f.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (f *callframe) GetGas() uint {
+ return f.gas
+}
+
+func (f *callframe) GetValue() goja.Value {
+ if f.value == nil {
+ return goja.Undefined()
+ }
+ res, err := f.toBig(f.vm, f.value.String())
+ if err != nil {
+ f.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (f *callframe) setupObject() *goja.Object {
+ o := f.vm.NewObject()
+ o.Set("getType", f.vm.ToValue(f.GetType))
+ o.Set("getFrom", f.vm.ToValue(f.GetFrom))
+ o.Set("getTo", f.vm.ToValue(f.GetTo))
+ o.Set("getInput", f.vm.ToValue(f.GetInput))
+ o.Set("getGas", f.vm.ToValue(f.GetGas))
+ o.Set("getValue", f.vm.ToValue(f.GetValue))
+ return o
+}
+
+type callframeResult struct {
+ vm *goja.Runtime
+ toBuf toBufFn
+
+ gasUsed uint
+ output []byte
+ err error
+}
+
+func (r *callframeResult) GetGasUsed() uint {
+ return r.gasUsed
+}
+
+func (r *callframeResult) GetOutput() goja.Value {
+ res, err := r.toBuf(r.vm, r.output)
+ if err != nil {
+ r.vm.Interrupt(err)
+ return nil
+ }
+ return res
+}
+
+func (r *callframeResult) GetError() goja.Value {
+ if r.err != nil {
+ return r.vm.ToValue(r.err.Error())
+ }
+ return goja.Undefined()
+}
+
+func (r *callframeResult) setupObject() *goja.Object {
+ o := r.vm.NewObject()
+ o.Set("getGasUsed", r.vm.ToValue(r.GetGasUsed))
+ o.Set("getOutput", r.vm.ToValue(r.GetOutput))
+ o.Set("getError", r.vm.ToValue(r.GetError))
+ return o
+}
+
+type steplog struct {
+ vm *goja.Runtime
+
+ op *opObj
+ memory *memoryObj
+ stack *stackObj
+ contract *contractObj
+
+ pc uint
+ gas uint
+ cost uint
+ depth uint
+ refund uint
+ err error
+}
+
+func (l *steplog) GetPC() uint {
+ return l.pc
+}
+
+func (l *steplog) GetGas() uint {
+ return l.gas
+}
+
+func (l *steplog) GetCost() uint {
+ return l.cost
+}
+
+func (l *steplog) GetDepth() uint {
+ return l.depth
+}
+
+func (l *steplog) GetRefund() uint {
+ return l.refund
+}
+
+func (l *steplog) GetError() goja.Value {
+ if l.err != nil {
+ return l.vm.ToValue(l.err.Error())
+ }
+ return goja.Undefined()
+}
+
+func (l *steplog) setupObject() *goja.Object {
+ o := l.vm.NewObject()
+ // Setup basic fields.
+ o.Set("getPC", l.vm.ToValue(l.GetPC))
+ o.Set("getGas", l.vm.ToValue(l.GetGas))
+ o.Set("getCost", l.vm.ToValue(l.GetCost))
+ o.Set("getDepth", l.vm.ToValue(l.GetDepth))
+ o.Set("getRefund", l.vm.ToValue(l.GetRefund))
+ o.Set("getError", l.vm.ToValue(l.GetError))
+ // Setup nested objects.
+ o.Set("op", l.op.setupObject())
+ o.Set("stack", l.stack.setupObject())
+ o.Set("memory", l.memory.setupObject())
+ o.Set("contract", l.contract.setupObject())
+ return o
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/4byte_tracer_legacy.js b/x/evm/core/tracers/js/internal/tracers/4byte_tracer_legacy.js
new file mode 100644
index 00000000..e4714b8b
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/4byte_tracer_legacy.js
@@ -0,0 +1,86 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// 4byteTracer searches for 4byte-identifiers, and collects them for post-processing.
+// It collects the methods identifiers along with the size of the supplied data, so
+// a reversed signature can be matched against the size of the data.
+//
+// Example:
+// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"})
+// {
+// 0x27dc297e-128: 1,
+// 0x38cc4831-0: 2,
+// 0x524f3889-96: 1,
+// 0xadf59f99-288: 1,
+// 0xc281d19e-0: 1
+// }
+{
+ // ids aggregates the 4byte ids found.
+ ids : {},
+
+ // callType returns 'false' for non-calls, or the peek-index for the first param
+ // after 'value', i.e. meminstart.
+ callType: function(opstr){
+ switch(opstr){
+ case "CALL": case "CALLCODE":
+ // gas, addr, val, memin, meminsz, memout, memoutsz
+ return 3; // stack ptr to memin
+
+ case "DELEGATECALL": case "STATICCALL":
+ // gas, addr, memin, meminsz, memout, memoutsz
+ return 2; // stack ptr to memin
+ }
+ return false;
+ },
+
+ // store save the given identifier and datasize.
+ store: function(id, size){
+ var key = "" + toHex(id) + "-" + size;
+ this.ids[key] = this.ids[key] + 1 || 1;
+ },
+
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) {
+ // Skip any opcodes that are not internal calls
+ var ct = this.callType(log.op.toString());
+ if (!ct) {
+ return;
+ }
+ // Skip any pre-compile invocations, those are just fancy opcodes
+ if (isPrecompiled(toAddress(log.stack.peek(1).toString(16)))) {
+ return;
+ }
+ // Gather internal call details
+ var inSz = log.stack.peek(ct + 1).valueOf();
+ if (inSz >= 4) {
+ var inOff = log.stack.peek(ct).valueOf();
+ this.store(log.memory.slice(inOff, inOff + 4), inSz-4);
+ }
+ },
+
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) { },
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx) {
+ // Save the outer calldata also
+ if (ctx.input.length >= 4) {
+ this.store(slice(ctx.input, 0, 4), ctx.input.length-4)
+ }
+ return this.ids;
+ },
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/bigram_tracer.js b/x/evm/core/tracers/js/internal/tracers/bigram_tracer.js
new file mode 100644
index 00000000..421c360a
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/bigram_tracer.js
@@ -0,0 +1,47 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+{
+ // hist is the counters of opcode bigrams
+ hist: {},
+ // lastOp is last operation
+ lastOp: '',
+ // execution depth of last op
+ lastDepth: 0,
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) {
+ var op = log.op.toString();
+ var depth = log.getDepth();
+ if (depth == this.lastDepth){
+ var key = this.lastOp+'-'+op;
+ if (this.hist[key]){
+ this.hist[key]++;
+ }
+ else {
+ this.hist[key] = 1;
+ }
+ }
+ this.lastOp = op;
+ this.lastDepth = depth;
+ },
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) {},
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx) {
+ return this.hist;
+ },
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/call_tracer_legacy.js b/x/evm/core/tracers/js/internal/tracers/call_tracer_legacy.js
new file mode 100644
index 00000000..3ca73777
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/call_tracer_legacy.js
@@ -0,0 +1,252 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// callTracer is a full blown transaction tracer that extracts and reports all
+// the internal calls made by a transaction, along with any useful information.
+{
+ // callstack is the current recursive call stack of the EVM execution.
+ callstack: [{}],
+
+ // descended tracks whether we've just descended from an outer transaction into
+ // an inner call.
+ descended: false,
+
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) {
+ // Capture any errors immediately
+ var error = log.getError();
+ if (error !== undefined) {
+ this.fault(log, db);
+ return;
+ }
+ // We only care about system opcodes, faster if we pre-check once
+ var syscall = (log.op.toNumber() & 0xf0) == 0xf0;
+ if (syscall) {
+ var op = log.op.toString();
+ }
+ // If a new contract is being created, add to the call stack
+ if (syscall && (op == 'CREATE' || op == "CREATE2")) {
+ var inOff = log.stack.peek(1).valueOf();
+ var inEnd = inOff + log.stack.peek(2).valueOf();
+
+ // Assemble the internal call report and store for completion
+ var call = {
+ type: op,
+ from: toHex(log.contract.getAddress()),
+ input: toHex(log.memory.slice(inOff, inEnd)),
+ gasIn: log.getGas(),
+ gasCost: log.getCost(),
+ value: '0x' + log.stack.peek(0).toString(16)
+ };
+ this.callstack.push(call);
+ this.descended = true
+ return;
+ }
+ // If a contract is being self destructed, gather that as a subcall too
+ if (syscall && op == 'SELFDESTRUCT') {
+ var left = this.callstack.length;
+ if (this.callstack[left-1].calls === undefined) {
+ this.callstack[left-1].calls = [];
+ }
+ this.callstack[left-1].calls.push({
+ type: op,
+ from: toHex(log.contract.getAddress()),
+ to: toHex(toAddress(log.stack.peek(0).toString(16))),
+ gasIn: log.getGas(),
+ gasCost: log.getCost(),
+ value: '0x' + db.getBalance(log.contract.getAddress()).toString(16)
+ });
+ return
+ }
+ // If a new method invocation is being done, add to the call stack
+ if (syscall && (op == 'CALL' || op == 'CALLCODE' || op == 'DELEGATECALL' || op == 'STATICCALL')) {
+ // Skip any pre-compile invocations, those are just fancy opcodes
+ var to = toAddress(log.stack.peek(1).toString(16));
+ if (isPrecompiled(to)) {
+ return
+ }
+ var off = (op == 'DELEGATECALL' || op == 'STATICCALL' ? 0 : 1);
+
+ var inOff = log.stack.peek(2 + off).valueOf();
+ var inEnd = inOff + log.stack.peek(3 + off).valueOf();
+
+ // Assemble the internal call report and store for completion
+ var call = {
+ type: op,
+ from: toHex(log.contract.getAddress()),
+ to: toHex(to),
+ input: toHex(log.memory.slice(inOff, inEnd)),
+ gasIn: log.getGas(),
+ gasCost: log.getCost(),
+ outOff: log.stack.peek(4 + off).valueOf(),
+ outLen: log.stack.peek(5 + off).valueOf()
+ };
+ if (op != 'DELEGATECALL' && op != 'STATICCALL') {
+ call.value = '0x' + log.stack.peek(2).toString(16);
+ }
+ this.callstack.push(call);
+ this.descended = true
+ return;
+ }
+ // If we've just descended into an inner call, retrieve it's true allowance. We
+ // need to extract if from within the call as there may be funky gas dynamics
+ // with regard to requested and actually given gas (2300 stipend, 63/64 rule).
+ if (this.descended) {
+ if (log.getDepth() >= this.callstack.length) {
+ this.callstack[this.callstack.length - 1].gas = log.getGas();
+ } else {
+ // TODO(karalabe): The call was made to a plain account. We currently don't
+ // have access to the true gas amount inside the call and so any amount will
+ // mostly be wrong since it depends on a lot of input args. Skip gas for now.
+ }
+ this.descended = false;
+ }
+ // If an existing call is returning, pop off the call stack
+ if (syscall && op == 'REVERT') {
+ this.callstack[this.callstack.length - 1].error = "execution reverted";
+ return;
+ }
+ if (log.getDepth() == this.callstack.length - 1) {
+ // Pop off the last call and get the execution results
+ var call = this.callstack.pop();
+
+ if (call.type == 'CREATE' || call.type == "CREATE2") {
+ // If the call was a CREATE, retrieve the contract address and output code
+ call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost - log.getGas()).toString(16);
+ delete call.gasIn; delete call.gasCost;
+
+ var ret = log.stack.peek(0);
+ if (!ret.equals(0)) {
+ call.to = toHex(toAddress(ret.toString(16)));
+ call.output = toHex(db.getCode(toAddress(ret.toString(16))));
+ } else if (call.error === undefined) {
+ call.error = "internal failure"; // TODO(karalabe): surface these faults somehow
+ }
+ } else {
+ // If the call was a contract call, retrieve the gas usage and output
+ if (call.gas !== undefined) {
+ call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost + call.gas - log.getGas()).toString(16);
+ }
+ var ret = log.stack.peek(0);
+ if (!ret.equals(0)) {
+ call.output = toHex(log.memory.slice(call.outOff, call.outOff + call.outLen));
+ } else if (call.error === undefined) {
+ call.error = "internal failure"; // TODO(karalabe): surface these faults somehow
+ }
+ delete call.gasIn; delete call.gasCost;
+ delete call.outOff; delete call.outLen;
+ }
+ if (call.gas !== undefined) {
+ call.gas = '0x' + bigInt(call.gas).toString(16);
+ }
+ // Inject the call into the previous one
+ var left = this.callstack.length;
+ if (this.callstack[left-1].calls === undefined) {
+ this.callstack[left-1].calls = [];
+ }
+ this.callstack[left-1].calls.push(call);
+ }
+ },
+
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) {
+ // If the topmost call already reverted, don't handle the additional fault again
+ if (this.callstack[this.callstack.length - 1].error !== undefined) {
+ return;
+ }
+ // Pop off the just failed call
+ var call = this.callstack.pop();
+ call.error = log.getError();
+
+ // Consume all available gas and clean any leftovers
+ if (call.gas !== undefined) {
+ call.gas = '0x' + bigInt(call.gas).toString(16);
+ call.gasUsed = call.gas
+ }
+ delete call.gasIn; delete call.gasCost;
+ delete call.outOff; delete call.outLen;
+
+ // Flatten the failed call into its parent
+ var left = this.callstack.length;
+ if (left > 0) {
+ if (this.callstack[left-1].calls === undefined) {
+ this.callstack[left-1].calls = [];
+ }
+ this.callstack[left-1].calls.push(call);
+ return;
+ }
+ // Last call failed too, leave it in the stack
+ this.callstack.push(call);
+ },
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx, db) {
+ var result = {
+ type: ctx.type,
+ from: toHex(ctx.from),
+ to: toHex(ctx.to),
+ value: '0x' + ctx.value.toString(16),
+ gas: '0x' + bigInt(ctx.gas).toString(16),
+ gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16),
+ input: toHex(ctx.input),
+ output: toHex(ctx.output),
+ time: ctx.time,
+ };
+ if (this.callstack[0].calls !== undefined) {
+ result.calls = this.callstack[0].calls;
+ }
+ if (this.callstack[0].error !== undefined) {
+ result.error = this.callstack[0].error;
+ } else if (ctx.error !== undefined) {
+ result.error = ctx.error;
+ }
+ if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) {
+ delete result.output;
+ }
+ return this.finalize(result);
+ },
+
+ // finalize recreates a call object using the final desired field oder for json
+ // serialization. This is a nicety feature to pass meaningfully ordered results
+ // to users who don't interpret it, just display it.
+ finalize: function(call) {
+ var sorted = {
+ type: call.type,
+ from: call.from,
+ to: call.to,
+ value: call.value,
+ gas: call.gas,
+ gasUsed: call.gasUsed,
+ input: call.input,
+ output: call.output,
+ error: call.error,
+ time: call.time,
+ calls: call.calls,
+ }
+ for (var key in sorted) {
+ if (sorted[key] === undefined) {
+ delete sorted[key];
+ }
+ }
+ if (sorted.calls !== undefined) {
+ for (var i=0; i.
+
+// evmdisTracer returns sufficient information from a trace to perform evmdis-style
+// disassembly.
+{
+ stack: [{ops: []}],
+
+ npushes: {0: 0, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1, 16: 1, 17: 1, 18: 1, 19: 1, 20: 1, 21: 1, 22: 1, 23: 1, 24: 1, 25: 1, 26: 1, 32: 1, 48: 1, 49: 1, 50: 1, 51: 1, 52: 1, 53: 1, 54: 1, 55: 0, 56: 1, 57: 0, 58: 1, 59: 1, 60: 0, 64: 1, 65: 1, 66: 1, 67: 1, 68: 1, 69: 1, 80: 0, 81: 1, 82: 0, 83: 0, 84: 1, 85: 0, 86: 0, 87: 0, 88: 1, 89: 1, 90: 1, 91: 0, 96: 1, 97: 1, 98: 1, 99: 1, 100: 1, 101: 1, 102: 1, 103: 1, 104: 1, 105: 1, 106: 1, 107: 1, 108: 1, 109: 1, 110: 1, 111: 1, 112: 1, 113: 1, 114: 1, 115: 1, 116: 1, 117: 1, 118: 1, 119: 1, 120: 1, 121: 1, 122: 1, 123: 1, 124: 1, 125: 1, 126: 1, 127: 1, 128: 2, 129: 3, 130: 4, 131: 5, 132: 6, 133: 7, 134: 8, 135: 9, 136: 10, 137: 11, 138: 12, 139: 13, 140: 14, 141: 15, 142: 16, 143: 17, 144: 2, 145: 3, 146: 4, 147: 5, 148: 6, 149: 7, 150: 8, 151: 9, 152: 10, 153: 11, 154: 12, 155: 13, 156: 14, 157: 15, 158: 16, 159: 17, 160: 0, 161: 0, 162: 0, 163: 0, 164: 0, 240: 1, 241: 1, 242: 1, 243: 0, 244: 0, 255: 0},
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function() { return this.stack[0].ops; },
+
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) { },
+
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) {
+ var frame = this.stack[this.stack.length - 1];
+
+ var error = log.getError();
+ if (error) {
+ frame["error"] = error;
+ } else if (log.getDepth() == this.stack.length) {
+ opinfo = {
+ op: log.op.toNumber(),
+ depth : log.getDepth(),
+ result: [],
+ };
+ if (frame.ops.length > 0) {
+ var prevop = frame.ops[frame.ops.length - 1];
+ for(var i = 0; i < this.npushes[prevop.op]; i++)
+ prevop.result.push(log.stack.peek(i).toString(16));
+ }
+ switch(log.op.toString()) {
+ case "CALL": case "CALLCODE":
+ var instart = log.stack.peek(3).valueOf();
+ var insize = log.stack.peek(4).valueOf();
+ opinfo["gas"] = log.stack.peek(0).valueOf();
+ opinfo["to"] = log.stack.peek(1).toString(16);
+ opinfo["value"] = log.stack.peek(2).toString();
+ opinfo["input"] = log.memory.slice(instart, instart + insize);
+ opinfo["error"] = null;
+ opinfo["return"] = null;
+ opinfo["ops"] = [];
+ this.stack.push(opinfo);
+ break;
+ case "DELEGATECALL": case "STATICCALL":
+ var instart = log.stack.peek(2).valueOf();
+ var insize = log.stack.peek(3).valueOf();
+ opinfo["op"] = log.op.toString();
+ opinfo["gas"] = log.stack.peek(0).valueOf();
+ opinfo["to"] = log.stack.peek(1).toString(16);
+ opinfo["input"] = log.memory.slice(instart, instart + insize);
+ opinfo["error"] = null;
+ opinfo["return"] = null;
+ opinfo["ops"] = [];
+ this.stack.push(opinfo);
+ break;
+ case "RETURN": case "REVERT":
+ var out = log.stack.peek(0).valueOf();
+ var outsize = log.stack.peek(1).valueOf();
+ frame.return = log.memory.slice(out, out + outsize);
+ break;
+ case "STOP": case "SELFDESTRUCT":
+ frame.return = log.memory.slice(0, 0);
+ break;
+ case "JUMPDEST":
+ opinfo["pc"] = log.getPC();
+ }
+ if(log.op.isPush()) {
+ opinfo["len"] = log.op.toNumber() - 0x5e;
+ }
+ frame.ops.push(opinfo);
+ } else {
+ this.stack = this.stack.slice(0, log.getDepth());
+ }
+ }
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/noop_tracer_legacy.js b/x/evm/core/tracers/js/internal/tracers/noop_tracer_legacy.js
new file mode 100644
index 00000000..fe7ddc85
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/noop_tracer_legacy.js
@@ -0,0 +1,29 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// noopTracer is just the barebone boilerplate code required from a JavaScript
+// object to be usable as a transaction tracer.
+{
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) { },
+
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) { },
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx, db) { return {}; }
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/opcount_tracer.js b/x/evm/core/tracers/js/internal/tracers/opcount_tracer.js
new file mode 100644
index 00000000..f7984c74
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/opcount_tracer.js
@@ -0,0 +1,32 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// opcountTracer is a sample tracer that just counts the number of instructions
+// executed by the EVM before the transaction terminated.
+{
+ // count tracks the number of EVM instructions executed.
+ count: 0,
+
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) { this.count++ },
+
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) { },
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx, db) { return this.count }
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/prestate_tracer_legacy.js b/x/evm/core/tracers/js/internal/tracers/prestate_tracer_legacy.js
new file mode 100644
index 00000000..77f25209
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/prestate_tracer_legacy.js
@@ -0,0 +1,115 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// prestateTracer outputs sufficient information to create a local execution of
+// the transaction from a custom assembled genesis block.
+{
+ // prestate is the genesis that we're building.
+ prestate: null,
+
+ // lookupAccount injects the specified account into the prestate object.
+ lookupAccount: function(addr, db){
+ var acc = toHex(addr);
+ if (this.prestate[acc] === undefined) {
+ this.prestate[acc] = {
+ balance: '0x' + db.getBalance(addr).toString(16),
+ nonce: db.getNonce(addr),
+ code: toHex(db.getCode(addr)),
+ storage: {}
+ };
+ }
+ },
+
+ // lookupStorage injects the specified storage entry of the given account into
+ // the prestate object.
+ lookupStorage: function(addr, key, db){
+ var acc = toHex(addr);
+ var idx = toHex(key);
+
+ if (this.prestate[acc].storage[idx] === undefined) {
+ this.prestate[acc].storage[idx] = toHex(db.getState(addr, key));
+ }
+ },
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx, db) {
+ if (this.prestate === null) {
+ this.prestate = {};
+ // If tx is transfer-only, the recipient account
+ // hasn't been populated.
+ this.lookupAccount(ctx.to, db);
+ }
+
+ // At this point, we need to deduct the 'value' from the
+ // outer transaction, and move it back to the origin
+ this.lookupAccount(ctx.from, db);
+
+ var fromBal = bigInt(this.prestate[toHex(ctx.from)].balance.slice(2), 16);
+ var toBal = bigInt(this.prestate[toHex(ctx.to)].balance.slice(2), 16);
+
+ this.prestate[toHex(ctx.to)].balance = '0x'+toBal.subtract(ctx.value).toString(16);
+ this.prestate[toHex(ctx.from)].balance = '0x'+fromBal.add(ctx.value).add((ctx.gasUsed + ctx.intrinsicGas) * ctx.gasPrice).toString(16);
+
+ // Decrement the caller's nonce, and remove empty create targets
+ this.prestate[toHex(ctx.from)].nonce--;
+ if (ctx.type == 'CREATE') {
+ // We can blibdly delete the contract prestate, as any existing state would
+ // have caused the transaction to be rejected as invalid in the first place.
+ delete this.prestate[toHex(ctx.to)];
+ }
+ // Return the assembled allocations (prestate)
+ return this.prestate;
+ },
+
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) {
+ // Add the current account if we just started tracing
+ if (this.prestate === null){
+ this.prestate = {};
+ // Balance will potentially be wrong here, since this will include the value
+ // sent along with the message. We fix that in 'result()'.
+ this.lookupAccount(log.contract.getAddress(), db);
+ }
+ // Whenever new state is accessed, add it to the prestate
+ switch (log.op.toString()) {
+ case "EXTCODECOPY": case "EXTCODESIZE": case "EXTCODEHASH": case "BALANCE":
+ this.lookupAccount(toAddress(log.stack.peek(0).toString(16)), db);
+ break;
+ case "CREATE":
+ var from = log.contract.getAddress();
+ this.lookupAccount(toContract(from, db.getNonce(from)), db);
+ break;
+ case "CREATE2":
+ var from = log.contract.getAddress();
+ // stack: salt, size, offset, endowment
+ var offset = log.stack.peek(1).valueOf()
+ var size = log.stack.peek(2).valueOf()
+ var end = offset + size
+ this.lookupAccount(toContract2(from, log.stack.peek(3).toString(16), log.memory.slice(offset, end)), db);
+ break;
+ case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL":
+ this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db);
+ break;
+ case 'SSTORE':case 'SLOAD':
+ this.lookupStorage(log.contract.getAddress(), toWord(log.stack.peek(0).toString(16)), db);
+ break;
+ }
+ },
+
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) {}
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/tracers.go b/x/evm/core/tracers/js/internal/tracers/tracers.go
new file mode 100644
index 00000000..c3c88a07
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/tracers.go
@@ -0,0 +1,59 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// Package tracers contains the actual JavaScript tracer assets.
+package tracers
+
+import (
+ "embed"
+ "io/fs"
+ "strings"
+ "unicode"
+)
+
+//go:embed *.js
+var files embed.FS
+
+// Load reads the built-in JS tracer files embedded in the binary and
+// returns a mapping of tracer name to source.
+func Load() (map[string]string, error) {
+ assetTracers := make(map[string]string)
+ err := fs.WalkDir(files, ".", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ if d.IsDir() {
+ return nil
+ }
+ b, err := fs.ReadFile(files, path)
+ if err != nil {
+ return err
+ }
+ name := camel(strings.TrimSuffix(path, ".js"))
+ assetTracers[name] = string(b)
+ return nil
+ })
+ return assetTracers, err
+}
+
+// camel converts a snake cased input string into a camel cased output.
+func camel(str string) string {
+ pieces := strings.Split(str, "_")
+ for i := 1; i < len(pieces); i++ {
+ pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:]
+ }
+ return strings.Join(pieces, "")
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/trigram_tracer.js b/x/evm/core/tracers/js/internal/tracers/trigram_tracer.js
new file mode 100644
index 00000000..8756490d
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/trigram_tracer.js
@@ -0,0 +1,49 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+{
+ // hist is the map of trigram counters
+ hist: {},
+ // lastOp is last operation
+ lastOps: ['',''],
+ lastDepth: 0,
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) {
+ var depth = log.getDepth();
+ if (depth != this.lastDepth){
+ this.lastOps = ['',''];
+ this.lastDepth = depth;
+ return;
+ }
+ var op = log.op.toString();
+ var key = this.lastOps[0]+'-'+this.lastOps[1]+'-'+op;
+ if (this.hist[key]){
+ this.hist[key]++;
+ }
+ else {
+ this.hist[key] = 1;
+ }
+ this.lastOps[0] = this.lastOps[1];
+ this.lastOps[1] = op;
+ },
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) {},
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx) {
+ return this.hist;
+ },
+}
diff --git a/x/evm/core/tracers/js/internal/tracers/unigram_tracer.js b/x/evm/core/tracers/js/internal/tracers/unigram_tracer.js
new file mode 100644
index 00000000..51107d8f
--- /dev/null
+++ b/x/evm/core/tracers/js/internal/tracers/unigram_tracer.js
@@ -0,0 +1,41 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+{
+ // hist is the map of opcodes to counters
+ hist: {},
+ // nops counts number of ops
+ nops: 0,
+ // step is invoked for every opcode that the VM executes.
+ step: function(log, db) {
+ var op = log.op.toString();
+ if (this.hist[op]){
+ this.hist[op]++;
+ }
+ else {
+ this.hist[op] = 1;
+ }
+ this.nops++;
+ },
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) {},
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx) {
+ return this.hist;
+ },
+}
diff --git a/x/evm/core/tracers/js/tracer_test.go b/x/evm/core/tracers/js/tracer_test.go
new file mode 100644
index 00000000..c769cd64
--- /dev/null
+++ b/x/evm/core/tracers/js/tracer_test.go
@@ -0,0 +1,306 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package js
+
+import (
+ "encoding/json"
+ "errors"
+ "math/big"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+type account struct{}
+
+func (account) SubBalance(amount *big.Int) {}
+func (account) AddBalance(amount *big.Int) {}
+func (account) SetAddress(common.Address) {}
+func (account) Value() *big.Int { return nil }
+func (account) SetBalance(*big.Int) {}
+func (account) SetNonce(uint64) {}
+func (account) Balance() *big.Int { return nil }
+func (account) Address() common.Address { return common.Address{} }
+func (account) SetCode(common.Hash, []byte) {}
+func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
+
+type dummyStatedb struct {
+ state.StateDB
+}
+
+func (*dummyStatedb) GetRefund() uint64 { return 1337 }
+func (*dummyStatedb) GetBalance(addr common.Address) *big.Int { return new(big.Int) }
+
+type vmContext struct {
+ blockCtx vm.BlockContext
+ txCtx vm.TxContext
+}
+
+func testCtx() *vmContext {
+ return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
+}
+
+func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig) (json.RawMessage, error) {
+ var (
+ env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Debug: true, Tracer: tracer})
+ gasLimit uint64 = 31000
+ startGas uint64 = 10000
+ value = big.NewInt(0)
+ contract = vm.NewContract(account{}, account{}, value, startGas)
+ )
+ contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
+
+ tracer.CaptureTxStart(gasLimit)
+ tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
+ ret, err := env.Interpreter().Run(contract, []byte{}, false)
+ tracer.CaptureEnd(ret, startGas-contract.Gas, 1, err)
+ // Rest gas assumes no refund
+ tracer.CaptureTxEnd(startGas - contract.Gas)
+ if err != nil {
+ return nil, err
+ }
+ return tracer.GetResult()
+}
+
+func TestTracer(t *testing.T) {
+ execTracer := func(code string) ([]byte, string) {
+ t.Helper()
+ tracer, err := newJsTracer(code, nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err := runTrace(tracer, testCtx(), params.TestChainConfig)
+ if err != nil {
+ return nil, err.Error() // Stringify to allow comparison without nil checks
+ }
+ return ret, ""
+ }
+ for i, tt := range []struct {
+ code string
+ want string
+ fail string
+ }{
+ { // tests that we don't panic on bad arguments to memory access
+ code: "{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}",
+ want: ``,
+ fail: "tracer accessed out of bound memory: offset -1, end -2 at step (:1:53(15)) in server-side tracer function 'step'",
+ }, { // tests that we don't panic on bad arguments to stack peeks
+ code: "{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}",
+ want: ``,
+ fail: "tracer accessed out of bound stack: size 0, index -1 at step (:1:53(13)) in server-side tracer function 'step'",
+ }, { // tests that we don't panic on bad arguments to memory getUint
+ code: "{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}",
+ want: ``,
+ fail: "tracer accessed out of bound memory: available 0, offset -64, size 32 at step (:1:58(13)) in server-side tracer function 'step'",
+ }, { // tests some general counting
+ code: "{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}",
+ want: `3`,
+ }, { // tests that depth is reported correctly
+ code: "{depths: [], step: function(log) { this.depths.push(log.stack.length()); }, fault: function() {}, result: function() { return this.depths; }}",
+ want: `[0,1,2]`,
+ }, { // tests memory length
+ code: "{lengths: [], step: function(log) { this.lengths.push(log.memory.length()); }, fault: function() {}, result: function() { return this.lengths; }}",
+ want: `[0,0,0]`,
+ }, { // tests to-string of opcodes
+ code: "{opcodes: [], step: function(log) { this.opcodes.push(log.op.toString()); }, fault: function() {}, result: function() { return this.opcodes; }}",
+ want: `["PUSH1","PUSH1","STOP"]`,
+ }, { // tests intrinsic gas
+ code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed+'.'+ctx.intrinsicGas; }}",
+ want: `"100000.6.21000"`,
+ }, {
+ code: "{res: null, step: function(log) {}, fault: function() {}, result: function() { return toWord('0xffaa') }}",
+ want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":255,"31":170}`,
+ }, { // test feeding a buffer back into go
+ code: "{res: null, step: function(log) { var address = log.contract.getAddress(); this.res = toAddress(address); }, fault: function() {}, result: function() { return this.res }}",
+ want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}`,
+ }, {
+ code: "{res: null, step: function(log) { var address = '0x0000000000000000000000000000000000000000'; this.res = toAddress(address); }, fault: function() {}, result: function() { return this.res }}",
+ want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}`,
+ }, {
+ code: "{res: null, step: function(log) { var address = Array.prototype.slice.call(log.contract.getAddress()); this.res = toAddress(address); }, fault: function() {}, result: function() { return this.res }}",
+ want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}`,
+ },
+ } {
+ if have, err := execTracer(tt.code); tt.want != string(have) || tt.fail != err {
+ t.Errorf("testcase %d: expected return value to be '%s' got '%s', error to be '%s' got '%s'\n\tcode: %v", i, tt.want, string(have), tt.fail, err, tt.code)
+ }
+ }
+}
+
+func TestHalt(t *testing.T) {
+ timeout := errors.New("stahp")
+ tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ go func() {
+ time.Sleep(1 * time.Second)
+ tracer.Stop(timeout)
+ }()
+ if _, err = runTrace(tracer, testCtx(), params.TestChainConfig); !strings.Contains(err.Error(), "stahp") {
+ t.Errorf("Expected timeout error, got %v", err)
+ }
+}
+
+func TestHaltBetweenSteps(t *testing.T) {
+ tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
+ scope := &vm.ScopeContext{
+ Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ }
+ tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 0, big.NewInt(0))
+ tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
+ timeout := errors.New("stahp")
+ tracer.Stop(timeout)
+ tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
+
+ if _, err := tracer.GetResult(); !strings.Contains(err.Error(), timeout.Error()) {
+ t.Errorf("Expected timeout error, got %v", err)
+ }
+}
+
+// testNoStepExec tests a regular value transfer (no exec), and accessing the statedb
+// in 'result'
+func TestNoStepExec(t *testing.T) {
+ execTracer := func(code string) []byte {
+ t.Helper()
+ tracer, err := newJsTracer(code, nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
+ tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0))
+ tracer.CaptureEnd(nil, 0, 1, nil)
+ ret, err := tracer.GetResult()
+ if err != nil {
+ t.Fatal(err)
+ }
+ return ret
+ }
+ for i, tt := range []struct {
+ code string
+ want string
+ }{
+ { // tests that we don't panic on accessing the db methods
+ code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx, db){ return db.getBalance(ctx.to)} }",
+ want: `"0"`,
+ },
+ } {
+ if have := execTracer(tt.code); tt.want != string(have) {
+ t.Errorf("testcase %d: expected return value to be %s got %s\n\tcode: %v", i, tt.want, string(have), tt.code)
+ }
+ }
+}
+
+func TestIsPrecompile(t *testing.T) {
+ chaincfg := ¶ms.ChainConfig{ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, EIP150Block: big.NewInt(0), EIP150Hash: common.Hash{}, EIP155Block: big.NewInt(0), EIP158Block: big.NewInt(0), ByzantiumBlock: big.NewInt(100), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(200), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(300), LondonBlock: big.NewInt(0), TerminalTotalDifficulty: nil, Ethash: new(params.EthashConfig), Clique: nil}
+ chaincfg.ByzantiumBlock = big.NewInt(100)
+ chaincfg.IstanbulBlock = big.NewInt(200)
+ chaincfg.BerlinBlock = big.NewInt(300)
+ txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
+ tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150)}
+ res, err := runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg)
+ if err != nil {
+ t.Error(err)
+ }
+ if string(res) != "false" {
+ t.Errorf("tracer should not consider blake2f as precompile in byzantium")
+ }
+
+ tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil)
+ blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)}
+ res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg)
+ if err != nil {
+ t.Error(err)
+ }
+ if string(res) != "true" {
+ t.Errorf("tracer should consider blake2f as precompile in istanbul")
+ }
+}
+
+func TestEnterExit(t *testing.T) {
+ // test that either both or none of enter() and exit() are defined
+ if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context), nil); err == nil {
+ t.Fatal("tracer creation should've failed without exit() definition")
+ }
+ if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context), nil); err != nil {
+ t.Fatal(err)
+ }
+ // test that the enter and exit method are correctly invoked and the values passed
+ tracer, err := newJsTracer("{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, step: function() {}, fault: function() {}, result: function() { return {enters: this.enters, exits: this.exits, enterGas: this.enterGas, gasUsed: this.gasUsed} }, enter: function(frame) { this.enters++; this.enterGas = frame.getGas(); }, exit: function(res) { this.exits++; this.gasUsed = res.getGasUsed(); }}", new(tracers.Context), nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ scope := &vm.ScopeContext{
+ Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ }
+ tracer.CaptureEnter(vm.CALL, scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
+ tracer.CaptureExit([]byte{}, 400, nil)
+
+ have, err := tracer.GetResult()
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := `{"enters":1,"exits":1,"enterGas":1000,"gasUsed":400}`
+ if string(have) != want {
+ t.Errorf("Number of invocations of enter() and exit() is wrong. Have %s, want %s\n", have, want)
+ }
+}
+
+func TestSetup(t *testing.T) {
+ // Test empty config
+ _, err := newJsTracer(`{setup: function(cfg) { if (cfg !== "{}") { throw("invalid empty config") } }, fault: function() {}, result: function() {}}`, new(tracers.Context), nil)
+ if err != nil {
+ t.Error(err)
+ }
+
+ cfg, err := json.Marshal(map[string]string{"foo": "bar"})
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Test no setup func
+ _, err = newJsTracer(`{fault: function() {}, result: function() {}}`, new(tracers.Context), cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Test config value
+ tracer, err := newJsTracer("{config: null, setup: function(cfg) { this.config = JSON.parse(cfg) }, step: function() {}, fault: function() {}, result: function() { return this.config.foo }}", new(tracers.Context), cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ have, err := tracer.GetResult()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(have) != `"bar"` {
+ t.Errorf("tracer returned wrong result. have: %s, want: \"bar\"\n", string(have))
+ }
+}
diff --git a/x/evm/core/tracers/native/4byte.go b/x/evm/core/tracers/native/4byte.go
new file mode 100644
index 00000000..a9d47852
--- /dev/null
+++ b/x/evm/core/tracers/native/4byte.go
@@ -0,0 +1,153 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package native
+
+import (
+ "encoding/json"
+ "math/big"
+ "strconv"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func init() {
+ register("4byteTracer", newFourByteTracer)
+}
+
+// fourByteTracer searches for 4byte-identifiers, and collects them for post-processing.
+// It collects the methods identifiers along with the size of the supplied data, so
+// a reversed signature can be matched against the size of the data.
+//
+// Example:
+//
+// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"})
+// {
+// 0x27dc297e-128: 1,
+// 0x38cc4831-0: 2,
+// 0x524f3889-96: 1,
+// 0xadf59f99-288: 1,
+// 0xc281d19e-0: 1
+// }
+type fourByteTracer struct {
+ env *vm.EVM
+ ids map[string]int // ids aggregates the 4byte ids found
+ interrupt uint32 // Atomic flag to signal execution interruption
+ reason error // Textual reason for the interruption
+ activePrecompiles []common.Address // Updated on CaptureStart based on given rules
+}
+
+// newFourByteTracer returns a native go tracer which collects
+// 4 byte-identifiers of a tx, and implements vm.EVMLogger.
+func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
+ t := &fourByteTracer{
+ ids: make(map[string]int),
+ }
+ return t, nil
+}
+
+// isPrecompiled returns whether the addr is a precompile. Logic borrowed from newJsTracer in eth/tracers/js/tracer.go
+func (t *fourByteTracer) isPrecompiled(addr common.Address) bool {
+ for _, p := range t.activePrecompiles {
+ if p == addr {
+ return true
+ }
+ }
+ return false
+}
+
+// store saves the given identifier and datasize.
+func (t *fourByteTracer) store(id []byte, size int) {
+ key := bytesToHex(id) + "-" + strconv.Itoa(size)
+ t.ids[key] += 1
+}
+
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
+func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ t.env = env
+
+ // Update list of precompiles based on current block
+ rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil)
+ t.activePrecompiles = env.ActivePrecompiles(rules)
+
+ // Save the outer calldata also
+ if len(input) >= 4 {
+ t.store(input[0:4], len(input)-4)
+ }
+}
+
+// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
+func (t *fourByteTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *fourByteTracer) CaptureEnter(op vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ // Skip if tracing was interrupted
+ if atomic.LoadUint32(&t.interrupt) > 0 {
+ t.env.Cancel()
+ return
+ }
+ if len(input) < 4 {
+ return
+ }
+ // primarily we want to avoid CREATE/CREATE2/SELFDESTRUCT
+ if op != vm.DELEGATECALL && op != vm.STATICCALL &&
+ op != vm.CALL && op != vm.CALLCODE {
+ return
+ }
+ // Skip any pre-compile invocations, those are just fancy opcodes
+ if t.isPrecompiled(to) {
+ return
+ }
+ t.store(input[0:4], len(input)-4)
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *fourByteTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault.
+func (t *fourByteTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *fourByteTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
+}
+
+func (*fourByteTracer) CaptureTxStart(gasLimit uint64) {}
+
+func (*fourByteTracer) CaptureTxEnd(restGas uint64) {}
+
+// GetResult returns the json-encoded nested list of call traces, and any
+// error arising from the encoding or forceful termination (via `Stop`).
+func (t *fourByteTracer) GetResult() (json.RawMessage, error) {
+ res, err := json.Marshal(t.ids)
+ if err != nil {
+ return nil, err
+ }
+ return res, t.reason
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *fourByteTracer) Stop(err error) {
+ t.reason = err
+ atomic.StoreUint32(&t.interrupt, 1)
+}
diff --git a/x/evm/core/tracers/native/call.go b/x/evm/core/tracers/native/call.go
new file mode 100644
index 00000000..faccc46b
--- /dev/null
+++ b/x/evm/core/tracers/native/call.go
@@ -0,0 +1,202 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package native
+
+import (
+ "encoding/json"
+ "errors"
+ "math/big"
+ "strconv"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func init() {
+ register("callTracer", newCallTracer)
+}
+
+type callFrame struct {
+ Type string `json:"type"`
+ From string `json:"from"`
+ To string `json:"to,omitempty"`
+ Value string `json:"value,omitempty"`
+ Gas string `json:"gas"`
+ GasUsed string `json:"gasUsed"`
+ Input string `json:"input"`
+ Output string `json:"output,omitempty"`
+ Error string `json:"error,omitempty"`
+ Calls []callFrame `json:"calls,omitempty"`
+}
+
+type callTracer struct {
+ env *vm.EVM
+ callstack []callFrame
+ config callTracerConfig
+ interrupt uint32 // Atomic flag to signal execution interruption
+ reason error // Textual reason for the interruption
+}
+
+type callTracerConfig struct {
+ OnlyTopCall bool `json:"onlyTopCall"` // If true, call tracer won't collect any subcalls
+}
+
+// newCallTracer returns a native go tracer which tracks
+// call frames of a tx, and implements vm.EVMLogger.
+func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+ var config callTracerConfig
+ if cfg != nil {
+ if err := json.Unmarshal(cfg, &config); err != nil {
+ return nil, err
+ }
+ }
+ // First callframe contains tx context info
+ // and is populated on start and end.
+ return &callTracer{callstack: make([]callFrame, 1), config: config}, nil
+}
+
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
+func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ t.env = env
+ t.callstack[0] = callFrame{
+ Type: "CALL",
+ From: addrToHex(from),
+ To: addrToHex(to),
+ Input: bytesToHex(input),
+ Gas: uintToHex(gas),
+ Value: bigToHex(value),
+ }
+ if create {
+ t.callstack[0].Type = "CREATE"
+ }
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
+ t.callstack[0].GasUsed = uintToHex(gasUsed)
+ if err != nil {
+ t.callstack[0].Error = err.Error()
+ if err.Error() == "execution reverted" && len(output) > 0 {
+ t.callstack[0].Output = bytesToHex(output)
+ }
+ } else {
+ t.callstack[0].Output = bytesToHex(output)
+ }
+}
+
+// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
+func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault.
+func (t *callTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ if t.config.OnlyTopCall {
+ return
+ }
+ // Skip if tracing was interrupted
+ if atomic.LoadUint32(&t.interrupt) > 0 {
+ t.env.Cancel()
+ return
+ }
+
+ call := callFrame{
+ Type: typ.String(),
+ From: addrToHex(from),
+ To: addrToHex(to),
+ Input: bytesToHex(input),
+ Gas: uintToHex(gas),
+ Value: bigToHex(value),
+ }
+ t.callstack = append(t.callstack, call)
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+ if t.config.OnlyTopCall {
+ return
+ }
+ size := len(t.callstack)
+ if size <= 1 {
+ return
+ }
+ // pop call
+ call := t.callstack[size-1]
+ t.callstack = t.callstack[:size-1]
+ size -= 1
+
+ call.GasUsed = uintToHex(gasUsed)
+ if err == nil {
+ call.Output = bytesToHex(output)
+ } else {
+ call.Error = err.Error()
+ if call.Type == "CREATE" || call.Type == "CREATE2" {
+ call.To = ""
+ }
+ }
+ t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
+}
+
+func (*callTracer) CaptureTxStart(gasLimit uint64) {}
+
+func (*callTracer) CaptureTxEnd(restGas uint64) {}
+
+// GetResult returns the json-encoded nested list of call traces, and any
+// error arising from the encoding or forceful termination (via `Stop`).
+func (t *callTracer) GetResult() (json.RawMessage, error) {
+ if len(t.callstack) != 1 {
+ return nil, errors.New("incorrect number of top-level calls")
+ }
+ res, err := json.Marshal(t.callstack[0])
+ if err != nil {
+ return nil, err
+ }
+ return json.RawMessage(res), t.reason
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *callTracer) Stop(err error) {
+ t.reason = err
+ atomic.StoreUint32(&t.interrupt, 1)
+}
+
+func bytesToHex(s []byte) string {
+ return "0x" + common.Bytes2Hex(s)
+}
+
+func bigToHex(n *big.Int) string {
+ if n == nil {
+ return ""
+ }
+ return "0x" + n.Text(16)
+}
+
+func uintToHex(n uint64) string {
+ return "0x" + strconv.FormatUint(n, 16)
+}
+
+func addrToHex(a common.Address) string {
+ return strings.ToLower(a.Hex())
+}
diff --git a/x/evm/core/tracers/native/noop.go b/x/evm/core/tracers/native/noop.go
new file mode 100644
index 00000000..91dfdbed
--- /dev/null
+++ b/x/evm/core/tracers/native/noop.go
@@ -0,0 +1,78 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package native
+
+import (
+ "encoding/json"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func init() {
+ register("noopTracer", newNoopTracer)
+}
+
+// noopTracer is a go implementation of the Tracer interface which
+// performs no action. It's mostly useful for testing purposes.
+type noopTracer struct{}
+
+// newNoopTracer returns a new noop tracer.
+func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
+ return &noopTracer{}, nil
+}
+
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
+func (t *noopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
+}
+
+// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
+func (t *noopTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault.
+func (t *noopTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *noopTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *noopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+}
+
+func (*noopTracer) CaptureTxStart(gasLimit uint64) {}
+
+func (*noopTracer) CaptureTxEnd(restGas uint64) {}
+
+// GetResult returns an empty json object.
+func (t *noopTracer) GetResult() (json.RawMessage, error) {
+ return json.RawMessage(`{}`), nil
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *noopTracer) Stop(err error) {
+}
diff --git a/x/evm/core/tracers/native/prestate.go b/x/evm/core/tracers/native/prestate.go
new file mode 100644
index 00000000..35a1117e
--- /dev/null
+++ b/x/evm/core/tracers/native/prestate.go
@@ -0,0 +1,180 @@
+// Copyright 2022 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package native
+
+import (
+ "encoding/json"
+ "math/big"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func init() {
+ register("prestateTracer", newPrestateTracer)
+}
+
+type (
+ prestate = map[common.Address]*account
+ account struct {
+ Balance string `json:"balance"`
+ Nonce uint64 `json:"nonce"`
+ Code string `json:"code"`
+ Storage map[common.Hash]common.Hash `json:"storage"`
+ }
+)
+
+type prestateTracer struct {
+ env *vm.EVM
+ prestate prestate
+ create bool
+ to common.Address
+ gasLimit uint64 // Amount of gas bought for the whole tx
+ interrupt uint32 // Atomic flag to signal execution interruption
+ reason error // Textual reason for the interruption
+}
+
+func newPrestateTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
+ // First callframe contains tx context info
+ // and is populated on start and end.
+ return &prestateTracer{prestate: prestate{}}, nil
+}
+
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
+func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ t.env = env
+ t.create = create
+ t.to = to
+
+ t.lookupAccount(from)
+ t.lookupAccount(to)
+
+ // The recipient balance includes the value transferred.
+ toBal := hexutil.MustDecodeBig(t.prestate[to].Balance)
+ toBal = new(big.Int).Sub(toBal, value)
+ t.prestate[to].Balance = hexutil.EncodeBig(toBal)
+
+ // The sender balance is after reducing: value and gasLimit.
+ // We need to re-add them to get the pre-tx balance.
+ fromBal := hexutil.MustDecodeBig(t.prestate[from].Balance)
+ gasPrice := env.TxContext.GasPrice
+ consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit))
+ fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas))
+ t.prestate[from].Balance = hexutil.EncodeBig(fromBal)
+ t.prestate[from].Nonce--
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *prestateTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
+ if t.create {
+ // Exclude created contract.
+ delete(t.prestate, t.to)
+ }
+}
+
+// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
+func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ stack := scope.Stack
+ stackData := stack.Data
+ stackLen := len(stackData)
+ switch {
+ case stackLen >= 1 && (op == vm.SLOAD || op == vm.SSTORE):
+ slot := common.Hash(stackData[stackLen-1].Bytes32())
+ t.lookupStorage(scope.Contract.Address(), slot)
+ case stackLen >= 1 && (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT):
+ addr := common.Address(stackData[stackLen-1].Bytes20())
+ t.lookupAccount(addr)
+ case stackLen >= 5 && (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE):
+ addr := common.Address(stackData[stackLen-2].Bytes20())
+ t.lookupAccount(addr)
+ case op == vm.CREATE:
+ addr := scope.Contract.Address()
+ nonce := t.env.StateDB.GetNonce(addr)
+ t.lookupAccount(crypto.CreateAddress(addr, nonce))
+ case stackLen >= 4 && op == vm.CREATE2:
+ offset := stackData[stackLen-2]
+ size := stackData[stackLen-3]
+ init := scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
+ inithash := crypto.Keccak256(init)
+ salt := stackData[stackLen-4]
+ t.lookupAccount(crypto.CreateAddress2(scope.Contract.Address(), salt.Bytes32(), inithash))
+ }
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault.
+func (t *prestateTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *prestateTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *prestateTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+}
+
+func (t *prestateTracer) CaptureTxStart(gasLimit uint64) {
+ t.gasLimit = gasLimit
+}
+
+func (t *prestateTracer) CaptureTxEnd(restGas uint64) {}
+
+// GetResult returns the json-encoded nested list of call traces, and any
+// error arising from the encoding or forceful termination (via `Stop`).
+func (t *prestateTracer) GetResult() (json.RawMessage, error) {
+ res, err := json.Marshal(t.prestate)
+ if err != nil {
+ return nil, err
+ }
+ return json.RawMessage(res), t.reason
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *prestateTracer) Stop(err error) {
+ t.reason = err
+ atomic.StoreUint32(&t.interrupt, 1)
+}
+
+// lookupAccount fetches details of an account and adds it to the prestate
+// if it doesn't exist there.
+func (t *prestateTracer) lookupAccount(addr common.Address) {
+ if _, ok := t.prestate[addr]; ok {
+ return
+ }
+ t.prestate[addr] = &account{
+ Balance: bigToHex(t.env.StateDB.GetBalance(addr)),
+ Nonce: t.env.StateDB.GetNonce(addr),
+ Code: bytesToHex(t.env.StateDB.GetCode(addr)),
+ Storage: make(map[common.Hash]common.Hash),
+ }
+}
+
+// lookupStorage fetches the requested storage slot and adds
+// it to the prestate of the given contract. It assumes `lookupAccount`
+// has been performed on the contract before.
+func (t *prestateTracer) lookupStorage(addr common.Address, key common.Hash) {
+ if _, ok := t.prestate[addr].Storage[key]; ok {
+ return
+ }
+ t.prestate[addr].Storage[key] = t.env.StateDB.GetState(addr, key)
+}
diff --git a/x/evm/core/tracers/native/revertreason.go b/x/evm/core/tracers/native/revertreason.go
new file mode 100644
index 00000000..ed2a7ca8
--- /dev/null
+++ b/x/evm/core/tracers/native/revertreason.go
@@ -0,0 +1,108 @@
+// Copyright 2022 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package native
+
+import (
+ "bytes"
+ "encoding/json"
+ "math/big"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+func init() {
+ register("revertReasonTracer", newRevertReasonTracer)
+}
+
+var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
+
+// revertReasonTracer is a go implementation of the Tracer interface which
+// track the error message or revert reason return by the contract.
+type revertReasonTracer struct {
+ env *vm.EVM
+ revertReason string // The revert reason return from the tx, if tx success, empty string return
+ interrupt uint32 // Atomic flag to signal execution interruption
+ reason error // Textual reason for the interruption
+}
+
+// newRevertReasonTracer returns a new revert reason tracer.
+func newRevertReasonTracer(_ *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
+ return &revertReasonTracer{}, nil
+}
+
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
+func (t *revertReasonTracer) CaptureStart(env *vm.EVM, _ common.Address, _ common.Address, _ bool, _ []byte, _ uint64, _ *big.Int) {
+ t.env = env
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *revertReasonTracer) CaptureEnd(output []byte, _ uint64, _ time.Duration, err error) {
+ if err != nil {
+ if err == vm.ErrExecutionReverted && len(output) > 4 && bytes.Equal(output[:4], revertSelector) {
+ errMsg, _ := abi.UnpackRevert(output)
+ t.revertReason = err.Error() + ": " + errMsg
+ } else {
+ t.revertReason = err.Error()
+ }
+ }
+}
+
+// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
+func (t *revertReasonTracer) CaptureState(_ uint64, _ vm.OpCode, _, _ uint64, _ *vm.ScopeContext, _ []byte, _ int, _ error) {
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault.
+func (t *revertReasonTracer) CaptureFault(_ uint64, _ vm.OpCode, _, _ uint64, _ *vm.ScopeContext, _ int, _ error) {
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *revertReasonTracer) CaptureEnter(_ vm.OpCode, _ common.Address, _ common.Address, _ []byte, _ uint64, _ *big.Int) {
+ // Skip if tracing was interrupted
+ if atomic.LoadUint32(&t.interrupt) > 0 {
+ t.env.Cancel()
+ return
+ }
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *revertReasonTracer) CaptureExit(_ []byte, _ uint64, _ error) {}
+
+func (t *revertReasonTracer) CaptureTxStart(_ uint64) {}
+
+func (t *revertReasonTracer) CaptureTxEnd(_ uint64) {}
+
+// GetResult returns an error message json object.
+func (t *revertReasonTracer) GetResult() (json.RawMessage, error) {
+ res, err := json.Marshal(t.revertReason)
+ if err != nil {
+ return nil, err
+ }
+ return res, t.reason
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *revertReasonTracer) Stop(err error) {
+ t.reason = err
+ atomic.StoreUint32(&t.interrupt, 1)
+}
diff --git a/x/evm/core/tracers/native/tracer.go b/x/evm/core/tracers/native/tracer.go
new file mode 100644
index 00000000..bc16a1f9
--- /dev/null
+++ b/x/evm/core/tracers/native/tracer.go
@@ -0,0 +1,85 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+/*
+Package native is a collection of tracers written in go.
+
+In order to add a native tracer and have it compiled into the binary, a new
+file needs to be added to this folder, containing an implementation of the
+`eth.tracers.Tracer` interface.
+
+Aside from implementing the tracer, it also needs to register itself, using the
+`register` method -- and this needs to be done in the package initialization.
+
+Example:
+
+```golang
+
+ func init() {
+ register("noopTracerNative", newNoopTracer)
+ }
+
+```
+*/
+package native
+
+import (
+ "encoding/json"
+ "errors"
+
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+)
+
+// init registers itself this packages as a lookup for tracers.
+func init() {
+ tracers.RegisterLookup(false, lookup)
+}
+
+// ctorFn is the constructor signature of a native tracer.
+type ctorFn = func(*tracers.Context, json.RawMessage) (tracers.Tracer, error)
+
+/*
+ctors is a map of package-local tracer constructors.
+
+We cannot be certain about the order of init-functions within a package,
+The go spec (https://golang.org/ref/spec#Package_initialization) says
+
+> To ensure reproducible initialization behavior, build systems
+> are encouraged to present multiple files belonging to the same
+> package in lexical file name order to a compiler.
+
+Hence, we cannot make the map in init, but must make it upon first use.
+*/
+var ctors map[string]ctorFn
+
+// register is used by native tracers to register their presence.
+func register(name string, ctor ctorFn) {
+ if ctors == nil {
+ ctors = make(map[string]ctorFn)
+ }
+ ctors[name] = ctor
+}
+
+// lookup returns a tracer, if one can be matched to the given name.
+func lookup(name string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+ if ctors == nil {
+ ctors = make(map[string]ctorFn)
+ }
+ if ctor, ok := ctors[name]; ok {
+ return ctor(ctx, cfg)
+ }
+ return nil, errors.New("no tracer found")
+}
diff --git a/x/evm/core/tracers/tracers.go b/x/evm/core/tracers/tracers.go
new file mode 100644
index 00000000..50785b0f
--- /dev/null
+++ b/x/evm/core/tracers/tracers.go
@@ -0,0 +1,52 @@
+package tracers
+
+import (
+ "encoding/json"
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// Context contains some contextual infos for a transaction execution that is not
+// available from within the EVM object.
+type Context struct {
+ BlockHash common.Hash // Hash of the block the tx is contained within (zero if dangling tx or call)
+ TxIndex int // Index of the transaction within a block (zero if dangling tx or call)
+ TxHash common.Hash // Hash of the transaction being traced (zero if dangling call)
+}
+
+// Tracer interface extends vm.EVMLogger and additionally
+// allows collecting the tracing result.
+type Tracer interface {
+ vm.EVMLogger
+ GetResult() (json.RawMessage, error)
+ // Stop terminates execution of the tracer at the first opportune moment.
+ Stop(err error)
+}
+
+type lookupFunc func(string, *Context, json.RawMessage) (Tracer, error)
+
+var lookups []lookupFunc
+
+// RegisterLookup registers a method as a lookup for tracers, meaning that
+// users can invoke a named tracer through that lookup. If 'wildcard' is true,
+// then the lookup will be placed last. This is typically meant for interpreted
+// engines (js) which can evaluate dynamic user-supplied code.
+func RegisterLookup(wildcard bool, lookup lookupFunc) {
+ if wildcard {
+ lookups = append(lookups, lookup)
+ } else {
+ lookups = append([]lookupFunc{lookup}, lookups...)
+ }
+}
+
+// registered lookups.
+func New(code string, ctx *Context, cfg json.RawMessage) (Tracer, error) {
+ for _, lookup := range lookups {
+ if tracer, err := lookup(code, ctx, cfg); err == nil {
+ return tracer, nil
+ }
+ }
+ return nil, errors.New("tracer not found")
+}
diff --git a/x/evm/core/vm/analysis.go b/x/evm/core/vm/analysis.go
new file mode 100644
index 00000000..4aa8cfe7
--- /dev/null
+++ b/x/evm/core/vm/analysis.go
@@ -0,0 +1,118 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+const (
+ set2BitsMask = uint16(0b11)
+ set3BitsMask = uint16(0b111)
+ set4BitsMask = uint16(0b1111)
+ set5BitsMask = uint16(0b1_1111)
+ set6BitsMask = uint16(0b11_1111)
+ set7BitsMask = uint16(0b111_1111)
+)
+
+// bitvec is a bit vector which maps bytes in a program.
+// An unset bit means the byte is an opcode, a set bit means
+// it's data (i.e. argument of PUSHxx).
+type bitvec []byte
+
+func (bits bitvec) set1(pos uint64) {
+ bits[pos/8] |= 1 << (pos % 8)
+}
+
+func (bits bitvec) setN(flag uint16, pos uint64) {
+ a := flag << (pos % 8)
+ bits[pos/8] |= byte(a)
+ if b := byte(a >> 8); b != 0 {
+ bits[pos/8+1] = b
+ }
+}
+
+func (bits bitvec) set8(pos uint64) {
+ a := byte(0xFF << (pos % 8))
+ bits[pos/8] |= a
+ bits[pos/8+1] = ^a
+}
+
+func (bits bitvec) set16(pos uint64) {
+ a := byte(0xFF << (pos % 8))
+ bits[pos/8] |= a
+ bits[pos/8+1] = 0xFF
+ bits[pos/8+2] = ^a
+}
+
+// codeSegment checks if the position is in a code segment.
+func (bits *bitvec) codeSegment(pos uint64) bool {
+ return (((*bits)[pos/8] >> (pos % 8)) & 1) == 0
+}
+
+// codeBitmap collects data locations in code.
+func codeBitmap(code []byte) bitvec {
+ // The bitmap is 4 bytes longer than necessary, in case the code
+ // ends with a PUSH32, the algorithm will push zeroes onto the
+ // bitvector outside the bounds of the actual code.
+ bits := make(bitvec, len(code)/8+1+4)
+ return codeBitmapInternal(code, bits)
+}
+
+// codeBitmapInternal is the internal implementation of codeBitmap.
+// It exists for the purpose of being able to run benchmark tests
+// without dynamic allocations affecting the results.
+func codeBitmapInternal(code, bits bitvec) bitvec {
+ for pc := uint64(0); pc < uint64(len(code)); {
+ op := OpCode(code[pc])
+ pc++
+ if int8(op) < int8(PUSH1) { // If not PUSH (the int8(op) > int(PUSH32) is always false).
+ continue
+ }
+ numbits := op - PUSH1 + 1
+ if numbits >= 8 {
+ for ; numbits >= 16; numbits -= 16 {
+ bits.set16(pc)
+ pc += 16
+ }
+ for ; numbits >= 8; numbits -= 8 {
+ bits.set8(pc)
+ pc += 8
+ }
+ }
+ switch numbits {
+ case 1:
+ bits.set1(pc)
+ pc += 1
+ case 2:
+ bits.setN(set2BitsMask, pc)
+ pc += 2
+ case 3:
+ bits.setN(set3BitsMask, pc)
+ pc += 3
+ case 4:
+ bits.setN(set4BitsMask, pc)
+ pc += 4
+ case 5:
+ bits.setN(set5BitsMask, pc)
+ pc += 5
+ case 6:
+ bits.setN(set6BitsMask, pc)
+ pc += 6
+ case 7:
+ bits.setN(set7BitsMask, pc)
+ pc += 7
+ }
+ }
+ return bits
+}
diff --git a/x/evm/core/vm/analysis_test.go b/x/evm/core/vm/analysis_test.go
new file mode 100644
index 00000000..5293e80a
--- /dev/null
+++ b/x/evm/core/vm/analysis_test.go
@@ -0,0 +1,110 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "math/bits"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+func TestJumpDestAnalysis(t *testing.T) {
+ tests := []struct {
+ code []byte
+ exp byte
+ which int
+ }{
+ {[]byte{byte(PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0},
+ {[]byte{byte(PUSH1), byte(PUSH1), byte(PUSH1), byte(PUSH1)}, 0b0000_1010, 0},
+ {[]byte{0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1)}, 0b0101_0100, 0},
+ {[]byte{byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), 0x01, 0x01, 0x01}, bits.Reverse8(0x7F), 0},
+ {[]byte{byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 1},
+ {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), byte(PUSH2), byte(PUSH2), 0x01, 0x01, 0x01}, 0b1100_0000, 0},
+ {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1},
+ {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0010_1110, 0},
+ {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1},
+ {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1100, 0},
+ {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0011, 1},
+ {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1110, 0},
+ {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1111, 1},
+ {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 2},
+ {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b1111_1110, 0},
+ {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b0000_0101, 1},
+ {[]byte{byte(PUSH32)}, 0b1111_1110, 0},
+ {[]byte{byte(PUSH32)}, 0b1111_1111, 1},
+ {[]byte{byte(PUSH32)}, 0b1111_1111, 2},
+ {[]byte{byte(PUSH32)}, 0b1111_1111, 3},
+ {[]byte{byte(PUSH32)}, 0b0000_0001, 4},
+ }
+ for i, test := range tests {
+ ret := codeBitmap(test.code)
+ if ret[test.which] != test.exp {
+ t.Fatalf("test %d: expected %x, got %02x", i, test.exp, ret[test.which])
+ }
+ }
+}
+
+const analysisCodeSize = 1200 * 1024
+
+func BenchmarkJumpdestAnalysis_1200k(bench *testing.B) {
+ // 1.4 ms
+ code := make([]byte, analysisCodeSize)
+ bench.SetBytes(analysisCodeSize)
+ bench.ResetTimer()
+ for i := 0; i < bench.N; i++ {
+ codeBitmap(code)
+ }
+ bench.StopTimer()
+}
+
+func BenchmarkJumpdestHashing_1200k(bench *testing.B) {
+ // 4 ms
+ code := make([]byte, analysisCodeSize)
+ bench.SetBytes(analysisCodeSize)
+ bench.ResetTimer()
+ for i := 0; i < bench.N; i++ {
+ crypto.Keccak256Hash(code)
+ }
+ bench.StopTimer()
+}
+
+func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
+ var op OpCode
+ bencher := func(b *testing.B) {
+ code := make([]byte, analysisCodeSize)
+ b.SetBytes(analysisCodeSize)
+ for i := range code {
+ code[i] = byte(op)
+ }
+ bits := make(bitvec, len(code)/8+1+4)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ for j := range bits {
+ bits[j] = 0
+ }
+ codeBitmapInternal(code, bits)
+ }
+ }
+ for op = PUSH1; op <= PUSH32; op++ {
+ bench.Run(op.String(), bencher)
+ }
+ op = JUMPDEST
+ bench.Run(op.String(), bencher)
+ op = STOP
+ bench.Run(op.String(), bencher)
+}
diff --git a/x/evm/core/vm/common.go b/x/evm/core/vm/common.go
new file mode 100644
index 00000000..90ba4a4a
--- /dev/null
+++ b/x/evm/core/vm/common.go
@@ -0,0 +1,82 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/holiman/uint256"
+)
+
+// calcMemSize64 calculates the required memory size, and returns
+// the size and whether the result overflowed uint64
+func calcMemSize64(off, l *uint256.Int) (uint64, bool) {
+ if !l.IsUint64() {
+ return 0, true
+ }
+ return calcMemSize64WithUint(off, l.Uint64())
+}
+
+// calcMemSize64WithUint calculates the required memory size, and returns
+// the size and whether the result overflowed uint64
+// Identical to calcMemSize64, but length is a uint64
+func calcMemSize64WithUint(off *uint256.Int, length64 uint64) (uint64, bool) {
+ // if length is zero, memsize is always zero, regardless of offset
+ if length64 == 0 {
+ return 0, false
+ }
+ // Check that offset doesn't overflow
+ offset64, overflow := off.Uint64WithOverflow()
+ if overflow {
+ return 0, true
+ }
+ val := offset64 + length64
+ // if value < either of it's parts, then it overflowed
+ return val, val < offset64
+}
+
+// getData returns a slice from the data based on the start and size and pads
+// up to size with zero's. This function is overflow safe.
+func getData(data []byte, start uint64, size uint64) []byte {
+ length := uint64(len(data))
+ if start > length {
+ start = length
+ }
+ end := start + size
+ if end > length {
+ end = length
+ }
+ return common.RightPadBytes(data[start:end], int(size))
+}
+
+// toWordSize returns the ceiled word size required for memory expansion.
+func toWordSize(size uint64) uint64 {
+ if size > math.MaxUint64-31 {
+ return math.MaxUint64/32 + 1
+ }
+
+ return (size + 31) / 32
+}
+
+func allZero(b []byte) bool {
+ for _, byte := range b {
+ if byte != 0 {
+ return false
+ }
+ }
+ return true
+}
diff --git a/x/evm/core/vm/contract.go b/x/evm/core/vm/contract.go
new file mode 100644
index 00000000..cf820ce2
--- /dev/null
+++ b/x/evm/core/vm/contract.go
@@ -0,0 +1,238 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/holiman/uint256"
+)
+
+// ContractRef is a reference to the contract's backing object
+type ContractRef interface {
+ // Address returns the contract's address
+ Address() common.Address
+}
+
+// AccountRef implements ContractRef.
+//
+// Account references are used during EVM initialisation and
+// it's primary use is to fetch addresses. Removing this object
+// proves difficult because of the cached jump destinations which
+// are fetched from the parent contract (i.e. the caller), which
+// is a ContractRef.
+type AccountRef common.Address
+
+// Address casts AccountRef to a Address
+func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
+
+// Contract represents an ethereum contract in the state database. It contains
+// the contract code, calling arguments. Contract implements ContractRef
+type Contract struct {
+ // CallerAddress is the result of the caller which initialised this
+ // contract. However when the "call method" is delegated this value
+ // needs to be initialised to that of the caller's caller.
+ CallerAddress common.Address
+ caller ContractRef
+ self ContractRef
+
+ jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
+ analysis bitvec // Locally cached result of JUMPDEST analysis
+
+ Code []byte
+ CodeHash common.Hash
+ CodeAddr *common.Address
+ Input []byte
+
+ Gas uint64
+ value *big.Int
+ isPrecompile bool
+}
+
+// NewContract returns a new contract environment for the execution of EVM.
+func NewContract(caller, object ContractRef, value *big.Int, gas uint64) *Contract {
+ c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object}
+
+ if parent, ok := caller.(*Contract); ok {
+ // Reuse JUMPDEST analysis from parent context if available.
+ c.jumpdests = parent.jumpdests
+ } else {
+ c.jumpdests = make(map[common.Hash]bitvec)
+ }
+
+ // Gas should be a pointer so it can safely be reduced through the run
+ // This pointer will be off the state transition
+ c.Gas = gas
+ // ensures a value is set
+ c.value = value
+
+ return c
+}
+
+// NewPrecompile returns a new instance of a precompiled contract environment for the execution of EVM.
+func NewPrecompile(caller, object ContractRef, value *big.Int, gas uint64) *Contract {
+ c := &Contract{
+ CallerAddress: caller.Address(),
+ caller: caller,
+ self: object,
+ isPrecompile: true,
+ }
+
+ // Gas should be a pointer so it can safely be reduced through the run
+ // This pointer will be off the state transition
+ c.Gas = gas
+ // ensures a value is set
+ c.value = value
+
+ return c
+}
+
+// IsPrecompile returns true if the contract is a precompiled contract environment
+func (c Contract) IsPrecompile() bool {
+ return c.isPrecompile
+}
+
+func (c *Contract) validJumpdest(dest *uint256.Int) bool {
+ if c.isPrecompile {
+ return false
+ }
+
+ udest, overflow := dest.Uint64WithOverflow()
+ // PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
+ // Don't bother checking for JUMPDEST in that case.
+ if overflow || udest >= uint64(len(c.Code)) {
+ return false
+ }
+ // Only JUMPDESTs allowed for destinations
+ if OpCode(c.Code[udest]) != JUMPDEST {
+ return false
+ }
+ return c.isCode(udest)
+}
+
+// isCode returns true if the provided PC location is an actual opcode, as
+// opposed to a data-segment following a PUSHN operation.
+func (c *Contract) isCode(udest uint64) bool {
+ if c.isPrecompile {
+ return false
+ }
+
+ // Do we already have an analysis laying around?
+ if c.analysis != nil {
+ return c.analysis.codeSegment(udest)
+ }
+ // Do we have a contract hash already?
+ // If we do have a hash, that means it's a 'regular' contract. For regular
+ // contracts ( not temporary initcode), we store the analysis in a map
+ if c.CodeHash != (common.Hash{}) {
+ // Does parent context have the analysis?
+ analysis, exist := c.jumpdests[c.CodeHash]
+ if !exist {
+ // Do the analysis and save in parent context
+ // We do not need to store it in c.analysis
+ analysis = codeBitmap(c.Code)
+ c.jumpdests[c.CodeHash] = analysis
+ }
+ // Also stash it in current contract for faster access
+ c.analysis = analysis
+ return analysis.codeSegment(udest)
+ }
+ // We don't have the code hash, most likely a piece of initcode not already
+ // in state trie. In that case, we do an analysis, and save it locally, so
+ // we don't have to recalculate it for every JUMP instruction in the execution
+ // However, we don't save it within the parent context
+ if c.analysis == nil {
+ c.analysis = codeBitmap(c.Code)
+ }
+ return c.analysis.codeSegment(udest)
+}
+
+// AsDelegate sets the contract to be a delegate call and returns the current
+// contract (for chaining calls)
+func (c *Contract) AsDelegate() *Contract {
+ if c.isPrecompile {
+ return c
+ }
+ // NOTE: caller must, at all times be a contract. It should never happen
+ // that caller is something other than a Contract.
+ parent := c.caller.(*Contract)
+ c.CallerAddress = parent.CallerAddress
+ c.value = parent.value
+
+ return c
+}
+
+// GetOp returns the n'th element in the contract's byte array
+func (c *Contract) GetOp(n uint64) OpCode {
+ if n < uint64(len(c.Code)) {
+ return OpCode(c.Code[n])
+ }
+
+ return STOP
+}
+
+// Caller returns the caller of the contract.
+//
+// Caller will recursively call caller when the contract is a delegate
+// call, including that of caller's caller.
+func (c *Contract) Caller() common.Address {
+ return c.CallerAddress
+}
+
+// UseGas attempts the use gas and subtracts it and returns true on success
+func (c *Contract) UseGas(gas uint64) (ok bool) {
+ if c.Gas < gas {
+ return false
+ }
+ c.Gas -= gas
+ return true
+}
+
+// Address returns the contracts address
+func (c *Contract) Address() common.Address {
+ return c.self.Address()
+}
+
+// Value returns the contract's value (sent to it from it's caller)
+func (c *Contract) Value() *big.Int {
+ return c.value
+}
+
+// SetCallCode sets the code of the contract and address of the backing data
+// object
+func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
+ if c.isPrecompile {
+ return
+ }
+
+ c.Code = code
+ c.CodeHash = hash
+ c.CodeAddr = addr
+}
+
+// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash.
+// In case hash is not provided, the jumpdest analysis will not be saved to the parent context
+func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash) {
+ if c.isPrecompile {
+ return
+ }
+
+ c.Code = codeAndHash.code
+ c.CodeHash = codeAndHash.hash
+ c.CodeAddr = addr
+}
diff --git a/x/evm/core/vm/contracts.go b/x/evm/core/vm/contracts.go
new file mode 100644
index 00000000..c9dc17d7
--- /dev/null
+++ b/x/evm/core/vm/contracts.go
@@ -0,0 +1,1313 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/blake2b"
+ "github.com/ethereum/go-ethereum/crypto/bls12381"
+ "github.com/ethereum/go-ethereum/crypto/bn256"
+ "github.com/ethereum/go-ethereum/params"
+ "golang.org/x/crypto/ripemd160"
+)
+
+// PrecompiledContract is the basic interface for native Go contracts. The implementation
+// requires a deterministic gas count based on the input size of the Run method of the
+// contract.
+type PrecompiledContract interface {
+ ContractRef
+ // RequiredGas calculates the contract gas used
+ RequiredGas(input []byte) uint64
+ // Run runs the precompiled contract
+ Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error)
+}
+
+// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
+// contracts used in the Frontier and Homestead releases.
+var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
+ ecrecover{}.Address(): &ecrecover{},
+ sha256hash{}.Address(): &sha256hash{},
+ ripemd160hash{}.Address(): &ripemd160hash{},
+ dataCopy{}.Address(): &dataCopy{},
+}
+
+// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
+// contracts used in the Byzantium release.
+var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
+ ecrecover{}.Address(): &ecrecover{},
+ sha256hash{}.Address(): &sha256hash{},
+ ripemd160hash{}.Address(): &ripemd160hash{},
+ dataCopy{}.Address(): &dataCopy{},
+ bigModExp{}.Address(): &bigModExp{eip2565: false},
+ bn256AddByzantium{}.Address(): &bn256AddByzantium{},
+ bn256ScalarMulByzantium{}.Address(): &bn256ScalarMulByzantium{},
+ bn256PairingByzantium{}.Address(): &bn256PairingByzantium{},
+}
+
+// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
+// contracts used in the Istanbul release.
+var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
+ ecrecover{}.Address(): &ecrecover{},
+ sha256hash{}.Address(): &sha256hash{},
+ ripemd160hash{}.Address(): &ripemd160hash{},
+ dataCopy{}.Address(): &dataCopy{},
+ bigModExp{}.Address(): &bigModExp{eip2565: false},
+ bn256AddIstanbul{}.Address(): &bn256AddIstanbul{},
+ bn256ScalarMulIstanbul{}.Address(): &bn256ScalarMulIstanbul{},
+ bn256PairingIstanbul{}.Address(): &bn256PairingIstanbul{},
+ blake2F{}.Address(): &blake2F{},
+}
+
+// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
+// contracts used in the Berlin release.
+var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
+ ecrecover{}.Address(): &ecrecover{},
+ sha256hash{}.Address(): &sha256hash{},
+ ripemd160hash{}.Address(): &ripemd160hash{},
+ dataCopy{}.Address(): &dataCopy{},
+ bigModExp{}.Address(): &bigModExp{eip2565: true},
+ bn256AddIstanbul{}.Address(): &bn256AddIstanbul{},
+ bn256ScalarMulIstanbul{}.Address(): &bn256ScalarMulIstanbul{},
+ bn256PairingIstanbul{}.Address(): &bn256PairingIstanbul{},
+ blake2F{}.Address(): &blake2F{},
+}
+
+// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
+// contracts specified in EIP-2537. These are exported for testing purposes.
+var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
+ bls12381G1Add{}.Address(): &bls12381G1Add{},
+ bls12381G1Mul{}.Address(): &bls12381G1Mul{},
+ bls12381G1MultiExp{}.Address(): &bls12381G1MultiExp{},
+ bls12381G2Add{}.Address(): &bls12381G2Add{},
+ bls12381G2Mul{}.Address(): &bls12381G2Mul{},
+ bls12381G2MultiExp{}.Address(): &bls12381G2MultiExp{},
+ bls12381Pairing{}.Address(): &bls12381Pairing{},
+ bls12381MapG1{}.Address(): &bls12381MapG1{},
+ bls12381MapG2{}.Address(): &bls12381MapG2{},
+}
+
+var (
+ // PrecompiledAddressesBerlin defines the default set of pre-compiled
+ // Ethereum contract addresses used in the Berlin release.
+ PrecompiledAddressesBerlin = []common.Address{
+ ecrecover{}.Address(),
+ sha256hash{}.Address(),
+ ripemd160hash{}.Address(),
+ dataCopy{}.Address(),
+ bigModExp{}.Address(),
+ bn256AddIstanbul{}.Address(),
+ bn256ScalarMulIstanbul{}.Address(),
+ bn256PairingIstanbul{}.Address(),
+ blake2F{}.Address(),
+ }
+ // PrecompiledAddressesIstanbul defines the default set of pre-compiled
+ // Ethereum contract addresses used in the Istanbul release.
+ PrecompiledAddressesIstanbul = []common.Address{
+ ecrecover{}.Address(),
+ sha256hash{}.Address(),
+ ripemd160hash{}.Address(),
+ dataCopy{}.Address(),
+ bigModExp{}.Address(),
+ bn256AddIstanbul{}.Address(),
+ bn256ScalarMulIstanbul{}.Address(),
+ bn256PairingIstanbul{}.Address(),
+ blake2F{}.Address(),
+ }
+ // PrecompiledAddressesByzantium defines the default set of pre-compiled
+ // Ethereum contract addresses used in the Byzantium release.
+ PrecompiledAddressesByzantium = []common.Address{
+ ecrecover{}.Address(),
+ sha256hash{}.Address(),
+ ripemd160hash{}.Address(),
+ dataCopy{}.Address(),
+ bigModExp{}.Address(),
+ bn256AddByzantium{}.Address(),
+ bn256ScalarMulByzantium{}.Address(),
+ bn256PairingByzantium{}.Address(),
+ }
+ // PrecompiledAddressesHomestead defines the default set of pre-compiled
+ // Ethereum contract addresses used in the Homestead release.
+ PrecompiledAddressesHomestead = []common.Address{
+ ecrecover{}.Address(),
+ sha256hash{}.Address(),
+ ripemd160hash{}.Address(),
+ dataCopy{}.Address(),
+ }
+)
+
+// DefaultActivePrecompiles returns the set of precompiles enabled with the default configuration.
+func DefaultActivePrecompiles(rules params.Rules) []common.Address {
+ switch {
+ case rules.IsBerlin:
+ return PrecompiledAddressesBerlin
+ case rules.IsIstanbul:
+ return PrecompiledAddressesIstanbul
+ case rules.IsByzantium:
+ return PrecompiledAddressesByzantium
+ default:
+ return PrecompiledAddressesHomestead
+ }
+}
+
+// DefaultPrecompiles define the mapping of address and precompiles from the default configuration
+func DefaultPrecompiles(rules params.Rules) (precompiles map[common.Address]PrecompiledContract) {
+ switch {
+ case rules.IsBerlin:
+ precompiles = PrecompiledContractsBerlin
+ case rules.IsIstanbul:
+ precompiles = PrecompiledContractsIstanbul
+ case rules.IsByzantium:
+ precompiles = PrecompiledContractsByzantium
+ default:
+ precompiles = PrecompiledContractsHomestead
+ }
+
+ return precompiles
+}
+
+// ActivePrecompiles returns the precompiles enabled with the current configuration.
+//
+// NOTE: The rules argument is ignored as the active precompiles can be set via the WithPrecompiles
+// method according to the chain rules from the current block context.
+func (evm *EVM) ActivePrecompiles(_ params.Rules) []common.Address {
+ return evm.activePrecompiles
+}
+
+// Precompile returns a precompiled contract for the given address. This
+// function returns false if the address is not a registered precompile.
+func (evm *EVM) Precompile(addr common.Address) (PrecompiledContract, bool) {
+ p, ok := evm.precompiles[addr]
+ return p, ok
+}
+
+// WithPrecompiles sets the precompiled contracts and the slice of actives precompiles.
+// IMPORTANT: This function does NOT validate the precompiles provided to the EVM. The caller should
+// use the ValidatePrecompiles function for this purpose prior to calling WithPrecompiles.
+func (evm *EVM) WithPrecompiles(
+ precompiles map[common.Address]PrecompiledContract,
+ activePrecompiles []common.Address,
+) {
+ evm.precompiles = precompiles
+ evm.activePrecompiles = activePrecompiles
+}
+
+// ValidatePrecompiles validates the precompile map against the active
+// precompile slice.
+// It returns an error if the precompiled contract map has a different length
+// than the slice of active contract addresses. This function also checks for
+// duplicates, invalid addresses and empty precompile contract instances.
+func ValidatePrecompiles(
+ precompiles map[common.Address]PrecompiledContract,
+ activePrecompiles []common.Address,
+) error {
+ if len(precompiles) != len(activePrecompiles) {
+ return fmt.Errorf("precompiles length mismatch (expected %d, got %d)", len(precompiles), len(activePrecompiles))
+ }
+
+ dupActivePrecompiles := make(map[common.Address]bool)
+
+ for _, addr := range activePrecompiles {
+ if dupActivePrecompiles[addr] {
+ return fmt.Errorf("duplicate active precompile: %s", addr)
+ }
+
+ precompile, ok := precompiles[addr]
+ if !ok {
+ return fmt.Errorf("active precompile address doesn't exist in precompiles map: %s", addr)
+ }
+
+ if precompile == nil {
+ return fmt.Errorf("precompile contract cannot be nil: %s", addr)
+ }
+
+ if bytes.Equal(addr.Bytes(), common.Address{}.Bytes()) {
+ return fmt.Errorf("precompile cannot be the zero address: %s", addr)
+ }
+
+ dupActivePrecompiles[addr] = true
+ }
+
+ return nil
+}
+
+// RunPrecompiledContract runs and evaluates the output of a precompiled contract.
+// It returns
+// - the returned bytes,
+// - the _remaining_ gas,
+// - any error that occurred
+func (evm *EVM) RunPrecompiledContract(
+ p PrecompiledContract,
+ caller ContractRef,
+ input []byte,
+ suppliedGas uint64,
+ value *big.Int,
+ readOnly bool,
+) (ret []byte, remainingGas uint64, err error) {
+ return runPrecompiledContract(evm, p, caller, input, suppliedGas, value, readOnly)
+}
+
+func runPrecompiledContract(
+ evm *EVM,
+ p PrecompiledContract,
+ caller ContractRef,
+ input []byte,
+ suppliedGas uint64,
+ value *big.Int,
+ readOnly bool,
+) (ret []byte, remainingGas uint64, err error) {
+ addrCopy := p.Address()
+ inputCopy := make([]byte, len(input))
+ copy(inputCopy, input)
+
+ contract := NewPrecompile(caller, AccountRef(addrCopy), value, suppliedGas)
+ contract.Input = inputCopy
+
+ gasCost := p.RequiredGas(input)
+ if !contract.UseGas(gasCost) {
+ return nil, contract.Gas, ErrOutOfGas
+ }
+
+ output, err := p.Run(evm, contract, readOnly)
+ return output, contract.Gas, err
+}
+
+// ECRECOVER implemented as a native contract.
+type ecrecover struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (ecrecover) Address() common.Address {
+ return common.BytesToAddress([]byte{1})
+}
+
+func (c *ecrecover) RequiredGas(input []byte) uint64 {
+ return params.EcrecoverGas
+}
+
+func (c *ecrecover) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ const ecRecoverInputLength = 128
+
+ contract.Input = common.RightPadBytes(contract.Input, ecRecoverInputLength)
+ // "input" is (hash, v, r, s), each 32 bytes
+ // but for ecrecover we want (r, s, v)
+
+ r := new(big.Int).SetBytes(contract.Input[64:96])
+ s := new(big.Int).SetBytes(contract.Input[96:128])
+ v := contract.Input[63] - 27
+
+ // tighter sig s values input homestead only apply to tx sigs
+ if !allZero(contract.Input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
+ return nil, nil
+ }
+ // We must make sure not to modify the 'input', so placing the 'v' along with
+ // the signature needs to be done on a new allocation
+ sig := make([]byte, 65)
+ copy(sig, contract.Input[64:128])
+ sig[64] = v
+ // v needs to be at the end for libsecp256k1
+ pubKey, err := crypto.Ecrecover(contract.Input[:32], sig)
+ // make sure the public key is a valid one
+ if err != nil {
+ return nil, nil
+ }
+
+ // the first byte of pubkey is bitcoin heritage
+ return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
+}
+
+// SHA256 implemented as a native contract.
+type sha256hash struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (sha256hash) Address() common.Address {
+ return common.BytesToAddress([]byte{2})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+//
+// This method does not require any overflow checking as the input size gas costs
+// required for anything significant is so high it's impossible to pay for.
+func (c *sha256hash) RequiredGas(input []byte) uint64 {
+ return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
+}
+
+func (c *sha256hash) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ h := sha256.Sum256(contract.Input)
+ return h[:], nil
+}
+
+// RIPEMD160 implemented as a native contract.
+type ripemd160hash struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (ripemd160hash) Address() common.Address {
+ return common.BytesToAddress([]byte{3})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+//
+// This method does not require any overflow checking as the input size gas costs
+// required for anything significant is so high it's impossible to pay for.
+func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
+ return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
+}
+
+func (c *ripemd160hash) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ ripemd := ripemd160.New()
+ ripemd.Write(contract.Input)
+ return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
+}
+
+// data copy implemented as a native contract.
+type dataCopy struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (dataCopy) Address() common.Address {
+ return common.BytesToAddress([]byte{4})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+//
+// This method does not require any overflow checking as the input size gas costs
+// required for anything significant is so high it's impossible to pay for.
+func (c *dataCopy) RequiredGas(input []byte) uint64 {
+ return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
+}
+
+func (c *dataCopy) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ return common.CopyBytes(contract.Input), nil
+}
+
+// bigModExp implements a native big integer exponential modular operation.
+type bigModExp struct {
+ eip2565 bool
+}
+
+var (
+ big0 = big.NewInt(0)
+ big1 = big.NewInt(1)
+ big2 = big.NewInt(2)
+ big3 = big.NewInt(3)
+ big4 = big.NewInt(4)
+ big7 = big.NewInt(7)
+ big8 = big.NewInt(8)
+ big16 = big.NewInt(16)
+ big20 = big.NewInt(20)
+ big32 = big.NewInt(32)
+ big64 = big.NewInt(64)
+ big96 = big.NewInt(96)
+ big480 = big.NewInt(480)
+ big1024 = big.NewInt(1024)
+ big3072 = big.NewInt(3072)
+ big199680 = big.NewInt(199680)
+)
+
+// modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198
+//
+// def mult_complexity(x):
+//
+// if x <= 64: return x ** 2
+// elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072
+// else: return x ** 2 // 16 + 480 * x - 199680
+//
+// where is x is max(length_of_MODULUS, length_of_BASE)
+func modexpMultComplexity(x *big.Int) *big.Int {
+ switch {
+ case x.Cmp(big64) <= 0:
+ x.Mul(x, x) // x ** 2
+ case x.Cmp(big1024) <= 0:
+ // (x ** 2 // 4 ) + ( 96 * x - 3072)
+ x = new(big.Int).Add(
+ new(big.Int).Div(new(big.Int).Mul(x, x), big4),
+ new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072),
+ )
+ default:
+ // (x ** 2 // 16) + (480 * x - 199680)
+ x = new(big.Int).Add(
+ new(big.Int).Div(new(big.Int).Mul(x, x), big16),
+ new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680),
+ )
+ }
+ return x
+}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bigModExp) Address() common.Address {
+ return common.BytesToAddress([]byte{5})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bigModExp) RequiredGas(input []byte) uint64 {
+ var (
+ baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
+ expLen = new(big.Int).SetBytes(getData(input, 32, 32))
+ modLen = new(big.Int).SetBytes(getData(input, 64, 32))
+ )
+ if len(input) > 96 {
+ input = input[96:]
+ } else {
+ input = input[:0]
+ }
+ // Retrieve the head 32 bytes of exp for the adjusted exponent length
+ var expHead *big.Int
+ if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 {
+ expHead = new(big.Int)
+ } else {
+ if expLen.Cmp(big32) > 0 {
+ expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32))
+ } else {
+ expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
+ }
+ }
+ // Calculate the adjusted exponent length
+ var msb int
+ if bitlen := expHead.BitLen(); bitlen > 0 {
+ msb = bitlen - 1
+ }
+ adjExpLen := new(big.Int)
+ if expLen.Cmp(big32) > 0 {
+ adjExpLen.Sub(expLen, big32)
+ adjExpLen.Mul(big8, adjExpLen)
+ }
+ adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
+ // Calculate the gas cost of the operation
+ gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
+ if c.eip2565 {
+ // EIP-2565 has three changes
+ // 1. Different multComplexity (inlined here)
+ // in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565):
+ //
+ // def mult_complexity(x):
+ // ceiling(x/8)^2
+ //
+ //where is x is max(length_of_MODULUS, length_of_BASE)
+ gas = gas.Add(gas, big7)
+ gas = gas.Div(gas, big8)
+ gas.Mul(gas, gas)
+
+ gas.Mul(gas, math.BigMax(adjExpLen, big1))
+ // 2. Different divisor (`GQUADDIVISOR`) (3)
+ gas.Div(gas, big3)
+ if gas.BitLen() > 64 {
+ return math.MaxUint64
+ }
+ // 3. Minimum price of 200 gas
+ if gas.Uint64() < 200 {
+ return 200
+ }
+ return gas.Uint64()
+ }
+ gas = modexpMultComplexity(gas)
+ gas.Mul(gas, math.BigMax(adjExpLen, big1))
+ gas.Div(gas, big20)
+
+ if gas.BitLen() > 64 {
+ return math.MaxUint64
+ }
+ return gas.Uint64()
+}
+
+func (c *bigModExp) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ var (
+ baseLen = new(big.Int).SetBytes(getData(contract.Input, 0, 32)).Uint64()
+ expLen = new(big.Int).SetBytes(getData(contract.Input, 32, 32)).Uint64()
+ modLen = new(big.Int).SetBytes(getData(contract.Input, 64, 32)).Uint64()
+ )
+ if len(contract.Input) > 96 {
+ contract.Input = contract.Input[96:]
+ } else {
+ contract.Input = contract.Input[:0]
+ }
+ // Handle a special case when both the base and mod length is zero
+ if baseLen == 0 && modLen == 0 {
+ return []byte{}, nil
+ }
+ // Retrieve the operands and execute the exponentiation
+ var (
+ base = new(big.Int).SetBytes(getData(contract.Input, 0, baseLen))
+ exp = new(big.Int).SetBytes(getData(contract.Input, baseLen, expLen))
+ mod = new(big.Int).SetBytes(getData(contract.Input, baseLen+expLen, modLen))
+ )
+ if mod.BitLen() == 0 {
+ // Modulo 0 is undefined, return zero
+ return common.LeftPadBytes([]byte{}, int(modLen)), nil
+ }
+ return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil
+}
+
+// newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,
+// returning it, or an error if the point is invalid.
+func newCurvePoint(blob []byte) (*bn256.G1, error) {
+ p := new(bn256.G1)
+ if _, err := p.Unmarshal(blob); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// newTwistPoint unmarshals a binary blob into a bn256 elliptic curve point,
+// returning it, or an error if the point is invalid.
+func newTwistPoint(blob []byte) (*bn256.G2, error) {
+ p := new(bn256.G2)
+ if _, err := p.Unmarshal(blob); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// runBn256Add implements the Bn256Add precompile, referenced by both
+// Byzantium and Istanbul operations.
+func runBn256Add(input []byte) ([]byte, error) {
+ x, err := newCurvePoint(getData(input, 0, 64))
+ if err != nil {
+ return nil, err
+ }
+ y, err := newCurvePoint(getData(input, 64, 64))
+ if err != nil {
+ return nil, err
+ }
+ res := new(bn256.G1)
+ res.Add(x, y)
+ return res.Marshal(), nil
+}
+
+// bn256Add implements a native elliptic curve point addition conforming to
+// Istanbul consensus rules.
+type bn256AddIstanbul struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bn256AddIstanbul) Address() common.Address {
+ return common.BytesToAddress([]byte{6})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
+ return params.Bn256AddGasIstanbul
+}
+
+func (c *bn256AddIstanbul) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ return runBn256Add(contract.Input)
+}
+
+// bn256AddByzantium implements a native elliptic curve point addition
+// conforming to Byzantium consensus rules.
+type bn256AddByzantium struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bn256AddByzantium) Address() common.Address {
+ return common.BytesToAddress([]byte{6})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 {
+ return params.Bn256AddGasByzantium
+}
+
+func (c *bn256AddByzantium) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ return runBn256Add(contract.Input)
+}
+
+// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by
+// both Byzantium and Istanbul operations.
+func runBn256ScalarMul(input []byte) ([]byte, error) {
+ p, err := newCurvePoint(getData(input, 0, 64))
+ if err != nil {
+ return nil, err
+ }
+ res := new(bn256.G1)
+ res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32)))
+ return res.Marshal(), nil
+}
+
+// bn256ScalarMulIstanbul implements a native elliptic curve scalar
+// multiplication conforming to Istanbul consensus rules.
+type bn256ScalarMulIstanbul struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bn256ScalarMulIstanbul) Address() common.Address {
+ return common.BytesToAddress([]byte{7})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
+ return params.Bn256ScalarMulGasIstanbul
+}
+
+func (c *bn256ScalarMulIstanbul) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ return runBn256ScalarMul(contract.Input)
+}
+
+// bn256ScalarMulByzantium implements a native elliptic curve scalar
+// multiplication conforming to Byzantium consensus rules.
+type bn256ScalarMulByzantium struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bn256ScalarMulByzantium) Address() common.Address {
+ return common.BytesToAddress([]byte{7})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 {
+ return params.Bn256ScalarMulGasByzantium
+}
+
+func (c *bn256ScalarMulByzantium) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ return runBn256ScalarMul(contract.Input)
+}
+
+var (
+ // true32Byte is returned if the bn256 pairing check succeeds.
+ true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
+
+ // false32Byte is returned if the bn256 pairing check fails.
+ false32Byte = make([]byte, 32)
+
+ // errBadPairingInput is returned if the bn256 pairing input is invalid.
+ errBadPairingInput = errors.New("bad elliptic curve pairing size")
+)
+
+// runBn256Pairing implements the Bn256Pairing precompile, referenced by both
+// Byzantium and Istanbul operations.
+func runBn256Pairing(input []byte) ([]byte, error) {
+ // Handle some corner cases cheaply
+ if len(input)%192 > 0 {
+ return nil, errBadPairingInput
+ }
+ // Convert the input into a set of coordinates
+ var (
+ cs []*bn256.G1
+ ts []*bn256.G2
+ )
+ for i := 0; i < len(input); i += 192 {
+ c, err := newCurvePoint(input[i : i+64])
+ if err != nil {
+ return nil, err
+ }
+ t, err := newTwistPoint(input[i+64 : i+192])
+ if err != nil {
+ return nil, err
+ }
+ cs = append(cs, c)
+ ts = append(ts, t)
+ }
+ // Execute the pairing checks and return the results
+ if bn256.PairingCheck(cs, ts) {
+ return true32Byte, nil
+ }
+ return false32Byte, nil
+}
+
+// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
+// conforming to Istanbul consensus rules.
+type bn256PairingIstanbul struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bn256PairingIstanbul) Address() common.Address {
+ return common.BytesToAddress([]byte{8})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
+ return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
+}
+
+func (c *bn256PairingIstanbul) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ return runBn256Pairing(contract.Input)
+}
+
+// bn256PairingByzantium implements a pairing pre-compile for the bn256 curve
+// conforming to Byzantium consensus rules.
+type bn256PairingByzantium struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bn256PairingByzantium) Address() common.Address {
+ return common.BytesToAddress([]byte{8})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 {
+ return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
+}
+
+func (c *bn256PairingByzantium) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ return runBn256Pairing(contract.Input)
+}
+
+type blake2F struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (blake2F) Address() common.Address {
+ return common.BytesToAddress([]byte{9})
+}
+
+func (c *blake2F) RequiredGas(input []byte) uint64 {
+ // If the input is malformed, we can't calculate the gas, return 0 and let the
+ // actual call choke and fault.
+ if len(input) != blake2FInputLength {
+ return 0
+ }
+ return uint64(binary.BigEndian.Uint32(input[0:4]))
+}
+
+const (
+ blake2FInputLength = 213
+ blake2FFinalBlockBytes = byte(1)
+ blake2FNonFinalBlockBytes = byte(0)
+)
+
+var (
+ errBlake2FInvalidInputLength = errors.New("invalid input length")
+ errBlake2FInvalidFinalFlag = errors.New("invalid final flag")
+)
+
+func (c *blake2F) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Make sure the input is valid (correct length and final flag)
+ if len(contract.Input) != blake2FInputLength {
+ return nil, errBlake2FInvalidInputLength
+ }
+ if contract.Input[212] != blake2FNonFinalBlockBytes && contract.Input[212] != blake2FFinalBlockBytes {
+ return nil, errBlake2FInvalidFinalFlag
+ }
+ // Parse the input into the Blake2b call parameters
+ var (
+ rounds = binary.BigEndian.Uint32(contract.Input[0:4])
+ final = contract.Input[212] == blake2FFinalBlockBytes
+
+ h [8]uint64
+ m [16]uint64
+ t [2]uint64
+ )
+ for i := 0; i < 8; i++ {
+ offset := 4 + i*8
+ h[i] = binary.LittleEndian.Uint64(contract.Input[offset : offset+8])
+ }
+ for i := 0; i < 16; i++ {
+ offset := 68 + i*8
+ m[i] = binary.LittleEndian.Uint64(contract.Input[offset : offset+8])
+ }
+ t[0] = binary.LittleEndian.Uint64(contract.Input[196:204])
+ t[1] = binary.LittleEndian.Uint64(contract.Input[204:212])
+
+ // Execute the compression function, extract and return the result
+ blake2b.F(&h, m, t, final, rounds)
+
+ output := make([]byte, 64)
+ for i := 0; i < 8; i++ {
+ offset := i * 8
+ binary.LittleEndian.PutUint64(output[offset:offset+8], h[i])
+ }
+ return output, nil
+}
+
+var (
+ errBLS12381InvalidInputLength = errors.New("invalid input length")
+ errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes")
+ errBLS12381G1PointSubgroup = errors.New("g1 point is not on correct subgroup")
+ errBLS12381G2PointSubgroup = errors.New("g2 point is not on correct subgroup")
+)
+
+// bls12381G1Add implements EIP-2537 G1Add precompile.
+type bls12381G1Add struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381G1Add) Address() common.Address {
+ return common.BytesToAddress([]byte{10})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381G1Add) RequiredGas(input []byte) uint64 {
+ return params.Bls12381G1AddGas
+}
+
+func (c *bls12381G1Add) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 G1Add precompile.
+ // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each).
+ // > Output is an encoding of addition operation result - single G1 point (`128` bytes).
+ if len(contract.Input) != 256 {
+ return nil, errBLS12381InvalidInputLength
+ }
+ var err error
+ var p0, p1 *bls12381.PointG1
+
+ // Initialize G1
+ g := bls12381.NewG1()
+
+ // Decode G1 point p_0
+ if p0, err = g.DecodePoint(contract.Input[:128]); err != nil {
+ return nil, err
+ }
+ // Decode G1 point p_1
+ if p1, err = g.DecodePoint(contract.Input[128:]); err != nil {
+ return nil, err
+ }
+
+ // Compute r = p_0 + p_1
+ r := g.New()
+ g.Add(r, p0, p1)
+
+ // Encode the G1 point result into 128 bytes
+ return g.EncodePoint(r), nil
+}
+
+// bls12381G1Mul implements EIP-2537 G1Mul precompile.
+type bls12381G1Mul struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381G1Mul) Address() common.Address {
+ return common.BytesToAddress([]byte{11})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 {
+ return params.Bls12381G1MulGas
+}
+
+func (c *bls12381G1Mul) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 G1Mul precompile.
+ // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
+ // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes).
+ if len(contract.Input) != 160 {
+ return nil, errBLS12381InvalidInputLength
+ }
+ var err error
+ var p0 *bls12381.PointG1
+
+ // Initialize G1
+ g := bls12381.NewG1()
+
+ // Decode G1 point
+ if p0, err = g.DecodePoint(contract.Input[:128]); err != nil {
+ return nil, err
+ }
+ // Decode scalar value
+ e := new(big.Int).SetBytes(contract.Input[128:])
+
+ // Compute r = e * p_0
+ r := g.New()
+ g.MulScalar(r, p0, e)
+
+ // Encode the G1 point into 128 bytes
+ return g.EncodePoint(r), nil
+}
+
+// bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile.
+type bls12381G1MultiExp struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381G1MultiExp) Address() common.Address {
+ return common.BytesToAddress([]byte{12})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
+ // Calculate G1 point, scalar value pair length
+ k := len(input) / 160
+ if k == 0 {
+ // Return 0 gas for small input length
+ return 0
+ }
+ // Lookup discount value for G1 point, scalar value pair length
+ var discount uint64
+ if dLen := len(params.Bls12381MultiExpDiscountTable); k < dLen {
+ discount = params.Bls12381MultiExpDiscountTable[k-1]
+ } else {
+ discount = params.Bls12381MultiExpDiscountTable[dLen-1]
+ }
+ // Calculate gas and return the result
+ return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000
+}
+
+func (c *bls12381G1MultiExp) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 G1MultiExp precompile.
+ // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
+ // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes).
+ k := len(contract.Input) / 160
+ if len(contract.Input) == 0 || len(contract.Input)%160 != 0 {
+ return nil, errBLS12381InvalidInputLength
+ }
+ var err error
+ points := make([]*bls12381.PointG1, k)
+ scalars := make([]*big.Int, k)
+
+ // Initialize G1
+ g := bls12381.NewG1()
+
+ // Decode point scalar pairs
+ for i := 0; i < k; i++ {
+ off := 160 * i
+ t0, t1, t2 := off, off+128, off+160
+ // Decode G1 point
+ if points[i], err = g.DecodePoint(contract.Input[t0:t1]); err != nil {
+ return nil, err
+ }
+ // Decode scalar value
+ scalars[i] = new(big.Int).SetBytes(contract.Input[t1:t2])
+ }
+
+ // Compute r = e_0 * p_0 + e_1 * p_1 + ... + e_(k-1) * p_(k-1)
+ r := g.New()
+ g.MultiExp(r, points, scalars)
+
+ // Encode the G1 point to 128 bytes
+ return g.EncodePoint(r), nil
+}
+
+// bls12381G2Add implements EIP-2537 G2Add precompile.
+type bls12381G2Add struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381G2Add) Address() common.Address {
+ return common.BytesToAddress([]byte{13})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381G2Add) RequiredGas(input []byte) uint64 {
+ return params.Bls12381G2AddGas
+}
+
+func (c *bls12381G2Add) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 G2Add precompile.
+ // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each).
+ // > Output is an encoding of addition operation result - single G2 point (`256` bytes).
+ if len(contract.Input) != 512 {
+ return nil, errBLS12381InvalidInputLength
+ }
+ var err error
+ var p0, p1 *bls12381.PointG2
+
+ // Initialize G2
+ g := bls12381.NewG2()
+ r := g.New()
+
+ // Decode G2 point p_0
+ if p0, err = g.DecodePoint(contract.Input[:256]); err != nil {
+ return nil, err
+ }
+ // Decode G2 point p_1
+ if p1, err = g.DecodePoint(contract.Input[256:]); err != nil {
+ return nil, err
+ }
+
+ // Compute r = p_0 + p_1
+ g.Add(r, p0, p1)
+
+ // Encode the G2 point into 256 bytes
+ return g.EncodePoint(r), nil
+}
+
+// bls12381G2Mul implements EIP-2537 G2Mul precompile.
+type bls12381G2Mul struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381G2Mul) Address() common.Address {
+ return common.BytesToAddress([]byte{14})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 {
+ return params.Bls12381G2MulGas
+}
+
+func (c *bls12381G2Mul) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 G2MUL precompile logic.
+ // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
+ // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes).
+ if len(contract.Input) != 288 {
+ return nil, errBLS12381InvalidInputLength
+ }
+ var err error
+ var p0 *bls12381.PointG2
+
+ // Initialize G2
+ g := bls12381.NewG2()
+
+ // Decode G2 point
+ if p0, err = g.DecodePoint(contract.Input[:256]); err != nil {
+ return nil, err
+ }
+ // Decode scalar value
+ e := new(big.Int).SetBytes(contract.Input[256:])
+
+ // Compute r = e * p_0
+ r := g.New()
+ g.MulScalar(r, p0, e)
+
+ // Encode the G2 point into 256 bytes
+ return g.EncodePoint(r), nil
+}
+
+// bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile.
+type bls12381G2MultiExp struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381G2MultiExp) Address() common.Address {
+ return common.BytesToAddress([]byte{15})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
+ // Calculate G2 point, scalar value pair length
+ k := len(input) / 288
+ if k == 0 {
+ // Return 0 gas for small input length
+ return 0
+ }
+ // Lookup discount value for G2 point, scalar value pair length
+ var discount uint64
+ if dLen := len(params.Bls12381MultiExpDiscountTable); k < dLen {
+ discount = params.Bls12381MultiExpDiscountTable[k-1]
+ } else {
+ discount = params.Bls12381MultiExpDiscountTable[dLen-1]
+ }
+ // Calculate gas and return the result
+ return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000
+}
+
+func (c *bls12381G2MultiExp) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 G2MultiExp precompile logic
+ // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
+ // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes).
+ k := len(contract.Input) / 288
+ if len(contract.Input) == 0 || len(contract.Input)%288 != 0 {
+ return nil, errBLS12381InvalidInputLength
+ }
+ var err error
+ points := make([]*bls12381.PointG2, k)
+ scalars := make([]*big.Int, k)
+
+ // Initialize G2
+ g := bls12381.NewG2()
+
+ // Decode point scalar pairs
+ for i := 0; i < k; i++ {
+ off := 288 * i
+ t0, t1, t2 := off, off+256, off+288
+ // Decode G1 point
+ if points[i], err = g.DecodePoint(contract.Input[t0:t1]); err != nil {
+ return nil, err
+ }
+ // Decode scalar value
+ scalars[i] = new(big.Int).SetBytes(contract.Input[t1:t2])
+ }
+
+ // Compute r = e_0 * p_0 + e_1 * p_1 + ... + e_(k-1) * p_(k-1)
+ r := g.New()
+ g.MultiExp(r, points, scalars)
+
+ // Encode the G2 point to 256 bytes.
+ return g.EncodePoint(r), nil
+}
+
+// bls12381Pairing implements EIP-2537 Pairing precompile.
+type bls12381Pairing struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381Pairing) Address() common.Address {
+ return common.BytesToAddress([]byte{16})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381Pairing) RequiredGas(input []byte) uint64 {
+ return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas
+}
+
+func (c *bls12381Pairing) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 Pairing precompile logic.
+ // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:
+ // > - `128` bytes of G1 point encoding
+ // > - `256` bytes of G2 point encoding
+ // > Output is a `32` bytes where last single byte is `0x01` if pairing result is equal to multiplicative identity in a pairing target field and `0x00` otherwise
+ // > (which is equivalent of Big Endian encoding of Solidity values `uint256(1)` and `uin256(0)` respectively).
+ k := len(contract.Input) / 384
+ if len(contract.Input) == 0 || len(contract.Input)%384 != 0 {
+ return nil, errBLS12381InvalidInputLength
+ }
+
+ // Initialize BLS12-381 pairing engine
+ e := bls12381.NewPairingEngine()
+ g1, g2 := e.G1, e.G2
+
+ // Decode pairs
+ for i := 0; i < k; i++ {
+ off := 384 * i
+ t0, t1, t2 := off, off+128, off+384
+
+ // Decode G1 point
+ p1, err := g1.DecodePoint(contract.Input[t0:t1])
+ if err != nil {
+ return nil, err
+ }
+ // Decode G2 point
+ p2, err := g2.DecodePoint(contract.Input[t1:t2])
+ if err != nil {
+ return nil, err
+ }
+
+ // 'point is on curve' check already done,
+ // Here we need to apply subgroup checks.
+ if !g1.InCorrectSubgroup(p1) {
+ return nil, errBLS12381G1PointSubgroup
+ }
+ if !g2.InCorrectSubgroup(p2) {
+ return nil, errBLS12381G2PointSubgroup
+ }
+
+ // Update pairing engine with G1 and G2 ponits
+ e.AddPair(p1, p2)
+ }
+ // Prepare 32 byte output
+ out := make([]byte, 32)
+
+ // Compute pairing and set the result
+ if e.Check() {
+ out[31] = 1
+ }
+ return out, nil
+}
+
+// decodeBLS12381FieldElement decodes BLS12-381 elliptic curve field element.
+// Removes top 16 bytes of 64 byte input.
+func decodeBLS12381FieldElement(in []byte) ([]byte, error) {
+ if len(in) != 64 {
+ return nil, errors.New("invalid field element length")
+ }
+ // check top bytes
+ for i := 0; i < 16; i++ {
+ if in[i] != byte(0x00) {
+ return nil, errBLS12381InvalidFieldElementTopBytes
+ }
+ }
+ out := make([]byte, 48)
+ copy(out[:], in[16:])
+ return out, nil
+}
+
+// bls12381MapG1 implements EIP-2537 MapG1 precompile.
+type bls12381MapG1 struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381MapG1) Address() common.Address {
+ return common.BytesToAddress([]byte{17})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381MapG1) RequiredGas(input []byte) uint64 {
+ return params.Bls12381MapG1Gas
+}
+
+func (c *bls12381MapG1) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 Map_To_G1 precompile.
+ // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field.
+ // > Output of this call is `128` bytes and is G1 point following respective encoding rules.
+ if len(contract.Input) != 64 {
+ return nil, errBLS12381InvalidInputLength
+ }
+
+ // Decode input field element
+ fe, err := decodeBLS12381FieldElement(contract.Input)
+ if err != nil {
+ return nil, err
+ }
+
+ // Initialize G1
+ g := bls12381.NewG1()
+
+ // Compute mapping
+ r, err := g.MapToCurve(fe)
+ if err != nil {
+ return nil, err
+ }
+
+ // Encode the G1 point to 128 bytes
+ return g.EncodePoint(r), nil
+}
+
+// bls12381MapG2 implements EIP-2537 MapG2 precompile.
+type bls12381MapG2 struct{}
+
+// Address defines the precompiled contract address. This MUST match the address
+// set in the precompiled contract map.
+func (bls12381MapG2) Address() common.Address {
+ return common.BytesToAddress([]byte{18})
+}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *bls12381MapG2) RequiredGas(input []byte) uint64 {
+ return params.Bls12381MapG2Gas
+}
+
+func (c *bls12381MapG2) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) {
+ // Implements EIP-2537 Map_FP2_TO_G2 precompile logic.
+ // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field.
+ // > Output of this call is `256` bytes and is G2 point following respective encoding rules.
+ if len(contract.Input) != 128 {
+ return nil, errBLS12381InvalidInputLength
+ }
+
+ // Decode input field element
+ fe := make([]byte, 96)
+ c0, err := decodeBLS12381FieldElement(contract.Input[:64])
+ if err != nil {
+ return nil, err
+ }
+ copy(fe[48:], c0)
+ c1, err := decodeBLS12381FieldElement(contract.Input[64:])
+ if err != nil {
+ return nil, err
+ }
+ copy(fe[:48], c1)
+
+ // Initialize G2
+ g := bls12381.NewG2()
+
+ // Compute mapping
+ r, err := g.MapToCurve(fe)
+ if err != nil {
+ return nil, err
+ }
+
+ // Encode the G2 point to 256 bytes
+ return g.EncodePoint(r), nil
+}
diff --git a/x/evm/core/vm/contracts_test.go b/x/evm/core/vm/contracts_test.go
new file mode 100644
index 00000000..1d4417c5
--- /dev/null
+++ b/x/evm/core/vm/contracts_test.go
@@ -0,0 +1,394 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// precompiledTest defines the input/output pairs for precompiled contract tests.
+type precompiledTest struct {
+ Input, Expected string
+ Gas uint64
+ Name string
+ NoBenchmark bool // Benchmark primarily the worst-cases
+}
+
+// precompiledFailureTest defines the input/error pairs for precompiled
+// contract failure tests.
+type precompiledFailureTest struct {
+ Input string
+ ExpectedError string
+ Name string
+}
+
+// allPrecompiles does not map to the actual set of precompiles, as it also contains
+// repriced versions of precompiles at certain slots
+var allPrecompiles = map[common.Address]PrecompiledContract{
+ common.BytesToAddress([]byte{1}): &ecrecover{},
+ common.BytesToAddress([]byte{2}): &sha256hash{},
+ common.BytesToAddress([]byte{3}): &ripemd160hash{},
+ common.BytesToAddress([]byte{4}): &dataCopy{},
+ common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
+ common.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true},
+ common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
+ common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{9}): &blake2F{},
+ common.BytesToAddress([]byte{10}): &bls12381G1Add{},
+ common.BytesToAddress([]byte{11}): &bls12381G1Mul{},
+ common.BytesToAddress([]byte{12}): &bls12381G1MultiExp{},
+ common.BytesToAddress([]byte{13}): &bls12381G2Add{},
+ common.BytesToAddress([]byte{14}): &bls12381G2Mul{},
+ common.BytesToAddress([]byte{15}): &bls12381G2MultiExp{},
+ common.BytesToAddress([]byte{16}): &bls12381Pairing{},
+ common.BytesToAddress([]byte{17}): &bls12381MapG1{},
+ common.BytesToAddress([]byte{18}): &bls12381MapG2{},
+}
+
+// EIP-152 test vectors
+var blake2FMalformedInputTests = []precompiledFailureTest{
+ {
+ Input: "",
+ ExpectedError: errBlake2FInvalidInputLength.Error(),
+ Name: "vector 0: empty input",
+ },
+ {
+ Input: "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ ExpectedError: errBlake2FInvalidInputLength.Error(),
+ Name: "vector 1: less than 213 bytes input",
+ },
+ {
+ Input: "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ ExpectedError: errBlake2FInvalidInputLength.Error(),
+ Name: "vector 2: more than 213 bytes input",
+ },
+ {
+ Input: "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002",
+ ExpectedError: errBlake2FInvalidFinalFlag.Error(),
+ Name: "vector 3: malformed final block indicator flag",
+ },
+}
+
+func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
+ p := allPrecompiles[common.HexToAddress(addr)]
+ in := common.Hex2Bytes(test.Input)
+ gas := p.RequiredGas(in)
+ t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
+ if res, _, err := runPrecompiledContract(nil, p, AccountRef(common.Address{}), in, gas, new(big.Int), false); err != nil {
+ t.Error(err)
+ } else if common.Bytes2Hex(res) != test.Expected {
+ t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
+ }
+ if expGas := test.Gas; expGas != gas {
+ t.Errorf("%v: gas wrong, expected %d, got %d", test.Name, expGas, gas)
+ }
+ // Verify that the precompile did not touch the input buffer
+ exp := common.Hex2Bytes(test.Input)
+ if !bytes.Equal(in, exp) {
+ t.Errorf("Precompiled %v modified input data", addr)
+ }
+ })
+}
+
+func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
+ p := allPrecompiles[common.HexToAddress(addr)]
+ in := common.Hex2Bytes(test.Input)
+ gas := p.RequiredGas(in) - 1
+
+ t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
+ _, _, err := runPrecompiledContract(nil, p, AccountRef(common.Address{}), in, gas, new(big.Int), false)
+ if err.Error() != "out of gas" {
+ t.Errorf("Expected error [out of gas], got [%v]", err)
+ }
+ // Verify that the precompile did not touch the input buffer
+ exp := common.Hex2Bytes(test.Input)
+ if !bytes.Equal(in, exp) {
+ t.Errorf("Precompiled %v modified input data", addr)
+ }
+ })
+}
+
+func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing.T) {
+ p := allPrecompiles[common.HexToAddress(addr)]
+ in := common.Hex2Bytes(test.Input)
+ gas := p.RequiredGas(in)
+ t.Run(test.Name, func(t *testing.T) {
+ _, _, err := runPrecompiledContract(nil, p, AccountRef(common.Address{}), in, gas, new(big.Int), false)
+ if err.Error() != test.ExpectedError {
+ t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
+ }
+ // Verify that the precompile did not touch the input buffer
+ exp := common.Hex2Bytes(test.Input)
+ if !bytes.Equal(in, exp) {
+ t.Errorf("Precompiled %v modified input data", addr)
+ }
+ })
+}
+
+func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
+ if test.NoBenchmark {
+ return
+ }
+ p := allPrecompiles[common.HexToAddress(addr)]
+ in := common.Hex2Bytes(test.Input)
+ reqGas := p.RequiredGas(in)
+
+ var (
+ res []byte
+ err error
+ data = make([]byte, len(in))
+ )
+
+ bench.Run(fmt.Sprintf("%s-Gas=%d", test.Name, reqGas), func(bench *testing.B) {
+ bench.ReportAllocs()
+ start := time.Now()
+ bench.ResetTimer()
+ for i := 0; i < bench.N; i++ {
+ copy(data, in)
+ res, _, err = runPrecompiledContract(nil, p, AccountRef(common.Address{}), in, reqGas, new(big.Int), false)
+ }
+ bench.StopTimer()
+ elapsed := uint64(time.Since(start))
+ if elapsed < 1 {
+ elapsed = 1
+ }
+ gasUsed := reqGas * uint64(bench.N)
+ bench.ReportMetric(float64(reqGas), "gas/op")
+ // Keep it as uint64, multiply 100 to get two digit float later
+ mgasps := (100 * 1000 * gasUsed) / elapsed
+ bench.ReportMetric(float64(mgasps)/100, "mgas/s")
+ // Check if it is correct
+ if err != nil {
+ bench.Error(err)
+ return
+ }
+ if common.Bytes2Hex(res) != test.Expected {
+ bench.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
+ return
+ }
+ })
+}
+
+// Benchmarks the sample inputs from the ECRECOVER precompile.
+func BenchmarkPrecompiledEcrecover(bench *testing.B) {
+ t := precompiledTest{
+ Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
+ Expected: "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d",
+ Name: "",
+ }
+ benchmarkPrecompiled("01", t, bench)
+}
+
+// Benchmarks the sample inputs from the SHA256 precompile.
+func BenchmarkPrecompiledSha256(bench *testing.B) {
+ t := precompiledTest{
+ Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
+ Expected: "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d",
+ Name: "128",
+ }
+ benchmarkPrecompiled("02", t, bench)
+}
+
+// Benchmarks the sample inputs from the RIPEMD precompile.
+func BenchmarkPrecompiledRipeMD(bench *testing.B) {
+ t := precompiledTest{
+ Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
+ Expected: "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6",
+ Name: "128",
+ }
+ benchmarkPrecompiled("03", t, bench)
+}
+
+// Benchmarks the sample inputs from the identiy precompile.
+func BenchmarkPrecompiledIdentity(bench *testing.B) {
+ t := precompiledTest{
+ Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
+ Expected: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
+ Name: "128",
+ }
+ benchmarkPrecompiled("04", t, bench)
+}
+
+// Tests the sample inputs from the ModExp EIP 198.
+func TestPrecompiledModExp(t *testing.T) { testJson("modexp", "05", t) }
+func BenchmarkPrecompiledModExp(b *testing.B) { benchJson("modexp", "05", b) }
+
+func TestPrecompiledModExpEip2565(t *testing.T) { testJson("modexp_eip2565", "f5", t) }
+func BenchmarkPrecompiledModExpEip2565(b *testing.B) { benchJson("modexp_eip2565", "f5", b) }
+
+// Tests the sample inputs from the elliptic curve addition EIP 213.
+func TestPrecompiledBn256Add(t *testing.T) { testJson("bn256Add", "06", t) }
+func BenchmarkPrecompiledBn256Add(b *testing.B) { benchJson("bn256Add", "06", b) }
+
+// Tests OOG
+func TestPrecompiledModExpOOG(t *testing.T) {
+ modexpTests, err := loadJson("modexp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, test := range modexpTests {
+ testPrecompiledOOG("05", test, t)
+ }
+}
+
+// Tests the sample inputs from the elliptic curve scalar multiplication EIP 213.
+func TestPrecompiledBn256ScalarMul(t *testing.T) { testJson("bn256ScalarMul", "07", t) }
+func BenchmarkPrecompiledBn256ScalarMul(b *testing.B) { benchJson("bn256ScalarMul", "07", b) }
+
+// Tests the sample inputs from the elliptic curve pairing check EIP 197.
+func TestPrecompiledBn256Pairing(t *testing.T) { testJson("bn256Pairing", "08", t) }
+func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) }
+
+func TestPrecompiledBlake2F(t *testing.T) { testJson("blake2F", "09", t) }
+func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJson("blake2F", "09", b) }
+
+func TestPrecompileBlake2FMalformedInput(t *testing.T) {
+ for _, test := range blake2FMalformedInputTests {
+ testPrecompiledFailure("09", test, t)
+ }
+}
+
+func TestPrecompiledEcrecover(t *testing.T) { testJson("ecRecover", "01", t) }
+
+func testJson(name, addr string, t *testing.T) {
+ tests, err := loadJson(name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, test := range tests {
+ testPrecompiled(addr, test, t)
+ }
+}
+
+func testJsonFail(name, addr string, t *testing.T) {
+ tests, err := loadJsonFail(name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, test := range tests {
+ testPrecompiledFailure(addr, test, t)
+ }
+}
+
+func benchJson(name, addr string, b *testing.B) {
+ tests, err := loadJson(name)
+ if err != nil {
+ b.Fatal(err)
+ }
+ for _, test := range tests {
+ benchmarkPrecompiled(addr, test, b)
+ }
+}
+
+func TestPrecompiledBLS12381G1Add(t *testing.T) { testJson("blsG1Add", "0a", t) }
+func TestPrecompiledBLS12381G1Mul(t *testing.T) { testJson("blsG1Mul", "0b", t) }
+func TestPrecompiledBLS12381G1MultiExp(t *testing.T) { testJson("blsG1MultiExp", "0c", t) }
+func TestPrecompiledBLS12381G2Add(t *testing.T) { testJson("blsG2Add", "0d", t) }
+func TestPrecompiledBLS12381G2Mul(t *testing.T) { testJson("blsG2Mul", "0e", t) }
+func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp", "0f", t) }
+func TestPrecompiledBLS12381Pairing(t *testing.T) { testJson("blsPairing", "10", t) }
+func TestPrecompiledBLS12381MapG1(t *testing.T) { testJson("blsMapG1", "11", t) }
+func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "12", t) }
+
+func BenchmarkPrecompiledBLS12381G1Add(b *testing.B) { benchJson("blsG1Add", "0a", b) }
+func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B) { benchJson("blsG1Mul", "0b", b) }
+func BenchmarkPrecompiledBLS12381G1MultiExp(b *testing.B) { benchJson("blsG1MultiExp", "0c", b) }
+func BenchmarkPrecompiledBLS12381G2Add(b *testing.B) { benchJson("blsG2Add", "0d", b) }
+func BenchmarkPrecompiledBLS12381G2Mul(b *testing.B) { benchJson("blsG2Mul", "0e", b) }
+func BenchmarkPrecompiledBLS12381G2MultiExp(b *testing.B) { benchJson("blsG2MultiExp", "0f", b) }
+func BenchmarkPrecompiledBLS12381Pairing(b *testing.B) { benchJson("blsPairing", "10", b) }
+func BenchmarkPrecompiledBLS12381MapG1(b *testing.B) { benchJson("blsMapG1", "11", b) }
+func BenchmarkPrecompiledBLS12381MapG2(b *testing.B) { benchJson("blsMapG2", "12", b) }
+
+// Failure tests
+func TestPrecompiledBLS12381G1AddFail(t *testing.T) { testJsonFail("blsG1Add", "0a", t) }
+func TestPrecompiledBLS12381G1MulFail(t *testing.T) { testJsonFail("blsG1Mul", "0b", t) }
+func TestPrecompiledBLS12381G1MultiExpFail(t *testing.T) { testJsonFail("blsG1MultiExp", "0c", t) }
+func TestPrecompiledBLS12381G2AddFail(t *testing.T) { testJsonFail("blsG2Add", "0d", t) }
+func TestPrecompiledBLS12381G2MulFail(t *testing.T) { testJsonFail("blsG2Mul", "0e", t) }
+func TestPrecompiledBLS12381G2MultiExpFail(t *testing.T) { testJsonFail("blsG2MultiExp", "0f", t) }
+func TestPrecompiledBLS12381PairingFail(t *testing.T) { testJsonFail("blsPairing", "10", t) }
+func TestPrecompiledBLS12381MapG1Fail(t *testing.T) { testJsonFail("blsMapG1", "11", t) }
+func TestPrecompiledBLS12381MapG2Fail(t *testing.T) { testJsonFail("blsMapG2", "12", t) }
+
+func loadJson(name string) ([]precompiledTest, error) {
+ data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/%v.json", name))
+ if err != nil {
+ return nil, err
+ }
+ var testcases []precompiledTest
+ err = json.Unmarshal(data, &testcases)
+ return testcases, err
+}
+
+func loadJsonFail(name string) ([]precompiledFailureTest, error) {
+ data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/fail-%v.json", name))
+ if err != nil {
+ return nil, err
+ }
+ var testcases []precompiledFailureTest
+ err = json.Unmarshal(data, &testcases)
+ return testcases, err
+}
+
+// BenchmarkPrecompiledBLS12381G1MultiExpWorstCase benchmarks the worst case we could find that still fits a gaslimit of 10MGas.
+func BenchmarkPrecompiledBLS12381G1MultiExpWorstCase(b *testing.B) {
+ task := "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be1" +
+ "0000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe9" +
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ input := task
+ for i := 0; i < 4787; i++ {
+ input = input + task
+ }
+ testcase := precompiledTest{
+ Input: input,
+ Expected: "0000000000000000000000000000000005a6310ea6f2a598023ae48819afc292b4dfcb40aabad24a0c2cb6c19769465691859eeb2a764342a810c5038d700f18000000000000000000000000000000001268ac944437d15923dc0aec00daa9250252e43e4b35ec7a19d01f0d6cd27f6e139d80dae16ba1c79cc7f57055a93ff5",
+ Name: "WorstCaseG1",
+ NoBenchmark: false,
+ }
+ benchmarkPrecompiled("0c", testcase, b)
+}
+
+// BenchmarkPrecompiledBLS12381G2MultiExpWorstCase benchmarks the worst case we could find that still fits a gaslimit of 10MGas.
+func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
+ task := "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f" +
+ "000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b99" +
+ "00000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b" +
+ "000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c7" +
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ input := task
+ for i := 0; i < 1040; i++ {
+ input = input + task
+ }
+
+ testcase := precompiledTest{
+ Input: input,
+ Expected: "0000000000000000000000000000000018f5ea0c8b086095cfe23f6bb1d90d45de929292006dba8cdedd6d3203af3c6bbfd592e93ecb2b2c81004961fdcbb46c00000000000000000000000000000000076873199175664f1b6493a43c02234f49dc66f077d3007823e0343ad92e30bd7dc209013435ca9f197aca44d88e9dac000000000000000000000000000000000e6f07f4b23b511eac1e2682a0fc224c15d80e122a3e222d00a41fab15eba645a700b9ae84f331ae4ed873678e2e6c9b000000000000000000000000000000000bcb4849e460612aaed79617255fd30c03f51cf03d2ed4163ca810c13e1954b1e8663157b957a601829bb272a4e6c7b8",
+ Name: "WorstCaseG2",
+ NoBenchmark: false,
+ }
+ benchmarkPrecompiled("0f", testcase, b)
+}
diff --git a/x/evm/core/vm/custom_eip.go b/x/evm/core/vm/custom_eip.go
new file mode 100644
index 00000000..058ab75c
--- /dev/null
+++ b/x/evm/core/vm/custom_eip.go
@@ -0,0 +1,154 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package vm
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "golang.org/x/exp/maps"
+)
+
+// OpCodeInfo contains information required to identify an EVM operation.
+type OpCodeInfo struct {
+ Number OpCode
+ Name string
+}
+
+// Operation is an utility struct that wraps the private type
+// operation.
+type Operation struct {
+ Op *operation
+}
+
+// ExtendActivators allows to merge the go ethereum activators map
+// with additional custom activators.
+func ExtendActivators(eips map[string]func(*JumpTable)) error {
+ // Catch early duplicated eip.
+ keys := make([]string, 0, len(eips))
+ for k := range eips {
+ if ExistsEipActivator(k) {
+ return fmt.Errorf("duplicate activation: %s is already present in %s", k, ActivateableEips())
+ }
+ keys = append(keys, k)
+ }
+
+ // Sorting keys to ensure deterministic execution.
+ sort.Strings(keys)
+
+ for _, k := range keys {
+ activators[k] = eips[k]
+ }
+ return nil
+}
+
+// ExtendOperations returns an instance of the new operation and register it in the list
+// of available ones.
+// Return an error if an operation with the same name is already present.
+// This function is used to prevent the overwrite of an already existent operation.
+func ExtendOperations(
+ opInfo OpCodeInfo,
+ execute executionFunc,
+ constantGas uint64,
+ dynamicGas gasFunc,
+ minStack int,
+ maxStack int,
+ memorySize memorySizeFunc,
+) (*Operation, error) {
+ opName := strings.ToUpper(strings.TrimSpace(opInfo.Name))
+ if err := extendOpCodeStringLists(opInfo.Number, opName); err != nil {
+ return nil, err
+ }
+
+ operation := newOperation(execute, constantGas, dynamicGas, minStack, maxStack, memorySize)
+ op := &Operation{operation}
+
+ return op, nil
+}
+
+// GetActivatorsEipNames returns the name of EIPs registered in
+// the activators map.
+// Used only in tests.
+func GetActivatorsEipNames() []string {
+ keys := maps.Keys(activators)
+
+ sort.Strings(keys)
+ return keys
+}
+
+// newOperation returns an instance of a new EVM operation.
+func newOperation(
+ execute executionFunc,
+ constantGas uint64,
+ dynamicGas gasFunc,
+ minStack int,
+ maxStack int,
+ memorySize memorySizeFunc,
+) *operation {
+ return &operation{
+ execute: execute,
+ constantGas: constantGas,
+ dynamicGas: dynamicGas,
+ minStack: minStack,
+ maxStack: maxStack,
+ memorySize: memorySize,
+ }
+}
+
+// GetConstantGas return the constant gas used by the operation.
+func (o *operation) GetConstantGas() uint64 {
+ return o.constantGas
+}
+
+// SetExecute sets the execution function of the operation.
+func (o *operation) SetExecute(ef executionFunc) {
+ o.execute = ef
+}
+
+// SetConstantGas changes the constant gas of the operation.
+func (o *operation) SetConstantGas(gas uint64) {
+ o.constantGas = gas
+}
+
+// SetDynamicGas sets the dynamic gas function of the operation.
+func (o *operation) SetDynamicGas(gf gasFunc) {
+ o.dynamicGas = gf
+}
+
+// SetMinStack sets the minimum stack size required for the operation.
+func (o *operation) SetMinStack(minStack int) {
+ o.minStack = minStack
+}
+
+// SetMaxStack sets the maximum stack size for the operation.
+func (o *operation) SetMaxStack(maxStack int) {
+ o.maxStack = maxStack
+}
+
+// SetMemorySize sets the memory size function for the operation.
+func (o *operation) SetMemorySize(msf memorySizeFunc) {
+ o.memorySize = msf
+}
+
+// extendOpCodeStringLists updates the lists mapping opcode number to the name
+// and viceversa. Return an error if the key is already set.
+//
+// ASSUMPTION: no opcode is registered as an empty string.
+func extendOpCodeStringLists(newOpCode OpCode, newOpName string) error {
+ opName := opCodeToString[newOpCode]
+ if opName != "" {
+ return fmt.Errorf("opcode %d already exists: %s", newOpCode, opName)
+ }
+ opNumber := stringToOp[newOpName]
+ // We need to check against the STOP opcode name because we have to discriminate
+ // between 0x00 of this opcode and the default value of an empty key.
+ stopName := opCodeToString[STOP]
+ if opNumber != 0x00 || newOpName == stopName {
+ return fmt.Errorf("opcode with name %s already exists", newOpName)
+ }
+ opCodeToString[newOpCode] = newOpName
+ stringToOp[newOpName] = newOpCode
+ return nil
+}
diff --git a/x/evm/core/vm/custom_eip_test.go b/x/evm/core/vm/custom_eip_test.go
new file mode 100644
index 00000000..c57d282c
--- /dev/null
+++ b/x/evm/core/vm/custom_eip_test.go
@@ -0,0 +1,243 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package vm
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestValidEIPName(t *testing.T) {
+ testCases := []struct {
+ name string
+ eipName string
+ expPass bool
+ errContains string
+ }{
+ {
+ "fail - invalid number",
+ "os_OS",
+ false,
+ "eip number should be convertible to int",
+ },
+ {
+ "fail - invalid structure, only chain name",
+ "os",
+ false,
+ "eip name does not conform to structure 'chainName_Number'",
+ },
+ {
+ "fail - invalid structure, only number",
+ "0000",
+ false,
+ "eip name does not conform to structure 'chainName_Number'",
+ },
+ {
+ "fail - invalid structure, only delimiter",
+ "_",
+ false,
+ "eip number should be convertible to int",
+ },
+ {
+ "success - valid eip name",
+ "os_0000",
+ true,
+ "",
+ },
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ err := ValidateEIPName(tc.eipName)
+ if tc.expPass {
+ require.NoError(t, err)
+ } else {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), tc.errContains, "expected different error")
+ }
+ })
+ }
+}
+
+func TestExtendActivators(t *testing.T) {
+ eips_snapshot := GetActivatorsEipNames()
+
+ testCases := []struct {
+ name string
+ newActivators map[string]func(*JumpTable)
+ expPass bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "success - nil new activators",
+ nil,
+ true,
+ "",
+ func() {
+ eips := GetActivatorsEipNames()
+ require.ElementsMatch(t, eips_snapshot, eips, "expected eips number to be equal")
+ },
+ },
+ {
+ "success - single new activator",
+ map[string]func(*JumpTable){
+ "evmos_0": func(jt *JumpTable) {},
+ },
+ true,
+ "",
+ func() {
+ eips := GetActivatorsEipNames()
+ require.ElementsMatch(t, append(eips_snapshot, "evmos_0"), eips, "expected eips number to be equal")
+ },
+ },
+ {
+ "success - multiple new activators",
+ map[string]func(*JumpTable){
+ "evmos_1": func(jt *JumpTable) {},
+ "evmos_2": func(jt *JumpTable) {},
+ },
+ true,
+ "",
+ func() {
+ eips := GetActivatorsEipNames()
+ // since we are working with a global function, tests are not independent
+ require.ElementsMatch(t, append(eips_snapshot, "evmos_0", "evmos_1", "evmos_2"), eips, "expected eips number to be equal")
+ },
+ },
+ {
+ "fail - repeated activator",
+ map[string]func(*JumpTable){
+ "ethereum_3855": func(jt *JumpTable) {},
+ },
+ false,
+ "",
+ func() {
+ eips := GetActivatorsEipNames()
+ // since we are working with a global function, tests are not independent
+ require.ElementsMatch(t, append(eips_snapshot, "evmos_0", "evmos_1", "evmos_2"), eips, "expected eips number to be equal")
+ },
+ },
+ {
+ "fail - valid activator is not stored if a repeated is present",
+ map[string]func(*JumpTable){
+ "evmos_3": func(jt *JumpTable) {},
+ "ethereum_3855": func(jt *JumpTable) {},
+ },
+ false,
+ "",
+ func() {
+ eips := GetActivatorsEipNames()
+ // since we are working with a global function, tests are not independent
+ require.ElementsMatch(t, append(eips_snapshot, "evmos_0", "evmos_1", "evmos_2"), eips, "expected eips number to be equal")
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ err := ExtendActivators(tc.newActivators)
+ if tc.expPass {
+ require.NoError(t, err)
+ } else {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), tc.errContains, "expected different error")
+ }
+
+ tc.postCheck()
+ }
+}
+
+func TestAddOperation(t *testing.T) {
+ // Functions used to create an operation.
+ customExecute := func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ // no - op
+ return nil, nil
+ }
+ customDynamicGas := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ // no-op
+ return 0, nil
+ }
+ customMemorySize := func(stack *Stack) (uint64, bool) {
+ // no-op
+ return 0, false
+ }
+
+ const (
+ EXISTENT OpCode = STOP
+ NEW OpCode = 0xf
+ )
+
+ testCases := []struct {
+ name string
+ opName string
+ opNumber OpCode
+ expPass bool
+ errContains string
+ postCheck func()
+ }{
+ {
+ "fail - operation with same number already exists",
+ "TEST",
+ EXISTENT,
+ false,
+ "already exists",
+ func() {
+ name := EXISTENT.String()
+ require.Equal(t, "STOP", name)
+ },
+ },
+ {
+ "fail - operation with same name already exists",
+ "CREATE",
+ NEW,
+ false,
+ "already exists",
+ func() {
+ name := NEW.String()
+ require.Contains(t, name, "not defined")
+ },
+ },
+ {
+ "fail - operation with same name of STOP",
+ "STOP",
+ NEW,
+ false,
+ "already exists",
+ func() {
+ name := NEW.String()
+ require.Contains(t, name, "not defined")
+ },
+ },
+ {
+ "pass - new operation added to the list",
+ "TEST",
+ NEW,
+ true,
+ "",
+ func() {
+ name := NEW.String()
+ require.Equal(t, "TEST", name)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ opInfo := OpCodeInfo{
+ Number: tc.opNumber,
+ Name: tc.opName,
+ }
+ _, err := ExtendOperations(opInfo, customExecute, 0, customDynamicGas, 0, 0, customMemorySize)
+
+ if tc.expPass {
+ require.NoError(t, err)
+ } else {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), tc.errContains, "expected different error")
+ }
+
+ tc.postCheck()
+ })
+ }
+}
diff --git a/x/evm/core/vm/doc.go b/x/evm/core/vm/doc.go
new file mode 100644
index 00000000..5864d0cf
--- /dev/null
+++ b/x/evm/core/vm/doc.go
@@ -0,0 +1,24 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+/*
+Package vm implements the Ethereum Virtual Machine.
+
+The vm package implements one EVM, a byte code VM. The BC (Byte Code) VM loops
+over a set of bytes and executes them according to the set of rules defined
+in the Ethereum yellow paper.
+*/
+package vm
diff --git a/x/evm/core/vm/eips.go b/x/evm/core/vm/eips.go
new file mode 100644
index 00000000..9b399f81
--- /dev/null
+++ b/x/evm/core/vm/eips.go
@@ -0,0 +1,217 @@
+// Copyright 2019 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
+)
+
+var activators = map[string]func(*JumpTable){
+ "ethereum_3855": enable3855,
+ "ethereum_3529": enable3529,
+ "ethereum_3198": enable3198,
+ "ethereum_2929": enable2929,
+ "ethereum_2200": enable2200,
+ "ethereum_1884": enable1884,
+ "ethereum_1344": enable1344,
+}
+
+// EnableEIP enables the given EIP on the config.
+// This operation writes in-place, and callers need to ensure that the globally
+// defined jump tables are not polluted.
+func EnableEIP(eipName string, jt *JumpTable) error {
+ enablerFn, ok := activators[eipName]
+ if !ok {
+ return fmt.Errorf("undefined eip %s", eipName)
+ }
+ enablerFn(jt)
+ return nil
+}
+
+// ValidateEIPName checks if an EIP name is valid or not. The allowed
+// name structure is a string that can be represented as "chainName" + "_" + "int".
+func ValidateEIPName(eipName string) error {
+ eipSplit := strings.Split(eipName, "_")
+ if len(eipSplit) != 2 {
+ return fmt.Errorf("eip name does not conform to structure 'chainName_Number'")
+ }
+ if _, err := strconv.Atoi(eipSplit[1]); err != nil {
+ return fmt.Errorf("eip number should be convertible to int")
+ }
+ return nil
+}
+
+// ExistsEipActivator return true if the given EIP
+// name is associated with an activator function.
+// Return false otherwise.
+func ExistsEipActivator(eipName string) bool {
+ _, ok := activators[eipName]
+ return ok
+}
+
+// ActivateableEips returns the sorted slice of EIP names
+// that can be activated.
+func ActivateableEips() []string {
+ var names []string
+ if len(activators) > 0 {
+ for k := range activators {
+ names = append(names, k)
+ }
+ sort.Strings(names)
+ }
+ return names
+}
+
+// enable1884 applies EIP-1884 to the given jump table:
+// - Increase cost of BALANCE to 700
+// - Increase cost of EXTCODEHASH to 700
+// - Increase cost of SLOAD to 800
+// - Define SELFBALANCE, with cost GasFastStep (5)
+func enable1884(jt *JumpTable) {
+ // Gas cost changes
+ jt[SLOAD].constantGas = params.SloadGasEIP1884
+ jt[BALANCE].constantGas = params.BalanceGasEIP1884
+ jt[EXTCODEHASH].constantGas = params.ExtcodeHashGasEIP1884
+
+ // New opcode
+ jt[SELFBALANCE] = &operation{
+ execute: opSelfBalance,
+ constantGas: GasFastStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ }
+}
+
+func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ balance, _ := uint256.FromBig(interpreter.evm.StateDB.GetBalance(scope.Contract.Address()))
+ scope.Stack.Push(balance)
+ return nil, nil
+}
+
+// enable1344 applies EIP-1344 (ChainID Opcode)
+// - Adds an opcode that returns the current chain’s EIP-155 unique identifier
+func enable1344(jt *JumpTable) {
+ // New opcode
+ jt[CHAINID] = &operation{
+ execute: opChainID,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ }
+}
+
+// opChainID implements CHAINID opcode
+func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ chainId, _ := uint256.FromBig(interpreter.evm.chainConfig.ChainID)
+ scope.Stack.Push(chainId)
+ return nil, nil
+}
+
+// enable2200 applies EIP-2200 (Rebalance net-metered SSTORE)
+func enable2200(jt *JumpTable) {
+ jt[SLOAD].constantGas = params.SloadGasEIP2200
+ jt[SSTORE].dynamicGas = gasSStoreEIP2200
+}
+
+// enable2929 enables "EIP-2929: Gas cost increases for state access opcodes"
+// https://eips.ethereum.org/EIPS/eip-2929
+func enable2929(jt *JumpTable) {
+ jt[SSTORE].dynamicGas = gasSStoreEIP2929
+
+ jt[SLOAD].constantGas = 0
+ jt[SLOAD].dynamicGas = gasSLoadEIP2929
+
+ jt[EXTCODECOPY].constantGas = params.WarmStorageReadCostEIP2929
+ jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP2929
+
+ jt[EXTCODESIZE].constantGas = params.WarmStorageReadCostEIP2929
+ jt[EXTCODESIZE].dynamicGas = gasEip2929AccountCheck
+
+ jt[EXTCODEHASH].constantGas = params.WarmStorageReadCostEIP2929
+ jt[EXTCODEHASH].dynamicGas = gasEip2929AccountCheck
+
+ jt[BALANCE].constantGas = params.WarmStorageReadCostEIP2929
+ jt[BALANCE].dynamicGas = gasEip2929AccountCheck
+
+ jt[CALL].constantGas = params.WarmStorageReadCostEIP2929
+ jt[CALL].dynamicGas = gasCallEIP2929
+
+ jt[CALLCODE].constantGas = params.WarmStorageReadCostEIP2929
+ jt[CALLCODE].dynamicGas = gasCallCodeEIP2929
+
+ jt[STATICCALL].constantGas = params.WarmStorageReadCostEIP2929
+ jt[STATICCALL].dynamicGas = gasStaticCallEIP2929
+
+ jt[DELEGATECALL].constantGas = params.WarmStorageReadCostEIP2929
+ jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP2929
+
+ // This was previously part of the dynamic cost, but we're using it as a constantGas
+ // factor here
+ jt[SELFDESTRUCT].constantGas = params.SelfdestructGasEIP150
+ jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP2929
+}
+
+// enable3529 enabled "EIP-3529: Reduction in refunds":
+// - Removes refunds for selfdestructs
+// - Reduces refunds for SSTORE
+// - Reduces max refunds to 20% gas
+func enable3529(jt *JumpTable) {
+ jt[SSTORE].dynamicGas = gasSStoreEIP3529
+ jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP3529
+}
+
+// enable3198 applies EIP-3198 (BASEFEE Opcode)
+// - Adds an opcode that returns the current block's base fee.
+func enable3198(jt *JumpTable) {
+ // New opcode
+ jt[BASEFEE] = &operation{
+ execute: opBaseFee,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ }
+}
+
+// opBaseFee implements BASEFEE opcode
+func opBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ baseFee, _ := uint256.FromBig(interpreter.evm.Context.BaseFee)
+ scope.Stack.Push(baseFee)
+ return nil, nil
+}
+
+// enable3855 applies EIP-3855 (PUSH0 opcode)
+func enable3855(jt *JumpTable) {
+ // New opcode
+ jt[PUSH0] = &operation{
+ execute: opPush0,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ }
+}
+
+// opPush0 implements the PUSH0 opcode
+func opPush0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int))
+ return nil, nil
+}
diff --git a/x/evm/core/vm/errors.go b/x/evm/core/vm/errors.go
new file mode 100644
index 00000000..004f8ef1
--- /dev/null
+++ b/x/evm/core/vm/errors.go
@@ -0,0 +1,72 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "errors"
+ "fmt"
+)
+
+// List evm execution errors
+var (
+ ErrOutOfGas = errors.New("out of gas")
+ ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas")
+ ErrDepth = errors.New("max call depth exceeded")
+ ErrInsufficientBalance = errors.New("insufficient balance for transfer")
+ ErrContractAddressCollision = errors.New("contract address collision")
+ ErrExecutionReverted = errors.New("execution reverted")
+ ErrMaxCodeSizeExceeded = errors.New("max code size exceeded")
+ ErrInvalidJump = errors.New("invalid jump destination")
+ ErrWriteProtection = errors.New("write protection")
+ ErrReturnDataOutOfBounds = errors.New("return data out of bounds")
+ ErrGasUintOverflow = errors.New("gas uint64 overflow")
+ ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
+ ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
+
+ // errStopToken is an internal token indicating interpreter loop termination,
+ // never returned to outside callers.
+ errStopToken = errors.New("stop token")
+)
+
+// ErrStackUnderflow wraps an evm error when the items on the stack less
+// than the minimal requirement.
+type ErrStackUnderflow struct {
+ stackLen int
+ required int
+}
+
+func (e *ErrStackUnderflow) Error() string {
+ return fmt.Sprintf("stack underflow (%d <=> %d)", e.stackLen, e.required)
+}
+
+// ErrStackOverflow wraps an evm error when the items on the stack exceeds
+// the maximum allowance.
+type ErrStackOverflow struct {
+ stackLen int
+ limit int
+}
+
+func (e *ErrStackOverflow) Error() string {
+ return fmt.Sprintf("stack limit reached %d (%d)", e.stackLen, e.limit)
+}
+
+// ErrInvalidOpCode wraps an evm error when an invalid opcode is encountered.
+type ErrInvalidOpCode struct {
+ opcode OpCode
+}
+
+func (e *ErrInvalidOpCode) Error() string { return fmt.Sprintf("invalid opcode: %s", e.opcode) }
diff --git a/x/evm/core/vm/evm.go b/x/evm/core/vm/evm.go
new file mode 100644
index 00000000..d8ca6d91
--- /dev/null
+++ b/x/evm/core/vm/evm.go
@@ -0,0 +1,550 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package vm
+
+import (
+ "math/big"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
+)
+
+// emptyCodeHash is used by create to ensure deployment is disallowed to already
+// deployed contract addresses (relevant after the account abstraction).
+var emptyCodeHash = crypto.Keccak256Hash(nil)
+
+type (
+ // CanTransferFunc is the signature of a transfer guard function
+ CanTransferFunc func(StateDB, common.Address, *big.Int) bool
+ // TransferFunc is the signature of a transfer function
+ TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
+ // GetHashFunc returns the n'th block hash in the blockchain
+ // and is used by the BLOCKHASH EVM op code.
+ GetHashFunc func(uint64) common.Hash
+)
+
+// BlockContext provides the EVM with auxiliary information. Once provided
+// it shouldn't be modified.
+type BlockContext struct {
+ // CanTransfer returns whether the account contains
+ // sufficient ether to transfer the value
+ CanTransfer CanTransferFunc
+ // Transfer transfers ether from one account to the other
+ Transfer TransferFunc
+ // GetHash returns the hash corresponding to n
+ GetHash GetHashFunc
+
+ // Block information
+ Coinbase common.Address // Provides information for COINBASE
+ GasLimit uint64 // Provides information for GASLIMIT
+ BlockNumber *big.Int // Provides information for NUMBER
+ Time *big.Int // Provides information for TIME
+ Difficulty *big.Int // Provides information for DIFFICULTY
+ BaseFee *big.Int // Provides information for BASEFEE
+ Random *common.Hash // Provides information for RANDOM
+}
+
+// TxContext provides the EVM with information about a transaction.
+// All fields can change between transactions.
+type TxContext struct {
+ // Message information
+ Origin common.Address // Provides information for ORIGIN
+ GasPrice *big.Int // Provides information for GASPRICE
+}
+
+// EVM is the Ethereum Virtual Machine base object and provides
+// the necessary tools to run a contract on the given state with
+// the provided context. It should be noted that any error
+// generated through any of the calls should be considered a
+// revert-state-and-consume-all-gas operation, no checks on
+// specific errors should ever be performed. The interpreter makes
+// sure that any errors generated are to be considered faulty code.
+//
+// The EVM should never be reused and is not thread safe.
+type EVM struct {
+ // Context provides auxiliary blockchain related information
+ Context BlockContext
+ TxContext
+ // StateDB gives access to the underlying state
+ StateDB StateDB
+ // Depth is the current call stack
+ depth int
+
+ // chainConfig contains information about the current chain
+ chainConfig *params.ChainConfig
+ // chain rules contains the chain rules for the current epoch
+ chainRules params.Rules
+ // virtual machine configuration options used to initialise the
+ // evm.
+ Config Config
+ // global (to this context) ethereum virtual machine
+ // used throughout the execution of the tx.
+ interpreter Interpreter
+ // abort is used to abort the EVM calling operations
+ // NOTE: must be set atomically
+ abort int32
+ // callGasTemp holds the gas available for the current call. This is needed because the
+ // available gas is calculated in gasCall* according to the 63/64 rule and later
+ // applied in opCall*.
+ callGasTemp uint64
+ // precompiles defines the precompiled contracts used by the EVM
+ precompiles map[common.Address]PrecompiledContract
+ // activePrecompiles defines the precompiles that are currently active
+ activePrecompiles []common.Address
+
+ // hooks is a set of functions that can be used to intercept and modify the
+ // behavior of the EVM when executing certain opcodes.
+ // The hooks are called before the execution of the respective opcodes.
+ hooks OpCodeHooks
+}
+
+// NewEVM returns a new EVM. The returned EVM is not thread safe and should
+// only ever be used *once*.
+func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
+ evm := &EVM{
+ Context: blockCtx,
+ TxContext: txCtx,
+ StateDB: statedb,
+ Config: config,
+ chainConfig: chainConfig,
+ chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil),
+ hooks: newNoopOpCodeHooks(),
+ }
+ // set the default precompiles
+ evm.activePrecompiles = DefaultActivePrecompiles(evm.chainRules)
+ evm.precompiles = DefaultPrecompiles(evm.chainRules)
+ evm.interpreter = NewEVMInterpreter(evm, config)
+
+ return evm
+}
+
+// NewEVMWithHooks returns a new EVM and takes a custom OpCodeHooks. The returned EVM is
+// not thread safe and should only ever be used *once*.
+func NewEVMWithHooks(hooks OpCodeHooks, blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
+ evm := &EVM{
+ Context: blockCtx,
+ TxContext: txCtx,
+ StateDB: statedb,
+ Config: config,
+ chainConfig: chainConfig,
+ chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil),
+ hooks: hooks,
+ }
+ // set the default precompiles
+ evm.activePrecompiles = DefaultActivePrecompiles(evm.chainRules)
+ evm.precompiles = DefaultPrecompiles(evm.chainRules)
+ evm.interpreter = NewEVMInterpreter(evm, config)
+
+ return evm
+}
+
+// Reset resets the EVM with a new transaction context.Reset
+// This is not threadsafe and should only be done very cautiously.
+func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
+ evm.TxContext = txCtx
+ evm.StateDB = statedb
+}
+
+// Cancel cancels any running EVM operation. This may be called concurrently and
+// it's safe to be called multiple times.
+func (evm *EVM) Cancel() {
+ atomic.StoreInt32(&evm.abort, 1)
+}
+
+// Cancelled returns true if Cancel has been called
+func (evm *EVM) Cancelled() bool {
+ return atomic.LoadInt32(&evm.abort) == 1
+}
+
+// Interpreter returns the current interpreter
+func (evm *EVM) Interpreter() Interpreter {
+ return evm.interpreter
+}
+
+// WithInterpreter sets the interpreter to the EVM instance
+func (evm *EVM) WithInterpreter(interpreter Interpreter) {
+ evm.interpreter = interpreter
+}
+
+// Call executes the contract associated with the addr with the given input as
+// parameters. It also handles any necessary value transfer required and takes
+// the necessary steps to create accounts and reverses the state in case of an
+// execution error or failed value transfer.
+func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
+ if err = evm.hooks.CallHook(evm, caller.Address(), addr); err != nil {
+ return nil, gas, err
+ }
+
+ // Fail if we're trying to execute above the call depth limit
+ if evm.depth > int(params.CallCreateDepth) {
+ return nil, gas, ErrDepth
+ }
+ // Fail if we're trying to transfer more than the available balance
+ if value.Sign() != 0 && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
+ return nil, gas, ErrInsufficientBalance
+ }
+
+ snapshot := evm.StateDB.Snapshot()
+ p, isPrecompile := evm.Precompile(addr)
+
+ if !evm.StateDB.Exist(addr) {
+ if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
+ // Calling a non existing account, don't do anything, but ping the tracer
+ if evm.Config.Debug {
+ if evm.depth == 0 {
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil)
+ } else {
+ evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ evm.Config.Tracer.CaptureExit(ret, 0, nil)
+ }
+ }
+ return nil, gas, nil
+ }
+ evm.StateDB.CreateAccount(addr)
+ }
+ evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
+
+ // Capture the tracer start/end events in debug mode
+ if evm.Config.Debug {
+ if evm.depth == 0 {
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
+ evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
+ }(gas, time.Now())
+ } else {
+ // Handle tracer events for entering and exiting a call frame
+ evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ defer func(startGas uint64) {
+ evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
+ }
+
+ // It is allowed to call precompiles, even via call -- as opposed to callcode, staticcall and delegatecall it can also modify state
+ if isPrecompile {
+ ret, gas, err = evm.RunPrecompiledContract(p, caller, input, gas, value, false)
+ } else {
+ // Initialise a new contract and set the code that is to be used by the EVM.
+ // The contract is a scoped environment for this execution context only.
+ code := evm.StateDB.GetCode(addr)
+ if len(code) == 0 {
+ ret, err = nil, nil // gas is unchanged
+ } else {
+ addrCopy := addr
+ // If the account has no code, we can abort here
+ // The depth-check is already done, and precompiles handled above
+ contract := NewContract(caller, AccountRef(addrCopy), value, gas)
+ contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code)
+ ret, err = evm.interpreter.Run(contract, input, false)
+ gas = contract.Gas
+ }
+ }
+ // When an error was returned by the EVM or when setting the creation code
+ // above we revert to the snapshot and consume any gas remaining. Additionally
+ // when we're in homestead this also counts for code storage gas errors.
+ if err != nil {
+ evm.StateDB.RevertToSnapshot(snapshot)
+ if err != ErrExecutionReverted {
+ gas = 0
+ }
+ // TODO: consider clearing up unused snapshots:
+ //} else {
+ // evm.StateDB.DiscardSnapshot(snapshot)
+ }
+ return ret, gas, err
+}
+
+// CallCode executes the contract associated with the addr with the given input
+// as parameters. It also handles any necessary value transfer required and takes
+// the necessary steps to create accounts and reverses the state in case of an
+// execution error or failed value transfer.
+//
+// CallCode differs from Call in the sense that it executes the given address'
+// code with the caller as context.
+func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
+ if err = evm.hooks.CallHook(evm, caller.Address(), addr); err != nil {
+ return nil, gas, err
+ }
+
+ // Fail if we're trying to execute above the call depth limit
+ if evm.depth > int(params.CallCreateDepth) {
+ return nil, gas, ErrDepth
+ }
+ // Fail if we're trying to transfer more than the available balance
+ // Note although it's noop to transfer X ether to caller itself. But
+ // if caller doesn't have enough balance, it would be an error to allow
+ // over-charging itself. So the check here is necessary.
+ if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
+ return nil, gas, ErrInsufficientBalance
+ }
+ snapshot := evm.StateDB.Snapshot()
+
+ // Invoke tracer hooks that signal entering/exiting a call frame
+ if evm.Config.Debug {
+ evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
+ defer func(startGas uint64) {
+ evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
+
+ // It is allowed to call precompiles, even via callcode, but only for reading
+ if p, isPrecompile := evm.Precompile(addr); isPrecompile {
+ ret, gas, err = evm.RunPrecompiledContract(p, caller, input, gas, value, true)
+ } else {
+ addrCopy := addr
+ // Initialise a new contract and set the code that is to be used by the EVM.
+ // The contract is a scoped environment for this execution context only.
+ contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
+ contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
+ ret, err = evm.interpreter.Run(contract, input, false)
+ gas = contract.Gas
+ }
+ if err != nil {
+ evm.StateDB.RevertToSnapshot(snapshot)
+ if err != ErrExecutionReverted {
+ gas = 0
+ }
+ }
+ return ret, gas, err
+}
+
+// DelegateCall executes the contract associated with the addr with the given input
+// as parameters. It reverses the state in case of an execution error.
+//
+// DelegateCall differs from CallCode in the sense that it executes the given address'
+// code with the caller as context and the caller is set to the caller of the caller.
+func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
+ if err = evm.hooks.CallHook(evm, caller.Address(), addr); err != nil {
+ return nil, gas, err
+ }
+
+ // Fail if we're trying to execute above the call depth limit
+ if evm.depth > int(params.CallCreateDepth) {
+ return nil, gas, ErrDepth
+ }
+ snapshot := evm.StateDB.Snapshot()
+
+ // Invoke tracer hooks that signal entering/exiting a call frame
+ if evm.Config.Debug {
+ evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil)
+ defer func(startGas uint64) {
+ evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
+
+ // It is allowed to call precompiles, even via delegatecall
+ if p, isPrecompile := evm.Precompile(addr); isPrecompile {
+ ret, gas, err = evm.RunPrecompiledContract(p, caller, input, gas, nil, true)
+ } else {
+ addrCopy := addr
+ // Initialise a new contract and make initialise the delegate values
+ contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
+ contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
+ ret, err = evm.interpreter.Run(contract, input, false)
+ gas = contract.Gas
+ }
+ if err != nil {
+ evm.StateDB.RevertToSnapshot(snapshot)
+ if err != ErrExecutionReverted {
+ gas = 0
+ }
+ }
+ return ret, gas, err
+}
+
+// StaticCall executes the contract associated with the addr with the given input
+// as parameters while disallowing any modifications to the state during the call.
+// Opcodes that attempt to perform such modifications will result in exceptions
+// instead of performing the modifications.
+func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
+ if err = evm.hooks.CallHook(evm, caller.Address(), addr); err != nil {
+ return nil, gas, err
+ }
+
+ // Fail if we're trying to execute above the call depth limit
+ if evm.depth > int(params.CallCreateDepth) {
+ return nil, gas, ErrDepth
+ }
+ // We take a snapshot here. This is a bit counter-intuitive, and could probably be skipped.
+ // However, even a staticcall is considered a 'touch'. On mainnet, static calls were introduced
+ // after all empty accounts were deleted, so this is not required. However, if we omit this,
+ // then certain tests start failing; stRevertTest/RevertPrecompiledTouchExactOOG.json.
+ // We could change this, but for now it's left for legacy reasons
+ snapshot := evm.StateDB.Snapshot()
+
+ // We do an AddBalance of zero here, just in order to trigger a touch.
+ // This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
+ // but is the correct thing to do and matters on other networks, in tests, and potential
+ // future scenarios
+ evm.StateDB.AddBalance(addr, big0)
+
+ // Invoke tracer hooks that signal entering/exiting a call frame
+ if evm.Config.Debug {
+ evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
+ defer func(startGas uint64) {
+ evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
+
+ if p, isPrecompile := evm.Precompile(addr); isPrecompile {
+ // Note: delegate call is not allowed to modify state on precompiles
+ ret, gas, err = evm.RunPrecompiledContract(p, caller, input, gas, new(big.Int), true)
+ } else {
+ // At this point, we use a copy of address. If we don't, the go compiler will
+ // leak the 'contract' to the outer scope, and make allocation for 'contract'
+ // even if the actual execution ends on RunPrecompiled above.
+ addrCopy := addr
+ // Initialise a new contract and set the code that is to be used by the EVM.
+ // The contract is a scoped environment for this execution context only.
+ contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas)
+ contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
+ // When an error was returned by the EVM or when setting the creation code
+ // above we revert to the snapshot and consume any gas remaining. Additionally
+ // when we're in Homestead this also counts for code storage gas errors.
+ ret, err = evm.interpreter.Run(contract, input, true)
+ gas = contract.Gas
+ }
+ if err != nil {
+ evm.StateDB.RevertToSnapshot(snapshot)
+ if err != ErrExecutionReverted {
+ gas = 0
+ }
+ }
+ return ret, gas, err
+}
+
+type codeAndHash struct {
+ code []byte
+ hash common.Hash
+}
+
+func (c *codeAndHash) Hash() common.Hash {
+ if c.hash == (common.Hash{}) {
+ c.hash = crypto.Keccak256Hash(c.code)
+ }
+ return c.hash
+}
+
+// create creates a new contract using code as deployment code.
+func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
+ // Depth check execution. Fail if we're trying to execute above the
+ // limit.
+ if evm.depth > int(params.CallCreateDepth) {
+ return nil, common.Address{}, gas, ErrDepth
+ }
+ if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
+ return nil, common.Address{}, gas, ErrInsufficientBalance
+ }
+ nonce := evm.StateDB.GetNonce(caller.Address())
+ if nonce+1 < nonce {
+ return nil, common.Address{}, gas, ErrNonceUintOverflow
+ }
+ evm.StateDB.SetNonce(caller.Address(), nonce+1)
+ // We add this to the access list _before_ taking a snapshot. Even if the creation fails,
+ // the access-list change should not be rolled back
+ if evm.chainRules.IsBerlin {
+ evm.StateDB.AddAddressToAccessList(address)
+ }
+ // Ensure there's no existing contract already at the designated address
+ contractHash := evm.StateDB.GetCodeHash(address)
+ if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
+ return nil, common.Address{}, 0, ErrContractAddressCollision
+ }
+ // Create a new account on the state
+ snapshot := evm.StateDB.Snapshot()
+ evm.StateDB.CreateAccount(address)
+ if evm.chainRules.IsEIP158 {
+ evm.StateDB.SetNonce(address, 1)
+ }
+ evm.Context.Transfer(evm.StateDB, caller.Address(), address, value)
+
+ // Initialise a new contract and set the code that is to be used by the EVM.
+ // The contract is a scoped environment for this execution context only.
+ contract := NewContract(caller, AccountRef(address), value, gas)
+ contract.SetCodeOptionalHash(&address, codeAndHash)
+
+ if evm.Config.Debug {
+ if evm.depth == 0 {
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
+ } else {
+ evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
+ }
+ }
+
+ start := time.Now()
+
+ ret, err := evm.interpreter.Run(contract, nil, false)
+
+ // Check whether the max code size has been exceeded, assign err if the case.
+ if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
+ err = ErrMaxCodeSizeExceeded
+ }
+
+ // Reject code starting with 0xEF if EIP-3541 is enabled.
+ if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsLondon {
+ err = ErrInvalidCode
+ }
+
+ // if the contract creation ran successfully and no errors were returned
+ // calculate the gas required to store the code. If the code could not
+ // be stored due to not enough gas set an error and let it be handled
+ // by the error checking condition below.
+ if err == nil {
+ createDataGas := uint64(len(ret)) * params.CreateDataGas
+ if contract.UseGas(createDataGas) {
+ evm.StateDB.SetCode(address, ret)
+ } else {
+ err = ErrCodeStoreOutOfGas
+ }
+ }
+
+ // When an error was returned by the EVM or when setting the creation code
+ // above we revert to the snapshot and consume any gas remaining. Additionally
+ // when we're in homestead this also counts for code storage gas errors.
+ if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
+ evm.StateDB.RevertToSnapshot(snapshot)
+ if err != ErrExecutionReverted {
+ contract.UseGas(contract.Gas)
+ }
+ }
+
+ if evm.Config.Debug {
+ if evm.depth == 0 {
+ evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
+ } else {
+ evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
+ }
+ }
+ return ret, address, contract.Gas, err
+}
+
+// Create creates a new contract using code as deployment code.
+func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+ if err = evm.hooks.CreateHook(evm, caller.Address()); err != nil {
+ return nil, common.Address{}, gas, err
+ }
+ contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
+ return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE)
+}
+
+// Create2 creates a new contract using code as deployment code.
+//
+// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
+// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
+func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+ if err = evm.hooks.CreateHook(evm, caller.Address()); err != nil {
+ return nil, common.Address{}, gas, err
+ }
+ codeAndHash := &codeAndHash{code: code}
+ contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())
+ return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
+}
+
+// ChainConfig returns the environment's chain configuration
+func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
diff --git a/x/evm/core/vm/gas.go b/x/evm/core/vm/gas.go
new file mode 100644
index 00000000..5cf1d852
--- /dev/null
+++ b/x/evm/core/vm/gas.go
@@ -0,0 +1,53 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "github.com/holiman/uint256"
+)
+
+// Gas costs
+const (
+ GasQuickStep uint64 = 2
+ GasFastestStep uint64 = 3
+ GasFastStep uint64 = 5
+ GasMidStep uint64 = 8
+ GasSlowStep uint64 = 10
+ GasExtStep uint64 = 20
+)
+
+// callGas returns the actual gas cost of the call.
+//
+// The cost of gas was changed during the homestead price change HF.
+// As part of EIP 150 (TangerineWhistle), the returned gas is gas - base * 63 / 64.
+func callGas(isEip150 bool, availableGas, base uint64, callCost *uint256.Int) (uint64, error) {
+ if isEip150 {
+ availableGas = availableGas - base
+ gas := availableGas - availableGas/64
+ // If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150
+ // is smaller than the requested amount. Therefore we return the new gas instead
+ // of returning an error.
+ if !callCost.IsUint64() || gas < callCost.Uint64() {
+ return gas, nil
+ }
+ }
+ if !callCost.IsUint64() {
+ return 0, ErrGasUintOverflow
+ }
+
+ return callCost.Uint64(), nil
+}
diff --git a/x/evm/core/vm/gas_table.go b/x/evm/core/vm/gas_table.go
new file mode 100644
index 00000000..f37d914c
--- /dev/null
+++ b/x/evm/core/vm/gas_table.go
@@ -0,0 +1,441 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// memoryGasCost calculates the quadratic gas for memory expansion. It does so
+// only for the memory region that is expanded, not the total memory.
+func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
+ if newMemSize == 0 {
+ return 0, nil
+ }
+ // The maximum that will fit in a uint64 is max_word_count - 1. Anything above
+ // that will result in an overflow. Additionally, a newMemSize which results in
+ // a newMemSizeWords larger than 0xFFFFFFFF will cause the square operation to
+ // overflow. The constant 0x1FFFFFFFE0 is the highest number that can be used
+ // without overflowing the gas calculation.
+ if newMemSize > 0x1FFFFFFFE0 {
+ return 0, ErrGasUintOverflow
+ }
+ newMemSizeWords := toWordSize(newMemSize)
+ newMemSize = newMemSizeWords * 32
+
+ if newMemSize > uint64(mem.Len()) {
+ square := newMemSizeWords * newMemSizeWords
+ linCoef := newMemSizeWords * params.MemoryGas
+ quadCoef := square / params.QuadCoeffDiv
+ newTotalFee := linCoef + quadCoef
+
+ fee := newTotalFee - mem.lastGasCost
+ mem.lastGasCost = newTotalFee
+
+ return fee, nil
+ }
+ return 0, nil
+}
+
+// memoryCopierGas creates the gas functions for the following opcodes, and takes
+// the stack position of the operand which determines the size of the data to copy
+// as argument:
+// CALLDATACOPY (stack position 2)
+// CODECOPY (stack position 2)
+// EXTCODECOPY (stack position 3)
+// RETURNDATACOPY (stack position 2)
+func memoryCopierGas(stackpos int) gasFunc {
+ return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ // Gas for expanding the memory
+ gas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ // And gas for copying data, charged per word at param.CopyGas
+ words, overflow := stack.Back(stackpos).Uint64WithOverflow()
+ if overflow {
+ return 0, ErrGasUintOverflow
+ }
+
+ if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+
+ if gas, overflow = math.SafeAdd(gas, words); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+ }
+}
+
+var (
+ gasCallDataCopy = memoryCopierGas(2)
+ gasCodeCopy = memoryCopierGas(2)
+ gasExtCodeCopy = memoryCopierGas(3)
+ gasReturnDataCopy = memoryCopierGas(2)
+)
+
+func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ var (
+ y, x = stack.Back(1), stack.Back(0)
+ current = evm.StateDB.GetState(contract.Address(), x.Bytes32())
+ )
+ // The legacy gas metering only takes into consideration the current state
+ // Legacy rules should be applied if we are in Petersburg (removal of EIP-1283)
+ // OR Constantinople is not active
+ if evm.chainRules.IsPetersburg || !evm.chainRules.IsConstantinople {
+ // This checks for 3 scenario's and calculates gas accordingly:
+ //
+ // 1. From a zero-value address to a non-zero value (NEW VALUE)
+ // 2. From a non-zero value address to a zero-value address (DELETE)
+ // 3. From a non-zero to a non-zero (CHANGE)
+ switch {
+ case current == (common.Hash{}) && y.Sign() != 0: // 0 => non 0
+ return params.SstoreSetGas, nil
+ case current != (common.Hash{}) && y.Sign() == 0: // non 0 => 0
+ evm.StateDB.AddRefund(params.SstoreRefundGas)
+ return params.SstoreClearGas, nil
+ default: // non 0 => non 0 (or 0 => 0)
+ return params.SstoreResetGas, nil
+ }
+ }
+ // The new gas metering is based on net gas costs (EIP-1283):
+ //
+ // 1. If current value equals new value (this is a no-op), 200 gas is deducted.
+ // 2. If current value does not equal new value
+ // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context)
+ // 2.1.1. If original value is 0, 20000 gas is deducted.
+ // 2.1.2. Otherwise, 5000 gas is deducted. If new value is 0, add 15000 gas to refund counter.
+ // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses.
+ // 2.2.1. If original value is not 0
+ // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0.
+ // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter.
+ // 2.2.2. If original value equals new value (this storage slot is reset)
+ // 2.2.2.1. If original value is 0, add 19800 gas to refund counter.
+ // 2.2.2.2. Otherwise, add 4800 gas to refund counter.
+ value := common.Hash(y.Bytes32())
+ if current == value { // noop (1)
+ return params.NetSstoreNoopGas, nil
+ }
+ original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32())
+ if original == current {
+ if original == (common.Hash{}) { // create slot (2.1.1)
+ return params.NetSstoreInitGas, nil
+ }
+ if value == (common.Hash{}) { // delete slot (2.1.2b)
+ evm.StateDB.AddRefund(params.NetSstoreClearRefund)
+ }
+ return params.NetSstoreCleanGas, nil // write existing slot (2.1.2)
+ }
+ if original != (common.Hash{}) {
+ if current == (common.Hash{}) { // recreate slot (2.2.1.1)
+ evm.StateDB.SubRefund(params.NetSstoreClearRefund)
+ } else if value == (common.Hash{}) { // delete slot (2.2.1.2)
+ evm.StateDB.AddRefund(params.NetSstoreClearRefund)
+ }
+ }
+ if original == value {
+ if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
+ evm.StateDB.AddRefund(params.NetSstoreResetClearRefund)
+ } else { // reset to original existing slot (2.2.2.2)
+ evm.StateDB.AddRefund(params.NetSstoreResetRefund)
+ }
+ }
+ return params.NetSstoreDirtyGas, nil
+}
+
+// 0. If *gasleft* is less than or equal to 2300, fail the current call.
+// 1. If current value equals new value (this is a no-op), SLOAD_GAS is deducted.
+// 2. If current value does not equal new value:
+// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context):
+// 2.1.1. If original value is 0, SSTORE_SET_GAS (20K) gas is deducted.
+// 2.1.2. Otherwise, SSTORE_RESET_GAS gas is deducted. If new value is 0, add SSTORE_CLEARS_SCHEDULE to refund counter.
+// 2.2. If original value does not equal current value (this storage slot is dirty), SLOAD_GAS gas is deducted. Apply both of the following clauses:
+// 2.2.1. If original value is not 0:
+// 2.2.1.1. If current value is 0 (also means that new value is not 0), subtract SSTORE_CLEARS_SCHEDULE gas from refund counter.
+// 2.2.1.2. If new value is 0 (also means that current value is not 0), add SSTORE_CLEARS_SCHEDULE gas to refund counter.
+// 2.2.2. If original value equals new value (this storage slot is reset):
+// 2.2.2.1. If original value is 0, add SSTORE_SET_GAS - SLOAD_GAS to refund counter.
+// 2.2.2.2. Otherwise, add SSTORE_RESET_GAS - SLOAD_GAS gas to refund counter.
+func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ // If we fail the minimum gas availability invariant, fail (0)
+ if contract.Gas <= params.SstoreSentryGasEIP2200 {
+ return 0, errors.New("not enough gas for reentrancy sentry")
+ }
+ // Gas sentry honoured, do the actual gas calculation based on the stored value
+ var (
+ y, x = stack.Back(1), stack.Back(0)
+ current = evm.StateDB.GetState(contract.Address(), x.Bytes32())
+ )
+ value := common.Hash(y.Bytes32())
+
+ if current == value { // noop (1)
+ return params.SloadGasEIP2200, nil
+ }
+ original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32())
+ if original == current {
+ if original == (common.Hash{}) { // create slot (2.1.1)
+ return params.SstoreSetGasEIP2200, nil
+ }
+ if value == (common.Hash{}) { // delete slot (2.1.2b)
+ evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200)
+ }
+ return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2)
+ }
+ if original != (common.Hash{}) {
+ if current == (common.Hash{}) { // recreate slot (2.2.1.1)
+ evm.StateDB.SubRefund(params.SstoreClearsScheduleRefundEIP2200)
+ } else if value == (common.Hash{}) { // delete slot (2.2.1.2)
+ evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200)
+ }
+ }
+ if original == value {
+ if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
+ evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.SloadGasEIP2200)
+ } else { // reset to original existing slot (2.2.2.2)
+ evm.StateDB.AddRefund(params.SstoreResetGasEIP2200 - params.SloadGasEIP2200)
+ }
+ }
+ return params.SloadGasEIP2200, nil // dirty update (2.2)
+}
+
+func makeGasLog(n uint64) gasFunc {
+ return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ requestedSize, overflow := stack.Back(1).Uint64WithOverflow()
+ if overflow {
+ return 0, ErrGasUintOverflow
+ }
+
+ gas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+
+ if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+
+ var memorySizeGas uint64
+ if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+ }
+}
+
+func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ gas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ wordGas, overflow := stack.Back(1).Uint64WithOverflow()
+ if overflow {
+ return 0, ErrGasUintOverflow
+ }
+ if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+// pureMemoryGascost is used by several operations, which aside from their
+// static cost have a dynamic cost which is solely based on the memory
+// expansion
+func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ return memoryGasCost(mem, memorySize)
+}
+
+var (
+ gasReturn = pureMemoryGascost
+ gasRevert = pureMemoryGascost
+ gasMLoad = pureMemoryGascost
+ gasMStore8 = pureMemoryGascost
+ gasMStore = pureMemoryGascost
+ gasCreate = pureMemoryGascost
+)
+
+func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ gas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ wordGas, overflow := stack.Back(2).Uint64WithOverflow()
+ if overflow {
+ return 0, ErrGasUintOverflow
+ }
+ if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ expByteLen := uint64((stack.Data[stack.Len()-2].BitLen() + 7) / 8)
+
+ var (
+ gas = expByteLen * params.ExpByteFrontier // no overflow check required. Max is 256 * ExpByte gas
+ overflow bool
+ )
+ if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ expByteLen := uint64((stack.Data[stack.Len()-2].BitLen() + 7) / 8)
+
+ var (
+ gas = expByteLen * params.ExpByteEIP158 // no overflow check required. Max is 256 * ExpByte gas
+ overflow bool
+ )
+ if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ var (
+ gas uint64
+ transfersValue = !stack.Back(2).IsZero()
+ address = common.Address(stack.Back(1).Bytes20())
+ )
+ if evm.chainRules.IsEIP158 {
+ if transfersValue && evm.StateDB.Empty(address) {
+ gas += params.CallNewAccountGas
+ }
+ } else if !evm.StateDB.Exist(address) {
+ gas += params.CallNewAccountGas
+ }
+ if transfersValue {
+ gas += params.CallValueTransferGas
+ }
+ memoryGas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ var overflow bool
+ if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+
+ evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
+ if err != nil {
+ return 0, err
+ }
+ if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ memoryGas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ var (
+ gas uint64
+ overflow bool
+ )
+ if stack.Back(2).Sign() != 0 {
+ gas += params.CallValueTransferGas
+ }
+ if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
+ if err != nil {
+ return 0, err
+ }
+ if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ gas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
+ if err != nil {
+ return 0, err
+ }
+ var overflow bool
+ if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ gas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
+ if err != nil {
+ return 0, err
+ }
+ var overflow bool
+ if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ var gas uint64
+ // EIP150 homestead gas reprice fork:
+ if evm.chainRules.IsEIP150 {
+ gas = params.SelfdestructGasEIP150
+ address := common.Address(stack.Back(0).Bytes20())
+
+ if evm.chainRules.IsEIP158 {
+ // if empty and transfers value
+ if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
+ gas += params.CreateBySelfdestructGas
+ }
+ } else if !evm.StateDB.Exist(address) {
+ gas += params.CreateBySelfdestructGas
+ }
+ }
+
+ if !evm.StateDB.HasSuicided(contract.Address()) {
+ evm.StateDB.AddRefund(params.SelfdestructRefundGas)
+ }
+ return gas, nil
+}
diff --git a/x/evm/core/vm/gas_table_test.go b/x/evm/core/vm/gas_table_test.go
new file mode 100644
index 00000000..efba3cff
--- /dev/null
+++ b/x/evm/core/vm/gas_table_test.go
@@ -0,0 +1,107 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "math"
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+func TestMemoryGasCost(t *testing.T) {
+ tests := []struct {
+ size uint64
+ cost uint64
+ overflow bool
+ }{
+ {0x1fffffffe0, 36028809887088637, false},
+ {0x1fffffffe1, 0, true},
+ }
+ for i, tt := range tests {
+ v, err := memoryGasCost(&Memory{}, tt.size)
+ if (err == ErrGasUintOverflow) != tt.overflow {
+ t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == ErrGasUintOverflow, tt.overflow)
+ }
+ if v != tt.cost {
+ t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, v, tt.cost)
+ }
+ }
+}
+
+var eip2200Tests = []struct {
+ original byte
+ gaspool uint64
+ input string
+ used uint64
+ refund uint64
+ failure error
+}{
+ {0, math.MaxUint64, "0x60006000556000600055", 1612, 0, nil}, // 0 -> 0 -> 0
+ {0, math.MaxUint64, "0x60006000556001600055", 20812, 0, nil}, // 0 -> 0 -> 1
+ {0, math.MaxUint64, "0x60016000556000600055", 20812, 19200, nil}, // 0 -> 1 -> 0
+ {0, math.MaxUint64, "0x60016000556002600055", 20812, 0, nil}, // 0 -> 1 -> 2
+ {0, math.MaxUint64, "0x60016000556001600055", 20812, 0, nil}, // 0 -> 1 -> 1
+ {1, math.MaxUint64, "0x60006000556000600055", 5812, 15000, nil}, // 1 -> 0 -> 0
+ {1, math.MaxUint64, "0x60006000556001600055", 5812, 4200, nil}, // 1 -> 0 -> 1
+ {1, math.MaxUint64, "0x60006000556002600055", 5812, 0, nil}, // 1 -> 0 -> 2
+ {1, math.MaxUint64, "0x60026000556000600055", 5812, 15000, nil}, // 1 -> 2 -> 0
+ {1, math.MaxUint64, "0x60026000556003600055", 5812, 0, nil}, // 1 -> 2 -> 3
+ {1, math.MaxUint64, "0x60026000556001600055", 5812, 4200, nil}, // 1 -> 2 -> 1
+ {1, math.MaxUint64, "0x60026000556002600055", 5812, 0, nil}, // 1 -> 2 -> 2
+ {1, math.MaxUint64, "0x60016000556000600055", 5812, 15000, nil}, // 1 -> 1 -> 0
+ {1, math.MaxUint64, "0x60016000556002600055", 5812, 0, nil}, // 1 -> 1 -> 2
+ {1, math.MaxUint64, "0x60016000556001600055", 1612, 0, nil}, // 1 -> 1 -> 1
+ {0, math.MaxUint64, "0x600160005560006000556001600055", 40818, 19200, nil}, // 0 -> 1 -> 0 -> 1
+ {1, math.MaxUint64, "0x600060005560016000556000600055", 10818, 19200, nil}, // 1 -> 0 -> 1 -> 0
+ {1, 2306, "0x6001600055", 2306, 0, ErrOutOfGas}, // 1 -> 1 (2300 sentry + 2xPUSH)
+ {1, 2307, "0x6001600055", 806, 0, nil}, // 1 -> 1 (2301 sentry + 2xPUSH)
+}
+
+func TestEIP2200(t *testing.T) {
+ for i, tt := range eip2200Tests {
+ address := common.BytesToAddress([]byte("contract"))
+
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
+ statedb.CreateAccount(address)
+ statedb.SetCode(address, hexutil.MustDecode(tt.input))
+ statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
+ statedb.Finalise(true) // Push the state into the "original" slot
+
+ vmctx := BlockContext{
+ CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
+ Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ }
+ vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []string{"ethereum_2200"}})
+
+ _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
+ if err != tt.failure {
+ t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
+ }
+ if used := tt.gaspool - gas; used != tt.used {
+ t.Errorf("test %d: gas used mismatch: have %v, want %v", i, used, tt.used)
+ }
+ if refund := vmenv.StateDB.GetRefund(); refund != tt.refund {
+ t.Errorf("test %d: gas refund mismatch: have %v, want %v", i, refund, tt.refund)
+ }
+ }
+}
diff --git a/x/evm/core/vm/instructions.go b/x/evm/core/vm/instructions.go
new file mode 100644
index 00000000..46409ce6
--- /dev/null
+++ b/x/evm/core/vm/instructions.go
@@ -0,0 +1,934 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "sync/atomic"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
+ "golang.org/x/crypto/sha3"
+)
+
+func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.Add(&x, y)
+ return nil, nil
+}
+
+func opSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.Sub(&x, y)
+ return nil, nil
+}
+
+func opMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.Mul(&x, y)
+ return nil, nil
+}
+
+func opDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.Div(&x, y)
+ return nil, nil
+}
+
+func opSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.SDiv(&x, y)
+ return nil, nil
+}
+
+func opMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.Mod(&x, y)
+ return nil, nil
+}
+
+func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.SMod(&x, y)
+ return nil, nil
+}
+
+func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ base, exponent := scope.Stack.Pop(), scope.Stack.Peek()
+ exponent.Exp(&base, exponent)
+ return nil, nil
+}
+
+func opSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ back, num := scope.Stack.Pop(), scope.Stack.Peek()
+ num.ExtendSign(num, &back)
+ return nil, nil
+}
+
+func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x := scope.Stack.Peek()
+ x.Not(x)
+ return nil, nil
+}
+
+func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ if x.Lt(y) {
+ y.SetOne()
+ } else {
+ y.Clear()
+ }
+ return nil, nil
+}
+
+func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ if x.Gt(y) {
+ y.SetOne()
+ } else {
+ y.Clear()
+ }
+ return nil, nil
+}
+
+func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ if x.Slt(y) {
+ y.SetOne()
+ } else {
+ y.Clear()
+ }
+ return nil, nil
+}
+
+func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ if x.Sgt(y) {
+ y.SetOne()
+ } else {
+ y.Clear()
+ }
+ return nil, nil
+}
+
+func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ if x.Eq(y) {
+ y.SetOne()
+ } else {
+ y.Clear()
+ }
+ return nil, nil
+}
+
+func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x := scope.Stack.Peek()
+ if x.IsZero() {
+ x.SetOne()
+ } else {
+ x.Clear()
+ }
+ return nil, nil
+}
+
+func opAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.And(&x, y)
+ return nil, nil
+}
+
+func opOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.Or(&x, y)
+ return nil, nil
+}
+
+func opXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
+ y.Xor(&x, y)
+ return nil, nil
+}
+
+func opByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ th, val := scope.Stack.Pop(), scope.Stack.Peek()
+ val.Byte(&th)
+ return nil, nil
+}
+
+func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y, z := scope.Stack.Pop(), scope.Stack.Pop(), scope.Stack.Peek()
+ if z.IsZero() {
+ z.Clear()
+ } else {
+ z.AddMod(&x, &y, z)
+ }
+ return nil, nil
+}
+
+func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y, z := scope.Stack.Pop(), scope.Stack.Pop(), scope.Stack.Peek()
+ z.MulMod(&x, &y, z)
+ return nil, nil
+}
+
+// opSHL implements Shift Left
+// The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2,
+// and pushes on the stack arg2 shifted to the left by arg1 number of bits.
+func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
+ shift, value := scope.Stack.Pop(), scope.Stack.Peek()
+ if shift.LtUint64(256) {
+ value.Lsh(value, uint(shift.Uint64()))
+ } else {
+ value.Clear()
+ }
+ return nil, nil
+}
+
+// opSHR implements Logical Shift Right
+// The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2,
+// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
+func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
+ shift, value := scope.Stack.Pop(), scope.Stack.Peek()
+ if shift.LtUint64(256) {
+ value.Rsh(value, uint(shift.Uint64()))
+ } else {
+ value.Clear()
+ }
+ return nil, nil
+}
+
+// opSAR implements Arithmetic Shift Right
+// The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2,
+// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
+func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ shift, value := scope.Stack.Pop(), scope.Stack.Peek()
+ if shift.GtUint64(256) {
+ if value.Sign() >= 0 {
+ value.Clear()
+ } else {
+ // Max negative shift: all bits set
+ value.SetAllOne()
+ }
+ return nil, nil
+ }
+ n := uint(shift.Uint64())
+ value.SRsh(value, n)
+ return nil, nil
+}
+
+func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ offset, size := scope.Stack.Pop(), scope.Stack.Peek()
+ data := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64()))
+
+ if interpreter.hasher == nil {
+ interpreter.hasher = sha3.NewLegacyKeccak256().(keccakState)
+ } else {
+ interpreter.hasher.Reset()
+ }
+ interpreter.hasher.Write(data)
+ interpreter.hasher.Read(interpreter.hasherBuf[:])
+
+ evm := interpreter.evm
+ if evm.Config.EnablePreimageRecording {
+ evm.StateDB.AddPreimage(interpreter.hasherBuf, data)
+ }
+
+ size.SetBytes(interpreter.hasherBuf[:])
+ return nil, nil
+}
+
+func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes()))
+ return nil, nil
+}
+
+func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ slot := scope.Stack.Peek()
+ address := common.Address(slot.Bytes20())
+ slot.SetFromBig(interpreter.evm.StateDB.GetBalance(address))
+ return nil, nil
+}
+
+func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes()))
+ return nil, nil
+}
+
+func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes()))
+ return nil, nil
+}
+
+func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ v, _ := uint256.FromBig(scope.Contract.value)
+ scope.Stack.Push(v)
+ return nil, nil
+}
+
+func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x := scope.Stack.Peek()
+ if offset, overflow := x.Uint64WithOverflow(); !overflow {
+ data := getData(scope.Contract.Input, offset, 32)
+ x.SetBytes(data)
+ } else {
+ x.Clear()
+ }
+ return nil, nil
+}
+
+func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Input))))
+ return nil, nil
+}
+
+func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ var (
+ memOffset = scope.Stack.Pop()
+ dataOffset = scope.Stack.Pop()
+ length = scope.Stack.Pop()
+ )
+ dataOffset64, overflow := dataOffset.Uint64WithOverflow()
+ if overflow {
+ dataOffset64 = 0xffffffffffffffff
+ }
+ // These values are checked for overflow during gas cost calculation
+ memOffset64 := memOffset.Uint64()
+ length64 := length.Uint64()
+ scope.Memory.Set(memOffset64, length64, getData(scope.Contract.Input, dataOffset64, length64))
+
+ return nil, nil
+}
+
+func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData))))
+ return nil, nil
+}
+
+func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ var (
+ memOffset = scope.Stack.Pop()
+ dataOffset = scope.Stack.Pop()
+ length = scope.Stack.Pop()
+ )
+
+ offset64, overflow := dataOffset.Uint64WithOverflow()
+ if overflow {
+ return nil, ErrReturnDataOutOfBounds
+ }
+ // we can reuse dataOffset now (aliasing it for clarity)
+ end := dataOffset
+ end.Add(&dataOffset, &length)
+ end64, overflow := end.Uint64WithOverflow()
+ if overflow || uint64(len(interpreter.returnData)) < end64 {
+ return nil, ErrReturnDataOutOfBounds
+ }
+ scope.Memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[offset64:end64])
+ return nil, nil
+}
+
+func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ slot := scope.Stack.Peek()
+ slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20())))
+ return nil, nil
+}
+
+func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ l := new(uint256.Int)
+ l.SetUint64(uint64(len(scope.Contract.Code)))
+ scope.Stack.Push(l)
+ return nil, nil
+}
+
+func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ var (
+ memOffset = scope.Stack.Pop()
+ codeOffset = scope.Stack.Pop()
+ length = scope.Stack.Pop()
+ )
+ uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
+ if overflow {
+ uint64CodeOffset = 0xffffffffffffffff
+ }
+ codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64())
+ scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
+
+ return nil, nil
+}
+
+func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ var (
+ stack = scope.Stack
+ a = stack.Pop()
+ memOffset = stack.Pop()
+ codeOffset = stack.Pop()
+ length = stack.Pop()
+ )
+ uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
+ if overflow {
+ uint64CodeOffset = 0xffffffffffffffff
+ }
+ addr := common.Address(a.Bytes20())
+ codeCopy := getData(interpreter.evm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64())
+ scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
+
+ return nil, nil
+}
+
+// opExtCodeHash returns the code hash of a specified account.
+// There are several cases when the function is called, while we can relay everything
+// to `state.GetCodeHash` function to ensure the correctness.
+//
+// (1) Caller tries to get the code hash of a normal contract account, state
+//
+// should return the relative code hash and set it as the result.
+//
+// (2) Caller tries to get the code hash of a non-existent account, state should
+//
+// return common.Hash{} and zero will be set as the result.
+//
+// (3) Caller tries to get the code hash for an account without contract code,
+//
+// state should return emptyCodeHash(0xc5d246...) as the result.
+//
+// (4) Caller tries to get the code hash of a precompiled account, the result
+//
+// should be zero or emptyCodeHash.
+//
+// It is worth noting that in order to avoid unnecessary create and clean,
+// all precompile accounts on mainnet have been transferred 1 wei, so the return
+// here should be emptyCodeHash.
+// If the precompile account is not transferred any amount on a private or
+// customized chain, the return value will be zero.
+//
+// (5) Caller tries to get the code hash for an account which is marked as suicided
+//
+// in the current transaction, the code hash of this account should be returned.
+//
+// (6) Caller tries to get the code hash for an account which is marked as deleted,
+//
+// this account should be regarded as a non-existent account and zero should be returned.
+func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ slot := scope.Stack.Peek()
+ address := common.Address(slot.Bytes20())
+ if interpreter.evm.StateDB.Empty(address) {
+ slot.Clear()
+ } else {
+ slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes())
+ }
+ return nil, nil
+}
+
+func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ v, _ := uint256.FromBig(interpreter.evm.GasPrice)
+ scope.Stack.Push(v)
+ return nil, nil
+}
+
+func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ num := scope.Stack.Peek()
+ num64, overflow := num.Uint64WithOverflow()
+ if overflow {
+ num.Clear()
+ return nil, nil
+ }
+ var upper, lower uint64
+ upper = interpreter.evm.Context.BlockNumber.Uint64()
+ if upper < 257 {
+ lower = 0
+ } else {
+ lower = upper - 256
+ }
+ if num64 >= lower && num64 < upper {
+ num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes())
+ } else {
+ num.Clear()
+ }
+ return nil, nil
+}
+
+func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
+ return nil, nil
+}
+
+func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ v, _ := uint256.FromBig(interpreter.evm.Context.Time)
+ scope.Stack.Push(v)
+ return nil, nil
+}
+
+func opNumber(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber)
+ scope.Stack.Push(v)
+ return nil, nil
+}
+
+func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty)
+ scope.Stack.Push(v)
+ return nil, nil
+}
+
+func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes())
+ scope.Stack.Push(v)
+ return nil, nil
+}
+
+func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
+ return nil, nil
+}
+
+func opPop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Pop()
+ return nil, nil
+}
+
+func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ v := scope.Stack.Peek()
+ offset := int64(v.Uint64())
+ v.SetBytes(scope.Memory.GetPtr(offset, 32))
+ return nil, nil
+}
+
+func opMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ // pop value of the stack
+ mStart, val := scope.Stack.Pop(), scope.Stack.Pop()
+ scope.Memory.Set32(mStart.Uint64(), &val)
+ return nil, nil
+}
+
+func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ off, val := scope.Stack.Pop(), scope.Stack.Pop()
+ scope.Memory.store[off.Uint64()] = byte(val.Uint64())
+ return nil, nil
+}
+
+func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ loc := scope.Stack.Peek()
+ hash := common.Hash(loc.Bytes32())
+ val := interpreter.evm.StateDB.GetState(scope.Contract.Address(), hash)
+ loc.SetBytes(val.Bytes())
+ return nil, nil
+}
+
+func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ if interpreter.readOnly {
+ return nil, ErrWriteProtection
+ }
+ loc := scope.Stack.Pop()
+ val := scope.Stack.Pop()
+ interpreter.evm.StateDB.SetState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
+ return nil, nil
+}
+
+func opJump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ if atomic.LoadInt32(&interpreter.evm.abort) != 0 {
+ return nil, errStopToken
+ }
+ pos := scope.Stack.Pop()
+ if !scope.Contract.validJumpdest(&pos) {
+ return nil, ErrInvalidJump
+ }
+ *pc = pos.Uint64() - 1 // pc will be increased by the interpreter loop
+ return nil, nil
+}
+
+func opJumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ if atomic.LoadInt32(&interpreter.evm.abort) != 0 {
+ return nil, errStopToken
+ }
+ pos, cond := scope.Stack.Pop(), scope.Stack.Pop()
+ if !cond.IsZero() {
+ if !scope.Contract.validJumpdest(&pos) {
+ return nil, ErrInvalidJump
+ }
+ *pc = pos.Uint64() - 1 // pc will be increased by the interpreter loop
+ }
+ return nil, nil
+}
+
+func opJumpdest(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ return nil, nil
+}
+
+func opPc(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetUint64(*pc))
+ return nil, nil
+}
+
+func opMsize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetUint64(uint64(scope.Memory.Len())))
+ return nil, nil
+}
+
+func opGas(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetUint64(scope.Contract.Gas))
+ return nil, nil
+}
+
+func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ if interpreter.readOnly {
+ return nil, ErrWriteProtection
+ }
+ var (
+ value = scope.Stack.Pop()
+ offset, size = scope.Stack.Pop(), scope.Stack.Pop()
+ input = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
+ gas = scope.Contract.Gas
+ )
+ if interpreter.evm.chainRules.IsEIP150 {
+ gas -= gas / 64
+ }
+ // reuse size int for stackvalue
+ stackvalue := size
+
+ scope.Contract.UseGas(gas)
+ // TODO: use uint256.Int instead of converting with toBig()
+ bigVal := big0
+ if !value.IsZero() {
+ bigVal = value.ToBig()
+ }
+
+ res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, bigVal)
+ // Push item on the stack based on the returned error. If the ruleset is
+ // homestead we must check for CodeStoreOutOfGasError (homestead only
+ // rule) and treat as an error, if the ruleset is frontier we must
+ // ignore this error and pretend the operation was successful.
+ if interpreter.evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas {
+ stackvalue.Clear()
+ } else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
+ stackvalue.Clear()
+ } else {
+ stackvalue.SetBytes(addr.Bytes())
+ }
+ scope.Stack.Push(&stackvalue)
+ scope.Contract.Gas += returnGas
+
+ if suberr == ErrExecutionReverted {
+ interpreter.returnData = res // set REVERT data to return data buffer
+ return res, nil
+ }
+ interpreter.returnData = nil // clear dirty return data buffer
+ return nil, nil
+}
+
+func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ if interpreter.readOnly {
+ return nil, ErrWriteProtection
+ }
+ var (
+ endowment = scope.Stack.Pop()
+ offset, size = scope.Stack.Pop(), scope.Stack.Pop()
+ salt = scope.Stack.Pop()
+ input = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
+ gas = scope.Contract.Gas
+ )
+
+ // Apply EIP150
+ gas -= gas / 64
+ scope.Contract.UseGas(gas)
+ // reuse size int for stackvalue
+ stackvalue := size
+ // TODO: use uint256.Int instead of converting with toBig()
+ bigEndowment := big0
+ if !endowment.IsZero() {
+ bigEndowment = endowment.ToBig()
+ }
+ res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas,
+ bigEndowment, &salt)
+ // Push item on the stack based on the returned error.
+ if suberr != nil {
+ stackvalue.Clear()
+ } else {
+ stackvalue.SetBytes(addr.Bytes())
+ }
+ scope.Stack.Push(&stackvalue)
+ scope.Contract.Gas += returnGas
+
+ if suberr == ErrExecutionReverted {
+ interpreter.returnData = res // set REVERT data to return data buffer
+ return res, nil
+ }
+ interpreter.returnData = nil // clear dirty return data buffer
+ return nil, nil
+}
+
+func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ stack := scope.Stack
+ // Pop gas. The actual gas in interpreter.evm.callGasTemp.
+ // We can use this as a temporary value
+ temp := stack.Pop()
+ gas := interpreter.evm.callGasTemp
+ // Pop other call parameters.
+ addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
+ toAddr := common.Address(addr.Bytes20())
+ // Get the arguments from the memory.
+ args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
+
+ if interpreter.readOnly && !value.IsZero() {
+ return nil, ErrWriteProtection
+ }
+ bigVal := big0
+ // TODO: use uint256.Int instead of converting with toBig()
+ // By using big0 here, we save an alloc for the most common case (non-ether-transferring contract calls),
+ // but it would make more sense to extend the usage of uint256.Int
+ if !value.IsZero() {
+ gas += params.CallStipend
+ bigVal = value.ToBig()
+ }
+
+ ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, bigVal)
+
+ if err != nil {
+ temp.Clear()
+ } else {
+ temp.SetOne()
+ }
+ stack.Push(&temp)
+ if err == nil || err == ErrExecutionReverted {
+ ret = common.CopyBytes(ret)
+ scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
+ }
+ scope.Contract.Gas += returnGas
+
+ interpreter.returnData = ret
+ return ret, nil
+}
+
+func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ // Pop gas. The actual gas is in interpreter.evm.callGasTemp.
+ stack := scope.Stack
+ // We use it as a temporary value
+ temp := stack.Pop()
+ gas := interpreter.evm.callGasTemp
+ // Pop other call parameters.
+ addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
+ toAddr := common.Address(addr.Bytes20())
+ // Get arguments from the memory.
+ args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
+
+ // TODO: use uint256.Int instead of converting with toBig()
+ bigVal := big0
+ if !value.IsZero() {
+ gas += params.CallStipend
+ bigVal = value.ToBig()
+ }
+
+ ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, bigVal)
+ if err != nil {
+ temp.Clear()
+ } else {
+ temp.SetOne()
+ }
+ stack.Push(&temp)
+ if err == nil || err == ErrExecutionReverted {
+ ret = common.CopyBytes(ret)
+ scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
+ }
+ scope.Contract.Gas += returnGas
+
+ interpreter.returnData = ret
+ return ret, nil
+}
+
+func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ stack := scope.Stack
+ // Pop gas. The actual gas is in interpreter.evm.callGasTemp.
+ // We use it as a temporary value
+ temp := stack.Pop()
+ gas := interpreter.evm.callGasTemp
+ // Pop other call parameters.
+ addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
+ toAddr := common.Address(addr.Bytes20())
+ // Get arguments from the memory.
+ args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
+
+ ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract, toAddr, args, gas)
+ if err != nil {
+ temp.Clear()
+ } else {
+ temp.SetOne()
+ }
+ stack.Push(&temp)
+ if err == nil || err == ErrExecutionReverted {
+ ret = common.CopyBytes(ret)
+ scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
+ }
+ scope.Contract.Gas += returnGas
+
+ interpreter.returnData = ret
+ return ret, nil
+}
+
+func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ // Pop gas. The actual gas is in interpreter.evm.callGasTemp.
+ stack := scope.Stack
+ // We use it as a temporary value
+ temp := stack.Pop()
+ gas := interpreter.evm.callGasTemp
+ // Pop other call parameters.
+ addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
+ toAddr := common.Address(addr.Bytes20())
+ // Get arguments from the memory.
+ args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
+
+ ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract, toAddr, args, gas)
+ if err != nil {
+ temp.Clear()
+ } else {
+ temp.SetOne()
+ }
+ stack.Push(&temp)
+ if err == nil || err == ErrExecutionReverted {
+ ret = common.CopyBytes(ret)
+ scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
+ }
+ scope.Contract.Gas += returnGas
+
+ interpreter.returnData = ret
+ return ret, nil
+}
+
+func opReturn(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ offset, size := scope.Stack.Pop(), scope.Stack.Pop()
+ ret := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64()))
+
+ return ret, errStopToken
+}
+
+func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ offset, size := scope.Stack.Pop(), scope.Stack.Pop()
+ ret := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64()))
+
+ interpreter.returnData = ret
+ return ret, ErrExecutionReverted
+}
+
+func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.Code[*pc])}
+}
+
+func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ return nil, errStopToken
+}
+
+func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ if interpreter.readOnly {
+ return nil, ErrWriteProtection
+ }
+ beneficiary := scope.Stack.Pop()
+ balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
+ interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
+ interpreter.evm.StateDB.Suicide(scope.Contract.Address())
+ if interpreter.cfg.Debug {
+ interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
+ interpreter.cfg.Tracer.CaptureExit([]byte{}, 0, nil)
+ }
+ return nil, errStopToken
+}
+
+// following functions are used by the instruction jump table
+
+// make log instruction function
+func makeLog(size int) executionFunc {
+ return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ if interpreter.readOnly {
+ return nil, ErrWriteProtection
+ }
+ topics := make([]common.Hash, size)
+ stack := scope.Stack
+ mStart, mSize := stack.Pop(), stack.Pop()
+ for i := 0; i < size; i++ {
+ addr := stack.Pop()
+ topics[i] = addr.Bytes32()
+ }
+
+ d := scope.Memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64()))
+ interpreter.evm.StateDB.AddLog(&types.Log{
+ Address: scope.Contract.Address(),
+ Topics: topics,
+ Data: d,
+ // This is a non-consensus field, but assigned here because
+ // core/state doesn't know the current block number.
+ BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(),
+ })
+
+ return nil, nil
+ }
+}
+
+// opPush1 is a specialized version of pushN
+func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ var (
+ codeLen = uint64(len(scope.Contract.Code))
+ integer = new(uint256.Int)
+ )
+ *pc += 1
+ if *pc < codeLen {
+ scope.Stack.Push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))
+ } else {
+ scope.Stack.Push(integer.Clear())
+ }
+ return nil, nil
+}
+
+// make push instruction function
+func makePush(size uint64, pushByteSize int) executionFunc {
+ return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ codeLen := len(scope.Contract.Code)
+
+ startMin := codeLen
+ if int(*pc+1) < startMin {
+ startMin = int(*pc + 1)
+ }
+
+ endMin := codeLen
+ if startMin+pushByteSize < endMin {
+ endMin = startMin + pushByteSize
+ }
+
+ integer := new(uint256.Int)
+ scope.Stack.Push(integer.SetBytes(common.RightPadBytes(
+ scope.Contract.Code[startMin:endMin], pushByteSize)))
+
+ *pc += size
+ return nil, nil
+ }
+}
+
+// make dup instruction function
+func makeDup(size int64) executionFunc {
+ return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Dup(int(size))
+ return nil, nil
+ }
+}
+
+// make swap instruction function
+func makeSwap(size int64) executionFunc {
+ // switch n + 1 otherwise n would be swapped with n
+ size++
+ return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Swap(int(size))
+ return nil, nil
+ }
+}
diff --git a/x/evm/core/vm/instructions_test.go b/x/evm/core/vm/instructions_test.go
new file mode 100644
index 00000000..30406b66
--- /dev/null
+++ b/x/evm/core/vm/instructions_test.go
@@ -0,0 +1,716 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
+)
+
+type TwoOperandTestcase struct {
+ X string
+ Y string
+ Expected string
+}
+
+type twoOperandParams struct {
+ x string
+ y string
+}
+
+var (
+ alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
+ commonParams []*twoOperandParams
+ twoOpMethods map[string]executionFunc
+)
+
+func init() {
+ // Params is a list of common edgecases that should be used for some common tests
+ params := []string{
+ "0000000000000000000000000000000000000000000000000000000000000000", // 0
+ "0000000000000000000000000000000000000000000000000000000000000001", // +1
+ "0000000000000000000000000000000000000000000000000000000000000005", // +5
+ "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", // + max -1
+ "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // + max
+ "8000000000000000000000000000000000000000000000000000000000000000", // - max
+ "8000000000000000000000000000000000000000000000000000000000000001", // - max+1
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", // - 5
+ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // - 1
+ }
+ // Params are combined so each param is used on each 'side'
+ commonParams = make([]*twoOperandParams, len(params)*len(params))
+ for i, x := range params {
+ for j, y := range params {
+ commonParams[i*len(params)+j] = &twoOperandParams{x, y}
+ }
+ }
+ twoOpMethods = map[string]executionFunc{
+ "add": opAdd,
+ "sub": opSub,
+ "mul": opMul,
+ "div": opDiv,
+ "sdiv": opSdiv,
+ "mod": opMod,
+ "smod": opSmod,
+ "exp": opExp,
+ "signext": opSignExtend,
+ "lt": opLt,
+ "gt": opGt,
+ "slt": opSlt,
+ "sgt": opSgt,
+ "eq": opEq,
+ "and": opAnd,
+ "or": opOr,
+ "xor": opXor,
+ "byte": opByte,
+ "shl": opSHL,
+ "shr": opSHR,
+ "sar": opSAR,
+ }
+}
+
+func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
+ var (
+ env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, err = NewStack()
+ pc = uint64(0)
+ interpreter = env.interpreter
+ )
+
+ require.NoError(t, err)
+
+ for i, test := range tests {
+ x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X))
+ y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y))
+ expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
+ stack.Push(x)
+ stack.Push(y)
+ opFn(&pc, interpreter.(*EVMInterpreter), &ScopeContext{nil, stack, nil})
+ if len(stack.Data) != 1 {
+ t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.Data))
+ }
+ actual := stack.Pop()
+
+ if actual.Cmp(expected) != 0 {
+ t.Errorf("Testcase %v %d, %v(%x, %x): expected %x, got %x", name, i, name, x, y, expected, actual)
+ }
+ }
+}
+
+func TestByteOp(t *testing.T) {
+ tests := []TwoOperandTestcase{
+ {"ABCDEF0908070605040302010000000000000000000000000000000000000000", "00", "AB"},
+ {"ABCDEF0908070605040302010000000000000000000000000000000000000000", "01", "CD"},
+ {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", "00", "00"},
+ {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", "01", "CD"},
+ {"0000000000000000000000000000000000000000000000000000000000102030", "1F", "30"},
+ {"0000000000000000000000000000000000000000000000000000000000102030", "1E", "20"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "20", "00"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "FFFFFFFFFFFFFFFF", "00"},
+ }
+ testTwoOperandOp(t, tests, opByte, "byte")
+}
+
+func TestSHL(t *testing.T) {
+ // Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left
+ tests := []TwoOperandTestcase{
+ {"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000002"},
+ {"0000000000000000000000000000000000000000000000000000000000000001", "ff", "8000000000000000000000000000000000000000000000000000000000000000"},
+ {"0000000000000000000000000000000000000000000000000000000000000001", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"0000000000000000000000000000000000000000000000000000000000000001", "0101", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "8000000000000000000000000000000000000000000000000000000000000000"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
+ }
+ testTwoOperandOp(t, tests, opSHL, "shl")
+}
+
+func TestSHR(t *testing.T) {
+ // Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shr-logical-shift-right
+ tests := []TwoOperandTestcase{
+ {"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "01", "4000000000000000000000000000000000000000000000000000000000000000"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "ff", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "0101", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
+ }
+ testTwoOperandOp(t, tests, opSHR, "shr")
+}
+
+func TestSAR(t *testing.T) {
+ // Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#sar-arithmetic-shift-right
+ tests := []TwoOperandTestcase{
+ {"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "01", "c000000000000000000000000000000000000000000000000000000000000000"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"8000000000000000000000000000000000000000000000000000000000000000", "0101", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
+ {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"4000000000000000000000000000000000000000000000000000000000000000", "fe", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "f8", "000000000000000000000000000000000000000000000000000000000000007f"},
+ {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "fe", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
+ }
+
+ testTwoOperandOp(t, tests, opSAR, "sar")
+}
+
+func TestAddMod(t *testing.T) {
+ var (
+ env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, err = NewStack()
+ evmInterpreter = NewEVMInterpreter(env, env.Config)
+ pc = uint64(0)
+ )
+
+ require.NoError(t, err)
+
+ tests := []struct {
+ x string
+ y string
+ z string
+ expected string
+ }{
+ {
+ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ },
+ }
+ // x + y = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
+ // in 256 bit repr, fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
+
+ for i, test := range tests {
+ x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.x))
+ y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y))
+ z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z))
+ expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected))
+ stack.Push(z)
+ stack.Push(y)
+ stack.Push(x)
+ opAddmod(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
+ actual := stack.Pop()
+ if actual.Cmp(expected) != 0 {
+ t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
+ }
+ }
+}
+
+// utility function to fill the json-file with testcases
+// Enable this test to generate the 'testcases_xx.json' files
+func TestWriteExpectedValues(t *testing.T) {
+ t.Skip("Enable this test to create json test cases.")
+
+ // getResult is a convenience function to generate the expected values
+ getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
+ var (
+ env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, err = NewStack()
+ pc = uint64(0)
+ interpreter = env.interpreter
+ )
+
+ require.NoError(t, err)
+
+ result := make([]TwoOperandTestcase, len(args))
+ for i, param := range args {
+ x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x))
+ y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
+ stack.Push(x)
+ stack.Push(y)
+ opFn(&pc, interpreter.(*EVMInterpreter), &ScopeContext{nil, stack, nil})
+ actual := stack.Pop()
+ result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
+ }
+ return result
+ }
+
+ for name, method := range twoOpMethods {
+ data, err := json.Marshal(getResult(commonParams, method))
+ if err != nil {
+ t.Fatal(err)
+ }
+ _ = os.WriteFile(fmt.Sprintf("testdata/testcases_%v.json", name), data, 0o644)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+// TestJsonTestcases runs through all the testcases defined as json-files
+func TestJsonTestcases(t *testing.T) {
+ for name := range twoOpMethods {
+ data, err := os.ReadFile(fmt.Sprintf("testdata/testcases_%v.json", name))
+ if err != nil {
+ t.Fatal("Failed to read file", err)
+ }
+ var testcases []TwoOperandTestcase
+ json.Unmarshal(data, &testcases)
+ testTwoOperandOp(t, testcases, twoOpMethods[name], name)
+ }
+}
+
+func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
+ var (
+ env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, _ = NewStack()
+ scope = &ScopeContext{nil, stack, nil}
+ evmInterpreter = NewEVMInterpreter(env, env.Config)
+ )
+ env.interpreter = evmInterpreter
+ // convert args
+ intArgs := make([]*uint256.Int, len(args))
+ for i, arg := range args {
+ intArgs[i] = new(uint256.Int).SetBytes(common.Hex2Bytes(arg))
+ }
+ pc := uint64(0)
+ bench.ResetTimer()
+ for i := 0; i < bench.N; i++ {
+ for _, arg := range intArgs {
+ stack.Push(arg)
+ }
+ op(&pc, evmInterpreter, scope)
+ stack.Pop()
+ }
+ bench.StopTimer()
+
+ for i, arg := range args {
+ want := new(uint256.Int).SetBytes(common.Hex2Bytes(arg))
+ if have := intArgs[i]; !want.Eq(have) {
+ bench.Fatalf("input #%d mutated, have %x want %x", i, have, want)
+ }
+ }
+}
+
+func BenchmarkOpAdd64(b *testing.B) {
+ x := "ffffffff"
+ y := "fd37f3e2bba2c4f"
+
+ opBenchmark(b, opAdd, x, y)
+}
+
+func BenchmarkOpAdd128(b *testing.B) {
+ x := "ffffffffffffffff"
+ y := "f5470b43c6549b016288e9a65629687"
+
+ opBenchmark(b, opAdd, x, y)
+}
+
+func BenchmarkOpAdd256(b *testing.B) {
+ x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9"
+ y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57"
+
+ opBenchmark(b, opAdd, x, y)
+}
+
+func BenchmarkOpSub64(b *testing.B) {
+ x := "51022b6317003a9d"
+ y := "a20456c62e00753a"
+
+ opBenchmark(b, opSub, x, y)
+}
+
+func BenchmarkOpSub128(b *testing.B) {
+ x := "4dde30faaacdc14d00327aac314e915d"
+ y := "9bbc61f5559b829a0064f558629d22ba"
+
+ opBenchmark(b, opSub, x, y)
+}
+
+func BenchmarkOpSub256(b *testing.B) {
+ x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37"
+ y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e"
+
+ opBenchmark(b, opSub, x, y)
+}
+
+func BenchmarkOpMul(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opMul, x, y)
+}
+
+func BenchmarkOpDiv256(b *testing.B) {
+ x := "ff3f9014f20db29ae04af2c2d265de17"
+ y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
+ opBenchmark(b, opDiv, x, y)
+}
+
+func BenchmarkOpDiv128(b *testing.B) {
+ x := "fdedc7f10142ff97"
+ y := "fbdfda0e2ce356173d1993d5f70a2b11"
+ opBenchmark(b, opDiv, x, y)
+}
+
+func BenchmarkOpDiv64(b *testing.B) {
+ x := "fcb34eb3"
+ y := "f97180878e839129"
+ opBenchmark(b, opDiv, x, y)
+}
+
+func BenchmarkOpSdiv(b *testing.B) {
+ x := "ff3f9014f20db29ae04af2c2d265de17"
+ y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
+
+ opBenchmark(b, opSdiv, x, y)
+}
+
+func BenchmarkOpMod(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opMod, x, y)
+}
+
+func BenchmarkOpSmod(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opSmod, x, y)
+}
+
+func BenchmarkOpExp(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opExp, x, y)
+}
+
+func BenchmarkOpSignExtend(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opSignExtend, x, y)
+}
+
+func BenchmarkOpLt(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opLt, x, y)
+}
+
+func BenchmarkOpGt(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opGt, x, y)
+}
+
+func BenchmarkOpSlt(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opSlt, x, y)
+}
+
+func BenchmarkOpSgt(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opSgt, x, y)
+}
+
+func BenchmarkOpEq(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opEq, x, y)
+}
+
+func BenchmarkOpEq2(b *testing.B) {
+ x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
+ y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
+ opBenchmark(b, opEq, x, y)
+}
+
+func BenchmarkOpAnd(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opAnd, x, y)
+}
+
+func BenchmarkOpOr(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opOr, x, y)
+}
+
+func BenchmarkOpXor(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opXor, x, y)
+}
+
+func BenchmarkOpByte(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+
+ opBenchmark(b, opByte, x, y)
+}
+
+func BenchmarkOpAddmod(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+ z := alphabetSoup
+
+ opBenchmark(b, opAddmod, x, y, z)
+}
+
+func BenchmarkOpMulmod(b *testing.B) {
+ x := alphabetSoup
+ y := alphabetSoup
+ z := alphabetSoup
+
+ opBenchmark(b, opMulmod, x, y, z)
+}
+
+func BenchmarkOpSHL(b *testing.B) {
+ x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
+ y := "ff"
+
+ opBenchmark(b, opSHL, x, y)
+}
+
+func BenchmarkOpSHR(b *testing.B) {
+ x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
+ y := "ff"
+
+ opBenchmark(b, opSHR, x, y)
+}
+
+func BenchmarkOpSAR(b *testing.B) {
+ x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
+ y := "ff"
+
+ opBenchmark(b, opSAR, x, y)
+}
+
+func BenchmarkOpIsZero(b *testing.B) {
+ x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
+ opBenchmark(b, opIszero, x)
+}
+
+func TestOpMstore(t *testing.T) {
+ var (
+ env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, err = NewStack()
+ mem = NewMemory()
+ evmInterpreter = NewEVMInterpreter(env, env.Config)
+ )
+
+ require.NoError(t, err)
+
+ env.interpreter = evmInterpreter
+ mem.Resize(64)
+ pc := uint64(0)
+ v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
+ stack.Push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
+ stack.Push(new(uint256.Int))
+ opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
+ if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
+ t.Fatalf("Mstore fail, got %v, expected %v", got, v)
+ }
+ stack.Push(new(uint256.Int).SetUint64(0x1))
+ stack.Push(new(uint256.Int))
+ opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
+ if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
+ t.Fatalf("Mstore failed to overwrite previous value")
+ }
+}
+
+func BenchmarkOpMstore(bench *testing.B) {
+ var (
+ env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, _ = NewStack()
+ mem = NewMemory()
+ evmInterpreter = NewEVMInterpreter(env, env.Config)
+ )
+
+ env.interpreter = evmInterpreter
+ mem.Resize(64)
+ pc := uint64(0)
+ memStart := new(uint256.Int)
+ value := new(uint256.Int).SetUint64(0x1337)
+
+ bench.ResetTimer()
+ for i := 0; i < bench.N; i++ {
+ stack.Push(value)
+ stack.Push(memStart)
+ opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
+ }
+}
+
+func BenchmarkOpKeccak256(bench *testing.B) {
+ var (
+ env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, _ = NewStack()
+ mem = NewMemory()
+ evmInterpreter = NewEVMInterpreter(env, env.Config)
+ )
+ env.interpreter = evmInterpreter
+ mem.Resize(32)
+ pc := uint64(0)
+ start := new(uint256.Int)
+
+ bench.ResetTimer()
+ for i := 0; i < bench.N; i++ {
+ stack.Push(uint256.NewInt(32))
+ stack.Push(start)
+ opKeccak256(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
+ }
+}
+
+func TestCreate2Addreses(t *testing.T) {
+ type testcase struct {
+ origin string
+ salt string
+ code string
+ expected string
+ }
+
+ for i, tt := range []testcase{
+ {
+ origin: "0x0000000000000000000000000000000000000000",
+ salt: "0x0000000000000000000000000000000000000000",
+ code: "0x00",
+ expected: "0x4d1a2e2bb4f88f0250f26ffff098b0b30b26bf38",
+ },
+ {
+ origin: "0xdeadbeef00000000000000000000000000000000",
+ salt: "0x0000000000000000000000000000000000000000",
+ code: "0x00",
+ expected: "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3",
+ },
+ {
+ origin: "0xdeadbeef00000000000000000000000000000000",
+ salt: "0xfeed000000000000000000000000000000000000",
+ code: "0x00",
+ expected: "0xD04116cDd17beBE565EB2422F2497E06cC1C9833",
+ },
+ {
+ origin: "0x0000000000000000000000000000000000000000",
+ salt: "0x0000000000000000000000000000000000000000",
+ code: "0xdeadbeef",
+ expected: "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e",
+ },
+ {
+ origin: "0x00000000000000000000000000000000deadbeef",
+ salt: "0xcafebabe",
+ code: "0xdeadbeef",
+ expected: "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7",
+ },
+ {
+ origin: "0x00000000000000000000000000000000deadbeef",
+ salt: "0xcafebabe",
+ code: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
+ expected: "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C",
+ },
+ {
+ origin: "0x0000000000000000000000000000000000000000",
+ salt: "0x0000000000000000000000000000000000000000",
+ code: "0x",
+ expected: "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0",
+ },
+ } {
+ origin := common.BytesToAddress(common.FromHex(tt.origin))
+ salt := common.BytesToHash(common.FromHex(tt.salt))
+ code := common.FromHex(tt.code)
+ codeHash := crypto.Keccak256(code)
+ address := crypto.CreateAddress2(origin, salt, codeHash)
+ /*
+ stack := newstack()
+ // salt, but we don't need that for this test
+ stack.push(big.NewInt(int64(len(code)))) //size
+ stack.push(big.NewInt(0)) // memstart
+ stack.push(big.NewInt(0)) // value
+ gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0)
+ fmt.Printf("Example %d\n* address `0x%x`\n* salt `0x%x`\n* init_code `0x%x`\n* gas (assuming no mem expansion): `%v`\n* result: `%s`\n\n", i,origin, salt, code, gas, address.String())
+ */
+ expected := common.BytesToAddress(common.FromHex(tt.expected))
+ if !bytes.Equal(expected.Bytes(), address.Bytes()) {
+ t.Errorf("test %d: expected %s, got %s", i, expected.String(), address.String())
+ }
+ }
+}
+
+func TestRandom(t *testing.T) {
+ type testcase struct {
+ name string
+ random common.Hash
+ }
+
+ for _, tt := range []testcase{
+ {name: "empty hash", random: common.Hash{}},
+ {name: "1", random: common.Hash{0}},
+ {name: "emptyCodeHash", random: emptyCodeHash},
+ {name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
+ } {
+ var (
+ env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{})
+ stack, err = NewStack()
+ pc = uint64(0)
+ interpreter = env.interpreter
+ )
+
+ require.NoError(t, err)
+
+ opRandom(&pc, interpreter.(*EVMInterpreter), &ScopeContext{nil, stack, nil})
+ if len(stack.Data) != 1 {
+ t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.Data))
+ }
+ actual := stack.Pop()
+ expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.random.Bytes()))
+ if overflow {
+ t.Errorf("Testcase %v: invalid overflow", tt.name)
+ }
+ if actual.Cmp(expected) != 0 {
+ t.Errorf("Testcase %v: expected %x, got %x", tt.name, expected, actual)
+ }
+ }
+}
diff --git a/x/evm/core/vm/interface.go b/x/evm/core/vm/interface.go
new file mode 100644
index 00000000..6a407a08
--- /dev/null
+++ b/x/evm/core/vm/interface.go
@@ -0,0 +1,100 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+)
+
+// StateDB is an EVM database for full state querying.
+type StateDB interface {
+ CreateAccount(common.Address)
+
+ SubBalance(common.Address, *big.Int)
+ AddBalance(common.Address, *big.Int)
+ GetBalance(common.Address) *big.Int
+
+ GetNonce(common.Address) uint64
+ SetNonce(common.Address, uint64)
+
+ GetCodeHash(common.Address) common.Hash
+ GetCode(common.Address) []byte
+ SetCode(common.Address, []byte)
+ GetCodeSize(common.Address) int
+
+ AddRefund(uint64)
+ SubRefund(uint64)
+ GetRefund() uint64
+
+ GetCommittedState(common.Address, common.Hash) common.Hash
+ GetState(common.Address, common.Hash) common.Hash
+ SetState(common.Address, common.Hash, common.Hash)
+
+ Suicide(common.Address) bool
+ HasSuicided(common.Address) bool
+
+ // Exist reports whether the given account exists in state.
+ // Notably this should also return true for suicided accounts.
+ Exist(common.Address) bool
+ // Empty returns whether the given account is empty. Empty
+ // is defined according to EIP161 (balance = nonce = code = 0).
+ Empty(common.Address) bool
+
+ PrepareAccessList(sender common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList)
+ AddressInAccessList(addr common.Address) bool
+ SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool)
+ // AddAddressToAccessList adds the given address to the access list. This operation is safe to perform
+ // even if the feature/fork is not active yet
+ AddAddressToAccessList(addr common.Address)
+ // AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform
+ // even if the feature/fork is not active yet
+ AddSlotToAccessList(addr common.Address, slot common.Hash)
+
+ RevertToSnapshot(int)
+ Snapshot() int
+
+ AddLog(*types.Log)
+ AddPreimage(common.Hash, []byte)
+
+ ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error
+}
+
+// CallContext provides a basic interface for the EVM calling conventions. The EVM
+// depends on this context being implemented for doing subcalls and initialising new EVM contracts.
+type CallContext interface {
+ // Call another contract
+ Call(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
+ // Take another's contract code and execute within our own context
+ CallCode(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
+ // Same as CallCode except sender and value is propagated from parent to child scope
+ DelegateCall(env *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
+ // Create a new contract
+ Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
+}
+
+// Interpreter is used to run Ethereum based contracts and will utilize the
+// passed environment to query external sources for state information.
+// The Interpreter will run the byte code VM based on the passed
+// configuration.
+type Interpreter interface {
+ // Run loops and evaluates the contract's code with the given input data and returns
+ // the return byte-slice and an error if one occurred.
+ Run(contract *Contract, input []byte, static bool) ([]byte, error)
+}
diff --git a/x/evm/core/vm/interpreter.go b/x/evm/core/vm/interpreter.go
new file mode 100644
index 00000000..f4055e42
--- /dev/null
+++ b/x/evm/core/vm/interpreter.go
@@ -0,0 +1,234 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "hash"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// Config are the configuration options for the Interpreter
+type Config struct {
+ Debug bool // Enables debugging
+ Tracer EVMLogger // Opcode logger
+ NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
+ EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
+
+ JumpTable *JumpTable // EVM instruction table, automatically populated if unset
+
+ ExtraEips []string // Additional EIPS that are to be enabled
+}
+
+// ScopeContext contains the things that are per-call, such as stack and memory,
+// but not transients like pc and gas
+type ScopeContext struct {
+ Memory *Memory
+ Stack *Stack
+ Contract *Contract
+}
+
+// keccakState wraps sha3.state. In addition to the usual hash methods, it also supports
+// Read to get a variable amount of data from the hash state. Read is faster than Sum
+// because it doesn't copy the internal state, but also modifies the internal state.
+type keccakState interface {
+ hash.Hash
+ Read([]byte) (int, error)
+}
+
+var _ Interpreter = &EVMInterpreter{}
+
+// EVMInterpreter represents an EVM interpreter
+type EVMInterpreter struct {
+ evm *EVM
+ cfg Config
+
+ hasher keccakState // Keccak256 hasher instance shared across opcodes
+ hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes
+
+ readOnly bool // Whether to throw on stateful modifications
+ returnData []byte // Last CALL's return data for subsequent reuse
+}
+
+// NewEVMInterpreter returns a new instance of the Interpreter.
+func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
+ // If jump table was not initialised we set the default one.
+ if cfg.JumpTable == nil {
+ cfg.JumpTable = DefaultJumpTable(evm.chainRules)
+ for i, eip := range cfg.ExtraEips {
+ // Deep-copy jumptable to prevent modification of opcodes in other tables
+ copy := CopyJumpTable(cfg.JumpTable)
+ if err := EnableEIP(eip, copy); err != nil {
+ // Disable it, so caller can check if it's activated or not
+ cfg.ExtraEips = append(cfg.ExtraEips[:i], cfg.ExtraEips[i+1:]...)
+ log.Error("EIP activation failed", "eip", eip, "error", err)
+ }
+ cfg.JumpTable = copy
+ }
+ }
+
+ return &EVMInterpreter{
+ evm: evm,
+ cfg: cfg,
+ }
+}
+
+// Run loops and evaluates the contract's code with the given input data and returns
+// the return byte-slice and an error if one occurred.
+//
+// It's important to note that any errors returned by the interpreter should be
+// considered a revert-and-consume-all-gas operation except for
+// ErrExecutionReverted which means revert-and-keep-gas-left.
+func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
+ // Increment the call depth which is restricted to 1024
+ in.evm.depth++
+ defer func() { in.evm.depth-- }()
+
+ // Make sure the readOnly is only set if we aren't in readOnly yet.
+ // This also makes sure that the readOnly flag isn't removed for child calls.
+ if readOnly && !in.readOnly {
+ in.readOnly = true
+ defer func() { in.readOnly = false }()
+ }
+
+ // Reset the previous call's return data. It's unimportant to preserve the old buffer
+ // as every returning call will return new data anyway.
+ in.returnData = nil
+
+ // Don't bother with the execution if there's no code.
+ if len(contract.Code) == 0 {
+ return nil, nil
+ }
+
+ mem := NewMemory() // bound memory
+ stack, err := NewStack() // local stack
+ if err != nil {
+ return nil, err
+ }
+ callContext := &ScopeContext{
+ Memory: mem,
+ Stack: stack,
+ Contract: contract,
+ }
+
+ var (
+ op OpCode // current opcode
+ // For optimisation reason we're using uint64 as the program counter.
+ // It's theoretically possible to go above 2^64. The YP defines the PC
+ // to be uint256. Practically much less so feasible.
+ pc uint64 // program counter
+ cost uint64
+ // copies used by tracer
+ pcCopy uint64 // needed for the deferred EVMLogger
+ gasCopy uint64 // for EVMLogger to log gas remaining before execution
+ logged bool // deferred EVMLogger should ignore already logged steps
+ res []byte // result of the opcode execution function
+ )
+ // Don't move this deferred function, it's placed before the capturestate-deferred method,
+ // so that it get's executed _after_: the capturestate needs the stacks before
+ // they are returned to the pools
+ defer ReturnNormalStack(stack)
+ contract.Input = input
+
+ if in.cfg.Debug {
+ defer func() {
+ if err != nil {
+ if !logged {
+ in.cfg.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
+ } else {
+ in.cfg.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err)
+ }
+ }
+ }()
+ }
+ // The Interpreter main run loop (contextual). This loop runs until either an
+ // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during
+ // the execution of one of the operations or until the done flag is set by the
+ // parent context.
+ for {
+ if in.cfg.Debug {
+ // Capture pre-execution values for tracing.
+ logged, pcCopy, gasCopy = false, pc, contract.Gas
+ }
+ // Get the operation from the jump table and validate the stack to ensure there are
+ // enough stack items available to perform the operation.
+ op = contract.GetOp(pc)
+ operation := in.cfg.JumpTable[op]
+ cost = operation.constantGas // For tracing
+ // Validate stack
+ if sLen := stack.Len(); sLen < operation.minStack {
+ return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack}
+ } else if sLen > operation.maxStack {
+ return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack}
+ }
+ if !contract.UseGas(cost) {
+ return nil, ErrOutOfGas
+ }
+ if operation.dynamicGas != nil {
+ // All ops with a dynamic memory usage also has a dynamic gas cost.
+ var memorySize uint64
+ // calculate the new memory size and expand the memory to fit
+ // the operation
+ // Memory check needs to be done prior to evaluating the dynamic gas portion,
+ // to detect calculation overflows
+ if operation.memorySize != nil {
+ memSize, overflow := operation.memorySize(stack)
+ if overflow {
+ return nil, ErrGasUintOverflow
+ }
+ // memory is expanded in words of 32 bytes. Gas
+ // is also calculated in words.
+ if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
+ return nil, ErrGasUintOverflow
+ }
+ }
+ // Consume the gas and return an error if not enough gas is available.
+ // cost is explicitly set so that the capture state defer method can get the proper cost
+ var dynamicCost uint64
+ dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize)
+ cost += dynamicCost // for tracing
+ if err != nil || !contract.UseGas(dynamicCost) {
+ return nil, ErrOutOfGas
+ }
+ // Do tracing before memory expansion
+ if in.cfg.Debug {
+ in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
+ logged = true
+ }
+ if memorySize > 0 {
+ mem.Resize(memorySize)
+ }
+ } else if in.cfg.Debug {
+ in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
+ logged = true
+ }
+ // execute the operation
+ res, err = operation.execute(&pc, in, callContext)
+ if err != nil {
+ break
+ }
+ pc++
+ }
+
+ if err == errStopToken {
+ err = nil // clear stop token error
+ }
+
+ return res, err
+}
diff --git a/x/evm/core/vm/interpreter_test.go b/x/evm/core/vm/interpreter_test.go
new file mode 100644
index 00000000..31ee9922
--- /dev/null
+++ b/x/evm/core/vm/interpreter_test.go
@@ -0,0 +1,76 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "math/big"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var loopInterruptTests = []string{
+ // infinite loop using JUMP: push(2) jumpdest dup1 jump
+ "60025b8056",
+ // infinite loop using JUMPI: push(1) push(4) jumpdest dup2 dup2 jumpi
+ "600160045b818157",
+}
+
+func TestLoopInterrupt(t *testing.T) {
+ address := common.BytesToAddress([]byte("contract"))
+ vmctx := BlockContext{
+ Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ }
+
+ for i, tt := range loopInterruptTests {
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
+ statedb.CreateAccount(address)
+ statedb.SetCode(address, common.Hex2Bytes(tt))
+ statedb.Finalise(true)
+
+ evm := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{})
+
+ errChannel := make(chan error)
+ timeout := make(chan bool)
+
+ go func(evm *EVM) {
+ _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(big.Int))
+ errChannel <- err
+ }(evm)
+
+ go func() {
+ <-time.After(time.Second)
+ timeout <- true
+ }()
+
+ evm.Cancel()
+
+ select {
+ case <-timeout:
+ t.Errorf("test %d timed out", i)
+ case err := <-errChannel:
+ if err != nil {
+ t.Errorf("test %d failure: %v", i, err)
+ }
+ }
+ }
+}
diff --git a/x/evm/core/vm/jump_table.go b/x/evm/core/vm/jump_table.go
new file mode 100644
index 00000000..ffe33bb0
--- /dev/null
+++ b/x/evm/core/vm/jump_table.go
@@ -0,0 +1,1106 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/params"
+)
+
+type (
+ executionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error)
+ gasFunc func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error)
+ // memorySizeFunc returns the required size, and whether the operation overflowed a uint64
+ memorySizeFunc func(*Stack) (size uint64, overflow bool)
+)
+
+type operation struct {
+ // execute is the operation function
+ execute executionFunc
+ constantGas uint64
+ dynamicGas gasFunc
+ // minStack tells how many stack items are required
+ minStack int
+ // maxStack specifies the max length the stack can have for this operation
+ // to not overflow the stack.
+ maxStack int
+
+ // memorySize returns the memory size required for the operation
+ memorySize memorySizeFunc
+}
+
+var (
+ FrontierInstructionSet = newFrontierInstructionSet()
+ HomesteadInstructionSet = newHomesteadInstructionSet()
+ TangerineWhistleInstructionSet = newTangerineWhistleInstructionSet()
+ SpuriousDragonInstructionSet = newSpuriousDragonInstructionSet()
+ ByzantiumInstructionSet = newByzantiumInstructionSet()
+ ConstantinopleInstructionSet = newConstantinopleInstructionSet()
+ IstanbulInstructionSet = newIstanbulInstructionSet()
+ BerlinInstructionSet = newBerlinInstructionSet()
+ LondonInstructionSet = newLondonInstructionSet()
+ MergeInstructionSet = newMergeInstructionSet()
+)
+
+// JumpTable contains the EVM opcodes supported at a given fork.
+type JumpTable [256]*operation
+
+// DefaultJumpTable defines the default jump table used by the EVM interpreter.
+func DefaultJumpTable(rules params.Rules) (jumpTable *JumpTable) {
+ switch {
+ case rules.IsMerge:
+ jumpTable = &MergeInstructionSet
+ case rules.IsLondon:
+ jumpTable = &LondonInstructionSet
+ case rules.IsBerlin:
+ jumpTable = &BerlinInstructionSet
+ case rules.IsIstanbul:
+ jumpTable = &IstanbulInstructionSet
+ case rules.IsConstantinople:
+ jumpTable = &ConstantinopleInstructionSet
+ case rules.IsByzantium:
+ jumpTable = &ByzantiumInstructionSet
+ case rules.IsEIP158:
+ jumpTable = &SpuriousDragonInstructionSet
+ case rules.IsEIP150:
+ jumpTable = &TangerineWhistleInstructionSet
+ case rules.IsHomestead:
+ jumpTable = &HomesteadInstructionSet
+ default:
+ jumpTable = &FrontierInstructionSet
+ }
+
+ return jumpTable
+}
+
+// Validate checks if all the operations are set and if they are valid according to the
+// interpreter assumptions.
+func (jt JumpTable) Validate() error {
+ for i, op := range jt {
+ if op == nil {
+ return fmt.Errorf("op %#x is not set", i)
+ }
+
+ // The interpreter has an assumption that if the memorySize function is
+ // set, then the dynamicGas function is also set. This is a somewhat
+ // arbitrary assumption, and can be removed if we need to -- but it
+ // allows us to avoid a condition check. As long as we have that assumption
+ // in there, this little sanity check prevents us from merging in a
+ // change which violates it.
+ if op.memorySize != nil && op.dynamicGas == nil {
+ return fmt.Errorf("op %v has dynamic memory but not dynamic gas", OpCode(i).String())
+ }
+ }
+
+ return nil
+}
+
+// MustValidate panics if the operations are not valid.
+func (jt JumpTable) MustValidate() {
+ if err := jt.Validate(); err != nil {
+ panic(err)
+ }
+}
+
+func newMergeInstructionSet() JumpTable {
+ instructionSet := newLondonInstructionSet()
+ instructionSet[RANDOM] = &operation{
+ execute: opRandom,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ }
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// newLondonInstructionSet returns the frontier, homestead, byzantium,
+// contantinople, istanbul, petersburg, berlin and london instructions.
+func newLondonInstructionSet() JumpTable {
+ instructionSet := newBerlinInstructionSet()
+ enable3529(&instructionSet) // EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529
+ enable3198(&instructionSet) // Base fee opcode https://eips.ethereum.org/EIPS/eip-3198
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// newBerlinInstructionSet returns the frontier, homestead, byzantium,
+// contantinople, istanbul, petersburg and berlin instructions.
+func newBerlinInstructionSet() JumpTable {
+ instructionSet := newIstanbulInstructionSet()
+ enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// newIstanbulInstructionSet returns the frontier, homestead, byzantium,
+// contantinople, istanbul and petersburg instructions.
+func newIstanbulInstructionSet() JumpTable {
+ instructionSet := newConstantinopleInstructionSet()
+
+ enable1344(&instructionSet) // ChainID opcode - https://eips.ethereum.org/EIPS/eip-1344
+ enable1884(&instructionSet) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884
+ enable2200(&instructionSet) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200
+
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// newConstantinopleInstructionSet returns the frontier, homestead,
+// byzantium and contantinople instructions.
+func newConstantinopleInstructionSet() JumpTable {
+ instructionSet := newByzantiumInstructionSet()
+ instructionSet[SHL] = &operation{
+ execute: opSHL,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ }
+ instructionSet[SHR] = &operation{
+ execute: opSHR,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ }
+ instructionSet[SAR] = &operation{
+ execute: opSAR,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ }
+ instructionSet[EXTCODEHASH] = &operation{
+ execute: opExtCodeHash,
+ constantGas: params.ExtcodeHashGasConstantinople,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ }
+ instructionSet[CREATE2] = &operation{
+ execute: opCreate2,
+ constantGas: params.Create2Gas,
+ dynamicGas: gasCreate2,
+ minStack: minStack(4, 1),
+ maxStack: maxStack(4, 1),
+ memorySize: memoryCreate2,
+ }
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// newByzantiumInstructionSet returns the frontier, homestead and
+// byzantium instructions.
+func newByzantiumInstructionSet() JumpTable {
+ instructionSet := newSpuriousDragonInstructionSet()
+ instructionSet[STATICCALL] = &operation{
+ execute: opStaticCall,
+ constantGas: params.CallGasEIP150,
+ dynamicGas: gasStaticCall,
+ minStack: minStack(6, 1),
+ maxStack: maxStack(6, 1),
+ memorySize: memoryStaticCall,
+ }
+ instructionSet[RETURNDATASIZE] = &operation{
+ execute: opReturnDataSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ }
+ instructionSet[RETURNDATACOPY] = &operation{
+ execute: opReturnDataCopy,
+ constantGas: GasFastestStep,
+ dynamicGas: gasReturnDataCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryReturnDataCopy,
+ }
+ instructionSet[REVERT] = &operation{
+ execute: opRevert,
+ dynamicGas: gasRevert,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryRevert,
+ }
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// EIP 158 a.k.a Spurious Dragon
+func newSpuriousDragonInstructionSet() JumpTable {
+ instructionSet := newTangerineWhistleInstructionSet()
+ instructionSet[EXP].dynamicGas = gasExpEIP158
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// EIP 150 a.k.a Tangerine Whistle
+func newTangerineWhistleInstructionSet() JumpTable {
+ instructionSet := newHomesteadInstructionSet()
+ instructionSet[BALANCE].constantGas = params.BalanceGasEIP150
+ instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEIP150
+ instructionSet[SLOAD].constantGas = params.SloadGasEIP150
+ instructionSet[EXTCODECOPY].constantGas = params.ExtcodeCopyBaseEIP150
+ instructionSet[CALL].constantGas = params.CallGasEIP150
+ instructionSet[CALLCODE].constantGas = params.CallGasEIP150
+ instructionSet[DELEGATECALL].constantGas = params.CallGasEIP150
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// newHomesteadInstructionSet returns the frontier and homestead
+// instructions that can be executed during the homestead phase.
+func newHomesteadInstructionSet() JumpTable {
+ instructionSet := newFrontierInstructionSet()
+ instructionSet[DELEGATECALL] = &operation{
+ execute: opDelegateCall,
+ dynamicGas: gasDelegateCall,
+ constantGas: params.CallGasFrontier,
+ minStack: minStack(6, 1),
+ maxStack: maxStack(6, 1),
+ memorySize: memoryDelegateCall,
+ }
+ instructionSet.MustValidate()
+ return instructionSet
+}
+
+// newFrontierInstructionSet returns the frontier instructions
+// that can be executed during the frontier phase.
+func newFrontierInstructionSet() JumpTable {
+ tbl := JumpTable{
+ STOP: {
+ execute: opStop,
+ constantGas: 0,
+ minStack: minStack(0, 0),
+ maxStack: maxStack(0, 0),
+ },
+ ADD: {
+ execute: opAdd,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ MUL: {
+ execute: opMul,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ SUB: {
+ execute: opSub,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ DIV: {
+ execute: opDiv,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ SDIV: {
+ execute: opSdiv,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ MOD: {
+ execute: opMod,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ SMOD: {
+ execute: opSmod,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ ADDMOD: {
+ execute: opAddmod,
+ constantGas: GasMidStep,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ },
+ MULMOD: {
+ execute: opMulmod,
+ constantGas: GasMidStep,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ },
+ EXP: {
+ execute: opExp,
+ dynamicGas: gasExpFrontier,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ SIGNEXTEND: {
+ execute: opSignExtend,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ LT: {
+ execute: opLt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ GT: {
+ execute: opGt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ SLT: {
+ execute: opSlt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ SGT: {
+ execute: opSgt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ EQ: {
+ execute: opEq,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ ISZERO: {
+ execute: opIszero,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ },
+ AND: {
+ execute: opAnd,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ XOR: {
+ execute: opXor,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ OR: {
+ execute: opOr,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ NOT: {
+ execute: opNot,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ },
+ BYTE: {
+ execute: opByte,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ },
+ KECCAK256: {
+ execute: opKeccak256,
+ constantGas: params.Keccak256Gas,
+ dynamicGas: gasKeccak256,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ memorySize: memoryKeccak256,
+ },
+ ADDRESS: {
+ execute: opAddress,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ BALANCE: {
+ execute: opBalance,
+ constantGas: params.BalanceGasFrontier,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ },
+ ORIGIN: {
+ execute: opOrigin,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ CALLER: {
+ execute: opCaller,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ CALLVALUE: {
+ execute: opCallValue,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ CALLDATALOAD: {
+ execute: opCallDataLoad,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ },
+ CALLDATASIZE: {
+ execute: opCallDataSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ CALLDATACOPY: {
+ execute: opCallDataCopy,
+ constantGas: GasFastestStep,
+ dynamicGas: gasCallDataCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryCallDataCopy,
+ },
+ CODESIZE: {
+ execute: opCodeSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ CODECOPY: {
+ execute: opCodeCopy,
+ constantGas: GasFastestStep,
+ dynamicGas: gasCodeCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryCodeCopy,
+ },
+ GASPRICE: {
+ execute: opGasprice,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ EXTCODESIZE: {
+ execute: opExtCodeSize,
+ constantGas: params.ExtcodeSizeGasFrontier,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ },
+ EXTCODECOPY: {
+ execute: opExtCodeCopy,
+ constantGas: params.ExtcodeCopyBaseFrontier,
+ dynamicGas: gasExtCodeCopy,
+ minStack: minStack(4, 0),
+ maxStack: maxStack(4, 0),
+ memorySize: memoryExtCodeCopy,
+ },
+ BLOCKHASH: {
+ execute: opBlockhash,
+ constantGas: GasExtStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ },
+ COINBASE: {
+ execute: opCoinbase,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ TIMESTAMP: {
+ execute: opTimestamp,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ NUMBER: {
+ execute: opNumber,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ DIFFICULTY: {
+ execute: opDifficulty,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ GASLIMIT: {
+ execute: opGasLimit,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ POP: {
+ execute: opPop,
+ constantGas: GasQuickStep,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ },
+ MLOAD: {
+ execute: opMload,
+ constantGas: GasFastestStep,
+ dynamicGas: gasMLoad,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ memorySize: memoryMLoad,
+ },
+ MSTORE: {
+ execute: opMstore,
+ constantGas: GasFastestStep,
+ dynamicGas: gasMStore,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryMStore,
+ },
+ MSTORE8: {
+ execute: opMstore8,
+ constantGas: GasFastestStep,
+ dynamicGas: gasMStore8,
+ memorySize: memoryMStore8,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ },
+ SLOAD: {
+ execute: opSload,
+ constantGas: params.SloadGasFrontier,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ },
+ SSTORE: {
+ execute: opSstore,
+ dynamicGas: gasSStore,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ },
+ JUMP: {
+ execute: opJump,
+ constantGas: GasMidStep,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ },
+ JUMPI: {
+ execute: opJumpi,
+ constantGas: GasSlowStep,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ },
+ PC: {
+ execute: opPc,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ MSIZE: {
+ execute: opMsize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ GAS: {
+ execute: opGas,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ JUMPDEST: {
+ execute: opJumpdest,
+ constantGas: params.JumpdestGas,
+ minStack: minStack(0, 0),
+ maxStack: maxStack(0, 0),
+ },
+ PUSH1: {
+ execute: opPush1,
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH2: {
+ execute: makePush(2, 2),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH3: {
+ execute: makePush(3, 3),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH4: {
+ execute: makePush(4, 4),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH5: {
+ execute: makePush(5, 5),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH6: {
+ execute: makePush(6, 6),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH7: {
+ execute: makePush(7, 7),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH8: {
+ execute: makePush(8, 8),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH9: {
+ execute: makePush(9, 9),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH10: {
+ execute: makePush(10, 10),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH11: {
+ execute: makePush(11, 11),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH12: {
+ execute: makePush(12, 12),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH13: {
+ execute: makePush(13, 13),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH14: {
+ execute: makePush(14, 14),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH15: {
+ execute: makePush(15, 15),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH16: {
+ execute: makePush(16, 16),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH17: {
+ execute: makePush(17, 17),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH18: {
+ execute: makePush(18, 18),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH19: {
+ execute: makePush(19, 19),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH20: {
+ execute: makePush(20, 20),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH21: {
+ execute: makePush(21, 21),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH22: {
+ execute: makePush(22, 22),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH23: {
+ execute: makePush(23, 23),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH24: {
+ execute: makePush(24, 24),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH25: {
+ execute: makePush(25, 25),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH26: {
+ execute: makePush(26, 26),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH27: {
+ execute: makePush(27, 27),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH28: {
+ execute: makePush(28, 28),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH29: {
+ execute: makePush(29, 29),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH30: {
+ execute: makePush(30, 30),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH31: {
+ execute: makePush(31, 31),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ PUSH32: {
+ execute: makePush(32, 32),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ },
+ DUP1: {
+ execute: makeDup(1),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(1),
+ maxStack: maxDupStack(1),
+ },
+ DUP2: {
+ execute: makeDup(2),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(2),
+ maxStack: maxDupStack(2),
+ },
+ DUP3: {
+ execute: makeDup(3),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(3),
+ maxStack: maxDupStack(3),
+ },
+ DUP4: {
+ execute: makeDup(4),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(4),
+ maxStack: maxDupStack(4),
+ },
+ DUP5: {
+ execute: makeDup(5),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(5),
+ maxStack: maxDupStack(5),
+ },
+ DUP6: {
+ execute: makeDup(6),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(6),
+ maxStack: maxDupStack(6),
+ },
+ DUP7: {
+ execute: makeDup(7),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(7),
+ maxStack: maxDupStack(7),
+ },
+ DUP8: {
+ execute: makeDup(8),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(8),
+ maxStack: maxDupStack(8),
+ },
+ DUP9: {
+ execute: makeDup(9),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(9),
+ maxStack: maxDupStack(9),
+ },
+ DUP10: {
+ execute: makeDup(10),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(10),
+ maxStack: maxDupStack(10),
+ },
+ DUP11: {
+ execute: makeDup(11),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(11),
+ maxStack: maxDupStack(11),
+ },
+ DUP12: {
+ execute: makeDup(12),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(12),
+ maxStack: maxDupStack(12),
+ },
+ DUP13: {
+ execute: makeDup(13),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(13),
+ maxStack: maxDupStack(13),
+ },
+ DUP14: {
+ execute: makeDup(14),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(14),
+ maxStack: maxDupStack(14),
+ },
+ DUP15: {
+ execute: makeDup(15),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(15),
+ maxStack: maxDupStack(15),
+ },
+ DUP16: {
+ execute: makeDup(16),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(16),
+ maxStack: maxDupStack(16),
+ },
+ SWAP1: {
+ execute: makeSwap(1),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(2),
+ maxStack: maxSwapStack(2),
+ },
+ SWAP2: {
+ execute: makeSwap(2),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(3),
+ maxStack: maxSwapStack(3),
+ },
+ SWAP3: {
+ execute: makeSwap(3),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(4),
+ maxStack: maxSwapStack(4),
+ },
+ SWAP4: {
+ execute: makeSwap(4),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(5),
+ maxStack: maxSwapStack(5),
+ },
+ SWAP5: {
+ execute: makeSwap(5),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(6),
+ maxStack: maxSwapStack(6),
+ },
+ SWAP6: {
+ execute: makeSwap(6),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(7),
+ maxStack: maxSwapStack(7),
+ },
+ SWAP7: {
+ execute: makeSwap(7),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(8),
+ maxStack: maxSwapStack(8),
+ },
+ SWAP8: {
+ execute: makeSwap(8),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(9),
+ maxStack: maxSwapStack(9),
+ },
+ SWAP9: {
+ execute: makeSwap(9),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(10),
+ maxStack: maxSwapStack(10),
+ },
+ SWAP10: {
+ execute: makeSwap(10),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(11),
+ maxStack: maxSwapStack(11),
+ },
+ SWAP11: {
+ execute: makeSwap(11),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(12),
+ maxStack: maxSwapStack(12),
+ },
+ SWAP12: {
+ execute: makeSwap(12),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(13),
+ maxStack: maxSwapStack(13),
+ },
+ SWAP13: {
+ execute: makeSwap(13),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(14),
+ maxStack: maxSwapStack(14),
+ },
+ SWAP14: {
+ execute: makeSwap(14),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(15),
+ maxStack: maxSwapStack(15),
+ },
+ SWAP15: {
+ execute: makeSwap(15),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(16),
+ maxStack: maxSwapStack(16),
+ },
+ SWAP16: {
+ execute: makeSwap(16),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(17),
+ maxStack: maxSwapStack(17),
+ },
+ LOG0: {
+ execute: makeLog(0),
+ dynamicGas: makeGasLog(0),
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryLog,
+ },
+ LOG1: {
+ execute: makeLog(1),
+ dynamicGas: makeGasLog(1),
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryLog,
+ },
+ LOG2: {
+ execute: makeLog(2),
+ dynamicGas: makeGasLog(2),
+ minStack: minStack(4, 0),
+ maxStack: maxStack(4, 0),
+ memorySize: memoryLog,
+ },
+ LOG3: {
+ execute: makeLog(3),
+ dynamicGas: makeGasLog(3),
+ minStack: minStack(5, 0),
+ maxStack: maxStack(5, 0),
+ memorySize: memoryLog,
+ },
+ LOG4: {
+ execute: makeLog(4),
+ dynamicGas: makeGasLog(4),
+ minStack: minStack(6, 0),
+ maxStack: maxStack(6, 0),
+ memorySize: memoryLog,
+ },
+ CREATE: {
+ execute: opCreate,
+ constantGas: params.CreateGas,
+ dynamicGas: gasCreate,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ memorySize: memoryCreate,
+ },
+ CALL: {
+ execute: opCall,
+ constantGas: params.CallGasFrontier,
+ dynamicGas: gasCall,
+ minStack: minStack(7, 1),
+ maxStack: maxStack(7, 1),
+ memorySize: memoryCall,
+ },
+ CALLCODE: {
+ execute: opCallCode,
+ constantGas: params.CallGasFrontier,
+ dynamicGas: gasCallCode,
+ minStack: minStack(7, 1),
+ maxStack: maxStack(7, 1),
+ memorySize: memoryCall,
+ },
+ RETURN: {
+ execute: opReturn,
+ dynamicGas: gasReturn,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryReturn,
+ },
+ SELFDESTRUCT: {
+ execute: opSelfdestruct,
+ dynamicGas: gasSelfdestruct,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ },
+ }
+
+ // Fill all unassigned slots with opUndefined.
+ for i, entry := range tbl {
+ if entry == nil {
+ tbl[i] = &operation{execute: opUndefined, maxStack: maxStack(0, 0)}
+ }
+ }
+
+ tbl.MustValidate()
+ return tbl
+}
+
+// CopyJumpTable creates copy of the operations from the provided source JumpTable.
+func CopyJumpTable(source *JumpTable) *JumpTable {
+ dest := *source
+ for i, op := range source {
+ if op != nil {
+ opCopy := *op
+ dest[i] = &opCopy
+ }
+ }
+ return &dest
+}
diff --git a/x/evm/core/vm/jump_table_test.go b/x/evm/core/vm/jump_table_test.go
new file mode 100644
index 00000000..eae6681a
--- /dev/null
+++ b/x/evm/core/vm/jump_table_test.go
@@ -0,0 +1,35 @@
+// Copyright 2022 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+// TestJumpTableCopy tests that deep copy is necessery to prevent modify shared jump table
+func TestJumpTableCopy(t *testing.T) {
+ tbl := newMergeInstructionSet()
+ require.Equal(t, uint64(0), tbl[SLOAD].constantGas)
+
+ // a deep copy won't modify the shared jump table
+ deepCopy := CopyJumpTable(&tbl)
+ deepCopy[SLOAD].constantGas = 100
+ require.Equal(t, uint64(100), deepCopy[SLOAD].constantGas)
+ require.Equal(t, uint64(0), tbl[SLOAD].constantGas)
+}
diff --git a/x/evm/core/vm/logger.go b/x/evm/core/vm/logger.go
new file mode 100644
index 00000000..50fccafc
--- /dev/null
+++ b/x/evm/core/vm/logger.go
@@ -0,0 +1,44 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// EVMLogger is used to collect execution traces from an EVM transaction
+// execution. CaptureState is called for each step of the VM with the
+// current VM state.
+// Note that reference types are actual VM data structures; make copies
+// if you need to retain them beyond the current call.
+type EVMLogger interface {
+ // Transaction level
+ CaptureTxStart(gasLimit uint64)
+ CaptureTxEnd(restGas uint64)
+ // Top call frame
+ CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
+ CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
+ // Rest of call frames
+ CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
+ CaptureExit(output []byte, gasUsed uint64, err error)
+ // Opcode level
+ CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error)
+ CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error)
+}
diff --git a/x/evm/core/vm/memory.go b/x/evm/core/vm/memory.go
new file mode 100644
index 00000000..35b72999
--- /dev/null
+++ b/x/evm/core/vm/memory.go
@@ -0,0 +1,105 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "github.com/holiman/uint256"
+)
+
+// Memory implements a simple memory model for the ethereum virtual machine.
+type Memory struct {
+ store []byte
+ lastGasCost uint64
+}
+
+// NewMemory returns a new memory model.
+func NewMemory() *Memory {
+ return &Memory{}
+}
+
+// Set sets offset + size to value
+func (m *Memory) Set(offset, size uint64, value []byte) {
+ // It's possible the offset is greater than 0 and size equals 0. This is because
+ // the calcMemSize (common.go) could potentially return 0 when size is zero (NO-OP)
+ if size > 0 {
+ // length of store may never be less than offset + size.
+ // The store should be resized PRIOR to setting the memory
+ if offset+size > uint64(len(m.store)) {
+ panic("invalid memory: store empty")
+ }
+ copy(m.store[offset:offset+size], value)
+ }
+}
+
+// Set32 sets the 32 bytes starting at offset to the value of val, left-padded with zeroes to
+// 32 bytes.
+func (m *Memory) Set32(offset uint64, val *uint256.Int) {
+ // length of store may never be less than offset + size.
+ // The store should be resized PRIOR to setting the memory
+ if offset+32 > uint64(len(m.store)) {
+ panic("invalid memory: store empty")
+ }
+ // Fill in relevant bits
+ b32 := val.Bytes32()
+ copy(m.store[offset:], b32[:])
+}
+
+// Resize resizes the memory to size
+func (m *Memory) Resize(size uint64) {
+ if uint64(m.Len()) < size {
+ m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
+ }
+}
+
+// GetCopy returns offset + size as a new slice
+func (m *Memory) GetCopy(offset, size int64) (cpy []byte) {
+ if size == 0 {
+ return nil
+ }
+
+ if len(m.store) > int(offset) {
+ cpy = make([]byte, size)
+ copy(cpy, m.store[offset:offset+size])
+
+ return
+ }
+
+ return
+}
+
+// GetPtr returns the offset + size
+func (m *Memory) GetPtr(offset, size int64) []byte {
+ if size == 0 {
+ return nil
+ }
+
+ if len(m.store) > int(offset) {
+ return m.store[offset : offset+size]
+ }
+
+ return nil
+}
+
+// Len returns the length of the backing slice
+func (m *Memory) Len() int {
+ return len(m.store)
+}
+
+// Data returns the backing slice
+func (m *Memory) Data() []byte {
+ return m.store
+}
diff --git a/x/evm/core/vm/memory_table.go b/x/evm/core/vm/memory_table.go
new file mode 100644
index 00000000..f83deb38
--- /dev/null
+++ b/x/evm/core/vm/memory_table.go
@@ -0,0 +1,114 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+func memoryKeccak256(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
+}
+
+func memoryCallDataCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
+}
+
+func memoryReturnDataCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
+}
+
+func memoryCodeCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
+}
+
+func memoryExtCodeCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(3))
+}
+
+func memoryMLoad(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 32)
+}
+
+func memoryMStore8(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 1)
+}
+
+func memoryMStore(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 32)
+}
+
+func memoryCreate(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(2))
+}
+
+func memoryCreate2(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(2))
+}
+
+func memoryCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(5), stack.Back(6))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(3), stack.Back(4))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
+}
+
+func memoryDelegateCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
+}
+
+func memoryStaticCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
+}
+
+func memoryReturn(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
+}
+
+func memoryRevert(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
+}
+
+func memoryLog(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
+}
diff --git a/x/evm/core/vm/opcode_hooks.go b/x/evm/core/vm/opcode_hooks.go
new file mode 100644
index 00000000..4606d386
--- /dev/null
+++ b/x/evm/core/vm/opcode_hooks.go
@@ -0,0 +1,47 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import "github.com/ethereum/go-ethereum/common"
+
+// OpCodeHooks is a set of hooks that can be used to intercept and modify the
+// behavior of the EVM when executing certain opcodes.
+// The hooks are called before the execution of the respective opcodes.
+type OpCodeHooks interface {
+ // CallHook is called before executing a CALL, CALLCODE, DELEGATECALL and STATICCALL opcodes.
+ CallHook(evm *EVM, caller common.Address, recipient common.Address) error
+ // CreateHook is called before executing a CREATE and CREATE2 opcodes.
+ CreateHook(evm *EVM, caller common.Address) error
+}
+
+type NoopOpCodeHooks struct{}
+
+func (NoopOpCodeHooks) CallHook(evm *EVM, caller common.Address, recipient common.Address) error {
+ return nil
+}
+
+func (NoopOpCodeHooks) CreateHook(evm *EVM, caller common.Address) error {
+ return nil
+}
+
+func newNoopOpCodeHooks() OpCodeHooks {
+ return NoopOpCodeHooks{}
+}
+
+func NewDefaultOpCodeHooks() OpCodeHooks {
+ return newNoopOpCodeHooks()
+}
diff --git a/x/evm/core/vm/opcodes.go b/x/evm/core/vm/opcodes.go
new file mode 100644
index 00000000..7e3a8702
--- /dev/null
+++ b/x/evm/core/vm/opcodes.go
@@ -0,0 +1,551 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "fmt"
+)
+
+// OpCode is an EVM opcode
+type OpCode byte
+
+// IsPush specifies if an opcode is a PUSH opcode.
+func (op OpCode) IsPush() bool {
+ switch op {
+ case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
+ return true
+ }
+ return false
+}
+
+// 0x0 range - arithmetic ops.
+const (
+ STOP OpCode = 0x0
+ ADD OpCode = 0x1
+ MUL OpCode = 0x2
+ SUB OpCode = 0x3
+ DIV OpCode = 0x4
+ SDIV OpCode = 0x5
+ MOD OpCode = 0x6
+ SMOD OpCode = 0x7
+ ADDMOD OpCode = 0x8
+ MULMOD OpCode = 0x9
+ EXP OpCode = 0xa
+ SIGNEXTEND OpCode = 0xb
+)
+
+// 0x10 range - comparison ops.
+const (
+ LT OpCode = 0x10
+ GT OpCode = 0x11
+ SLT OpCode = 0x12
+ SGT OpCode = 0x13
+ EQ OpCode = 0x14
+ ISZERO OpCode = 0x15
+ AND OpCode = 0x16
+ OR OpCode = 0x17
+ XOR OpCode = 0x18
+ NOT OpCode = 0x19
+ BYTE OpCode = 0x1a
+ SHL OpCode = 0x1b
+ SHR OpCode = 0x1c
+ SAR OpCode = 0x1d
+)
+
+// 0x20 range - crypto.
+const (
+ KECCAK256 OpCode = 0x20
+)
+
+// 0x30 range - closure state.
+const (
+ ADDRESS OpCode = 0x30
+ BALANCE OpCode = 0x31
+ ORIGIN OpCode = 0x32
+ CALLER OpCode = 0x33
+ CALLVALUE OpCode = 0x34
+ CALLDATALOAD OpCode = 0x35
+ CALLDATASIZE OpCode = 0x36
+ CALLDATACOPY OpCode = 0x37
+ CODESIZE OpCode = 0x38
+ CODECOPY OpCode = 0x39
+ GASPRICE OpCode = 0x3a
+ EXTCODESIZE OpCode = 0x3b
+ EXTCODECOPY OpCode = 0x3c
+ RETURNDATASIZE OpCode = 0x3d
+ RETURNDATACOPY OpCode = 0x3e
+ EXTCODEHASH OpCode = 0x3f
+)
+
+// 0x40 range - block operations.
+const (
+ BLOCKHASH OpCode = 0x40
+ COINBASE OpCode = 0x41
+ TIMESTAMP OpCode = 0x42
+ NUMBER OpCode = 0x43
+ DIFFICULTY OpCode = 0x44
+ RANDOM OpCode = 0x44 // Same as DIFFICULTY
+ GASLIMIT OpCode = 0x45
+ CHAINID OpCode = 0x46
+ SELFBALANCE OpCode = 0x47
+ BASEFEE OpCode = 0x48
+)
+
+// 0x50 range - 'storage' and execution.
+const (
+ POP OpCode = 0x50
+ MLOAD OpCode = 0x51
+ MSTORE OpCode = 0x52
+ MSTORE8 OpCode = 0x53
+ SLOAD OpCode = 0x54
+ SSTORE OpCode = 0x55
+ JUMP OpCode = 0x56
+ JUMPI OpCode = 0x57
+ PC OpCode = 0x58
+ MSIZE OpCode = 0x59
+ GAS OpCode = 0x5a
+ JUMPDEST OpCode = 0x5b
+ PUSH0 OpCode = 0x5f
+)
+
+// 0x60 range - pushes.
+const (
+ PUSH1 OpCode = 0x60 + iota
+ PUSH2
+ PUSH3
+ PUSH4
+ PUSH5
+ PUSH6
+ PUSH7
+ PUSH8
+ PUSH9
+ PUSH10
+ PUSH11
+ PUSH12
+ PUSH13
+ PUSH14
+ PUSH15
+ PUSH16
+ PUSH17
+ PUSH18
+ PUSH19
+ PUSH20
+ PUSH21
+ PUSH22
+ PUSH23
+ PUSH24
+ PUSH25
+ PUSH26
+ PUSH27
+ PUSH28
+ PUSH29
+ PUSH30
+ PUSH31
+ PUSH32
+)
+
+// 0x80 range - dups.
+const (
+ DUP1 = 0x80 + iota
+ DUP2
+ DUP3
+ DUP4
+ DUP5
+ DUP6
+ DUP7
+ DUP8
+ DUP9
+ DUP10
+ DUP11
+ DUP12
+ DUP13
+ DUP14
+ DUP15
+ DUP16
+)
+
+// 0x90 range - swaps.
+const (
+ SWAP1 = 0x90 + iota
+ SWAP2
+ SWAP3
+ SWAP4
+ SWAP5
+ SWAP6
+ SWAP7
+ SWAP8
+ SWAP9
+ SWAP10
+ SWAP11
+ SWAP12
+ SWAP13
+ SWAP14
+ SWAP15
+ SWAP16
+)
+
+// 0xa0 range - logging ops.
+const (
+ LOG0 OpCode = 0xa0 + iota
+ LOG1
+ LOG2
+ LOG3
+ LOG4
+)
+
+// 0xf0 range - closures.
+const (
+ CREATE OpCode = 0xf0
+ CALL OpCode = 0xf1
+ CALLCODE OpCode = 0xf2
+ RETURN OpCode = 0xf3
+ DELEGATECALL OpCode = 0xf4
+ CREATE2 OpCode = 0xf5
+
+ STATICCALL OpCode = 0xfa
+ REVERT OpCode = 0xfd
+ INVALID OpCode = 0xfe
+ SELFDESTRUCT OpCode = 0xff
+)
+
+// Since the opcodes aren't all in order we can't use a regular slice.
+var opCodeToString = map[OpCode]string{
+ // 0x0 range - arithmetic ops.
+ STOP: "STOP",
+ ADD: "ADD",
+ MUL: "MUL",
+ SUB: "SUB",
+ DIV: "DIV",
+ SDIV: "SDIV",
+ MOD: "MOD",
+ SMOD: "SMOD",
+ EXP: "EXP",
+ NOT: "NOT",
+ LT: "LT",
+ GT: "GT",
+ SLT: "SLT",
+ SGT: "SGT",
+ EQ: "EQ",
+ ISZERO: "ISZERO",
+ SIGNEXTEND: "SIGNEXTEND",
+
+ // 0x10 range - bit ops.
+ AND: "AND",
+ OR: "OR",
+ XOR: "XOR",
+ BYTE: "BYTE",
+ SHL: "SHL",
+ SHR: "SHR",
+ SAR: "SAR",
+ ADDMOD: "ADDMOD",
+ MULMOD: "MULMOD",
+
+ // 0x20 range - crypto.
+ KECCAK256: "KECCAK256",
+
+ // 0x30 range - closure state.
+ ADDRESS: "ADDRESS",
+ BALANCE: "BALANCE",
+ ORIGIN: "ORIGIN",
+ CALLER: "CALLER",
+ CALLVALUE: "CALLVALUE",
+ CALLDATALOAD: "CALLDATALOAD",
+ CALLDATASIZE: "CALLDATASIZE",
+ CALLDATACOPY: "CALLDATACOPY",
+ CODESIZE: "CODESIZE",
+ CODECOPY: "CODECOPY",
+ GASPRICE: "GASPRICE",
+ EXTCODESIZE: "EXTCODESIZE",
+ EXTCODECOPY: "EXTCODECOPY",
+ RETURNDATASIZE: "RETURNDATASIZE",
+ RETURNDATACOPY: "RETURNDATACOPY",
+ EXTCODEHASH: "EXTCODEHASH",
+
+ // 0x40 range - block operations.
+ BLOCKHASH: "BLOCKHASH",
+ COINBASE: "COINBASE",
+ TIMESTAMP: "TIMESTAMP",
+ NUMBER: "NUMBER",
+ DIFFICULTY: "DIFFICULTY", // TODO (MariusVanDerWijden) rename to RANDOM post merge
+ GASLIMIT: "GASLIMIT",
+ CHAINID: "CHAINID",
+ SELFBALANCE: "SELFBALANCE",
+ BASEFEE: "BASEFEE",
+
+ // 0x50 range - 'storage' and execution.
+ POP: "POP",
+ // DUP: "DUP",
+ // SWAP: "SWAP",
+ MLOAD: "MLOAD",
+ MSTORE: "MSTORE",
+ MSTORE8: "MSTORE8",
+ SLOAD: "SLOAD",
+ SSTORE: "SSTORE",
+ JUMP: "JUMP",
+ JUMPI: "JUMPI",
+ PC: "PC",
+ MSIZE: "MSIZE",
+ GAS: "GAS",
+ JUMPDEST: "JUMPDEST",
+ PUSH0: "PUSH0",
+
+ // 0x60 range - push.
+ PUSH1: "PUSH1",
+ PUSH2: "PUSH2",
+ PUSH3: "PUSH3",
+ PUSH4: "PUSH4",
+ PUSH5: "PUSH5",
+ PUSH6: "PUSH6",
+ PUSH7: "PUSH7",
+ PUSH8: "PUSH8",
+ PUSH9: "PUSH9",
+ PUSH10: "PUSH10",
+ PUSH11: "PUSH11",
+ PUSH12: "PUSH12",
+ PUSH13: "PUSH13",
+ PUSH14: "PUSH14",
+ PUSH15: "PUSH15",
+ PUSH16: "PUSH16",
+ PUSH17: "PUSH17",
+ PUSH18: "PUSH18",
+ PUSH19: "PUSH19",
+ PUSH20: "PUSH20",
+ PUSH21: "PUSH21",
+ PUSH22: "PUSH22",
+ PUSH23: "PUSH23",
+ PUSH24: "PUSH24",
+ PUSH25: "PUSH25",
+ PUSH26: "PUSH26",
+ PUSH27: "PUSH27",
+ PUSH28: "PUSH28",
+ PUSH29: "PUSH29",
+ PUSH30: "PUSH30",
+ PUSH31: "PUSH31",
+ PUSH32: "PUSH32",
+
+ DUP1: "DUP1",
+ DUP2: "DUP2",
+ DUP3: "DUP3",
+ DUP4: "DUP4",
+ DUP5: "DUP5",
+ DUP6: "DUP6",
+ DUP7: "DUP7",
+ DUP8: "DUP8",
+ DUP9: "DUP9",
+ DUP10: "DUP10",
+ DUP11: "DUP11",
+ DUP12: "DUP12",
+ DUP13: "DUP13",
+ DUP14: "DUP14",
+ DUP15: "DUP15",
+ DUP16: "DUP16",
+
+ SWAP1: "SWAP1",
+ SWAP2: "SWAP2",
+ SWAP3: "SWAP3",
+ SWAP4: "SWAP4",
+ SWAP5: "SWAP5",
+ SWAP6: "SWAP6",
+ SWAP7: "SWAP7",
+ SWAP8: "SWAP8",
+ SWAP9: "SWAP9",
+ SWAP10: "SWAP10",
+ SWAP11: "SWAP11",
+ SWAP12: "SWAP12",
+ SWAP13: "SWAP13",
+ SWAP14: "SWAP14",
+ SWAP15: "SWAP15",
+ SWAP16: "SWAP16",
+ LOG0: "LOG0",
+ LOG1: "LOG1",
+ LOG2: "LOG2",
+ LOG3: "LOG3",
+ LOG4: "LOG4",
+
+ // 0xf0 range.
+ CREATE: "CREATE",
+ CALL: "CALL",
+ RETURN: "RETURN",
+ CALLCODE: "CALLCODE",
+ DELEGATECALL: "DELEGATECALL",
+ CREATE2: "CREATE2",
+ STATICCALL: "STATICCALL",
+ REVERT: "REVERT",
+ INVALID: "INVALID",
+ SELFDESTRUCT: "SELFDESTRUCT",
+}
+
+func (op OpCode) String() string {
+ str := opCodeToString[op]
+ if len(str) == 0 {
+ return fmt.Sprintf("opcode %#x not defined", int(op))
+ }
+
+ return str
+}
+
+var stringToOp = map[string]OpCode{
+ "STOP": STOP,
+ "ADD": ADD,
+ "MUL": MUL,
+ "SUB": SUB,
+ "DIV": DIV,
+ "SDIV": SDIV,
+ "MOD": MOD,
+ "SMOD": SMOD,
+ "EXP": EXP,
+ "NOT": NOT,
+ "LT": LT,
+ "GT": GT,
+ "SLT": SLT,
+ "SGT": SGT,
+ "EQ": EQ,
+ "ISZERO": ISZERO,
+ "SIGNEXTEND": SIGNEXTEND,
+ "AND": AND,
+ "OR": OR,
+ "XOR": XOR,
+ "BYTE": BYTE,
+ "SHL": SHL,
+ "SHR": SHR,
+ "SAR": SAR,
+ "ADDMOD": ADDMOD,
+ "MULMOD": MULMOD,
+ "KECCAK256": KECCAK256,
+ "ADDRESS": ADDRESS,
+ "BALANCE": BALANCE,
+ "ORIGIN": ORIGIN,
+ "CALLER": CALLER,
+ "CALLVALUE": CALLVALUE,
+ "CALLDATALOAD": CALLDATALOAD,
+ "CALLDATASIZE": CALLDATASIZE,
+ "CALLDATACOPY": CALLDATACOPY,
+ "CHAINID": CHAINID,
+ "BASEFEE": BASEFEE,
+ "DELEGATECALL": DELEGATECALL,
+ "STATICCALL": STATICCALL,
+ "CODESIZE": CODESIZE,
+ "CODECOPY": CODECOPY,
+ "GASPRICE": GASPRICE,
+ "EXTCODESIZE": EXTCODESIZE,
+ "EXTCODECOPY": EXTCODECOPY,
+ "RETURNDATASIZE": RETURNDATASIZE,
+ "RETURNDATACOPY": RETURNDATACOPY,
+ "EXTCODEHASH": EXTCODEHASH,
+ "BLOCKHASH": BLOCKHASH,
+ "COINBASE": COINBASE,
+ "TIMESTAMP": TIMESTAMP,
+ "NUMBER": NUMBER,
+ "DIFFICULTY": DIFFICULTY,
+ "GASLIMIT": GASLIMIT,
+ "SELFBALANCE": SELFBALANCE,
+ "POP": POP,
+ "MLOAD": MLOAD,
+ "MSTORE": MSTORE,
+ "MSTORE8": MSTORE8,
+ "SLOAD": SLOAD,
+ "SSTORE": SSTORE,
+ "JUMP": JUMP,
+ "JUMPI": JUMPI,
+ "PC": PC,
+ "MSIZE": MSIZE,
+ "GAS": GAS,
+ "JUMPDEST": JUMPDEST,
+ "PUSH0": PUSH0,
+ "PUSH1": PUSH1,
+ "PUSH2": PUSH2,
+ "PUSH3": PUSH3,
+ "PUSH4": PUSH4,
+ "PUSH5": PUSH5,
+ "PUSH6": PUSH6,
+ "PUSH7": PUSH7,
+ "PUSH8": PUSH8,
+ "PUSH9": PUSH9,
+ "PUSH10": PUSH10,
+ "PUSH11": PUSH11,
+ "PUSH12": PUSH12,
+ "PUSH13": PUSH13,
+ "PUSH14": PUSH14,
+ "PUSH15": PUSH15,
+ "PUSH16": PUSH16,
+ "PUSH17": PUSH17,
+ "PUSH18": PUSH18,
+ "PUSH19": PUSH19,
+ "PUSH20": PUSH20,
+ "PUSH21": PUSH21,
+ "PUSH22": PUSH22,
+ "PUSH23": PUSH23,
+ "PUSH24": PUSH24,
+ "PUSH25": PUSH25,
+ "PUSH26": PUSH26,
+ "PUSH27": PUSH27,
+ "PUSH28": PUSH28,
+ "PUSH29": PUSH29,
+ "PUSH30": PUSH30,
+ "PUSH31": PUSH31,
+ "PUSH32": PUSH32,
+ "DUP1": DUP1,
+ "DUP2": DUP2,
+ "DUP3": DUP3,
+ "DUP4": DUP4,
+ "DUP5": DUP5,
+ "DUP6": DUP6,
+ "DUP7": DUP7,
+ "DUP8": DUP8,
+ "DUP9": DUP9,
+ "DUP10": DUP10,
+ "DUP11": DUP11,
+ "DUP12": DUP12,
+ "DUP13": DUP13,
+ "DUP14": DUP14,
+ "DUP15": DUP15,
+ "DUP16": DUP16,
+ "SWAP1": SWAP1,
+ "SWAP2": SWAP2,
+ "SWAP3": SWAP3,
+ "SWAP4": SWAP4,
+ "SWAP5": SWAP5,
+ "SWAP6": SWAP6,
+ "SWAP7": SWAP7,
+ "SWAP8": SWAP8,
+ "SWAP9": SWAP9,
+ "SWAP10": SWAP10,
+ "SWAP11": SWAP11,
+ "SWAP12": SWAP12,
+ "SWAP13": SWAP13,
+ "SWAP14": SWAP14,
+ "SWAP15": SWAP15,
+ "SWAP16": SWAP16,
+ "LOG0": LOG0,
+ "LOG1": LOG1,
+ "LOG2": LOG2,
+ "LOG3": LOG3,
+ "LOG4": LOG4,
+ "CREATE": CREATE,
+ "CREATE2": CREATE2,
+ "CALL": CALL,
+ "RETURN": RETURN,
+ "CALLCODE": CALLCODE,
+ "REVERT": REVERT,
+ "INVALID": INVALID,
+ "SELFDESTRUCT": SELFDESTRUCT,
+}
+
+// StringToOp finds the opcode whose name is stored in `str`.
+func StringToOp(str string) OpCode {
+ return stringToOp[str]
+}
diff --git a/x/evm/core/vm/operations_acl.go b/x/evm/core/vm/operations_acl.go
new file mode 100644
index 00000000..a2f36d1e
--- /dev/null
+++ b/x/evm/core/vm/operations_acl.go
@@ -0,0 +1,244 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
+ return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ // If we fail the minimum gas availability invariant, fail (0)
+ if contract.Gas <= params.SstoreSentryGasEIP2200 {
+ return 0, errors.New("not enough gas for reentrancy sentry")
+ }
+ // Gas sentry honoured, do the actual gas calculation based on the stored value
+ var (
+ y, x = stack.Back(1), stack.Peek()
+ slot = common.Hash(x.Bytes32())
+ current = evm.StateDB.GetState(contract.Address(), slot)
+ cost = uint64(0)
+ )
+ // Check slot presence in the access list
+ if addrPresent, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
+ cost = params.ColdSloadCostEIP2929
+ // If the caller cannot afford the cost, this change will be rolled back
+ evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
+ if !addrPresent {
+ // Once we're done with YOLOv2 and schedule this for mainnet, might
+ // be good to remove this panic here, which is just really a
+ // canary to have during testing
+ panic("impossible case: address was not present in access list during sstore op")
+ }
+ }
+ value := common.Hash(y.Bytes32())
+
+ if current == value { // noop (1)
+ // EIP 2200 original clause:
+ // return params.SloadGasEIP2200, nil
+ return cost + params.WarmStorageReadCostEIP2929, nil // SLOAD_GAS
+ }
+ original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32())
+ if original == current {
+ if original == (common.Hash{}) { // create slot (2.1.1)
+ return cost + params.SstoreSetGasEIP2200, nil
+ }
+ if value == (common.Hash{}) { // delete slot (2.1.2b)
+ evm.StateDB.AddRefund(clearingRefund)
+ }
+ // EIP-2200 original clause:
+ // return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2)
+ return cost + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929), nil // write existing slot (2.1.2)
+ }
+ if original != (common.Hash{}) {
+ if current == (common.Hash{}) { // recreate slot (2.2.1.1)
+ evm.StateDB.SubRefund(clearingRefund)
+ } else if value == (common.Hash{}) { // delete slot (2.2.1.2)
+ evm.StateDB.AddRefund(clearingRefund)
+ }
+ }
+ if original == value {
+ if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
+ // EIP 2200 Original clause:
+ // evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.SloadGasEIP2200)
+ evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.WarmStorageReadCostEIP2929)
+ } else { // reset to original existing slot (2.2.2.2)
+ // EIP 2200 Original clause:
+ // evm.StateDB.AddRefund(params.SstoreResetGasEIP2200 - params.SloadGasEIP2200)
+ // - SSTORE_RESET_GAS redefined as (5000 - COLD_SLOAD_COST)
+ // - SLOAD_GAS redefined as WARM_STORAGE_READ_COST
+ // Final: (5000 - COLD_SLOAD_COST) - WARM_STORAGE_READ_COST
+ evm.StateDB.AddRefund((params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) - params.WarmStorageReadCostEIP2929)
+ }
+ }
+ // EIP-2200 original clause:
+ // return params.SloadGasEIP2200, nil // dirty update (2.2)
+ return cost + params.WarmStorageReadCostEIP2929, nil // dirty update (2.2)
+ }
+}
+
+// gasSLoadEIP2929 calculates dynamic gas for SLOAD according to EIP-2929
+// For SLOAD, if the (address, storage_key) pair (where address is the address of the contract
+// whose storage is being read) is not yet in accessed_storage_keys,
+// charge 2100 gas and add the pair to accessed_storage_keys.
+// If the pair is already in accessed_storage_keys, charge 100 gas.
+func gasSLoadEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ loc := stack.Peek()
+ slot := common.Hash(loc.Bytes32())
+ // Check slot presence in the access list
+ if _, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
+ // If the caller cannot afford the cost, this change will be rolled back
+ // If he does afford it, we can skip checking the same thing later on, during execution
+ evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
+ return params.ColdSloadCostEIP2929, nil
+ }
+ return params.WarmStorageReadCostEIP2929, nil
+}
+
+// gasExtCodeCopyEIP2929 implements extcodecopy according to EIP-2929
+// EIP spec:
+// > If the target is not in accessed_addresses,
+// > charge COLD_ACCOUNT_ACCESS_COST gas, and add the address to accessed_addresses.
+// > Otherwise, charge WARM_STORAGE_READ_COST gas.
+func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ // memory expansion first (dynamic part of pre-2929 implementation)
+ gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+ addr := common.Address(stack.Peek().Bytes20())
+ // Check slot presence in the access list
+ if !evm.StateDB.AddressInAccessList(addr) {
+ evm.StateDB.AddAddressToAccessList(addr)
+ var overflow bool
+ // We charge (cold-warm), since 'warm' is already charged as constantGas
+ if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
+ return 0, ErrGasUintOverflow
+ }
+ return gas, nil
+ }
+ return gas, nil
+}
+
+// gasEip2929AccountCheck checks whether the first stack item (as address) is present in the access list.
+// If it is, this method returns '0', otherwise 'cold-warm' gas, presuming that the opcode using it
+// is also using 'warm' as constant factor.
+// This method is used by:
+// - extcodehash,
+// - extcodesize,
+// - (ext) balance
+func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ addr := common.Address(stack.Peek().Bytes20())
+ // Check slot presence in the access list
+ if !evm.StateDB.AddressInAccessList(addr) {
+ // If the caller cannot afford the cost, this change will be rolled back
+ evm.StateDB.AddAddressToAccessList(addr)
+ // The warm storage read cost is already charged as constantGas
+ return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil
+ }
+ return 0, nil
+}
+
+func makeCallVariantGasCallEIP2929(oldCalculator gasFunc) gasFunc {
+ return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ addr := common.Address(stack.Back(1).Bytes20())
+ // Check slot presence in the access list
+ warmAccess := evm.StateDB.AddressInAccessList(addr)
+ // The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
+ // the cost to charge for cold access, if any, is Cold - Warm
+ coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
+ if !warmAccess {
+ evm.StateDB.AddAddressToAccessList(addr)
+ // Charge the remaining difference here already, to correctly calculate available
+ // gas for call
+ if !contract.UseGas(coldCost) {
+ return 0, ErrOutOfGas
+ }
+ }
+ // Now call the old calculator, which takes into account
+ // - create new account
+ // - transfer value
+ // - memory expansion
+ // - 63/64ths rule
+ gas, err := oldCalculator(evm, contract, stack, mem, memorySize)
+ if warmAccess || err != nil {
+ return gas, err
+ }
+ // In case of a cold access, we temporarily add the cold charge back, and also
+ // add it to the returned gas. By adding it to the return, it will be charged
+ // outside of this function, as part of the dynamic gas, and that will make it
+ // also become correctly reported to tracers.
+ contract.Gas += coldCost
+ return gas + coldCost, nil
+ }
+}
+
+var (
+ gasCallEIP2929 = makeCallVariantGasCallEIP2929(gasCall)
+ gasDelegateCallEIP2929 = makeCallVariantGasCallEIP2929(gasDelegateCall)
+ gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall)
+ gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode)
+ gasSelfdestructEIP2929 = makeSelfdestructGasFn(true)
+ // gasSelfdestructEIP3529 implements the changes in EIP-2539 (no refunds)
+ gasSelfdestructEIP3529 = makeSelfdestructGasFn(false)
+
+ // gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
+ //
+ // When calling SSTORE, check if the (address, storage_key) pair is in accessed_storage_keys.
+ // If it is not, charge an additional COLD_SLOAD_COST gas, and add the pair to accessed_storage_keys.
+ // Additionally, modify the parameters defined in EIP 2200 as follows:
+ //
+ // Parameter Old value New value
+ // SLOAD_GAS 800 = WARM_STORAGE_READ_COST
+ // SSTORE_RESET_GAS 5000 5000 - COLD_SLOAD_COST
+ //
+ //The other parameters defined in EIP 2200 are unchanged.
+ // see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
+ gasSStoreEIP2929 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP2200)
+
+ // gasSStoreEIP2539 implements gas cost for SSTORE according to EIP-2539
+ // Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
+ gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
+)
+
+// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-2539
+func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
+ gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ var (
+ gas uint64
+ address = common.Address(stack.Peek().Bytes20())
+ )
+ if !evm.StateDB.AddressInAccessList(address) {
+ // If the caller cannot afford the cost, this change will be rolled back
+ evm.StateDB.AddAddressToAccessList(address)
+ gas = params.ColdAccountAccessCostEIP2929
+ }
+ // if empty and transfers value
+ if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
+ gas += params.CreateBySelfdestructGas
+ }
+ if refundsEnabled && !evm.StateDB.HasSuicided(contract.Address()) {
+ evm.StateDB.AddRefund(params.SelfdestructRefundGas)
+ }
+ return gas, nil
+ }
+ return gasFunc
+}
diff --git a/x/evm/core/vm/stack.go b/x/evm/core/vm/stack.go
new file mode 100644
index 00000000..a731b157
--- /dev/null
+++ b/x/evm/core/vm/stack.go
@@ -0,0 +1,146 @@
+// Copyright 2014 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "fmt"
+ "sync"
+
+ "github.com/holiman/uint256"
+)
+
+var stackPool = sync.Pool{
+ New: func() interface{} {
+ return &Stack{Data: make([]uint256.Int, 0, 16)}
+ },
+}
+
+// Stack is an object for basic stack operations. Items popped to the stack are
+// expected to be changed and modified. stack does not take care of adding newly
+// initialised objects.
+type Stack struct {
+ Data []uint256.Int
+}
+
+func NewStack() (*Stack, error) {
+ stack, ok := stackPool.Get().(*Stack)
+ if !ok {
+ return nil, fmt.Errorf("type assertion failure: cannot get Stack pointer from stackPool")
+ }
+ return stack, nil
+}
+
+func (st *Stack) Push(d *uint256.Int) {
+ // NOTE push limit (1024) is checked in baseCheck
+ st.Data = append(st.Data, *d)
+}
+
+func (st *Stack) PushN(ds ...uint256.Int) {
+ // FIXME: Is there a way to pass args by pointers.
+ st.Data = append(st.Data, ds...)
+}
+
+func (st *Stack) Pop() (ret uint256.Int) {
+ ret = st.Data[len(st.Data)-1]
+ st.Data = st.Data[:len(st.Data)-1]
+ return
+}
+
+func (st *Stack) Cap() int {
+ return cap(st.Data)
+}
+
+func (st *Stack) Swap(n int) {
+ st.Data[st.Len()-n], st.Data[st.Len()-1] = st.Data[st.Len()-1], st.Data[st.Len()-n]
+}
+
+func (st *Stack) Dup(n int) {
+ st.Push(&st.Data[st.Len()-n])
+}
+
+func (st *Stack) Peek() *uint256.Int {
+ return &st.Data[st.Len()-1]
+}
+
+func (st *Stack) Back(n int) *uint256.Int {
+ return &st.Data[st.Len()-n-1]
+}
+
+func (st *Stack) Reset() {
+ st.Data = st.Data[:0]
+}
+
+func (st *Stack) Len() int {
+ return len(st.Data)
+}
+
+// Print dumps the content of the stack
+func (st *Stack) Print() {
+ fmt.Println("### stack ###")
+ if len(st.Data) > 0 {
+ for i, val := range st.Data {
+ fmt.Printf("%-3d %v\n", i, val)
+ }
+ } else {
+ fmt.Println("-- empty --")
+ }
+ fmt.Println("#############")
+}
+
+func ReturnNormalStack(s *Stack) {
+ s.Data = s.Data[:0]
+ stackPool.Put(s)
+}
+
+var rStackPool = sync.Pool{
+ New: func() interface{} {
+ return &ReturnStack{data: make([]uint32, 0, 10)}
+ },
+}
+
+func ReturnRStack(rs *ReturnStack) {
+ rs.data = rs.data[:0]
+ rStackPool.Put(rs)
+}
+
+// ReturnStack is an object for basic return stack operations.
+type ReturnStack struct {
+ data []uint32
+}
+
+func NewReturnStack() (*ReturnStack, error) {
+ rStack, ok := rStackPool.Get().(*ReturnStack)
+ if !ok {
+ return nil, fmt.Errorf("type assertion failure: cannot get ReturnStack pointer from rStackPool")
+ }
+ return rStack, nil
+}
+
+func (st *ReturnStack) Push(d uint32) {
+ st.data = append(st.data, d)
+}
+
+// Pop A uint32 is sufficient as for code below 4.2G
+func (st *ReturnStack) Pop() (ret uint32) {
+ ret = st.data[len(st.data)-1]
+ st.data = st.data[:len(st.data)-1]
+ return
+}
+
+func (st *ReturnStack) Data() []uint32 {
+ return st.data
+}
diff --git a/x/evm/core/vm/stack_table.go b/x/evm/core/vm/stack_table.go
new file mode 100644
index 00000000..8f502f56
--- /dev/null
+++ b/x/evm/core/vm/stack_table.go
@@ -0,0 +1,45 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package vm
+
+import (
+ "github.com/ethereum/go-ethereum/params"
+)
+
+func minSwapStack(n int) int {
+ return minStack(n, n)
+}
+
+func maxSwapStack(n int) int {
+ return maxStack(n, n)
+}
+
+func minDupStack(n int) int {
+ return minStack(n, n+1)
+}
+
+func maxDupStack(n int) int {
+ return maxStack(n, n+1)
+}
+
+func maxStack(pop, push int) int {
+ return int(params.StackLimit) + pop - push
+}
+
+func minStack(pops, _ int) int {
+ return pops
+}
diff --git a/x/evm/core/vm/testdata/precompiles/blake2F.json b/x/evm/core/vm/testdata/precompiles/blake2F.json
new file mode 100644
index 00000000..a25f9ae5
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blake2F.json
@@ -0,0 +1,37 @@
+[
+ {
+ "Input": "0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ "Expected": "08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b",
+ "Name": "vector 4",
+ "Gas": 0,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ "Expected": "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923",
+ "Name": "vector 5",
+ "Gas": 12,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000",
+ "Expected": "75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735",
+ "Name": "vector 6",
+ "Gas": 12,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ "Expected": "b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421",
+ "Name": "vector 7",
+ "Gas": 1,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "007A120048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ "Expected": "6d2ce9e534d50e18ff866ae92d70cceba79bbcd14c63819fe48752c8aca87a4bb7dcc230d22a4047f0486cfcfb50a17b24b2899eb8fca370f22240adb5170189",
+ "Name": "vector 8",
+ "Gas": 8000000,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsG1Add.json b/x/evm/core/vm/testdata/precompiles/blsG1Add.json
new file mode 100644
index 00000000..184d765a
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsG1Add.json
@@ -0,0 +1,730 @@
+[
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ "Expected": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28",
+ "Name": "bls_g1add_(g1+g1=2*g1)",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d280000000000000000000000000000000009ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e522400000000000000000000000000000000032b80d3a6f5b09f8a84623389c5f80ca69a0cddabc3097f9d9c27310fd43be6e745256c634af45ca3473b0590ae30d1",
+ "Expected": "0000000000000000000000000000000010e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc0000000000000000000000000000000016ba437edcc6551e30c10512367494bfb6b01cc6681e8a4c3cd2501832ab5c4abc40b4578b85cbaffbf0bcd70d67c6e2",
+ "Name": "bls_g1add_(2*g1+3*g1=5*g1)",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ "Name": "bls_g1add_(inf+g1=g1)",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g1add_(inf+inf=inf)",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992fee000000000000000000000000000000000001101098f5c39893765766af4512a0c74e1bb89bc7e6fdf14e3e7337d257cc0f94658179d83320b99f31ff94cd2bac0000000000000000000000000000000003e1a9f9f44ca2cdab4f43a1a3ee3470fdf90b2fc228eb3b709fcd72f014838ac82a6d797aeefed9a0804b22ed1ce8f7",
+ "Expected": "000000000000000000000000000000001466e1373ae4a7e7ba885c5f0c3ccfa48cdb50661646ac6b779952f466ac9fc92730dcaed9be831cd1f8c4fefffd5209000000000000000000000000000000000c1fb750d2285d4ca0378e1e8cdbf6044151867c34a711b73ae818aee6dbe9e886f53d7928cc6ed9c851e0422f609b11",
+ "Name": "matter_g1_add_0",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed2000000000000000000000000000000000441e7f7f96198e4c23bd5eb16f1a7f045dbc8c53219ab2bcea91d3a027e2dfe659feac64905f8b9add7e4bfc91bec2b0000000000000000000000000000000005fc51bb1b40c87cd4292d4b66f8ca5ce4ef9abd2b69d4464b4879064203bda7c9fc3f896a3844ebc713f7bb20951d95",
+ "Expected": "0000000000000000000000000000000016b8ab56b45a9294466809b8e858c1ad15ad0d52cfcb62f8f5753dc94cee1de6efaaebce10701e3ec2ecaa9551024ea600000000000000000000000000000000124571eec37c0b1361023188d66ec17c1ec230d31b515e0e81e599ec19e40c8a7c8cdea9735bc3d8b4e37ca7e5dd71f6",
+ "Name": "matter_g1_add_1",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f00000000000000000000000000000000114c3f11ba0b47551fa28f09f148936d6b290dc9f2d0534a83c32b0b849ab921ce6bcaa4ff3c917707798d9c74f2084f00000000000000000000000000000000149dc028207fb04a7795d94ea65e21f9952e445000eb954531ee519efde6901675d3d2446614d243efb77a9cfe0ca3ae",
+ "Expected": "0000000000000000000000000000000002ce7a08719448494857102da464bc65a47c95c77819af325055a23ac50b626df4732daf63feb9a663d71b7c9b8f2c510000000000000000000000000000000016117e87e9b55bd4bd5763d69d5240d30745e014b9aef87c498f9a9e3286ec4d5927df7cd5a2e54ac4179e78645acf27",
+ "Name": "matter_g1_add_2",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e4000000000000000000000000000000000c3d564ac1fe12f18f528c3750583ab6af8973bff3eded7bb4778c32805d9b17846cc7c687af0f46bc87de7748ab72980000000000000000000000000000000002f164c131cbd5afc85692c246157d38dc4bbb2959d2edfa6daf0a8b17c7a898aad53b400e8bdc2b29bf6688ee863db7",
+ "Expected": "0000000000000000000000000000000015510826f50b88fa369caf062ecdf8b03a67e660a35b219b44437a5583b5a9adf76991dce7bff9afc50257f847299504000000000000000000000000000000000a83e879895a1b47dbd6cd25ce8b719e7490cfe021614f7539e841fc2f9c09f071e386676de60b6579aa4bf6d37b13dd",
+ "Name": "matter_g1_add_3",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d30000000000000000000000000000000019fe3a64361fea14936ff0b3e630471494d0c0b9423e6a004184a2965221c18849b5ed0eb2708a587323d8d6c6735a90000000000000000000000000000000000340823d314703e5efeb0a65c23069199d7dfff8793aaacb98cdcd6177fc8e61ab3294c57bf13b4406266715752ef3e6",
+ "Expected": "00000000000000000000000000000000010b1c96d3910f56b0bf54da5ae8c7ab674a07f8143b61fed660e7309e626dc73eaa2b11886cdb82e2b6735e7802cc860000000000000000000000000000000002dabbbedd72872c2c012e7e893d2f3df1834c43873315488d814ddd6bfcca6758a18aa6bd02a0f3aed962cb51f0a222",
+ "Name": "matter_g1_add_4",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f90000000000000000000000000000000001461565b03a86df363d1854b4af74879115dffabeddfa879e2c8db9aa414fb291a076c3bdf0beee82d9c094ea8dc381a000000000000000000000000000000000e19d51ab619ee2daf25ea5bfa51eb217eabcfe0b5cb0358fd2fa105fd7cb0f5203816b990df6fda4e0e8d541be9bcf6",
+ "Expected": "000000000000000000000000000000000cb40d0bf86a627d3973f1e7846484ffd0bc4943b42a54ff9527c285fed3c056b947a9b6115824cabafe13cd1af8181c00000000000000000000000000000000076255fc12f1a9dbd232025815238baaa6a3977fd87594e8d1606caec0d37b916e1e43ee2d2953d75a40a7ba416df237",
+ "Name": "matter_g1_add_5",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1b0000000000000000000000000000000019cabba3e09ad34cc3d125e0eb41b527aa48a4562c2b7637467b2dbc71c373897d50eed1bc75b2bde8904ece5626d6e400000000000000000000000000000000056b0746f820cff527358c86479dc924a10b9f7cae24cd495625a4159c8b71a8c3ad1a15ebf22d3561cd4b74e8a6e48b",
+ "Expected": "000000000000000000000000000000000e115e0b61c1f1b25cc10a7b3bd21cf696b1433a0c366c2e1bca3c26b09482c6eced8c8ecfa69ce6b9b3b4419779262e00000000000000000000000000000000077b85daf61b9f947e81633e3bc64e697bc6c1d873f2c21e5c4c3a11302d4d5ef4c3ff5519564729aaf2a50a3c9f1196",
+ "Name": "matter_g1_add_6",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442a0000000000000000000000000000000011f649ee35ff8114060fc5e4df9ac828293f6212a9857ca31cb3e9ce49aa1212154a9808f1e763bc989b6d5ba7cf09390000000000000000000000000000000019af81eca7452f58c1a6e99fab50dc0d5eeebc7712153e717a14a31cffdfd0a923dbd585e652704a174905605a2e8b9d",
+ "Expected": "000000000000000000000000000000000013e37a8950a659265b285c6fb56930fb77759d9d40298acac2714b97b83ec7692a7d1c4ccb83f074384db9eedd809c0000000000000000000000000000000003215d524d6419214568ba42a31502f2a58a97d0139c66908e9d71755f5a7666567aafe30ea84d89308f06768f28a648",
+ "Name": "matter_g1_add_7",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795000000000000000000000000000000000d713e148769fac2efd380886f8566c6d4662dd38317bb7e68744c4339efaedbab88435ce3dc289afaa7ecb37df37a5300000000000000000000000000000000129d9cd031b31c77a4e68093dcdbb585feba786207aa115d9cf120fe4f19ca31a0dca9c692bd0f53721d60a55c333129",
+ "Expected": "00000000000000000000000000000000029405b9615e14bdac8b5666bbc5f3843d4bca17c97bed66d164f1b58d2a148f0f506d645d665a40e60d53fe29375ed400000000000000000000000000000000162761f1712814e474beb2289cc50519253d680699b530c2a6477f727ccc75a19681b82e490f441f91a3c611eeb0e9e2",
+ "Name": "matter_g1_add_8",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a1900000000000000000000000000000000006d92bcb599edca426ff4ceeb154ebf133c2dea210c7db0441f74bd37c8d239149c8b5056ace0bfefb1db04b42664f530000000000000000000000000000000008522fc155eef6d5746283808091f91b427f2a96ac248850f9e3d7aadd14848101c965663fd4a63aea1153d71918435a",
+ "Expected": "000000000000000000000000000000000cfaa8df9437c0b6f344a0c8dcbc7529a07aec0d7632ace89af6796b6b960b014f78dd10e987a993fb8a95cc909822ec0000000000000000000000000000000007475f115f6eb35f78ba9a2b71a44ccb6bbc1e980b8cd369c5c469565f3fb798bc907353cf47f524ba715deaedf379cb",
+ "Name": "matter_g1_add_9",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac9430000000000000000000000000000000016380d03b7c5cc3301ffcb2cf7c28c9bde54fc22ba2b36ec293739d8eb674678c8e6461e34c1704747817c8f8341499a000000000000000000000000000000000ec6667aa5c6a769a64c180d277a341926376c39376480dc69fcad9a8d3b540238eb39d05aaa8e3ca15fc2c3ab696047",
+ "Expected": "0000000000000000000000000000000011541d798b4b5069e2541fa5410dad03fd02784332e72658c7b0fa96c586142a967addc11a7a82bfcee33bd5d07066b900000000000000000000000000000000195b3fcb94ab7beb908208283b4e5d19c0af90fca4c76268f3c703859dea7d038aca976927f48839ebc7310869c724aa",
+ "Name": "matter_g1_add_10",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e00000000000000000000000000000000065eb0770ab40199658bf87db6c6b52cd8c6c843a3e40dd60433d4d79971ff31296c9e00a5d553df7c81ade533379f4b0000000000000000000000000000000017a6f6137ddd90c15cf5e415f040260e15287d8d2254c6bfee88938caec9e5a048ff34f10607d1345ba1f09f30441ef4",
+ "Expected": "0000000000000000000000000000000006b0853b3d41fc2d7b27da0bb2d6eb76be32530b59f8f537d227a6eb78364c7c0760447494a8bba69ef4b256dbef750200000000000000000000000000000000166e55ba2d20d94da474d4a085c14245147705e252e2a76ae696c7e37d75cde6a77fea738cef045182d5e628924dc0bb",
+ "Name": "matter_g1_add_11",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276b0000000000000000000000000000000006a3f7eb0e42567210cc1ba5e6f8c42d02f1eef325b6483fef49ba186f59ab69ca2284715b736086d2a0a1f0ea224b40000000000000000000000000000000000bc08427fda31a6cfbe657a8c71c73894a33700e93e411d42f1471160c403b939b535070b68d60a4dc50e47493da63dc",
+ "Expected": "000000000000000000000000000000000c35d4cd5d43e9cf52c15d46fef521666a1e1ab9f0b4a77b8e78882e9fab40f3f988597f202c5bd176c011a56a1887d4000000000000000000000000000000000ae2b5c24928a00c02daddf03fade45344f250dcf4c12eda06c39645b4d56147cb239d95b06fd719d4dc20fe332a6fce",
+ "Name": "matter_g1_add_12",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a578768100000000000000000000000000000000068e79aea45b7199ec4b6f26e01e88ec76533743639ce76df66937fff9e7de3edf6700d227f10f43e073afcc63e2eddc00000000000000000000000000000000039c0b6d9e9681401aeb57a94cedc0709a0eff423ace9253eb00ae75e21cabeb626b52ef4368e6a4592aed9689c6fca4",
+ "Expected": "0000000000000000000000000000000013bad27dafa20f03863454c30bd5ae6b202c9c7310875da302d4693fc1c2b78cca502b1ff851b183c4b2564c5d3eb4dc0000000000000000000000000000000000552b322b3d672704382b5d8b214c225b4f7868f9c5ae0766b7cdb181f97ed90a4892235915ffbc0daf3e14ec98a606",
+ "Name": "matter_g1_add_13",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f7680000000000000000000000000000000000adac9bb98bb6f35a8f941dbff39dfd307b6a4d5756ccae103c814564e3d3993a8866ff91581ccdd7686c1dce0b19f700000000000000000000000000000000083d235e0579032ca47f65b6ae007ce8ffd2f1a890ce3bc45ebd0df6673ad530d2f42125d543cb0c51ba0c28345729d8",
+ "Expected": "000000000000000000000000000000000b5513e42f5217490f395a8cb3673a4fc35142575f770af75ecf7a4fcd97eee215c4298fc4feab51915137cbdb814839000000000000000000000000000000000e9d4db04b233b0b12a7ff620faefef906aeb2b15481ce1609dad50eb6a7d0c09a850375599c501296219fb7b288e305",
+ "Name": "matter_g1_add_14",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931d000000000000000000000000000000000d5bb4fa8b494c0adf4b695477d4a05f0ce48f7f971ef53952f685e9fb69dc8db1603e4a58292ddab7129bb5911d6cea0000000000000000000000000000000004a568c556641f0e0a2f44124b77ba70e4e560d7e030f1a21eff41eeec0d3c437b43488c535cdabf19a70acc777bacca",
+ "Expected": "000000000000000000000000000000000c27ef4ebf37fd629370508f4cd062b74faa355b305d2ee60c7f4d67dd741363f18a7bbd368cdb17e848f372a5e33a6f0000000000000000000000000000000000ed833df28988944115502f554636e0b436cccf845341e21191e82d5b662482f32c24df492da4c605a0f9e0f8b00604",
+ "Name": "matter_g1_add_15",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d500000000000000000000000000000000091ee883cb9ea2c933f6645f0f4c535a826d95b6da6847b4fe2349342bd4bd496e0dd546df7a7a17a4b9fb8349e5064f000000000000000000000000000000000902d7e72242a5e6b068ca82d0cb71dc0f51335dbd302941045319f9a06777518b56a6e0b0b0c9fd8f1edf6b114ad331",
+ "Expected": "00000000000000000000000000000000122cce99f623944dfebffcdf6b0a0a3696162f35053e5952dddc2537421c60da9fe931579d1c4fc2e31082b6c25f96b500000000000000000000000000000000011366ffa91dc0b7da8b7c1839ea84d49299310f5c1ca244012eed0dd363dbcf4ad5813b8e3fb49361ef05ea8cb18ffe",
+ "Name": "matter_g1_add_16",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debe0000000000000000000000000000000000d3d4f11bc79b8425b77d25698b7e151d360ebb22c3a6afdb227de72fe432dcd6f0276b4fd3f1fcc2da5b59865053930000000000000000000000000000000015ac432071dc23148765f198ed7ea2234662745a96032c215cd9d7cf0ad8dafb8d52f209983fe98aaa2243ecc2073f1b",
+ "Expected": "000000000000000000000000000000000113ccf11264ff04448f8c58b279a6a49acb386750c2051eab2c90fa8b8e03d7c5b9e87eccf36b4b3f79446b80be7b1d0000000000000000000000000000000004358a1fabfe803f4c787a671196b593981a837ee78587225fb21d5a883b98a15b912862763b94d18b971cb7e37dbcf0",
+ "Name": "matter_g1_add_17",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb600000000000000000000000000000000034f725766897ed76394145da2f02c92c66794a51fd5ae07bd7cc60c013d7a48ebf1b07faf669dfed74d82d07e48d1150000000000000000000000000000000018f4926a3d0f740988da25379199ecb849250239ad7efcfef7ffaa43bc1373166c0448cc30dcdbd75ceb71f76f883ea7",
+ "Expected": "00000000000000000000000000000000167336aeeb9e447348156936849d518faee314c291c84d732fa3c1bd3951559230d94230e37a08e28e689e9d1fef05770000000000000000000000000000000005366535f7a68996e066ab80c55bb372a15fb0ed6634585b88fe7cafbf818fbfebbf6f6ddd9ca0ff72137594a1e84b35",
+ "Name": "matter_g1_add_18",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154b00000000000000000000000000000000079e5a154cf84190b6c735bc8cd968559182166568649b813732e4fb4c5c428c8b38e8265d4ef04990c49aa1381f51c8000000000000000000000000000000000ae08e682ef92b4986a5ac5d4f094ad0919c826a97efe8d8120a96877766eae5828803804a0cae67df9822fd18622aae",
+ "Expected": "000000000000000000000000000000000a3d66cf87b1ce8c5683d71a6de4bf829d094041240f56d9071aa84ff189a06940e8e1935127e23a970c78ca73c28bf6000000000000000000000000000000000b2adda87740873c0c59e3ebde44d33834773f0fe69e2f5e7ede99c4f928978a5caaede7262e45fd22136a394b3f7858",
+ "Name": "matter_g1_add_19",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af0000000000000000000000000000000008cefd0fd289d6964a962051c2c2ad98dab178612663548370dd5f007c5264fece368468d3ca8318a381b443c68c4cc7000000000000000000000000000000000708d118d44c1cb5609667fd51df9e58cacce8b65565ef20ad1649a3e1b9453e4fb37af67c95387de008d4c2114e5b95",
+ "Expected": "0000000000000000000000000000000004b2311897264fe08972d62872d3679225d9880a16f2f3d7dd59412226e5e3f4f2aa8a69d283a2dc5b93e022293f0ee1000000000000000000000000000000000f03e18cef3f9a86e6b842272f2c7ee48d0ad23bfc7f1d5a9a796d88e5d5ac31326db5fe90de8f0690c70ae6e0155039",
+ "Name": "matter_g1_add_20",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719290000000000000000000000000000000008e5afc16d909eb9d8bdaaf229ad291f34f7baf5247bbd4cc938278f1349adb4b0f0aacd14799c01d0ca2ed38c937d600000000000000000000000000000000006cf972c64e20403c82fee901c90eaa5547460d57cce2565fd091ff9bc55e24584595c9182298f148882d6949c36c9d5",
+ "Expected": "000000000000000000000000000000000caf46f480ae2ea8e700f7913c505d5150c4629c9137e917357d2a4ba8a7a1c63b8f6e2978293755952fbed7f0ad8d6d0000000000000000000000000000000002e62e715b72eebbc7c366a2390318f73e69203a9533e72340aab568f65105129ffc9889a8bc00a692494d93688c7ec0",
+ "Name": "matter_g1_add_21",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac0000000000000000000000000000000013a6439e0ec0fabe93f6c772e102b96b1f692971d7181c386f7f8a360daca6e5f99772e1a736f1e72a17148d90b08efe0000000000000000000000000000000010f27477f3171dcf74498e940fc324596ef5ec6792be590028c2963385d84ef8c4bbb12c6eb3f06b1afb6809a2cb0358",
+ "Expected": "000000000000000000000000000000000dea57d1fc19f994e6bdda9478a400b0ada23aed167bfe7a16ef79b6aa020403a04d554303c0b2a9c5a38f85cf6f3800000000000000000000000000000000000b8d76ccd41ba81a835775185bbf1d6bf94b031d94d5c78b3b97beb24cf246b0c25c4c309e2c06ae9896ed800169eeee",
+ "Name": "matter_g1_add_22",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff320000000000000000000000000000000005728a219d128bc0a1f851f228e2bf604a72400c393cfb0d3484456b6b28a2c5061198656f0e106bbe257d849be159040000000000000000000000000000000011f6d08baa91fb2c8b36191d5b2318e355f8964cc8112838394ba1ded84b075de58d90452601dcfc9aa8a275cfec695d",
+ "Expected": "0000000000000000000000000000000012e6d6c518c15cfd3020181ff3f829e29140b3b507b99251cc7f31795128adec817750296bce413bac18b9a80f69ca5000000000000000000000000000000000131ee9b748f6f1eb790adeb9edd0e79d89a9908368f5a6bb82ee0c913061cdfffe75d9ba411a49aa3f9194ee6d4d08a9",
+ "Name": "matter_g1_add_23",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f200000000000000000000000000000000171696781ba195f330241584e42fb112adf9b8437b54ad17d410892b45c7d334e8734e25862604d1b679097590b8ab0a000000000000000000000000000000001879328fdf0d1fb79afd920e0b0a386828be5b8e0e6024dfeea800ffcb5c65f9044061af26d639d4dcc27bcb5ba1481a",
+ "Expected": "00000000000000000000000000000000111c416d5bd018a77f3317e3fbf4b03d8e19658f2b810dc9c17863310dfb09e1c4ffdbb7c98951d357f1c3d93c5d0745000000000000000000000000000000000af0a252bff336d5eb3a406778557ef67d91776a9c788be9a76cff7727f519a70fc7809f1a50a58d29185cb9722624fd",
+ "Name": "matter_g1_add_24",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c2000000000000000000000000000000000231b0d6189a4faad082ce4a69398c1734fcf35d222b7bce22b14571033a1066b049ae3cd3bd6c8cec5bec743955cdd600000000000000000000000000000000037375237fb71536564ea693ab316ae11722aadd7cab12b17b926c8a31bd13c4565619e8c894bffb960e632896856bbe",
+ "Expected": "000000000000000000000000000000000d2b9c677417f4e9b38af6393718f55a27dbd23c730796c50472bc476ebf52172559b10f6ceb81e644ec2d0a41b3bb01000000000000000000000000000000001697f241ff6eceb05d9ada4be7d7078ecbbffa64dd4fb43ead0692eef270cb7cc31513ee4bf38a1b1154fe008a8b836a",
+ "Name": "matter_g1_add_25",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd10000000000000000000000000000000015653d1c5184736cdc78838be953390d12b307d268b394136b917b0462d5e31b8f1b9d96cce8f7a1203c2cae93db6a4000000000000000000000000000000000060efeece033ac711d500c1156e4b6dce3243156170c94bc948fd7beae7b28a31463a44872ca22ca49dc5d4d4dd27d1c",
+ "Expected": "0000000000000000000000000000000003996050756117eeab27a5e4fa9acdde2a1161d6fbfff2601a1c7329f900e93a29f55a8073f85be8f7c2a4d0323e95cc00000000000000000000000000000000010b195a132c1cba2f1a6a73f2507baa079e9b5cb8894ea78bebc16d4151ee56fe562b16e2741f3ab1e8640cdad83180",
+ "Name": "matter_g1_add_26",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc0000000000000000000000000000000018adb42928304cbc310a229306a205e7c21cdb31b9e5daf0ff6bb9437acee80cd8cf02b35dab823155d60f8a83fde5cc0000000000000000000000000000000018b57460c81cab43235be79c8c90dcda40fafcaf69e4e767133aee56308a6df07eac71275597dd8ed6607ffb9151ed9a",
+ "Expected": "0000000000000000000000000000000003c7a7ee3d1b73cf1f0213404363bf3c0de4425ab97d679ed51448e877b7537400f148f14eba588ed241fea34e56d465000000000000000000000000000000000c581b5070e6bb8582b7ee2cd312dfeb5aaf0b0da95cf5a22a505ffba21fc204e26a5e17311d1f47113653ff13349f57",
+ "Name": "matter_g1_add_27",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da00000000000000000000000000000000001da65df8574a864ab454e5f2fa929405501bb73c3162a600979a1145586079361c89839cc0c5a07f1135c94bf059f9c0000000000000000000000000000000002560df402c0550662a2c4c463ad428ab6e60297fbc42a6484107e397ae016b58494d1c46ac4952027aa8c0896c50be3",
+ "Expected": "000000000000000000000000000000000d7a539b679e5858271a6f9cf20108410eb5d5d2b1a905e09a8aa20318efbe9175450385d78389f08f836f5634f7a2f0000000000000000000000000000000000fb624e5f6c4c814b7d73eb63b70237c5de7d90d19ac81cac776d86171a8d307d3cc8c56da14f444fe8cf329ab7e63dd",
+ "Name": "matter_g1_add_28",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e0530000000000000000000000000000000005311c11f4d0bb8542f3b60247c1441656608e5ac5c363f4d62127cecb88800a771767cf23a0e7c45f698ffa5015061f0000000000000000000000000000000018f7f1d23c8b0566a6a1fcb58d3a5c6fd422573840eb04660c3c6ba65762ed1becc756ac6300e9ce4f5bfb962e963419",
+ "Expected": "0000000000000000000000000000000000849bbc7b0226b18abbcb4c9a9e78dca2f5f75a2cbb983bd95ff3a95b427b1a01fd909ce36384c49eb88ffb8ff77bb000000000000000000000000000000000087d8d28d92305b5313ca533a6b47f454ddce1c2d0fa3574b255128ef0b145fa4158beb07e4f0d50d6b7b90ea8a8ea8a",
+ "Name": "matter_g1_add_29",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265e000000000000000000000000000000000c8e293f730253128399e5c39ab18c3f040b6cd9df10d794a28d2a428a9256ea1a71cf53022bd1be11f501805e0ddda40000000000000000000000000000000003e60c2291be46900930f710969f79f27e76cf710efefc243236428db2fed93719edeeb64ada0edf6346a0411f2a4cb8",
+ "Expected": "00000000000000000000000000000000191084201608f706ea1f7c51dd5b593dda87b15d2c594b52829db66ce3beab6b30899d1d285bdb9590335949ceda5f050000000000000000000000000000000000d3460622c7f1d849658a20a7ae7b05e5afae1f01e871cad52ef632cc831b0529a3066f7b81248a7728d231e51fc4ad",
+ "Name": "matter_g1_add_30",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc80000000000000000000000000000000013267db8fdf8f488a2806fead5cffdcbb7b1b4b7681a2b67d322cd7f5985c65d088c70cdc2638e679ed678cae3cc63c80000000000000000000000000000000007757233ad6d38d488c3d9d8252b41e4ab7ee54e4ef4bbf171402df57c14f9977dd3583c6c8f9b5171b368d61f082447",
+ "Expected": "000000000000000000000000000000000c06fef6639ab7dceb44dc648ca6a7d614739e40e6486ee9fc01ecc55af580d98abc026c630a95878da7b6d5701d755c0000000000000000000000000000000007c9a7f2bc7fa1f65c9e3a1e463eb4e3283e47bb5490938edb12abf6c8f5a9b56d8ce7a81a60df67db8c399a9a1df1d4",
+ "Name": "matter_g1_add_31",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff17000000000000000000000000000000001975bc52669187f27a86096ae6bf2d60178706105d15bce8fe782759f14e449bc97cb1570e87eec5f12214a9ae0e0170000000000000000000000000000000000ca6106d6e6487a3b6f00fc2af769d21cb3b83b5dc03db19e4824fc28fd9b3d9f7a986e79f05c02b3a914ff26c7a78d6",
+ "Expected": "0000000000000000000000000000000002fbf4fba68ae416b42a99f3b26916dea464d662cebce55f4545481e5ab92d3c40f3e189504b54db4c9cd51ecdd60e8d0000000000000000000000000000000008e81e094c6d4ded718ef63c5edfacb2d258f48ccfa37562950c607299bb2dca18e680a620dff8c72dedc89b4e9d4759",
+ "Name": "matter_g1_add_32",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3f00000000000000000000000000000000109f6168a719add6ea1a14f9dc95345e325d6b0e56da2f4ecff8408536446894069fa61e81bdaebfc96b13b402fad865000000000000000000000000000000001806aa27c576f4c4fa8a6db49d577cd8f257a8450e89b061cbc7773c0b5434f06bacf12b479abf6847f537c4cbefcb46",
+ "Expected": "0000000000000000000000000000000014e0bd4397b90a3f96240daf835d5fb05da28a64538f4bf42d9e7925a571f831c6e663910aa37dcc265ddd7938d83045000000000000000000000000000000001695d405d4f8ba385ebf4ad25fb3f34c65977217e90d6e5ed5085b3e5b0b143194f82e6c25766d28ad6c63114ca9dcdf",
+ "Name": "matter_g1_add_33",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9af0000000000000000000000000000000019d3623a7866933e2d73214ceb2e56097a1b047db5943c3ecb846890aa02250126e90fc76a729a952cef895bd154cc7d000000000000000000000000000000000e87c376bbd695a356ef72226ac7ef6a550d99e9693d8485770a686e568ae28c038ee201d3f2ea38362046236ade91cd",
+ "Expected": "000000000000000000000000000000000ffeab47985bd9b3e10ce27c6636bbda336dcf540cd37eccc3faec2adff2d97dd126633bd83a7d3c8c73c3623bdf0ba2000000000000000000000000000000001992eca4b1e924b360d57ca98b543ab496a8b55bd288d23f03bcc1b22f6bc76d95b12f47c3e305812097253c73b876dd",
+ "Name": "matter_g1_add_34",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c300000000000000000000000000000000163aaecf83d6c77a5d7417e73f5cf9d71a6aedfd194b2f3b53c608d06a228190f4f79ac57b029d77504c72744df4ecc0000000000000000000000000000000000416e6f9ca188d16daa2c28acd6a594f8fcb990eaa26e60ca2a34dfcad7ad76c425b241acedf674d48d298d0df0f824d",
+ "Expected": "000000000000000000000000000000001812bcb26fa05e0ab5176e703699ab16f5ef8917a33a9626ae6ff20f2a6f4a9d5e2afe3a11f57061cbaa992e1f30477f000000000000000000000000000000000680acf0b632cb48017cb80baa93753d030aa4b49957178d8a10d1d1a27bbdc89ac6811a91868b2c181c5c0b9b6caf86",
+ "Name": "matter_g1_add_35",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db000000000000000000000000000000000aba7362eee717d03ef2d4f0fef2763822115fcc8fb9e2e8243683b6c1cde799ebc78f23812e557de2cc38e2b4a2e56700000000000000000000000000000000170833db69b3f067cf5c4c4690857e6711c9e3fcad91ca7cd045e9d2f38c7b31236960e8718f5dd4c8bfb4de76c6c9b9",
+ "Expected": "00000000000000000000000000000000196ffe76a4b726fa8dd720cc1cd04c040724cb18ec10915e312eaa90d124100b08f0ce3a7fc888f46914319a3d7581f4000000000000000000000000000000000e2612357059ca6dbb64efb98ef19370560c9e83e2aad7ab2d9015e2444fe4d8c796b5577584aac9f63258beb5ae863c",
+ "Name": "matter_g1_add_36",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da8257721808000000000000000000000000000000000a98ae36c690f2e3be8100f43678be5a1064390e210328dd23f61f5a496b87398db2798580edeabc6273fb9537fa12880000000000000000000000000000000009aedf77bb969592c6552ae0121a1c74de78ba222b6cd08623c7a34708a12763b5ff7969cf761ccd25adc1b65da0f02d",
+ "Expected": "00000000000000000000000000000000072334ec8349fc38b99d6dea0b4259c03cd96c1438c90ef0da6321df2495892de031a53c23838ca2b260774fa09b5461000000000000000000000000000000000e4535767c2477c4f87c087540c836eeffcd0c45960841f9c3561a8a5f8e61ab98b183b11192b8e7ea1c9c7717336243",
+ "Name": "matter_g1_add_37",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e00000000000000000000000000000000015c3c056ec904ce865d073f8f70ef2d4b5adb5b9238deaa5e167d32f45cad4901aa6d87efa2338c633e7853ce4c19185000000000000000000000000000000000a15f1aa6e662f21d7127351a1655821c943c4cf590e3c9e60c9ab968b4a835f87fb8d87eee6331ee4e194e5f1ea91f4",
+ "Expected": "000000000000000000000000000000000140fb6dcf872d0a3bff3e32a0cb4a7fb7e60ee4fb476bb120c4ce068e169d72e1c167d7fda321280d5855983d5a9af800000000000000000000000000000000108f54a4ec3ba26dd614f4d94c5c82652583906986158ad40ffea54c17703fa4b0bd7806633e1c0318d06e8dc7d41cde",
+ "Name": "matter_g1_add_38",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcb000000000000000000000000000000000307841cb33e0f188103a83334a828fa864cea09c264d5f4343246f64ab244add4610c9ccd64c001816e5074fe84013f000000000000000000000000000000000e15bbeb6fff7f1435097828f5d64c448bbc800f31a5b7428436dcffd68abc92682f2b01744d7c60540e0cd1b57ab5d4",
+ "Expected": "000000000000000000000000000000000a1b50660ed9120fff1e5c4abb401e4691a09f41780ca188cea4b1c2d77002f08ce28eb1caa41ee3fe73169e3651bb7f00000000000000000000000000000000125439ac3b45c698a98063ab911364bd3c6dd2a69435d00d6edf89fc5566b33038e960a125e5e52141abb605587942fe",
+ "Name": "matter_g1_add_39",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6300000000000000000000000000000000013866438b089d39de5a3ca2a624d72c241a54cbdcf5b2a67ebdd2db8373b112a814e74662bd52e37748ffbfc21782a5000000000000000000000000000000000d55454a22d5c2ef82611ef9cb6533e2f08668577764afc5bb9b7dfe32abd5d333147774fb1001dd24889775de57d305",
+ "Expected": "000000000000000000000000000000000037b4e8846b423335711ac12f91e2419de772216509d6b9deb9c27fd1c1ee5851b3e032bf3bcac3dd8e93f3dce8a91b00000000000000000000000000000000113a1bf4be1103e858c3be282effafd5e2384f4d1073350f7073b0a415ecf9e7a3bfb55c951c0b2c25c6bab35454ecf0",
+ "Name": "matter_g1_add_40",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f180320000000000000000000000000000000017440fd557df23286da15f9a96bb88cfbc79589b1c157af13baf02c65227dc0a5bdec6f2f300083ff91dae395ed8cb75000000000000000000000000000000000ad09b4290842cc599d346110fdb39ededbb1d651568579564e274465f07b8f77eeaf00fece0c10db69c2125de8ab394",
+ "Expected": "0000000000000000000000000000000007c158b4e21566742f7e4e39a672bd383e27864505acef4ef8c26f8b0a9db418f9c088b555b8e9eb25acf9859b1207b40000000000000000000000000000000016e06a1ace89f992d582af0de7662ef91c0a98f574306f6f6d0d8d5e80166638d2deef70105cce2e9b20faa9d6315510",
+ "Name": "matter_g1_add_41",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f0000000000000000000000000000000000d7ccc3a4efdfe1a92a88e453933b8216016091f1b9d575faf18a5b3abf90daf077813167a3f4acce7359472dee544bb00000000000000000000000000000000128008c075ab176100e755cbb8de5b9ff0e9a78114f862d26ed030d9c1d1dea1c21ec8ae4d82a84d3ff5ae4c1cd6f339",
+ "Expected": "000000000000000000000000000000000b84f9de79c748e37797c629cb78b86b4b736b199f161b30147b5dacf6eabe0b54afce40d5dacfe9a8ee8da5ef5b49de0000000000000000000000000000000010277ad094bb9a3b96379b1366dd90125b51a21ebeb4f776a81d9d9c1f37ab58c32a884a26fa32c83783ed0eef42b820",
+ "Name": "matter_g1_add_42",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5e00000000000000000000000000000000008da4a93d5ffcdaa0adc736a59f0c187ae3bf11ecb5e9e6f6aedea976a47757739042200b4c4593c2dd5db555425531000000000000000000000000000000000a6fdb2d4160c6c35223daa6fa10d0b1073de07fe4f2eba28e65ed049ff8d8852ed0538b30759fe7a0d944009ddf9a6f",
+ "Expected": "000000000000000000000000000000000d740bd1effd8674250618af0358ad0b83bbc787f0264af9c2ada72fa5431be909e82155da1de0211f46fb307e9949f0000000000000000000000000000000000ddf62c91d587a14b64feef07da52c081b40fbbf9a0f2eae8b66022e0850fc94de6a467e7e4f580c7f2c806f6c6ed8cf",
+ "Name": "matter_g1_add_43",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d790000000000000000000000000000000003258d7931a1d72ab6344c7e96c0dbd435a7909fe68cc679c08ca9b62f7a6a04863082cbcfdbe9a736625d895e4f3bdb0000000000000000000000000000000009ee3e470e2b2cebc955ba3444b7e478f887138e36c13bd68490689122627269ea5e7ce22dd9c69792394a24187103d6",
+ "Expected": "000000000000000000000000000000000af674691f5d87655f0066188fac5013f31b4169a0181d3feb7ac3beae0d9a3429d4125f099ee344f644a2de8b941f9f00000000000000000000000000000000042a9603b8e4a6c37d59ede3a1398f5f80c5298da66de575a204ee28811d9f7c7c0dd40cef3769bd72a2156b9eb620c8",
+ "Name": "matter_g1_add_44",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e820000000000000000000000000000000001833807f1ced52399305419450355499a63411837ee61ad681559d59561db18511eb1e8ad3161e7fe30016b560d18b8f00000000000000000000000000000000198b11b31586e17964a4a4ccdee85703163d2106481833e71f26327a589bafb43578d08d87f6cb19c7a04b4ca92392bf",
+ "Expected": "000000000000000000000000000000001081c3359a0fadfe7850ce878182859e3dd77028772da7bcac9f6451ac6455739c22627889673db626bbea70aa3648d50000000000000000000000000000000000f4e8766f976fa49a0b05ef3f06f56d92fe6452ff05c3fac455f9c16efadf1b81a44d2921bed73511dda81d6fc7478e",
+ "Name": "matter_g1_add_45",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b811580000000000000000000000000000000007dc719ae9e3f1e11d3ed4747a546a7b973ccb1967adb1b3066645a8bde9632bcfa3530e768f088ddbc022b169e67cbf000000000000000000000000000000000bbf9cf884b19c84045da1cead7dcd9fdbf39d764ff1ad60d83ed1e4fd0ce0554f0fb618203952cf02a7c4ba466c66b8",
+ "Expected": "000000000000000000000000000000000f60d66fd1ed5eb04f9619d6458c522cc49f5ace111aff2b61903b112559972f80ac615591463abf2b944c4f99d4c03e000000000000000000000000000000000001a1abfa869be2cda6bd7e05454a8735e1b638db7e1b3715708539c2d14ade53069c7e68b36d3b08cff80837028b7d",
+ "Name": "matter_g1_add_46",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd0000000000000000000000000000000014b78c66c4acecdd913ba73cc4ab573c64b404a9494d29d4a2ba02393d9b8fdaba47bb7e76d32586df3a00e03ae2896700000000000000000000000000000000025c371cd8b72592a45dc521336a891202c5f96954812b1095ba2ea6bb11aad7b6941a44d68fe9b44e4e5fd06bd541d4",
+ "Expected": "0000000000000000000000000000000015b164c854a2277658f5d08e04887d896a082c6c20895c8809ed4b349da8492d6fa0333ace6059a1f0d37e92ae9bad30000000000000000000000000000000001510d176ddba09ab60bb452188c2705ef154f449bed26abf0255897673a625637b5761355b17676748f67844a61d4e9f",
+ "Name": "matter_g1_add_47",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe900000000000000000000000000000000104ee0990ba4194916f670f44e254200971b67a18ed45b25c17be49df66e4f9b934bac8c1552ecc25bdaa3af55952076000000000000000000000000000000000591094d9d89afe025ca1832d7f3e60444f83e72403a434b42216b6c4213980d29e4ef0c64ae497006de550c1faa9425",
+ "Expected": "0000000000000000000000000000000006db0cc24ffec8aa11aecc43e9b76a418daac51d51f3de437090c1bcaabace19f7f8b5ceb6277d6b32b7f3b239a90c4700000000000000000000000000000000069e01f60ca7468c6b9a247c79d18cf3d88bf5d1d62c76abf9237408edeba05dea744205ac5b501920f519bb847bb711",
+ "Name": "matter_g1_add_48",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193a0000000000000000000000000000000004840d028d0c0f056aeb37b7a8505325081e9822ef26046f2da72f2155c20987dd51f4b5577c5395e24288b71d2ce5140000000000000000000000000000000015f231a233e997633c1d6492e0df358fb658ae29d0f53928c8a0578484c899a699178ca3223772210063aa08991c3fff",
+ "Expected": "000000000000000000000000000000000fa72bf2d7d564cc4982b9f2cdca743d2ac14f0f1be4218dbafb8b93a9277e55273487a5d2857fd3f731ac4ee469a6a1000000000000000000000000000000000fce44f886453c6ca5ebde9af41d2be92d1126e9897d72978a179dd7eebeed6242b6e9718604ab0c9369529a0426a575",
+ "Name": "matter_g1_add_49",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece1738220000000000000000000000000000000004877b97faa1d05d61ab65001110bf190d442cabcd6d4d1b9c1f0e513309aebd278f84a80354dfdef875769d00ec2c7500000000000000000000000000000000187066cccb5008bc2ffd0bcd1b227a5a0fe0cd4984316ba3cfd5113c4632a04c56cbda8d48993bd0dd50e9b7ce2b7ee9",
+ "Expected": "0000000000000000000000000000000019ecd38afacc6b281b2515270157328e18039d51574bae0f7e0ef16c3f6da89f55ddee9e3bbb450ad51fe11edfd9f18d00000000000000000000000000000000088a5e292761bbf7a914a9f723de099035e91bd3c1fe9cd50728a4ceaa4fd3953683f30aa8e70ba0eb23919092aa9e22",
+ "Name": "matter_g1_add_50",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10c000000000000000000000000000000001881f5aba0603b0a256e03e5dc507598dd63682ce80a29e0fa141b2afdadf6168e98221e4ee45d378cee0416baaadc49000000000000000000000000000000000070d255101319dd3a0f8ca3a0856188428c09de15475d6b70d70a405e45ab379a5b1f2e55f84bd7fe5dd12aeedce670",
+ "Expected": "0000000000000000000000000000000011ccd455d5e3eba94567a17bcd777559b4ff1afa66fd6f05f99c69937404290a2f1c83cfd6c2c25886ebff4934332c0e0000000000000000000000000000000010920aa3d5974df25530610ef466adce3d51fd6a508d4b1111739c586dfd7ba9040836e075fd812fe111d92f25b67f51",
+ "Name": "matter_g1_add_51",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bf000000000000000000000000000000000b53e5339f25bcd31afd091362874b5042c0b762ed7425341331630addbc4dccc299936e1acdf89823c36867d46c6f28000000000000000000000000000000000fc3c6b522268511dd52826dd1aee707413d925ee51aeb0e5d69c0e3eb697fabbc14783b5007e240cc0c53c299a40ada",
+ "Expected": "00000000000000000000000000000000060773b9b8f3babdba3db27089b7be3e6e287a635dbae19576039d34ae18a0e6413278bfa280570f6329ae05cdb693fd00000000000000000000000000000000075fb9527f99a8c8db41e67baaf1deafffd2c134badb1b3478a26b5501b31dca858fad6f0d52f412d5631ecfa72eece4",
+ "Name": "matter_g1_add_52",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b2000000000000000000000000000000001693f4ebab3fed548784264196fb01cf55311399f47cdad74a9543bda5d1ca682a00ee04bb0b3954d5a0f00ceef97a750000000000000000000000000000000017f4019c23bd68e84d889857c417b17aa96c780fec3c1ed6ca75100cc70c97a8bb8272ad4c6de896d76dc2a1b09c7a61",
+ "Expected": "000000000000000000000000000000000a3ea8afdc83794f18f9a9427bcd60a355196925d38fdf74ab09d4a08279647b2da6f1fbe30948a785497d6c6dddc2a9000000000000000000000000000000001263c88f1ca3e574cafac21641432d45ee01e1b05eba95716565922abe28c7f0fb004c255afcbfa10cf7959bbe6b00d7",
+ "Name": "matter_g1_add_53",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b0000000000000000000000000000000005d5602e05499a435effff3812744b582b0cd7c68f1c88faa3c268515c8b14f3c041b8ae322fe526b2406e7c25d84e61000000000000000000000000000000001038eaf49e74e19111e4456ebba01dc4d22c7e23a303d5dec821da832e90a1b07b1a6b8034137f1bfdcddeb58053a170",
+ "Expected": "0000000000000000000000000000000019258ea5023ce73343dcd201ec9be68ec1ee1cb4e5b9964309d801c2bc523343c8ebc4f8393a403c7881e5928f29db14000000000000000000000000000000001423bf52daefb432162ce2bd9ef78b256ff3b24d0a84766b87119489fd56ecf6156b2884c8a7e1220e493469723cd7f8",
+ "Name": "matter_g1_add_54",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751a0000000000000000000000000000000002626f28d421d9d1c28f5e1eb5a51ada9610dbdd62cd33c4078d2fdfc18dbd092e2847cf705ba5fcd8c1a60c1cc34a3b0000000000000000000000000000000001f7b8cfdb7e406c920f5fdecae45fb4be736f209480ccb455f972c6b1a1aebdd5ba116903c46ded72ce37cd8836e871",
+ "Expected": "00000000000000000000000000000000081d674f5b9c7c64673c39fe33f4f3d77271e826dcb4dfd2591062e47c931237e8539ef9c886c9e112eccc50da4f63fd00000000000000000000000000000000141b700695839110ed4ced5f8a3f4fd64a8086805358ab4a5abd2705592e616cd95ff01271212ca9014dcb68d8157ba0",
+ "Name": "matter_g1_add_55",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df91000000000000000000000000000000000259e307eacb1bc45a13811b02a7aeaaf4dc2bb405dcd88069bb6ec1c08a78905516169bd3440a36921764df0ef3a85b000000000000000000000000000000001263372b675124f6cc19ca16842ba069c5697dbf57730875fe72c864a81189d7d16fe126b5d24953a0524f96dbac5183",
+ "Expected": "000000000000000000000000000000001908aa3a640817e31a4213156fbd4fd39ab39eb931091670a0e06399def71a689e67286f90d38ce9f97cb85f6488d9c8000000000000000000000000000000000764e46b6b82aa2f8862d28e9d543a751a9de855645377b9633cc098c2110ec6ed4fd30f0044ea5868c93f950f6cfd24",
+ "Name": "matter_g1_add_56",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c04000000000000000000000000000000000a138203c916cb8425663db3bbff37f239a5745be885784b8e035a4f40c47954c48873f6d5aa06d579e213282fe789fa0000000000000000000000000000000016897b8adbc3a3a0dccd809f7311ba1f84f76e218c58af243c0aa29a1bb150ed719191d1ced802d4372e717c1c97570a",
+ "Expected": "0000000000000000000000000000000004ad79769fd10081ebaaed9e2131de5d8738d9ef143b6d0fa6e106bd82cfd53bbc9fab08c422aa03d03896a0fb2460d0000000000000000000000000000000000bb79356c2d477dfbcb1b0e417df7cb79affbe151c1f03fa60b1372d7d82fd53b2160afdd88be1bf0e9dc99596366055",
+ "Name": "matter_g1_add_57",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e29460000000000000000000000000000000019f60f2cf585bdbc36947f760a15fa16c54cf46435cc5707def410202a3f4fa61b577ab2481e058b0345982d3e3d1666000000000000000000000000000000000a70b7bbc55e1f3e11e9eb7efd79d4e396742de48d911ddff8dd0a7cf10422423d5e68021948e1448e92c2e07c194776",
+ "Expected": "000000000000000000000000000000000a87e7e115ccdf3c2c1a2716491d449c3f8329e73d264088f4af444d43cf05f8be0410da273ce7eeb32969830195b7e70000000000000000000000000000000010a973d6e4bd85105bf311eb0dcfdc0a5d38dba1c099206b60f2e2df4791fd58846bf19d83769506e1561212920b4895",
+ "Name": "matter_g1_add_58",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d318400000000000000000000000000000000109bd6e0636a7f96ffe2ce8e109171efaacfcd60189c7050259ddedd15dd257e11f2585bbd84e4a3f4d8fc5fbc0289cf0000000000000000000000000000000019b420d778da53aed81b48f2c9b9eb399e771edd5e124a41577452b409ca2503e2798cd25d791f489352fc7b7268ae23",
+ "Expected": "00000000000000000000000000000000162bd29f2de10002c1c446bd9583e89751fb91703ad564e7951d41673e28d214729aa9b4b9875c397989df197c912d5f0000000000000000000000000000000004d393181871c93714afab6c33c16f68ec391fbfcad606ac65cc1d070949c099e21f710e2fe0dd4e4f50f99ea2167a7e",
+ "Name": "matter_g1_add_59",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae920000000000000000000000000000000012bb529b45ad7875784b62a7281d025002f15e7f86cc33555e7472df60da2cb15d37c8bf628142818c0711ee9047fb4d000000000000000000000000000000000baa801623312d95e2b51ce86373fea516007e468f265d974c2327c1779830db180bed6dbe8a64f0959aad26eaafb8d9",
+ "Expected": "0000000000000000000000000000000010c4b328d264893099d89ba81b0765d0642bf36b0ac043be090c7b4f7987d21a906228c3c208c4ec5123d577efb0771f0000000000000000000000000000000016d08ce3bf755da7d4bae5f4b06b37845c17a717329c547e941be93325a04e9a5095d3f6e6c6f9ec3b1a740f59d88919",
+ "Name": "matter_g1_add_60",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b1700000000000000000000000000000000002c9e50f37ff0db2676637be8a6275fce7948ae700df1e9e6a0861a8af942b6032cca2c3be8b8d95d4b4b36171b4b0d400000000000000000000000000000000050f1a9b2416bbda35bac9c8fdd4a91c12e7ee8e035973f79bd35e418fd88fa603761e2b36736c13f1d7a582984bd15e",
+ "Expected": "000000000000000000000000000000000f798f8d5c21cbce7e9cfcbb708c3800bf5c22773ec5b44590cdbb6f720ccddf05a9f5d5e6a51f704f7c295c291df29f000000000000000000000000000000001483903fde5a968dba6924dfac3933cd39f757e2f89120f4ca9d03aaaf9e18252bdb5c5d3939471666b8a42aeb31b4ed",
+ "Name": "matter_g1_add_61",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ec000000000000000000000000000000000332cdc97c1611c043dac5fd0014cfeaee4879fee3f1ad36cddf43d76162108e2dc71f181407171da0ceec4165bcd9760000000000000000000000000000000015b96a13732a726bad5860446a8f7e3f40458e865229bd924181aa671d16b2df2171669a3faa3977f0ee27920a2c5270",
+ "Expected": "0000000000000000000000000000000001c762175f885a8d7cb0be11866bd370c97fb50d4277ab15b5531dacd08da0145e037d82be3a46a4ee4116305b807de6000000000000000000000000000000000bb6c4065723eaf84d432c9fde8ce05f80de7fe3baed26cf9d1662939baac9320da69c7fe956acdd085f725178fe1b97",
+ "Name": "matter_g1_add_62",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c50000000000000000000000000000000003ebca978ea429eedad3a2c782816929724fc7529fbf78ea5738f2ca049aab56c1773f625df2698433d55db7f5fc8ca2000000000000000000000000000000000d2477f57b21ed471a40566f99b7c2d84ce6b82eaf83a6c87a7c21f3242959c8423d4113b7fd8449277b363303bb17b0",
+ "Expected": "00000000000000000000000000000000071dc0f985703bd8335093779de651b524c02faca5fc967766abd3f6f59176d2046d7a14d18c0b757b8c9802e44ebcd300000000000000000000000000000000154e5cb66be8979ee276e8e0f240557e3f7dc074c497293af589256652da21d66a6e6b00ca5bfa6f89963fbd5bc6cf48",
+ "Name": "matter_g1_add_63",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001461afe277bf0e1754c12a8aabbe60262758941281f23496c2eeb714f8c01fd3793faf15139ae173be6c3ff5d534d2bc00000000000000000000000000000000148ad14901be55baa302fa166e5d81cc741d67a98a7052618d77294c12aea56e2d04b7e497662debc714096c433e844e",
+ "Expected": "0000000000000000000000000000000012c4dd169f55dfb5634bc4866f7cbd110648b5392ace6042b5f64aba3278f24085227521b7834864f00d01ec9998dd6800000000000000000000000000000000102d7a495850195424677853da01d70caeb6c0af5270bcfffbc2d4252c0f3680518cd8d2a0a6dbbbc7b52923a5b26562",
+ "Name": "matter_g1_add_64",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002218b4498c91e0fe66417fe835e03c2896d858a10338e92a461c9d76bcecd66df209771ae02c7dcace119596018f83c000000000000000000000000000000001990233c0bae1c21ba9b0e18e09b03aeb3680539c2b2ef8c9a95a3e94cf6e7c344730bf7a499d0f9f1b77345926fef2d",
+ "Expected": "0000000000000000000000000000000010c50bd0f5169ebd65ee1f9cd2341fa18dd5254b33d2f7da0c644327677fe99b5d655dd5bfdb705b50d4df9cfce33d1400000000000000000000000000000000088e47ffbbc80c69ec3c5f2abe644a483f62df3e7c17aa2ff025553d1aaf3c884a44506eff069f4c41d622df84bbafa1",
+ "Name": "matter_g1_add_65",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f7000000000000000000000000000000000160e0f540d64a3cedba9cf1e97b727be716bbfa97fbf980686c86e086833dc7a3028758be237de7be488e1c1c368fe100000000000000000000000000000000108250b265bd78f5e52f14ef11515d80af71e4d201389693a5c3ef202cf9d974628421d73666ead30481547582f7abaf",
+ "Expected": "00000000000000000000000000000000168af33c85ae6e650375ed29b91218198edd9135683f6a1428211acdcbf16bdf86f0a95575e47ee0969587a10fa9f3c90000000000000000000000000000000012d9f5d692c870b3da951b6d07797c186a8ddc89b9f08a1c0b8f0f119f10ca0b155e8df5424cf48900ad3bf09ce6872a",
+ "Name": "matter_g1_add_66",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d20000000000000000000000000000000002fa19b32a825608ab46b5c681c16ae23ebefd804bb06079059e3f2c7686fe1a74c9406f8581d29ff78f39221d995bfd000000000000000000000000000000000b41ea8a18c64de43301320eaf52d923a1f1d36812c92c6e8b34420eff031e05a037eed47b9fe701fd6a03eb045f2ca7",
+ "Expected": "000000000000000000000000000000000b99587f721a490b503a973591b2bb76152919269d80347aeba85d2912b864a3f67b868c34aee834ecc8cd82ac1373db0000000000000000000000000000000007767bb0ca3047eee40b83bf14d444e63d98e9fc6c4121bdf04ea7148bcfaf3819b70dcebd9a941134e5c649da8f8d80",
+ "Name": "matter_g1_add_67",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000002a540b681a6113a54249c0bbb47faf7c79e8da746260f71fbf83e60f18c17e5d6c8a7474badafee646fe74217a86ca4000000000000000000000000000000000fe2db7736129b35dc4958ffd0de7115359857fb9480b03a751c4fceb9ae1b2b05855398badffc517ae52c67f6394e2a",
+ "Expected": "000000000000000000000000000000000bc719a8397a035fc3587d32d7ef4b4cfd63d4a5619ab78301d59659208f86df9e247e5d12650acc51a3bca3827063a900000000000000000000000000000000150d5519380a65b1909b0d84da374484675d99b00b254d03e423e634a012b286e3fe074e9b0a7bb24ff52d327249a01b",
+ "Name": "matter_g1_add_68",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e787900000000000000000000000000000000019d917eb431ce0c066f80742fe7b48f5e008cffa55ee5d02a2a585cc7a105a32bbf47bdff44f8a855ade38184a8279e0000000000000000000000000000000012ee762e29d91a4fc70bc7a2fb296a1dcdd05c90368286cca352b3d5fffc76e3b838e14ea005773c461075beddf414d8",
+ "Expected": "0000000000000000000000000000000008197403ab10f32d873974c937ef4c27fbdb0f505c4df8ac96504705d4851cf951fb0263335e477063884527b21edf160000000000000000000000000000000005396f1affa20ca8530b519a4d5d400969f0c8c8731ecc0944e8086388e89a7ff7c16d9a2a90780972c4762b88a0f0af",
+ "Name": "matter_g1_add_69",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000d280fe0b8297311751de20adf5e2d9e97f0c1bfe0cd430514cfddbafd5cdcb8c61bd8af4176cc3394f51f2de64b152400000000000000000000000000000000039f511e890187f28c7a0b2bd695ae665e89b0544c325a44b9109da52cc6908d81e1a27163a353ab275d683860c2e007",
+ "Expected": "0000000000000000000000000000000002baea63055f72646189bdd133153dd83026f95afad5ce2cffbee3f74c8d47d5480094b2b58b0936c78aa33cd9a8f72f0000000000000000000000000000000013e600456a2d76f5a760059e0ba987b881c6bc10d6161f388d7a9d8b2031921054edfec46afbd80b1364d8e8f6a5a7a2",
+ "Name": "matter_g1_add_70",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000015bad24d12b5d68558e961a17dbc3e1686e1b918e6192ebe6f3f71c925177e61d0162e018ac81126099effa0cadfa185000000000000000000000000000000000de73182569184b3d79dcfa8c27f46ec7a31fe8a3fd73fe26eec37a088461192bdbcf4d4b37b33b6177d6fde015d1631",
+ "Expected": "000000000000000000000000000000000ced641c930387432d512861eefbf2d6131017154f99a0d3d24da880dfd2aaae91c2d9634053fab8b85fc11a7884d30600000000000000000000000000000000122071c0e87fae5031c850dccc4777c3ec9d8463bbc4ed84364d4261bc9d38f696a4320d53eea926a75ed9fcc9789a07",
+ "Name": "matter_g1_add_71",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b256730000000000000000000000000000000015cdf7dafedce64aba34e1f18c57b28f297629c07ee96b732029b545cf5ea6afdf926daa6a48d1250c67aa2a8b797d370000000000000000000000000000000004867352f86267dbe8e32806e4ed02f1487e036051068f8e06d02e8dea6d3773b422e065d2db27c89ea69246d0185351",
+ "Expected": "000000000000000000000000000000000e2c633351d627a075acd1e373bec96ba41b047f0307201f4b7c9978c1a72243d0b18113604cc421b8f66d76ec9b1360000000000000000000000000000000000844e258d602bf9aaa35ce46c4c91c80dd9337053d8ab22c1163a0571fcd1488a2ef57476e2b66dd9c26963b28284d11",
+ "Name": "matter_g1_add_72",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000077eb801bcde78e9dd73b58d2429a907ea0f5600a8005093d471be373bba23ea70bf828c766ccced6a46db84b440053f00000000000000000000000000000000101af9df2939089d72e42fe2dc3de3e32be8f4526a2263ebd872d0080ed4a152107bb3d2f56176bf72d5ae8bd0c30a3f",
+ "Expected": "0000000000000000000000000000000010205c6be10a5fc5390b0e5ae47a8a822c8e9a7a96f113d081cde477ec0de7bf0e8385e61780b2335e4297edb35bcc6d000000000000000000000000000000001796af180463ed70cf330791c8201ee3f0fe52993f64819291bda33017285fcc3a515669b3d48a411276c849fa021f6f",
+ "Name": "matter_g1_add_73",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a0000000000000000000000000000000019b09bb7dddd11c5d0e304dac120b920601dd3a3505e478c88850cc701c17eb02aa7bfb20e4017a62fc4fb544d4f9e8f00000000000000000000000000000000048ad536cf89576d4cce83ef065bc16c47f1a28ae27bd71d30d8f2177a9c6f8b2ed0cdf872ead71bc5a1252bccb4a7e0",
+ "Expected": "000000000000000000000000000000000fb047098a1996a625cd19021f81ea79895e038756878d8772aaee9b6bbb66930e474dcc04579ad58f4877b742a890900000000000000000000000000000000017da74a4caefc55794a36eda7938371f42265cc1f2d87d41883152db82873daeb59642e8e663afddd4f24536a1f52b3f",
+ "Name": "matter_g1_add_74",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa30000000000000000000000000000000005f84f9afa2a4a80ea1be03770cb26ac94bec65cf9cb3412a07683df41bb267c2b561b744b34779635218527484633e30000000000000000000000000000000013ce1d1764961d1b0dff236c1f64eabec2ce5a8526edf6b0bccb9ea412e5a91880db24510435cf297fcc1b774b318b65",
+ "Expected": "000000000000000000000000000000000f4ca788dc52b7c8c0cb3419ab62c26db9fb434321fc6830837333c2bb53b9f31138eecccc3c33461297f99a810e24ad0000000000000000000000000000000006785d4f9cdf42264c00fdc4452883b9050eb56e2f6e46c7b8fc8d937dfe4d3ad5072d969a47c4811b36d3887256d0b9",
+ "Name": "matter_g1_add_75",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000f0dd7a15dfc39dc2df47cf09761498b0b363157d8443356e768567f5a6d5913c2a67f12d93df2dcf50756bb686836b100000000000000000000000000000000055914dbda5b115222e738d94fbd430440c99bcc6d2c6cf7225c77756ffadf765b2d83447d395e876b5f6134563ed914",
+ "Expected": "000000000000000000000000000000000ac0f0f62202d09cede55ca77b7344b46fd831b41015eb357cac07f0fa49c2564c2e9d5c591630226677446a9100757c000000000000000000000000000000000ca21d0128ef933fc1a48c1b4967f56912513e63a416d86ad40c0a4590b2edf88e4e8a286338b8b176d8b341ea480277",
+ "Name": "matter_g1_add_76",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb211000000000000000000000000000000000a6ff5f01a97c0f3c89ac0a460861dc9040f00693bfae22d81ea9a46b6c570436f0688ed0deef5cdcc5e2142f195b5c000000000000000000000000000000000193a17880edffe5b2ebedf0dc25e479cac3b136db9b6b24009ea0a9ca526d6dd9714d10d64c999d4334baa081b9f2fbe",
+ "Expected": "000000000000000000000000000000000b728d4ae4b45fae9a9e242524e95e44f175356726da50f46236f690eec17fdd5edce5df1253383378dc8f9c1fee98ae00000000000000000000000000000000131d28a5eab968c45ddc86b82f220dcdeab7c009c7c61986ee4e55045c024e1bcbe76a4e35000b5699ccec5858ba427e",
+ "Name": "matter_g1_add_77",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a000000000000000000000000000000000b35fcf625cde78fba1b70904acb97d7eb449d968e8013855d44292e9c3b0df3cfbcace6f292ec3c7717e25490bb4c67000000000000000000000000000000000af57abd87df55034c32dbe68bd1c0b47139fc2c3a8887b7c151e57b57c9002070337c8dcb2ce2687f9f007d48dd68c1",
+ "Expected": "00000000000000000000000000000000178a19966b5b0fa70c138be7f5ea51d5399c7b8dcc5171cbef82ecb1451aeccbd1ed29170a27f404ebf6daa2ec99bd69000000000000000000000000000000000b1b748494806175030f6b5e2977c58982bd6ec6662d69237f0521351653c772a40035f2504ac8949fb448a901379fd6",
+ "Name": "matter_g1_add_78",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b00000000000000000000000000000000177a51fcc81580ccb7a8873fa93eaf860ca8fedde13cdf3eb53f11e66a1c1e934b82ee9251f711c5c479f33a22770c47000000000000000000000000000000000a0edc9a58f4bb414aa0aeec7bfa6076fb62bdbaee987192c18855adf4e813e7103b943e1dddc24754acfa90600a5750",
+ "Expected": "0000000000000000000000000000000019195049a2d457709e284c84c72a211224efc4d7d46d25c9a537eea94149b06506df02a2a4e0a6428263e9605eaaacb500000000000000000000000000000000061139f9a70ce7cd87ed3a701163bde247382295f557b47a3a0a880d2780f015e8ac753eb3243f9ad138f92c3a2257c5",
+ "Name": "matter_g1_add_79",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d000000000000000000000000000000001552982822e0b64a6204b27da0e192873bb5bd2997784ff0b6ed53801b402501a665c17f0a379fd946ab1adfae43c6af000000000000000000000000000000000938359655fe135dd2a390f83e27273feb68387ba94f2b6f7c15389f8272d64231ebe9c8271de90ff2358d935359ba85",
+ "Expected": "00000000000000000000000000000000168f958a40e85341d90012e134976d1a5839e807948410cc0c81a50961552c052bb784c50da4c734f6aa583777c22b28000000000000000000000000000000000d26998bac6ec11bc5fcf6fe7262c984d6500cd5b21af979048b940e20054f8d759f8a011f3e09d01d10f9cf8ab150e1",
+ "Name": "matter_g1_add_80",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d50000000000000000000000000000000000d94885dcc21b0b98821b6861a4d094e9eb5d5adcf7ca4275c5b759abbf9a9910f3b38073183d54a0569ecbbc1e9826400000000000000000000000000000000034a54b4bbb3f128608a866f5f5c554cf6ad7899f6650ca663a5bd5f1a3e4471e35a2440644c0e4e0a56080936b46d12",
+ "Expected": "000000000000000000000000000000000d4734ab1bbcf9e30cf142a7aa9e8cde1b3c88d92397b8d7d48c7a7402561feee58a810abf67776e1890489efe7f8ec20000000000000000000000000000000005be9e4af0c0c183c43601339f162345f7c013f5941167cd925057e91c4641e19091a20123a36f2e803142833c0bc1ef",
+ "Name": "matter_g1_add_81",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000014f16cbb17e7f63284d8a75968a4c8fc8ee7f37233ed656d696477c507c23e7c7eaf54001f44c93deb14c298aa6f94c00000000000000000000000000000000169bde83e861889c50b2138c76531a5866235d515a6fee4da7aaf8e8b903f2848a9fe7bbd55eac7f1c58ce3a88e7249d",
+ "Expected": "000000000000000000000000000000001400f774b2d932c6b990da6e1b3493685e8f51d429e0c53e9af1b4a2d3876781b790bca4a1bc28ce0240ea21be24a2350000000000000000000000000000000004993fcf5723b7e02095d4ba73ff3194bbe36027bc9099b57084c91c7e7d50b76331bfb06d3c678d3e401bc3f7fcc577",
+ "Name": "matter_g1_add_82",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000009acc4b4678b4b645fde47d1b75a5dda8caf6696ad2bf312dd5c12d7f3ab50b95152f5fe59842650c8a1a785f345c3ab000000000000000000000000000000000b672989004fe54f4d645e40cd29a21418151134fd2b90a68185040ceff141ced7f7ece1fdd9137c32589fa04b105a0e",
+ "Expected": "000000000000000000000000000000000fcb0ab180a69b0a230d9dba98099fdce4969f82fc7e7ad93352a7c8dd448bb0ba9c7d62f53d5dc80506bc36190d9bc700000000000000000000000000000000047b7306f4a53c21d42993c50f2365486d02dac495f2dee4f8971a4af308396fce6c90f3cfde857bf7a2c6bf5d0d8aa7",
+ "Name": "matter_g1_add_83",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f6000000000000000000000000000000000198e12ade128447a240e03e024183c401d605cab1ed81f0f5bb7bc4c7cc9c889a2a01f59c0e37a0767a927719e5a95d000000000000000000000000000000001946e39fee9b76ce552108b339b9b24d11e43d3275ac19d2d4bc745c409bdc3f7c473a60c4d3a4d2cc3b598ae0d66880",
+ "Expected": "00000000000000000000000000000000050b45f896fa40099cda8b1f20ab88644915c16f926589cd709e00149b12922347fa7122175424cd44e8875f217b9ad7000000000000000000000000000000001122b7e9b1509efe5616368b14085bdd36fb7adb85cd5a7f23e327548986f5298c045a602b6ee1265d53a4432a4a3c0e",
+ "Name": "matter_g1_add_84",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac47388620000000000000000000000000000000009c48aa2681b3005b24075bb3a122ac100cbaca872f761f4398edaba9dd9da6d04d4a4925028297dfe5f77c2b0b5c821000000000000000000000000000000000ea95c646fb68aa458e69c267a6ca640a6a24d40bdca0161246e4521d13c46facfc1ac86dfc0a804cfa6665cebeec822",
+ "Expected": "0000000000000000000000000000000005325a499aec678ada9eb673d366fe0475e885d5188e2fb687a96949e8f782852fba962197976b868ec083c512bfb66b000000000000000000000000000000000c4d6fcacc8d82401882bee355b37930d83e3cea2e4a7bc133e65a3e0af919b25fc3f30c333873da9406845ce42dbb87",
+ "Name": "matter_g1_add_85",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae80000000000000000000000000000000008e8799a6cc0339e94e861692c81eee53e8a7b326523d5344b416bfbce04290585ef56018834cfd93d234bfa2943369f000000000000000000000000000000000fa1b01aab0878adad693ec769fb68640931c355b3802c51d4a3772300be5b16ceecdc8328a229b3b9f3639170db96f8",
+ "Expected": "000000000000000000000000000000000685ec14da61c48bcb697966aca9e27601db43f0fb1f32e026fb33738eecfbb7012aa1ca3acf36a21fa846730245add70000000000000000000000000000000003fc52a1c3342b12271bbc178545bb20e96e8f1fde673e51f3d27ab5cb42e60aca49c6077e0f687be59b2d25cda9718e",
+ "Name": "matter_g1_add_86",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000bb3a76287fb98fe668cb0a5de603c768340ee6b7f9f686a22da3a86926d8734d2c565c41f94f08fa3ef0e665f4ccb520000000000000000000000000000000016c02dbfb307c96d5b9c144672fe62f3e9cd78991844f246945ee484cbdef2a4c1b001a017cafb3acc57b35f7c08dc44",
+ "Expected": "00000000000000000000000000000000021796fd6ef624eed7049b8a5c50415cc86104b2367f2966eb3a9f5b7c4833b9470ef558457426f87756d526d94d8dfe000000000000000000000000000000000f492dca3f0a89102b503d7a7d5b197946348e195954d23b8ab9ab7704b3bccecaa2123b8386662f95cd4cfdbbb7a64d",
+ "Name": "matter_g1_add_87",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f00000000000000000000000000000000127420ff97df415e336cf3e24c39c161fad630c45c7ccef80f1831c4f5ed54da12f2c49a161e72bc70285fa0498e46d00000000000000000000000000000000013e605c21014f72364f8bff392ce64a10078ea537237fa282d5dd252ba1677b84b8c15d7925e54a4ab36f1feb13d3064",
+ "Expected": "000000000000000000000000000000000ae916770455b0a63717e81802f5a7fcfbcc3e260b7adeca02a61a520c338d495eea29c4f070fd6efc1b8d23eb285e4c00000000000000000000000000000000134784e092744df573ba78f7d6f3cf1ed19491a0fc7ddfa02d3ca043bcf102fd40c33ac44b03a947308e3cc7af41c2df",
+ "Name": "matter_g1_add_88",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab40000000000000000000000000000000016f41e8b098839944adc12481e5f965657a4faedd4f4cdea51a9597a6a0356989e791a686d3d2ee6232ab93683259c6b000000000000000000000000000000000d27b4a56b2cc2216e61eb41061f9a586a704652704906f7fe0eab869ba00d34205ea66f7a02d337d08b916598494e52",
+ "Expected": "0000000000000000000000000000000012842c9d7f4309f6e40124a071d317f5597de419db0d5a8e5324a517f7b61dfdeea2fb4503ad7cdd8deb8aaa5c412554000000000000000000000000000000000ace4d9f98ee6e8a4416ef14d64f26dc49e102e69eced46ef829a352e58e8c1a7e1f083e3f4fc07f24ccd1685dedf215",
+ "Name": "matter_g1_add_89",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000019e7c8d182e3b674dfa21539613f7de5d4872d4f4732307a5c6d95ada7e81a01bc25bda34e0b46634e0b0b32cd47e8ec0000000000000000000000000000000008149237de73ab46d5c20dfd85b07f593c0caf2e2e364335450e3ebb478a9f6b9ac0af89174dffd92eda2783a5271f01",
+ "Expected": "000000000000000000000000000000000875289fdaead079a283aafe4de7035c88662642b6bba389b17583f8e3b5801dada6e46bd897af961997665e6ed4a55700000000000000000000000000000000050a6b9c1db35865df0a042d27a042ff4b8d3bec2fba6a3a28a71c5a574620dc05cda0e70932ce9b8966e4592220c147",
+ "Name": "matter_g1_add_90",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a6000000000000000000000000000000000c0f33f2d76366af661d6fa58a8b5aab207d35ce03899e495f7ddccedf201d9816f270468b207413a2ca70380c798fc60000000000000000000000000000000002a7dc7e2b163e65cadf93b5d682982288c8f36d08b1db8e0b1cb40cd3c7231f3f1672da42b4679f35db2076a8de5b42",
+ "Expected": "0000000000000000000000000000000019ea92820dcd442358db359146797aa82beff6154946b1ea14dccae05e8252b776b817dc044a20764e3514cd22799c0b000000000000000000000000000000000ed929fef2cb11e8b6b9b5d52bfde82080eda747f0c82f33b9cb87019476f0c128e6b918a4486172dee2884ba538ae5d",
+ "Name": "matter_g1_add_91",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000118fb45274a6b0ca9fe2654821e3b30caa46444f7c64b1921cf16dfd56a43916947d4fb6968d718a59a30ed38d65ce3000000000000000000000000000000000110e8e73e640bbea6927cd770baaf887c8e0e0c58260bca489c39b6dd7a24ab8c0c0a2495133d8ff8c7afb9790b37faa",
+ "Expected": "0000000000000000000000000000000009452bd0a167683e30c673ffd4e750c66a81edf309a8d2d6dd915c358b30b0ffc001c4165b1b17bf157a0f966bfd91d00000000000000000000000000000000015df0b1ee359dd3e35a7b2c33edbb8e92b18804ae3359a369c6a529f5561298e6be9a3498c9477f33353124af7e91968",
+ "Name": "matter_g1_add_92",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000005dcb54cdf9635db275540c16307fc9f07b4ca5cd91e3977e4b95b58e8103e40ed9fa74752b2a43d95b6acb6f5fcbf440000000000000000000000000000000007ef8457752a47864ef2698176a53990e4822421ecf83b2716251e3ce69151ab2767d4a6611a0a6e0e40a57164ffb94e",
+ "Expected": "0000000000000000000000000000000011f1ac702a06699dd64b63ebdd8b5381578f63b603c63c3a47413fe764af239ab7024712320f3ea3daefa6bd3cd3dfe9000000000000000000000000000000000918bb83a22b4fc66247e007c17155c4c2ec6326131c10fe04a5f9b82ddeca3d21c7c397a70a3949fda4d766540c85ff",
+ "Name": "matter_g1_add_93",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c35850000000000000000000000000000000006d3335e092616363e94436bb68be89667c706564ba687f4a3494fcf7da62fd9ad8ae68cb76524926c261983711a14ad000000000000000000000000000000000f085a3d013592c402a380e2e8d9019864a775e7b8e8b94603c8cc1eb1def1e91075fd5675f76534397e2a7d76c2331e",
+ "Expected": "000000000000000000000000000000000344951ccb5e60d1838f7793fcf8b765f5f252b69e1cfdb4bd3c20692c8ffa01afbda6950974a65f6ac74afb9da5942e0000000000000000000000000000000014f5f0e6b99a04d1c5c2adf96c53dd41f8c01aab8db4f0e6d7fc5eab27f6c03c429632db4e1c21467c09d8a54066a4d3",
+ "Name": "matter_g1_add_94",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b0000000000000000000000000000000019e2ed6e9757e2339d013078fac91c966045f7a1416a56135d75e603c2021a8bebf4acbf6c0d5ba911f66510e9a7ad1a0000000000000000000000000000000008b8585444ffb3bd4fb6ee23e8128142aa72fd574a506151a0eea8979cbd694e03897caba63771b0490d46063bc5bb57",
+ "Expected": "000000000000000000000000000000000a449fb0da911c544887b24860bc5fcaaf054041cc80f16bbb44c796520bee454d0d06f84fd5aa179a44fd4fac9f144a000000000000000000000000000000000fca81401349089caaef9156a86c64271c77235c9efd136dcfad9894450b076cb3dd1a05bfa1e62ef904435eee5d2250",
+ "Name": "matter_g1_add_95",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b767f399e4ebea34fd6b6b7f32a77f4a36841a12fc79e68910a963175d28cb634eeb8dc6e0533c662223c36b728cce2000000000000000000000000000000000cb3827fd6ac2c84f24f64789adac53439b4eba89409e12fbca0917faa6b7109aa831d16ca03191a124738228095ed65000000000000000000000000000000000f4a256b4288386545957a3ba28278c0ce69a8a412febfed1f952ca13e673822bacb6b7751ea75893b680ea363aab66400000000000000000000000000000000152379d006e74798199f83b0c6c22a98440ef653d7f0a8c5e3026bcdabec8be59a3cc291ba05860bd0639c5c5f5bee26",
+ "Expected": "000000000000000000000000000000000c427721953e139d4f12ad2a3f8f91a4caa49875a87001b619c8a6e909a7da8ddd9dd026bf56d5f85d49fd17527106a800000000000000000000000000000000018add2816914ef51a289e707ba0224fcf0b7bcfa4001487e90dbdce53f1b596e1f5872de32fcee6f63bce4484ccbef7",
+ "Name": "matter_g1_add_96",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000150b75e9e9c03ada40b607f3d648bd6c40269aba3a1a992986dc005c9fde80bb1605266add0819641a0ca702d67bceed00000000000000000000000000000000083b43df032654f2dce90c8049ae4872a39f9cd860f08512930f43898e0f1e5625a5620818788797f3ca68134bc27d220000000000000000000000000000000012dae9aee13ed6ad52fe664bf7d2d0a1f134f0951d0d7ce5184e223bde164f6860967f9aaaa44fa6654d77d026c52d2a000000000000000000000000000000000f71889d64ec2f7da7319994883eb8bd1c753e6cdd3495036b630c35f07118a1bc10568c411ecbdf468a9cdaa9b4811b",
+ "Expected": "000000000000000000000000000000000275b8efb3a3e43e2a24d0cda238154520f0a2b265f168bfc502b9cd4a07b930756961ae7e4fe3f01a5473d36ce3356200000000000000000000000000000000113403d5a968f01ba127dd8ef6c8d7b783a10d039a6b69c617032eba7122e9297f3ce2360c829ae64fdc9794695bf173",
+ "Name": "matter_g1_add_97",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cba419694214e95a3605a9b748854d16c8e6e1ee151c907487d8189acfac1361b790a5e78f43593152027295adf8df400000000000000000000000000000000110813ff6e0ddf3427e2a514d3f0bfbadcaf9dbf039e0f93fb9643d1e62bc2469fe84cd9ff0d585bdd1037255bbe54850000000000000000000000000000000004e9dd69012ab596b5d3f1f8e4593b448685fcec4ab3394008178b137b762ddf9150cbb8dbb74c8af45bd8baab9a6c4f000000000000000000000000000000001132b66a2127885774062732127951f051c9c3c9b5aba02406e3f3cd4ecfe2dbf6614ebaca3bfe9efbe4f6e5b15ba0f5",
+ "Expected": "000000000000000000000000000000000594c808954bb930bd038806500c9e3fd6460a83554e945baeeec2354a3805f046c76aea62c249080f16ae8e70f8fa6b00000000000000000000000000000000046924a32fb3f2df9a52615e45eeea2fa3ac0e2ccd38458194ada6b4d993ecdc0f441e41d0ea37599254a06aef68b9ae",
+ "Name": "matter_g1_add_98",
+ "Gas": 600,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000106df8eba767e90cce0eabdaacc24d8e226c6865012ef8cb1460de5a319d443fdc6b4f4e58fb668943e0528b1809da10000000000000000000000000000000019789f464c95c179af18704c0b67b881991880f75ee7b03b9feafa3eafcd0f7d30a17fdd9cf439ff7fe683adca2083b50000000000000000000000000000000017a81b957a12adf474a2913e8636f169ea9cd10be62c16b88f95f5caf661f158a032a9f7d249fdf2765caa1564bed0570000000000000000000000000000000017fbf2abc62dc2678b65d509e19c9c9c5d961c72565649a078da8dff98be6236ef314e9ff8022f639ff565353345c230",
+ "Expected": "00000000000000000000000000000000002c8bc5f39b2c9fea01372429e92a9c945fad152da67174f4e478fdead734d50f6e2da867c235f1f2f11bdfee67d2a7000000000000000000000000000000000c1dd27aad9f5d48c4824da3071daedf0c7a0e2a0b0ed39c50c9d25e61334a9c96765e049542ccaa00e0eccb316eec08",
+ "Name": "matter_g1_add_99",
+ "Gas": 600,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsG1Mul.json b/x/evm/core/vm/testdata/precompiles/blsG1Mul.json
new file mode 100644
index 00000000..0e166a29
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsG1Mul.json
@@ -0,0 +1,730 @@
+[
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g1mul_(0*g1=inf)",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g1mul_(x*inf=inf)",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g1mul_(1*g1=g1)",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000011",
+ "Expected": "000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436",
+ "Name": "bls_g1mul_(17*g1)",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992feeb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e",
+ "Expected": "000000000000000000000000000000000f1f230329be03ac700ba718bc43c8ee59a4b2d1e20c7de95b22df14e7867eae4658ed2f2dfed4f775d4dcedb4235cf00000000000000000000000000000000012924104fdb82fb074cfc868bdd22012694b5bae2c0141851a5d6a97d8bc6f22ecb2f6ddec18cba6483f2e73faa5b942",
+ "Name": "matter_g1_mul_0",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed24d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d",
+ "Expected": "00000000000000000000000000000000195592b927f3f1783a0c7b5117702cb09fa4f95bb2d35aa2a70fe89ba84aa4f385bdb2bfd4e1aaffbb0bfa002ac0e51b000000000000000000000000000000000607f070f4ae567633d019a63d0411a07d767bd7b6fe258c3ba1e720279e94c31f23166b806eabdb830bb632b003ca8b",
+ "Name": "matter_g1_mul_1",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be1",
+ "Expected": "0000000000000000000000000000000014f9bc24d65e3a2d046dbae935781596fb277359ba785808fd9ff7fd135ba8c1ddc27d97a16cc844427afbf4f8fc75a60000000000000000000000000000000017e3a485f84e2f2bdcf3255fe939945abe60dca5e0ae55eae9675dcc8d73e06d00b440a27ab4dc21c37f0bd492d70cf4",
+ "Name": "matter_g1_mul_2",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e44c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a",
+ "Expected": "000000000000000000000000000000000827517654873d535010e589eaf22f646cf7626144ca04738286de1f1d345342d5ae0eab9cd37ced9a3db90e569301720000000000000000000000000000000002a474c2443d71b0231d2b2b874a6aeac0452dd75da88e6f27949edafc7d094cb1577a79f4e643db42edcaecc17d66da",
+ "Name": "matter_g1_mul_3",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d38964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b89",
+ "Expected": "000000000000000000000000000000000d7e5794c88c549970383454d98f9b7cebb7fdf8545256f1a5e42a61aa1d61193f02075dc6314b650da14f3776da6ead0000000000000000000000000000000002054faff236d38d2307aa6cbbc696d50f5b3ffead1be2df97a05ebbcbc9e02eaf153f311a1e141eb95d411c0ec6e981",
+ "Name": "matter_g1_mul_4",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f90787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c944",
+ "Expected": "000000000000000000000000000000000ff16ff83b45eae09d858f8fe443c3f0e0b7418a87ac27bb00f7eea343d20a4a7f5c0fcc56da9b792fe12bd38d0d43c600000000000000000000000000000000042a815a4a5dca00bd1791889491c882a21f0fe0a53809d83740407455cf9c980c5547961f9ebe61871a4896dace7fbd",
+ "Name": "matter_g1_mul_5",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1baaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e1",
+ "Expected": "0000000000000000000000000000000009e425f5bdc7df5c2a72303918e5a3c7d2fdeeb071179c533f83cdcf38dbbdb1ec5f4ebc85f3ed80757641ee3f8a8637000000000000000000000000000000000819a3e81e9ac2baacdc778225129e16344107517157ab2a7bc5e3480938585c55fd2dd7185f52251f5ab191f162cf5d",
+ "Name": "matter_g1_mul_6",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442adac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c",
+ "Expected": "0000000000000000000000000000000015e6bea7ecf15d91bde67231f794397502c087960fab36d905137ce2608172b5a5def065cf7ee567ca7fb08a22adecf80000000000000000000000000000000001eed472d6138fbc56e10edb62563c086fdeb9acf6de957f2367db7f1c80d2c23197c09039ed55e65cb56de9fb9be64d",
+ "Name": "matter_g1_mul_7",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795bb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd108",
+ "Expected": "000000000000000000000000000000000220a71ad70fcf7e47df60381fbd1aba33c03a3f8537ba2029ad8e99b63c8677e0183f0b5bb2a5e1b23bc56693adb45c0000000000000000000000000000000017f26ac6ffc79ded7c08e08673336402f47ab48ef9ee2e46e3265e5cbb790cfc86f41bd1b578c5891eb052d11197c850",
+ "Name": "matter_g1_mul_8",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a190fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f8187672",
+ "Expected": "0000000000000000000000000000000006b27724c4898b4f71be9727b773709a7905997d06a41ee618b7dcf864d7457bb3241046f0139c1d678b6ba6226f090f000000000000000000000000000000000b20cabf58f9c29897e20e91a9b482f5f867bef45ce0941cb8850aaa2022182298a1a24655a4b905f436520cc42a30cd",
+ "Name": "matter_g1_mul_9",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac943b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea",
+ "Expected": "0000000000000000000000000000000004745f9877b3a0851df5bb770a54c69d5355cdadddc9d961e2bfdb3d0531d3d0f780f462335289be29ad4c62cb1250a00000000000000000000000000000000011034a094f59212c29e3f91c48df670e7a4021e4586645d250ee74a90f4b7b51510a5048dba3b555511c327ed211f81f",
+ "Name": "matter_g1_mul_10",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e3b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c76",
+ "Expected": "000000000000000000000000000000000841c1538c1a3b54418c1c5557a5815c9ed74f6e1c8ed70e1ad424220dc522c530e2e48affe6cb3190abb25af84b91a300000000000000000000000000000000167490a2aa6c8796736cbd364a4d18007ecfee403bde5dc13c611a214610e85af314ddddbf05ea129e027e0ae8d89b36",
+ "Name": "matter_g1_mul_11",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276bdd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c",
+ "Expected": "000000000000000000000000000000000ea1f952d65dbb9a40209aa89e367d9d75e1b4c3a70a609efda5fbe7f5c5483163671da425545d3f1afb817c6d8c59a0000000000000000000000000000000000cd537dc11cc63dd15c8ff74d15961390eaee59b2d5697b18c1ea6d534d71551f5e195e8a0793140d821dde97dc77623",
+ "Name": "matter_g1_mul_12",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a57876817010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a",
+ "Expected": "0000000000000000000000000000000004c92b7cf9199f47008dd561e624c822a067c57fdea9d016f79e6c7956dda9df0e36b4e78715f3da1319af9f4f1fb160000000000000000000000000000000000d2851d68617567ad5308f69dc5dbbf37603c2ba48cb3759b70fc4301fdce3bdc9fca076e2ae09562396c1b8558ccdcc",
+ "Name": "matter_g1_mul_13",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f76894c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a659054",
+ "Expected": "0000000000000000000000000000000006ed98add25d64f7488ed270e0899ee3633c84b73de26557c552017e7cda4cba1228c15e87efb5a740284dddb8cc80de000000000000000000000000000000000b363e14b0285fbd24eaacfe80b992d8df1abfe83991cc55b0484076385374bc87d9c7860177f06143c600503ac54577",
+ "Name": "matter_g1_mul_14",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931db3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746",
+ "Expected": "00000000000000000000000000000000164671460621354cd352d93ca7de51828b3e6db0a37d2894a0ac475a5facdbc3ca5909d3bd7553271dadaa68b7474e2c00000000000000000000000000000000188827c6e2f4e9796c71703ba53ba2ded71bd6e8280e047fb6ea440b8dcafa7c4252d26bee1780ac67790e0d603c8ca7",
+ "Name": "matter_g1_mul_15",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d507f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf",
+ "Expected": "00000000000000000000000000000000023b2129ac67abc79966102ba223b982d40ca83e9b1ce33dff681c751b3f0c692f8bf19fa0394eae190767899829d1d10000000000000000000000000000000015449c6b5ee2c9f8b28e9732c9ebf6ffee5048263f7b5050a5ac9a76b034931a5c034f91d24b461636f5b116e37a26a5",
+ "Name": "matter_g1_mul_16",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da",
+ "Expected": "0000000000000000000000000000000004edac7b03b5861d178bb4aa34e795c776fd95e7c0980f19d111ef208ca4854f73a3ddc219bb6bca173dec67b0e863a00000000000000000000000000000000004dbff672368f86e048c3e33cbe90aba570484b4ca2221f7f6adaa1738c369f4c02c0a10118e84ea8e53cfbaa10fa48b",
+ "Name": "matter_g1_mul_17",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb6e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed833",
+ "Expected": "00000000000000000000000000000000169d637c52c31e4c62c9563a508869f7bb5adc7defedb5f4ba9f3eabe517fa8c0be2e44d656e50903dcab67a6a44984d00000000000000000000000000000000192b39d5cddac36940d896a738e25c25217768e1d0ca712968718b8fd9ad492bae63063b3cb168368c3df196306b6a1e",
+ "Name": "matter_g1_mul_18",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154bd411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f",
+ "Expected": "000000000000000000000000000000001608c3bfb131eae485545b7d19b8f42de18dcea6a0db3279eac2b7c008fbead54046bf13dd63835abe9c63110e12526c000000000000000000000000000000000abb41b2f17cfcc2292c5bf559b38af3b25db40121c6a5627997f65765eee1743c204f1161abe3f71ac1fe4de6aec1d7",
+ "Name": "matter_g1_mul_19",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af6bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc",
+ "Expected": "0000000000000000000000000000000016e3125ae97a2b1184e2c6dfe5d9459ac567c686e65674f3b0513df6de5e80d1efbff3c254e509eec3f951b0835b5829000000000000000000000000000000001889481258d3e898ed4e4a43e74c0eda5ba26c0b7525973ca86b896969240ac5928ba58bc86ec17a47f2469d023682dc",
+ "Name": "matter_g1_mul_20",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719292a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c52",
+ "Expected": "0000000000000000000000000000000017d8c0aa81ca6a1e4de8d0b8b3a13b1d6350f79ee8439da97a5d564d435f4d40bde99138b67284beffbb176daee92352000000000000000000000000000000000a04e0bee6b9681db56604a6dd5e41c072e84f8ee9cb4054410eb610472b96c09802a1d70e325c40c7ab7e248eb2e3e4",
+ "Name": "matter_g1_mul_21",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b1",
+ "Expected": "00000000000000000000000000000000089ae9fc5cdba1a24ca87fe4f1207d1a36c494d842eed330069f988d3bc8554af1deee3a5c59b5e74729097acc1185fb00000000000000000000000000000000002fd95001da3011b48067d351ec8667c2b2390b23fa0948896725292311dbae71b51d6d5d57e173970bc992d11fdd11",
+ "Name": "matter_g1_mul_22",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff327064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e9",
+ "Expected": "000000000000000000000000000000000548e7564e09c2bad9859dd63dd1045878c9b257015558b18cf5911d1763325e411c1fb8af52e8766fa7adae83eea12700000000000000000000000000000000111235351d136905fd19fa726eb6626085875c33c98067a01fde9688a5b2c289cb8e3f5d6a85d0829200a355c82f423e",
+ "Name": "matter_g1_mul_23",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f2686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b",
+ "Expected": "00000000000000000000000000000000165504769c7ab0d28b39f38f3bd09cd47c63b74c57d39935d1c03e262f9da0e8b0b9264b0d8e2908423fe5c74288c208000000000000000000000000000000001680df1d577bbbb66ffa10258bca54b74cd90a7b3f3d50472e70e18ef54b7a4412e9eb93e39b9b312e3e8e00a52e4067",
+ "Name": "matter_g1_mul_24",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c23176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a6",
+ "Expected": "00000000000000000000000000000000087a52e8eadd5461e202a640024fa17e201a9f0a2984be3fecfdeef86abed72d059e8879d0be8789f2a6db0d2cf55d3400000000000000000000000000000000196fe307db05207661a5a5f8f7fb24d8fea18ef91941ea7febbc18819f49f73aef9dd1bdf4fd605e031dc04f16fa92e3",
+ "Name": "matter_g1_mul_25",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd1d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36",
+ "Expected": "000000000000000000000000000000000301caf675cd5359bcc274b6141bb6ac53ab6a86a38ad4f8c3233cc9c1a77723eb0de4a2014e556185947dc1ef6624e3000000000000000000000000000000000136d286e623637f12c8b86cd9fad2bed8479ace5189e064a4e12e6e641447dfb0399757026126ad2d169c05011f5031",
+ "Name": "matter_g1_mul_26",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc9915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc",
+ "Expected": "0000000000000000000000000000000004ce73cde58c9af5d1f76e100849b0ba3d3cc6491e76b39cf4d7b681fed0686396440f6a721f73b31fb14b4c7624c176000000000000000000000000000000000e26b15c1051d7b049e82476a30545cfa4bf0a2075681d7028797c528712c7fba7a59145c9dd9ca9f5e9b1ac8a68b126",
+ "Name": "matter_g1_mul_27",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da05061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b208792",
+ "Expected": "00000000000000000000000000000000028a89c904f63eb8e68096bd2001458a4b9b32556c93fab5e52ab26ed73d62f0489d6bf1906a62c8148d50d30222a65f0000000000000000000000000000000007e54f21e2ac6d5287289ed9e2a15d457b5dac22ef36c19cb28a6cf9a0d11c981bf6549ddaf7ddc0a59b3d3a4698d975",
+ "Name": "matter_g1_mul_28",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e053f396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c",
+ "Expected": "0000000000000000000000000000000008c39ee7c8d86a56ad1a9dbe005b4f0d44849d6fea6bbeb0732de725ad561befd49d465a134bd1a63a39eadbb6e0bce1000000000000000000000000000000000d5c892c92817fa24afb0a0fb319ad21e309edfb6300397a215e34eb3aadf91cb41b4ab1c5273bfea6eaf33982c75eba",
+ "Name": "matter_g1_mul_29",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265ef0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa",
+ "Expected": "000000000000000000000000000000000ba1650840e24c0f99ddd10a6c3341661e5c96b2e95cb6bda3340e7a0167c906e2f0ccbac6f0be2d7dbb3f9370a5ec960000000000000000000000000000000011638a3d9a81c0fe2ebb547808db758c7cfa8648b4835fb8c4931fd622da3a001fbce9a21d61f98f35b1e907913ffd25",
+ "Name": "matter_g1_mul_30",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc8915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c",
+ "Expected": "0000000000000000000000000000000000eccc25cfd8c5a58b330a74b92af0c2b932772eacfe898ff3d391fad5dfba52a3940e8edfc9bef5c4de670207c8585100000000000000000000000000000000095ae48a94c92c332915b0c07511bb0d54c316ff3a0dd2509a18a21320b506bbefa76a459260efdf4c045404f02e114d",
+ "Name": "matter_g1_mul_31",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff17d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd",
+ "Expected": "0000000000000000000000000000000017a7f3b439a98885994a6832b6394b0ec9968f665b5810da58e3ece3d8e8694c482a15d3129732b43d4b7008660f19c000000000000000000000000000000000195299086d3b9448b26fe830522d520d132ed59744e677e6eb114ba7d7045019a0d0386cf817701ca3afad2a0487a689",
+ "Name": "matter_g1_mul_32",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3fc00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc45",
+ "Expected": "00000000000000000000000000000000063c123a3cdb92469e7e57a18eaf3e7cab1d85d64cbcb52499d2e611e6ba71c717b0ebaf4cc9208b18c925a5ec167b78000000000000000000000000000000000fa5e78ae10ed8a4dee9440bfc7637d903404749681f85bcb62444d921c4fd809a646ffe3bb7c70dc906d07c62381415",
+ "Name": "matter_g1_mul_33",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9aff661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b",
+ "Expected": "00000000000000000000000000000000192b1497c71eb894a7509bbdaf308428e4d5899edb15f9e6e45a88340f55e1b76ee0901a830b66114deccda63a913a6b0000000000000000000000000000000017d58bd474a61ca0ceb23ec392dc08abe5697b8394fd60440cf787f15cddab36aa99c2ec2341bcc06dc1771b5f0fa139",
+ "Name": "matter_g1_mul_34",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c3346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca",
+ "Expected": "0000000000000000000000000000000015f72ad769cbaa2bbce0aecef9559b825ba4ec17ec5be2d9f0dbc7184383eb3e201de5163e71f1e71655acd5ee1fb30000000000000000000000000000000000194d27d9045b9760e66b578af24b282d9aeb28eb51206d2e18dc04bcb6df90553a846736afd92b23aa004f8de90bbf9f",
+ "Name": "matter_g1_mul_35",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db39a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc",
+ "Expected": "00000000000000000000000000000000146f12001844bb0ec185e773175634f2e56bfa7190caa851ad16443b629b375ce3967b0c936d30dac2f126343722ce5e00000000000000000000000000000000080e8e90ed0d259ad803269711e511577769f7886b425f9b7857dc90ab36438cbd7435f6eecf2328f5fb6eb56f370163",
+ "Name": "matter_g1_mul_36",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218082c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447",
+ "Expected": "000000000000000000000000000000001344d2c2bc5ef45dc69597e948ed6021d84f7bf2c36119869a3f84288f3bdd6fc3a0de2b9e2564a930c2207c1ee36a0e000000000000000000000000000000000dc4d15ae09642ffa17d77510fb1ad4bf9e06084e9d352f4e234ea35f33458df4f23a209e29da42c41fb9a3cec3e8242",
+ "Name": "matter_g1_mul_37",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d4828",
+ "Expected": "00000000000000000000000000000000084f2ed8573d5d04e41909d5c8ed3feb88f572726fc86d17d466276342f01503f7c8552498f8a7e96c875c4928b808f2000000000000000000000000000000000b618ca81b6ee891690099459634e011b5f59fb5c96488b0205139a65c77f15af135b3528a5ca3b794e7b2991d2434d6",
+ "Name": "matter_g1_mul_38",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcbd4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a",
+ "Expected": "0000000000000000000000000000000014733ee8425f42a30010366e4585cbbbdde6ed602a639bd299e63c113db3d797fa01075e24a042a060a043c9e1fa79f40000000000000000000000000000000013b44e1932681d238c52e959e1e3daa7a2e1ac67252ebea0cae90e8249f85b61812b9e09203d38d96f4916837b3693c8",
+ "Name": "matter_g1_mul_39",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6341776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb",
+ "Expected": "000000000000000000000000000000000ba15476a1346fbe9be2720721b592ce7c111b95f0b8738495e6c28487e12fcad60006314dfe68789e60f4df2db14eec000000000000000000000000000000000b44b9a9f695c94ad206717daa3128b672924d0db83ae0d47b62b3c79428f6fe151a65a39ae411e18b128d6796b67bbc",
+ "Name": "matter_g1_mul_40",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c425",
+ "Expected": "00000000000000000000000000000000070dfc697f7068180a7a792604d7b8453dbd393c993be9829a263ad5864c3575d3fb235692ab12a4dfa4221bc6e0c6d600000000000000000000000000000000123a9d9b83e2ca7c95de9602116b1e14d48175073e1fe766458e3fd4b6676f120adfcc5c497febe2f7ff68b1e3508e3c",
+ "Name": "matter_g1_mul_41",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f0e7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96",
+ "Expected": "000000000000000000000000000000000dcad6e29cda2332dff09377460c7a2b9d908ee53ab13f648cd892bf68a44ffcc8cd5d501f8b068f506b506d01d3f4430000000000000000000000000000000003aa625a60932474ca3f914a3e0aa8384533723f824b12c686a64863a734d96ba13670c8b355b52b0c01b49fbffb6149",
+ "Name": "matter_g1_mul_42",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5ec26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc",
+ "Expected": "00000000000000000000000000000000023909bac6048bff0373d27a06dbbb8aba8ddbada93f4fea65c983598307f3c3a8cbe163462484ebb88165c6b6da41590000000000000000000000000000000002162d8a498670158c23daebb724168b5379d9124b064de871674a3ecd15e6b546366287563928a1e279fb1eb2ea0ba4",
+ "Name": "matter_g1_mul_43",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79bba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca",
+ "Expected": "000000000000000000000000000000000f79050036c4bb6c6b8e91abb300dc49a75b32faaaeb258661c905b4d936f4096d59de89b911de294603a0e3443fada5000000000000000000000000000000000985105497cd87d5ae2698479da55f6be9bc2cf5a2093b651d7305b67e36343debaf19c266ccb55c23f3de55bdae23a6",
+ "Name": "matter_g1_mul_44",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e820705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a",
+ "Expected": "0000000000000000000000000000000017901e77745a98c09d6740597c40f27df841cca6dd95653a1da6d8eb1c57d5ebffa6a7b894369b6b419c61462697080b0000000000000000000000000000000001732540a1bfa4a1a851106209ce4807d7c0a33816d3742ad5e2729229f3403940e03b93121b79bb94c24f7e60539ece",
+ "Name": "matter_g1_mul_45",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b81158f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa4",
+ "Expected": "000000000000000000000000000000000f990d646495fff77d090f4a69b8af0e1762982b53ef8ae9bb955ad8b894942b85c7726587c9fd956ad58eb9e3ca25630000000000000000000000000000000007b7315e1f93cfba8076cf539aae01fd3bbe1cf92daa168a6fd6a2e7c969d35c51fe7eba04f1e0dd3e2020635f2c4f09",
+ "Name": "matter_g1_mul_46",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556",
+ "Expected": "000000000000000000000000000000000de9d7e58919ba6386f32af53ccf36cb0b834855ac8dcc19af3c3c9522c3db2985e51ba36067b61181cb0fe8b47d853a0000000000000000000000000000000010ff0800ed1b4067f8c920462f7abd7361dac2371716f7b8648d64a71cc7d53265db6d80b26b9efddd572a2273ab1b17",
+ "Name": "matter_g1_mul_47",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe9a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac7",
+ "Expected": "0000000000000000000000000000000011a11cc098144fe9bd42ec8845be76b6cae4b3001a79f4bbbf9f20e8ac8bca5b37ef8006c958318c3894aac7d6bf77e8000000000000000000000000000000000d5c1e6b78c40a356a35bfabfd66a81924d2eae6d428b5caacf8f3992ab980640e857e756e649ca83f5aa4bda7cd00b7",
+ "Name": "matter_g1_mul_48",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193ab473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602",
+ "Expected": "0000000000000000000000000000000002e72f4568780fb41858edc3f5796f7936a30ee9ddc7b5034d9341614d301c7906238bfde3bcb77f063fe652a43b88270000000000000000000000000000000006f971f4a8ac554df7ae7ecdfab724410f1948af994d760c5f5977961f891ba4f4e76b27c3f0e5a1471ad017e91a9af7",
+ "Name": "matter_g1_mul_49",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c013",
+ "Expected": "0000000000000000000000000000000014b9ef8878af80f824748389d608bc9d0ffbca96230ed590d8e351586607a614f2658e348ac172f3184c1e5fde50f550000000000000000000000000000000000630f0556407c140d0a05b10ea65de48e4866e040455ebcd54fb6ed6996a6a3ac7a94a6818ba424936fa505c2c364124",
+ "Name": "matter_g1_mul_50",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10ca9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc8",
+ "Expected": "000000000000000000000000000000000e66c8be115a941ef7adf4490faea39149a3d812c29d4afb36febe3f813c7390a715f838dda90cd73556f89abf3949120000000000000000000000000000000015d85c185cb86af3ca1c526ffa6e9459a9c699c5a4d57278f33b14691e980e0f86b9239e626fc4064890cb610f10e496",
+ "Name": "matter_g1_mul_51",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bff228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b",
+ "Expected": "0000000000000000000000000000000009db6ac72cdcf1f69c6593bc183aaa2b3980ff78a4417e23243f81243987ec6f2636641c9e9c738c7af2a1e9f94149d0000000000000000000000000000000000ca7537c04c06607e42403e84e7d9e55b2a06c730ec342f16d03689bb684918e85f637e7a6279d95cb7774f106139d0f",
+ "Name": "matter_g1_mul_52",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b29431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb511244",
+ "Expected": "000000000000000000000000000000000620b092ea8cb718ae9669da4ff2faf639fb5e657b7759fdf292e6d841b51545afbabf95a98601847f64fc7367f872ff000000000000000000000000000000000a14bfc0e328310d62f116652b1de3a18282b122e0e3965619a099466986a546b73696274e12bd395224018a48b3d80d",
+ "Name": "matter_g1_mul_53",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b2051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d83",
+ "Expected": "000000000000000000000000000000000a633928be3f3bb4c94cf4d8d7a8169779f8bd4bad31ede895937e8e8b0ddea956d255776141541ef5791aa3a0bc6d360000000000000000000000000000000003dc3b703753a7b8ccf7676b04cac8021aa311233a99e8d5290655d2f84555dedff62f9f81322307b538c3f3458f6313",
+ "Name": "matter_g1_mul_54",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751ab96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f852",
+ "Expected": "0000000000000000000000000000000014911a8b41cb65cb7ccb940a472cfa58861f1a506a4f719888eb35d48ed9774ea0a0dc3ba38760253bedb4a1acd0963a00000000000000000000000000000000031388c90440f22cc63a1e9450256e5cfcf2f7448641ac66b43d542c4b77e9c590b957efdb1c6d75846b3faccf033276",
+ "Name": "matter_g1_mul_55",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df9178176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c",
+ "Expected": "000000000000000000000000000000001968070c01f0aeeb42ab71730f5b78ec122c10ca9dac1764ff5e916fc85a5eb5ed406c03263c57858fb03b15ac0035550000000000000000000000000000000012ecfee330e1cc8006c73e9d41ac1947b67f8704d12faf8c0c05c2519dca68be7bdf88a58eb4825b35a1d270554d6ce9",
+ "Name": "matter_g1_mul_56",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c049c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da0",
+ "Expected": "000000000000000000000000000000001469e7ab4c3740701927da2b0e34508a73387aea671857b042dabbc65cb849f8c8ed0b7f8c8e37f80aeee98ba953f4e4000000000000000000000000000000000674212f9f8e1419608ccf1a0447533fbd6fda87a35cb9fb39c8a7daf5d12f450c12bfac9e9f872b2643b1f8f201439a",
+ "Name": "matter_g1_mul_57",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e29462ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd45",
+ "Expected": "0000000000000000000000000000000009c756aec59a68832728b1133a69f0794f6a082e2f0f161e488078bec7420a0da19e812def625df9b12aa36d94d8a38600000000000000000000000000000000014aa28b18771ca07b7627446eb60d53bf4837541da661a0e5cadcfeaf58f5a650a39ac304f48e45d9b714cead9ba5d2",
+ "Name": "matter_g1_mul_58",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d3184fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f",
+ "Expected": "00000000000000000000000000000000153548fb1d7f1721c7fbdfeb167e1c060a90aab8f7b6572f4a2707de91b03a7b5e68f792a18d940167ae83d1380d6653000000000000000000000000000000000113bb747eab3987cd195e9eb755735698993332d517890f4e3285bf7274f8579ffcf84908a4758f0bb932021f2c76d6",
+ "Name": "matter_g1_mul_59",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae928a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d",
+ "Expected": "0000000000000000000000000000000014ca98181489c96227f8052a77730ab446615cb7b2b00a600cdd7defe8b3ee1cd53a6d98892ffccda5fd4916e0cf5886000000000000000000000000000000001567c3207cbd42c0445ea96b464dbd9099b85f5df1932d152436c936623d92fdeb009e69919368134501fa9363a0b1c4",
+ "Name": "matter_g1_mul_60",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b170d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a",
+ "Expected": "00000000000000000000000000000000139d093364c313d400603dba5a79479d566245a397f88aae748e110e09e7ab6dd271b8c37a90b86f6b48490ec1d0d8f3000000000000000000000000000000001099d4cb400f2d786dd2dd5d162580d2113c8405f51e8a619a6894d86a7f7ceb237289808acffa274069c24ee27c860c",
+ "Name": "matter_g1_mul_61",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ecdbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad997",
+ "Expected": "000000000000000000000000000000001247d4d3b1625ffccd350a9fc9759295637e91d9167d9bc72bbc1b60b1abb71dc29595b49ee1edc778f5219416bcd0cf000000000000000000000000000000000dfc69cdd0e4e126208b76a4e5fb8d032ae93031dde7da9bb1358507d4480881576c5d7cb7f0b3fa3032c0151650f2da",
+ "Name": "matter_g1_mul_62",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a",
+ "Expected": "000000000000000000000000000000000150849c60273de83f9ce2016238c273359ecf486adeacc4450e1d1a6cb79fc0d0fb38974489375d5763da8a5f4e743e00000000000000000000000000000000157ec6c2dd68dc5fb3cef4e935fedb74e1f0e856f1d75890bf995a08ed6b53b52e2e0d412ae190365b139101e7fe040f",
+ "Name": "matter_g1_mul_63",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d",
+ "Expected": "00000000000000000000000000000000024b59fbec5240fbdf3fb4e565bbec20f26edbc2a1bf7ecaaeb5278ed9fe13d1e360fa298e2d3f9b2880b00aff827f620000000000000000000000000000000013ca56975d9fd667bab347ed67fb96a433d57836ca4069976e12459152e1369154bd095a15980880e21fd02b1d7e3156",
+ "Name": "matter_g1_mul_64",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e3616",
+ "Expected": "000000000000000000000000000000000aaff66eca5ddce81533afa27e2db1c25a2c6f0dc1dd7c2236d4c89cb9d2539e109cd1362dbfee86397156c3703d44e60000000000000000000000000000000013598d8ef4470998aec290e941576f5e94d696f7f0be40e3131b516a1679c5b0eba74dc9ae00ecb8f115e4613a50f3bb",
+ "Name": "matter_g1_mul_65",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f7a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af",
+ "Expected": "00000000000000000000000000000000163cf5475fae000c38e59754cd29f1290ab2d6550552e9186555d1ce2960b7dca5834e0347699d2869b8c9bc42f6f717000000000000000000000000000000000b21bd3bfe50e0536135a910359527f80c130a08029c24f990c82f02727def21973a20a2021c95aaa3a7c8a980b44f33",
+ "Name": "matter_g1_mul_66",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d245111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d145",
+ "Expected": "000000000000000000000000000000000bc3667c38602e7e1c018cc62933c013a9e78c375b50ba06f0c3d34fead5ec8a9658702a0856625a712520ac99afde230000000000000000000000000000000015c6b5487a52b41ae1a4634c8675f7b847aa5d319ee9eec0c92fc06d8e92e1cacc90ee394f8c90ce3e2c00307f53dec6",
+ "Name": "matter_g1_mul_67",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531fc07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a",
+ "Expected": "000000000000000000000000000000001358e1724cb3ec4028a63e4252eff164defaa41b21042037ea9a1e06bc1a0a1e838afc1965ee665de3da0163d22682420000000000000000000000000000000019828e11831e3e4216d843ed3446345edb357b2082b7947fe71932dfd894543928ddddd8649d32b4f1349f63f60bf095",
+ "Name": "matter_g1_mul_68",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e787929b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd0",
+ "Expected": "00000000000000000000000000000000130e09c096ce8ba86ae71a817426d929c7f9f8bfe00e76668b0041e935d1531d6f58e5eb743df3cf86fe88bdfda8c8a300000000000000000000000000000000187b25d8216fa3851bb6fbace998bf3f23dea80dd6e1cd94bb6a72d335702694804c6ef3d350519c5e781f941bb72f92",
+ "Name": "matter_g1_mul_69",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a63d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf54258",
+ "Expected": "0000000000000000000000000000000011e61e5158d9a7c59a5007732a76e27d14602e15159e8f62bd13be8b44c96736af5a77495c3da55c8244af6e60eb4f2c0000000000000000000000000000000008deda8447009898c89c6766e8add105892992585724d520c38d0d4f8c833f88d8c331e11b291b6def6847bfa9629d2b",
+ "Name": "matter_g1_mul_70",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f57a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e",
+ "Expected": "000000000000000000000000000000001182f2e45f06a729f82442ddb372f2eb8dbfccf12edd8df0764072c9f14cbe001893d932e89b948a643981ea8aa4fa41000000000000000000000000000000000910335dbdbef74b844a6f3b879d14c23c711ff2362213636ddab7eb1a44cd4b687659f8dd521c134b56bc4eed0ec5bc",
+ "Name": "matter_g1_mul_71",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567381b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83",
+ "Expected": "0000000000000000000000000000000019576d68ce66218d4c9e2e6fa9985451eea46ce60b11a74cf5ea9dbb9d0e8741d11436dfd77b0a8b490f4882cc5b416b00000000000000000000000000000000088ba5153e91738f7524034a2609848652a7e416fc68537ab2c16b6699f69695c62e5724dfda2f3b4f90277f5005bfa7",
+ "Name": "matter_g1_mul_72",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc3ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de07",
+ "Expected": "0000000000000000000000000000000005720fd4bff4da704edb7e317e3d41f1d1f45e3c1f22c1b98ee0b6875af414f6f58793e8ffd5c89bcec2af711973ca1600000000000000000000000000000000051441e34eed472766186a44b2028d86eebadd597cb7e3fa4f935d30aa043f11fb18670b31f0a3b8aa23bc8f05361064",
+ "Name": "matter_g1_mul_73",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b6",
+ "Expected": "00000000000000000000000000000000141a0eb238edd1cdb670737d94f658fef728691620f9c6d98e34ed8bd166b38ae6912b5bd90ea21b091766ad27d689480000000000000000000000000000000002d0e7d2584586ab2f08cbd419df3defab53a287ca467b6b081e474711a23608831c1507bac4f328750731b99a06c6da",
+ "Name": "matter_g1_mul_74",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa3ac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c79659",
+ "Expected": "000000000000000000000000000000001227b7021e9d3dc8bcbf5b346fc503f7f8576965769c5e22bb70056eef03c84b8c80290ae9ce20345770290c55549bce00000000000000000000000000000000188ddbbfb4ad2d34a8d3dc0ec92b70b63caa73ad7dea0cc9740bac2309b4bb11107912bd086379746e9a9bcd26d4db58",
+ "Name": "matter_g1_mul_75",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c88586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d",
+ "Expected": "00000000000000000000000000000000187cb196679b6baf78a7908c37d7f31a9fcefa90b7cf165d0748a358e6dd86fc5c2d91ff1c4429a563b5962b821cbb01000000000000000000000000000000000d94711dc6efed34385579532f59964ab18b9debeac96044f3eec14cb36965f380d21d39c246e972aa2d5891ce417e9f",
+ "Name": "matter_g1_mul_76",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb2116e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712",
+ "Expected": "000000000000000000000000000000001405c27eb28f58e7f66988a300df376f3536723e2ba5934d843ae629669485015c90a8da60ef5c00c63c0b08a00203a70000000000000000000000000000000000a62dc83ce27987849070a6022ab6a06186e2527f39ae94d5a23d2e4d234a465d50e03b0d7d175ed7f53ced0c3bbc8f",
+ "Name": "matter_g1_mul_77",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a85cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a72",
+ "Expected": "00000000000000000000000000000000142fa228919f71f75df073927d03d9204b36a5177b4ab7bc995b59ff312034f7ff916635e27abbe775379aafc24a35c30000000000000000000000000000000014429fb137cf912995ca785902877e6675105b252a64282412798f883063824fc31cd79b356ea4e4822363b948ec27d1",
+ "Name": "matter_g1_mul_78",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6",
+ "Expected": "000000000000000000000000000000000cf0aa7969ec44cc21bc8cca97fc8a581aecb63054c4fa3b7b69d28e0e2e901fa51c42a629145d9126e63aefe7978c8b00000000000000000000000000000000199d565f26b9c6496a4115eefc75f1066480f498a50314b396685a3ade8e50ab03c7f56316be2bcc02dff8b11ad5e4d9",
+ "Name": "matter_g1_mul_79",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b",
+ "Expected": "0000000000000000000000000000000000bf4256ce2a2a976e35a9eb266d11dc53d043f6fcafb47eee06e120457ea56decab47ef22b251c6cce17df9a7d91e3300000000000000000000000000000000152c438e11fe1d661eea7c631e04e02eb9204ebe52cbceca1ab6a9b4c889a1ebdda01d7505df29fe2204ef5787749a63",
+ "Name": "matter_g1_mul_80",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d506e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a4035",
+ "Expected": "0000000000000000000000000000000007754a49dcdde1354412d3fe2e108675fde8a1df069c86be54c4bec46338a0952aeed50842c2486ac652202c26a1861c00000000000000000000000000000000023fe3f5e6786e339002e14ac5c9fdaac3c012526b33da9ed314cdb145f9279a71e306f5d51243a0f0dcdf59bc5d55ed",
+ "Name": "matter_g1_mul_81",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad51a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff",
+ "Expected": "00000000000000000000000000000000141464b4326b0353aa99674bbd98853b926aa580c1e03673297bcbe9094eb1d795331d16d883e0583ed0551f064d7a0f0000000000000000000000000000000002dbbfb86c4d313bdbc8ebd266c190e38645016aca22261665dc850b0d7db8b240aacebec8af097724e5291ff43e6f90",
+ "Name": "matter_g1_mul_82",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a9251bd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b",
+ "Expected": "00000000000000000000000000000000118ab56a65ca63becc8aea3f11b370c705f32418d51fb1b1ab64bdb8f0125de2a760cf21e7ffd4d99e9d7cde1368791c00000000000000000000000000000000047674c8f3627527dbb41f51fa52c0fe3a921d07466cb2b5484e4c8094556cae247347a0a1a98499510d1ce5067480ac",
+ "Name": "matter_g1_mul_83",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f6a300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d",
+ "Expected": "0000000000000000000000000000000000d76cf9fa103355e6f5cd4baa3420e694f252249aa6171569b70cb43c906eae9b60bb79b41af8dc714bd917638bf538000000000000000000000000000000000b9272015e64f292d7b76867714a55d7223bb026f354b20109e81122fa13fd0426bb3aec705b477e7b9560c5a99c9d60",
+ "Name": "matter_g1_mul_84",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886233e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b33",
+ "Expected": "0000000000000000000000000000000007c87e6d92bd41b7fa6a6ca890bf0b58304875a79af7959d9226a5be2f4ac2b4531fd09712eb6299c23d7c1c5ba3997f00000000000000000000000000000000164fb86eafac39e06c2403e315bff96faecc57474bfc964736b1850696ecfedbaa0795e537b8f541159d479ac5b52560",
+ "Name": "matter_g1_mul_85",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8c48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f",
+ "Expected": "000000000000000000000000000000000fb01ce0567f09dc44fd473009d2467c8c16da5ea7b39a1f1dba7b3656cadd6bdf2bf68f96a43252d92e428c1d2785490000000000000000000000000000000008b4fa645f3c56459a17c912c82ca36165e730807282cabeadd9c6c4a12c8a592cbac265021ef62c60eb60df3ff61061",
+ "Name": "matter_g1_mul_86",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f594228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c",
+ "Expected": "000000000000000000000000000000000b9c328c8a18113e1d1f783432c857015eaefa724fa2c441d5ef76b158ee6fe0cd1775b0c6db7600754cbf25fea528fe0000000000000000000000000000000019d30c3557af1da2ca169e70625732d9a4396b51f3b4988a9aba1be62538fd51c167c83e921f4876224d361afc90eaf8",
+ "Name": "matter_g1_mul_87",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82fa417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f1",
+ "Expected": "00000000000000000000000000000000041054430741e889d4cd8e7efa41547eb624bd775fd9fb64cf9e3dc2c6df27c95ffb8d76933ac4fa1952a5820ff88512000000000000000000000000000000000e8a28f5c622482b296a43ddb607e0f25635664fa849f3d6840ed7118892106a787bc07806dfd83935754d2057f2eff8",
+ "Name": "matter_g1_mul_88",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab446561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb",
+ "Expected": "000000000000000000000000000000000da2286b44e7e90e19d51c3c41bef375c54688b07afffbd7c528589dbf7f012e1fd248b9067a3faae9f1c6b626a5c90b000000000000000000000000000000000bfa0a482b0fc445f7b99c52a48116383bb70d5f2ebec5b7715796fbd0da744d0467584bfc1c8a42ace833d57c167a24",
+ "Name": "matter_g1_mul_89",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c2cf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf",
+ "Expected": "00000000000000000000000000000000148a7e9b0b4fde322f1177ced0bba34abec4a3e500afb86f9ae0a71bd75004e9c631d4cb26798bf963f7aa367f74630c00000000000000000000000000000000097f4c0893f9beadd66e4cfc6976dd277e527b1e31443e07554dacca52390066a4b37a7f0824cbaf51d3a555d696881b",
+ "Name": "matter_g1_mul_90",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a6f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5",
+ "Expected": "0000000000000000000000000000000003e1d921b5e0280f7370d55967e716bdacb7521547e22190e89862dbfcce02dfe7fa7927a70e7bc33448b9321de3d8ae000000000000000000000000000000001163f78de4af8494666c64d47d68a0feb0905c42ddfa024398401202d1fe0d6672bd1bd4222a8d106668ba4617683485",
+ "Name": "matter_g1_mul_91",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e40ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e",
+ "Expected": "000000000000000000000000000000000a94a186b96acbee87f9c1745dc301229ec750c6967262e629924227c6680b1d404e4b23d998611ad0e415610dc8edd900000000000000000000000000000000014da21c0f6930a79c8afbe42f73e048236b6d9f9ef8f270733fa1cb1012377eab37ddf2b9c742fea44020caeb95beb9",
+ "Name": "matter_g1_mul_92",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefbae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be5",
+ "Expected": "0000000000000000000000000000000015cc6c31dfa9482c6341f816786562481bc3a4db4a4a00807a9c7c676eb32b9dc7e002ed4971f26c1dddea00d78721b5000000000000000000000000000000001303660b6bcac611b2d41a4f7ac9ecf3f0b4292f83f2fdeba300a060131322ee3c2da3ca3539114114ec8a76dee6a5ac",
+ "Name": "matter_g1_mul_93",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c35851268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c0",
+ "Expected": "0000000000000000000000000000000009f1903e9a7d275487a503b9c968cd86823fe6667c09593b60ac2c88f306e20ccde32eebb5942a03fabde9195c5c500200000000000000000000000000000000179b41dbc2ede95ba7dad512329aeca9ca3bfd4da4b9620070d76d8fe8b49ad7fa92358070dd5098a2eaff490641edbb",
+ "Name": "matter_g1_mul_94",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728bf9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169",
+ "Expected": "000000000000000000000000000000000f9736431073987708757d61927a45cfec471c8366776e140f62d805afd948fd132c4a5f4049de3a1474d0cb52c3c25e000000000000000000000000000000001515b057952696810a90dce1ee8464fd6370e8af5434a99333eacd1fb2884f6e8c568f887030a4957ff6d24ca02f4657",
+ "Name": "matter_g1_mul_95",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b767f399e4ebea34fd6b6b7f32a77f4a36841a12fc79e68910a963175d28cb634eeb8dc6e0533c662223c36b728cce2000000000000000000000000000000000cb3827fd6ac2c84f24f64789adac53439b4eba89409e12fbca0917faa6b7109aa831d16ca03191a124738228095ed65070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b4",
+ "Expected": "00000000000000000000000000000000195460b2d59df32f9f41eaef1139d45f0cb8f35a7982c38d356a8a8412f25e600580026d2d908b0493edba5dbea85f5c0000000000000000000000000000000004b339d62b3cd4cc966c6b4038adb302f997a16d8a6dfebd153295de08e57d1513cf0f16d82dc450e4d6f52621a42fb4",
+ "Name": "matter_g1_mul_96",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000150b75e9e9c03ada40b607f3d648bd6c40269aba3a1a992986dc005c9fde80bb1605266add0819641a0ca702d67bceed00000000000000000000000000000000083b43df032654f2dce90c8049ae4872a39f9cd860f08512930f43898e0f1e5625a5620818788797f3ca68134bc27d22d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e125",
+ "Expected": "0000000000000000000000000000000012cf2bcb79668067b7a265672ca614405868cf189ee9789b9e1e3186d231176dab5fea86cc5865392db8c75fc5d124c900000000000000000000000000000000121bf40feea00e151b718157b8c024f126762d84cff20aac08e7f2a027ab88b33e134a410c2af279a39618f7d21482a0",
+ "Name": "matter_g1_mul_97",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cba419694214e95a3605a9b748854d16c8e6e1ee151c907487d8189acfac1361b790a5e78f43593152027295adf8df400000000000000000000000000000000110813ff6e0ddf3427e2a514d3f0bfbadcaf9dbf039e0f93fb9643d1e62bc2469fe84cd9ff0d585bdd1037255bbe5485041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b",
+ "Expected": "0000000000000000000000000000000013a530f94e7600820dbd8aabefde2acb8b3c74e833457102fbd297317eb532c0622636ef9e9376fac1637dc745fe895000000000000000000000000000000000139eb14d3b69be977413c832bfda234348186d46fe177154e34fe204f62ac79f4b0f59bbef39b0676d81ea42a0946fb3",
+ "Name": "matter_g1_mul_98",
+ "Gas": 12000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000106df8eba767e90cce0eabdaacc24d8e226c6865012ef8cb1460de5a319d443fdc6b4f4e58fb668943e0528b1809da10000000000000000000000000000000019789f464c95c179af18704c0b67b881991880f75ee7b03b9feafa3eafcd0f7d30a17fdd9cf439ff7fe683adca2083b57cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf",
+ "Expected": "000000000000000000000000000000000bf700422a382546a74376b0292f3a49ceff5597f0d2b726b1ff099bcda7ba92238a21db12eff5c314a29dd2387bec850000000000000000000000000000000005e22e3c772f3634b1ccf4e311241977eb20e7269540ef22d379de26ab80c58461dfa3b67848e0d584fb11de1917949a",
+ "Name": "matter_g1_mul_99",
+ "Gas": 12000,
+ "NoBenchmark": false
+ }
+]
diff --git a/x/evm/core/vm/testdata/precompiles/blsG1MultiExp.json b/x/evm/core/vm/testdata/precompiles/blsG1MultiExp.json
new file mode 100644
index 00000000..62b91f6f
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsG1MultiExp.json
@@ -0,0 +1,723 @@
+[
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000011",
+ "Expected": "000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436",
+ "Name": "bls_g1multiexp_single",
+ "Gas": 14400,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000e12039459c60491672b6a6282355d8765ba6272387fb91a3e9604fa2a81450cf16b870bb446fc3a3e0a187fff6f89450000000000000000000000000000000018b6c1ed9f45d3cbc0b01b9d038dcecacbd702eb26469a0eb3905bd421461712f67f782b4735849644c1772c93fe3d09000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000147b327c8a15b39634a426af70c062b50632a744eddd41b5a4686414ef4cd9746bb11d0a53c6c2ff21bbcf331e07ac9200000000000000000000000000000000078c2e9782fa5d9ab4e728684382717aa2b8fad61b5f5e7cf3baa0bc9465f57342bb7c6d7b232e70eebcdbf70f903a450000000000000000000000000000000000000000000000000000000000000034",
+ "Expected": "000000000000000000000000000000001339b4f51923efe38905f590ba2031a2e7154f0adb34a498dfde8fb0f1ccf6862ae5e3070967056385055a666f1b6fc70000000000000000000000000000000009fb423f7e7850ef9c4c11a119bb7161fe1d11ac5527051b29fe8f73ad4262c84c37b0f1b9f0e163a9682c22c7f98c80",
+ "Name": "bls_g1multiexp_multiple",
+ "Gas": 27504,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d2800000000000000000000000000000000000000000000000000000000000020590000000000000000000000000000000009ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e522400000000000000000000000000000000032b80d3a6f5b09f8a84623389c5f80ca69a0cddabc3097f9d9c27310fd43be6e745256c634af45ca3473b0590ae30d100000000000000000000000000000000000000000000000000000000000b7fa3000000000000000000000000000000000c9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b6000000000000000000000000000000000143be6d078c2b79a7d4f1d1b21486a030ec93f56aa54e1de880db5a66dd833a652a95bee27c824084006cb5644cbd43f0000000000000000000000000000000000000000000000000000000004165ef10000000000000000000000000000000010e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc0000000000000000000000000000000016ba437edcc6551e30c10512367494bfb6b01cc6681e8a4c3cd2501832ab5c4abc40b4578b85cbaffbf0bcd70d67c6e20000000000000000000000000000000000000000000000000000000173f3bfab0000000000000000000000000000000006e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb9090000000000000000000000000000000017d81038f7d60bee9110d9c0d6d1102fe2d998c957f28e31ec284cc04134df8e47e8f82ff3af2e60a6d9688a4563477c0000000000000000000000000000000000000000000000000000008437a521c9000000000000000000000000000000001928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb700000000000000000000000000000000108dadbaa4b636445639d5ae3089b3c43a8a1d47818edd1839d7383959a41c10fdc66849cfa1b08c5a11ec7e28981a1c00000000000000000000000000000000000000000000000000002effc7b3027300000000000000000000000000000000085ae765588126f5e860d019c0e26235f567a9c0c0b2d8ff30f3e8d436b1082596e5e7462d20f5be3764fd473e57f9cf0000000000000000000000000000000019e7dfab8a794b6abb9f84e57739de172a63415273f460d1607fa6a74f0acd97d9671b801dd1fd4f18232dd1259359a10000000000000000000000000000000000000000000000000010b4ebfca1dee10000000000000000000000000000000019cdf3807146e68e041314ca93e1fee0991224ec2a74beb2866816fd0826ce7b6263ee31e953a86d1b72cc2215a577930000000000000000000000000000000007481b1f261aabacf45c6e4fc278055441bfaf99f604d1f835c0752ac9742b4522c9f5c77db40989e7da608505d4861600000000000000000000000000000000000000000000000005f04fe2cd8a39fb000000000000000000000000000000000f81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed0000000000000000000000000000000011af629591ec86916d6ce37877b743fe209a3af61147996c1df7fd1c47b03181cd806fd31c3071b739e4deb234bd9e190000000000000000000000000000000000000000000000021c6c659f10229c390000000000000000000000000000000000fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a550000000000000000000000000000000004523f5a3915fc57ee889cdb057e3e76109112d125217546ccfe26810c99b130d1b27820595ad61c7527dc5bbb132a900000000000000000000000000000000000000000000000c01a881f8abc4d8843000000000000000000000000000000000345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c00000000000000000000000000000000083d3baf25e42f2845d8fa594dda2e0f40a4d670dda40f30da0aff0d81c87ac3d687fe84eca72f34c7c755a045668cf10000000000000000000000000000000000000000000044496e633650ef8f6fd100000000000000000000000000000000051f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e000000000000000000000000000000000b6a63ac48b7d7666ccfcf1e7de0097c5e6e1aacd03507d23fb975d8daec42857b3a471bf3fc471425b63864e045f4df00000000000000000000000000000000000000000018461a3d444ec527fcbf4b0000000000000000000000000000000019bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3000000000000000000000000000000000adb3250ba142db6a748a85e4e401fa0490dd10f27068d161bd47cb562cc189b3194ab53a998e48a48c65e071bb54117000000000000000000000000000000000000000008a0eb53c748001536d7ffa9000000000000000000000000000000000d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a414950835820000000000000000000000000000000009d0d1f706f1a85a98f3efaf5c35a41c9182afc129285cf2db3212f6ea0da586ca539bc66181f2ccb228485dd8aff0a700000000000000000000000000000000000000031133a6c7d698078a7ec7e11300000000000000000000000000000000073eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086000000000000000000000000000000001825bacd18f695351f843521ebeada20352c3c3965626f98bc4c68e6ff7c4eed38b48f328204bbb9cd461511d24ebfb300000000000000000000000000000000000001171d5c4909480aae3b110d01c1000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc75843600000000000000000000000000000000000063376fcdf64c9bcbeeff0f9f9f9b000000000000000000000000000000001252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada0000000000000000000000000000000002a1bc189e36902d1a49b9965eca3cb818ab5c26dffca63ca9af032870f7bbc615ac65f21bed27bd77dd65f2e90f535800000000000000000000000000000000002344b4be368d3b617df4aa8dbdbc19000000000000000000000000000000001271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4000000000000000000000000000000001407ffc2c1a2fe3b00d1f91e1f4febcda31004f7c301075c9031c55dd3dfa8104b156a6a3b7017fccd27f81c2af222ef000000000000000000000000000000000c896c3f9d64341ba7c5f8a06271dce3000000000000000000000000000000000272e9d1d50a4aea7d8f0583948090d0888be5777f2846800b8281139cd4aa9eee05f89b069857a3e77ccfaae1615f9c0000000000000000000000000000000016ab25d6a997bcac8999d481633caa41606894aae9770cdb54aac65ac0a454dd0346b3428fefd837b1e3f654f8217f4a0000000000000000000000000000000474d97a9cf29e85d4a35f6102fe7984b1000000000000000000000000000000001780e853f8ce7eda772c6691d25e220ca1d2ab0db51a7824b700620f7ac94c06639e91c98bb6abd78128f0ec845df8ef00000000000000000000000000000000095bc13d5a05c686e20d7b904db4931272d84d051a516fbb23acf7981d39bffa3943d08a9be01fc48e5241cd8b775ddd00000000000000000000000000000195894e95ca3e59929612e77c1075322aeb000000000000000000000000000000000b48aa2cc6f4a0bb63b5d67be54ac3aed10326dda304c5aeb9e942b40d6e7610478377680ab90e092ef1895e62786008000000000000000000000000000000000f6fc00c0697119a34363c0294acf608eca3c680d80183a59c89b45a66dc750f818a27e3a6e136d69e7580a8afca001b00000000000000000000000000009027ceef3ee429d71b58b84919d9a8d54189000000000000000000000000000000000c8b694b04d98a749a0763c72fc020ef61b2bb3f63ebb182cb2e568f6a8b9ca3ae013ae78317599e7e7ba2a528ec754a000000000000000000000000000000000951b70c206350e1edc2aefdfaa95318368c151e01e468b9fb1cf7c3c6575e4f06c135715cc5e51e1b492d19adf9bee000000000000000000000000000333e268f0b5b1adf76b88981fc305f03ce4bb3000000000000000000000000000000001717182463fbe215168e6762abcbb55c5c65290f2b5a2af616f8a6f50d625b46164178a11622d21913efdfa4b800648d0000000000000000000000000000000008531aa42aa092a91e0894d84ff0bcec0d37cede43dec85cca80ffad335d6f69da18335869ba1174f73bb37501404d6f000000000000000000000000123717b4d909628d6f3398e134a531c65a54e8a1000000000000000000000000000000000cb58c81ae0cae2e9d4d446b730922239923c345744eee58efaadb36e9a0925545b18a987acf0bad469035b291e37269000000000000000000000000000000001678cefdd942f60480b5f69738a6a4cea5e1a9239d1bd5f701ad96c2dd1fd252f0aeea219bddcda4bc8f83983a282aff00000000000000000000000679956d49265608468757580db6b8b1821c2eb13b",
+ "Expected": "0000000000000000000000000000000005548dad0613ef8804a347152e8267acdbbcab98a795fc0da2d9df5c8ec37e0eb32e82950fbe5f8ec330b8bffafe13e40000000000000000000000000000000014e94dbbf60d89b3f68a5a076fcbd7cc0b683eae228f5d5036ee61012996ae2d347cec19dbd4eab547fadecdb31c078a",
+ "Name": "bls_g1multiexp_larger",
+ "Gas": 89400,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992feeb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed24d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be10000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e44c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d38964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b89000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f90787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c944000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1baaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e10000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442adac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795bb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd1080000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a190fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f81876720000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac943b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e3b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c760000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276bdd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a57876817010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f76894c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a65905400000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931db3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746",
+ "Expected": "000000000000000000000000000000000b370fc4ca67fb0c3c270b1b4c4816ef953cd9f7cf6ad20e88099c40aace9c4bb3f4cd215e5796f65080c69c9f4d2a0f0000000000000000000000000000000007203220935ddc0190e2d7a99ec3f9231da550768373f9a5933dffd366f48146f8ea5fe5dee6539d925288083bb5a8f1",
+ "Name": "matter_g1_multiexp_0",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d507f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb6e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed8330000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154bd411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af6bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719292a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c52000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b10000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff327064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e90000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f2686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c23176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a600000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd1d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc9915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da05061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b2087920000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e053f396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265ef0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc8915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c",
+ "Expected": "0000000000000000000000000000000017479d99909c144a5a5fdfd71721f4a2ee90b2b9654e069a38b460945b9291fc74e6922a7dbab9bb12b4bff9e2d0175b0000000000000000000000000000000015cfff11afe08d76944c9f810017ecf78b8ed54096078195d65a5418f660cf9b2024646a8532e349eac5d32d59c829db",
+ "Name": "matter_g1_multiexp_1",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff17d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3fc00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc4500000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9aff661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c3346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db39a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218082c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d48280000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcbd4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6341776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c425000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f0e7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5ec26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79bba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e820705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b81158f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa40000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556",
+ "Expected": "0000000000000000000000000000000001c143e5d7bba56a959b94955f8eaab82a92a2e2b355baac7da0b57281645c689486059fb590ef2576a7a03a7c57e85d00000000000000000000000000000000182b1e16004c7e6f55923dd0b1dfa7346d1243996070db78f45c4c0a2cef95e93c6373903b5e0dc63f171c8164c2fb5a",
+ "Name": "matter_g1_multiexp_2",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe9a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac700000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193ab473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c0130000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10ca9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc80000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bff228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b29431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb51124400000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b2051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d830000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751ab96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f8520000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df9178176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c049c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da0000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e29462ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd45000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d3184fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae928a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b170d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ecdbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad9970000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a",
+ "Expected": "000000000000000000000000000000000b2997ce4cb01abbb0ae6d28099d20e1f08c33351a6f0dce417a279789d6c581d4bc5a4a261e37e6df31a6928040d1f60000000000000000000000000000000003068e73dbbab6fddfd3c1e4fbf58bab58f15e1630c8c236faf3048be840abe316084aad7dd4ca6ee9d353ea8db536d6",
+ "Name": "matter_g1_multiexp_3",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e3616000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f7a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d245111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d1450000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531fc07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e787929b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd0000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a63d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf542580000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f57a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567381b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc3ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de0700000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b6000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa3ac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c796590000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c88586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb2116e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a85cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a720000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6",
+ "Expected": "000000000000000000000000000000000ed96265e66875001ebbe888571ded16799d0bf5a6bad0abaca75b94bebf3023487a29fbe26a68f1cc90485df379845d0000000000000000000000000000000001be40cb29d8b722f91515f7e18372f7a0f77bc3ef2852c59e7533aeb67cc4cc4aab0b8e87f9a4982806124462ae94ec",
+ "Name": "matter_g1_multiexp_4",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d506e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a403500000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad51a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a9251bd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f6a300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886233e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b33000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8c48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f594228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82fa417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f1000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab446561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c2cf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a6f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e40ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefbae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be50000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c35851268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c0000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728bf9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169",
+ "Expected": "0000000000000000000000000000000008644b6d6adf9d5b6b50d4759363901ea94218881fac2006ea391c41fed2a94645eeb3359df803d740710f0f7842b985000000000000000000000000000000001168ff1897eb699e475b8ca2930ae9ccff139d534c7cc606c7bafec0ed23a6e55c6ddb1efbb1b5f75044d0a7e122d204",
+ "Name": "matter_g1_multiexp_5",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b767f399e4ebea34fd6b6b7f32a77f4a36841a12fc79e68910a963175d28cb634eeb8dc6e0533c662223c36b728cce2000000000000000000000000000000000cb3827fd6ac2c84f24f64789adac53439b4eba89409e12fbca0917faa6b7109aa831d16ca03191a124738228095ed65070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b400000000000000000000000000000000150b75e9e9c03ada40b607f3d648bd6c40269aba3a1a992986dc005c9fde80bb1605266add0819641a0ca702d67bceed00000000000000000000000000000000083b43df032654f2dce90c8049ae4872a39f9cd860f08512930f43898e0f1e5625a5620818788797f3ca68134bc27d22d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e125000000000000000000000000000000000cba419694214e95a3605a9b748854d16c8e6e1ee151c907487d8189acfac1361b790a5e78f43593152027295adf8df400000000000000000000000000000000110813ff6e0ddf3427e2a514d3f0bfbadcaf9dbf039e0f93fb9643d1e62bc2469fe84cd9ff0d585bdd1037255bbe5485041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b000000000000000000000000000000000106df8eba767e90cce0eabdaacc24d8e226c6865012ef8cb1460de5a319d443fdc6b4f4e58fb668943e0528b1809da10000000000000000000000000000000019789f464c95c179af18704c0b67b881991880f75ee7b03b9feafa3eafcd0f7d30a17fdd9cf439ff7fe683adca2083b57cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf00000000000000000000000000000000107e1fea76b5f2be2d12e11082fe690f01bfe6cefe22ce67de968e410ef51a6192b5b28a89f222db7e5b5fd5b8bc7c4000000000000000000000000000000000014028a700cbde8bce295c564dfbd73294f9bb65db3db9d38312cdc31410ceaf7151ff5d9420de2a5bc8f0d609893c0612adc8edb64db5bf0ed6724f3b54140ed6c81ca65ef9d1b38c8bca6a62bfd3c6000000000000000000000000000000000a57058bc228914bbb3e3e8f6a73842533432e0cf226cc02990b9b99a74b0acbad498036d8fb72a163590c75b6041d060000000000000000000000000000000016d275fe8c7e37058f287e1646c28ad1b4a675c0eef9671cf95dfa25617e2f2d515b2fbc04cfdffd5d487b255dfca245d1535bfcd68e8136808edf89967fbbf76b7f58d1a8ac95ebd4944b9e440f20b20000000000000000000000000000000016b6ecca57c78d6595e6b55b9360bd946b2f0061b98d931d82b03ed747998285e093c978015f0b775867ad0d8b4a1f82000000000000000000000000000000000b584f6f00bbcb2432b6cfbd4f6c88e228658887b5278e461ede804fc8a65dc6c997de30efc65b4f43e3d96717b938644c576996d90abde581afb58903cde4b9443eeb65e21b0d68c578e04c8f28f3d3000000000000000000000000000000000d1eac060ddc0a327396051c8c4dcccb77d11da05678d0720dec020d8aa29cb8ac959184417267cd7386feb1c81146a70000000000000000000000000000000003f8b5667ee4707958ecb93a1772849d5d8a4d42a2367ca058b160dbafa8ac0b98d5ea216fd18130237a1f17ce905feb3c558cc615b1c61c9a42b8b0ab4668ffcfc9e95bbe958e72e7a5500058e6b0bd00000000000000000000000000000000180152247144900b015c3db2d8b26d45a57930a5ca988c1fbf74b63b48afa149347a343f3fc6b1f31ddd6de079391efa000000000000000000000000000000000b6f3ae16d2a580ae06634455302db85fa94d71def14c84cbacc5ef98335d6d87faacff7a9bc14dea342a6a80d9bdfd661301b4957a468e2817db5914ff102bc96460a2c5c15e78bd42884b1223fa71a000000000000000000000000000000001918c4f95a0d0931ac3f254cd61c10cadce5cb9e1ef352edc8e5944c8aa8ecd90c403ed764ef42f646c7ec5e3126a140000000000000000000000000000000000ed644cd065411c63c7d054a57344e7a909e1d0a6b414bccbd356f15d16fc1b42c681cb6b36b143e91b31866387fa94395cd2686d24a5bdda0bcb118a2c0eb5ccfe411ec452e1beb3adbda7e93ea367c00000000000000000000000000000000070dfa1dda5ba02e94b29a63f8eb571ed7e8b0d037a0203af9a8350dacec092be1bfe33f4134b2afac77b9a36f95208000000000000000000000000000000000019e11a80ce3f9b3321cc6fd1ea2b314bf0c71d0dde80cd5b4de5f0d974597f57036613829dc777a6f6ecd6f9bef2f85fb81d555d1e2df92cdb487a888fbedad976dce54b5c46a39893edeac21a12d6e000000000000000000000000000000000584b7ea99ce0398473167289d34314c60ba913338b0bb690cfbb013496d24854863237a4d716437dc6ae33326240bd800000000000000000000000000000000065964a064e4da56471c9aed383e6eb38b58b9110a2cbf991d6dee869d2f1307cf7273d203d941ead90ed67c923dfcd5bfeed84bd95fb955d1b1045c059ffd051324dc8966e504164e54f76f02eb1b860000000000000000000000000000000007d6061bdf40745ef7573917e0e19f240b6e917f7cd4c47e01969b9afdc6af4e3c93e0f1dc2d15790bc2e6f182c01f680000000000000000000000000000000014625d3f2825121a907b570e9aeececcf81137f40ca6d0c00d709ba9931e403c0c2ed262a8f4c2b24305dcd3185b81b0e3b308b95f6d496e6d5b910b6aabef8d9f868471653e8254ab4d49d593180d2500000000000000000000000000000000087b5d6595554184fee36be472a0ddb9ac7f9beb20817647fa9978b2e0c3549ece4f061b58054e9191ff3f120c12077b00000000000000000000000000000000168d8d995c1fd032ca7b0aef2ad5c37ef7c7cef8b61ab8fcb5ea2d449455bc75b1b85631fd2ff8f5ca4e5880f36905ded4ea92e0e776be341c8444d4040ec121a2847256c5c9bc918adb28618548b048000000000000000000000000000000000f44cda026dc5e30eb06f12307bd582b271ee695fa68fbff48674c0499dcc875d617471830958e31bcd2c883e97a9e590000000000000000000000000000000002977682ca8ca450df2ac3c3880b1235e0ad8436a36364d319903fe2ca2664e05a70840aaf2d62531cd8c4ba4bfae9124c07f5188e4c6270a7e9e2f551683c4f9dc943ffc7ec279d15816a7f4910b8d300000000000000000000000000000000107dd39f779801f608cceb4784134894d2d9aee37cf328bb764d8afcb6d1e0f1387b36bf5b7b335099849278eac44e8200000000000000000000000000000000045c985714b519061a9c8d8c9665b582abdc4116a48a70e0d3c4a7709568aaf011aa8ecb893ca483878404b3f8b22e41a819a0438efd7ec0c1e3eea07ba201af6a832fecec818adbb781ad0c23e81dae",
+ "Expected": "0000000000000000000000000000000005605f40a1116742ed53aaf7092715355ba8e41d5d49909f79ec9580955c4a9e696fa30df37e4044de4d23fa1c4121530000000000000000000000000000000015acbfdf914883d16918f980aedc2dfddc428ef8e9897776443ec3cb091f6cbeea31634ef5ed061792710d5d2c87b8b1",
+ "Name": "matter_g1_multiexp_6",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001696e814de192623543f822a22344258c8ef9b92c178c4bf2404b38f39151828bf518a868cde3db5cffb745f1bf0023900000000000000000000000000000000125bd1df30f4799271a9db03842f98ccb5a5c3acbe813b8324fefd06e3c8ec4e2c0be8c2d24328a2d1169bf6ea0ce46fb15af019ea2de662bf187930caea19d0aa07a74b49fa7d1819a539e06e4c69ff00000000000000000000000000000000138dc5c034135105c8899eeb61ab54a84cf02919e5650f34518f941aea5bbb6f9df3ee6bb2056d0b9e060158140f990a000000000000000000000000000000000eec8442c8656ebc4696ee13273b12f3e362862acc3b8ec6f2b53f58f74ea23b33c79fbbd2058ad205f4932db2e87ae9064a6af51c1d499c4c28556ad1255af7467bc750bf2db2842d626647bdb334610000000000000000000000000000000008f7f45310b5638221cfc9dece18010034c00b3cf170535008d60dc7ed6ff90bfe87e03d94e9a38201699f0742d8973500000000000000000000000000000000185b62a19864e21e1bef19fbbc21863c75f558bcbfa1b948bf939876188f4fbff5d5f4f756e0ec5348e194bb4f70706ca3daea5a083af43711fcb09282b66882ae5b5b8e1714e9186f33ac0dfe48b7ca0000000000000000000000000000000019269dcdf3772ae4969b68a0b4f87c5097aa8bcc9e6155638c3de94fc22b4965386be28e059bcea69f993cc388ea9a79000000000000000000000000000000000b95f44ad9f14cb5e3b9a338d0e4345153c4ad0d42aa00a4c12df117b89d9cf8bb556041d49f94b8f63108f03c56a449bd682acd154f6e16a583ca4968d28471653375ef79df078b17b2cd9634258dc10000000000000000000000000000000011c86d420b6d8820af8a3ef511d79aed7c82ee08df993a5ba479b29ef2f968919444a7c48a24ec33522e1206bb9ab784000000000000000000000000000000000f4a47f3f14a25108c2c9262466d14e3a8d1f21bd2d3d6f28f03f35bf23a4b5b494a7cafe6ed5f39195e07b1692bb6da562223d3fae1d303a01ee4642fb4cc70f21937ba7fe377260fe82262a8455a7700000000000000000000000000000000091d9fb6493f4441c6e57a5a58210a6b78e86f1a9d204094ba6fecf2c146522cf842219c900d7cb95366cf7e411ff4a00000000000000000000000000000000015254260fb67e88d0067ba7006a49814c74a5369837dc5279c0fd19c8826813c922793c96e0f708092158ac297a368ddaf1d0fdab6185e1c3f9f621ddc169ba92584db0b40b6ace7ed563eee0090629f00000000000000000000000000000000027910712cefec94f0fd4de6aa70ccc408e64d5de6b473086009c525fb6d058ea03bc99f7ab49cdbad3a42bc8ec0999d000000000000000000000000000000000c0b0bedbad83ebf6af4f5757035b8292fadae4bfbef9f3bfcadd21dd796d7e3ecdf9685ca6d4d649b2f0702a3280d40e910487c91f3839d5961f02a67f3b357206e406ba207dde969498e40d4a26e88000000000000000000000000000000000b0ae8987464ea0b77201d468db7256b135a5cebea92dddb3aff10e451568e714f1c418b6d53903b89bc71109180b8c20000000000000000000000000000000003050becb4625f8e3ab2cf13dd1eb8f7eefc7e14c16934b87661adbf0139631108d241bcb1fb24c5b989f6d424cac883396d32c2c9ef685120995d2244756bd45591618597306193422f3b5df4b075d2000000000000000000000000000000000dba43568347a96f26f2633d9fc0fb4610428a8d4992c2734b20928bf974bf642a5122995884cf11b76126ba66522c8c000000000000000000000000000000000b9bb25b0db32149736b671ceed44df71f36a33c15ed821f591098ecd873355cfb8a39fc7c7378a19d84a5b232227ab92087e21d775fbc2c20dda715e46c9c4970394e40e991c78ecc13a2a5d0b0f30f0000000000000000000000000000000018d46d1a9ec91cc7983b29ac83fe9101c0ca36276d40743d2a6010d574fe1c16ebd9d7f0c83cad5ec2b2f652d3e6cfa500000000000000000000000000000000185f6367fcfa70e7a005c1739c0d0a19b5ec8de766037ec92840e66e2e9db18ba2356676899763183222f9957f48f300f44043002a94560d725da2ac44f30cc5f14f52dff5671c6689efebd803b1df7a0000000000000000000000000000000016677511c781b2b97456c3059c19b3e12a865cc21ad71cf06979bee1a3128682a4a86f3e07cdbc9ff7b5aa7a9899653600000000000000000000000000000000006307c89ac36a88c6921c020d32530fb69338afbb33929e231fa704f0454d642c47a3b8d320b4266283a8571944d0558624c83d846ad2e53f3f8ff5ffd3fca8723e6cd431e89ca29a4d662e82004b600000000000000000000000000000000015a9b215eaed682e4704cd3b1265962ae0e24555a16612ac762040e1fb9b412eacec5130a6f6a31eb670806be7ed775f000000000000000000000000000000000f60035910c438c177a27e6141d0ddae706d3e852d61e37cf8bb2f03550feeefa7213545e3af5ea614c91b51bc2fb378b2b2a8a42887ca6dff5b5364d88962068496bee79cbe74de0e8a06209feb3832000000000000000000000000000000000077b7a4c4644b21ac3ef56db1163f7b2e07a817cfd9d4c6830a97d0ae0b620e0b235376d590162c378899ba12eadb5900000000000000000000000000000000022beafe4b4ab44434c9dabae45a395b5b8da15da2fc2e723c1b30b5efc95e880846844f27eb47dfae8657fa27ab64ef88ecb5976f63a38d7f3d8c8ec441b705563c5e3d899870ab5d2ff84467fffefb000000000000000000000000000000000324928100db98f5a1af039a8e1b63099214982f1729ba633b51166da97e861426bb91283b386ed4b465d791e63928ce00000000000000000000000000000000178823756c0facbd4b1cab22f346ea7d1dce0ab687263265350c9939d52abcb5a5000b3395f8268a38027410675e8baf951f4960d6614b098249eb9420077ea5ad11e38d1694f4df33719d1127338f440000000000000000000000000000000008828eea92c3245eea4d60ee385734d3237e4e346e52c5de8b24c82325819be6984da4f0c1ecfc6ded5d0539a6f1f1490000000000000000000000000000000017169bab8970f47a303d2487e3af707eddaf7c4453e9d2d6bbaf953e74947b5fd40663173edd55c0d6aad7884f69a0967056c7d93d8453be369831dc0575df6438db488780d518a53d19b8f5d22d506a000000000000000000000000000000000787474664b2803e78489de6c5d5f1938e784e552bca4c32196cfe121380aad591c9fe4d9230dbe976b3ed3b3044b8630000000000000000000000000000000000c026547c94cea37793fee439c359cbeb2b985a33559ab25d1b55773c24faaf4fe511fbf7df085bf5c1715c79469cc28aa982de1583c25307e9e2c8cf2469a0b1076c6be2fbf12caa8584f34988221a",
+ "Expected": "000000000000000000000000000000000a7153c6173dc27b6a241c046a2a9bc25b85c4621667d0a10550cf7a090a8fb914725201876a5bd2af09d4fefdede3890000000000000000000000000000000007aeec94a64ac629673f3be3cf660f471e3e928de0884300ca8271d42c92b965c86bfe76df61d0645e955f40cbe3751e",
+ "Name": "matter_g1_multiexp_7",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015fec2d82f5286d2067b07d83cd1c131d3fe18628101c3e45caab07f3c775c97e1533836830959cd7e434fc3fc392203000000000000000000000000000000001050e1396a5053c902441cb33003d9c54e6b631a80e3c132dfd37805bfe87cc2ddc495200268fba0376c5fa071fad230a18ca15f0d931619363f5ee56bd7657b2298f228cae8d185c9d062910193e9c4000000000000000000000000000000000fbcd07180f265688329d72ca68cde644a580cc9d698e40f69380065110ff5a61149e4aa9f67056e0e1603bfb9b5b3ce0000000000000000000000000000000006f363a9addd63a59035cad90cd52213665069f540b6c6cb41cfff5711376885e3242b596d051a59f681941bafeca53eb54274927eb29fea0cdc464271c918826d5249b2180a52a5020480d1020c9795000000000000000000000000000000001164abfa75cb4d711ad811c4df430ecbd6329968ab003fa680d235ab34a9565e5c08add76cf412f132b54812671da7a900000000000000000000000000000000141c9858dd17dbb027dde22dd65f6a7cd38a1999eb7977cde87ad762425e364e1395851b1cdb41094551e530d891b0d15849bffc842c21277be88dfae0040c54b072ff526731947cbec0cfe963f2d0dd000000000000000000000000000000000b95d221c628a77bb75ee5942c9df4b700268c90c4e6330ab5533d13d59826c81aeef7621ef6145f48bef9607d280ad2000000000000000000000000000000000b2ae1b6f916d77c31e4421f8d0241201bdab5339f95eae0e9491b4da5e226f8eb3f754d40be3b446ad6d18f28158b08aeff769da1b62fde321d46c66f8ee7f2129446d805ab7f7bd586268de8f57c4300000000000000000000000000000000128989e92641f3c3a914c13e986aea1bad2c87a8c28cf156bbc68bcbb134b25cd672832f2a988f60d2ecaaa1b83159e50000000000000000000000000000000000106dc95373dfcc85d9de6b5b609554b67e8683f90ea13156c8318aa8de0a2355a721b3bd77a6329264ae671c05af4a52c9e56cfe957b924c9c0294e1c1f12474331c662c8e86288c97e6a8b8b5b2020000000000000000000000000000000009fd9fc9ecc0d1521696bfe7624360d11111523a4ee0e30432a468dbaf1c101691fa527aac5ab531be822ae914b0afad0000000000000000000000000000000016b317ad68ec471b0ad67be2c489c9f5bb0d8bb6b5ef909ea975cb17f5964564d5f1a61d32d60c457923e4680a218b9bdecec569d223c724d162250ed1d074ed9f4080aaae3f44b77df05292be48ebd9000000000000000000000000000000000b982f33980dea4d89b577c9f849f8b8d9cb0c7efec7e17284d45c855638fe9ab2e5bdc52ba79d06a9133f66bf0ea2b5000000000000000000000000000000000c252a2e2769d3250479091050133808a1b0fd20af2b41cdeebe7cfcf7e3a92b9ab17cdf4d370f9fc391981db76de39c915ac9453b831c41becd3c1f412cdf5379e9cd5c80bc6df92ecfc5005356d2aa000000000000000000000000000000001769e8b5fda96ef205750826f34fdda3587efddc86f69d37001c62938a90efc23a3ae150d223ef4bf3766ab7d86d80df0000000000000000000000000000000009ee24ab483300764bccba33b55b8889b084288ffda23d157f650df34125fd803624d88f2bd0c3c3ca51bcb57b9f4dcb58fa60bc7cff4edde18301af2348faa69ed4f31d437decb7d4fe51142d179e6000000000000000000000000000000000146001b68cd902fbb4548c3e7cfae9cf3c8916e462f1becb9918c8de42483ef65f418d6e93200e8ec95528928916bdb10000000000000000000000000000000008bef4996b8120613292dc76dcc77b07b24d4498d6bd35f5dfb80ad241ad97bd161cb2c5c96fb250b70f8aec1aee5b56c29be0b271d4e22d39e9e06db9e50845515880f30c5bfac80bca39a2d8d61ea00000000000000000000000000000000019d02e168efb5769416132b0457ee1ca74bd5737f9364623bb270e8218c96e71dc49403584aa0a7e6c15bf6948ddb956000000000000000000000000000000000510c0917796c7ef2e100c7656591d04c3c5968d688b36b93dd690b0a8ea55694157fead964b85a5eef1815cd5932819dc8c2e971a3a4b9909dcc5cc6a0de50286294ee15f441521e0f1d2c3ad3a76e9000000000000000000000000000000000dd05e53ee40f051037c88fd28364aba276c793047007a20f893d13222c35b24e14f6c74004c3d8070405621380553af00000000000000000000000000000000191d7f1863ab7bc4ad1ebab359499f4df75b8c7a58fae8fe7cca530c7a56e5ee1617b343765960ca4bdc0245ff997a9221c9ae0132a4886820115e71e280d33378a04344f635c769fffe91e89fa7ea470000000000000000000000000000000013320367c29a4f1527e8c0f3047f776d7c892d08988c402c55e90e84b07ed7f0932c3b5fd19f8d133aa839ebd90f6428000000000000000000000000000000000f8396d819d7aabefda680c8ad51c7f907911dc4da7c5fbb7e599e7f3b758c5e7c9e9ab4de1700f72f109d7206c1be0ee1067c01d5565d0f387516d9721f7f4e5253d5af8353db4a55500e20a95f3c96000000000000000000000000000000001413f6a4ec8b21a459a4aa33ea9d92614857df629ec16990939fbb8ab11fcc919a25a10423ded219ca5b94f71377dc2c0000000000000000000000000000000014a3320275a64ede5e1221c78b421c1e4474bd499263aa21e97af103d7cb62335faf4b85b5983c5865599b709e95efc4a23bf766a1e1c068e6e8e4b60391583ac197ade53caf0f8a43c53d1bae9f13e500000000000000000000000000000000057c3c7e4cf799d716483f1e8bd4e6ec91ad9566379683c54204ce46a0e5635fd9852b0a83328386643b2017b9b551f90000000000000000000000000000000010e3d5725beabfa7e4843eeb5bcbf6e7a54b4b82fd1768a3c276bba8fb7dd25dcca7e20e74231e2f7cdf0ff50cb9cf7c2c505d4fd8287a897e01517ddbd7d7ea9d26ae4f58fbca172e5265e2b62858b60000000000000000000000000000000009d85ce8e918ddbcc47494c4b194649fdbc8de31f5f3299ea4bec7c68ff56c7f6ae916c85118553b6a6634ef9b8820f50000000000000000000000000000000000c9a680e6389d447a4884b4e134a3e025f8679edcba56bf8ea2061a00e34d38c325319a8a5efb556fc2536886e225912908006c06ceb9188651c59d434988cb5b51a5a75772ba71875444c65ddf0f4f000000000000000000000000000000000f34c8793a9ec6c34c704159d18e385dc9a127e0a9b5f95667f58e68f5ddaa272f68f5fb55e105010fb656954f25927c000000000000000000000000000000000fa1d9379fbd273b05aaa8ef5397eae24cc14f83118b2584085312986c192d2c5e3a0fd8fe5c2d82be2ee5b006413a2be8e8724c80f3527de5f0b2b98ecdf0b8d0471e63c0763a89da8a21a70dbf8399",
+ "Expected": "000000000000000000000000000000001223d94bca6cb3225511b4e28797ddbf1b1e2d059c6f7c5e852331f381c578016671b5390dff3898f9048e5868b253de00000000000000000000000000000000093eb1c50064251cf043e7c7af7518b883a8f760deac99f6e10c3dc941fed718f2293ec2cecaba6d58060374bce11a8f",
+ "Name": "matter_g1_multiexp_8",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001429e7011c17bff6df1b3237a06bae78d427720af641d2614f32cfef8c537d5ae9315c0b179af0a114a486e2eff7bc470000000000000000000000000000000003b9caa69b5495dd33139d14146919f9344efe2416b665dc262bd09ab91f3f07d1fb5eaa3c3a94606e74ee747114f347e14282bc687a00264b4e4678ff238d5205f6b6fcc10040d9b4393e93f76297a80000000000000000000000000000000012b481abfcf8ecfcaed39a4277492641c420acb65ec809a7d55892091c7f76f82c02e7baf2a648cdd5cdac45113b11e90000000000000000000000000000000015d32649850a5c99a787ceb894a66b58066c9257dafc4a6cfad2887e7a19f8af69f8d1fa69258289e417954d064e63eb5307650d6cfc681508fc7b8dcb5291837582eba6588132f46ab8fba674a1f5af0000000000000000000000000000000006038134150b97e785f33b0accd0d1991c7b97aee1acf9bf671188f61a846a9603f2d3f56d2edc0564d1ea7967e112460000000000000000000000000000000019434ad4fe571da11e2de03c891d19ea2729f4bb7b7863ae0bb8f18b53852ad4dbbbe682da2c8568fbe96c6c9a7236dc7d6a25511ba63f0b7ebd2189cfc4c551083ac92b144e30dd81d27e59dd86e2260000000000000000000000000000000013786032ab493b5026cf23fdcc468ecc486cc8179c9510d99a503031d1fe39f9caedb2d42dcdfa17173e693e2344bd05000000000000000000000000000000000f1deaaefeedfac7f708092bbe3005be7c4b56499bdeb8fc742b72be7ffe4d8ca90e605502f1863d89a41ed794e06586eac8e5cf13de6db37982390c8b6b0474795f479584960748b7ffed881285e2df000000000000000000000000000000000aff14b235c3569586e67cf5113ac0ab32d442a1c07cd9e249149d719dbd64f8ec1b07c4241af135d3869eae05ddc0a40000000000000000000000000000000013d960e93447cf6df8bb48db45532d567dd2b0756dd674625657e5364f81b4bb94bf436b54bfe9afe8eb5f4bd1be90732c134652c27da0a0272b0783551ae44db6bf592ff299b48c50c550367d470b5b000000000000000000000000000000000f85e9736fd9d3f9a839f701b6d8a6724af55ea74d28f101f97229f4b406016e50f54a0b3d2087117f352bcc28b53d5e000000000000000000000000000000000b2717e98f9fca574ad9202bd76ff6e53c74c342d1b6049fe66310040217563a4e5df460f264769418cfdc443dc31e008dca9ff432bb483ad726bd20cf96b07ab6f07170a1449f0f1b50ddc6e1a02538000000000000000000000000000000000ed8e6113d657b2d3283e50e9d054e612793fcdebfc31c53ef4f417e63c76234900c627b7e8c433addbeb6a79bcc5d380000000000000000000000000000000012f0a3095ae16b5535192a932f188c62c3cf01d2184f8e299794bcba86d4573e423a0eda4e17b4b512c5e06367e470f6146433a0738ab1b044e059f49a8af8d85546d0e34eaa0edf2b2a6ee466c0def80000000000000000000000000000000002fa5630b261e07326fb51aa2bd897ab49e0b960f769e3207906a530fd759a53db8ae17fa79c8e8c889a923fb38888770000000000000000000000000000000013d49d032b888aeba7e652b200c91042f409a6a824d1aaa04bc402f94233385254a2d1f8605d15d04013ab0de9e40a94de0399ce1ed861c0ebce1d4e811ea0a3d87e21a54ae34e6b5e1284cbb9497368000000000000000000000000000000001495234b14a93a24881f3b4425dfd82b49aa1828746b06822097c8338da57db37ddc836a9abc46f7a0cd17ec08d36fef0000000000000000000000000000000013b868cdd5ed7bf90018873ae2ec84e4bc71d002483831ab7a4a19bf18feabaa210a729ebae606ea18ce16458e997497c2b034594fa53a0951e2116db1b063345fa42dc8c870e1146f1b00f626dbcfdf000000000000000000000000000000000f223490fde3ae0d7b94412b3aa86030e5d9dca805f6ab5b025ce8e9648aa02067fd29ab9a1915c2df7b2186f35a2c74000000000000000000000000000000000aa747ff7e24cf6d1dd2c4fe9db8c031b78830e98cab27cf765fd874fe6b7731c13af69559748c81f3915f9f3a6c63bac1e6d9c5f8911014f0f540211af5184d96fdfd47c03bf2d7bbbb3bf1a330017b00000000000000000000000000000000134f8ec87b5572c062f6f3b43ee896c2e019356214ad397f703a839d39215bec954f02d3f81e3442586ba9762bb9690e000000000000000000000000000000000218735ec0b5bf9b59dee7cfc70ec4c6f21aa129d604fffe824b7ed6b6346dc242757abbe98c19c02d5235da448e331d6df5a133d3332e1f79f41201f8cb2c8c8d4d1ab0f640c4de6bd6e34884a77aa2000000000000000000000000000000001510f39616d7f576980055d0547c603d882dbe85dd0b634577fae134f210736007345d035d815306db660de4a07fc24300000000000000000000000000000000064d356ad7bd2edcd3622b1fc225fe319f86b5f7da875cd57fe5adc5bdb6443c5b09d676950e2d069bd4303b8f9206928e7219a9d431c597fe9700d43da8b545072f5a27a9f1af99053ac0494087dca10000000000000000000000000000000014d4184d69d34b8e509f3fc7e7033d76b10ba913d6109bdf842be4c49cc0c29576adae2f75e6fa054bd989e26bda58170000000000000000000000000000000019d0b70eb45a353166bfaabcb661b46eb1b7d8a59a903cbf9e43ceb6ece492e78d7f1765922e981903153072a08bde098efb8a7a5e48d5f4a011a4aa0dbab22ede62c903414d005d507ea3d77bd47a6c00000000000000000000000000000000087bc015b995ff8a840fbbf23db2cdaa8bb2dcbc38e12b588bdc4186a77409fa2a4cd74347f568c5b516879b70552df9000000000000000000000000000000000b15f04955dc27d19ad2a97a99e0890e6d3ad17d29f6b30f866f8cb3ee7789038abcc24c63d4525860e64593af02e39f47f53e2c06664e1daffd7d9b114e12d4190d5d0fa2244d61a13da915c39b8d530000000000000000000000000000000013eb2ed1d78059beb34c3fce731d42ba28c485dbc74916e373424917d60bc8c402e331e8aa2fdf70360049740e670da7000000000000000000000000000000000eaf5b5e47a2312410035d87aba7196f3f0b65abfaac28ac80accc9d87a1115b7f175e59ea2394198a2876568986fbebfb109d9a0a7b62c7c452bdf0a2853c4bf65e5439fdc83aedec8c0bf73a16b5580000000000000000000000000000000012d7a2e92adfff3d37ad21dd26299188e25b628a9e9d7b54d2eb8a886e80de812a32db9816964f2c0ad25d9f0aa6ae9e000000000000000000000000000000000c7084afff475bdc0a4ec265a3cb3f87d862270b6263a47d869786495abdd4316f6f154b997224d3a895010ce04151c34b0a931b894fbe61115fcf52be51d44afdcb96c94117c75adffcd8729b0a699a",
+ "Expected": "0000000000000000000000000000000019c9d9833332c6dd40c200d53b30e92f1595c22568b31882e24b8fb17be41f4d2f9692ca1e63106c59ba574f8b0764c9000000000000000000000000000000001414165b510abdf0d4a32236cdbe51fe2b5c9a31942710a07bb5664592a3f1b5c821edea44bd7fe185cb53b11d6407df",
+ "Name": "matter_g1_multiexp_9",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000038e60d2dae22dee4dad0d9e0658741c13d165d3718c763270292602852625ac83c5ebc1a6d86c181686cd01a1891b520000000000000000000000000000000007299913b59e2d245fa489d92873b7d2bc8921191a34a0d7f6c5774757ea4eb3d667ff8f3e9293f0d2354ef03cb6592b68ce22e379ddb8352d12eb597c179c7089c6388542909876c69ee377b14054e7000000000000000000000000000000000b07454ff91e3f9707880c1713c69f8a44d70040b44d96ac74d196853c62f264ccbe6d9c8945905092d9bef665e45bf9000000000000000000000000000000000405c965e2e8cb5e85ef9e18927c7e86e63e7aeb49f45b3428089010f34eef9ff37eb005e6b86e20236dc870661dd68c61529338195b665f1b80c4b95b7c3a26a7229884be1f4be9d49e1274a9ec3f81000000000000000000000000000000000557c7f55246759b901e4e8478aac7b80d37edd5d6be057e5aeafe3d8da008e48c96c17ab1093a6a4fb39cbe9364fdff00000000000000000000000000000000158908f112d7cdcf867f1a5b05062b92972c2947be213ede3a7fed7a477fd57e69e1de82164f7cbd53a3f4f4bad551d744d740a72e6c8b5632314408022093618321c8c0a8cf2fcd9ebacbe43505a01c0000000000000000000000000000000001701edcc472ffbbf157b1f239968924bb91825754bd4fda9f13450162e82932b8f5f39e54ec5975dbe7dc744d6d676a0000000000000000000000000000000017d13c1f6d64af2a808c3ba20792af9ee9c626235ceb9ced3c7acb4bc864ba47e55e0945a430da47da1e87f015dc024724872a78e340ccb077259aae65d6c448fe6bfb64daf4e2b6ecce2cc9525e35a700000000000000000000000000000000011231262d0fcf5a4b92cc1ed62aa66a55be739eab1316219ed2bb8d3e939e25b840b75f914cdd3f07b3f57bbc07c23e0000000000000000000000000000000001eabe4a5782244ceaa57ea0b58ed1334dcb94e449b7fb905805cefb786e83af66ded006cadc651a7b2cb07c3e3fceb401a1d84826bf78f493417a06a800d58dba688800026638316fcf9ae534436fc000000000000000000000000000000000045bb823151b691e26b0e706b8abb248ecd87107a88c728e7a627a962aca7f85d4c88df949b3c53e2d32ef18f60675350000000000000000000000000000000003342b2d1a75300ae9ffbae66326936b19c7e59fc6f597ff09f2e5d50c1942f161dcbcbba00e4a46d87ab51074320132c5a3268a8ab5a12214b266aaa4eb562aa05dd19575a7f3ba2d549a25f1900cb800000000000000000000000000000000043d72d26ee669ae8e47eaa74199feb37d51f5c99151a8f854362469e5acb2c5f6d2c208e7d674efa189fb90275b835e0000000000000000000000000000000019e6f1b3137bdb49c534902abbf42893fd576a211b93c831dee90723c7daeecdceccd3eb981537d4fe729d6e48d70d6ae62a7b00d2be967df04ef56121c95c8736efa95e1faa0196e1f4485da82b3c3c000000000000000000000000000000000837b6a981e486865dc4d6d0c123230ced707e2518277cbfd0be747a8c9c76be6aff8b06df76f7c801fa34d11141354900000000000000000000000000000000011d745300b20c5ff1e607ef3a42ac31cc55e8be979b091aac0396748e607f00f30ff579321f2e660e90e8e5f9efd4f77a883bf845d1ed04e0664d814cf0b49cf8c3e8b8594ae5d2834c753851ed7803000000000000000000000000000000000740837b02d2923815914ee9cfad663eb7246ec8c56e632cdc2dce25b6e475dbb6a75ed2ca6790f5f83fd1a274832e8d00000000000000000000000000000000188034daa9801ea182b712da519f7524cbb9f641146bc0fbf77e72ecd066bd577672c1ccf28a2c4d3cb9854cb2b9e7c80f474e8f4051c4e91124c14895fe9e2516b315d805b79013caf830524fce888000000000000000000000000000000000014ddfffbffd0317ba7e248f648cbc98fac2be9f0cc31d6476f41527c25fe8d078207965eb2382ee1e0f08a38fbff7c10000000000000000000000000000000003e492f3667da69d44b35899f425af2ba51130aa6341bcc0d4d9646cc96b090061acece81ed16c7e75fa452818748b119b3a5790750825ab75ab7422f833c671b95c6c58619189db66a6215ce907381c0000000000000000000000000000000005107fd2b5b483173992b0f2f51dc24bdba94b5174c063b52c33a8cf84ce3adefe0efe08e6bf4de3e68189e495b39c6d000000000000000000000000000000000605e8540f1c7f5790c306643a68606581a16a60d33607064dad5572947c93f3846f66afae10a66cd33621c6a2dae30c6607a48ba3fa5c033a1ef90260ada14ee50c95e5167bf801ddbd3acb77c3b3880000000000000000000000000000000012eb811b231a07e27e997900be274f73720afe3b0626104a9d5aed39a3931595f2ad57cf6e8f12d5110cf38fc8e7f244000000000000000000000000000000000abf1b8abe848b91333b4bb226b81a33aff5b8f7af70108538a3c706da182476a42e0e5c2fcdf694c8a12f62a996c86c030db724eadd2f487d31dd4354b5c0321a7983aead21759807bd893217c4d4050000000000000000000000000000000009d2b5044a8fe22a957b6d1eb20454db2cff51e7ebb6357b3c6b95387b1fd810b94eab4aef4f0a0aec4e6a693903dab60000000000000000000000000000000012ccb794eb1174735b5f7700ef95ccb67691cd3673d601dbf6b2e2469521f1b2ed283f2f98a9cd601867de4640c9517988e71d0be8fd050f6dbb8b2fb3ae2a9e593bef7a5163255aabeb07282e8793e30000000000000000000000000000000003eb6e7ab6dbf66614ff5b55ed36243e1d9baa317f01aacbd7f3a015bddfd818c6764c0802e97a42063a18edd9dd091d0000000000000000000000000000000018571d50a947e56f63b26a4377678c838de7b315e655104eeee48b7d5e6f5ee5d876b3ebdebcbde4080e022cc88c995326989184bb87a586b8752733f9ce9ea06422c6a898f0f402cbcf760a7a21c95c000000000000000000000000000000000906d5a1691dcb7dfd5d78f0688e95de2e2f06cdc70f8760e43a562365939d3fa23ddaaddfd1ddfbd3bc9777783a7ab600000000000000000000000000000000168422a6171f5ae44b645b6b6e73011494dc75e98793db2424bab311990eb7730a9a45234afb78aeff7778503cf4e5a03d1dd9cc44b30a4623a4d14861688cb678bbb8b2f8ae3ba140f60e64c05514b10000000000000000000000000000000011c20d0c6140e0e11d3ffb8c28c6bd80ec495d057775f6dc331c98b0b0aba17568e1ba773771c703068dcc6747187767000000000000000000000000000000000f88fde780460bd75f46f593cf6fd0aa25ad14cccc061d9ae2cd8c20398f24e76ef614008efc9ffe1d1884df1122111b5639d80f55e24e05e3d943340e324f6738a593a915a6bddb40f01bf12f73daef",
+ "Expected": "00000000000000000000000000000000018ed322f140a351069f18d039ebded8630fd019e8c6c401dc760ec5cc6536bc2f52a6cd5400dca0caae95e4b9282967000000000000000000000000000000000b9666fbbe91ec8bd670b2a64571a34d689eac44c5b63a43f60da08df51b003d85c03f0eab3e2042b1175af3501de8b5",
+ "Name": "matter_g1_multiexp_10",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b42381a83d4472a3a7a18d2ba5266bcca254fade1170c6f55d442aa2a7674008fb35c58d5a638280e0ff7531617a768000000000000000000000000000000000eb5de05b5cdf9f95c5a3ad30ce068d5491006640be4c7f02b7498963b5769d516efb9a117c60c1c5fb71617d42c977142fe1e5b3c0245e5cfaa1ee8dd8ccc4ea8878ce2272d152fd8b24032297ac01800000000000000000000000000000000163ee62f1ea9219b921ae7ed0f121426fe9fb8fc0056916c81ea9e713f1a16e3f2bec6ed0e3e552a7173f8dffcde82bb000000000000000000000000000000000f5fa0e4980d3d2b92e98e76e5d67815ce55858852f03ec7b8809b02d4b1e9e1a6c8b06bd481d9d153acc68378e779fa253bdc5565b6ebc219a75ab74dc5ffd304c94e67160389f87111899ac07a71b7000000000000000000000000000000000cfbefb41304008b0e7341451f13d65681f0726544f14fd1c0d02433d3c34a4769f1456960cfdb11b6bcf016b906228d0000000000000000000000000000000001adf387f4feeb3845b12449fd5294802ed30ae211d0837eff1b22c3fedf538ec7119c1fe69ed7d595f7c0fdcd54f684acbf64f93f6f85805517ddf0358ecfea1fd58a3666b8dd9d3773a28590fb8a13000000000000000000000000000000000d736d3b8b586e09d6ecb1ee2d7eb28bd68aec60234e90611da8f1e1aedebd9c74718d41a89186a4a5dcc3f7cc81e99e00000000000000000000000000000000000ec0e89da57affa4686494e8e0f5517f11532f6e294215bd060c370fc64c26e34ee1e2d77cf341226daf84791f5e3cd9d3f97893eb4f14f21f68110f612a444815fbf2f76b8399ba6045c8a44270df0000000000000000000000000000000008fef795f8bfb6de5feee020a9363adb1c26fb521439e405570b4e997f55af5783968b24d2e95144bcb6b38e4ef9497c0000000000000000000000000000000004d4e31720644e8828faeaeff38985ffa4fa2f7bdaa476b5c4d7eee81c89491eedd3f4262effe118a4c204eb555abfbd05fb554531f53b8cef8d93566df80878baa96f92bb54aec19445980b1a1f6c3400000000000000000000000000000000195f8fc4b1ca0c7041810b02bbc38b8bcd0711dccfd80de2b2f357f4a732e65492d57f455e99fc810d6f86eeab0ac101000000000000000000000000000000000e3010ed298656b91b5aa342f6be7250cf5504fc3aa26a2c7f46f90e852fd7799d96a85b25e6066b7d24794648a81331d79ba2c485f0aa0e35212fd7fecf970258903bd2427c4c8b97c2c425ee11909900000000000000000000000000000000192cc18dff89d9a94e6f0498419ceb9f21d70e42a1b9b64bea093d67075d499184d7b2106f74d31ccd1863beeb7be0a9000000000000000000000000000000000b80e940dce71be82106640d99c121dd21e99ba459f0dc8b1f11cdffaa0d8ab295b9711c23de1f4bc35120a89948b91a44c7017258bb979cc9bb8acbd3a3e62eac7aa152db46cd7398ef07edd031e4f6000000000000000000000000000000000b53f55edb182dd08e2c9d0ee43aa3d734143b54686295410f80086d3aebf6fc681d1150e808d684f47b0eb23fcaf629000000000000000000000000000000000d73442636f4d5dd1374cfc7ab29b995420995bee9808aec29ef7d1aac08c0ee51a0390330a863295af6129b7e8171d82583e821328ae90a7db16b20525228e8d915bc8d46a642cb0a06dfb64168cf1c0000000000000000000000000000000002bd8316507e6eded2034cf268b2b4660211e6bea2e82b3e3a0902bcda0f9ae9980b401f36178f681691ee7c10dc4ecf000000000000000000000000000000000e9af98fdbd02ef62ae90f1e87c4e7a8eb2089204b1c58dc6e59fa32d001c97f22740d8a13ccab23b5a8842b693504a8506f22d323a740553d6107e651c192c1dc6e0a0161a82351f125f08c77e53fdb000000000000000000000000000000000aef5a5d5b46d340fccdfad359b0499a5c62ff4e5d9b9d6f7a5fd6a97e96820b7fd226e7a2aabaea392869a40cd38e1d000000000000000000000000000000000865d32d825149d26b60969ca567ca85af5e280b835cf541b20b0a4db83309dd2b5700f802ed9106af73b912dcf9630b7f1bc0e1ebff8f935330c35573f9fc3b900606da9cca9a36b425977af47c7ca600000000000000000000000000000000153310de30b7a485753dd8443f8638c12b21083f6133a1c093648bcb566b33f73631c6fc558f32abeb0d6df8430e61a900000000000000000000000000000000005be397e9f77556ad952dba0540f46cbc7db910d5203cb976e168a7be3a3b8557c5f08d51cca9379552694a291d67fb4429b85fae16200da6eb8f62e95e027c24aa6ee2a145f6ef225139f29aaca29c000000000000000000000000000000000cc75210c78f2e7903b7c33379a6ab412e92f35de51a152cfd2f4a5d122f9e558b617d8a09670990b7f056e95eb058ab0000000000000000000000000000000000aee8eda7c1bedd39f97efc60af110e64662b9990257beff15ef5e7856e5ea388df058ed8aa6dd93cf5a81ba48cb88854a852baf21df9f4ec8d711a48e6ffb36be8c09c8c60eaa090876236b2eae37a000000000000000000000000000000000f396976e55dc0c46fc4543a8dbf690b8da7b6010a03e04c9010f01abe1b3beab8870be0b6a2c6d6afdf85c6fd38d8b70000000000000000000000000000000006c60eeaa2d94b571df8a6291c2b12b2ce9f17f414264e4af2a006d6aef2d70436ef0978139751d4ccafce200f16f06113814a3c6386b19f7b93c2c4e0eb1568e8bd3f0012a1ae1357b127c33808aa04000000000000000000000000000000000543f8d9faa2b3cac2518f1462c297595ca10d8415143c8ff3feecfa58b648d0dd0c25156287b2f29f3b6f9a60f02701000000000000000000000000000000000be673141c496cdeab5ba8604e081ed3006828c7c877d8990efd29798c1ceae3093e052f1f928fac0c5cf84174283844aba0fb0440b2461ef64af6ec5f15db381714fce1da6e03ca962cfc94bba26d74000000000000000000000000000000001342f79c96ba0a29de9a77cc2e10314bf2e15a7d192a90af9c025e2f23ff30fe49cf239b180cfb6f8c35f95c115777390000000000000000000000000000000011f0bfb11be253b3680817af2b929de9ccf06dc574d17cf6680643b87e5fadd06b54224f155c1393c870c2dd01d6bb07c01749cac36dbbdba5662687fd1ea5391ef9d0bbd24e05bb5904a20fa6a1e11e00000000000000000000000000000000183eab3c2a127818862c6cb42bfbc9d59c51043dcc28c68d3fea08331323c9dd50cc34a4ef66a97f98684a5d9a982a1d000000000000000000000000000000000228f8f774bb68f966f3ffab5d0928a59707d6fb4f6ca84fed831a8212f71085cdc27b1d52909bdc005b3250f26cff3b9680fbd6e6c7b1b14b000d3d18bf93242c74662ef108d711d85d8d442e415ffd",
+ "Expected": "0000000000000000000000000000000017ddd94df17d52e842abacf3467f4461e345cbb680ae624f98c6885e40b17940bc240da17ed0a1a45f13f2ce4ab8dc100000000000000000000000000000000005ea5144aa5d5393b98db4d23477011638dba465a542dc28691ee2807ffc08413938ffb74e16c7afc507f85d76acbcd1",
+ "Name": "matter_g1_multiexp_11",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000023977b65312306b1a746b94bebbe79ccef0342ce833684a273d8baf74e0ee71104d6c453acf02d0c4f3909144b1a3b700000000000000000000000000000000050494df74705eddbf97da56a21bd673e2b0d3a9cc157168b8b413a89359c9c48f09e756f8e6ecc67811d4bd8043bba91ddff10527bb64de6ee2e3ab4959ebef9e7a6964b7482f9fae396b2b9b0cff9e0000000000000000000000000000000015862e2e3cb73ed2ba6b0b69dd9fc4c308c0a79e5cca2d2a42fe94e9b029b22b5b6aefe0503798d78d4599dd5c201cd0000000000000000000000000000000000c49723dfa37fb1592722b14e6c75110cf2252ad5170131bb72fa35bc359470bbda292fc2a459dab89900eb251e848e12943fa2957d267019309f4fe5b6725379d893dcc270ff7f35b3811ad1d8d12b1000000000000000000000000000000000af2d03791884033b8293fb636b0c569d9b008b075c6c71ddd7b0c3f5e139a17e1fbb18144d1ecf491d2fc40b7369c0d000000000000000000000000000000000d680b707e32626219fba862cbb18e39e03a8b9ac78f7bde619049748f7f0e49cc0223f1111dfc1f5c851229e62a9cdc1551a3c2d0391fd8dedade892e8e2171e652d2a9b52f2288451c55f77fac788a000000000000000000000000000000000b442117cecac25834a442ef457061634d863875c10e1809a3b9464eef6760f074e06c046a74bfb34f4d16255cd4f62a0000000000000000000000000000000000febea79eb8102b2632b6fe3151d9d972d5dded2893a117a6cd7e2bb662f042131cf06d04ca5c88c8535155910f9e008eb2fa94a5c97c28d95008dd1fe60137b34c2e763292d1b86993c02790b8c91f000000000000000000000000000000000d355c97dcf055181b8c523bbdf7eabbf064159c15532bef1e1be56146d72c08eb5d6994a3be7d6f4a4ef204f0e6d8dd000000000000000000000000000000000cd6d4e6df1ef7cd5fcd360e8aac511a3aea1f3e29536c193f4c3a2ff0f3ca16ebec620cecddfa8f27732eacbea75500f72ae1def6c988f9242bff0e683b8d2a5c1aecfd6ebb9442131ec5b5b825d0f600000000000000000000000000000000072ff95f5cd9416eac2cd83781acf856a0bfa567a079bd3cc909eeaf5a3fb31090e3e2ccc3acd44b6b04b47b5b8609a7000000000000000000000000000000000b7a39ab3ec7de26c86eee5d8737c7ae7e5969b03457b7b7b5720e3492ce254a63e031fc477361606a24821830d27271331451748146f0564ab0d91b09db87e8a6ba8b14f8329bc041911616195f9fc0000000000000000000000000000000000886babc1acee93b5f96e4a0700805982657d15170c77468c77000f21978f0cc154a265de2f766d6f7f8600f378b219c0000000000000000000000000000000013cc47f0a1e5f7315e6ddb9003dbf901824e419854d234676e4a8593bc5ad4c15e8c59ee6985d0b729e7d095e9b7642416d298bf591bd927aee24a37c5ba508c3bc121f5150fcd1a70c1f27a79da7d73000000000000000000000000000000000567f08c96b8431a133cb284144f6ec8f7c68722f18ec257b4def0a18a754507eb477f405b8c256adb797f45ed2755050000000000000000000000000000000004945b59bc84df7b793dc759bc2a3352b3eecc5cd59bea7a9560c06ef25828ad2e9ccdc6b3beab7a71a702b829208b8556be810c3fa86e35bc935fc2b27971c9c41d03c8ab7b6c8869db90b6e0986ef4000000000000000000000000000000000584ae62e22e0c2fd733cf2093f7a1f3c763453cc34a7a7a4548d8fd43c95f13be06da4e41f257f6d38e6e6921ad0f6e000000000000000000000000000000000dc803ba6a45298075a8cf45939a61760de44d22407da6ac0d63939918daa6f78e8d0b7cd794256f992cc89b8622e737aea4445926775a6baffb4dbeb249dfe3b3e0c29f2a579927f540d8f6451553ef00000000000000000000000000000000090848e332eec39e026eac0e6416d1ecd5aee8b4d82712b6c113da1e7d38901470743af43bae951d4141592f6057caec00000000000000000000000000000000140f8aa557213d49097ef315a18ae7e62924a97c71139555baf08c70674031934b629a457f75bd801af579f9fe9395579ee0e58d08779add74b68dd75e82df172b719cb5a772b0bbb34d3401b9f212ea000000000000000000000000000000000e29d6fd73f56b4546358967d7f0080e6cad97531e3d672a91a6dd121f35cdf0f452dfee1ad98b7c832c2878b495f3c100000000000000000000000000000000050fe9818b36baa8ccef166247bc673baa8424e19a19b199ea5e9d0baf56fd68cb339fdf5d041b31545e28bb2b8fe32c773d07cb9d20744a2c3ac88082a8d6606acdc892666753793a2b8bb81116cc6d000000000000000000000000000000000c13e5062ec580886d09c87c7cc72f7f19227eca99b0092a7e9759672ed1405d21fbdc8985847fa1b57129ac40bb036b0000000000000000000000000000000007d6407d32f846088759be5369c5ab66d2f512f00c93eefaca86a86bf7b1e3ef39ab85fb6c317c28c4e331a19b927650f6bb1445e9146b117bd0c95b009fba670a5391874dd314cefc884bdb0a4eba6800000000000000000000000000000000112839aa4daa7b0d614dc6a555731cd4b595a0495f2a2f0f1a3b3fa1b603c36348e265145583e8bdfa8a2a26c1f822f1000000000000000000000000000000000383bcca42f2513ce42342f4bab5377ec276bf0f1910718c7203d450f15c5b6a3648a82e4cd1222109171030eaf05292d4158de4e23d793ba77c24a70f0ad07314927fff34361b0d74b25e8922512d7a0000000000000000000000000000000010aa255df04dde054fc069473dbbcde9c68dbd71048b195df2b23e5471e5cd39eab5658ce689ca09db80c72e099907120000000000000000000000000000000013cfb46746c9bd13aa88a24ef3097b35ee2302e76b19ed001baee8cbe5b19c2620043efeaf81697ce48af0717a1066eec629ef41d5a2ce49fd81930406f19e760a47074e159ce372dd67e7ea46ad706b000000000000000000000000000000001888735aecb7125b08f2a840957887fb5be0517788a8931fdb8d280579776c5ad70e6454303ba23908bc6fb864a4ea290000000000000000000000000000000019479631b9c711f700ff2353aac97cd0ddbf14669cc046e686ef19ff0bea0aa74b4bf771882f7226de0d4fe356301912c718651715ab786b4855092ed21be41b499b7824d0bcf68ad31b31ee4cb730d50000000000000000000000000000000003233c1edded239fd465f7f7833251b98ffed6180b56676bcbe2ed361438d26db671c03a6454a4fda34111e358eb2cb10000000000000000000000000000000003cc9768ad0576a34550b913a895e2687481c6adb3371bad5cc8f9792c61aec555a52bcb267c337649fa00293c9b4af3c685a2872c4980518fe60c61e2276ef53c007166f7eceb355b4cd533f42c00b7",
+ "Expected": "00000000000000000000000000000000117879988edc3cc57fe19ab04eee6f9e94a30811b809afe922d63bc3d785a3a581b69512180beb89402410a4d8abf6620000000000000000000000000000000000beda376a5f1499882c560961f8b0cfc44c712d6691677ea24db18b138af8a21a5a4fcb9cf5814473b0ef7c00719700",
+ "Name": "matter_g1_multiexp_12",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bc83829ec8e98081abac2fa8e0572e819b570b2499d4cd1e6748f48c350c392f5d52c672dd0bbcdf1469414d7ce929c00000000000000000000000000000000007d1574eb65b391475b49857766c808fa95ac2a78755d8d740d2df90bfa9aab3dd5c850d536c9794f6cfa2f004b4550c067ecd54e9ef59996493f846ecca63bbd7ec28da586f0b8d41bfdc6d97a35cb00000000000000000000000000000000022e4ed74f98d69a9bb1037a307eed57210d3ca92648ca9c54546c7b57102558ab12f5d2bb46502ba3c07529f64b72b30000000000000000000000000000000005ea660c44a9d36696a899ed1bbef1d951656f2eae553f4f124ac9cee3d7de13556a7884ffc07e20d5afb7bdb9c6f1638b5112baca5e0f2bfb885c5041189612918d203a117d886bcb3b27df7e64d17d000000000000000000000000000000000f6f9411caaf7bbed9b05368ed8bbc35a0439a5c1ae417215d10adaab203aa0a607642aa8b94f4846add8f5f8db755530000000000000000000000000000000012eba1de04ecff3405596452a4f5830bc6c8af2ab0e84115a8a04a2cf60400eb741e8eda78ef733338494fd4e7b16f812db7ad39ec8129e9e9206bd46cec6a8ad3362ade1beaa97befe148f6c67a9c2b0000000000000000000000000000000009898acf9cacee1f5750d54798a4c31796fc471a17c9d2ddbd00262f5a82e3ca968c3e02334c29aeae9b16d8916def1600000000000000000000000000000000017f5a3907bc14b6cf182af2778c88704fc6b02d2b47bbbd6e40a448a89ad1455f868dba330452112973ab69489534ece2400a11d9a67041824b97a96f0ea9da8848e7990373655d76e8bd4eb84df5dc000000000000000000000000000000000e782486684a6c3fd7f5977fa40038e8a9ac0a8611e79c18ea5328248be9ad4d95c63ba9ce41d3b4d85701283369063f000000000000000000000000000000000a98e9f649d2431991dbad1cc7f4ea0c89a58bd7e75e4a5bf7d9a728943363777c1cf84bdb1853a976e4e66a6d3fa8cbaa2d17c409ade92566ddb3913806723d41067540a36a9c283bdacb273c5b258a000000000000000000000000000000001171bd468b4d40e77b8264e082cf7a168d88ec3c21adb6c33f215e82f5ff3d0d2314e0fb12d7ec93aca92532debde74500000000000000000000000000000000099bc823a44c54fd379798eed2559d95275b324481c248d452a02755e1b5a48a7b0694b637dce4c21ad7d73a63cef2a3e5e3d21862b64e09a0893ece646de60cd66aa483662125ffabc46cc52f1cdefa00000000000000000000000000000000190f9d82f079757ad752b17b419c63ca09e3c8a23d0f56b1e738dc8ff4d588a4a2360687679e51bd75615c18c49103c400000000000000000000000000000000191b91de53dc0807b537540e81d9219daee48ad27de9e5ab2980dcc09062b80dad2a0a9024c5b0465e04e6ea2b225d0249510ab1b7850badf58cacad67fe47135f6524f0d160f3013e8ff1c881e469e4000000000000000000000000000000000c8f48d3dacefba0e1719f74867b539a65d640d2372ad38bcfc43548f7ad3d8a04337878529119b9175068b511efb04c0000000000000000000000000000000003c7b5c11985fd7ff7c75e2cdd8670f75de655aa81f6b99206ed8a344f86ae85d2fb14bce434a25a5ee25c903c238341713aa69664a8c721cefa7d6dd3fe9f92432b4d350621d5297805fcabb21ff8c600000000000000000000000000000000055e115a8a7edec3a443354b381f584ba13a5802520c54b51ade1bfc7c93c96c7cd66254738929aea2e88edf2895d82f0000000000000000000000000000000001bdf3f4b489cc22c6f57a1eba23d3348c5567d0dd1cc82924873813b92a0d0b2b90727589028b9844d351e13c6e3868c040d8bf0a787346560fa3b100b2dd9adb3f7ee716b8103abdd9609363345ae400000000000000000000000000000000041fd1625afa48a446454d6613c17cc6a65b3ec8b8f2125c0eb7b8e5d07968397d43969a6579226f496d9b24dbb71b820000000000000000000000000000000006131c506f243b5ac40354f826ac1838839eee9f61301aabd88e499d40e57df3122edc8b36f0a8b16b72f9ac783efd3e17b811aeac4fb7d91abc655f8a4392176f9060346073c957ef903e25d10935a000000000000000000000000000000000113a08cd0728cb3bab3886681d8cd4e5f14b3a4a7979f9929ed4d8dc77de6a65f7bbbf8a282818ea3f21e6ea59ab1f5100000000000000000000000000000000032e95b26193c9768cc9967c9710c7695f57fce8a4e089f290526842963504cc8c99981bed3cc7d827eedcf686c813c3bd1f096026159218836a46b9801a4f0c43189324d20220aca777b826eaf25752000000000000000000000000000000000ac19ea5cb7169ffa2741bbef922e0ba307e2bff5eb67fbd2c1545bcfebb79948489605f3c6c072444093e996594c95700000000000000000000000000000000111c277e16440fc3f0cfe16bb81b927cf76553fad040c1825210fa145240abb0bfc8a40a016db15844b8830d4d725da3f221dedfc21098ff9a9507e493d0fdb1efa6029fcdab23a016515078c76f7627000000000000000000000000000000000906df246466ac720b1db9445902aeba8ff5c747133b037f29b33880b3f511621a0241fcc46adb0532682feb4e8819bb00000000000000000000000000000000145b356e384183788358353a69c49332ca137e9faf30bbcd7a67434a980c27630c3f21781a36fe73e82459318b59331bba5b30d1397bf28100f108b84e05107ddd6cae2e82f1973ce187e8c3a7d02f3e0000000000000000000000000000000003f2f02b7ab2d2165836349ef8f53e42d223f4f6a892e7b72db93362de3929fcbda5edc4606766fe26ddfda9d09b283b000000000000000000000000000000000feb10a6ba91dddb0829cd6b95a78958fd55cdb120a7237a2842df1a2007530775848c3976804824698a4370fb022bdc19aadc83d1db9140af303c0492d2b9bb9e2b53ddb62cd2132bdf8ef62aaed683000000000000000000000000000000001433eeb265f1d57027a80189806d071edb1f5ccb97da0b5e00dc75eb88304ef2eed287f5d74264245684a1677a23b3f5000000000000000000000000000000000be2d2b5fd307192ef8a0b2b4dc9970c112a236a71ee899a0a5147012a206a0274d34901594f54bdaae26f2552da481b87eb6fc40b00246910626ab66bfbac96ea09242d1d70496466e4d681942050700000000000000000000000000000000011b50012e0d92c0f74e3b6e83d60bf77e710dc03baeedc949c1af218bcb87ca1528a745aa819a5b615ac355dec360eed0000000000000000000000000000000013cd46e3cbe008dcec36e64285173b7d545359c23fea32d3a1fa2918c5c5d671a87d90791b70a740564c0f731fbb32013bb5926f36808c0024ea7388998b4cc8c6c48d32917f6456b39d514143c6eded",
+ "Expected": "000000000000000000000000000000000cd7a2b89d286a421808305db523aca962c3f253f6defcfee9b74bd7f00b3ca8521b520376659d584b03fc5dd736d3f800000000000000000000000000000000117b8b8a8e299cb0fe3eee45651069a21988a2421b1d349529cbaf7362425349148fa043581e5fd275cc94a4fce44732",
+ "Name": "matter_g1_multiexp_13",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016b98dda34f703f90438f5c2624c1ccc870b18cf8eb964800ec97179f67f82c521b1cccb1b81ebd3484da1349e4c0cc3000000000000000000000000000000000c743850f15041ed9023ce296570036f96db4a510903a0e7971592348651b44afc0091c8f0d6e86bbed8bd3f6b28072af44b0204792359895b448bfe6ffaedc14d54a6d72be7a49718c0a933807a399d0000000000000000000000000000000007df1648d65d140c775f729e7739a807a7f430de0711671807a7154a8e5723a2b9137175d47bc319ca659faca10af23d00000000000000000000000000000000199ebb99b555fa438587b9badcf5d7858029e905b97229f1de4ecc1940ccac59503e0e1a99c9571d50ba39ac3619699bde25977e7426cd5652559626ff8b195ab7ec679de987a6a22a6a0e366759dea0000000000000000000000000000000000027b64caa979063b420cff77cd259e54bf86498f87e7297651f9bbad6087a8b4b704b27746db53f8869d080a22363c90000000000000000000000000000000003239455ad4ab885727a25b0cae5115d87ac9ccfd93120ffded5130ac683b3b2485fb358e3aca3b6cac4bb3da5b4210d2e7ae497b44f531fe203a599622954804c06d5348dc17eb1537e750006584b210000000000000000000000000000000002f14454852a72159581b8a931d863c65170fa9280cb811c697fd067a505910d17fcb71b27963c2a6a02264aa0e1fa04000000000000000000000000000000000303f0857d990e90e19a076d2d331f5eb7fbcf102dbf8d4cb29f159fa2277eb413c0c10c3b501cefd9ca581ca62876c5e073adfb5ab96730c53015a4ab6210a35a37b2331ff5123e00798c33e040a91300000000000000000000000000000000192b3fcf7dd2534f226ad51f40e7256064eb788e7c91b1155908fb752ed4e854fda44af13f0c681fcb818eb4202eb64100000000000000000000000000000000125b51b4cf8e9427db9baeee0417b02c2d296ec4adfd437667238ffe5137b85b40fca4fa705f81d0b4b6d788a8456f1fe6e752d40d411f1ee6e67f48109c9a059226b446601047a2189ab815a3fe13c400000000000000000000000000000000130798c851758638c03f90f9181814eba97c5f93de85a71bbcc360bc53e4491e8fea38ff8c94061cd5008b0333ff26af0000000000000000000000000000000014758dbfcbbf0e1c78fb3ad4945bd300a74f2555338a009d807e2cf0e5fe582729556bd3ecb79db131ed9a72c3362c37e657fda33cf4ed1aa89dbc19d58fbe3043acb5795dfb8c0cb97620f16f8f243500000000000000000000000000000000093318a1c189c8957c9736a56a4b3e8da13bc8a303303bbc106148a0a7f319e30f5dcd11787dcd3424255c7a02cd3e760000000000000000000000000000000015f0767a3a1e3c448ecbd4ac8c4c70db6daec95a1e4b3a69cb5dc10fb43f8ad030e360832f7726cb166e0fe5fad0c860c73458e18d6f832f362dec7c49140e6523ead045131a1b719b0c836c1ef13a79000000000000000000000000000000000c7143093aea0143c58e2c459472f44b6b759a3f036aefced481eef6fb3a1b2af72ae4cc4de06af2a8a99e27cf9cae140000000000000000000000000000000019f44d1120d82e50f7da3c1e87a47d3433152b7141e9085eb54e04f30f5931d067f9ad559cf5d092dbaece723e6a724138cb0a2b191f538b30187dc730a8c665bbfce8186883500baaa6c3242a0d14740000000000000000000000000000000012a171d46d2bbfab83d02e023f5edb18e353ea82174d1a1653952bbba234c7de4fd5ed212c81f795e8c7a0b81e37087a0000000000000000000000000000000015dd85eecde306a845917187c404cee066038a764beaca9a58b859873b06652800291506b4c995581866a3c2bd7f19618a27de64d41d13ab67c1f7b1a7390ab4dbba7d219dfeb31255f9401d5b3c62f800000000000000000000000000000000176e512a4122ef10ca1fe6626cd2c839d4c573bede92092e5ca55b0bb936de9b62297b2a598a033e9a7e49ba9aabb9190000000000000000000000000000000013bf0f4c0dee3c9298192748497803a906e4192333b1ca61deff010a63eb8e4cbd63c7bd5b5546540e71bcac6000eb5380030798960729d63db70b8bc3c0030e80d9b8ae766e3330128557e6c34442f600000000000000000000000000000000066bb65bbc3f8ed9cdd5cfcdb121274427ab7dff904551a60be48f8197c84400d54ec27ed25c2a09687f1067c10edae5000000000000000000000000000000000afe1e97e1dcee30959a6411328f0d69134bb4c3a0d5ac53b87f254593f7cecf3070eaa9e19de76ebc6e1052a41ccca00d32b6969af54dd345f42320ea96def3c6f4dfd4e22a82686b7a3c57a0df5250000000000000000000000000000000001439b3031d7272f92c7072c6b44dd3a1c328251d34e1fcafc5f864b7072086168fa6f398d6334fe7fc56d6fc0e776eb600000000000000000000000000000000090885199f56df470628357ad224e19c29dc435ac54b8c17a7df5cdd24c3fdfb136952063dcb446ffe271ab5775bbc51969848f1b8b36bd28967b762168edb451322e2f0c4b99b7f9112c9a66093fb3f0000000000000000000000000000000011a0c8f7d76a36e605f193efdb5f7899d7db5b89ab0603dd6184e69a7e51f0d7e12f466fbc917cc5b6dd6d4a0bac16c30000000000000000000000000000000015dfa17cdd22984bec570d2ca24a5ac373f6f174b66aed70a15ec892caaf92c73ad3d7ef11b2f4a0104df8ec5397f5e9957ee08a513c5e22bbec04722575a9b4f3a1343db0ae5beef4e66fbbe1ac90440000000000000000000000000000000004bfe701f6645589925b34c1117cf62752b4e242e38bf056ef36515338a5c3698f561d65b237123677d926c1616618ec0000000000000000000000000000000011892535443daffffce0867dee36b7bc711006bc0963e6a061066b889adcde877a8dd3661250b6bc48064ed9dea304168e0cf0f590f77d13819001916d2c58a654d0b9d3c47c842f2d649cb2570dc0d50000000000000000000000000000000017666cd38f1e7139fd032a79776301e4eef7fc22c144900c711f1568634d9712b2e3566bcfdd152faeef20b47cf6cf7100000000000000000000000000000000150c30df0eb5945ab96603b0f36120a4f697b6958a9929f6dd8d1b8a34a1d1d3f1a34bddf9ff7f1e105ca23ac34b6f7671a8c2a479dec43d644ec4113142e666bcefd6d729d4faccbc147effa836ddab00000000000000000000000000000000107f9378f695524614ba000d6fd1b72c5eafc4ee60c5ba36ddb72814936403fded547f8d15083186f7f5f5d94c1ce18300000000000000000000000000000000140bc17d86038d4fed0580582f55d90259b460ddaeb37a70063d09d83f5fb6c803f8b467927758cb7cc52a2a6f8a84ba2d2d59a7f138327a20263d6338d2a92fa5a2f741daefe9aa81d06f20a6fe3641",
+ "Expected": "00000000000000000000000000000000179ba87e1596396fb5cf88f91f56e3fd6f01dda6f95363be3365bd42960ed620b7648863524c22663bad20d128d22f4c0000000000000000000000000000000001ad84c4e62b0494bab4f2ec2931d2331d88502674a1bf58b765eeb022f3d6fbe8f8546818d965a8be79a94be86292c8",
+ "Name": "matter_g1_multiexp_14",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007eefedc0360b258ca2bc9add8e23b9d535f35332e7a35952fd832d7fe3d448aac08a01073876a21914a501dbca513850000000000000000000000000000000016188049abc44154b244c6af4e115caa14a977efcdd524ad78e5dce010f2f48259708d14454630eabf2318bb271315007740a826d524fdb7969776bede5ada468a0115229152907cb2b050760c18c8e20000000000000000000000000000000010a19a7cae27e432b77c77d26653c6f17507413a5037621bdb096fa4f33e68dd86d5aa3b52fa54655730fd88415c3eea00000000000000000000000000000000031925aae4540280dd6d08fc53478fbf05b0ec784d04abd04c3a8dadb04ad9adebe87101c6401ebb4a808104b3d7e88fd226f56bf3935ea95d976fde5790ba0584e5bbc78b37279aed8e50389899b9e9000000000000000000000000000000000447e249cb49d64494fb1f1b18c94a44791fd8d4957bac13df1f992480f72a14c3aec517184700d87200092e866d60ee0000000000000000000000000000000018a12284086bf2f64297a65f6c8b55b4ff3b791372b88aed9085152e24b1214655a74a182e131d7023f949c8cd9602dbc133e1989ac82e4d1c9852a6c7156a34b05784a58231d59e3cc875ac5834d5c8000000000000000000000000000000000780d3f5c10ab7932e3e3b45c942d1ee2a12f28070674d9c666016d084613f3ffbcccfb576fb7779feb2d0e614106c990000000000000000000000000000000000ea320730367c89cf162305c69ad594d8730d71a910f53143770f50024bdbc40b7d2486b1eec63b1ac7dbaeb51ef9640fdae1b53f6442c4378774a981c90d282d5f8793feb2334470c873491e41740f00000000000000000000000000000000049ff517593107482da6805fe4ab49cfe9cf71c9a95eba00091511719eb76db98f71f089a701c6c136b398a40dccfee700000000000000000000000000000000038d1566f1057bb2da7813c39374b79149e598e1651dc3541a445264693495dea35a6515dd2173f7de43964dd5e8257d70f1de7cc5e6a2cf7dd4b6e60ada67ca47e7b9417bb5f599048fb0c9b2abf33d00000000000000000000000000000000016baae36e71ce87a6dd7136f7572788c256ef88cb73e550641f14a557828e06ad64f001fe78d69465fed92b67e8dec3000000000000000000000000000000000613a6b87249bfdfd01016ce920aaf902de85c066c2d64c866ca0a93950a1a971cc561560a4122d9a766e38f9dca9239ca82cffdf59b742a736ae9a6d36f7840c46c20c126ec054f47ad52a22948d721000000000000000000000000000000001921d310700ff4e2868a28dd29ae6e0216bc27ee9463cc8dd2823a1b4670abe973859e86719142525ae5c76e2df0bae0000000000000000000000000000000000b4b4952e96be92ba6c78037e529c197c9404cfb67af04f39d24045c742b34a700057b2cedb3193dad70e64944642c01fad69492cab4ec7eb89ed37f1e7fe898ff49ffac4ef2aeb75d9c6b544109a08f0000000000000000000000000000000001dae69033cf21e6e1618efba143426df1501250c82f214ecc9ccbf957e685d9831533cf7f747fc22309227aca1d1a2200000000000000000000000000000000114abe65155656679b89a11c7961435ea9f77fe2f957833dfb61b8538695e2569e509f0ee2c0bfff75f83d9399a3d49b5af71c9baaf54967683f8553f72abf789da465041ee5a92c9ce1ad562c91c4d700000000000000000000000000000000128e019ff92e7171d3c791bd4cf75b0f47c2a9d8722b4a8279f1178db6dddf8a4c00083a935168518a1c26a56b23624f0000000000000000000000000000000008d0c5f3300e73682f4756e6ff1d6722dde576beb587301ded34427d6935e59e76cc8a8cb0ea5f659db9ad5435851e53c7effc9a7fe773a420ca430c58bb94e7baf26b9a97b618a15e7a18b31e5914f1000000000000000000000000000000001110168c2dc1c2f0df0dc645970c0feb03bd644fdbe1576d5e5a8090282bcb81ac9be738d18e72a31ceeb5ba826b40290000000000000000000000000000000013fccd2429da394be698812af6c3288e89a26f0244327cd38bc85d5c3bb934004bfe24449534b7d271add7a279bdc8512d5a3d0370f4a58c21016d208609f1d3e7cdf43abdb85199bfc67dd12f589b8a000000000000000000000000000000000199b9c9772a8c1bb0c015c467098bd38b5f73e5d0b3f627c8279b8dc853fa2952faad01e7be353a2762b8144cc1614c000000000000000000000000000000000f781597005df947eaccca59939253b936d1ae84805ec27dde0dc707a4583af408672addb2eea607a14faec9dabe61ae3549b86ed3fb880269be22b9cb8be6f24385bb5e24bba81bce9fd5b72ce2ab710000000000000000000000000000000014bd5d22e4bd2f7b8df4add90446650fd83d72d531395fb35dfcff72eca0886ded935e7a0e3fc99a7dd07efa1ed60c3f00000000000000000000000000000000122cfac9ae5c98dd162576c92e9acb4582b9eb67117bfbf4074654fc8bc473793a7139995666447a7663f3af1446dc35c8f6dd56906fa13144dc87c31b53186b0683cad220ab2de89d2fb515bb269cbc000000000000000000000000000000000f67ef1eff6875abb96378e5a7b1602b5dc553554987589b9953c4401fefdcc5cd7b196a1a65cb3daaa13f9fdd703835000000000000000000000000000000000f58ef60be74af52c23662e6b405f1d5c359b2ce9d15b5e139460e10da0e31161fb52f529c7b406e52c6f600d5670f3c9ec934eddc44729d05f193ac927fbcb022288ffb2bc7d4f46d1bfcc7efacef940000000000000000000000000000000000b7dc680fbfff55bf0cf276a864f448d5a9feef303d2416e7d87d6d669456b951a8769026bbba545685e1f92277b182000000000000000000000000000000000c36a14d5693b0d9d91d831c0581d1f4ee801f86e5c32f10cc400f66b58f247594c30f0059b4ea79995d6f9d90b0009ebd211ec887635ca841c4608fd00bdc0f5fd0f6365dcdfd7d6f4c36f4b25b5b1b0000000000000000000000000000000014dd947a01add8294f97a84850e6dd11ed4a513e7656daac5b725cff501446e95e3b966492e028ec23fe1238b53d99ea0000000000000000000000000000000003d9726342018f802df12fc867998b6016743739a2a4f47e1f6f50992e4fe23a6bacfea0e7ed5be570eb8242ec4101ec10bce61d4e35770e7737636c0f9a664eefa948662d3d22d1f1708fa48d3043de0000000000000000000000000000000014182228dbd223cb5b601521608bd7f87659f86a7a01233d4158484024730925e3d841e05e07f2a330b9495fb028db6d0000000000000000000000000000000002e0ad163d40a56215a774751434d19ea17341f41701d41e521983ff753ed76c435c6e2b543510e47060edaaa06d29f665c86930c1d142985bf85ce70bbad170947e850e5c6ac7803fc45980dd37a57d",
+ "Expected": "000000000000000000000000000000001364f0b671bbcf69b3a101dd758ce54434d59fd053591cb744841ba2061bbe2be91cc9f2cbe1ec058119ec8a5e909024000000000000000000000000000000000cf5be1c16fd10ff97a154826067ab7cfd7b78ca5ad0a2e2117155f1ee126286019f8a1049b86095887e79ba67216a33",
+ "Name": "matter_g1_multiexp_15",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010040f531866c4e6fdc255e2a7ebcea89ffc36d44e265d5129f8be44b07f00646a7810662723546ed158b2cef146c7120000000000000000000000000000000016d6a5e46b2067c29e11d00b6b6ae9f0987afb4e9357c1d223fb2962589c3527f94d4e01f2ce6a7c57f971756163e48108e559e394a9c1ff07a45bb3e022f9c212eea4ee5b77db1c5b93ce72c0512b790000000000000000000000000000000002b6e3a234119f0f06a2b049d952230da40590a84d241ff76483169428e787093ae88c4040c64f2f1e3aa5be2c37db3b000000000000000000000000000000000732aea9a2ac5612ac350b474d9d267dd1ffa822cead992d3eb411efcb6992d196d66868a0e1f89dd47da584d075d4f55e55826db8d12169a31ca27beec80554954f522b56f7994c62bdb527c2438d5d0000000000000000000000000000000014c3187e04024d719560e36b5a63228a685f085aa080c82244a3a704aa2ed68b219d1c699e49dc1fd648e904ae638e3d000000000000000000000000000000001911df5a9f709b8434856c14fe4111935156a984a5e8cc27081059840167c3daf468a290461bf6cbd2ea4fa21255d7c11362e8e39ec661cb3c5af64e0001cc94701194344a7404f1ecf7df0d5633eff9000000000000000000000000000000000216ba7fa8afa06136b054c11bbd978209017dc4d8c8a2b05fa717a97f4d88abd9efc1e9879de709b87d7de65c859b65000000000000000000000000000000001797c34bdde358ba5533d5bb531915545e3ba359ea1fd66d9dc2ce06f7cdb64684bf11e5bc02097f3b957957c986de1074d3d66cde7c4c8a4499708a0c6f7c4da458eb970b6ca87e23601c702365b6de0000000000000000000000000000000013343f0b79485528b8a5ca5e0780e8925ea7277970843ce3699046673a41c977dd0cbbc97273ed47a1a105a0017853340000000000000000000000000000000010f3232b511b8d529f91f1ab613af1e2443947fb2e29c4f98d1dbab1aeb965079f64281d0b10e58e26a4bc0577943873389e0d43f2006449fe2de506dcdba4cd0e6077e2228f7d8b6ec9d8a4129c494f0000000000000000000000000000000005aa017b9381423c9d00982fffb93a7cf9bceceaaf31895a17ce3a9bc42bc5b6f5c69679ebc91c9e5cdaf7651cf78621000000000000000000000000000000000c77e86d84377ceab757a0da9bcea401b3db29e8e577da793da0d5338eb471315315171ec4bab4e9dab36f4ec6d907a85f8dc332cb31e43bc2e551356cb8d1533c6e567d34622667e7e4e3ddef352f03000000000000000000000000000000001971e5758027516443fb373a8ba8cb98b78fd5d16b42a83becd2a9b06e8ca7d255fd687cdf10de7dfc6bee5cfd199b1f0000000000000000000000000000000013465b45ed2469c2dc6ef4b4b8ac90b9b30c793425093898203d3b13d76cf4b8e0836c6fe57e637a6eb08bffa3bb55250dc7052044251fd360538fa6d5dec9fcee53faf2f07de5d8df212d04f968a0b6000000000000000000000000000000000c14833dd82daba173eeb40c29912c0edacff741bc3ab03ae4911c334cf91d5832a8847d7e175934f61089f523b77fdc0000000000000000000000000000000013820819e27a27009ee44a5cf02e995bb317ee49b6068d2e9f4c5f072d233a6808d0feb61958e047f70b2bb1a5426319c579dd4f361fed9084d9c66a3ec4c6af5293710ba5299df3abc4cbaf5802b53600000000000000000000000000000000105a1323577a38bc9495090b4d023a9dfed8b510a9a6d755f7ad6af72eedf1c92e6a5172cf68608d8dac34242d1e0eb200000000000000000000000000000000147d889d919a58de8aad3b4735359201c47d8961a1dbd321061a81c67b1a05c6732782975445d9c1f2aed12b0b7306f469f0f3c3f516ae34fbecf45f4636c22acffbee765952b332c0f3d8cadb9c93f1000000000000000000000000000000001335049a2ed3629ca83f041e4ccedede286445e4b79f3afe225bbee6273e0cc84b32b91c54991dd072c54ecf0d6c538e00000000000000000000000000000000098220fab5661a40cf34782efcd62ede159c82dba8c6e9f032f7216b888ad85fca1031c4622547a03f14185b3eb6d0d576618f1954730111e572937cf0c9f7b3298a11d18cd890cb419f732c766bc6210000000000000000000000000000000018799254b6fe847f53e2892343dc77efa3717bccb3589b776584fcc9e934deb3b8fa4c1ac0709ce505ca4d1504ed822c0000000000000000000000000000000017b98c35564c9d67b77bfec8ce23310c93167a5f75a4680420e8d71d8851f4061d897fd86b52d4a8cdde391c5b21a63afbb9f2400ed1dec7ea63d2b26bb3e9c2acf70117e3026626f6f88a0787617788000000000000000000000000000000000499468c8da336124bb89285a81eb76fb05e4ac2bde68d2f78f1de8926109631ee3e33eeebf686c7f6b7b4d68d13d2fc0000000000000000000000000000000001ac43e7c6d46e88d88a195180df6a3a91b3aabbe54f88c8b39168ead4b9847a031561828b0076b9b94c8fc7cc0c4636a0170d7b7604b8951a95d49b6697e2d0cd2a41c3671d8f96e936cca911dd516d0000000000000000000000000000000006690b59efd7c3e7f9477cc35fc5e13a5dc7f485100ecde7771e7bbd9f79f72719cd45cc9e0e791b7b5dee6f0252c53d0000000000000000000000000000000008b6f82c8514f7804a1d75f347f08334064b81ff95765355550c53098e19a4a5fe59c6a9611f4795981047754a6304792c2afc06f19e627e9ec0edf1083823d30ac569346040965e1c92e0c15011c90b0000000000000000000000000000000000ca51cd2fbe8d015a2e80bb4a24f52abfe6b99b1fbf1b656d4398f76e8e73e7a441dcacb43a4bd0a1dd45df2ed03a4e0000000000000000000000000000000006269d0e0f77f3ac5af8f70905ddb323362ec5de91a1eb90bf3773457a2bc2d018942e58c04013b83a7764b6639ea87c141d0ff346e46a20c2498a74f910e9bb2d5d8530afc7ba47c3525861c9e8c59200000000000000000000000000000000122f6c35f7b1456952b56a5f90ef9066a191a4164d4b2f81965bf7318d485c725141576e5a1164c3c17a8bc387c9262800000000000000000000000000000000086bcc20a2f0f0afd4ce845243061e1c12eb238f2d3fd711000f259c31d826c2bb56617479139cd611d35b6548a438101d688a1aca2a837e0a353039294a9988a7111ac134a6a8a68e4f881e7486025c00000000000000000000000000000000008ee124fb457671b65c0f9f550ce1ef196c3bf13a5403a3a21a801cb1a335012b43cbdab33a1ace7f84a998a4322ae20000000000000000000000000000000005b0067f853d9dec4dee3b2834679b9145bba170f22b7e1dbbb6ca3dd98abe4f41673b283f9c43f2cc7ee2305b874a0e1b59c33ff02791031e7a9424c781ff17a209d132af06f5b825df363fbd902cd4",
+ "Expected": "0000000000000000000000000000000016dbe06af92533e96177581a7a349811e0a3d3826241c4ca047411d5b24c76dcb6849df7f4ca050286b2d84afd71ec9f0000000000000000000000000000000012dc4fc05526d6dd6da27b117294da4e9473a34699871b7bc9f02937a8308c57b5387a6fde0dd09e8a01702a8b97c4cd",
+ "Name": "matter_g1_multiexp_16",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001394f8d94cccdaf982b1c6a8080be6bbb65c9352a961cd5daf2f817a17bd8d5e3e086c6f54f6068691f3edc4378215350000000000000000000000000000000013560d0482e6ef2fc19cf274f85bc3d14236273dd8af86107839882dc26dbe897a7de90ab5457ca440498265bb59e59358fef5bc887b7caf72f2a533fe1455ae523841bd49b4adf16cfe87edc6f573eb000000000000000000000000000000000bfc36885481f9ea9aa275c1b4a774fd01476c6f956fe75b5f6e73199928b1928108658e35dad50b298307598582443a00000000000000000000000000000000161f833b58de4db4de0af0fd17ddf81ba20e4b6ca21dd80852cb992afce9857e6cf99cc580664a970e9c6928d13dffba73b243b83d44158a66eb6d31e7c4ae1f4b3ddbba81b2cf9a654ca7c4ea2147ad00000000000000000000000000000000042489a05aecc0fc139c0ef0c703860ed36f8bdf50e4c772487c0d27b46b395f6417ae34ee98290a40b3b765d5a41d430000000000000000000000000000000018fdc2c8ac7aa01ae6dbf84412de8a47c3c504f2abed060c63190265babf779384dd6e3330e91198f5bce5a103bdcd701ea87af09f6e62111c48993c408efd3db9ebe218ac68f61a461ad9ec1306873d0000000000000000000000000000000005a44b3af7b95c7869d74c7084d0e556a67b39090b7a62fe51fa833cee316044a26d4e383695ecd3bb1715d0693f2f1a00000000000000000000000000000000112fafd6d6f1da250d12817711bc999217d16d7a6a923b5e11cb91a333898fb27f7b89885567d33b39923d7a664960eca691b9635e38a46e2469811405ef6325ae7ef88a67c1d1c5b05806da329f27e000000000000000000000000000000000197317f509ddb9d536845443d7966314eca15f20cfcbf3ff2f8701d94974e35cc0957855e0085b3f85c7da512ea882910000000000000000000000000000000018b1ddc196607122be575ebc923dee96823fb4f8ed05fd8639b1af06ddff25398e67709809b642d4d9c21dd8ab6e65470d9a35f474325d0f065442805cab3beae4a186b252ebae54a567dec6695588f1000000000000000000000000000000000c7ed49a60aa90f074af9f7fb19f6e27ec4a83ce2ed77a44c70c8e0bec02318bbe44a212c505efed3550ab6a1ea2c6d50000000000000000000000000000000013c0a772ce2c97522607b1b05cd9a89e930b6371202b69eddd108237f1495eb1c6ca65549c5ab030cc4f7e3ff4492fe9c20e998acda67d406a238f16bc2b3066a6d69d2436577b8900a180e6a71b0a01000000000000000000000000000000000fd64797f2bdd429e6f5217858cb14d78b7054b178b74696b8bc8ec9f9ede70bd03c36c824a3f775ee2f8cd6be7e2ca2000000000000000000000000000000000f675a8a43da599a09ae2367240870636ed385eb280cc199fb7c4ee575f5e3c5fe0b302566cde70b956f3c2b20fdf09c6fb773cde356e2edac3afd2bf703b59161162dc1e915873ecf606dfc0e6efec500000000000000000000000000000000065856fe1dcbef934cef47b177ecb7df76cc8796624400d5c0518aa9438bcadf397234808d099bed89ab674560ffbb1800000000000000000000000000000000071b2ff64379ed3e20cda000602c3504616dd673aebbe7690e797d6428ecfbdb29f11138169f3462dffd319cad68b96ebffc1a58dd06752a2a77abab835d089599b4781ae51ab998ff3c5b68329068bf00000000000000000000000000000000094d6e0bae02b4e7541a27111092737e7b27fe742fd0400672953d8fd787482195a2cb59a91e8584be002976c3c3e9b8000000000000000000000000000000000c2146b68ef535ed9efbed7fd02ea5cf6ba8cc20ad8bce17c06e5d595282f6e7453e2cd267181e477f511cd4fd56e8b157f35cfd74f62fa39f919400f4d692855a4b4e9f91920e4306ebb2e772a484f40000000000000000000000000000000003925e9f1e24531f9f26547108671a6a0fcf58aa6ef2bcf9f4f64b659782b93187bdf2988029de9f51e5d41cbbc4744d000000000000000000000000000000001975210e2c8bbd2431288a42f9cf5d6bd6c6afa2eb05caebe740c0a1f680b9cced0f32f8f84e368563183b97aeb6e7ef2d1f3709700634653374fba5a94d69163ef616a72a63d462afd9f01c9ddba8400000000000000000000000000000000004a2ac3d53c193265889f6c3802d7c68b938ebb6298dbfa14d1a9f515647482c84ebbb3855686b544d4299554473f1d60000000000000000000000000000000003283688bec2b8ff2e34565f8e254d579f57f9c0fe0e8521129088099a5005dfa9d565d52a75a2b26148205dae83aa6a614ed9a08dfd406df00719d5eeacfb0a96413b608974fd0aa1d4c6176b968dc00000000000000000000000000000000001b82af64f984294882fef7e5ba880ed8b0a36a90a5e9680ddfc5d86e65aafc3899a7d63e2a420113ba29412a025a0970000000000000000000000000000000012b11a5bf0f7895e329c2c6bb3d1737aeb5fe9f32a96262d8268c74687a460c47a89e252e607032576e7b67f5ad655b87c1dd2e5e5f630fb1d07e8934dd3ab029917e7775e401c0bcf7e1fd83aef72840000000000000000000000000000000003ad0dbf936f79659ccab765a61633ebb648503a774e92b24967aa8f8e45c5e26f03acbc7984a45e089ce68c5566664c0000000000000000000000000000000011686f58262dca9399d95cf2828b50b216e1df251b61c77f952c21374bcdacd99d26891fe5f335afb7ec76ce7d95b43f64e9d16cb61f2bcdef30cf544d97e078fccb999b96a1da0eeaa0bf232f01995f000000000000000000000000000000000ddfea60c169079c0fb4b9c3ca539e43b7f184f31cfa2eeb942acd2a84b472597c83fb52544479f326bd1207b4e872f000000000000000000000000000000000102108e827cf4473ba1382a2fa8f3b904f20a40657784d54e3a91fcf2703dc6fbcfb7f4b0e04c3a53a24a6e14b5735f435bca9082d66c06761f702dd439faa4957caa70ce0343268787f41a2f4bc0cbf000000000000000000000000000000001286a578ce3829f289cb98aa41cb6bd7274aecbe15b5087d8c16d575fd991878b06c88f17fd4bd905c4576494ca9f8fe0000000000000000000000000000000018e3cffb0746cf70aa79053ac579c1adbb09ed5b6a8b5e7b84951460e551e9bb62f2c1968e37ba34f7633e60a5f1f2a97980eac6c8db86ef83748d10b210835e53baf8cc9f607915df272b6e28ac6b28000000000000000000000000000000000ad648d5e0a45c8208fb9b6adcb3c47cf0e20ca906c4fdb31e5c2f0678fa3ddb6e27848a39e8035cfd9eb91aeea824200000000000000000000000000000000005ea40be38d82e2b256bd5e26e71dc642e06145d94c1ca4fcfd6e63e2bbbd7b7aa153b498793e94ed1d89691195b4aa3a256ebae4b204b3888d7bd244bbff26431ab5890098870f13800bb3be3e842ca",
+ "Expected": "0000000000000000000000000000000013a9e1e306a5cfd461a1df4f2097f0beb079a845a959ca3a6d3e229198c75d29daeb5e7b65603397353cf800e0a10d820000000000000000000000000000000016532afaf2b6d884a5b593cb8dbc38b4e2bbe522ac69b745fe9938834d66e2393653e31b052a803f3f901abdcb352eae",
+ "Name": "matter_g1_multiexp_17",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a187eff5afd944ea8731afffb4aefde4046b812b47e7cd99687ce40a5af90d6a4a2c7e2c9ce515a229e6c99ce46933a000000000000000000000000000000000121183879453793d954c99cbb007ff428c721d0e0b9cef192dbb177696ab9d575d3ade2cd56964428adfbdfbafba7505805f2e8013007c4f6d8abf441728eda8d742ea2f1df545f85d092f50ca8275c00000000000000000000000000000000196b029b6a808602b09dd4597db611f19bb911b3acb5dce08bad8676cae9910865355cca0a109bb8d7b60359da6d0544000000000000000000000000000000000cf045d01c1a6d6ae397b39833243ad3cc310be9220f71a248032e9325c7186ce3ea40fbcdae5258410e1a513b69713e502d777b25f3112ba2264022e2f28dfb6e5d5239ba097e9d815928be44b6a62a0000000000000000000000000000000000c6578ed0ccdfea63fe924d0a30c4aa7d65d9f85ea832733013c0ac225f039bd6f94b4acf634a01ac67b7165a810db8000000000000000000000000000000000624981245bedf55b95217691d9dfbc16d0d83476f8c09a46f9541d77c29ff978ded7fb7fed7272701e385e016647463e7d64b471cca34ab0c91f61ff26719c7186dfcdef13895d37ead407873736a74000000000000000000000000000000000a406d8da1910d9ae8e52ac70f1fbb85954ff7590863ba9f6e00861160f83defd24e99be31ec63489a483fa77d84ffaf00000000000000000000000000000000170bac083f0f6f4ff5edbacc5cedbdfa314de364e86486cac0e656d27e6a4880ea3f76ebe0f69927299bbe4a734e0482e5723630020fdb48e44adda735943c91ad7d1e12f3c32d823833eacfcc8b02ba000000000000000000000000000000000b8a583c24eba7a27a05bcc606a10a306ec07401ddb8de8e9bf206250ab7cc720903bd81a2c17a9e075ecf0ef99ad65a0000000000000000000000000000000006d5c7e9faf830ebd0154dc1c366b84445a85f0ebfc13b5339294752f4d1dc352e0e4204d9d64abed83e8297325de2556e9e37bd811b76133c12268d325ebbd6656e7ed718cd777458867dc98b1b3bc500000000000000000000000000000000122735cbd1927c40688662c740db5cb78425942985ea69c729061a6ba749c78d4fc3d894d07c285aea9ee104f59581690000000000000000000000000000000007c18425af769864f403c39ce3df4f07d4b7319342457d0dee30ce4bab013b754e2ab7492f2dbcd5bac2ec1ca2e0220f7d46516db284a3938e672ad3c6bd40313d77c5d643ffcc59e3f55ad983cdc0ed00000000000000000000000000000000039c8c0453627d13ca0e174f5a27525f8a0054ced2b9e7d92c0ba7bcf06c78c1e1632db35abe2a81f72b986934ade66300000000000000000000000000000000134876b42096d986e6004364e176e23f81637f8ffd3dd86097f480d25aca9ce3a96c9dc73b651106b4de307c002dad95586cf63c5e52b44aaa79cdda6dd6fa92c6fce11d867b2ff5a04c9e44e0b3930000000000000000000000000000000000032e727809658a52f60a973d32bf47bff5fc45404e6652facc1801d52188dc7db79ac1bff415a6c3e49e417f205422c7000000000000000000000000000000000c83d3e5ed78c1304f42afcc0143f959ca24348510e241c3e79ed5eff8742a89b4ce131e63544b9497c2a1712999a18cefaac96bc5f686d6b952e7082236622b737fda0dd3900bec71654bdebc8ba2e4000000000000000000000000000000000c2bb8dd01510ffe473715d7714e47dc8fff0f24af49405e55a9537a617dbf425950ca3df681f1fb2a3721afdc5a4d730000000000000000000000000000000019fcf0bdc8cf0f14c4b8eff44ce2646feecb3ab0555f530f579cb2764badb6445166598824f7b0c46a857865ade1278239d6045573dafd09ab2a0d8ab6e97b0ade43bd79d820749ecf19cf7d99792ca80000000000000000000000000000000011a463b5221e4c3abd9652917379564ed2830907464235fb6f9038f1d3a4f0f8cf9f6ccbbf66c86e216975b2d372400d000000000000000000000000000000000f0e9d5050d539f9211ff7d3cf3f0e7108c5580b634b122810c78d8fe047ac709bbb06ab1501e08f0e58093ba8208e0d4c4a2ff4ce4b633ec8fe0bfea42ccc329b7d3fbce96c26989b3c7a391c9e806a0000000000000000000000000000000010b293dd411de6a5cc464e919d290d6bdb51952a7a68cc27aee3ec80808bf05a50763fd4c17f25e94e655997bc948860000000000000000000000000000000000f18c7ab95bd74d9095ea9ea66b2b14987157162b8b8a313a781ce58b05d2307db4e853733a45344923488ae9dce1a459af09ef1f27cb83189e4e13f3801c08d3a2adc8b5f88717954ee84499defc0c40000000000000000000000000000000013ca27fdf920f901634156567835601ac0b84efdc79d7d979c2156041bac04f3297c1799d3b0641df33da9647e604b87000000000000000000000000000000001527cf040f6c84496ceb57df9c9ebda89c394eef034e40f5e6b540e931775ab91a4aebbf6078922da479ff397cc5271ac72c1dc1efefb775a1bda754ff17389a6b6b6bb25e22697847d24a117eb8974b00000000000000000000000000000000197c0e4474e27fcaf203819563b86e725778409c7d6792fe41820c495e412382fefda97b7df560885082c70f9d522024000000000000000000000000000000000b14b9d40bf866d933a15e16f06ec16b502ea8e7084d68c74418414fd281a6da50bc443647fdba348b26b4a3490d0ac4b4a0c7c2e611a24c722975ae882dcb4b45e6f6b41cfc87e8c766beefd5b10bfd000000000000000000000000000000000a254b07ca0f2c9219fc0dfb49bdd7901999cc85161f741500a3ae8be566e64f8a5fb3e59985444206a2cd02ed4ee99d000000000000000000000000000000001726739e92da7bf5a6d2dfbf96fee6028fc7022cb1be2f838ec1b9bd08ef141f4b24e093fcbd99080721063f8b7c98dc986d48aa5b00fc16c36dcad061d10937b55ec4deee63cc2841b7ebab84f910d2000000000000000000000000000000001133389c12bf1d2e232cfef1a8303a733edb0dc4fa26acedbb288166fd232b79f67cbe76227ab2eb517f1c3126b929a30000000000000000000000000000000001ca6bf5c18255bb3c533ece833964320bee7c3da4af56d876058edd15f89b0ef147fba11e1d539d528e4bc452e17df8979d4df836daac0960fbbb8919d2f90c3457cc987153def711d6e8a12fb14363000000000000000000000000000000000d0caaa05d3a01c89d6efad96f5957f1f9338136119e8530853a58c0698583d834fb0f045e212e6889d8baaa49815c790000000000000000000000000000000009e7fd124160f6ba3afa752b2557f1c4b5f4010a6d4a3c8a8bfe350c6b6e198b9e3d11f2ec7dc6a02dad4c07bcd4bb1d25ae495ba75cdd0bfe200ee24d813e1aa93c100ce861c9ed7fa5537e11778990",
+ "Expected": "00000000000000000000000000000000138cea47ce2ea638f06c26d24ce87073f98b023b800245b6fc74fc2851d79a402b49c54e5df4e1aa98e33801d3fbb965000000000000000000000000000000001558e37121ec3710ff5e6c2a4e418c803a5b83cdeec98c8216b8dac7890ce17bff08a95ca2aacb40eccc761c8a31e8c0",
+ "Name": "matter_g1_multiexp_18",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001920ce210ffc78b2c053eb2106acf1e238ac5160b50187fe816010e8a95ec632a7fd29565aefa4bec90d87701c2610dd000000000000000000000000000000000322ce646a20e23a1a68361806cf072ae3d6310f4055f5289ace0036a90b5c7ada537e614780156f6a103ed726e15b4fbb2a329761a3d6a2e4d9d63d7bbf7fc6fd321ec0344cc4d7d1b6565c475ee967000000000000000000000000000000000a1ee4319282f43ab9cecccf2c7f5e08f35a6c7e7bdc8dd2f4d642e8968aff377791a5d1e2b2152c59a8f36d9bbe04ed0000000000000000000000000000000012e60ad9f99f55859f2529ce02b8b41f8565705455cdfeef3cb315903ffbf29fabffc2546359007a36ba579b6dd06c2043cbc3dd7ec63ac63618a9e5da1f9c3fb952c6fc6972dfec6caf1a415a0aa79e00000000000000000000000000000000000c2aa9516360c840b7f88ce0cfaa0ebec502bc9cb9304c1a4d895089a2344bdb6623638e730cf30c66d977e077423a000000000000000000000000000000001163f60b32213940c9cfdeb2c86d5ccf61c0a714436b3d0923ec338ce7bd35542726a87a1311c8072fd589499c26521d733a3a84eddaf3af8c5009646a899f6ae8cf233f535e360e29e2952088ebd7b600000000000000000000000000000000116aa02028755dd5195ce0b2d3234d31b07b557a52330fdb50064a18015ae630f427a4512dff06f93ae67c4fd0c1e10f00000000000000000000000000000000117d4a68064b3f11d88ce976ed43ceeb742ba6f473645995a2773121b2b8edb8fa2715f51c8be109f8d91c44e8943e7c5112b5912aa3cba657d8de3dc8138fec92b391d5f988b82e19f16fe52fafea7100000000000000000000000000000000166cbdb131fadd6c4e7a94af82ce4fc4805dc34aacb0d6cd89e69cef0b9071b112ea4a7d9d03e3dd961b5d833b84195c0000000000000000000000000000000010736a73e2283849595569db9a5b0b9cabf2182c3d8c40a39fa32abe52dd6038edfb8176f64ec12671e3411dd69397585683e0b33b5463bc71283f0625269b2b33ead69c1eb7b23a996c31c514d06937000000000000000000000000000000000ec2405173e541945011d09092cc3a71d9dd1ff54451127181bb2d5b50876a148e59f298ee30ec5473c520be0a53d61f000000000000000000000000000000001239198a5b1f6f57bce914583c3bac476a922e56d2bb30da4912acd31cbf307bc258f22fd9f6a0073ec48dfdaa4799bb5bcc597c5ed7f79173942a0250e618c93cd0917b37b5f354d63a2c02a576080c0000000000000000000000000000000000232940188006769a382a4958383aa6702b2cbfb9c2907a989938ac618f23e241767b021e8ae11c23617ab393d4f85a0000000000000000000000000000000016a672061fe76ed943e36b2d6fa4aadf579db96eba5e4c60cda2884ddcbb0f37668638a3167d8858cd296917eaeff8e0f2613a8e50fbc6683ecdd7c7fd38b4caa8e5dc9778909fc8680a58b16ebf40da00000000000000000000000000000000066fe1f7cb3d67c20a1ba29a52c0c86d6a2aca176630ff20d45632398a39404619e55b8ade69e0cb0b7a6f363c3b2d4d000000000000000000000000000000000aa25dbff2a8c1f1d0982a709fbe88563813e918c8f25f0da9c5d0dcf3abc257f7e32def4efbf74035aee1ee350cd4fa57a747bc919991ef9b7b10388bf3f301fd910f807ccd31e322be46580a71b7c60000000000000000000000000000000001e54b0e8f34cbfbc20c9feffc555036857c31f453a1bbcffe67bb71d0d6b2b278b2ec5d6ab6648b397c9255a1139993000000000000000000000000000000000bb6d6c1a41675b3394f5b9cf14ddfe73c188592916f24240edcf0940fdab1d1fc04a11bea4af90d0d9f6734a743b38086ba09829f4bbb383e2e131d554c42edf1065022975655c07df2b3445a3e6cbb00000000000000000000000000000000099f521ecae704ed5a37ac90dd4beb4fa21ac197d467185c8329ad7b87c02943a228285b109178bbc2606e89699403ce000000000000000000000000000000000a95a85f84e76ebace78bbedbd13c6b79a6339dba246596e0695aac18d2b14b370c033e62a01caf8484dced0ebe8a76a03fd5e91f590fbe171aa3f006617b20ad645626c970c2351e048b2ac377321360000000000000000000000000000000005b8ba4c7d3c83fbe9bcbcbf60b0b3ce42b52ca19a5a322fb18bc20f81c2fcac23e1f62b9fd6edde5ffa2e37f685e06a0000000000000000000000000000000008c03604012e4dff47923a2a43382edde86c76754a1073ba51fa3a2ec7011268ffcd1452d46786682ab2ee4848210cc635ee16785c004dd2a01920c52d3244e2160fec2d17a519974d4331527cc62791000000000000000000000000000000000869a2ec19afbe70ad0a15532f776f56da5d7a7dd5b75194d0c65d0304c69a6d0363c0ff3b549e8d15171fae18ea13f8000000000000000000000000000000000389d0e6c9d73bd98202191b5b213fbe77bcf527faf98f4d25c9dd3ea2cec8f3b1e8f261d9fc8baf7b1c21dfd102f99104a6d6e29336015d99e107cd312e300bd54f815c785f6008c47c99fa0084527000000000000000000000000000000000138a4f53b8fcaea11869a6208e7498238dd80be79cde96885e6e5226315deedc98a17f8d75df733ab6f15dc24efb5c5b000000000000000000000000000000000d25d69d6d5a9c597fbec8aa7fbbe579dd86c5fd3747378e984c20b34e018b83f889bef3069c693a91ff552fff1fb8a403f9cd3873dc6243748e16e4806f8eaa339edcfdbf4408a8e41a3df80c98162100000000000000000000000000000000192e8e186cc9159d2207b0af2dca495e9d0c82fb376041360ea80562e470168b52a3326553902fd6f5a43ead32eb968e000000000000000000000000000000000fcac12d18fdfb661a12d112fc3414839bd34aa244ce0cb40be79718ec37a014b43856e5e4b003f4816e04ce612e63ca34135a2e7853c74725bdaee1ceadead7b4c7d729650df6544bd525c05c942342000000000000000000000000000000000b860984aed11a63656e3390f5e94695d8cd9367ad7961c65d714637c68ad88a3602699ed3f627f0fbc5782ff18775af000000000000000000000000000000000ed00636e74e8163645c43b8b31f05228da7c42aa332ca250270e5f14b3660fbadb8e8957f52592d942b1cc1bd2eb0a50033fdcb731830951dc3c4b33f06310eca51762cb7279039b3d7d9ace93c5f2a000000000000000000000000000000000b162c0897755fa47053e45ee1b298404818ca282a7b5818364c292a6052703502656e536f2dfb470730e9bef0d7cbf6000000000000000000000000000000001924ea42eddcddda067126534e8b862f0e16dc0cc296ea892115a9ca9734fa03d019e90263be2c909528129a12a68d874c8112ebfe12bf44e84796e8b0cd03a93d2164d6edf1f06a5c520330a177da87",
+ "Expected": "00000000000000000000000000000000056604e75c1069b4a061ea72cae2cfcba90130f6db6d9c268649089ce4ae1cbd80120a086e3f066f2584f5b2233b468c0000000000000000000000000000000018c5e93590b89119ad7d44f80cce5ecd97d4a4d3010a19fd02a58342752b166a1b82dbbad30d6f3404b330dba6a57454",
+ "Name": "matter_g1_multiexp_19",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015f9de55b3b45c16d59adda55d9f5059e765ddc06d22d6e68c099358d8df0229c6fe368384a0486af1cc9e532f78817a0000000000000000000000000000000018b992d73dd4c602afd82ad0845ee2c6662c860c5b7be197c62a8a20e91764004b5293ea40602574e91c313e8103e7a1dbb32a4fd8b9dc58a382a7e436e23f49a134915372553eee8c605436221acc8000000000000000000000000000000000157a9795cf9a45d2ea5e0312783829cddce176c63eb16195e7994b0688f9f30a4f2b2113e955bc66dcf05b5441521889000000000000000000000000000000000dd9365359ce805327b8f627f02ef5458cdc806bba246dbb21065c89e7ac6093004d214145cf3dec605195f14f1a49d357df9664d3e17d9d46a886efde4e37e38859893113558843bc019699eeed8ec0000000000000000000000000000000000066d9a54dbb5fe64835523e8ae05bb70b1934e389db0ee7547da60e4af965c7eee14a148f2e3269f01e8a545480db610000000000000000000000000000000017d6a22dffc3eac4366d0d35bfdd053d73d7b3392e7f52fe04e7e481783db3232f85687d2341358d2148fb3af7e9315de2b433b7a95c26e598002cc00b7904816d59baaba79bae7c6a7c26dcc48a487e0000000000000000000000000000000008be91d2752203afba19d8f3660118f83dbf851a6d2c54af389ef979121c55426d0761812de72a79d46c66dfcd00d5cb000000000000000000000000000000000269b050e36718ef4ebbc89bd88106a4043b267d974439855b6027f7fc3441518c39af6d3fee46e87d399d3ef03c63c82897583b53567bcfdbc63ae3e864a9cda24bb732694a6b27415c5212c7f45a94000000000000000000000000000000000dc976bbec5c5791688499da28c1d120e8a68eb5511ddf54525c047378016f68e8590b95f05cfeffba56c3daeb0729dd000000000000000000000000000000000af6e02afcbb707fd4d8bdcb5e73e1db56d7a2eb02258b91ec4a5c46c4627525220c11e6e379077677e1b733e2df60e02f7ff17e54d759eb9c51e16cf6f12d645bf2d091427416b4edbe1dd21947b4d900000000000000000000000000000000119b86eced2222d203b6428907269b950bcbc1519859c013349b1c7acf486d3da5c4b35319e6b1ba8ae815e4ea14a6900000000000000000000000000000000015c342be097ba679319b83a68164f6820e2ceece3a90d1ec296514f0ccab6e454a0fc444d599a812bb4d78e656e8897fce0a097efee666c22d1dd0ae8c8e11283aae781e1deadceb3ebbcbc5e5280a610000000000000000000000000000000002da8de95ee2ee1be2f3ba8afd8f52a4fd0e352c295e92aa8fe9a08a03b6170222f5d6cabc9b9d9bf2835128c6ece3e9000000000000000000000000000000000fddd2b5faaff49cec261eaa8d093b410e024e1620863b6b9bd882088b59afdd4445a4971f31738e2afeafb36900b2d47b2baa349884b54b542e3993210ef002f70c6467c7d512801f0003da789c00580000000000000000000000000000000012060c8cab190beadf40a2e3d927d7cff21c475dad04d64c718d02ead9e351a27be81a3c5a71c6c95aa7d7e287070356000000000000000000000000000000000233ee868716db87f46d546aa1a7e4d3e70b2592efa0104d9f4fab1680c627484a33346406f61499e3971157a6dfbf972b94d087c3ea101649ed57ff308dd3ae0d25a1ad8884763cea1b0b7c56a3834e000000000000000000000000000000000cb9c4b59eb8bbbfb8aa2e9ed72eab69735a0154645d68428f0bda762d3b061b0659b31a907f531a55c0906532c539e6000000000000000000000000000000001806c7e8a8d95a34403ec78b43dbfe0bb09014fbe0e019f8c3b6ffd91a75d5e361a6794996e975309fa716b6c6a933784f8c35b920a35b71dcf8d15a8a826e5a7c2a2c4f1ac2c2e3a6d100363e7f541800000000000000000000000000000000131a492451e5c0ff787a233f72766339d7dae09f2e17c6bec9faeb08e4e48d6407b12adf2dffa3911395d5f25980c9650000000000000000000000000000000001f14d5268c422f94657a20ca02be7d007ea88e1a352753b2fdcceca5275a7ac101c0ecfc075735eec82b8fa6bd61c980ae6101fac82c10267770e74a0ee16b5be6eae2d455d742303a3c624d52aa726000000000000000000000000000000000d988d419d559b1b487297cec19386f28659fbc5f121750b6bbe941794954e82e67c15a9a00334527d85e9be706bc2960000000000000000000000000000000004c222c037fedce38f42da2b08f06614ec9b166cc6428e3c4cad8ffa440af3d8fca7b9e4aff727eb0890effbc2b88060002fb31d0372e7730499b26d617b53ea04821c6eae922326d755a0df31b559ae000000000000000000000000000000000fc9786ef5291943cfd885238090be47632c10cc46df48f6bb5250a7a85690f1c90f5f5bae03a71d7c52634cd0deff340000000000000000000000000000000019b4ec13ad67e058906a3559cc683511715b25e52f39a591b22177e2dd235e042832f740269544de112d9100c1ae49d9aa846e68337f4e9c99dde506a3af792732342e3b836376d4816557fc1fc9b916000000000000000000000000000000000570b5e7b74c04db066d0aa751c9f763f59c6121e4e2ca4eec222277049143fb2e5fa39ac0fb41cd85310e4504f662ef000000000000000000000000000000000b522af535ca2b9db0cff08bf8ba19862e8f964b6210ee19f0cfccae8972150ae41ae1b8ddce4b1d2733c7dd47bc4c87df9035283f1afc294ee68b2668870aa45e483d208483d9e967b11990cb55d860000000000000000000000000000000000892cc60eeaa0ab6584ef2731538a84c6a1e8dcc2efa9591ef1321442684ca9fd953553268ac4ed44bf50004683793550000000000000000000000000000000010234542eb7231f4356c34e11e7b4f08b4cb405a31aa87f961d4eaddbdaf5ba6227b2764e7c7c9ba76bac7da3b19f6014005df80aa522e889e7720a9f2e44e6e7e19c3160ea282ec87a4b446d7b1c45f0000000000000000000000000000000005f3ff7ed08cfc6bfc8f5b55e2b368cd7e9f4a508ab46c7a383b2123b0346b81c39ba1304d628448c65d8c86bec682760000000000000000000000000000000001cbd3457f6925d5b8db7a785587d0dc6e2ad2ff5a6683dd11c8946e953dee72bd52760cc977987cd06a2679c74f9b64893c9daec43032946a9e892dce960e07d29b304000378145148b9a24afd15157000000000000000000000000000000000aa17bed794d72f8ac77989ce1b78550da54b4920ef6ac4ee0e83bb3cac5431cc7fb5c300c021045d4d391c67963feab000000000000000000000000000000001300e87daa3c36d87138628ad9aac5ec7d62e979c83c5ee4ce9a375fdabc745fc5874578945395ae128022eb98c6d8e4f685e6bb7713f8fe202c05dfd18003eff261456026a5185ee9e68aa821fe7c5b",
+ "Expected": "0000000000000000000000000000000010a773006edb1a84341f2971f9226841142b26bcc4af52bc8b000f165f6c59d094aa2eab1b83b3623c6c09145b5bf6120000000000000000000000000000000000130a0242c95fb2b858256de2fe27df7f5736765f880673300e3506a5e756b3b563e52b481c51a003bac76d04f56c5a",
+ "Name": "matter_g1_multiexp_20",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000090ef8b0781c66698848215b3aa84f7be47f86a9d95bf5a1ebe9c3dd6615d4fb4c6425f9e0029fa3d7b94052ef8bb252000000000000000000000000000000000cd1927ed1bfac35325d69fc924f4045c5af9fa5b0a18fbf6c658a3a6d405ac1159d1c82934aa116a98cceb382dde2ee94b3c88e51af5822177b85978526036a426c9ca1077d594618ebb8fac4cdfc89000000000000000000000000000000000dfb10a6b4e5980400bc275ba5cd8211b8a6bb6cce026546b9459805ba48f46a429ba683ad3f96ace4a4ffd6cfdecafd0000000000000000000000000000000001f643a6d83f235edd9dea19f0f2ecb98a82ba295d8ad45f75be5c0d5b1a1522c5d9f5ed812d47da6e5fe8d7924648fc6e456b39f4efe6581657f5c701c696fde8acb59e856943f15cdd639c1fa68ed7000000000000000000000000000000001824ddc80e263475b6ae3b73ef5613c7334b2f71c95d64cbb84dd489851580e767be29e7c7b47d53668a0ee3e6bcb03e00000000000000000000000000000000073f6ee13c3b05c466d35ac49c33e5ffebe5e8325f8f06b893042734bcaa4a1bc76da272602664c2aff48e731cea0304e5d306f46a31c14de7b2940104d0a4424ebaff805a81f1c4a910566057c81604000000000000000000000000000000000abe490a12162aa01307e814684261566302501f589c655b3cb840876259112a1924b1ee723e0c81d6cc6b19535d52f20000000000000000000000000000000006a2205d02f58dff40715070cfd635aa5e68553eea8718090e5f6a96dfb0a2f5a23e11ba92d38a7cee16ce67aaf5de194ff6d13bb0967945ff3b6fbbc104296805e4fedc3c25bb55b75cc997834de6b700000000000000000000000000000000180b5eb4201b4f10f605b4a7f5f5e25783bbd7c9e354238dacbd29563cdf119c832b4ca5c908329d5087d5c8c6786d68000000000000000000000000000000000ac5f56013acf364ce736c455a88a4b2615ca40fc67251039eb99df3cf6423fb85695cc035b6a9b47ef15db7406880bcde4fb2dea292b76d8130e6aa8aff5edf0097de935b252d42a777d4d9b8615ef1000000000000000000000000000000001963e29f92f6f72be2afa4635221b0d2f6afe9ada4582bd7ca4b77eb77fc4503578f38fb49aa1838751db8cf1ca0b0cd0000000000000000000000000000000009856a48f12966554afbcde1971499ee3ae40c9c5c3aef13bc415fddb97545ed84d5f50d2a26b9c16c4403a487dca614bac5c50a3a8a37111114c22839c88ce4072940c06f0d8b6d53fed155d0399ed70000000000000000000000000000000006cb805ab137fc56763f73867a7ee5635448a8a66bbeaa9ff07554db3d07aa38542884006744f6719f4cfab1392039820000000000000000000000000000000005e6f6f14f7aedc757cc458ba363fb5d97ee0dc092cf6866083722d4535e1b852c1d99d0c7c57e96a644de4b431c7f9bc3f37387bad1af3a896a7e66a80dfce2df1709fa252b6fbe4334d02bdced4329000000000000000000000000000000001045bd19d4fba8380467df25a777b1ed2850b7f5c5ff5501c048339c2f71278b2c97e4815973303e9eef283378cd8f470000000000000000000000000000000003278c7c8aa02c15275cbbdfc49f6286d6e7fb208a71a4da390c0c853684d7b4d8a6ab24953075a6a45f79fe0c9b910b70fbf5da3959a49fab7e97b3df3f2a38d16d714dd798a1f04ec2cbf84fce76910000000000000000000000000000000007af4aafeee0372e88786c6025a710fad46252a8df870b56bc1d8a39497c2422bc01aebfb567b5b68273ac59b5cc8d6f000000000000000000000000000000000dfe4a8471e42dceabb609b983b59dfd9869f29fdde01a168c07247252a9be6555a823a61487778597e0ae305da4205fe538bcefab5d8d0be5fc143e632e86fc065af3f2f621f293b914980abfd6a0c70000000000000000000000000000000005f847129487acc07fffe21e2d0aa6275a586f051c06e2575f3bf8549ad9f6c2678c541d0dc7bdf909b7cff683ecc5bc00000000000000000000000000000000163451ea5122e16ee62d58d6ccaf8cd981a29aa820d77967e69478127a76092e9bd0dc9f24a27ddca5b40b1fe8ce18b130b921d8cd2ca46aa6f3e0dc6ff08d77972fb0a248bd39e90a1e9f32be9e892a000000000000000000000000000000000faa1804b1f65a6ca75d032186b5dda63799a5fff3ffcf1f53eeb04bb5ce08be40fac13295937f34666e0f0be3bdfd9c0000000000000000000000000000000016a9086134daa2a1374fd8eb74ea65858ebe8b2990bb92972121ac68bd6bd77916203a1033ac4b163d863d9120bea0a33a5ccd9436b15d4d04a8ee9894c116190062c4e7cfabb047b585f3aa1eeb4605000000000000000000000000000000000a2ad31568d9778b306525e275bc4f525d86c04dbb98f48e72adae813ce9d02dc6d826a813ffa5b9f9d014e92de42c520000000000000000000000000000000014e928d48c4ca7640a5f5c55c8ae756fb6f03bc1a8e4e907ba89865ce610fbd919a024e86969c52a4216d84b37673cb5c7a5bf2cfedd7048be7ac7d2ff19d4f8bf0a94295ebdc5e792393e0e4bc27d5600000000000000000000000000000000041fc07f8759995530350fdb8712304083da882a5e4df8188cdad48a3df91a5f1bcc1b2a25fb3c9b59e2c935d579a9d1000000000000000000000000000000001925153fa12217d98007963237a665e56570cc666651c29729445adab3963d599a4eab996b192be1d49c7429d9f0cfe43563651d5f5729a0ffca6b383d884823aa3b0215fa057bffd8142199a16e4ffe00000000000000000000000000000000006c45218eaa27435aff594c2601276950bb99fb3c1756dbec76e609d163b2593933b5ecd5fd8544d4bd2d145821831c000000000000000000000000000000000a43ab2ea73a8e1131e184fbe9004aaea198a3dab575d3516b422c275f20c7a6e5d41bca0aa3dfe7ec761dca0ba6687d833323c3a668541ceba18375531c3781dd98525b49dafce4c4b3188c90f3f4b5000000000000000000000000000000000d17ec8ed30bbca5766def9fa375219503bf2f7322d2cc36a38fcc8471fd9d11d2a30ef004e39cac4d1ed2d33a66f7d200000000000000000000000000000000108e6c9ef3a5a41662fa16488243af3419e2d8e78c0311446186c96f20d9c15a60b5470eb95e0e58143a3c71a7565b05d422e21fbffa7d55270eca9c96bbefa29dd915aca266071673e970daa0ca9c050000000000000000000000000000000017f498e192905962fdaf41120027d49267523bee9de8e412161cec69c62d2586752d1da3d15e89446b5941a2f321beb60000000000000000000000000000000015e9e4eb30296ca3355ba9c5eee343fe7edcbf5bd110ca5be12f55191d0f07b563881f52e65588a8f4b3e03dfce6566e3ba7ea9ffda87131452b24a9efcdc91d1262d0d7550e5a6b787eace3577159b0",
+ "Expected": "0000000000000000000000000000000008b5f4f55def15b4590e978384fa0aa87e088916de20ff0fbd688ab3a13138f32d1e89cddc72acdf69fd86aaed6cbc4200000000000000000000000000000000022a02016f38156fcff83fceed881f96fe14e5d3410b4fc50e607d8a23ca986351ce48d6af970590f68aa2ad7181c9e8",
+ "Name": "matter_g1_multiexp_21",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001155a7d2cf81ee4f8d65c835ef422075a9453bb85b3566ec0545c1198b93749beffffbad14ededaa5bc6443736f77bb800000000000000000000000000000000073e4df0ea06345dba9fe772710ab71153e57152c74bd05d8cd4229c5ba1301f7e654f3fbb2a45526f1bc3b09c72366f16aa2cadacb129598aa459bb2e6b7fb26d1bcb7a49617b6ef8e57018c3db1f51000000000000000000000000000000001238e5a46f24e0f00d2b45bfad87f96140ce10d774f4a17c3df224b58693afa7cd0655e5ab202998f4f8b4b5e22cb82d0000000000000000000000000000000012628d85d982086640b09f046c5bf07b1cf718b5b4b20bd99d64382bbd8bd0112230609d78ecdc742cf1ebd24f1750ef8c02014d5392d30863a12102d1c9315839b5611dccfdb489207f918662513850000000000000000000000000000000001363b85a95432193800bdf353de1a5764cc2333b0369ca7dd539f230bffe81dce11288a289e0842f2db62a89e6f6af1a0000000000000000000000000000000003dc043b958167a900cbca116b097724e64d49897f8fb6a31df99e100be837e873328f5113a28c9fb510017d28d90d30d960ff678e1b46ada4f866adf354ba8c1514df10ebe7d88d2c8de117ef5ea24900000000000000000000000000000000175aef023d9375ae90e9f562f88e0a4affdd399c3755c1b22494445d4e7d96899aa4d5f77ab9392051de4cb7e400ca830000000000000000000000000000000018e3eab56eae429c09f9eed67492181279704d947cff0f1c9a4919dff5e6fe07fedcaf5dae854dba6719194f9fccde1704753af76295f72295645243ffc87ffc2110c9d8dfd20b464760ad965d7a97940000000000000000000000000000000018d7001b1d4a67d22399c5f9b3262183a47b6fc81786f8f7b78e80fdafb3c0c175756e602c92855e8ff9d99d4116e3a40000000000000000000000000000000018451928599da4a14442910a5bf125d97f0b67af4194797b3f54ecc9ef0be840a1e0ede13e1415391f57044d71fae2efd1b8760cc40d093912fb073c5012f910ae90f0a979cfe6d81c603adbb98289030000000000000000000000000000000013ca19bea2e93c748cd2adf682a123416823a2473148e59d87da33cabba8e0ff2516e5b2bc9a8fcea9dc4240b20133ad000000000000000000000000000000000433fa5475709a7b70044f88a5949064e32014f1d64826abbf60789380db6d5ccfa750a868d9902e4646bae766e241acab79d640b042664b23667d6c60ef9a5d59de72aee57a78d75752b350ce56d8da000000000000000000000000000000001236e6ebf0b704a18f85281b09a9552e8a478c66e59c9f5d53eb6ff1f606fd667a6f0bfe239970892c9c295a378fe389000000000000000000000000000000000cc5c1039850f3333981b1cd6457a466dde93e2355c2052cc325e18604f59cb22588b6d892685fd7843938fc1b5b8d8a1d1a2965e995bd4380d4ec52fe8e65e7fd99b1ca9f4f0c656adf7051c4b9a99a00000000000000000000000000000000003f86a5cabfe7792de25b9d8c58a283c5cef56e23dbf713851b42fc0d66481ce1946d1c632e38b9de1a55ffa0bd7f5a000000000000000000000000000000000f548b05782ebe160d487c622f8378786712cb5b68545ede95b34b08698f600e02e918fa2253a8be2c1b773cc74c41042cfbf2abd851d2c1f55c56d4f8b11b196c020c2584cb03764580d410d66784d40000000000000000000000000000000015a4bfb53e57dcf53483fca1b4dad7f788e48fedf8bbd7ac40b1707c35a57011a0c7f77ce6626821221e59d8185b9ca40000000000000000000000000000000005618adc16eb9771bfe731dea180e7e2b3b0c9537806349e653a586dea4633aaff7fa7e7ff165fa16ae0013c9672a783214edaf16742762baa58a3d22d5bb2305cb03a1326adc68adcd268428f82a1e000000000000000000000000000000000039895bd3ef87c094c9cb1ec77229d615e76dbf0f3bbd399948a70714d6835b570e54f46f94197657dc94d36c4a49093000000000000000000000000000000000f1c6f8b06ea4378234e99d16fcc439a64cad45a7f8ec567755febdeeeaea4f4b133af18a4c00b3778090c5857739b66c1f38916d6bdd5d379967dcd058ebce5887ef2bccd5fb7c2bcd758e374a195e20000000000000000000000000000000003007275e93f828b96d060e775f2b92d191d6da44b1441bd0aaeccc5abcfc7d2b5e9cfaf7b8497016ec992b13455af2c0000000000000000000000000000000015c1320efcddd0709a12a75049633dd871747e51f099e40908542a3e426d7a29b6633f5e69a4c0b5c32ad0269a969bbf1cb8c8303157f23987f8a2d206f3add697b9d0a303393008429e93cd35711f7400000000000000000000000000000000068dbddbfea897bc2b20b6f967aeafb0ef759082f55a180b3eda87174d0e036761f1be1c682d1a4c33f5113a6ff4e2240000000000000000000000000000000004ad9da407bd80ef365df2eb763ee35ae06074dae0eec7e2a36e57df4b3e5ac333e373cc60c1986543c0c23f3124253561ca9ab9c3df673b7ff8be098cdadd8354c17becdf82e7e99ce264174653007a0000000000000000000000000000000007f506a54adb1f763d55278419d4c18ca581b28ee369f33b848be495dbcce72c76533b809d70e26dda71316cfc3a1c73000000000000000000000000000000000a6c574799ba920ac58d6cea6d0f8ae249ef5310609904965bf86fbf88269530badbeededfcaa03892f1ad6b76818ec4681a0861df30946911d789a5da1f5b89c38fa1a8c0407b608122a18be05955da000000000000000000000000000000001424ab1e7a30035c4ee7d5bdcd8ef87a0aac284a36259742b68a5997e7dd3f2e5065e2238f2e29a23ac5ae9bce3bedc1000000000000000000000000000000001530257b63872851431a0bf5397dff45d6c201da58d7b779318beb70a5ee2a93142e4c5c43c3d65ddc65fe2df1af18906f0798b448ea0d10c84e2a8896f153b1ac3b84c5fed6a4ba6c932260bf01d34e000000000000000000000000000000000bdc58489ffec3668363be0a3e45ca2115bd5cd1745f86f1842ab82ae31b08a1f285e88dd4e0c7b94778f42d495b1f9c0000000000000000000000000000000006f4d2a07ebc588a8f9993ec6048092b6dad82c25275c922b2842253a8fe24e191cad4fab51621198147c6d1bfabeb0ba8b7de8f34053facf1338b54cfbe38dad73121a0429663f484277af9a230abe6000000000000000000000000000000000096e94b43a1dae483b49c1a616c010c25b660ec3566fb7d9c295d3b43c60ba4967b3f0abcc0634de5cf3fba14169fea00000000000000000000000000000000026146a58d55ba4cef1cfbc1db6efd46400b78f508ecc0b2eede8834eeb741b68ade43ef2300fdfae18c02b86e3386768823cdb73dd076ad95679a9d7b11145c12a81b825477f799300d1fd761417c2b",
+ "Expected": "00000000000000000000000000000000143fd63e2576a606ec59d017e6582711718a542dd0a4c84566fa4312b2d2bbb2d71c1e0ab8e4e214ef2376706a20e3130000000000000000000000000000000001e97699fd2e0badc3a97f6cc55bcf729142aaa13c51f9b155e5904382ed0d94fbe1d2553d602a71ac7ff39189848a52",
+ "Name": "matter_g1_multiexp_22",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000023a2a3e6e1c1cc57b2295c664ac26abd0f5bbecc0ed8e9850f90b04484c0cf048a76477ddde84e90cc452429e28b78e00000000000000000000000000000000194aa1d8332fd8120ed518f27fd827e3c955c2cbb2cae8d5e677f55963565dfdd232c83a38826621e8e66565f8e200b39f2e54f21b7f2116c30d6e444ca82fe800435cbbd72a98a6d22bac92039c540700000000000000000000000000000000124adb0352af8f18a631cb0078ec7daf00c2186e04d3ee47882d557b0e9e7fda0e0d258393ded20288789085583a97dd00000000000000000000000000000000053f94d0889a5122b6dfb1da2d7f13a836b9be039f127a011991c360c941e5dab8cb3c7ff3d7e128e52dfeb776aeedafc8cecea241dd6a924c9b9cc3d390fbf40ab897208ce9d3e4a148b2c30c25e7eb0000000000000000000000000000000009dee1a168c00632903b93fcf330b28ec7dcb8d6fba65f369237ef873ecaddd60a2d1af6e5b087f07a103f096aeb5e600000000000000000000000000000000006f90048b72dc28cf4cb40585925e62275d44df95fcbf1206e2bc762a455dea5fc6b830420d49b2415d259f8d5ed3ab7e428fab2c596f23bc3c9e9855b74295f52caf73cb7371c93c65370583f7fef4c000000000000000000000000000000001750fc7241cee9d71d95f0023dbc4b1f41ce794e9e7822a29a84c93b9374ccf0f11f931795fb824bb5c9fdb4f9e7bd9c000000000000000000000000000000000a0e6e6c76088200a345531f589ed883203e35c8ad8413575bf961b1e8d6716829f632e72fe90947dfa46745c9ffdefdf7d3d755410f77a0e4b2fad0f184fa9312b559785fb04c6020432465799ebe2200000000000000000000000000000000141d878adfaa6a3982cd0de93b4d64ba840a07c026ca443d6d4c2b6c36cf882e109d80df63b1626c112f9a89809788080000000000000000000000000000000005a5888d22a2f654a58d9a03c68d59cde9ab5e5356b2288033ba58fe2dbacf533e59344bdf30eed07698261d6269fc70557b05efdd02ac9d8e1453c82a321d798f3106bd18764140faede610ae01fa80000000000000000000000000000000000afb5e198ea80997e7cace2d5b271e3907525b6383e9d45d8a7717317655a79bec3a48800149d6bbb11a838b1338079200000000000000000000000000000000060dee81112b7e0bde192c9d382b1eb695f3a1b0b9ef7ae33b1c5ef8ad9134c23b4f473103df15a97bd6de007b828fe63313884abc4d430c06ae843d263f2efc1bba35f6cc270de05551e1f86096bb75000000000000000000000000000000000a9327207fa94bdffaac0a8741955968ee2278dc0fd17e99c6f4717e8b0db2ce7915b1b028c81d48380cdef05ecd5a7e0000000000000000000000000000000006c24bd6aa5f9c41bd4551afaa6baf5bab1729b7012951fd0ddaf2c6dd03ddc2030d49dc92073540503718a44260fb028faea236e782a8fbe27ab15f051ed007a61e25247f1f259b9300974f521f30c800000000000000000000000000000000195d0a7f5a351dff02a805fa08b2a793d9e0c74ae95fbf2f42bfefae8aeb0deccadeb9a2dbad7285c015ce14724879ba000000000000000000000000000000000e177a86f6aebee8bad62d77703d1d34a1b708e84216437c02e0694fe722414f2ef2577c1d39a45b4cfe6c73f411b1b413994f5645c6ce83741e48ae472674921bb2d9b8abb7d04ddbbb85a3f2f7f090000000000000000000000000000000000bc7fbda14f76ed98e78eb84033b65f286527ef76ba56dae43a094a23067e10798065674daa14f912ee13dece4f36b17000000000000000000000000000000000f69104995530de05660aa048993c4e08576488deaa177520676c9cd53034ef101fa3911e40933975aa958efbb1b931f81eda24db328588e8c670ab70431ddeebb0749b431bc1bfbd992c91f35d59b180000000000000000000000000000000001c3bfedaa15025440c6cd32115555fbbec439a9a2fbf706ef21e06a534af3f43baf46897158e211ea8821a5e32f932e000000000000000000000000000000000fe08cc9ff0fc601e5609ca139ae0ebe58faf8d2e2f4f3d0a1231382a15ebdc8f67271b556cc24fc5408daf3c7f74f875bf25b5070829e3d5a66ad24ba9930f3ad64767c51e432b51bdbe2fab470688d00000000000000000000000000000000032c376b26551a064cace577ef53077cde48c284af5633152c89ee109e880b511c0b90db1b30d6d9700037489f6984af00000000000000000000000000000000059c013cde62f10f39175335b76adc5cf7330ffa75d770d908ac7e0fba6faa7b9453e8d0215f0589af872b2e648ec1d0a9535c082e11b366cda0000d8ed0f92ee30fd2c4364c163a718518321c5e85d20000000000000000000000000000000009cb943167f21d9399b184f0bc0c2aca58dcf8e702614ffaf5407644ffa9eda85efa12dd23e756c5ccb5bbb25abe57e9000000000000000000000000000000000d4f59115321181962452c6f3c1e086cbfbc155f2c3019e51e73fd193e9b11ec891b2dfbd95198b318e4513c62cd51bc2c4cb49adce0292e259e92b229bf7965864a945de86eda3ce0bc9f1a6dc8b7b2000000000000000000000000000000000637e1dae04d31282c2278e087eac9ba8506d3c1349c6b98485cf32805bcad002e37d55667f1cc8e5e11f35b4d228cba000000000000000000000000000000000778c3a40e79d6288d3a93580c8f8bef7591acfac2c734018d61aea5dac020360ad4c69b4422f7320b87ff22e30d9a6a5e927f57aa85b2df54b4bddaa041d43766c8929c8b9146d723806ee0cf04227500000000000000000000000000000000069a54448ac1c9ee754fc28c9b671e84a67e884492f8e84e09e49cbcbcaf07fffed42820b1de61cdd0bf6314a2f4a1e20000000000000000000000000000000008f5512a1a70d3a61ee7fd6750813a29c47410b7ddd62db0426b3caf9cd7c31029638499c2e27e5922810cb9bb130723606ee8a5fdd9890b8017f6c432a45517d65328f13f3a2bb42d7115c02929db7a00000000000000000000000000000000078356cf80bc64c0e03da2198da5971b01341024a620ef4a455291b7a694ac3d91fe6f19299d725cdf7506e0485485da0000000000000000000000000000000015af5f875422c1e3ec6bfc5e57ed793f368799c2e068669656294be0de25eb772aebbc61358b410fa9ef79c72f309c84c1a77ccb4b32a762d60b37827ad6c3448c33af6af861c131adb5920ba3c2b8510000000000000000000000000000000019699fb3c6af71eae16b8ee123870888d646ac71dd31d0bb3ca365f728a6687540851c8539dee5c34f16871ca244ac6b000000000000000000000000000000000e68a278bee81ea53d4a52e84c8f534a0fb8c065bbcad9f3727917402746b4d1f611ba5064f0c3cea6f4d7fe84948dfd47cde609c38eabf457cdbd1e0c5366bf523dd5801d66a0282bc187d80417f455",
+ "Expected": "0000000000000000000000000000000009057b093eae9c7ab2455b447a681857d588819c94b1cdffc0e315987b095edba1ca727043667749c56591429f9173b900000000000000000000000000000000157bac2835d2f972fd1269039a7b6159b7a81a1bf4327cfbd3be8b7c779631e8beea634ffefd9771c910c612d6925384",
+ "Name": "matter_g1_multiexp_23",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015b6687a34084292423eb600bacc585b4e686251892b16a52d0783b1490a82f68f4eba5eefd36d147c4ec442d2eddf8b00000000000000000000000000000000151f59108d7383351b426ba8bebcf2a04976550aa2d10d5f89d5ed7c3bbd3473ebfa29c1706560866c8596f7549085cc3c79fe6374bf8f91bf7851ff935a124b54fdb5db498d2d37939fcd43bb93d29a00000000000000000000000000000000064e3333f828b1e54d201c043bb0f327d8c9af2cb96fbf587dcfbd55547d76784de0981a0ac86b65f4b8e45b19abc66f00000000000000000000000000000000172b76a242fb2bd9070ad26497a5c190d08472d3fbffa83dafc53d2bf612bf805691bc8f850da8c230ca0b8bd4fab818a59fcd2baa47621ebd90c5cd12b89f2a533ae86d537fbb61a14b1a80982c9257000000000000000000000000000000000158e81d92b789696efcdbd6e3e7c16386d6e5259a247991118dfbb3674643fb97a82fe404832cdbcbb58156c9548e59000000000000000000000000000000000fa0d18e57d64db246ee52980218c3eda5fb7b1029e1c76c9894548df52f69725fb7ff090417ae05957a652029d0a37019ef9fdfc5f0c4ac41255eb172d485317c124211498a8b9a74c0bfda15b986c500000000000000000000000000000000027a07cd6b7cf0219b57110edf07d758ea40b1cca42270b341b2bc33c78fb9cf52acc31676811032d3f618898a0d13330000000000000000000000000000000000e1212938244e425860646cd0258b65556360e832d4f2262984f4e307023896714731a2db10004e5509a1dc25f49ab7b8ba028831f429d027319a92fc0f30def8b97a43da456ddc79443d9f8df72cc1000000000000000000000000000000000bd589682a8510471ab1be8c348ed0d242548f0a5b85ee9eaab5af164367be21684ce2329a64a6afdc6a30ecc5bbb51b0000000000000000000000000000000008c8af9dd0e06a08f2da0ab7cdfc20100b94c04c7e6773a0351bc0e0ea503a69e5f25f250f0bbc5c7685795b279ae151edf8a6d86471f58c69c1a5e7518c69c34165e72ce84fbe0b7f69d9c2717e5d4d0000000000000000000000000000000015865d51ca8131cd5d2b0cb11c2f06e39b7e167ddf504d5772d478d48463668c4f7dabed00cbaca414b6ba96224c95cc00000000000000000000000000000000042fee2fb44ab45d310ab00896170a638940edb2df9a0f06c077bd00d203966d49694c82cd59c378445ae0577471221c0dbaac3f5e25ca3d1d50ebb31258ec4450feca1e02c84672ef15c49b4de2cebd0000000000000000000000000000000017257c7d5c733cb6e9ea1bc93bda4f36b98375147a119c376996beb6f0bd030c997ac52b1556d01152991738dc640788000000000000000000000000000000001155b29f473d9abd15514a0ae1cbd0b6a4ef394aa65f4fadfd3e9551c1d8420fac28acd5337fc5d114c092bd45e9e30d109ccbb8fcd4d4651b84f4708799d84ad0a717aedaf5a76d2970a7b93bd23d370000000000000000000000000000000009802bef3feb5688df77c86c74214451e4613d0260fdc5ed6e763226d3eea8a583c7dcf29eaf4c0bf16c907ceda76db9000000000000000000000000000000001447b1f7ac05cf8dce7e81de516d7303b310316f49ed5ef3f40f03db17926ff5f6656d859367805c889e07919224a6436326fded2b8a3fbf7637bc25bd201d20e3d4d724806cfa678ee039a39c24e86a0000000000000000000000000000000000057b59f849f0237ad511a75b66a77e79ae062025e5019eb71b7b7ad94a96c2905e25afe4357506b2472f99bc71a8ca000000000000000000000000000000000f10b6ad9fdb4f346c5b4a499722e377c7649a800bb95306dd7e2ab7542e59455ea5541f2d75e7cfb1da5dd03bf037a1e005efa8ee75dec8a013029292976e107a507ec09e3c34fb4baf2979fb759f1d000000000000000000000000000000000e0725ff4149698aa757e794590ce446a1589d9a574587575ef64d6a3c935fbd78fb60c7c840d7ef42eee8d72a5ce341000000000000000000000000000000000f0478a776be354e29bf8bd2710a8529cd01da31853d04ea722225bde560f2d9da302ce4f2634c9385ffeae379324b743917f8baf17f71222166cb9b6c4beb2e57d0d054cba3f7fd3a28cd3dc4b409490000000000000000000000000000000003103b0553facf8f3cd18967a758b73111a4a9987b0ceca3a20d6657a7e365be3925f63bd09990e33e1162bbffb63278000000000000000000000000000000000998a34ba445dbefe6023e737f3e35cc6416289185a26611301721db3a24f80dd784b001a2f2a745ffc3d0da5a9e6204f0f73e1b62561f5b0fbc409e6534ad9e37d1c0724b35cdd3f94bf6489e500fbf00000000000000000000000000000000041e13fb55bc9ed069c6d625ee08122efb0212f525b319b88197450ed1a60fc7283f61083ff263e4df10499b689498670000000000000000000000000000000010d931f006adaf737afd1ed2d1a631f519e6d1e9e22166c24830e92e3571e9f138ba901f5ac2f03192c9701067e7906b3ea24fb6447f2493c78a267daa158eabb70c1b60af8175d0d4594c99122cb442000000000000000000000000000000000bc0d401197ce816b692c5ac3ea539cc9658de56e48b4c3ac78631f3c529d4fa2a656f66098a702b4307fc56e147f962000000000000000000000000000000000d89fa2bbf3ad409a9ee7b7097662113b94fab95c98bd47a70fc2707a6aff23bf39944aad5509aba34930d7343762f6e5ed307c01d9e29a0571de07c62d5fcfc80749f02b8dbaaee9f69dc9263e9918800000000000000000000000000000000103cc442deeb800c14c9b3071c13d354d8c36d187e580073d150f4936ff178817dce67ee276d1633e003e66985c038cd00000000000000000000000000000000188b34fb0a4fc2408d8c70eab6df4c6c42d92ac5e43827044db526d4208acad4561c1310115448bc00feb9ee7cfdc40a877f31ddcb55d961bf9bc09903bd927451390922d647d589302855141cf5cef500000000000000000000000000000000145220a2f8fc61b2973d219042580a0edfcbd73a6bb6feea3655dd33bde8a25e0fb841a3b038049e554315100e6724c50000000000000000000000000000000018bf41cf4ce164819a8b00e630401f0332f5caa08b03bda27c205e8fcc5ea7a3374b591a4adc581f492cb07445c8995f145c1442ab82241f56c27dec2cd4dbfa9fc3cf1ab72bc521ab32a82346f8f607000000000000000000000000000000001416a39ffccdb10f65e5f06c8d7af68fbe894a0778e7270ab167ae2a5e917fb0eef1ef1b9fd45c991a45dc92a223ceaa000000000000000000000000000000000755c58a0692f8ff860430c5f75fa35366391f7e5313936e04230a1fcf1142c81b01e68fb3c888effddc0a498f264da9de4d1470f6cbce027465b4dc2a3deaca14e34218910aa76cb45d47139b31df88",
+ "Expected": "000000000000000000000000000000000d73a7edcbb7163795dbb5a5b4daca733e07f6498d336a5dea1a61c9edee346f74676afe0d6d39c39caa1fa7660ab311000000000000000000000000000000000f3d573970077a17967ecc0fc5e2e7dd4b6ce910f1891f444e36761e2ee3a72fce399993405761de29f9563f74d8b1c7",
+ "Name": "matter_g1_multiexp_24",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008c2f928feb8b65e521b7218b029a4f54022a28a18845614b3b2de93035228c282c73ce172997e6af93a402e35158ce3000000000000000000000000000000000ca2dd2c06221058a4a7a06438f035ddbd96f6b39fe80c0029f41246a2c8a4410961555e43d9b3d5d87dceb8d0be1ef42576b42e0728db912a78eec2b7b4c96575e341e86a7592a07a660c11e00448390000000000000000000000000000000010d919a48f588429918f1b2f05ba6e897c45b12d905615e045c1969ee8a7d9ae262551f546b7de764266d3ab656c3137000000000000000000000000000000000a40d6f247315e0440b0b8195fe5f7a7dfdb2e1be9e593f7933691fd22789ae94bcb6bfebf3b84afaef7cae9fd539b5379f9205ef0e3a85199c60ad9267349fdc7b6fba4cb765ab21750eb3dcfc48d8b0000000000000000000000000000000005eaa990ca9d57885e6ee3eee10b6e2dde6e1652a743c62ebce4871ebd2d3c8e4915418aea4f4285ba375ad1923b70a200000000000000000000000000000000159919c720eefd062ba8d72fd3befd953e1272695471315ff500830c9b5b60ce5f94bd6e966828d69f7f268bb423dfd7300679b7be7c71224247e8034f5d30a63f8707d92d843a703f0fa93160f65715000000000000000000000000000000000b7244995b7819857f716288dc59eee9ba5ac7bfe010937ea0b67ee71388a3792e5b7feb6890a436db4f1b26df18b38c0000000000000000000000000000000009a0b73360bc0ca3b632c0116f21ffdaecf37e4d6c904c98d6225a08d7caadf5024ad6b457cf31b924118ea147ff10fb0454b01910548432a0f706818a98151e38ff9e854f1faa95ad41a7239b5cc4910000000000000000000000000000000005c2bd45375084cbc4bfebf41709a87c2a8d52256a5e4bc162501bc119394186fd624c5d3d6749708be2811da2c84c15000000000000000000000000000000001626cfa6e87e41c2f0960d6d2b8e303ff8de00c78d1e788f32cdf548a5ca00db1f3a3c082f051b4bca93788243d9b0973685617371b27ba8898ce7f30776d817ff09ef68a9d6721d4a923ed244ae8206000000000000000000000000000000000f736c8cab0794e3751a9e13027a8e4ded1308c23be3d75b373780eb69f130654121435c53b62a929cad39c605637ce10000000000000000000000000000000015b1edb73501789811fc09fe0156344a7a4eab1f04d1fabc24f36e2ddef7c2ccf9643699cfc654b7169d8e371c14e8c660cb5aa2a0cd1e8c3fdc06a3a1f6f9b6d52a8cc2e98c85b8e258f72d03efc2540000000000000000000000000000000018dbc414f9e1c66af803b0c228a3fe77c94c29239e529cee652099d80795c460a507538eea6c94e99b78779fc0f3f33400000000000000000000000000000000151bf39a8e3e85b9361a9472e95cafc3ae11f7d0b952714d2836b903910a8c701e0c3832b8c88592bb8507694d9109b5addb1fe778c84242953db87d2307b40eeb776f17767c3a4311b5d2ffd738f151000000000000000000000000000000001241319f49e1bcc2d3f3eaca51d2e4c395241e2c5d8f32749a168e4af17570793fe086610432db1f93fcbbb95ced8b49000000000000000000000000000000000d90602dfcefc3860a78a8f51432a7608a7c483fcd86c0ee6a70f8ac723537825c14736240cbcf903c94d04e24e8ecc928416b4b4e965a5f024723fbad6ef2f65a1381e70201e26ccb40188dc3d0fae800000000000000000000000000000000024f26ba0c3295002418f7839b774cd305cecc3c2cfe20974343dafbfa6677c2fa6be5c546a1fe81458678c3548d8d6a000000000000000000000000000000000fc8ac2bf4585e8ac8454e3e424e858e1d67cb6b9a7181e26af803d8895717796f20abdfce0dfb390bbc0c7b16c70ffb78077a51f88236dba6d16d7fd681c631510106b0eb7448df456eb9ce758e74cb0000000000000000000000000000000005f24bd878cf5832ebcf008835f12f9dfbc78b2f6e46ee384b419928aae0e754d86809d360b0afc01bd8f2f8d79a685d0000000000000000000000000000000004aafc9a20f52d1c78a17e7824062a1e7165362ff265dddd4c3458c7810a8e59104d36035c93284988eb708ba196d6a2871716e790e1a0120fd26d169b8ffe3fcc0d03683dcdba7d2f953f05444076ce000000000000000000000000000000000375313e7ab999d174735b5290bf9ea333a62387996bf4df3dc33d9a5212ac0645789ef4153223d488aa2fbbcfe808f00000000000000000000000000000000014b792fb5bc39dbfe409356bd75b195d7023bf6f715a4102cf36ef05b52fb2284cc0739fe5ad628a760049c3624a3f2876ed0a27553db6ac6d3959ff4c9bc5807fb7d4f0a56095ed2bbe31dbfa41827700000000000000000000000000000000006ae2c85b2b267c86320c4cdc56b1a09e25f0f68dd208e898ac5b1c0645aca3dd8000eb544eb666f4256806123480800000000000000000000000000000000006670390bd47829d3c31cf2da8fdbbb64b92b47c78d3ab638727ea834ea6203e45a9a023060056c69c1fb567c35b671795ce72b30d989889c8779c4056e441bbcd93629efc2877d36d27f670711e21c40000000000000000000000000000000011c78f1b6d0ecc5523dc089852d95dee641222c743dfd09ff2e56d008ce523762bbd9c7bec6c18e9885b7022131ad30b00000000000000000000000000000000066a1aa8af751eac5dbaf2d3ae285e0cc7a975c1787178f550a42e8ba89fa74a1b18f27716eb7ccc4f21b7957cffd8e806d220f64de05bdd6e1140c1e409fdc13f43bd31cd94e633be38ecf22ebd77db000000000000000000000000000000000cbc0fe6b4956c0f7b9fdd36ea14a4d8284468c280605a31536636114759ece1339f06e050260bbf936b560586e7d12c000000000000000000000000000000001213bfe642bf78554d91820c362b73b7059cf20a0aefa5855f9e61a0490d165f6f61416e135473e2de54bf97cc14b8f6257da8ac7d23c5ed965d8bfc76a642a36ea6ec4c45baf6882021372e8643f0980000000000000000000000000000000007cac206b2d123cbe9375f5c913939b25886a51c857271a59cc2fae2e9d669af0ada833c72366f78be265ff9db049d0e0000000000000000000000000000000002db3f65b6fe7c6688f8d3741e448ac6ff322b8769277572f0198dd6ee8a99397aaeb9addd0892286a9ec6028bf9678863d017ba8c7ed138b1bc70141abc5cdc3afbccd8b1db5a6b5f775efa62b8dbc3000000000000000000000000000000000a60331f8e8b26e97366c0e4cfea158e78ac72d63f219e1abbb670675bea008609f7154752438d9c7758b2a2e076da7b000000000000000000000000000000000d40d90f498a2855ba35f1c4bb3c5409b87062d7857bd97dd37d6e5fa53c94c78319c6b16bdcbf2610ba379d50d131e47a16e23e37ecffd514d47199cff249415a6d366fdfaa82450f0744520258955c",
+ "Expected": "000000000000000000000000000000000ddd3c7964bf51207485b0575afb6430cf801bae388ff78a69b8173c27431e0593584f9e755b99a5b2ed3113b3fc0082000000000000000000000000000000001735fb40978d364be3521ada17c3ae74b2a738b412906fdf425bdf13ec09e5acdf29013b03fbabe889fa261302a7ca42",
+ "Name": "matter_g1_multiexp_25",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c52993730e412fec923e33f3da42adadb5d87290ac4448d7df9b401e28b3c7fe7f49c7b7e4bad5412c815931416303e000000000000000000000000000000000db71c91975e41b3f12e303bd8ad15f7c9836b146073946129ba3815bc3217b6116a2a03137608cdab8807d5834eb12026a9bd0a71fd58edf81459152782733536e960d27e35f9f84d00da256bdc118c0000000000000000000000000000000009657686875d82eaf4f93f3e710c467ced1348b60aa47658992771195660c4b96798cfec584ace3bc64040666de71f8f000000000000000000000000000000001375f7e985d987df508321c3d0aa7e7a06cdb78117248e19c3344dc443da319f49c00ff605c057d1ecd942e8b04a5e4ef1e168ab93674bd7f2bf73318a48ef17ef4464fbefd39f77c17ebfdb24d679b6000000000000000000000000000000000da69e098b5e2c8be2ba699f20fa38cd27b9c78025e071ecb2d9fba3bc84b1e673eed79f1887fcad9bfd5b0516236a1f0000000000000000000000000000000016c4ca4d9f15716b7efe6f9e61aaad880423243b2d5ffc96804fc70f29b633dc16474f7194b5e3ca12ab5a1627da580f97fb0d947d71a1b032070a12588b85065c19affd0db53e466f194f04f58dba2e0000000000000000000000000000000005370f5c60fb3bc36ee208e8c185613390748452cf6191bfad06c9bcb52501873bff63892066e0afcb01a0204cbc951b0000000000000000000000000000000003c7a2a97cf7be433864541082bd04467bbb42b2ab708866c8520a6582cce5225af13acb887b6b6a8d627c90e43f6e7b640f850bad2f22049f2f8aaf3ee57564fb38a847e428e252f003eaac465f7d67000000000000000000000000000000001820666eb1abd6144df2f21f2d46096410274e346ba862aca0e62d293fc64a6fd213dca4ddc1a4e414796f59db4d6104000000000000000000000000000000000a2521c021f2fb7beb76a2ff4c7ce96cf1d05823ad8edd9b2021eb39c08e0c7caff505ea76bcff8f6afb6e8c2e81d2f68bf91051da5bce0a51bcba6f4e1b3c9063743646f4e75e3e5a8cbc84e8112af4000000000000000000000000000000000e756ad1ccf0404e110a778f66ade3d10464bf8902f646f7d7ff38d15ef890bbc6d61d48122ba6edb799630a62ae084a0000000000000000000000000000000005b322f44f07d3db292c43f9ddf9ac9e44e8d16c07537bf563c98e02c2705eefc1013e627567ac2a03698268707cd84e8da771e0e827a52a2f7e79e0e5d93ebae04c1ed78cab87d4353f24ffc52099b3000000000000000000000000000000000420b819a63b7ff7ce541661c5fa8cb107cf00ae678981b3fc1b568174ae3864a8241f1e9b656cadeeba232156e66feb00000000000000000000000000000000136fe878b886bc14fed061cd8ff1fa2d85f05bab922bf18a1f09b55c331e7cc9bf0f9860e9112c2f6242b6d1124851dbd6cff707bff10fd53ffeff8e9400966d8ffba6d4ad6a8e7e456df10f8f5ebed2000000000000000000000000000000000b73d3549a6b2f76741aa39ee9bc2bda8cd55759bbedaa9ecc5802310b054b01670dc803938aaea547389d7b0ceda469000000000000000000000000000000000227fc49bdf53bc4f916714ea9789b526aa53efa1eb032c4030519608c62434443847cac82a13e2dd2eb48f73473d8e1e00831cce307cb44e8dbd5edf24f1535b837277160d2cf6daa4e862e57fe73b100000000000000000000000000000000167cdb86301937bff18287eb0b00f5224e674953d70258065e5e8370016cac8194ec8c2f44330adaea44426aaefac7d70000000000000000000000000000000007e9128bb015f01aa725796d7b7851f9c2819a8a578bc7d3af02f7328c922c26335ae9f87756f52409c446852bc710ada8168d56385722f339a5b27fc25a88034d348e3d533ff4dc99d28536c1c09a770000000000000000000000000000000018bd46832b101d12f95b21332b7259719c1f94c056118d877324656d285f73a4fe2cf637cc62a45647db92ba9d6c7d18000000000000000000000000000000000fe58fe2c19ee903d82da6da8713863423f10edb954606b6c56326eb8eea6c66cab63b0c816479f8107612391072c634b929ae82ded73a4876c041d2e52fa811882fb8e22690a27cb4ad3ca05169bbf00000000000000000000000000000000012db7fda36505d19a2c6ba5072044154f444eaaf3e12cce81ea74f28e691e4b7a730095667a71308db5e8322e80fc66a000000000000000000000000000000000fd0f22b05bf82688ac72e9ede526bf806695ff430ff3c750c2946d58ef90c778e4c5693d152e39fb1837bb10cf5f3be36999c516d4acdfbcd488d39e3073db9db6cdd0c0fd1d29d58294ace6d2d199f00000000000000000000000000000000116ba7b6faedd465fd4d1e5f42ae80c133a1d158614894ba663f87137f6108ae03b8e80bf32852ccce78b776dc224c760000000000000000000000000000000004c3702ff7fd9c74169ea76c00efb7b475d45efb12e1b5b700d47a970ed9f95f46e4c0ac66cd12fe79d62898b24b54a0fd0bc405e3970dc2bbd7dfe0c54b7c64543fc241000adeef4f7aa2f1dd2506770000000000000000000000000000000016254d89b0e2a8315253434d5444000d9b56b8f43d3c20d17fd26da4c8e7432d6e463b71a5b2a1a7f559a908d73abf6a000000000000000000000000000000000170c490fe3962fbfaaea1707bd28ecdd46ba29b5d8a0a35baf7fea4eaa47694e680e47e8a9f07d25078274074e232dcc36afa3c8581df069292d53b8ce3e35ca136a0b3f95a894958105fde9c77e39d0000000000000000000000000000000007a7fd283d64efef7094fbd6162da2fd56399765b559674c18d1cf6df51036007ad6c9af62bee534388ea093d3cdc3c90000000000000000000000000000000012fcf920eeec2c1728f3e620fdab1f8a0b99c6219f44b0fd19d0f7f4a15d1636fce7b4701f9c3963cff9b030c3759fb20f0a2bd678c5858be2a49ca54de8716fdeec84e1935b8f44545c740417efa7e40000000000000000000000000000000009bcf0b2d49ce38914ea877832eaa3f1034cec429cd9fe0d06ef36691ac8ac6b69a712792e31afc700872d08c2e0fa48000000000000000000000000000000000f5fd9d2d4710d1cc6c13c88ae602f584a7b671df91cd544697070eff3342d80d750e15e09358125d15fbf8a1ae8df93c8e420db340ef2c1b5c6a71645e303eee95cd93228770b639287b14b6a5c59ba00000000000000000000000000000000053fc59a0b84028cbb3a97dc3124927d6a0eab1c58d4c6d143462bf73c0c847712bf22557a1181750146fe63e9c9668b000000000000000000000000000000000c1fa8c1539ae702bc9441085a89790a5dcac9b18925cdb1e21b95c9f7286795e8f36e7a8b4c3f4dcfa12454624911675398541eb5a03271e2ab5ec2aeb2da80e634f63a050c25de98ad13e9d63d09bc",
+ "Expected": "00000000000000000000000000000000085e4232f0daeddb9e1ec8731855cf855d7dbc05d4b82d10b77a53306ee7a38ebf45bdeef1981325a61ecd754944c84d00000000000000000000000000000000061e32056ac411c3917684356a6ab3c7068f55d30ebcf8cfe446c68267923e4fb98596aded9740dc7944847a2e617fea",
+ "Name": "matter_g1_multiexp_26",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000070bcf49d6d066afa9b008fa22fd52f63b68a648bfbb5cb3eefd6feae666f3fd0b9a8447f427d5a9db52ba49854db7cc000000000000000000000000000000000947d708a02cd0a18342bc04639e8d126fc4c97acb497aa507e1c4c3912b04bdca886b75b9b9e1c5ca745acd090433119f99387baca30b9cf63ad10c445daa142fcae1ab3c0a366a068bb5efc9abb3a9000000000000000000000000000000001023942a16150e6497289627dbb0205a7c34afc704232ef214a6609125e90260d68b7c60600cd6f4859ddcad46c015580000000000000000000000000000000002da96265b7460ea6a8d51122bbd2442c6784d4f5bcf6d8b0b6eee6ec82e4d03c9265887f88c106792795837c02ed76e4283a1773995bbc97a6df107082fed4ba40e2d30c5472a25a7643ca9e78b8b8b000000000000000000000000000000000d5be6f99bb9a2379d1e542ece048164fa5d14e0c6c459180717b3da46e8446e9def576635ac1124e1390196fe97f39e000000000000000000000000000000001482d8339b402e3bffe61aaa298c8bae4286f1fbfc877a66e21cfe239bbee383d701d95a6c2b8193d67df5a551bb7aba7f4202d670fc3b48eaa92e925f48821d2ae057d90c5f184edcce9ea900ab51a6000000000000000000000000000000001969dbab76e6a158506b9dd38c647d4a670a21458a9552d903ac686855fe021a7dcabc91e712aa252de369c9234fdb59000000000000000000000000000000000b60179a6fa6146aa6e57b097f20944c123916c6722fd7e606aa34b8da579f6c126dcbb251da7917076a83e2e4b02d32a76cd8d292a7053c449cb98f13cf768c6e37da9d702af28c16dceacfaf9cdef5000000000000000000000000000000000e5fa0feaca8dca2a6b4a42e4a291383ec867f12b85593360f8caec45d31109373dc16d985a4702e3b5684774699e6b5000000000000000000000000000000000ae96f4a4ac0d0a6fe6aabcf902eb0765aee9ac81ad09e7e097d649b0c0165de6ad7e5ffd4ae7d8a272034f28c85ad6f97b7bf8acdfbb148814afee1df79aea17261dad6f78772111a6dcb021d8c79d00000000000000000000000000000000006391a93eb14641ff145f690c626ca412af266d50b903f7465d9a9b678025a35a68bf1962bb5ffe76ea07989a7d807920000000000000000000000000000000001a90846cba7c708bf8b4bcdb3415e17e80ffc9b48820d3307362327b29eca0d1bb7fcac9c09d09fa309829679080b36efdbd5953bc33bfba09fe7b3ee22c46c3a86f557e4b5f272853e67fd95a0f9b0000000000000000000000000000000000c9cc9547fd49cb22986f7a1dc1da89b05f5e7c0d3cf2179f22002df9fa2c586bb3f1496c0c60f8ba36b631fe74c8fcf0000000000000000000000000000000014f8e4e8c5a12b61caf4325d1e4a8505409d722e4eb16d51be5f01f863e5dc1ca68df1b83f546d22fc116f1654a3b30e9a331bb218b99fd38451483a10e8add23c9641b975af3897670884efef90d45200000000000000000000000000000000123292cef01012c3723b4713a345ea7648bdd8b8edaf76f149f1afb993f196f57b3315d86a374fb78a34486ea10e0c26000000000000000000000000000000000ee2389f669431df6697d79ba16d3e4d9bb4264c9ac146a772de6a9a8ac94760cdde7f613a4ae6592509b04b1f8233cce9301dc826bfe2988cf93c29ca9f01421b75ba63c5ed2cee1599122012ada36e000000000000000000000000000000001284787a11e0164bb197f69702d0d746975bd96a3b9221841c7193676861e97e11077b74e69f744c521ddb40689f9685000000000000000000000000000000000eb6c4c25fa1322f7c829691d938f87ba6bcce850404bab57cc3be8c3d0abcf123be8922af9967b83789fe64e2cb35f40a1cb530e8b828542fa4114de6aa936bd2be5ef3a9b7a0e20e475022381d62d400000000000000000000000000000000069f8970964efa22facc786291d6ffe860929121595fa713f4a12f9e99d8508d7d20f7d19c51514538d1ce89d2adb78500000000000000000000000000000000122bc9405ccae4e409c1aa22b36db314a19ef6e67a572f7ea67c247085205302ad12ef7f83d3616279892ccd3c456980cf2f0c33bd044e8c4468b4b7e137ae294c178e7b6c9f19878331fb93220db2cb0000000000000000000000000000000017b92fbdb00429846fb30633a2c3f383d32d0bd433d5a46e27d3c7bd6880948f89bf70b3f1639a18d308ba80b7209df00000000000000000000000000000000012374e8e7c1fdaa4ad4a2d8607afb62ce939bed23ea42a51fbac995e2c3026c2daaa338be160dbec2602a0fdaa1e9897e5f460dacc592bb947ff6f1c15b8464824aa5c957a645a763138ac1581ac576800000000000000000000000000000000004850419631e3de2617bb6b51ef19bf14dcc9f4c7b24ae817cb239342081947f1799080cafaf51ed687b9dabb2f3581000000000000000000000000000000001108a0463d38d617d0a778bf9478ab44050ec290e442ac41e23b526089ab5aabd5819a8f08f903343e93177ce4042c82f26a9736f728e16d7b8ce0cc59e2ccc848c181459fff4321982c08e9cac57946000000000000000000000000000000000c9ef168fadf7a056e6cceef0430f65a57b0f2c3372a5d3c533871c91cf81c40d3459cfdb5f1f66f53b2d8d50124ed15000000000000000000000000000000000483ebcdc219c4c361735aa0ea96c00c4908b9db62ed8cb565d25a7fa664829bcacc37a5608a3c3ea3a42ecf74708ee9ccf0a9be4775d65bbfc894f8ca66fa6f69d4249ea7f6b076fe193f2805e64f94000000000000000000000000000000000f7232dfd8367af413dd078f9d5f47b8c76c38b3ccc4110fd59764265e6a368fd4609b52c21f8e6db2c73908d4ac0b3d0000000000000000000000000000000018433b00ede4de21cd6a1c78c5d280af98b814f0a60c625f0a8f355be43d8d99346282b6d9911c4d4074fe827b55d726fc6bfb37cbfb10a1ffdfcb91d9a52883cb9a606f4ffa8849a6e07386dc9bb3400000000000000000000000000000000015b0ef81908ae275b2d5c3cbc563b8424ee0be0e1f2fb77f67749a79b7730d33028a136d133825da14448b05bda1409d000000000000000000000000000000000461c575bf65c6c5754a214c2e72d6d24df2cc228ae1c9f99d75eebf9cf48f20945a6483185337aa7c0096543dc0a527d94959e16f6d780628694075ba5aa1a476d89d8fffcf4b4ab7e6343c011fee920000000000000000000000000000000006e7385d061bafef2c731ffedd01758f153e2635c7f2bc42ea2efe29931697a1c50e4a13ac420572afc523b7316190cf0000000000000000000000000000000018ad5dac1577c9cc1e9ed30ab277dd381a6babc17e86538570abac44573a8c2439d97cbc370cd2b5d2c6509a18dbc96f122f3a5e940ee7e5038421619daffb8a6f433605f37e78d863f814b51b2ec4e2",
+ "Expected": "00000000000000000000000000000000020da97236c2405d3f1bf4e937d8285014a190bbc59a17b7163a292a2b825f086db5d371776988d1aa2d7529a64d2a4e0000000000000000000000000000000016cf6d7b831a81d0c487bfc3380a1dc8a1bdada61426a457993f7d6c9c8fee9ee4959324bf7a2425b070aeace3cdaff6",
+ "Name": "matter_g1_multiexp_27",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017df783852d1f1f9c6dcf1975ed2dfacf3dc0cf942cbd7243a0cea7907ddb289f378ae59b30661d06d0702792ea9e9e2000000000000000000000000000000001717bc4192402e587400b4e7243db7e79fead2f878079c3af998b3a683a0539aad5d6c1e5da6e0a00ffbd10a2d891ff2b3908c739d505a1d6fa85a6dfb7a155202710b45861f1a8a7ac7bb3274a180cb0000000000000000000000000000000018c9cc123fd18d50a7c878b31622a3727864fa61d784285b990fd116567c69dbc7ed872866db2166c7af1812157af9040000000000000000000000000000000000f38e55466a6d1cc2512c1282f74f5c0c19777365819e48606c0a86d2c6aab8938475d15a74f24db868802fe935f6107e0e27a8a416eb38c989a66b84f037a5a24ef3358e20cd553f037a0a2461d310000000000000000000000000000000000816580c761a2f54c386cf60b1417d51a310bb7569a50b475f8d45f13ed6c1f11640079b5d6119270d616e77a489069d000000000000000000000000000000000d9af7b25803b611351f00daa88464e49b277de8d8fe22284a9001a13ed63ff931937d27ee19ba4000ebc212fe03a0390a3cbab01c34856b892aacdabe63d0a0c241ebc137a88c83ad22cf38997b211b00000000000000000000000000000000032fbde9d988ef200df573dc99b087a8ffbec95349256989774194dabea55d970ba303657837bdcdce3b59eb54669c86000000000000000000000000000000000d65e89d8df2a189761e04d35c9f4d3a5292d1dc0d083bc9a982a131b07df6250cc969a3534808959b583923bf02125cb386bebe0e49b7f07b0ac61b15306c2515a1ad6fd76a1825dd29a60e845c0e4a000000000000000000000000000000000ed3f47ea234f8fdc16e97eec7f4521941c37acccdfc422fefc6df9c1127ed293998945fb1bdce89ea18b9ec2b6e5175000000000000000000000000000000000a066fb6f1d69b88495bcb0f0eeaad2a41d5c6764e2dcac2ddb4ac340cda72d7b51b7901c758df15ea16e4e46c7053298902a82d33993a10c56b2fa3333cabf1c5d47a9c78354d58f70ce4807cf20628000000000000000000000000000000000ca7faa768ce5ddb6d668436e2e1692893d07afdf7466c00bc8c963b80cf0d44f6eb9a2070a7bd889ef692a81f9d76d8000000000000000000000000000000000f86fb53e3f061cbe777c7aeb63402616c428216a0c65d5d5a13cce1dc31567a4051420d54b4fc93c6bf263601046712426a4e2317fee033a226a91a52a5830f9ac2cf5f329feb6bdb382438b8a39f2a0000000000000000000000000000000011113946d8ed7e5e545ecd0ef30de293206f3ac50e6010fa7a1cb0371f47aab2d8775c51172c4dbacb05414e65fdae10000000000000000000000000000000000022a7b8af616e4076f625f8151d748f4f49e6dbe439ec695b854544f8a498c7e261c366a4c81be5b9cad85a4eb07c36de0390c05fb0dc9b4a3f76b51cf952a11b909ce13f9abc9fed6a349b8efa98ad000000000000000000000000000000000d863702db9f9e43ea311fdd7e0d87495ed0bbbddaedd3333108704417521b3da4b8ff0bf904710b0200453ecb2948620000000000000000000000000000000016a520d1162c7070030fea7702420de2a6e0f255c28a89bbcaf663c0d6761d201f07d86adf5ea6589e27bf844abf85a57431db9e576643f93505b5b25836218759e736c0d650a5221a652338b0073eb6000000000000000000000000000000001357cc987a4ee7c7bc063ec8cbaecbea0ace4b80e3af01f74d23801d5d37326ab5732222f60ad864cdc8c5dfd3edb37f000000000000000000000000000000000094fbbc2936e1730a1abeb42e58818ffe6dd97bed27a1e4fc090388d943763b055301852222503a2d2a9dedf69b3da26745a32591e359efa41e9ea93a016d2eedf1da112cddbf31818e8d687b36af2e000000000000000000000000000000000672e9a4eb4e8be8efab0595bcb7a6fdf269db71dcb585c12f9d7c1a8414b6e11d91373959d47a4c64a8890766f68671000000000000000000000000000000000203f3804abe330bca60b7bf9925a626eeae79d58ce7c71658b2fceb8cc93da9d455b6d59bb58bdc23b58238d4f01948ed37a5f4bfca6b77ff9e4f7e03bfed52ecf02a8f84ed3da6da2787a4ee81ad9b000000000000000000000000000000000c4e95c27fd983c31fcacb578a688c2fe055516735b5f1ea1415c5cd29592e7720eb2f548071fa3ac642b70e339757dd00000000000000000000000000000000067ab19ad1c97a773164e812771aac69fd5d199e4f60eb28c7aa5f09dd9b3adea959ab4ad47683d27394714eab4a40d281633dd6e729bc17ddc596cb1f17dc6f0e50c052a0b8c5a4c83900d918a9eb560000000000000000000000000000000003da3fcadcafc5eff08a736e4cacb1d6617c3f0850ffe33ff1648f783a4467163d1ddda082ba0b54e678b171b1f79618000000000000000000000000000000000a273fbd5fe99df4f724fb20ae0fee994823d374979ec7ff23dbe148f6977145de9a1f20eda777cbfe0fa4cf8c2a8949c6b019d29219b57404baa955f66cf1b2ee6571ad5b80d471ff6db569e32a1a5000000000000000000000000000000000015b74087be4a98f4c5cb442e4e893d4d92602b1ad36d0f038f232ce25b53e19816f44122e8f5c821b40a0cb36897fef0000000000000000000000000000000017e50b1e84c7e767171edbddc397653c35b34141bd69ca7123792d6f20532f6daa5ed18615bb364b72744f96d4a730be6a76411ce02b4dfc84ddf62ed26508a2dfa5edb5a98a6a20dd69e8b8e7ad2f5900000000000000000000000000000000131517851372c44894bf433d5162d0da394b87a9554e9d4f6174d5712dbf69f756c5da1534eed80f8596f906f36799a100000000000000000000000000000000130a4583c7529129831ad621cd1e04a8fcfeed67ea96db4932809ac140a089e6252bcd101f17d4653555b1bdd9ea3a9b5906098e4ad7e4eb2e996075c7cd660fbc399bc942f9080404b9d0758c4ae14c0000000000000000000000000000000002b8d72148ed7076656128040e7dec82ecfc2d5ed05050b27361a85d0fae6d90de6dc32dbeaebac039187e3883ab238d0000000000000000000000000000000004021fbb748bdffca854bfc5de8f69a9bec478181477d3c6e41a7da2fab3100f7e2737ce958c046d6447370d47e373ad94ef8c281a9be3766fe784ae017d93f608dc2cb97cbb7dd3e3814b5ade845d370000000000000000000000000000000015d1c5bda34c6fafa52dd3801d94a04c53a3acbe43cdd128de3a346739df5afc6dba58d63c7cc09d18589c41d9679cff0000000000000000000000000000000014367ab7f03febf90be2279a87890527935725880ae3d418ec055004f312fa0c42c8f6fbc9c319117f6ce600d86910f16feced33019b3b66d335f2118cd22b2952cdf9757fb3a0cff55b7c4f245fb438",
+ "Expected": "00000000000000000000000000000000130db02ba2d24a3d70439503b089e6da4cde7b5c51b1d69774b38ae0f265aeb8996e50ef077ec12199ffa3d000adbf38000000000000000000000000000000000de25ad8eb2142051fb2c97175cb4cb2984ddcab65dcfacb76cfe60f6a47083a22dac4f6e06e357a194249b7363210be",
+ "Name": "matter_g1_multiexp_28",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016785db77cadde48a4ed0d2f8aa9f91bed9387a4766c3566217afec80b180461c8e1017297888e9c5896e509a26137b000000000000000000000000000000000025b26ffb3fa42b1a9e974eb23ada4b9329d670e38970e7abc937463e522887d777934895be0cfbf13d213b3b737a5f6cb5e7df372d346fd13faa90b0d6961372ce2f32ec379e5e50e7ed8a13942cd9d000000000000000000000000000000000d90bd38049f2a8de869d8a748c9ff3120542f38fca6e8d5fbbff86baaabf0f19dbf449cf23c043dfea322d99837f7110000000000000000000000000000000000ede89c8bb8299726ec685765f10167c5b844e427d3c15da6ec2c1d97de174819d52caa96d5cc938e93dd09bbd1e0d813a5fa1674c20c97d08608d200f3f7611010e6a25a790853ed4ba0c5aacf111b0000000000000000000000000000000019e1e2706e878e60bf6fada47a4d4028750cb27749bcf8fff531ec75d1ff9b3a1b5e0bf19e2758899c3d8bc96a18a0540000000000000000000000000000000004b5f00109eb4832ffc9108740f0728ac059c613654a771beaaa028fef06b6cadb9dd182cc573d7ada1dcaf307a8bca4ace10870acf190b373c19ce615e20e5cb96d3c6be3ec155f2b29825f8476b77400000000000000000000000000000000013844937de287b98db2b9631d8e36bc36ded8bbb3ebb2005ea5ab39a4844fa354b62feb7433b8fd3e72aa89ac8e4ff50000000000000000000000000000000005603183a5fb09ffcf6faabcb5042328496f8b0f83e8fe9031f9dddfefef43ee4525d1afe859177d4b9f966599005bdb8d9e38d9383f09cf0f8a8077f1d1dba091ff0abdf7e77c3b65c2df48d6c6f5360000000000000000000000000000000008ad6b2bb88897a2e53d4fb9910b6244faaa045ef32a2fd223adbe6e0b1a5c1683dca69c0e9515dccf7e4589f1e69bff0000000000000000000000000000000013564245d53366d8468b51f88becc288b695879a70c3c753933092904b9fa5e64e39be30edf1f5e9de7eb29c4b3cdfebabeffecf9b404c6bb2e2d0c78fbb8609a38e3d3187587c3848e8f9781b7e9f440000000000000000000000000000000003b587bba9173011da620ff930befccb7b43093052636d6632fb6e9b59b8d127ffa0b7829b59873ae347eccf0e6c86c5000000000000000000000000000000000363be6dee6dd9a1271b24ff84c6557adc62738805b31714c9f7208c320aff220c02b222b96c62af96f1eb42b5299a63adfe53846c0038203d8b8df0cb636aec7d4ed7f78b0b0c1734be448bace08f340000000000000000000000000000000009b403c5fe094f6ec4e4b9b7d098c3ca6fcd838e46a885506ebe8cb3d8b29849a8f3d8f9550f6d33315e69f6c1a6654a000000000000000000000000000000000714a7aee8bd6d754b9bf0292be50836e13ae886f7952c61afb1b45a02a2c378d6d22eb3eb882206a3141e43658a068c06e9d4e41b628be51690b86aa8938db066c052f3adff774d35eee1e332312d3f00000000000000000000000000000000115f7928ee8b8e47af2739dd70bbccbbd8c4c4f9b92868b981e407887b448745514b67164df86126a7aa53af9ea7a0ab000000000000000000000000000000000772b21e2bdc688f0b883a2ec5accd48a13ff3917d1c5ca8896faffca7e4097021ae3c348bfc2e8174db93e079979967b3d349b1546a8c235d60c41408c969a0fd42425f8b5ddc1fa5102d2821bde2c60000000000000000000000000000000011bbf90f59d646617a6d074f5938f64232550e189c6d8105bcb67a3607e13b4668701f64933de602e5daf7b0f4f50c8300000000000000000000000000000000153ff6cb6a6dc6b6ec086e2ea8122d23e2c6abb8d59c7535fcbdfa721ba505d7e9113cfac69e1d81611c72e872071bdd29b83950e79750e9827ed92856e4d1e1b5f0b47c6bbf3611a1fef8f2fc47659c000000000000000000000000000000001897421ca9a740a1f03d67ed31b3922d7f6067287b4addef6689303571b49bae574c343e967dc0f270aa4f91381609520000000000000000000000000000000007ab14771a4e256ec4009aa03af8caedbec4b3ab21d6499041ec58afe17175a656a7600c4bdac42c92efc9d2d21b48bb6b5ac07fb4a184dfed685b93d2265cebd02a3296a3b0416cc6a115242079752e0000000000000000000000000000000005e4061b14fa76d4c02d77adc7e07881dbcb023dca9dbfd1301cb3252410d54db87816a6403d18c2ea8c18027674133600000000000000000000000000000000079d3ca06d0878a569a3984858cac6daf967bacb3fd540187e47dc2c0790d6cfffd1ae1f377c75910f0b9a17d2cde2bb3a7a25ad9f02bf51fd73550ccde12374d9b151f2f6fe535bfaa43efc391f7897000000000000000000000000000000000e2814ce8e1011c37f6f7c38ee9543c65d0d40282793dec81b195b2d4f4b55f2d2b68416eedc6aba6e31b2234c3f08b90000000000000000000000000000000006ddeccda49ae15e5574bce201589758d7ab8baaf1348c30111e997154b6ba413c03e939e288fd95d808017387f1882947944c8c814f143f746175ba0b2d75e2ae73730a265d869763f0e986c088bfcd000000000000000000000000000000000b78dc15a4f413ea9c8b347cd82c278cec530a28d239694d051812c4af08b5be888064f54d2fa2278ca4734549cdd41b000000000000000000000000000000000a8c5ecc1541fd79771037e247357599146fc46b852536529b841bf4b21978a85dd09c01baf8878bc2b6bd8e36bb93c030f33b187df3516866f259ff959d57fa9c53323d5c851fdabb96e5ea470518ac00000000000000000000000000000000172140620e46db480b2a9f1b7f9d0b374c0fa19145e3349906aba351686e0b75305db408fca3465fd263d06157ea471d000000000000000000000000000000000c20ddfb4502ad34e0934812913e222fd9aa201b9e10b4af688031d2202663e9c044cf3374ede037ef0c7aaa82428ccc4da8401050f30459e026a207ca631f0684a10813c64ee86dbdf06b7b29cd97860000000000000000000000000000000009d75caf6ffb593ff15d5635502abd9ef88675210aaf98a73bfea25888c90b63de14501459a038f07ca502b2b0eb98ea00000000000000000000000000000000091c4826870da1d2d7da43fabda1311384f24bc6d7693ab92f59cb76a06ea129911abdc22addd72181c3ecaa15dffc884d940555d48649f30026f70450b2caf2b8f7148b28bfd4349458ae89c323512e0000000000000000000000000000000011e977de99564d61c5e0d1654ceca0d0d63dc09a6dadf6baac980bbb97f38513459b391e40c09329d22be015fcdafa6700000000000000000000000000000000119164ddb3240c59428f11ef8c7e0469d219a591b926296f394048dd59a62a21ee2dbcca55f79df5cac6b784a2e06bc5e140e30424d2cccc91be1fd3a62d9ee49c9d64fa062d9350b3fa567ec21bb06b",
+ "Expected": "00000000000000000000000000000000073edf80ee80c7d1675d05f8bed28da759098f44730bcde3ca1a9a8e286ff1791fbf22bc36de06d88b20f7f1422dbe38000000000000000000000000000000000d52fe400f41b902f8801063c0f3e793bf643c027676e0a1ad3860e5455bdde58d988b929582823e5d7ee0af8987c551",
+ "Name": "matter_g1_multiexp_29",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004663e332c105837eebfb9ecaf524a8f7f4d651f3eeae6909824eaaa6250c9f7fc212f98c6b3d4c08c5198477f240a8300000000000000000000000000000000057144a8578437c9a10a7801fb179e417e9bbe1b85e9dd8e2208943978cdd77a8345d682ba83950e174c6cd39c9eb936a57b2c351a7946a20cbae1fd789ecc5f77376b09e911749831e9b5680185b1530000000000000000000000000000000017c44ab586ecd185de616da02f99ee799487b32baf2470871865baa2b2e3ca20f61e6c82d741853b71c5578199d46afb000000000000000000000000000000000c77154ab5f0ba817b30672367bf1e19f9e53a95d7fcc4565f82f604a07d5eedba2182cf1bcca2371af4d1bd09146cb98fbff9f8ac4ad10718d46a857ba28f182263bf2d13c8b6a00902af737dea56160000000000000000000000000000000002df334ee40a5aa144d3727ec6c19d8dac476c01935e7ddbfc164112e35cca9180ffdae5e56f1fb31741c327b5733d6b0000000000000000000000000000000006c1721530a765ce427eacc4e5679c42591d5d1443f0a1bca8a87dd19d6a33b731db6561c50a35511735324c5f402858b061de16f4f609c6947733b58c6444fa9549721fd9a2459652e8e4b8c69b5d6100000000000000000000000000000000016682e225b46618ff794f2da02a82e40193289c9df4ed6985b4daca3e9ce9ac6e8ce84a3fd6776119ae1a2e84f62e73000000000000000000000000000000000e383f55e44fa8528e80fdf391f2804f7b7f3367e0db07b78647e9ceeba5fb151a5b867bafb2d9c07a6a572ee71c2714355ed5b57b28451ad98fbacd5ae87551b7304e4ef5cf7b7dc443a66432406f9a00000000000000000000000000000000176de8a3ee21e803ec6fd42f7f297daeaf1541c08c5c359e286ba65b78d7c31a0a630a2c73d2e886cfcb289783f30cf20000000000000000000000000000000010645db8d7d42e004c4f76bb2fe8b99a3177624ce0c1f465e67f3767bb57ca80ebadb12fba65bd021106e17adcd8553430b6eeb01874ff4b0fb07dc9f23d8e45455c1480eba7fb3033942214e85a77200000000000000000000000000000000006c151767d1066f9567ed86f7759a6f425a9a130a4530a2dec0913e4efe2485dd4b0105f453e90bf27cbeee5d0482af40000000000000000000000000000000019a081fb1fe2893f1919628cb8a3b332ef072971fe6ea7fbaf79d327440274a589045db5d3f06d6dc32d6bc7038c528b89a697a0e8d2cf512edd2a3c3df354eb30a3eaf697779dd9270234b367c2b5ff000000000000000000000000000000000d19d55d1fa04f886078bba50e09ece3a394f3413745785c16d17c5936941345e42e4ac50cba055d79f2d813c69e0b20000000000000000000000000000000000ba513864132f44be3056d3d3d1fe8d10b8be954e785e3d07f816875a3454fb6d44c1a6da8c9644648b46dc7d8a0b67120b72463d54ac1d8f1b3f56f0f98861768b05d5174cf1883dd8eb0410420d5620000000000000000000000000000000019cb4ac7844effff88b242db9908bd8773d91cbd8e076127493c548350bb9f8230d57a3e9c4e4b212e5686bee925d80a00000000000000000000000000000000021e94fbe9881b2f5ce2e8d777a33336fa21c24818cc1b6b699f0bf5cf1f22d7b9fe85be05d09509b88391f78eadf14e3de7997113708f9d092836c2b0b59abf710d8401baea6de73ee0689436f035fe000000000000000000000000000000000c6429ad7548acf43bd9e7fd9ccbb09b5b9b4474937bcca985a2d00c62cc8b72e07e725a5d447e2a92a6bb9fff0c50c100000000000000000000000000000000135ae562ac2225bdfcbed36817c8deadf892da1f8982f4bf53271320bb4e702022128dfbf9e48fc6623648878020c1a67fc3d0560432dbb721f8a0610f0db31dfdfea8cd5ebe8da3fe3b8ac5358dd4400000000000000000000000000000000004a813c60a1988f7983f6ac644a66369153319e3bceda90fcef6fdf3e53ceb04b2c5d240cc65aaeb2530e8931f1a962b00000000000000000000000000000000141411938210cef5576dacba6d521bc46b13ce9c1f2a9aa41a0e9b56639995b69b6198f2a406ca5e471cb0a48233985ff0b271f02031a126f8632e30d8b17cc5b57de7b8b873e0971ff392d4246a40f400000000000000000000000000000000041855bc5957b8649451b7d91ef58fe8e0770b113ea3009815e60cb36c9b7ab797b4448d3747fa9b64b7fb50af906b6d00000000000000000000000000000000048f78b763a88fb7122e117ea4946a631be83b5ae456f0c77a16f3f2b546802bea7117eb27e23a5db65d616966bf2630f8b5c136aa5e2d670edcfb5bee9ff6095d85a332ad55763fe1e5e8babd145c070000000000000000000000000000000003ca70d52cbfe2c097c17bd300f4baba1d03951c6dae613bfbbd53f68598a71d80a285af1a16365b5b82991599ae8fd0000000000000000000000000000000000ff454d717d8518415f23ced167ad7ad1ec76c437e29fef81b5604e8bc628b320fa39c192f32aa6201c2b5b4035cfddc285193e7c10646a4601787edfad3d76e19d5b013a0a954873d92bd5293d3258200000000000000000000000000000000098363ac967c6800b28c28afe92c1379574ec11e0585a0319273aaa6b92322563ad56144437569f3b9cd70ba9e7f9e030000000000000000000000000000000006e4aa226ef031c07150bb231046f36b8ced6b795b3e3f25f707435abc214f14e0c420c699f9c880e8d647ba85d467ef35bb2175fff61894ccbb69d90375df627e925f1ac430a349e75580dd39546e440000000000000000000000000000000001ced5366374fd923b3196d8f6e35900b80d01eeaa6ac41bf7d05d1fb7d47810eb8cd2d1ab793126edbe863be4c1224200000000000000000000000000000000010b27a94ae8413494e0560a10ac71554ff502be7e86cd9760b0d4ea7d1df926cf7ff1661b7902fb93ebcfd1542619caa25856e5fb9547c48d41783bf2cd13493a1fd71e56b9c7e62af84a1f6cdae1c800000000000000000000000000000000120ffc413256888669dce253043ace9a8c924f2996d73ef3a64d76d88dab415c870071a22b97da222361dc02d91cb25e000000000000000000000000000000000940f2259f4fadc3bfbed20ed2b80bdd86f30a846d6167661339e15548f6e57030fcd0be99496fa406a2d025077a4a4e1155c0b9c4185025310e8020eb52abb6f2f1780da15e4ba81f3c9a88ed1b4a640000000000000000000000000000000003ea26434b5bc703c242cc5e84e17be5c7777758f0b232feccef6d200db9a03f10df46cf0eead48064f8dbbccccc3369000000000000000000000000000000000649df5d665a64565079201123e954e78f07177739d082c2bd0aabddcc13f9fec6ef082a1348a369e446b82181e52aadc5610b2707ce84ce67e82d5c0e5f5cd2c90925aefc1e39468ca86475012df045",
+ "Expected": "00000000000000000000000000000000110fac33d46271daf3924995a4798b3f62c79562d3b44f736b91add9f2af779a614d4b12a9c0d7c60bcb1f104b35474c000000000000000000000000000000001592121fbb147085613d1b647cb0e4a7b895bfd4e5391b45bcb287975bbf0e5218078d3e88f8383a506550ae07c9d167",
+ "Name": "matter_g1_multiexp_30",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000033f3c31337bc48622d27a9a3224a2acdb5c538a59b497a4a85840c81cff667ed0a0e4e3f4bb23a9ae53c1e79ea54cbb000000000000000000000000000000000cf0dc22af4530260cde26aa0eedc83a0ec3ae87d024e6907f3d22070e1054b3d4f24d5ace7218ed44763af6ec3f25ee32fac970e52778cc90396a5ba92ab98e26499eb1ff17d4bc4c1f78b64887d3f1000000000000000000000000000000000935dce5baf85335575af5a6801b36647727c3e28f224cf25227bfaa52fd646d6fdf0f24466631a93506a58b5f2df9b70000000000000000000000000000000007e032c51e2d9aa53a3120e5777a14963af8a9fc65dadf5da779c5ade6aa043ff496cf4f33e2672dc5e10c4a06dad86a6583bac9672a77f2fe62bea4364aacf62d5e10eb3a757fa0595a81f76543e86300000000000000000000000000000000178e7b4d05c4b7762b474649b38a5ce999c67ea677fee77115ce7e55207d87a82b6d05516ab41c2bac294fc382c0e12400000000000000000000000000000000126e5aef1a9729c73278b805cf102934239d1f706bb3fc3a81f3726feb4b3d2fd8de69fff2f20d5e5217edabb645e8df5a8e1d77c9e42a187054c938a8a5b4bafa834021b727036ed3941b1c1deb9d030000000000000000000000000000000014760b82d3b4949c67d38c6d9172e12bacd52ed49f442d781aeccb7c0444407629e3b7d5d5e1be996940966785940e46000000000000000000000000000000000aa2d6391e40e50ab9ece25786a42e8dc657e9112683279b143be5665bca43746244c27352d3600dc62c2c1c7776924339c02150e4e89b25563985c7802c0c43d00c721d521b54e767c1f509f584bf2b0000000000000000000000000000000003f7c65aeca3fe6e67c91e1f284be35149276a9d9c0c1907010d8ce26d5c88f2a68b632530a31e41388cfc97529485f40000000000000000000000000000000012b9322902ed50ae50e3bb3e07eddec3245df27f193fa88a7685795990a5fecfa4be4b5bf8b0702897cfa369d614eb942196ec0e9d2f572856217521fcc5e2869f16d5ec5fe76f7d350698f55ff0c5650000000000000000000000000000000013995f89bc17b99384e389c9a768fa4bc37526606966a74a370c9f964cd9d3a7dff9d6be2319d2c8c9d5ac1b6f5140b20000000000000000000000000000000017b32d8800e21a4553a1a15ddbee029788f58023164e65b25086e0dbe2ee0c16e519dcc4753c322b50c24edc305cc26d8df5017c9c35604f061a7095d976d08bb3570ef8fb518cb606cd39a3060157ab0000000000000000000000000000000017601971d5328ca817108dc9899c9c3b88aeca2ac5c03f70662c9bf6bf3e06d25fa4b7150e0838c21c9b089c7102a17700000000000000000000000000000000198db85ed42c61e1137fa50c8b2a3ad2eca4e9dfde3553b8ff7ee3aa6389d73c80d500c883e52be5cb9fe8f828bba84f7b82e7e565f8a521d1a9d0ecafc029f76b70042e1ec36c20e3789b49c7e50ef0000000000000000000000000000000000c830262d029435b1b857e7e3cd118e8a6825e3e413f5a5f67b37da686f442577c0beca3e86c13ef6924472305ab54b10000000000000000000000000000000003d35dcd36ea7352d453041e821dea655422ae01a50731698af020234e3ddd38140c24ba2af296a964f4f5896bc0af8c8260c1b7a249ba215f0dc127a41876f858b20f4422140bb7695c8f98e4c474d00000000000000000000000000000000009830bb211c58fdb25fb97a4ba226ab03516911e7b7d98f25b94c827774592b5d5c56edfe3c3040454def1429f81c4fb0000000000000000000000000000000003f34873ad16852f435cec18f977db00f786b7860c580ae0dcff8f03a8a1edbb417f01e0dbeaf035b6f60b733f38a564cd68d2b074d038ee0d9887168dc16805ed55df26329a4c0e062c2124a6e50667000000000000000000000000000000001718cef19fe02a179385ba031f23d28e20e7f57ee82db31e632cc3530d17291e54e8a01564963835c724056c53f9853b0000000000000000000000000000000016c44ed6c85628341789e80e1d95a10399b6ac126319bba3c66bdfe6a40f2b06b721a0867c30be1356656cd36e6370aa2a40c2e796148ed1c539b0584b90cb386844fdcde5d3766cbfb1d1b58626fcd10000000000000000000000000000000011267a6e9adc4b547ea0f42ff6cc9b35a40c3cdfd7ea3c4169fe1efdf533341969cc591f26fe9a48a44e544c515339310000000000000000000000000000000013d878f761efaacf28677577c93d825336698772044266d469b934332412bde9ad5deeee4c1f534a9fd89e799584d3394a1e176fb26983e549aefff9aeb220f50e071222073422dc2c44abd85528ee280000000000000000000000000000000004ca71357762ac2e9bc1f53919ee2c19d071fbd3918f5948f32ecc78be1e65672d12afb4d4a8df41a038bd5448bb0a04000000000000000000000000000000000b80b54ce782afbdad1cfbd57a852f629c0452346d5b898062a8abf12c73bf79296564d3fdb867ddd81156697a00f03ba62e07bb97ca3805ba2d30f39f44e70a7b2917889c26b84bac8f9739bdf764090000000000000000000000000000000009cc641fda19b0e33065a35e74a7ac28ca1bd3bb8a7fd350244ad0cd5dc89d91e7b2865e78ba24e112589e298e6c5cb40000000000000000000000000000000009c3ce4324dacb1e2ca82f4ce6a7ed1292f204f4f7b2c5e0086843546c5c00d16be4e7bd9c979ecd3af590b40b0d70a4a14278fe7a08174660c08323de272b2110047a1d1d8bd0e3c7d76dde030e00a60000000000000000000000000000000016ed972bad2d24d80332c4aeb1dc012ae4fc30a11597df1ca73114945c20e337d1c424e636d403141c737103a4dc02470000000000000000000000000000000009ab2d22c0161247a3c4eee341027a97009ea95bfd45fd186e15feaaabcfc09fd39dfeddb2d3631b943958620555fed81f516ab5b36a59e6300a54d17363ffebba35fa0c64cadb21e541af5078545b40000000000000000000000000000000001721e0fe2ebc0be63df10f4b9db3faa5c5fc3ada0bfea176c4fcd1cbb696779c03602cbcc1da3917dfc09af72fa3cee200000000000000000000000000000000192e3e3b5b9b087aba72b852319c200451a4976a4e7cd817eec04c007c8a2f800fe0bf7834d22a21c1989ad8c6ef73973bcdb23f9568e409271b5f907fd64b0cd81939a52a6db38fd8d95de76213f7b5000000000000000000000000000000000159c5a01e76ee666e8e22aafc77e27705a633bd3d1dbaca92117e4b80f917a3bfe80b36d3fc7721ed2fb8434558c780000000000000000000000000000000000c8c356e19c759e1eaacab45b4fd2e0b42dadf6aa2ee8c051b8ef4de0c4e583fadfd86ff6bbfca1eed42a29afa470c8c1b716b02b3e94600867e019be166f4532d264e0aa65d723dc0e117aded59245d",
+ "Expected": "0000000000000000000000000000000010f2b9ae629ef12f213e6408c94601482c4c3cd0ee33e3418c86f0b8092d1a1ab7d2600140f6e1231297c3bee4a48a9400000000000000000000000000000000018446e6fc72ffb3c6c25d6aee2d9a8bfafec7b4f63dd3f98fde09c088876c7f4d30cc0ee31985526712228766ad91d9",
+ "Name": "matter_g1_multiexp_31",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000de77471af6d857548f26f2ccea9c33f50db361c59b097fa481887b5a5deb4fcbaa25ec1008b131fedd3711d4d3ba029000000000000000000000000000000001037ee7b2005032974767d672e14be86177621db0ad5d7df5faa966b0e7db6319ead334358142feb370f60cec698f3d1bcfdf0495e49dbb8a8f9a0dc517351f39a6d823dcd42715f329dc78400bd74fc0000000000000000000000000000000000ae57db1c0d1575c49f8b049667e1c8ba0ca863fa56ee58a34ac1ae780c92418ec50294b666a0f99e0efcb2686a4d27000000000000000000000000000000000aa08900fcc4f9b551229b7a8a59aa9b337100c68703ef60597f6acaaa7c1ce910e643549dd0c328a7fa17e44b68de1cf095238bcee61ec1317c0f98ad4f8f9b39c5940cf37a8a3a676787d9dda994380000000000000000000000000000000016cf186f3a0ee77c7e990ec0784d99510320114793fd7a672d5f739e9b0f1186faaa9d5914860d66173696c603173b3000000000000000000000000000000000124f5c20e988b460c261d274251841cadf5c99a12c9ae8b4b3baa7fea8b592192dac3506860b15289df704cdba1dfdbfe45a6d64cac817cd479a501c77b6720c6777c6026dbee471b490fee9f242a67000000000000000000000000000000000166434c1551befa708de9201c02cfe18020d18ed881ac4d154f5e560995f302b57b1694740f76232307ec0ff729b2709000000000000000000000000000000000a961fa3c19068590b4c252c0429414ef393ee071b02a4ef15f6a5c722a73d145c8e058ebe1997058b38ce7961860da954868215022673de608cb43a3cb74ef2073ffff34c54fbb43f19b22a02bcc2ad000000000000000000000000000000001618c78e4962162f253729c4cbe326e7ea7dfd6d5cdac1b17353135485d434fe7c4d857df673793e9d12ee65dcad4bb50000000000000000000000000000000016921790d30423d878255c44966b316f9c29dde6695d66a97139fbc6fba9c4df9e291c308effc424e5e2134680846fc37068c3ba82e52fce0223a9f28c1d42681c7863c94797d1786c1adbc3e6d10dbb00000000000000000000000000000000128a8a8584726a4aa2cab71853f843f49efa79071a8ed0a6ed2c7913fbb85e254184d457163fe647d0ad719d04e6857100000000000000000000000000000000158d36271e87ac2879fdd3f1fe8ff306126adb340ed93406951e372a7f7f3deb1c347ccf598f2e007d92f502038bd4960042b8005283c7b91ef4b3ff7e20a91349c8c3d1301c9b54b901e8348a7d186e00000000000000000000000000000000047e63ded02c49b7126a1023f1ed4a0af20c2d5e95718f474e4171c0fa888d7fb53b6a2bfcd47893aef6657f31071167000000000000000000000000000000001404e16f51ea45098d5bfa00ece3df841a3a6630bff2b02a8063ff9af5c3f149e504f04e1fc9d9bf35324569e8b2e1730a3eb64ce8fe140d94956b0685f91a5462dba1a90093e803dc617559a66d20da000000000000000000000000000000001866eb045ddc4e29fa612a31a34355ecaaa8482cd0885bbfbc5cc0b3870a86a2b4c3f15da23638dc03619cae6b721f1800000000000000000000000000000000086aeb6a413db889a86bb3fe036486b4e26dd614aabf575f8d63614a300df8a528c9f6d47d59daad59d840f591063b22ec88ed0eac8d0f2f618530e91cdb9ea36b8d56c1001a6792a09e11ff65fc02aa0000000000000000000000000000000001765c386f85f7282251b6054f03a3941d44f9a8ea2814a49f75519f9fc985133937e2c9e06b59441a6d9a95c806d6b10000000000000000000000000000000011db74b6bd144f9a0d48185a3e9f4adbc79131764b6e82f11823f1bec92245a55d82e6d949f3378ea6605ec84f0613285f03e53ff983fe4886a3dfc03a353fb77927d7a0d1998a1c55ca7421a4bdac6f000000000000000000000000000000000bc9a01aee9eb527491f7334959b0f4275492afa38044f0e6dd222a3704f440b5ae2120e8e2798179634c65f3d674413000000000000000000000000000000000ff19f94b6802a4788c4fd84f66b9be03fb1417544d56d0e473caae0f9b9124c622e6298624fa1d53886fb5ba8b470fdcc1b04dc356bd348211ccc4c50d12cb382660a4f9526539c2a0c52b021ed2165000000000000000000000000000000000df5ceaa6ca501d1869b51f035c19c0f3f9db39c739f882a380930cbde7737790b25a2c01e65ed477755c2beb16e97f300000000000000000000000000000000148458f4ff4fcf8559b9f8a2ee4e486febff21d91fe4bc3c77988007cf700186894f1c1fa18ee3c4595a462712750d3097b584ee05c27d45390aba36772ed49d571837567e95f1fd3ba3fc1ba591672700000000000000000000000000000000029b16c9578701febf6662da833091deee23e647a15f16895fc057a37c153fa738efb1742c4bfcf27eda953a07aa01c3000000000000000000000000000000000196d74cfb1e6472b7ab67a664a7c46ad0377c2b465e12d94b035b4b79c7e358475339e09690557e4b280cc84391eb84752542cd551cafc5d50852526ba0a23d274317e1e4a6e75c0d19319e5853b8b6000000000000000000000000000000000e005ebdde060ed0233d1b1d6344b8d21f8cc1ceb6d4fcca389303e1c44c5964a4521dac8ce225e2e4909c4b2a47f622000000000000000000000000000000000fb3185aca9683a81d41a17b3a6048e75549d589354d4652756a4663cb25b9fbca1bcb9158e2ed73765d03be4e2b570f2f76a0fa585828f79553fbf3baac6a2776b782de66dedd6b734f9342e734ee300000000000000000000000000000000004df18eeff223e3a255e6652c3d14a6dad17c76e0597b43a6679a85f78d4bbaac1e2fc0ccf6a89149dc18045169345860000000000000000000000000000000019d60ee8b23308fdcfbb26ed30fda1dda5c6841b46fcd902e6c34dd268fdb1426e215d21bf650a340b284d5c7516efd3f638e6a70917c89811851109296a7225f9c7c5b3d7fe6d6ba6c7d1ee77db44580000000000000000000000000000000006b084e91066f299e44a0c37cf65c30009006ddda34d4151b0c18a5545d67f2bc76df0bf9a78fd2b771795c8d041655d000000000000000000000000000000000262ba1d9dbb009f779e2a584ed313d78e4ac69a811e071c10e21027138234a32deceab16a33767fdc4a78062cd23ec71c4ac944341dc68fee586d221db2a8167e833f18f012afa7c3844def6dfb26bc0000000000000000000000000000000009aafc73979c000236c08e089828880f54645b5ff4c1dcfea0ff41ffe8e3fce8ba0dbcebf0d4205bb6616a737b6d3542000000000000000000000000000000001399a2072604d50f92ee186924ce32c4e887803dc258b7495aa2f3d2187571045db7f360d2614b198f83bc8024b06559b0eedaee9347b10ab7b346fbc16c10cc9db486f561f88b756c269ebbba23a7f4",
+ "Expected": "000000000000000000000000000000000365ffdbc48aabd8f0e786634b9a853cb8312bf295543bd280c1a0a9f7d0f8ba95b3aebe31987ffab1f69a504edeac2400000000000000000000000000000000150af5ab7e9b1bc60cda3ceeada36abf9bb43f1182659d8d72281c1f1cdba73fe7d6e52abaa7506b89ef43f092f25bba",
+ "Name": "matter_g1_multiexp_32",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000012a651f467e9a1c1cc99c82e16cab2cef53b77268d968dcc73c5008e103d2e4d19aef4cdffa24b9474fcb393a48d6a70000000000000000000000000000000005d202cf9bc8c0124c0f817465eee7d4b1219071cfde50ce2cf8951efcc21fa19c762a1a8630eb7b8dd90cd03b8bbb0484adc8cfd2e42abc2f0e0d7e9c4b378f73731905760bfeeef01c94f8d5c3cacd00000000000000000000000000000000060650b71c97950ce5cd6b6bfdad46d66df454c5aae1ea313a70e7fc841e06f64a31edaaced17d8de56f1ee75f5263540000000000000000000000000000000018a211f44acc52e92ab5eb1ce304d80532fd4dacce60370dc62d9ffdebbf749689620798429b5ad1d8293c1967a43c12bbd5d4a15998d733326ce23cced86ec5d5b410c29ee98a4de19f2662c3933dd10000000000000000000000000000000000f51ac340d512becf5d7a515111f63123e9bc940242ba42be9f464b89847a8cca9d93360851e3d047de4ee667a6baf0000000000000000000000000000000000dd7e71b516b3752c5be5ee5f3908c17e3e019b46422f24659596a42e569ba9e8711b1e8f8329cfbb990942f258cce103717aadf16301a9c8741d65c86ad7f849101e30b7b1a344643b100a8582a6ad10000000000000000000000000000000015d542246cc0b46bbf5571c3173abfcf10ba447e5ec962b5f712ea7de3974c2873df1979c9d6432bc88d02588a3730f00000000000000000000000000000000005e1611597c12a4c7aaa25bd9ab1b6d30c58bd1fce3d87d66a03f25d6ed110c84c3e902ff5475795b5159126debf6cb522788b3597da7b9b106203dd0ea97527aa8f5149754bbb0c10bb6eca8a46d9400000000000000000000000000000000018f565b38ce775e6b40581f757935efca255311b872fea3bfafa0662620ad5a02a7e8ce48c17daf45668c95ab0487c4e0000000000000000000000000000000010686971b402783c1e7d60126cf484fd01b871944179adc4b28de5d72e5b8823b48d382a8b69f6b4681c74961ca2a3843c21276fc1371060c226424eb9886de6897b15b075fc5a51aab4710e9dddd3840000000000000000000000000000000008d42e31cb4c514e450f56488208444481db0beb5807c6f1c2d82ee09c9413cd6726dccd72e0b8ab6f6ce6492921b14f0000000000000000000000000000000012143ca6dcc3bc9edb5b10c3a47a5130e393986dc5e83d1eb61d9b193ca28193101eadf00916a3cdcf7b6c1369b17038ccbce4e92cf377f67244995badc72db0b80fe37c9b7d443595156fa41abea17a00000000000000000000000000000000101eb8b48df43c3e01c1508aa9d3dbfe168e7458cef2ff61c15d5b4e8dd11be6b9a76966c01682fb07368f22362f355a0000000000000000000000000000000000babbb820a5a8e0bbbae1e2455d54b97f6771ff914fe33a007734d5072a993df31c6a2726c8b03a8c2dcf48a73959a8ff79345f31c107841ae388f6cf116d10bc696aec4933de56bb9affe7e20c649f0000000000000000000000000000000002fe8c461de25f5e6c5a082fbc4ecab5a37dbba9255ebaa0b5d245735edd27550968c2558ed24f7bee99092228e37c8a0000000000000000000000000000000012513b2fb62725aaf948403c13f11a6d7461c70cce3e4f912c8d2cc9f2a8676d9bb37face3770e7c0121bad6af6302d121cf773387d5351aeab99971eaa3b207fa6a318ad60f1c3e16b7f68251f9c91000000000000000000000000000000000175c93838001f4c67a3e0e5dd7eded26a8818b2e492eab2e0e6f8b421e3d3611561c8b933010a3c5ff96128631f4e88700000000000000000000000000000000136292092a366a73a5609cb1e7fa403c59825e99c8c91a37b289ed779c4a3db71370a4bda2cf8509cc9d4b4731b4f52d2d69cfed6bb2d33fedcbd215dd4e9632a3cf86a4b2716406305f6a85e6090a05000000000000000000000000000000000d03e1d6dc4bf59262fe3bc3e163565110b751c534e57c621b4be59bac28d6e8bb379cd4afa3740797dadf32194fde310000000000000000000000000000000014ee46a0cf13e795c8a46399ae63e1b812f237eea725539265e13d3ad1a663374dd566df450fc1191512ba978736e5b779cabae288f8a9a8cd54523c20825b8fb07886bbf0ba0c5c807956f268af4fa10000000000000000000000000000000003cefffd8fa01842c36dd9fe1c57efef3278eebe5d1020582c3d13ced75d24177127da37eb59e9b46b4a0a19421a5aef0000000000000000000000000000000016c258ffb2edb299fcc04ad309ee5d8a8f186db5f3af8011d42b22b23687c2e814e2a8d366f3cc61d7c89bd9619523b31973977d8e8c592f9063c5a14a658990f9c3405643089eb58324cd3f05b5b5e400000000000000000000000000000000097b6535843436f879ce659b6ac9563d81ac0262b9a861bbb367bf8244a35a5de51f3060d05cb2174cb41c8c3dbd8dfb0000000000000000000000000000000012dc9607e0ebf73e3577ba1ab39437b03215e366cf1ecffeae4ad4c7919a63f62e45103db65de4c9e3281d7604b07f24a610bfd375a7b8d0b034c17c8fa27d4366b06c681131fa7daaeeeb08e25c2ca60000000000000000000000000000000004479ec5d5ba2f1c661df8e4f85320d0e754372e0c463098b0ad7477f7373f309c674dfd31c7f08cccbbf4bbd17c23d7000000000000000000000000000000000470cabd9f5c4bb8b1a370888d8f0f486387a89efb92912072fb0907a1e64f3327e9beaddeaff44c502414632243d6fb99ffe1dc2d7526338462860501d75380a5ed9d53e675125342afb6652a97437b00000000000000000000000000000000038101da3c35dff20a878300bcf69e393b77873a971838581daa9d096b00bd6fec3dceca882a02d397a90c816fb415a4000000000000000000000000000000001184246344c03be6103acd745b3ed37d8f67ebf0caecb00cb2528e0da9aa3f352a4677dd6b832c042d6e1235da7521fbfdd97465982b58e69993711a6a64134bc4e76b88ba1948af91ba3339e9b9d3e90000000000000000000000000000000000cf99121ecf9b02cbd006348b16f9d80f64ae3c946c4802ec6bc056bf6e95e01b80cf3fd10ab1d30260a402b7c46f880000000000000000000000000000000015f35fe1ec8c258095394ab2b021d63ce54ed4bfe14cc5666f5ea4d5a0461d535b8bce3263913c1b4e6db6996cdc037d786a2a3974c84752b32f29707805c71992d5d473f4b7bc1f0757d126607a1c07000000000000000000000000000000000e83f4b1d3eb8d45ec0fd9a4ef001e5bfdcfb9c99a6d1dd4b4e8043b4d11f5c6fd65296a33c7fd26a4e30dbbe1869090000000000000000000000000000000001197b11d6747280b37769946549ad9d4a1ff1006ac726d7cd322cdb4e3cf86906c7ed371e770fd95ab4fbaa1b7b514d985d33a7fbe6ac6eb42eb932dfbbca2f771ffad5e80fde686e5df9d34e9f83ad6",
+ "Expected": "0000000000000000000000000000000012f496f031f5c1b594256e272520ab98f3733fc9c481e7ec8de8ba70f493065eb25b681a3959994d37aec979c22c6c3b00000000000000000000000000000000015dbaf471eeef9307d8dccceaee179d8c9072b052af66fbf049ad1d346e08bb555238a763e903541fc72d9edc30ec30",
+ "Name": "matter_g1_multiexp_33",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b632afb8deb955e64fb4ff5aac396152e23b11a3f326df0d77b3ec078934cfd5e486244aebb44cbd1599f594991a26d000000000000000000000000000000000519f9de5a5b1623e4524be68b5ba0f997addb4da78adcc9c3d5910009a261fdf8b0efbb6e2a085e74112ac4e2106ef319582dfd9cb80d44c17c5f62360e62f6736d186194f0f8483e34d8d18d832d370000000000000000000000000000000005456d9312825dcfe5501b2c38aa610a767bd38f46cdc8acd92f0c8206a9c2f9b8f65c8baedffdec5e69f03fd3adc4c40000000000000000000000000000000009b2dab21ba4e4b4c284a623994b92ed5fff0fc198bd154fcfac9abe5f05b830066b44894ac6f92bb2f61bc88a7867a8ac0bd9b8746fd02aa70d8b8a2b5d3be46baecf9449d8cd3d620cf9efb3c615d10000000000000000000000000000000009f55a987011dcfc796df284c7bd758c3024d4f09edb3884dc087de26fc1df0f71067d44fde07fab9334971b4a0bace000000000000000000000000000000000003a4ee3e9ac2632cc81cbd4ba397d44f738ee390a4af6ecd65079f412bdd8c4a37d5413d0d9a7dbeda8a1267d6d843b069d889881d5bb87dd65a9a02a7fe239bdb55ee54a6310bc987e7c5772404d7d00000000000000000000000000000000173c7db310b54a4a720074dee01dc0e5f84b606c9c3ea0962bd4610b569f478d7a5221feaa944054cf7395e578d730d8000000000000000000000000000000001697f0e16c49b223dec9e0fa429e68dbaf96b004a561aa3e37158064ceb9232c1cd21156c053fb89ddb230deaa7f8336be658348e299bbf2438a0c013f86eeeb69a013b8004a4996189472f3372b326c000000000000000000000000000000000ab7f085b711171f999d0c4a46cc7c8cd8a429f6bd90d1b860c01066bd0d193f1c1441ae5aa97d690569807749ed69e1000000000000000000000000000000000824841eab90d56a1810c129b8f27d0068fbb7e3536d6e56cdfdd9eb553e283c5d0ab1c418869e886fafce53697520859b9d0ec92ae7df3f52a95747659f8fa3ca2cd01e8d7ef6de384111246886bafb000000000000000000000000000000000bbc8c5b5e4373e76457fa45acfd3f1151735457b0fae06e1d3e6e5dfeb35815aed44bbe6395039481ce02d2aa2c502900000000000000000000000000000000089ac22ebc582bb71a60c88638747e2243096e8d193fa1863089698fbf6805128f9e32636d6f954ff03bfb6c5bcb0060d2ffdf1237b4e03c219806f2dea745c94bf08924e1b9f11deeedf0db19da6f3f00000000000000000000000000000000001fea43c3029447965718c8e76100875acc8fb4da66f7a4f7fc5260de3844aa9e9a89ae4d9baa11c118b9f851fd63de000000000000000000000000000000000844aecf4a3ebfd8b711dfa9efaf1a57d635f46fb980903e362d4ad55d48c4289a3fb1f439e6b7d8f88cc51867d6b462cca0751c9534cee7f14d11b7c8ccbb2c537a799df59f850bb125c6362d72e9c4000000000000000000000000000000001384e33086ebe795cde3c951de9b48f3f0fa2f627524cf0c4e3691599b62d4611c6a84897298c287d162825c3f153a75000000000000000000000000000000000a04af7cc41c2d3663444c8aaabeaf70dd146dec114458b3d1dbc95cee99ba89a4c5a38f2974622292e3236fe2aede6d17f890a1120daca4a1bc1bc0fa7529f0a87b5fd6ec385f12b270bc0f1a5281b400000000000000000000000000000000158820954aaf8e6387cc0e8e528723e0875f5f719a46ae5cd9d967674815a2d9679aea9b5736f882d37e2dd26b7db17f00000000000000000000000000000000058cb933f8dbac61a22477cdb3f52c9e3de6f060dd51aada35b6f8480a53e8eec8f82800e89ccaa2d2eb1dfb4352f16561ca18257d9d989ec13d4f158b18ec17d59344f4558b6dae6c0aa0c2f37affb50000000000000000000000000000000000a7c9c1bf574503a884ecde5e921da80b299c4efe674a2d5c841e6036adaf7c1156393116c2c0b9827978d43f1e3e440000000000000000000000000000000005cf22e56bf4a46504ecedb072fe5e18096f9da550065612a1d00cf79c65384dea1bf59cb7c52de905a04f1886f36c8a0fc004ed8a135ad97cdd1bc4d0c3ccd15e65031ad7e3cc13ef2c260958bc43be0000000000000000000000000000000018e344838e2efd9363911898f27882f67454dc3b1bbc71f1d99e787bbd6a1ec9744876156ed8db2ccd826f2b4fa784050000000000000000000000000000000005528854a8568ec6491c79aae1df15d965cde683c9ea400b470105117f2bf3b41d2f958a8dea5f866a55e60fd06c1f07d8cfaa1037e2c81c6973b221dc7badf25ebe3fb4b42bbdef1124265df2c7ccc400000000000000000000000000000000047dfb6a6125ff02e12c4a9d88ebcdf8a4375367e1473f5a0d99152bf0a4055138aa9a83d98d7f74d9fb8888f643cac00000000000000000000000000000000019d0bf5162ca55d8113a97cc3255d090c6924362e6e05083fc323dafc3b12e898cd600d2730acf8cf5cdfd4420962881c25ecc5d37659ebb0c9e21ea2f8fddc518e3d8faa99627b21faf105445f69d7d000000000000000000000000000000000e132de353cb09b69ab369c616718b9cf492cdb9d3002593319a6e7b61c7d90f94808b75d8c7e3b9d7a811d01baa47a1000000000000000000000000000000000d636abffa063379e2084cfc09da5ee04d40d8e74ba0247a01be414cce820024766195520f1d2eaa90fe254e12a4d86026cbb32382902d9b1963779070d749cbc4df1e7605f840819f2c04aaf89c732f0000000000000000000000000000000013f2367ff71430cb541557f79c5ae8a0d9053d82341d83037c1f73a52585255b205706227de4e87d6ea2ca602483d2170000000000000000000000000000000011f3f4e882de30b40bc160e69fc2bf4f7c588cc83bb9dce3467accec7c47714e2b326be001a36c42ba39c7f56b72d6fc699aa549077a80ff8732b5fc9df148a90f405bccc14bf7305266836566b7a98b0000000000000000000000000000000014bcf3f26683234584d79b436cc608462f1e2c20b5ecc5019988d8e30137859a4b6d0e1135dd5bbea0781b8ed3f0653700000000000000000000000000000000090ef29bf63ca97ae8388588227e1d1a0653c43b16a35a63f2ab4f0b11fd8005d9a85d30a7406491d983f347e4dfb9f140e2de1a2901f1380a383a741d79fbb0a041da5d7bfb92edab74cd483edf9523000000000000000000000000000000001817fac61301ea6a43d7968b22616b836ecd1f20e5883e9b475c18353b066f93bd68a8274d0b6ea4480d8e314766dff7000000000000000000000000000000000c52fc676604061338bf0712fc1606dd09783a1f9a5250e3417056e3c39e59a28c7707d5225808414279ab61e49b6081062b323592118868d547e83b731d15ba2c7bdb1ee4fdf73600c2584f1db0b45d",
+ "Expected": "0000000000000000000000000000000018410462829b3a72024468ddcbc42d59a99a70296024654f99b591ce016304537c525513defb655417ba3c0f5e614aa8000000000000000000000000000000001416a19f73407c262f5e464021eeae1d1f10c3ae5e45f132a2f402a75cfbe409651d3795e482b15d29037e2f7105255b",
+ "Name": "matter_g1_multiexp_34",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018e6f25220e4b4011a0291424b4062930f5df45eaf1581d9591560fd77e630411e0abd57f9973d4542741de5cf3132e7000000000000000000000000000000000b31f903e7fc36327e404973b90efe5a5d2249770170ea1e58839e19d8aee99743be012b6e8a3fa73efc6bdc08be372f764ab6f4c43630d5e79e8c474d76d8973a7b7bd1c7f1a985333cf1a6be5ccff20000000000000000000000000000000005dc07fa620d476d8f64358c920a401f8b08abf739befe1c266fb307b959f37542140e398c33b082d09f9f53cedf6f810000000000000000000000000000000019d8e51a28c936b5037424a7ffa8cae75496131eeb2b2d5034e4e882c1c91f6bbabc9ce4fb2fe4be3da4eba46326a3603280f1b1e78d2339f64b5b2f2bd77aa24623b79fe2c9debab4212f4ff564983b0000000000000000000000000000000006f5f80dcfe8be87d057e2162788f7599e55b69ee8c6bb6a47c505aa324ddb5ffddacfcff35cef3dee6264ef73d6a353000000000000000000000000000000001056081108195d4d27af7332215c0b444c9f63c7574eefa81046e1d064825492e2dfc5bf2ab5847a37e6b253d9dda9fdd4d27ff9d03ab9120ac2adfeb36b070015f0e90782255ddc9111704c5fb111770000000000000000000000000000000008db431907692896f9e6e254a6eac1a0ba5f9cb84563da69c3601aff1370b7a5a98edf5a5fbab06abfb4496c777bd83f0000000000000000000000000000000018a3bc407fc42236c4429f241fa760c6513614653e8b02835480dbe1152763bc6a1a7fe076e8bb44ddc04322cc906e1ac66d5291311c7cdd1f33e5365ec0689608b3569427a8f6a9cd0b94b671472e66000000000000000000000000000000000cf32da94af97001664607c7840631a8df02a008fe262c6dc649a3eff34a42dcb98884212bf3e979629c98cbe5fc457f0000000000000000000000000000000019b3b4d82326ec1aaa3de3b2f8e329ac0243d3f6bf9356886be4033aadd0398a5c58c68510de29f92a7ca910d851da244b718a5129659250640e333f4567043ca749063e63d87efd86a9995adfd3b845000000000000000000000000000000001504d90c52af16b5f88357c87d4be7c329855ccad6f6633af0fcf4341fae54aa4b1ddc1aa22fe1ac12e9d850a05a9ffa0000000000000000000000000000000012ea642b96304316451dcece5a6bb324d197e31f56ef3f1a17c973742322d08f443b7cd156787f8291b52c0a6f78b4b1708891f45d7bee38fe382820260061e212c6cb9a8572b4d1854f3ab09409b05a000000000000000000000000000000000fc61e9589a2dd7f6dfd613225d80a70ceb977bdb518b5a16e415f887eb73fe9fa5c9130d5fc6deb4ad153c5de0907d6000000000000000000000000000000000a0fd7de87139581e9b1ab707e25c186640db92875a7822d61d8c476c40ea07bff000cbfe6975076434d0b703695740685ac0f94f300b004c7f20aafcfd9129d6c2590749504a3f08c4cc708fa30100300000000000000000000000000000000188901f19a776ebd2ddad60209f4545ca9b0a038b0b3c67b6f5e35d61f8cc2a297d51450663c4af182079d3ab6b01d2000000000000000000000000000000000151b9eaaa281acd803abd71ee4098b4ff6535e5081a33cc68ecca54eb9f1a8f94f3b1b21440f33b8648ec456dc1cf7f3fdbb634bc0f99c5795f3c4d6a0efcda7f71427f1eaa1c5411caa6cb05ee314780000000000000000000000000000000008ce8bd24052a8e1472bb64cc215974e20bb16d502b3a8113cd6e3e9a2bb7c3fccd45ff711518e8430221f40859374ba000000000000000000000000000000000aac2e8db9123be3e82905a0fe780daf4a841f6f961428b9b431c3ba2ac31e8c06118402bfc7fd15fbe3ada0ec8bbb2af5e4695c01849259fb969183de385ef30c2403e081067c2d9b6b5522c73fcf2000000000000000000000000000000000017c580f501a1c4823483ae718371432a8a69e16e42dc0b15bb8e01729b6707ec20b898e3835bba40d7e8802d9438281000000000000000000000000000000000bcc167264fb9d6c27272c2280d8e89f9655ac7e6408694a3a4ca6fd0b46d1d7e3cf608bc2ac343806c5de42ae7a99e80ea6fd588db5efc5fb2248634cca683d39d610886b59eb3077fa9612c368d7690000000000000000000000000000000017ae89082d6f531bb7905068a9c00017ba8ac8867c6e467fcd3e88e9229ba5b21ff4d0a5ce937b75b3d5dfbbe35f2e7000000000000000000000000000000000005bda8d641b782ed51c416d0ebb1cc7c8f623d49b741a7cb93b3514e71d5b9102ba2e6c768661686c2af2acedf466e4dc2060a3421c5a8336c80983c9a160345901a496c3a74fc5248fca081d099539000000000000000000000000000000000150ed2c2b2d1b0b87badd0dda44325000a6fe98d335e03f0d4d147b20d4738e1e0f0ae0ddb2783bef283684e631ff45000000000000000000000000000000000ec1fa174f3f42cdb0fb67a520da161d9a9d1e53a5b0735738580fa3e80550c95cc3a1cf67fed67dc2eee1597e469fe0e27e4afc3e6d59d0f5871b35eb83b46cf15da6c326e88dd8edf84031f58e23f900000000000000000000000000000000111f184636052719c6df1541c100d5a21d573370fa7afd18f5ddd1d86842169eeb02c494b33f2bb2f54278530729bfbe0000000000000000000000000000000016be03c9764aa34c898dcaacabd1493610f55efd36ca0b35eb48e89c7968e7a720d545b18fdb95954e01596856d42975cc7efff04f143e2d038de153861da5e04016a7eb17fbe6365de13069d088b1a100000000000000000000000000000000114fa84ccbe9552a2ce2368f1778a1fd3c67303d8036fe4ba171ba9f2f6039aec1a59fea1b8efae88c01bb50e53950440000000000000000000000000000000017a51bf70c41571f36d003c0715238b6c8fd64185f616cd9076b730ad16caf364a75fe68de246249a42cfe013606874709a2c3dbb4ee4f485dc60dfbd94a358a7c62204c021f2d7b140187ee9ffdc4ce000000000000000000000000000000001450fe1500a6fa9d966a0c905167a414d59a3f8a064089f09db047241e9abc31d9e41ef73558eed741541414731f838a0000000000000000000000000000000017e61d4092537ec48683f86b72123637df25a5fd926e5703f993678a798dbe635ea29303f8b4d9ac76231a71cf515a70d9b15c065497392e4b477a556ad620d44e671137cfd570d53590b7528f8ff680000000000000000000000000000000000e72f0c855fce66335533c05ae30031cbde78ef07571eb1b645fa3ac5f3a7d76a4d60cf078145617c5a7ccb16266bbee0000000000000000000000000000000005b3981900432b193985f28a88a72ca9958b4628e5ff9d2cf8b0b23184e2bd433d495636de3d56711f207719fdd3fd2f9e2a72eff2ec29a65b417767e7090b73c2fb530de6c8f4e4ba30543946423b12",
+ "Expected": "00000000000000000000000000000000110feb31a1c40d570d7281ed9f0c0ac8418f4a7aeb6be3221b130945becc15bb353ea63623ec7dba2844d3f527c167e6000000000000000000000000000000000d76c7aed58945a7fe52f37eec3be7cbd4438645a649a04859a487e9e2d4c82bfc76f7ba990f825302861d82a748c8f2",
+ "Name": "matter_g1_multiexp_35",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000030c6580a3dc73be106748d070b24d9231c382df143fb4bb8ad45e4723b40f90724b7e54510da1b2bee523a29aeb58100000000000000000000000000000000010cb3562fa1b0a3778393412994e46028367ed52dd62a1d446fa02b50acd48a784ab49141778bee5036b7d3a95c9ec217b9aa7e0bfaf135ff24720773ccd1e0a46fab6d678d91a14de137061e145fb9d000000000000000000000000000000001972db503f6d70a0b247eeac7fef277098604e54465309967b68d24ec1cece802d8c4b699eabb72e03736902d41fd5b60000000000000000000000000000000007f30233f9043927a629b11e7da48f895fce86b31911ff5c511c7b50642c296d37a3078e2e12f1adfe668731d0e6810ec6733c9bb7bd195622b96c4181e8c8837d1912fbadf77d6029f7fc44d793b4800000000000000000000000000000000011ab9fd98e42539382c85bf76b563478fae8cca90ba1beb0be56b405da8326e6f1348b94eba61fa29c78645f8eb96f8b000000000000000000000000000000000f30617240632d129ceb69de1d69a23c9bdf950819608deac0600d1d1fd730a3a6d22dcfd635b25154b5ac7e22b20c70410bb66334c677397d04f59eade9630463065cd7da3c9d50580c7d66bbaf487d0000000000000000000000000000000007556b86cbfa9f186f38fb1a8adce4c08f93f874bcb36ba61df5750c7927cec8896bf831c0150c249067ddada2e914bf0000000000000000000000000000000016ecf045f13c78de8aa18c2ddd1714bfc532ba8ff5b7851b58240cfede20f032067e943486df628995b8f3845289eb02d97a16fc5b2c70829b15f73615286eba334de1f520b5f0f6a83d2578399cc0b30000000000000000000000000000000011379452e627dbed2ef1c74eb917b95b3933b8fad8295235cdbd6a4394d9b75cd3598c930d48c2d4abbf1558c65e97490000000000000000000000000000000005e7044829ae3f9b073e4a2237de96b0a1bbec3a30dc39c839573eff77321b1e0a49d555f0e31b8aa096f83f5945026bbdbac08202bbe5df1229e99c76c1727f7789e0f8c2002f0a2c195bdfc00acb360000000000000000000000000000000015f8f0f22c1553ca663ce7e9ac00514eb53443f6c4869f985dceb118ee60a88a4826e9dc7fdbf61e77cbc93768fbfde0000000000000000000000000000000001646ecc89754ac57d7d6fe9b871692d65057f23d397a410bcb07ef3df0a3c3fad9eca515f0d0dcf0610edbdaf4cdb5d743da827b812ec6ac23b00208cbad0f2e8b3a32434aa61dde029683c34c1ab1900000000000000000000000000000000003a18dcef4939e154aa790b0ce8265f27cfff48d5fec149d91307759eaddf601c788da6ed8124764bad940f117751b0e000000000000000000000000000000001813f4650490f3839fdc9f96ef744ea93a9fd86f8a43d767259c2e0abafe308fec2bc6b9d62c1dd7b5ab1aebc19586e93c7a8f7bf434ce5e63ac9365448da8663745f66689b4b04968f9b8b1b68058930000000000000000000000000000000006490f351e78a40c0cdb827aed3869db293c7d654b43d69ad1c9b3b536b1fbac67d50a835878171974669a30ae9ad1bd00000000000000000000000000000000041816bf846528e23eb129689a87c2325f1b8edf237c530eaf578a908fa0a2604baa19d6e0b4a5801280c27285896d5a51f2e2bcfa6ebf84d3ad83c57257b9032e5d62a8663ed5d77afce00f33382bc600000000000000000000000000000000064be79c5d382c6dab72bbf28defddf14cc7cdbb23eced6bd93abed078175668d4dd66d0b3abc6384165d26bd86680f9000000000000000000000000000000000fa4c8be5d20d16bee7bd5bacc0b0086875a14a119b4888bc408850c0a099603fe3f79d334e45bdc9130132ea15a180f6d8b15ec8908bfe008414757c0c7f79b3079f9db86d91ac3ec8f38ae2c94d48b000000000000000000000000000000000182f23242108b022ecc1d156a97f1a5fea2cc2e059dcc82273212f37c312ab77886c1adc370bdcc6ee05cfec957db970000000000000000000000000000000014ceefb3ca54bfde172e0455d34f1f462208df69328782b7961ade821ab91e7b3ed5426b4065fad10cc8fc88c90d8e87f4723e85076d48389c3fb5a5df16b6bc6f7a69ca701632b1159677bd8a6f7bb10000000000000000000000000000000009339b95b043903f2a3b5926a27e57cd0c45e7955946718e7dfebb01f18e9d7a2002c670769c4674773a835311f2e58e000000000000000000000000000000000ba94f6b625c507934f633d5420654056a939c68899c41e3f337f7b927fe82191d39905b349870ba0c41c8bfc97d64a9a632938a6df169fb64daa55d2f874ef7629d5be41dfa0d50827c082333f0fca00000000000000000000000000000000007604b5eb3218140b94732a601da577da3cfebe04dc7dcd94396c1a6704a0ef5a5bbd0c31c196f2876e1a4bb7490629700000000000000000000000000000000193098ff839d38c9bbda43944d7b0a3ec9d0d6732519d4cfbec506d29801780813b2faab46658c4383b2f26c477580af283a4da7f71bde54d4b7e28b2b23e2eb05d8b025e77e15810625d71faca6d6e500000000000000000000000000000000022ca1a16df42ba543a118212a75eca13707ee01eb3ce27d3659b1fedd99b9fae859f4eaa51e9be9107704276b578a0c00000000000000000000000000000000012d60cf33701caf11be6c9e3ebbddb9c7066dec3821a2e0f9e5b94e029dfea4063bebd4b2fe18c2442311c2bddc7c08d402b71c1fc5c3f3a4ed9edc73457a27ea427f83a784796e01b7a1451b3305b00000000000000000000000000000000011d4918642919c801fff0962062a387a4dffe693ec09cd3d0286a18e3a22c84fc09e8396ca82e6054d8535cd888179230000000000000000000000000000000016a1f0c7fec5647dcce688d3e4e526749bbf23c1fcd9e9168ace47399f9198c9b3a6b8aeca68febde1b7beeea0641aa2310bc47acb3aba7eaa490ec104ed9b2985f65c7347f69fdc67b76f6f43846a990000000000000000000000000000000017203c37b21375a524bcc906843a0045229c5531ca23177dc88026e83723db21d9a8b5e52cc0be1d232818ed9abd496800000000000000000000000000000000097b4d7fdfa442dcdb64e405965439ebe70e4e71cc8e13e299fcc0b5dd88c67d6d0dfd254ab9b545e66295e2f3df14dd91b88ce9888e5dcfef70d6f960a456dbabc792571f2a98746b7d833e7fab9850000000000000000000000000000000000fc4198a87e789015a1e44935321677e84356aa9e06592f9cdbd149d13ac312980f3048dcb9bd02779a3b10fd24ec98b0000000000000000000000000000000011425345ae1139647f93fc13eea0e920c491a49998430a339cd9d4260479a427515109753e70811be4cfb3b96db5c78b3e82cc1261ac3864266379b4d518e25c05bc492a8946b38b8a64acf47aeec4b8",
+ "Expected": "0000000000000000000000000000000011cd4c4507778871fd7b28aaf79274178df83f3e53c256dbe7a52df884d28df6a0d87d20238a15f489546a459195ace0000000000000000000000000000000000439a672492225fc09e46bb178a5d38956ae237d9f7d187d4cee14597facf2c06d7e70be5ce20e1f1389e4da6321e455",
+ "Name": "matter_g1_multiexp_36",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003790fe37a3aa78cdeafa76bdbebfebb22ab5f1e09e4e488418568fa307a5db18f9d93126b0d3cdd6a28abe3a4648f6e00000000000000000000000000000000043244b9c78fa56c611bf72bd6a17148abe76fd0efbd25085d7b46c90318ed591c5975f79653b98440f5f7c04cae4d7ea2a1148f1ba719b2da92c418fd137efe21a44dd4cce013ab36e57d97dfed92990000000000000000000000000000000008e8fcaf6d2056c6e144295d437f7f1422f6af7a1b62e0b8073141b2992b6ba865822aa2d9fe439aa1d896b2a6d231c4000000000000000000000000000000000bc693fcd2021972914747e48c600c444bf69ca8e1386655bb5d987608d648965c754668ae0a72c2439ba0ed98e5e581fec5d6167d7777169348cf81ad3eab5153f8f2f18fb5935c5ee5e3a759f9b5af0000000000000000000000000000000004e877b9032e168650ec3502ba65118aa0a8013b995a647210c1c36a6e6c702a93caef674d03d82da1f7c5d7ddfa0d0200000000000000000000000000000000063dd22dcd667c8288ca5b172e34b4eb783403105523c0467139b814e048fa21245879a5e9188a1a87d26fba52a9f601da609e1c8fa42a993ff355a70d44dfeebc71a801daa36acd437daec5d7b645d10000000000000000000000000000000018cb2fffa3181bb665dedf1d60de6096e8c5ce43287cbd86c2df5a5d42d0129c73cd281c085fc562b7afdf52f0a680c80000000000000000000000000000000007f9884780460ea018351b4ccb5a120d44312056b96c5ba77cc38789627d20500d6b7e69dbf6ab49d6bee998a6aded67bc5f7f5d096247ababa51852724ce9ddcc6acc7ab6180beaa1cda97dba94b4ea000000000000000000000000000000000bccad9f23b4c1231eb07df139548b66714a064dbec4ac6ac43ce18671144f2bf7ed99f16442b9f6600e1122c58f52e50000000000000000000000000000000013646b3c310a4b3f279e17f45fc8104d2c9d00f698b869479a5a0e1c2131e3f3a9dce86115ccd539bbd4346261c5a75f3222b41a59f9551e91572ae00582e1e41989ff5f8e2cd1ee1a78f55c2b28ecb4000000000000000000000000000000000d02250115596126e858a63a7082a8c8f8ebe055653f5a60c855ddbbe3ed05792d08e5cc348094b8dfa4584037be597c000000000000000000000000000000000f68ec7da947cd0a57177fb91d12a820ef8574f4c524fe54b9420f9ba4944759c92d5919d6dc8030fc663c34519b64c37431e5c1fe5f8d38c759bc48e8207695a3cdf07d4c1fd02f1009088539085da1000000000000000000000000000000001960580ae965c37c2ec219dd0753749bd70ac2f0c4a3837418023c5142caf7b4dbf592554a6dd95872e018e912e3a20b000000000000000000000000000000001210b4093a07616543ac2034faa9c4a93b5f4cc3daffef2d8450b1a1770948de56c5bdbfdc9f1dc9af5e20778c1e8e6cd474e755f6ce9045baaed65c80f5a686547089e8cdf4ad2b7c2ce7c255cb5c73000000000000000000000000000000001955d93fc0f3ce0563ca4f4ffae0257297002001a3eb941cb9d3bf82b8d7f97657ad7168bd386636aaf45398745d5158000000000000000000000000000000000cc7a0babdf499322e060f2c83897fa7b6c3e7b4f56de3a18c823e0ffd87545a3dd68947df8cd8d3de5795ef7cb05391976c8775b0eaa1e4aa384d222efc476305c7ea2d625cf5c67ea4368d7a9fccd1000000000000000000000000000000000d451eb31b21eff2c18b52b882e1eac68a524e3db43f233a9d08139667cd0173e3c716f29085c599a09f19019fcf447f0000000000000000000000000000000015852c483c8545fbf0932c99b1944ac58b37228d15284c7be5f5259bb8002abd57b26c244846652a862d46016221eab19db274233c46caaa9c99690fd00fcbfa4eaaad7c41f8ae84313448c787165f6500000000000000000000000000000000044e70861dec38d2b5ac7fec042c6b931d4e0a072073333f03ec4382fe40919b29378cac920836b1641e5e2db053c5c2000000000000000000000000000000000c422a91c81a99caa32666511c0ae4decc67cd94e85260b49760ac9e97894b0eb434d39c3884aa4614360b79681403f94ac9f9ed46ae5aca33af9ba1c0fa5a2138d4ca02b962fd1d02b4636114ce1997000000000000000000000000000000000af002ec82c5ac0dc87e1ac27f4cd052eab67bda318557c70fcc2edbdc071ac4a3fcae90f73ee514cdf8a543ef59050d00000000000000000000000000000000109f720464ff2eb2978d66370041206abd9ef0c6ce79d51f7d233c49b72da520612e59c39f3a775e288ba2220fac1563ab300ee55e90ac046dbd772da788dacddf72c559d9378b39507987a9774301b0000000000000000000000000000000000f62e7d0aa954742a2018d42dd9cd76f041d9ac46ce659f4e192053a1d0c9b23fad78a06f61d2c90eb7b4d1bfe6d951a000000000000000000000000000000000ad5a5ce7b66928d8e6e3806a25425bbf2bc63f8ec87002a913c28ab702b83b6ba590b41a0691daa5b921a12375ef47b275b22db781d5e8fd07f36788bc1219c4b4a13554c28d92a381adae111b265730000000000000000000000000000000008b836a23836624b39e3b3388027093125749a5edd5df50ee0cadf1d485c9dac9c2569a82484269fe7af02334369a29b0000000000000000000000000000000015232caa0c064d8d1bb7fdcd23c0eba21685fc4671e9f04cd1dbaa0382aa4e9d87aea42a99cca22205367d7b2261defaec69b95dccdbf193d9ee4c51615c0b7be5ac6bed3f2559f0cb2755c634839ce7000000000000000000000000000000000875311ab0cde9a925383dc84e4ee8e1610b2f5af0e1f530aed4155cb8ef0b5050d907277f55d8dd542a89e4e0990bc30000000000000000000000000000000002c7a0d315bedb602f8ec558648ffa69831b9fdb6c14fdd44e636ff00777f2f8ae4aa23aca1b261460e6dfd87e7e501131e2bf1816a84c190eaa850ecfe1a9376123e0d0732d90ac3537668f8f18b9f7000000000000000000000000000000000f9531c4998aafabc26e1ab588a97a78c236a854c3fc92424320a37a236d5181d34f8e5533aaaab2a6ea3385acc85f6300000000000000000000000000000000130350be432fd7d68940fd5f54649820ff5b3d015448d48d1f4db3a05ab0405a73ccfc8eea1966abce35833b5d03bf79f4087feda4bd8205d96cd0bf6eee44c27a6669d7ae8e16c731849cfbb2324e1e0000000000000000000000000000000010fefde43b2cbdab52ba664e12c7a6ff29f647942e16ba5a0d41701754ec63bf199ac8e710ae8dc6a033abbcaed3e05c0000000000000000000000000000000002189172e607876a6e1664fddb990009dd5c7a8412d60f7dcb235ed1825c756598bc67f8d5d383c2570a880492d4ee1967b81583fcdc9afe5f35974dc9b6310ee8e1c92031a49c08b05555fc0d33517f",
+ "Expected": "000000000000000000000000000000000765877938c1a8170e2c2fda55241e3c64f7485bbca218f4a2026d00ef4708d014fe4194048da8e994cae1088694d1b4000000000000000000000000000000000b32833dc9a39e1e73578b21f75136be6c6aa2b4128b0e6ff4fe099f7b7a8ba8f2b769f68d32ab4d1f37793aca8ecfc9",
+ "Name": "matter_g1_multiexp_37",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ab94114b3ecf9535261a0726a9bc0e0907385d56206b61b7a42f643d46296c4022bedae90d761d3c002dceaa9167fed0000000000000000000000000000000008e67942ab2b9aaf2f6f865b7e957a25dd7ab8d8a0cba02fb1648e4c7f15ce00f4f5d09199a583f38425bc62d32ddde69f3c65c2c25c6c37aa45b1104745cb8ec511a165ffdb7e304f5478aa3add4d7e000000000000000000000000000000000e53abd9ff27231fbb09155f794e5d126c490314016e31c0b12bd1d2af97a705bc267f92e20b64c91d9af1bbf5e45b92000000000000000000000000000000000ce7d0cc6656108aa7005a56d15a497009c90871f01eb38f1bdc82edcbe4945a2f2b67c9b812aee42cc9a9bf9ee84bc08fd50c46bade91a13d6dc5a06ee62e5e89e0ae7ee885e5516ca6c2dacc36f6f30000000000000000000000000000000018c2688f573d4849b6d19e711ef4d14659c2c580eb938434a3b2afb8c20c522423db4c7fffa42eee9ee907a6492b77ad0000000000000000000000000000000016a7e69d5539263fd6b7eb893d476a00efb8cf09f21a54e9ff0d1c11e9f3651eac8a5db31b40598af6c943f864ff60ba128db1a106328916ca5d63c0b5722642febed26f00a89430d52ec3eae25a019b0000000000000000000000000000000002380f3260c7289ab2005f7b1d7f572565ec938bd894bbb0047ced0b652fa2e74aef19c9fe6bc1fd469b2a4640245777000000000000000000000000000000000f32ca31e6bbb72a02f4b0da0e1627dab9cf1195fd7f48613c89b06c702e662478b24d8b3730321f803ae3a307fd498bd45665afb6a864893e389511a0f7b2df74c9e45a86fb69f6bd79854e3a88c2060000000000000000000000000000000001892b0d219ebabc3be00f45b00be55ae486eb79b1e41aa7dc8457aa0812e7276c21024c79646128fcb2b3c517aa41c3000000000000000000000000000000000793bed9530c814fa0d0ed1684614c1e6968dec931868a64372dc1b648b1f99ccce20fffec7d485a226033601b92a7f228f5fd09c2c1819adf8e6d0e0f4e4681babff46757edeff3839e9691888c132200000000000000000000000000000000173f49cbbe6304aa41513d3742b89c6b07a91be50264350d71bc03fb9efe4faac4a19e2591795ff4a7e67fef7a85ed430000000000000000000000000000000019bb5dcc59ddf055f099a1c3949bb50972c4cfd035d4d829dde4ae94ff9669983e9b1a7edccfc2436648dc942862676fe6e61390ef88f20591570ec1fe71c3ed769ee8e234c7cc7303a4cdc065717736000000000000000000000000000000000e3daf60e4929b4a237caeab203f86e6eed0ac630a8b955a03460a7e609398d076c660401f8d2bd9601e5bb5e315e1e400000000000000000000000000000000058b20160ca2232cb8b6cc63c5a8e11613afb9776e22d93f687e7ba005b099531f9693f65f153db01f20c8e9bdd7839ea83c5af2f9d10c06552ea7d1749cbfa7574b238433c1c0e4788efd0cafeffa57000000000000000000000000000000000c89f1ebd19fb920b6748b15192829d58820ee4995cab9035ad6bfd8dedadbc6352058806a7d45fecefce40133261f360000000000000000000000000000000019151260431a35d124fe44116d86ea99e3f3aa14e2eb09be8193dbaa8f26fb0ae2451ca1c70610233d3f0af9d2e33fca4bcc88d85a5a8a29dfad37ba97ab3a5defde4ec356146db8d10f33bfb36ddd3700000000000000000000000000000000162b48d56f439ff56197fad444dc460cc6432722b9b86c7abbbfa383ae1546e160716d94e442183196816084da90bf77000000000000000000000000000000001278d0796c26110f66930ea9248078c222a0590a031df30c62fe6beeefa70deb0c8287b0d204a911c147cb6344632bf329d5d818e62c9791c320e01a3164e142d9804e9caa7f96b4c3b76baff38ee2e6000000000000000000000000000000000f4fdfa45aa3b5d1838b4dc8a2dc6250c069806ec3c551ac961da5b44eb58d962d843a1c17ebf89bd653e9e44d16300200000000000000000000000000000000052ad9ce994c837596339dcfb73ee25bf8326657633fb5861039f197249d425e35c238dcebb287b77f41bfe7f4db5c9b971c8aad41e401ab6c49dccba28ef26acf4961978e94e633b72c581ac03621e400000000000000000000000000000000185c62a080df61ddc97ab56d2286ceec655172b6c863b509a1a92eeb0719060528ad3a3365ad5e7c0858167ac2c6d22100000000000000000000000000000000126b489e107dfdf4a4638069944d1b1297db734e5da1964086114f9f62081527d7d3f6032c2f29e75b4e1ccf5b3776d4659ff910eea5280dc5c24c542516053637a5dbea576a94a22acefc902e56568e000000000000000000000000000000000f884244e098975b837a58ae0218e7e2606821c95f51d114a483ed5d31a59c9b9cb3b1db029a0286eb95686e0457afd8000000000000000000000000000000000caab7f67feea4752d3822979a770a28c879f5e8f916b72dc71a3b14820ce170fd229fdb61596d9e89b4be8f515c470e12ff32d44eb442a711250875d86a401d0dccc95e5ee39bec71738fd812d487c600000000000000000000000000000000155d3e886cce6f257513529e40c21b5657ef1ff1f4e71bc32b968db3e05652b1ac780da573fe1a1b94b7fef86e7c260f000000000000000000000000000000001184cf09544ec2826d0101d2b79095da6e5f77d453203c52ea17b6476360ccf166ef092eccf86dbe3a260f7fd25a2794666b820fae2459b98f9bff20275a3c96ddcaf98a78f3f5fa4a2c0a26cea79352000000000000000000000000000000001523e919446b532593b8e70cff1206e8910444c01399c0dbad932b596cd0b9c2e40983ddb38eeff4fbd5e8d2b15bdc780000000000000000000000000000000004be8fdc3a3296e543701ce8c1184a983a2932f33913d6d733f5baa3a783382739b697fab4a3d6f9ac5b85ffbbc78a3540a9181633a146d7f307ca7606cd45b8e721c46b955a6989d421baafd8e401390000000000000000000000000000000018d20e7846239f472ef42c78454b6c335979ec563ecbbc3a93176a7be9dde603e6f21afbb68058035958ef7392dff3f20000000000000000000000000000000011ae4de8a7e1a958a1186bda4890d282773788f7d5fc5432393ac9deaba8bccb5db952547f6aae49b8a90c813c5a93a4662ac80797c633d8b9c8907acc2960ebdcb5bdad82d9fceb4411d5173b7411fd0000000000000000000000000000000010641c99a359d16dc3e3f68547288c944d44c7c3e6177fe94428ddcf3c86937a3fe1f41a31eeab551e11cffac012e1fc000000000000000000000000000000000f407b01737dca388d0793521b667757d70e626ea0ba3b051f522639e752280b5657b1b97beae3105489161ae95a470059401af15d9b83e2ad68cc8e2ad1508391516ba0b26fcc5ec6eda8b318a374b6",
+ "Expected": "0000000000000000000000000000000010084535f50807f287eabff2fdb83d34ca30454e4cd747cc3818a9dfd80c30fb3bf2f9f771d435b79a2d36105266f0c1000000000000000000000000000000001663a611323246a963856a92d52947e72dc123dfbeaeb9a3ede6147246814630e5304b50a6585894843790f5d4c818c3",
+ "Name": "matter_g1_multiexp_38",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005315310b8412d62f5d63fd996e8c6b14aaad5a6c83eb3505a28fa6bbe469f7a7cfcf10b49382aad4d6764859ef4910e0000000000000000000000000000000012fbfd9ee8bc712354fa3b73e57fcbb07231aeac980e99d5843fdabc081a159bfc6507911212adafc162dfc21a5afb739c351c585d1920b8cfb89a5bcd72fe041b17f7bd091ba505b287778b0be4e87c0000000000000000000000000000000014e14689a5ef5b9ee89369c5c0de07fbb7980f37294a0e7570191b73f4406ec4bd9bf4ca2521f8d90157e9c3c7d4211900000000000000000000000000000000040d06da8127e64a71532afc8846bd7eb6fd5e845ca0f1d96effe0b12a2f8afb121d7fbe89f632262ba0e382e8204701ec42da11e95cebbeed0ebaecd31be24801fdec8b81f4046fea52f553c4e7910b000000000000000000000000000000000c5ece364affb6af365a4c7506389694b9a10f3ad6798c326852fe85a892014b6901d097aa8910256f47ca1d4667b5a20000000000000000000000000000000003f300682da34e22416f1ca2bc3430e3b153c95773c8c76660603a0ecddc20ba570545d9307a6b0910eb406aa14d196bdfdd8996780460757702e34ad98f5f64a8c1e0bc8851d6c97f02749b8f77cd03000000000000000000000000000000000ad0508c3b4fcc1cc608d002b66bc703cc16182a6e83794e4f3739238c3e02fbb6387ceb445791d54321ea52f779a35d0000000000000000000000000000000009a442ba572cdd9e658080fdf1753670c27e88fa894c307eaeded6ead17799365d1cefd1fd13f0dc321c0e881a4965d3f256ff23b38b3b986a62074c5a3e05e86ead9431fcdeb67512f6d502fcefe3c30000000000000000000000000000000018825670284d3dcaa90a678ff37f23e8ba36307f3c1146a8f6c782f7b43ce16f281dd346962904684c22c1980a772ffc000000000000000000000000000000000d65166eaa6b4ed79b5ddcd7b44f06ca1bf8b960211bcb17d5a26a8595a1ae1aecee9945a674b92384ad05f2f0f64fb6c01b3c8bb0acb17198bde9adce3b0f7ed4cd8615f837aee928524b0984c99d0e00000000000000000000000000000000098da5d9289f26b61486e3ea52b0145a47847ff2b9f1d2756e363e5ea0bab27a98fd01d633a46ab48aa1d2f1d2886f9100000000000000000000000000000000191412a43858276e4d7e69542f9e6ba4fa9bc0a8784df590aeb1e0d65ffb56cce0031916af640dc3e57662f5e5203436458f882b63c99ada33d8215111a6df21c8f7424eb2fe9f429256201d099413c10000000000000000000000000000000013a279c27bf2234542f4ac0e4c2676b41b3cdfa1b55d5c0eca1c686589c37ac63139a7f532910fefe275a08ce2d37fe50000000000000000000000000000000002f56719390112560fda45943509729fef3eed60215190ca1f90143a4d2ae6b41aeaff7edf027f27857d56bae1900ecc804d7a35e5731b111a6904e0998d90ce86cf612914152fe3d2fca0201a41166a0000000000000000000000000000000016489ce6e2b8298e2fe0836556875156502d36aaac621e45514ef03db87631cfcd308285fdcf8ca7ae8bf65bf53a37b3000000000000000000000000000000000b6c8fe0db4492a309148c54465ca06c59c7b71e4418d8fc1874cc338df40fc1355a523387187402b04f5d01b5e5b82b6f1629a801db6bb4066588ed79f75223120728c3a57f7129d88f7f877149223300000000000000000000000000000000065358f885a974a1f64ffd526e5ced18ae5ebab2ed6c9719c9f879adc940292ad124fe5b6c8278c82a33d1ab2a1916130000000000000000000000000000000010d019536f727f8ae098dd9ccb6344417042855fc6722443218d83127cd2b07a6816698dc1a48776d2cbbc937f83163dfe80ddbcaeb784e24975b9a42801c89bdfb842cbde5fbc0c3d70c0632cfcdab80000000000000000000000000000000004248c5eb514980da698bc5146fd3743f5b1a458dbb17edd38f65c294e48bbd55e0d9afb3b39df2e82085fbc03e5655c000000000000000000000000000000001830c1d21ff8cd1ad8467ae0a8d2a34367e7c44829f7530263ef3d7d5bd9eef76b756f475448c308f4c03453f54b43cc1aeff13de7bcc4bc2ac1b37e28ce466805757dda29c9c743eaea9da33f47f4fd000000000000000000000000000000000dbb72f9afde915110f2483c09291595c369f0b4ce2c91779da9266c9f74764da4976a221c4997cb940302ce0e59ac080000000000000000000000000000000012de4b2ca14004be2c64ada45e9a0ba7989ea0e22d0407088a092cad87b4e26b33d5d8f96fe6831e085c6fd27901af61c4984739882bd2f882e12660815b96d2af7812d7ae87f5be034b88e9e04fa289000000000000000000000000000000001387a1edcc34afa05541e15e2355d3cdefbfe22ab7481e1f194e461521894b97b2e18c9fbab1eb5d8e508a0bdae08b5a0000000000000000000000000000000016c4ed675f20aaf2c825de5bc4c11ce1e85a0b91b08577080108ab7b52bb674f78943a5f619f557b96a72206cc1bd447e7f33141d383a1a927b7645656ff7a5795901a997e27003c5672ae4fbab4aecf000000000000000000000000000000000498481301a55b2d1dc95f8115534b1baade13c2cc4d5bdce1fe8cb1734004600a2359e5dd1c61c7338275e2f4fdf455000000000000000000000000000000000a3d2ee413b7e6c0e32e51dcb7d124be92990b7e4307b9b459da1db20f85f4a35964b7987933634fb62a07f797b00b27fba4674313a9727aa4b733832a0e06666d3e38184836edf786317de9dd055cbf000000000000000000000000000000000a885ed8c3ab46b60a7d2e198b6e8d069ca8f7e0692f2b8ce99df2f44979b6045fc17991bfc27867be79e2055cc8aeac000000000000000000000000000000001728864f0fda8476fda4df08fb6aa9e40a01dbf19a4d22c4fa0c319d8496d405f0a5f9c79ffbdd5a4c1b617326f3d774dc0c4d0e34d8a16b3bfb51ffc9b3c353817e8e357c608b5075c173204963606e0000000000000000000000000000000016edd94f91c43f15818752660e4737071d44edcec5d5de426141966a9880bb894f3566e98a05232b9717bf85d66a57c6000000000000000000000000000000000a789ee6ecb80e2ab9c6e7a945ae4839c620f9a7bf430ce09b57a64479d5a10a1ec0a721678b5bece737f0dce97a3a56e4e31f5b6629463311b9d3c8333c33c5b2e79761ffff9863acd9d636e1a9586a0000000000000000000000000000000008affb2247059dd4bd1498c8e229dcba313b156e2f420fa55331e7eac93d44af55a6c02bf2101d90955b95ff6fcb411d0000000000000000000000000000000004759596f12f17d7bad24723ccd6f86c646a39beb2aad35ae5a219ef57e1ce6eb310b2098130489421709bc20b4a53d703f256e58f60307ac1888a1b0b14b56c7435213e271eecc79b4a6f88d102be4c",
+ "Expected": "000000000000000000000000000000000f841cf3d8897108b4a57a7802a3cf8a43ae31e711a6258991b6d5b3851e9e0d759fb90899e462828ff9cf996bbe9ec70000000000000000000000000000000016fa655a67f441e967d3137f6ea8f6cf636fc1a7bb662b1e22f87397e0c77f34e015e6bc124291647727102a12561dd8",
+ "Name": "matter_g1_multiexp_39",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c98e02c9f7784d0dbcb4a49c97a9365cd069817d57cea3042cb4198180b95d141c5ba4d383de188f06faf8f845f78110000000000000000000000000000000014be6f602cd67fc2d147925cd6c90457dd253db766c4b8f737cfca02ae15b47d5798c621091c4be71fec75e0b8b1c00feb850f01feb55bb99e4accee0aea8fe6ed0bd29b2ca942ffe09456733aff10ea00000000000000000000000000000000077bb03ccd915742dcf3c2640ec61f05bbd70987d2dbe9641e0e34ebed3600703e8f9c382e77f99b70c47f54496bb6840000000000000000000000000000000015ad452396c23e820d1e8a8a9cd7557062ca9c627cc7439d43c528e0170e2760e7761c9cd872141543834c89c75537d72b373fd7e5806d227ca1f49ab0a7f8be2b5950906c8974de9f2cb4e13ed20a9a0000000000000000000000000000000008eeb6c2c00a9f95c5b238290b06a67c1cbe0e96da246537c29c0efa36b53230c3c5d91e3fa9d129743e5a9d87e81d0e000000000000000000000000000000000ede1011370a956f240419cdb8a0c8ae869c3d583d938ec32e29c5ece68ec8be0e69296ff0c97aacba59991d65a25563babde7f3fdf9fba868b5eac61337be0d73517ac3f06c39b4eaceeb27ab6311db00000000000000000000000000000000179776b08cf2da01a94bfe7be4b89b3308330cf797906f85889b63487115b386c68c8518158342747377fbda82a6d2240000000000000000000000000000000003e51d69bfdb73a2abb469b379e2b4825423d2a2cf2cec62e2313a76d260be1b0f2892bf82e5435e88205ecc9424275d5ba1635cf82b25b2d7e466717f5716c33f5f3e826bdedf19dbc1d95ff0c8052e000000000000000000000000000000000af478b121104742d0cd13473d1b7f647437d980999cbe7aa8d2246148d970136f6194df1785027ce944cf9ba00aa4f500000000000000000000000000000000170e9f798184188cc21b0950e0f3a570398a97405dc87a2e077af96799960a938f363d216474422d8f4762fe5893ece61a0a832e5bbdf897553c1aed35fab43aa3f4510c1782115e14e5d56229de2dff0000000000000000000000000000000005817e3812f73d3d236e45664af8a4abd2d4a44f741c3c1866588c2bdd88b11741b1c272b68e20800abf3adad7125a400000000000000000000000000000000008dc859c2323f0d2dcab76bd8454209c86685a971d531a32b00985eb822d33691c2524fe25d14ca386047a4976b9e7159b75e0582e9ad7aa4a02ed5ffa22e55570c9f20e6a24e2186e8a2a2f838fa453000000000000000000000000000000000ee06092a2ba4c33f5c9dc6062d50e3b133c7fde5c81056f74a2d869e8f92310f07629db9cc2b755f12016cb7894aac10000000000000000000000000000000011714a54e236d1e13f9b649a0aaa80cff9e093342c71a8dc9ff1e2d4e95b0f6b4219ed847ba6620d23feded7d95944183b7252f8f3cc6341d490c5c4464bb36e012f1b05057f405aa907ebb2c983f6460000000000000000000000000000000017f6061908e62edbb8fc5498eec23a51c861815bc1b437b7383dabf303e6a45d52e73f8363addac61974043afacb02ef000000000000000000000000000000000f3fc04d17d801741f3583e072110b327a3488135659fab2e8b1d2aecf4694f6d168bdd60624713a7c2c3314f8309079f10427f6e461e7b63b781e116a4d5136ddc79ff86b71fa754f00c797c035412b000000000000000000000000000000000db7d958b44ac5ff3bdb4991dbcdcbeab36bc6d21d9e0c8fbb1eb66601df227a6367ccc783a92c534a30b17be462b95d000000000000000000000000000000000424eb0d9da831c658ff048d3e9ee43a900bd1ac98bee97be073ea55be1dfd07d425e0906779f0e3459fc69d316599e56440c89f8b10ce15806938b7ad65ece194d2fa3cc8d7d5591bc1d52d010896af000000000000000000000000000000000c9cf785be01b7f4bfb0140004873d0db4c8b1387dac0fec42c6ae1a72123ea5cdd2b8c98c69b78d617b16c48ebfff2b0000000000000000000000000000000015c4856f183d26d13196739d9b9c971af111b4905b669f3e46bbc8d8c4281cad1be05e9ac28de0a98031923fcd1f5aae43f1bb26469b778edd10127e634fed4d749e25b41d8eba86eff2c068c33e714f0000000000000000000000000000000001802675ef47f9660d5969dbfce973c8bb3e6b2a2717fac9a509fb3c7ddb272db86f283992eb3167145f2e496002fb1f0000000000000000000000000000000014a5b5d966ff72e036c51686dc6a9f39a487ab8adab6fa4a906f28acc67d64576fbb3a00cefb7720f42ffcd62fc8adefa40251ec7a7e9f7cc29948b122010d9745752df3f4a9c67427a8b58122ad4e7e00000000000000000000000000000000076ed600ed860f16ec5dbae3f09471302bf85fde7702b3376b0d670f93560e77699bed969e7001570f44dc5e37aaa830000000000000000000000000000000000c993a8b08d2eb00bcee05e1c09e8a37834fac53643643402f60fbfe2cc7d795f5c68f3d6a32c8604c37211585830426e03e5eb477506c397bc1a5204b30872085a36b65b7a8df3e0e187f3022736329000000000000000000000000000000000eaeaec30bd8d8dd9ad4d38ff97e08706ffbe51388a93967cf16155b10d218e5b1213c29c8054cb778a0d3ad22d32eb200000000000000000000000000000000079e5f2bf405cf2dc79984ddb3f813a07225729d4cae8ddf7536e9240fbd0480f6b66321749a6a9286cb07758482e7f865cb04110bbfcdf00616c2826e253f61cf955756e94dffcbb6001f59ae4a93c10000000000000000000000000000000009a0933829c2a3f2c3e93f58551e7572ecf6eaa7857aa899a7ff0eeb15ccd601559b9ff844a177568632bc0ddd6e80a5000000000000000000000000000000000b69f23cc1556385897bb7457a706cdd8539a3ed3e7fa504ffbd95abba1e824dc77911efd1ad0a9c37e1a41a76ad38d13ce1bb7cf7d7a55f0624bf5c4c35327b178923d88be748a9b079720c27b500e6000000000000000000000000000000000d3c4cfdc03ef5fa066be3c26744032e5a2045746cd303b6df542a6133c671f4d25dfbd889840fd624125b63839a1aaf000000000000000000000000000000000102fd619ac946e99c765010a4ac392ab907c37b31f628d6d58c0ade093ef394a7547de36ca0630820f4b5d857dce449e2b4c64b363efef0c5525b0337bf407879755f060af451075f4345dea7e681a3000000000000000000000000000000001589cebd579c2cd31226245f1dd3e428a76c7d0012f8dfac4dd3428a716d05a0a79763f0061d3b5846dc29a8a006a37c000000000000000000000000000000000bdf3425e6cbe628f9223930cb74ace4358e12e5d367a3604edb05cf0f0cbde84346ef45597bd61592500583827524144c85e47ebe2c26e0aa25661d3353b5d88c632182aaecb35303d8d47f01308a0d",
+ "Expected": "000000000000000000000000000000000555fd5a7818bbaa7e786f11eaf6f8620b9686b76c6293fd91690a4d181c0b470295313294589daaac429607b0020c9d0000000000000000000000000000000009c3a53113a657a5f7e30ec28056455f700cc7c3d40cbe4219dac00980675023bfb7462e634c8a131493f12725a27d5a",
+ "Name": "matter_g1_multiexp_40",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002d49464783e5ff91aa0dbf6827315dd308e778b3da5833cfca3b6431ae784193d915a566142ef347b6ca024b6f1695e00000000000000000000000000000000029051d39ea4369a837d4cc8cec1eb8f9e7f9c3a247dcf99dc75eeae43378b4b9c4175aaa5eb3f7abdb1afc15bc2076d5bc589e7d89994400c511789cbcaea19b077e0b02d625e549bc6f2673ce40128000000000000000000000000000000001363b8347ef6754f61520942fa8cdd07e6dc2b72cd40ae41a23622be239ee25834482533ea7edb9cfd5a4e21e4f33f020000000000000000000000000000000004495e8d41b145ca7f5268e66c03528c8d976cd650d815257906e46c1f9a0827e0e79f5a8c2906ec96718538e1da3b1d2c3d2a0cba111642a6354c117d494be805cad5b5c486bc47906a2d37a9cd9f850000000000000000000000000000000007735147af3bbef7cf0c4a7c8f1dea302a5e4edf01d42c1e484f7fb1f4b8fa23b8a7a16fbece9270d8786016836bc979000000000000000000000000000000000053406bb3d2a4cf37924643a186a56844a4e77ea4c9e9e2c707b5f947ef956369f400e448930aef7135449f8cc51ae1530ff74626657262fb49460b2c6981155871f2eb5562581a74f968233c3cbe3d00000000000000000000000000000000133b92eb9f9a3c6cba655d5f26f396dac467b6444657eb0a811dc6a58ba1898f24b336f4fe9b11c1e0795891b00b6c150000000000000000000000000000000018952f3a7f8aa78a8c5e5bd96ecd5d2b2f237916d8e2982c40cb7498423f12c6ddd3cf1afee75a3e2cd773bad7ac3bf6d182ac912b005e90ab81d4f2a906da8309a69576a8afaa160fad2540ec04991300000000000000000000000000000000051453a8b81b0b0a1566540b3026e40676ea48e3c5aff89ec4fe3b36c61aea27ebe01fe8a811fd3ff73eae0a67027cfc00000000000000000000000000000000090b399b1e5af056b428a4c270eb204df4999e53807d34ca750f30b292cd38030491c3d1b0e08600f40a16f707b4903242a002a460b51429e25f85ec4abaa580ac1a14315b1627bd52349b7b81a641d600000000000000000000000000000000142bcc3458437416506631c4dda54572b5d66093ff23f152957350a3aaa462000ab000cb8e9c9b23a17149b5d012adb0000000000000000000000000000000000734c0fe1df24449ef498fbb60558010093cbc8a14ae068aba2f70bd7718e30450411a81499a895e3d84079a9dbb19557a650dd3765032ac139d1b54ec7a5457c9e3caefa6af45d198433e5949d149ad0000000000000000000000000000000010a7a3380a6d8b2bbf212da72eefb57d2fc2305ce222e8d908bb572600bef7ff55b1df6a9af717e1345967cc18e779ac000000000000000000000000000000000c5a3aa84b489c879eddd3c20df6d510edb5e9ac5c1a2e42b770571ceec315d560235b27468299e2e60af3ac1283be12bbedc44d54349cff199befba9531dd4120a51e2b830a3e356e68cff31bbe365b000000000000000000000000000000000035471ee35c187e24cf0d113c0ca1ab6322528153d0687b15953c39290ec295c0dd4197b72448f2a692537064ede8fb0000000000000000000000000000000002717020e3369b288314a42fd8ab6c6ddf7007480ebc4fa094ff7c4c4b750f477917caf071d2f1897a826fe870c2b7dabef3956ac71bfe97029b8e3f85923c2fdf9cf1ea6582b68d5a4eabc6b044c80d000000000000000000000000000000000b501cef8ea57ae253de63d81998768e115d58b353ac1ed6e90d24f8c39a31bac1a5be1b535a1dfe05e72d80d1db8b0a000000000000000000000000000000000a3b62c001c4b725f7cc861fa042c31fde4e77b3b0610df63dcbb7e89d3fd746919c2bd8ee4d623838a05d42b6932383392f5b4291fbb18a93248e830b08fadbaad6434040c02b45cade73b77f22c2bc0000000000000000000000000000000011cda0c937d8fb2b21174ff3a5b88aa5e1c9a8ce6eaf26cac9fb3ee7f3ad20e74ebbe2d1bd9f4faa3acc43b6e6d0d70b00000000000000000000000000000000195257a442c8e39ee6b72cedaefab0034f48bb988a3355ad07b3e3e314800b2ce30267dad6ef3fd9dccd7d2318dbce0a20a96f963375d7a294b584f2da699a6a00eb5781f46830987346cf4fe922a2f6000000000000000000000000000000001630ea3c7f910ee8574f29d652e86fe3125c306218a894df0b4688ba582ea7d597d7e62cc2e7c78dc2db289f587f10ce000000000000000000000000000000000d2ecfe74480518ad4f5ded701afa68040246a08df1b8dcfe6fdffe77e33c6bbd37192c6c41c6ab5af506ba58d8b3fe4115cb4646c8996239f4fdda8c27a335361f0a19550d6eb0225c008408c4725880000000000000000000000000000000017a910c111d7a0f7e7a3d48b1cd358e2a1213edc077034b06d1e96beedef80473ec17d1c10bc2d33d4fd2a8c052d926900000000000000000000000000000000040167897293a68c980bc34b3f79802b95186200b40b4763fee9cdce8afc681ee916042d619cd51361e6e02688b4915ac8a8d98c93c392aefb64ce0c7ea455ba14c48bfbad0e3dc38d43abbc3276caab000000000000000000000000000000000dbca3203ee6c7fe8d6504ad2041aad2681b889996bbe28ff1282cd20da563dcd5c9fea5fd03072134019f579e4ef7af0000000000000000000000000000000001317a861403866494eef2bf59519f2d324586e93a0037d07312dd8df4ab844525afdf4b70f9e21a6e0230bcde35db4d8221622734dc6ccf6c7b84b387a3dfecafe187dab70ba373b4416ce3c505bef200000000000000000000000000000000069ea1da08dce1c1239d49411861d3e8ee7e6082d9bf8ff0aad1cbebdea6dbf82fb0d6332ae436327440b71ce6535ed500000000000000000000000000000000079904ab7b16de5812ea3eae39d790aad32db02c9cbf7b8a3a8d4222d3baf710ba1cc5bcdcf4fc9e2c4567992fa911edd3d1f427a25f5df025fa71244cb92dda9391d65b04756c41de0f67ea072c375d00000000000000000000000000000000173ca2615b65e574bd77c8cf55bb116462a7ab9ad4a3879f0eefe03f1a6c0d30feed076e0fb21fc60ee9f270af180cda00000000000000000000000000000000179351092d68e7e0d428811cd4503a57bab9a4072f1bd27b5e8445ec0058eb46af58c4752601b53714b816a4bd386048b55c943fd9b11f2fb8a89f6c08a6eabe9434062354d845f1ac740e6043443f8b0000000000000000000000000000000016c9d1fc1790a15985028a38e57c87cf010c87bdeb2a288a055b4b08497abd1d616fa8b28d6da8cc23047e9f8bbe6bec00000000000000000000000000000000089601933b759bb565d849c3837570feb39d442461d764a22f993a695fe1c55283b8c7db02694aa66032512d44dc88867b0c1d54e51b8572256aeb72bb032a5011a3e8ec5ad7e8b6e0397b9f6fc64c9f",
+ "Expected": "0000000000000000000000000000000018bda18912ce64106fd3d54ec2024a1d3e4a807d7bb8aaff7b515d75c9934d4729c14a4a72ca7654ca811a69f09d170b0000000000000000000000000000000011478fbc5c03470d9cfbf3decf9416e1dbea8a696636b94244c5c637e43f81eaed0210b1cbcdd291094e8581dba3548e",
+ "Name": "matter_g1_multiexp_41",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000446af4281a01e0a20b7428d06b63b89573912955971be4a5cddca514708419640f8a7f95b50ef8714a04e1fd81bec64000000000000000000000000000000000087b94d8493239047a5cef74dc20d7708d7e3365018df80624cc5511483c3a5d9b14ac3d4aa391da60980397e4fb1e96f082a5ffb8baa38ffd684a4a70114343a1e723bfcbfeb57d0a85ad5e592d74100000000000000000000000000000000033e5eb4bae80d55f512a48b44054d0efb8af1f9870fddd99df00f31dd437025381df3f4023ca217ba924a961864223e000000000000000000000000000000000f6d7a7371eddf7283890d59bea3c61fc3bff19eb7fa333ae713fb9a73c4971354474986ef5a9a81ca8c5b38bb67f58d5160286a6d23c30595809dab6ee6523d7d235114d1b295087e024b4f6ffc80e50000000000000000000000000000000013d4e9518d398fc0add8233fe58c198d65966844fe286fe657891245fba8f37665e2bc40e4e70886667c9e2c0a1c245300000000000000000000000000000000089562c10b287d4d66b2b694d29fbac936f700de78525e9be59a83543593b42c5c577910e7ba1b67d840d88e7a3e53fdbbca29b94b6583d46753473143d13a7aadb0b18d6d35d7423b8a004991fa1ce50000000000000000000000000000000005762727639503eb63854e5fd3de33bcdd80227e16de19cd7cfaa10b7863915e490087dbb980b6dae5114df7d56716d300000000000000000000000000000000104306b38970a94b5c8839ff282883b7c88c7ef45a7ed49a02b322a16521faf2b881e2dfe22da3f4472e2bea9fc40d7e607c80069dab2a16e39370de32df20534aca46565cf573159a93c64f1f0c4a1a00000000000000000000000000000000056e61b51113719c1829d4ae4361f79c543961de801b1a62ebbc3cff04b0722be241236d4e1b2dcf7c309ab9735334a700000000000000000000000000000000031ddb45e491ba2d719b1f72f54640c63e281dbf6ff84eba2eaa2b781d87e243e7bf84d7151f27556156970dc8a2407f41c1f256e866d218b3ec20c132446945177d518573ae3f0e739ebcc8821bfbc700000000000000000000000000000000029eff96206ff45ea9bd0be2b83cdb660d6bb2d236971517b962faa54535f01097327a00154bf35dbe47841eb36417020000000000000000000000000000000013734f1218c3c34d2780920806c5ad211128352d8a41c2a1035594f470ae347e372914827775094164a5db9d0b2a1ef7c72a47e2267010c532d676ee3c3ebfb2be2b7569f6f7a22f76733d7773ed383c000000000000000000000000000000000f3aa9f069b07cc935a974ad4eeb47e8b0083397928e8102651ee54f53005625c359d82fc8b5dbe1c76f650cdccc2ee2000000000000000000000000000000000e2bf6a8c4234d118676a29f12daf244ad9aa562faa970d2d63feb074946ca70da039e2de104f1524b1a8f3897f053f4c52f48e84a68d99124e678dabaf376c956dbe9603974283a9efc7c27e830e959000000000000000000000000000000000795a2b6b27209b48c00cc8d37864f14c6be66d6a41038122a28186d7bbcc4b02f531aaabd000fc93c685ceeb67bc3c500000000000000000000000000000000143926b42a6654e439fd01883f1ceb524cd8b5b1f2e3eed3e905f6e948736790cc1325d1b04e30247e4971b75939a766e4fe662495bffd8ace4c1ddb39e612b361bf90a0f1bdf6c7fde2bcf63df1bbd200000000000000000000000000000000074096150c9e04c082a1aea20c785b3a7396568e43707c42c512575a97db8127c8c1e0548d640dff8821d7d235f268340000000000000000000000000000000012dde2f1d15c04292bb5da4c467cd674ddb43e401799257524cf3097d0dda1f3c9f2f0637cfee914a4c66d737f9e3278651e67e96f64b80f4978fdc1cac90be538774e34c2f619f8b8e60cd2aa20f269000000000000000000000000000000000109196dc59d6ec06fc4c774f665612c11bc3e826ca4ba528a15c6290f733f3aa1fc441bd896021471e1e85943fc9ec2000000000000000000000000000000000aa0d17d44bf354e48275ee3e4f06291e242402469be6f4cd4a62ad3871d878c1d27a8d06974c5c1138281802368edb01a6ecd3db89a7f07344b5728efffd35a11f7380c740669f746fdf565905a1ca000000000000000000000000000000000067458ca402c19488e2515037abf9323ab8288e0e11f7cdee18b3da50cfa377435cfde1f63dcdc451ce65a05641cae370000000000000000000000000000000010ed9c895629bdafae66ea176388be4e4ce45cb13ecbe0869ce57f0f48852b6b8c47bcc4a14fc5327f1df372ad9f5d4a7db5ef4c1c174c2e5ffe5555f54f4e845c463bb5105381fb39eddc01103b1bf7000000000000000000000000000000000f393c5fc8e5f1cbc7b59742e5b6236c9d1d262d0b736c1bc188ebf58f954bf2835cc70617062a01459c139f328c912d0000000000000000000000000000000015501635aa7565045ef59067e0ae91a5ec4871485ba411425987d540bcd7b5782aa7164dd631e4c7896b3949cb115f9a14018f14c50d40d3324952ec22ed247c13c4cf10eacd32c3671757bd12b041e600000000000000000000000000000000174b0620cb49d8b1a5798c3746046c2888c8e96664dc7bda5b4e90336517448eef534469a40086703d9a835d2a94930500000000000000000000000000000000033db9968fd6322e7bbb9de572e8c92b5e3717a9496803e3f6ef8dd796dc6487909ff318ad6d4d91297ae6f2daf07bcbed4a28dc3acaf2220ba56d026b292a7d017bcbe358dedc57556cf638517bbb14000000000000000000000000000000000449ee22d2c23ec02fdf1751bb59feafef9291d6d56f7120612948875afdea56453e081c5c5086205ea83f0b8cd541ca0000000000000000000000000000000006114d6d8ef1e4c6d79b23a2b91e5577323107d90523001cf7d6d18a0ecf3b414d4fe1a3eb831a6d907fce9d22030bcc30fb17a38b7d0888eb02394eed26406bce9e92779251bdbcb432153a550c0850000000000000000000000000000000000c2082409ec14f6121de6ebdc06656a28dfc5e439a0278593dc6aa845e8091d8caaef45ea1ad05aa12e3c1533275a663000000000000000000000000000000000a2ad9980247640d44d3b37c7b7b2c1b57592ac12cfe9aabca4f88ba90c8b3221a2b9f5e4ce19ffcdbbaf99ffc584219980b5873a5d0f78c3b8582581349498fa997fe3c6b1abe0edaed594253359d8700000000000000000000000000000000108ea3fbf78237f0e90d4addb69f25eadb0f21c89d92774b4fdcbc97632f1622ab4ab408fee95e735281ea5da5c2c8130000000000000000000000000000000012338527c7932a737daab3f8de98b9f2aab59aa1b12e84d3674a8ddbc1f86a8a9e7eb0ba854e9564407aedd489b6016c619f5719c320320a3c45dcd6207575e0d8527c458c56d3decf1d12ead8a985a1",
+ "Expected": "000000000000000000000000000000000aaf02063d6b5b395b75faae4039cf2eebb69053f1f161242b47854cf07786788930f3be2598520c178301ae0bd13ab80000000000000000000000000000000019574e1de9161a11e804d8077973c5ca70ff7925c847d870cd2bc985a8724d41331fec6c1cb341f7509a37371db9e4be",
+ "Name": "matter_g1_multiexp_42",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000048708595ff4f08cfa2b1c101ec7b3538a2e6044157bf39a63255b5540211105f680464be5b03256f9153a90a4e62d44000000000000000000000000000000000f2fad0353cd8fbcf0ba75a403209094d88d8c8d068eb0c7077b8263fd9f7bff8d6234d75ac4da232667b5c566604706119d33d32affaadbf6c2b6243bb7b344a971270b488cf887334fcb15de2818cc000000000000000000000000000000000866fb774b231d82a4508ff9b017ab836936299954b2b404affea65f315b62da34c76019192f5c9a447dba8cc1b9075d0000000000000000000000000000000004e050fb7a17bc738a55f1ceba48920c62648a27cf438b770a66166522fb0929069fa6f2b2b742ed689f554e9023ec14f1d832b355d7e0ac3653431528ad0a8f6819daaa19292a00c910ff0ff39f46d5000000000000000000000000000000001710b342a52b0781d1ea18a9f07d54fb18e9c90e44815cc7509aca3a5c9ca3cca6bc32ff6ff726cfa353faca4f097e9f0000000000000000000000000000000017fd38b122a7ac39533af597b462224b86370f6e6814ca1ea71d961b9c7cf94b952fd75502031cde0851773b2c6b0108e6dcfa50f6129544835b5a4568954264ea68d9e2e5d4370ee31026997a3fbfe90000000000000000000000000000000001fd243a3c69dd5e7ef19cfbd9b7cecd475e88d7be85dd3a8f48eb46d5dca39d05aa4b43c0c700b6632ebc0b4cb3baeb0000000000000000000000000000000008ebf24e9d2de0fd82c69e0ddd1625da0367c2e9f975118dd2ba5606d77de377be10515d9eb921be5136ed25fa6b27abf7822767391d3b2331e8e1b81c659c6e0262f7355063decedabac9797a84f0f400000000000000000000000000000000021f919adb62791296db3a0b81f03b87c01d94ca312f55cd94364eaa654bc47684d7b0336a3afe813ef1aefc7dd0ced2000000000000000000000000000000000b40dd6bc2fbfa2ed277d88f77aded330c54c1c46a781ccd039b270ee9b799a70855ddb1201dae29a1b124dde1e6acaab1ba1cd6a4a6c433624dec63547119c0d492e3f38afb04e5153d82e400631aef00000000000000000000000000000000054f284874c53bc914040e6751ddd444604d34a38314d8057fa0f77978150fce0add250a6bd8693ede79c9f6b2e025de00000000000000000000000000000000045f6579793d166198d73ccd03da2e907efdb31b54b0b0fe3e2f1e02edd7d9cc0c08af089330d53aedb60aa7cafb0e0ca41e184bcaa0721caa4114d6393ae2251fed84aef57c7927a170145308bb136700000000000000000000000000000000189aa0df86ba479009d4bfb8608c31d3d49f52f1bf758e5c05ee9e5a673bfa15e1c6c37a978c4c431ea035cb7948297500000000000000000000000000000000120c90261fe77d6f41a42a170b28df1c9e6e0cc4bae247303f399d3be7c6ce8319a43e7d551fe554783ec5ccaeba3bb363cb451d8eb3565274793925a1869ca5a25fb19639449c71a761809f785568de0000000000000000000000000000000005e990869491ce375477b586b63641ec71adf226c631a14ebfae3514718ce546987c17c9ef41f9005c10eb04909a74ee00000000000000000000000000000000141b8edf812a2918dc9a2242301a7e7f6433a83298be9312cb48f0d3f0c819a4368ca961a0b6f09f9e077cca6111657e6a2f94d55f784ebfc6b6260327372217d6a5b9637ea5f9afc1a65f99c221c29f0000000000000000000000000000000010f3f93de5573e42ced8278a7a12b58086c04f8b862e11f256f26731560e606ab81d61a1090857eada5f8eb3afc363c400000000000000000000000000000000111915ab2711479677489dad7695cb02626a0525ae9ca51b5271d5fb6ff438d99730369654240b05b5d47fe00847c6327d889a3362f551b88e63463b7f0cc334fab3fdd302b630e419e362ec1eaaeec0000000000000000000000000000000000ca6c2f2191cf86c596b439de0e0df79b441de41c7661d4b80723f14337a379bed9b97958d225700f06f8be5401399e10000000000000000000000000000000015904391fc3cb879147c2b5192641c4ddde11ca8129c3a03b82f5f824b2ae60b3a33c925112d2de94ba3eee10761da528bdd400ad873cd6ec546bff698171942d536b94e69dfef4bbf316a471d4b45cd000000000000000000000000000000000fefa6dadbcd8edf2861c6ff4f5eb501a76507b1fdc1b8cc992226a7e5ee17ea343cff89426c409bc36c2aa3a8f5793600000000000000000000000000000000166706cd1ae090a41ea211d1333d360a1e34dde717979295a0d6a870932f31158e43ca041d1978815aadbf761275953163b496a64cfd15410192aee9912f869deea5a08eebd6b160667e12fdf23c44510000000000000000000000000000000008f02061fbfe82eacd770520b46ab49bc29bf358468adcf904854e39b30ec4e363e80f18eeec8064947bd8612c37493a00000000000000000000000000000000138888a1fd168e9c94959cf026605691b4100a828c3a75ce95f3dbeba2a21d8a44dfaaad834dbafe28c12154f41f652e70de38cb4627f53509eadb0918e562c6fa68a4cbdfa9f7578a8aaa8182f531500000000000000000000000000000000002a07974c00de6936c31202e2b0c76c30ad15b6c42393d5c5d2b1e0d5eaba8b5680d3837a8029283f572d43d2944e4b10000000000000000000000000000000013fa3f905a5618b7aa3ee5ed37055f0472fa361fbe07733f9c500657338c62bd4cc3b0b89e8223894f365a58100ee35416732c583e8049a5de38642cebab774d90d5f87601e3599ffc9af692ba532e620000000000000000000000000000000000775861019fd75c201b3a23141c8e962948ce38fb0f15cf9d08d56ce0dc574300e0a6ed90a7c50b8c71a1a9c466d16200000000000000000000000000000000066ea30b3a1bd410e3c70b1173b91d3eb9fd0be55b2d583c4be627c3aa9cab1b2a5fe13ccb37d781965b1b121079916c4a037e7562adfbad6b1ac48b8e4b6f277a788ea2f4416ed2900ed2791f09bc24000000000000000000000000000000000ec3ae37e6e5b0c623534f5c02d998bad139394daa28aced4b9f781a5ca671a02f1638cddd3bfb5124f9c5c830cdd9e20000000000000000000000000000000002688ab0be331d6f8246a54749c54fc111d2f7414ddcb1f3b42724e5bf14cb8ff3546a3b9be6115d91f62af8c3eed35efa878f6a2e18b88d6badc5b42775e92c17974f3a18817b7769d44ceecac46b890000000000000000000000000000000005d5e2230d538b05b690e878c03d793fc70c391e853b0ae3609f81a7f24aa6d5a67f3138308328783888645d1d84a15c000000000000000000000000000000000d625eed47e245ee74aeb91fbd72981c4f2afd53deff7ab478f32e2a8635431d9ab9848f7912dfa4bdf8ee7201ff418bc4f1a7d2b66e6202c957a649384cb277dbba769afd60708b457613f0f3372515",
+ "Expected": "0000000000000000000000000000000007cff832bedad3caa9c91ac59292828e79811f91c51c4799e2752ac0c12e2c47a2a07ad0521097af7e4a939f3fd230b70000000000000000000000000000000015037ed0ec4981737fa94f276aa9a4325a2267b90f34844f14a92d677060a23e23e3ff0b3df77e7e67e85c23b28cd44e",
+ "Name": "matter_g1_multiexp_43",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006984b92b5b868004f39ebf04f41084d03704732363e65c823e5ad4a0a3fb4c983ff9375249bdcc2f46650921031bc1d0000000000000000000000000000000019b9d69589cd29a9909af5a303586aed5e33650331b9866a6d959b8580ca8312ad0e96c7214ad50db7502f50ecdcdafb0241da9d8505208b4d3ba2521a42f28df7d06fc212e9e84931cbd30ae3ba2e1500000000000000000000000000000000173433f7025400852ffdfec020a44b545b365158ba8f919f434fcd995c0d84509c77d8a05405c79953b8cb667047690e0000000000000000000000000000000017d73ee336ea56efa64038b31d5abb6650c4c6f7efe67add40d09faf93fdd9fae44732bb69dbfb0dc8267c4d01d8aaae6fecab1334668102e47f1e7139059c1d715a1851a026a1580f93c2daa3f08a2700000000000000000000000000000000184ef5b6e309fee5030e2cd8c6c3ec49b1cfb09cc9cfb349ed47e17409d9c478e8e54f285a3b3a4025464162b172d33f0000000000000000000000000000000009b78ea5d2fd2113a4bbcbbe6d0108bcf27b60ff435b5b587e91155eb0ac6ea35c27f276b7e11fe5fb59508454fd8bd24e2023c64a3b51cc3d82e262f83260ed4a5e9e3238b85077852fd501b52aceed000000000000000000000000000000000d0b8aca446806ab51b4a49049cede15587aae742ce7d80c2a05d255429c945d1337b4fa7ecb8f2c3b7c0b0299a41ad8000000000000000000000000000000000bce866df7061aa4319336ba1f876254a8e0faf3faf2f9ffdafd0ebd7d7d0c854c61b476583207818f484ccf7faf90fddc0a88f0aeb2b082dea6b50d591018330c2276830ed554840c10772403561ed70000000000000000000000000000000007018908a64fe5795ad178b8bb1c8540ccc5c78ddccf4e6cbae72bfb84e794d23172998d29e568b186cacfd025962a010000000000000000000000000000000004751f7d225407a8d68b4a196e32cb4c0bc6a9ed9f2093e4242b268d6c5df978b8595d8940f59be860b66310bf8a5460f68c9e76d9d8914f14007c968a31089041e67312c6a3e5d30e65efa55894ba74000000000000000000000000000000000f61d66b0539c7ce56da9308d0ccfa9245158541b2d1b14c381ba53471ae9944ef3ec9f4eaf52c95d5d0bda92d6b9a47000000000000000000000000000000000612e57aaddc6eedd9b8a08b991bebe6f5cdf7805c2cd4de5853856f11eaee94c4c2e0799254f98348cef63236cbae3980eb90c6cc25b3a48d93b94b698eff513da37210ba79d22d76a270aa97fd5107000000000000000000000000000000000b8a8cf0fa6ea9f3154eb35994cfe2f7af4252adb8f26d718163f2bbee3cf1bfca400f4d3582fd5fd407083e0bb48ccc000000000000000000000000000000000c3251d0d9e8520b3e7b43acdef58c75348786654103fc770c7ffef8593b169bba3eaa2686791f919fc70f40a171bda8067bfd893b12c79e13659ee9b5f22de71d806a85410c9a23dc43363915a606b10000000000000000000000000000000008138d173e3e8f5e63f6aef89cf2437690dd0c848435f6032f943ef6cbca87bd2a622f9aca825b7caefb497450dee4c200000000000000000000000000000000183379ed3c9a6a6904e169c68d627bb828a05a93e38ea3b7886db2fe6d1015319d3887136180ab7dbddaa26b1fb3335f34abb11f7ed6d73fb81ce2777acd6bbe8839112c527ef4ad88b094cabdb4742a00000000000000000000000000000000083f8fe152f7edcde2c81107eacee9c58ce22b5aeb10eac15e7df1657a813c98b182433655380c9e8ac18efff2188b5900000000000000000000000000000000100b06f6129bd9063d2841f4c244adf2dfead83e23f3b1586126623ec35674ecd6422efa0e86ed0502a83549551afebd8d6693acb1eb73f6ed1bb4f74f1062f720a7f2c0ecf2b5a944ff89feb2688e1900000000000000000000000000000000072c644635936a91dcaee40e3b4794e634c315a39a9cb5cb99ef6784b332fdcfaafdc80e228cd19d0104d5796f584c350000000000000000000000000000000002318bea9077484e9c1937dfa63774b5ecf6fc63ff06e5cb653553d5111a981c09c907069ffe11b5704ea60a9987328329ca1b157e6a2b5b88d7467e851282491ed30382ba217b82ea5cc9ca0c698693000000000000000000000000000000000aa7249112c7897c9b1f95a7d8299790a25d155dc9ef7b1ad6dd7b186bcddfacd4c77ee95e634b5f283c8caebc00b9c30000000000000000000000000000000012e31211b2bc88c568e08157da9c3e3220dcd563cebe44653ff4d62f8c306ee9136832704272317342f634e66e8e66a240bb53575662fa0b726469da01c39df389efde3936d2eee18d7035704130ad6d0000000000000000000000000000000003a5576b3663114b410276a8c537a93f790276754913df727ec6c0a684ab3c705ec04b8bac882bb9c5223702860885520000000000000000000000000000000002221eb21003c6512428cccf8a9c775df9b72ed8810dada5c92463e6cfa3d619f22a22e314b9b8882c9e2f609b73353a1574a30a575138c44881c1c126be214c6b68335d7338875b8a398196f27510d700000000000000000000000000000000111829f79d4ec1a80533f76f32503cae2842981e29ddf9a376d16ecd7037d3e0dd1f8cc84d512fbb39d58564c019a559000000000000000000000000000000001808e65ee7f31a1fc15d187eebd76c63a3158469099bd6acddb0cc96354072f636651137d060efd850fb599a6965044e6dd51553c4119255b31cb0aaad7391694f7dd29420420b513699747bee819a99000000000000000000000000000000001274417dae37cd33b2a3e086f327df292b6f997e5c93e71add346d6e5f6ded135c8d6047978c10c5c38752006b7f76910000000000000000000000000000000014f867c58d3be7b09891f087f47c1bcdf82c16f899ba960d8a0db4a5eb66efde12dbee75e77816cf9afd4877d9d08f32d88f049ab3ee2b01af449abce08ca14ea3b065f06a8665ae3510b4c04f423082000000000000000000000000000000000d98fa6b2371f65f6f0b62133d1a294a7faa9949c7df16818657a9757fbd8381222cbea98a72a951e4b2b69b216f705b0000000000000000000000000000000016331e8f0661228b1e5f4df59a09de5133d16e06e1628afaf8b2a1160961ed9738400078bd79cb5bada5f99748ba220b19d6e227185c538b122858ad5ae594720fa7f743f5805552152a213ebea64aeb0000000000000000000000000000000018f129d1799d9b46dcea6d239679eb64f144adbe1a9561044355cf66b4b1158513406ef4423468b5ae446c4128dc03d8000000000000000000000000000000001669ead3f97913fe5448bda1bb0be354fff223e51bda5eba9743526e964247211e9cccf75e6f99c6abb5b8912af94f5d3f53123f01c4d0d4c18dd72ea87ebb5fcb559df255773fa0165f1432c229deb6",
+ "Expected": "0000000000000000000000000000000013426d2d18267fa615975295d2029d2e5730fc845556d501c8c6ff8442cf0f3c7facfc329f6703043bb2d45acc1639130000000000000000000000000000000012fea8316f8eb7cd655aaf9cff8e395592360eb6d62bd42f6e1d1e27b9b54bfb7be5b56791d5ba55a798f073f9b5634d",
+ "Name": "matter_g1_multiexp_44",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018eef275d602fb152cee956b04313bdbc8f0079da7bd8d6841fbff1f63a9626f17ea3f7a8332023fd9793ed2eff3990f000000000000000000000000000000000c41214c40c5c65e79f561b59d7ae103cf8c60f78c2b0a16d96a2e714eb30eeb0cf748044bdca077c4be5f4ed155ec50cdf2bbbad52a3f5c0b3959d46a8c42f6f5250a93c3dcc636712a4a2baed289c90000000000000000000000000000000001e5db25f5964e3a5030005152fbe9c00252e37dba6febdb7441046f734d4b86d60334d91960b09bd32d258b7ca2662b000000000000000000000000000000000949bfe49b0256a01da76f5c2270cd0b6ae70fdbeb55f932895d0e72d94eb6db236a8ea40d419ec6d9354c611b8010a918adf5d8fbdf81f8e4bf2f622e2d481fb2dea06a1aaa289ce4f6e783eb9a98dd00000000000000000000000000000000158addae39a79638dbd1a7cc280e0a24d18a4914ce4e290f8f79c147c4e817d95a01bf6b074ef8e819a124cf4e3bf088000000000000000000000000000000000bd2f13538d08742b3bc7b1cca9cb9e059b4bcff76b49a189f506b4bde56d8a58fe0bec2f8425ba5d574dcbc5efe0e93650e995b73b63d068fd54f596cd9669fc3061f0c1da77ae7d0f5bec012f9ba69000000000000000000000000000000000f8615d47e4327d862fa64ff4b9be14df2cad729b816ac7bdcddcb32500b6523af3303fe36c0e93b638992c671958d5c0000000000000000000000000000000011aa78c5d0073fb9b34235555bb2e3f27e55a1d576ad4e3f63974cfcb2646c6ebfd6e595d46613987c0c8e86846845dc3350d4f13e25052b1162dad3ace76e5cda71680fdc89460d8fa88c0d157df426000000000000000000000000000000000fe66db078653da2fcd1490a36db9371039f3630bfa4d574cb700b19697c7194e8e44453e16ae71db6c9001e18392a76000000000000000000000000000000000cc69605c26212c6a088b9a5c2cf6024e46f035e4c64da67383f294d6186bedc18922ac891f742165e3f09fb1720d476283f0256766690c88df6cf7c968b9a96121d26d19672ce9adc84b699476a32db000000000000000000000000000000000a280b29948ccda96a2a05ceb9fca703dd63c65ebe18a0002cf1c63b8f64282cf9d3d4d73ba3a13426f253d09f83ebbe00000000000000000000000000000000146f604d1e90c4a14aa6599ff5c6389e426232a2dff39334f3390006f021f83500300b7b0f1585ad591acb1e0baadcd7145cdeae7fd3f7455dfd2ea9a064c135f0a0a36990ea34929e292e4cdfa0f4720000000000000000000000000000000000be58255d1f227af95dc9a818204d687064d62166c16f1de052aca69a37ae98c2a73a9a9cc6cf187128e5b86969e2810000000000000000000000000000000003f1155d7e91220bf0b80943a16a9f41e4def1d5f8ce44d95dc2f9099019a1d5e770158338ec248eeda7c5af412890cdd9cdaa979ab08b454dcb961e3cc4bb18f706bed93a72a9c1e105cd69c0b691af00000000000000000000000000000000077c3ebd0169da81bf07ab1bfb8770732e4182a30504cbdc8fb1abc49f31d698c17f68de1a6d8bada62e98e09bcb22130000000000000000000000000000000000d677a33c1590cb55c9c78afa455fe2b349c465e90537a73906343aef577afbfacc8e157ea6f834ff959f3dea5941bcf262f9f7a26353193939bfbbdc50ee35614a3c099776f08b21e0c4c97521eb8e000000000000000000000000000000000aa0a3898520c5bc19d7f3a8e0710585dd08419b39d9bdcfe12f7baa6b4cecb50bc0d6e877ccc2518e4d0254934669ec000000000000000000000000000000001376af22bb714adbd16d8d41ab503066fbe78f799aa8c1d8958eda9e4c8c6fbe119e592f655e0c3f93455e8acd8a2bc14f0d2915e82c9a69f9e9af64a2c5cacf61ead492bf69912a35ad6a316f9914a80000000000000000000000000000000011b1300312d0ad0352ea153746f051816693008f2d0b980974bc354996ebb664e910350e28770192f59c053f3f2bf00500000000000000000000000000000000125d87c441a1dd88f489514b1d550387aaba857d5a6bef20acfdc0afdbba3e98c2e0aee0528cb78970395a9da853ffba25ed3f13198b69604c08b414562f67a67aa8dd4a7bd3c066874182d21ed9004d0000000000000000000000000000000006a05ac512adc0dccb74c7b4c2187763a6ba8db9e290cb0efd1325b7a463e0e14a3e7463b5cedd732527dbd131246c6a0000000000000000000000000000000001c1b41b6d5c823c05a5d6db55d7068409f5fec25986db6e2689dc6ec3e0d85749db6deb737445c5feacd69925c5dfc44ae188cc115e9d492be64abefa4bd4c93b61dd42a7d213e1100b8108611a616300000000000000000000000000000000143d22823412da99f7b87a794662bded7b7ebad9742e4d6fffd471b1bdc748c6f1b5bb395cd0a79c7291b9e8081825ba000000000000000000000000000000000f2b98d54e293befed0a97667791ae35494084229b2a25494fbd7295a04f03173a52efb8ff9033c4615ad1185d4e9032eede725a693277356ce71ffd7814a77fcc30eeb3a2b8863fb91ca03da1cbe37a00000000000000000000000000000000172919c33fd97de83b30740356c2bb2a9c97c3616d9f80a8d8266e07a1de21ad974ea796d3cf56660fc4e0df263a27c80000000000000000000000000000000019afdfd10bb736e8a6596db59f4f9a8244e585fa81ae315a768c8d91716de32d42fb75a57da238dc597885f083049a769d0618f898594b23ee3754fe390d6bdfa7d47fe749d6819e306935c1eab6b046000000000000000000000000000000000a944d2667a10dc5892760cd3e13289785f0a5a461068d70960e6546a0543474f92d68ecfa96efd19619d976af2ee491000000000000000000000000000000000a88a16dba3fa6cb5ef21015b18a14956ec9ec29650929fbd0308fa59ac4aa389aa2e306a3a68fc04e062367a72b3f861e1c9420cfa91026286d7f986b538c13e8c97893995485308c69f053927f96220000000000000000000000000000000014118a990f2649838954ab911e795c453ecd0d700077a5fffd1a4f303087074d595caf1b20399578ff1e23a2cada7e5200000000000000000000000000000000145bf8164b82ca5f8f93d89ca65a894c6d15e38da2cda296a94aa1a1efddc4d2663b8f09efc3b2d78510c4dceef8558fe5095ed9a9181aee392888e3194ebf9c4a6d87b503f4668bb6cc0d290880a44f0000000000000000000000000000000012db33b91d99f44cdc785470e67a781b4a72ae2dcfe4555efe5b7527b9a76de8e492c4dc7793ad948cb46070eb1cc5be000000000000000000000000000000000ecf06e454ea574dbb9ba6209577425a58267d01f29f8706d06018a9caac994d2dbc9c6ca9fe3ec01aed9aa2ab886c60dcece8ee33d3bf3188574e94a889794077035ee92473b7266d92a3c018771b4c",
+ "Expected": "00000000000000000000000000000000003747597e0f9bc39306319018fd08bc936c4d37cc6f84ef296df5a36cebf0aa46ed35ed215ba89a247174fd72fc7c1c00000000000000000000000000000000150f973b61f26aca79a3f7d1705999308a96136b08673322b4729f16b471e38f27e66996e2921cfad0cf889878c2ce27",
+ "Name": "matter_g1_multiexp_45",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000046e955a4631d1a490f92cd40ee0a31c096210ead2b307a7aac60e84efc04898da5d4d9767f1303ad5652a0e377f0738000000000000000000000000000000000afd054be493fb26c7826c9c1f62365ebb28ed853bd3a45d266f4c690a24e179b2eea5261adb0bc50dd184c165231d2eaddc845ad867f1e2664ef0e78bced8ff6904c5836e7c63ea3a9c858fd7b710b6000000000000000000000000000000000ec3c20a24a5f9fa7c5754007407d1aaddaeccf3f7956914ed3b06dbcff7f15c6d487a3b71fa9aeb61352698a93ed14f00000000000000000000000000000000086f3cdb1e21cf60a7a57e7ea7e00b4698a837916eb1f6ac1c6cf97ef2abd48292ecfa471ba7d9b8688b6f0dcfb6af62c78cfc6a30cea34d3d3505f4f897631f67ba77913734f6c2895d871fd6d5581c000000000000000000000000000000000769b870411b65a1a86dfdbbd7dbb65feb708f9f90ee73153e42f7141cc660c50f41835ee44f58c7ffa136b944e84dcf0000000000000000000000000000000005f0480b4a35dacd304d8feca77f8580f66396a6434af09b98d57fd4f9f781012f3900407a49f4e0aca8d3ebddd2a7bea1e40df9e1f7c84633cb3dc2223296887de7281ea66c5e1f2d5816334f7b280a000000000000000000000000000000000208f1b01599c969333ddf9accadb24f1c8239f82f5beca72d0d6d823b59a3b8c450e25a2da32b5a8cf8c0f47137e04000000000000000000000000000000000054051408658f025572a45c731e81f3fb88d741a632f1e2acadc48a1f257a69481c9c11e655c226d8e0623d34fc9fc158810b9ce0020904dc1903338089c30e616ed0be03741572ce46946883874f4ea0000000000000000000000000000000001738659b582e3667cee963fbea8cf695daa6b811dd808e724ae77db2060f248accf645db52f9838802c5322d993488e000000000000000000000000000000000a36fe571929153dd774fdcbaff2b924cd3f0ab4aced47d22a2662ac6f415b89372406c4ea5a0a466d4a4c5cfb02ad7d93e7702da2ff9f3f14586a9ae80c8713743d61b915a7c379c1faa1b151406a9a000000000000000000000000000000000c70dbc5f707fb949a2e0cd57e0ba6a5d28a2d85affcb55bdc9fd24a3fe395bd78b7431175a629475c0932b769b55d6e000000000000000000000000000000000a49fcd19bde4473bb98384bd63e96508b539fb80e1e0cd9fc9aedaacba0c36d705ad16a47f345c083401c6640675823eca54e365faa35d2c9be259b53a1157b180a373813382f47c9154af18a2d83270000000000000000000000000000000011236c10b9622f4e3d468d91ba9c6c072be74aea66f5bd77411193bf2358a03fd47d029dc7b50343ef72fe9bc08c7ea3000000000000000000000000000000000b923cf7f612e800c2c52b51203e12a72d6f106c0d047d1317711954cb33d44678f509da27f03dcfa1d4482a9cc2eceeabe2079ecb3618de3accdf291d9479bec32bca1f9fe87b00b64a12d735f5b9a5000000000000000000000000000000000883a868a58809bbe3ec9df32f8b963030d71a3ae97250ee9aa8446a8b1a4428324f22fddbe77b338ca58de26b1ad73f000000000000000000000000000000000a49fcca1f052e82fef8913b64268a33ef1d2ee213ce96e60a3a1842aa304c63cce711bba8f523302d9252e3def20e3fc541a44756ebda14aea95f1a1d05e7366dc0285305116b907fc89e777ce45f79000000000000000000000000000000000d1ed017ef4702bcd3bfbbcff36000af6a1d26ab363e68ea5629027e0b90352bf1d8e03c13a7955da6c15507cc1c9f47000000000000000000000000000000000e09830e54fe9eddd416479a1740f6f1b7693f2d153d322f27779b16bb6451d7657df85a55da75a4aee0a2e33b3a46e637d521d31de52681f1d9bbf64a12f9bc8fe0ac61aaef14d7e8d048ff09e6578b0000000000000000000000000000000001f902e2947de38842c207b9029743da51ad0dffb61615b22c73d88739d80c926c07f97507ca3bb830c66661b397dc1f000000000000000000000000000000000d8a1d29f87b3335287142baf613fceebe9d4765d29e46bbc9e459af5450256295538b49081d849f3253f07357451b6e4904a876d4ac1341e88fc4808508c89c19dd74aa8fb1dd7673cbc2d28e7d920e000000000000000000000000000000001846aeb64ead3a9b6da3b6f5de234fdc98442bbdc402af2d016c9dd25de8f9ca09269a3f01a812187ab7427b2bf31603000000000000000000000000000000001775e3fa3bd35f96faaaf9c3ce1d2391f89340f8d533e41a1d637fde7a2cd7ad997e50a6e9437468a1d5940e4004bc9068911b04d8155f90c7c5c0cb519ee6ff14c0ae27ece0374f30fa148235e8cb490000000000000000000000000000000008aff7ad8d3e83ecbf5c3fa2cc9a5328531b1dd6e30b2aa618aa087281202de8f4d356586d64082fb039db4c9ce6c3e40000000000000000000000000000000014196e8ec67e5f0093da2b1233331bf1e90a8fe1db52b2629c0d25e3c181d595c03bbab3b399c87236d2353f1ea6bfe9481e894ecd52a252cc76547513e2cf0a5cc6b20c3dc9c64c7f34f29a488258ef00000000000000000000000000000000018ad28e8d8c1d9dfd8f8cf4e60214446a988285005d92e38d46ba32f619e982cf96ab10b605b1e378d7b46b54282ff300000000000000000000000000000000029807f431a2101ac341241af021ee35c47e0ffa1975c982f75c10ebf3ab9081d294578288a5c308abb074b3e3c756c672780ab3c48c8a102469799ba2f70d2fd9d324cf558a8c8b49e2ecdb71ae1c9b0000000000000000000000000000000008cf05c3d3bbcc63ee761f7cab1494299a3e2274ebaebedcbae5b35ff33bca129d79f73ea77152f19cc67fc66ff774040000000000000000000000000000000009ab576dbf0e8cead9450eea0a506c83f12d09fd2267715a76eb46602756859146e96920174dde3a361636986a3d38e084ae1de8aaf498bd2d91bd828bc64e56482b225322b86529da703f47289c6567000000000000000000000000000000000006f62bad30339a1a912280ba5d982bdf0d3c04ad9051555eabc32eef501e80d996f183a990ebd17301ede13db85f6b000000000000000000000000000000000b0c4bb1a10f8a281b83384ee05be2d65d6dfcec36253b9101cec7f1193f8fe3d29333034de96dc62d18a97153ce1d153256548db55ee9de70ebf6fa347d81bc50494b937ab1c3079977234a34cbfcfd0000000000000000000000000000000010afb2bdbea9f6eb0c75ddb0a4404116498920557a5d416c6d855978e47aa90da70f29519ab244079762fbf965edcd070000000000000000000000000000000000b8b62a1e52eb3805056576810721cfcdb5b0d94759a11862cd7b0a88e3ddadc0efaeccfb89662860e187f8af2039f8575ae146524544307ee51e58a654d7324983a87e1b37d46cea1a4ec34114b44b",
+ "Expected": "000000000000000000000000000000001422eeff2bf06ecd67e0b310e7201773577a899fab8ee7c5b6ef5ce1021c9371e106c49a6b607cb3d58852f0e671000e0000000000000000000000000000000017ff4ceafb7c286f2036e6bf47a15e6695beacc7b988dc35f8521459203f69975d297160dc67fb88c4ed2fd7b61ccc0f",
+ "Name": "matter_g1_multiexp_46",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008fae47827bf8786df7e9f8cb38a8e01354ed4417a05332e45a94f93a5ec61f11d517f5554d5444001ef2991f2e7eed60000000000000000000000000000000005cd17cc813442f45e7c2fc542a6359b16db4de7749677b1575f12ed694514b3569b722ab257f7678a230ca3ccb6e0ed1129275f3ab3125db33d43b36c7de0ad60a6e9cb4457aa03275caea9635f0b070000000000000000000000000000000005aaeaf87735d9e9895e8703177faf8b11bea34aaa045852c57e9b86f6283332ab633f3e6947b84784733f6f73b289580000000000000000000000000000000004957220d5264c0ff61dbeeb0d0d51278386227a9386756a042df89fff5ff9a4d3e3e52293cc94ed729d00ed3e70b1a32dbcfd8680258eee451db60f3f42f02f388f87440d00badb0a725964042515c900000000000000000000000000000000049bec519df011ae5f19c85afb3301f41f71119ea6cd9eaffa9a00f9cb901681eec5f3f694ef9b4fe768a25a55afec560000000000000000000000000000000011414953ff3fec28aabaf3d62236d6a972da12c42102911a3ee8e88e188970a11487df719a739201b31fcda4e52d7c515a6f194abeb6b7c1c561aa820bba658f0277870e2a32f972f9d18ca361929b010000000000000000000000000000000003e5345484f59b269fa25b659e9a43573d4191c3c02f5f94534bfcd63d9abd57b2f3ab92f9fc746a852b185a6ae2c778000000000000000000000000000000000b7d7648096606b0c3fb93627e484eca017b95b27a8098e5dd332bb45171793570c69fdc16caf5b16e65f68c817de3bb579450b7aa155a3ab61e47e337ddbcd17b197de2dbb76008cfaa09d3fc806be4000000000000000000000000000000000c6afd550c55cc41cea88e670443d97c6419a295918dfde1d5490718f18ccaf8fa0cb68c42fa2cf583284cc70bfb0a11000000000000000000000000000000000f88ec67e9ba0e169ebf93fffed1fb14dd1aa3e1a2fa614a140c1a2147fcf051457cba68043efdb1b851bace84078fd64be94f96ec4a3d4e028644c63b2577a9ef849b403acc55e42432c3063a918d1600000000000000000000000000000000143a1884ecb4121e2c1c0cf2998b690d7f01aa3deec1a2ae5542647a3721f7be47c21ca071f92d74d9c3d9027b56d9c300000000000000000000000000000000113b01f060d10d95776b35c2b294216f768a323aececb308d3de24299dc12e55fac82c3134519456660a3465abeeb5950983e6618e9e4208cfbaf647592e42b2d30de9e74e4943fb2bb49109a66302aa000000000000000000000000000000000019a5620f3241d03d63ccaffdfabf7e99e784399929cfc3218d6b828d7ce137c9c6cf3ae830630fcef3cfdff705490e000000000000000000000000000000000114347768e5c8109c1bd47623eb51764d4b3f63f333677bfc28b143fcc1142f4d9094b2355408cd8c412a37a4579e0706615e300a924ab962e0b7fd0b044cae9516d96de603ee80695718c27d7fba0c00000000000000000000000000000000043c0f4b09396d4b14deb7c5027ef6cd2d426fa4f93d4ba9c3647031d557a759e3426c113fa3949cadb8b98a64bd69880000000000000000000000000000000017efb6ab8b2eaa0768bb740cc8a4e5ecbad81087cec2a307e5f53b5f431d19e3467dee84df6c6453ad4566ffa2380c9ad77d3e9e64e00b9356cceb62209ad48fc89e69e2214aad2edeba18122727363900000000000000000000000000000000140f0efabdc88a109da948494a9fca5ff790ccd6c629a088cac62e043e00e38c4281e49173ea0e423152c5b944d80ac10000000000000000000000000000000006d3d01cd44e56a4cd62d88a22c701b42c116082e92abb629e64040f57a240d71718927aedbd8ddef910198e1bb09c6841f75c89ec973f65b11786e186f4d42ee2e85c40f29745d9f428af08a39d5681000000000000000000000000000000000f20ace44f4b981adbb3035e450a656ce3d8464fbe4c45b9f7035c00aef11e389cccef660dddc025786d4f9216ef60c1000000000000000000000000000000000d5fb0a9e9ab03893a9ec61675af29e88bb30f3b61e05d7c5a3d823159bf8e641ad894ebedba4bd681df789e0c3d2547c70cfb76a04d1a9e0d937292e5553ef371e20d5d3dd33611edc0da178e2e4a16000000000000000000000000000000000dd38f99872751b4571253940ca588424190bae80434a3126a7ab5ad1383c55ad769e09179d148d151506e5cf5007b3f00000000000000000000000000000000032b2b9a8b13acb6589fea9e8b8d2535285bb32ab0e519cf8c63ea3e25d58cea7f9fb27481adcb9475abadd6f1384f4f8db878b7f5fe817599add432ecf262f19d80ac834bb0a0f983728f6e2c189c88000000000000000000000000000000000c696064b7c9653cce986e119686b2e01216faf8098d494bdf6d302c4d176b24b05bfbd70b9ea3ecc16312f899f887180000000000000000000000000000000001b5b8d333dbf1d84feaab7737d3af13d3995d3ea976d9ea1cf1d005090a809fa6c210a6363495c2b22902442fc5080b70751fe88ad289c91dfcd3c3c61ce1e33f4146f03fc0dc77cde9b32b51c75fc000000000000000000000000000000000082bc6c7ff7924b88b4a6cda58295d050bbe8087670bc6036b5bad53247b803306ea596ee0689d805e7b4de65a634eeb0000000000000000000000000000000010a79825c716dce1572e6e8886f1c698d730327f195871db7a9b6690e9ba1dc38e8d92b34ee32b33705edc021f42349184bf139cc0b6ac94697b7dc278063a74e478d47528da3f84f55fb0adfd851d09000000000000000000000000000000000cbd4ac75eb0928f366d3b99e05799bf3d9dbf187e557f211af5ae514101961ba750e81ede07cb5a14c49884a9b55b980000000000000000000000000000000004fdb80f44f89e6cb44b950735703653152466f30a410109a24b555c4e6907b2c1d4f54c9c0d2b7954002a74f1b65e23d19d9496e7ebca44354d5c6e1f6b8211eb06ca23a6444c307f92f5bc6dcc2dbe0000000000000000000000000000000019a41f73feae98fd65e365912f5bc6c86142380b2633feaba440a6c635ce2bcf7f871f1f033f93f9f8668360da3898090000000000000000000000000000000005bd1afda6a52adb550fd9bb59826bcf492cdaae8e9600e517d77832a8f3ae8777756421fe7640aae0bf07518ff695a66940e3509e1fb090fa787fdf633a74380cd5de722678826224641e46a6e920df000000000000000000000000000000000ce2a96c1ac3e2cd01ee4a20258436b62dfc2efb96a7148cf887c25d635aded48d18d38da7347abeaf72d73d613fafcd000000000000000000000000000000001773ef3bc5044059bdb5100430d4936f328cf876a48bd30784c8d3767a119bdbd5f1f97d78d52afadc42ebc85f912f0f7b27d21c1d6e06d9fba7b61fb87d364a7a6252c70b8ace2d3679ed87ce0fcf7e",
+ "Expected": "0000000000000000000000000000000013fcc5da42975bad80f3447a1ba05d9c6a51383921164ea3e93e983e24055f6398fe773b0e7a50d98568d49de36e295c00000000000000000000000000000000188455bd9ca4a0d3174cc8f0794d8c35356f697e62265d9e3d8e72bb2d1450caf5bf79dc5ba78a363a23d2ad58891165",
+ "Name": "matter_g1_multiexp_47",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000466047055d438bbdade1bbb00a7bca3ec0ce30b042e56afb9a25de1407d5937038e01e3c07595f46bd00cc8202d2200000000000000000000000000000000016bcc696716c21293b68d4f29d9cf675d447b726d579628417cc457043186d54f27c28b47d2e430041f9417ba323109dfacfcdf87c6ca0506b070abff83ce7812181c31729cc534497aa8dabe2433513000000000000000000000000000000000e8eb8fa4c0c2c86d0e571cd4708361e606c9fe789b60e099278d35d169424721bc789a6048774d739a5ceff56adc668000000000000000000000000000000000ddb7d2e6094f1940dc0f41509bd430163b220aeed1b8c0a2b90e37f791410a35d682b75223b32febc95500c7006f6626546fa692d9cd61895526282193c90148099e2afa54f7903a5431f932bd5fa06000000000000000000000000000000001080ce47aa1c38db9c71d1834c0b5d59676b0d938ba55a62daaf50911d23e286b3b813c7261bfc19e95f3bc8ea3b91fc000000000000000000000000000000000bebf539c3c03dd260d579aa853c28ae582b9c904ba2c56bb1239aebbfae10c05d9e33c8e1c2bf90553025d3279572fba9c1460c1cbb2a552e3452d5c5535868ee9c2952ec3fdb52dd826c16ae3d00bc000000000000000000000000000000000ba078b44f92e90fca4981c66e89c5490b34f92e4026d826c2076a995269e4d4fcab419a508b530793c465531a631ead0000000000000000000000000000000007c19bb972c27c00b5b1a8731ed7dc9af8270187cd26b1b9d65cbc96688fe2f0ae86ffe753a50b4500a46c01a75a93032c36204b6a005a64819b06804eb94c311d78977b557e7acfa82e147b4d6ec62f0000000000000000000000000000000009b70de2dbfe9af8ae771ad5bf0ff962c9f906a3637f992b08946c864b3d1dc996a2ff918ecb3c9648ef9188b15b624c00000000000000000000000000000000186a9f4c06ce9d5a969b959e4b17d4428393d02d0e7259fcbfab8898481bc97582ccd0e1d87d1735e28dde10a99b683e9160c5a553479a10996704c3eda8e57be88eaaf5d1efc8371e7e10d7d106e4810000000000000000000000000000000005b7dcbe86bb6e6b328325141c1da77f8af531bf1463bf3c8c94812784314fb13e457fa461c1c51aef0721c5d6ceb5e9000000000000000000000000000000000d9d1ac39a5ecd61670c1b0d061d93a198eca1d294d2e64c3f9e0a872e7c93212ce7835ae0a7fc2a42ab5c02192d70715e5a50e5dbabb7a56897935683f80a5b16dbef3c23461e241fbdfceea38e3ee2000000000000000000000000000000000741769993f2dcf5869b8153bbbff2e6e5d429fd2d862bdd590fc50a8f186bfb105f5d57f736b07d919bf0dff0cf4094000000000000000000000000000000001917c91f954f68c6406d6dc716dacf729a8c4a0de73e04cf0ce554eac40d750fd25b289127023af299c6f63372c01b7d4a95b293daa2761cc456b9667517f499c4d9eb9eb1d82237e7a7819b5d44f7a2000000000000000000000000000000000bb29ce10d6e571e62611364143e08a60eee5ccb13dcb77f17fde5829ae5fc025b309c98f892aec1fdedb7d1920e658c000000000000000000000000000000000ab6fe2dd5eb1b90f15a3632749c351ec871038f0550dc54cf1bf2575f80ecb8a3c0d3c1a333bdd803e22fb6bd3e64bc5e22ef32d111261dfcb5a2e8d23c8d920f013bd9602bbef45e6d4e0909abdef20000000000000000000000000000000004fe17772d4205d7b1d0cce0db3404119707893e20f6b27138918d2cb0e4de49cd5df1258103c1fac903c1a443cb62530000000000000000000000000000000014d8246911dc40ecea823f02c0e17e690a5f66848223218dd1735cadca1a0ae89d7afbdc727158257d2cb248323c55316e687c0ac8fab70de2416642afa1553bb38183d2914050602874491057f78786000000000000000000000000000000000784a1b282846404f71227064ff1a97766781900136d4b7ac73bab19cf8e03b449ddd35360fdb6dcdac80e335ac5cd1600000000000000000000000000000000074fc137d93decad1cbd4b753fe9ef3b8b3445c12e358450ff494a1fbd6e192ad7a4812358d85f6e3cefedea3aadaac6428f1a27ea15135f044643dc36a3f9c2b4446a3136bb11f696b0a430a7454b3f000000000000000000000000000000001661e6d386aa6516f08decbbac9c1c3411ae9cae62b05037dd626a2e2273eece64615c54a4d73e09814d497067f9e6e30000000000000000000000000000000007543030f8995237f65cec9b69b0356a29133d8be27b5f79aea580955042242c2bc1c6a01539b6b55ec9af96db60b394ae21ad8a6c9d75b51133e81ec34d66ca70a52529c5c3a2307b0e8d6f1c5e7d9700000000000000000000000000000000148597902b3ffe4ba8a5f9012e699a3cf189f58275557d98d132b72d3c34e5faa0953ec8cb10b0228a23803b70836e200000000000000000000000000000000008741bbe372a1e5a697e7059a9e80de8a012b0cc7b12c14bea098c16cfea154204d4e27753f1a8fae0e618223da14fdd88a23b118179ee2c34ad030993a2d2d70375311b95254c44254a32508abcb612000000000000000000000000000000000cfbbd4632e8998ba59721686310ec115b98ef470c3c4bbe427495d6d95d06ec6180e64b509c4c06e32862e17939a2cf00000000000000000000000000000000060042078794f4539a9b3e3127632c3c8b46322a669605d1774e995c5d82287d3d9be51690b4b5df6de8d55b20941dc630eac099ededf0087275d1af828bbf79ef7fb0e77179a068f2ebfe4c749a98c90000000000000000000000000000000007e67da2f320e1ef0d3afbd50634aff753a2e2104ddc03244a0c79eeb117ed1beb7316f7c5e116bbde47c53d47e725b3000000000000000000000000000000000b5399ef864331db729724870b431d8dcd8d3279cd00a59de2fdc15bbdff2035794025edafa21fce97836e93b41aae067e8dcbf708682225fe3f71b7a687da23de5ed188e40585be05533580121325770000000000000000000000000000000014bd7f0effe81cb626f92422ae7900bafa7f4c2d51d4ee6926eff68b60c7f41e667a57bb0506f7c36d3549cf154f6cf300000000000000000000000000000000050aecd688a63075feacfd29d1ab6430176dbc5ba6d406636a6650427a9e0b0d51df51d8dca27665b0b6c60e08d5b087532cd42a9b698a2c2d22b1a620a7ec60daa9d1eb8ac36894603be7bb9b5e37be0000000000000000000000000000000009252c5f7f7f3b36c5dd32991641c9f8244579960fd2d07a8641b82c5cb1768a36f4e5ad623319ef3f7d0c670fee58430000000000000000000000000000000018e432d33e506ce42bf3d873e36ed6ede0c9de44203cdd453cf91c42fc2ddaadaadd2e3870c5f5c171cfe76862ce44dc3ccd5e19892765e549a63238e664c732af781fddea558a117cb927bc4a1aceb5",
+ "Expected": "0000000000000000000000000000000008b38b298fe2dfaed042b35ce73c76ece7537fe5181ce647de756349a8dc48d3296e243fc7613abb10e254e2b0197d7a0000000000000000000000000000000018d59a69b976b1bacdffbea68d523da3fd0d2910db0a509760bce56bcba36a55fbfe11cdc14cad50e6951ffdabf97a64",
+ "Name": "matter_g1_multiexp_48",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005d929298c9361736ef5f7c83b6a851c344d72b7bb92a8201d629bf9bc1e66e4db6dc9df64ffb41a11eeeba10be52ec40000000000000000000000000000000007962e1b1b823b770b44eab51b3b84fd7e0e57a2a3f7eb1ad9c3ab02677376cee08b0a2977552a0f9399584b576f17f148da17551b2369b723bf932173a9167663f8389d2461b763d6a061df78d7ff1c0000000000000000000000000000000013283d9b3cb5ca4c3a39517adf466d2b7fc90f4895a24effca7ebaee4df8735c69993c7cf2483c3480cd2df4be04366f000000000000000000000000000000000fc94dee82225161feb78f2a7c951c41f43ff3c1109a824b56c01854688feb86e240c9fa48534809354e74ca8360cda4def52379c8b9e7c24d971c3456b85b51a63ab03761ec66c8dfac1018833e05940000000000000000000000000000000000fb727cd02c5f69af676f9cfa68cc4363cbfe5343e304ff5180ed1f57e6928fb808539276feeb1e492ae2455f65de0b00000000000000000000000000000000082d09bb2e1f1585933e1b9076711803e71c2236ff78e83f5dae6ad492c1d723120ef64eb25c8e91486d102c2297c9e5b2225be6985b9c8fa59a2890da56427612a4334937761e24a33d37f0f951a794000000000000000000000000000000000882f34897651c59970934848ba13e815710b4952dc0ee1abd0e04ed82ab399ccfb16ec966d010eab51e5fe514af91ae0000000000000000000000000000000017a32754dbdae7a2541eddba29cb8ca85a0c6d189f9bbbfa24d477e9f1ec2ab8f7dd2a5aa7a596d3a2af916ecfbdb2c2a64ce8ad619276bc7a00cb49faf6cc84b917ae6b37654363f5719a727a220291000000000000000000000000000000000db9ec112ddb4a9c6e371440d0c79bf043c5a3c6c6bd613dc031ce9b81b49a32b006a165ef29a8e05f019b76b3cf520c0000000000000000000000000000000002485dbc3c3e2aeafcf18dfecd842ec48b2e79d3bf7936917df759a9ca2e25fc3f137eb88a701f5fee1ccbb06d5cb08c0b891d638d7e76e0dcb230b1f9a7c3b35b35193c43a6c86f345f5a5bc9c708f500000000000000000000000000000000100d1fb78f53423c8cd60de5d39a004ee1c99b2fdf6847a62c73c33bb3d317ec06afd6424359481f8ff2d0730cfc9095000000000000000000000000000000000211cda7659f1e848c931ba1f65ca9c6021067ca01cdc8e87f5c742006f6dae39645553b69a4ae00ab6eca16afd0bda7571175eb91888222085fc2dfe0f4401ed6a1fc5df86c0c6b8e44fba6454305bf00000000000000000000000000000000004b07c2cb575e2499e333140e48446fdaa00368a74b87e607e285781b42eec39d1578d2e34701ed28488f160e9e50680000000000000000000000000000000001c2d66d28031aa91f6aacfdd80d222b4a0bc699a9b58b7f5d68bb9ed0a297ffbec3a6ba968f225732879f2f9907ca3954c9e7f7ca14c66b8431e25e6eddb4f20507d03bf124eb607957ca2f43a0c17b000000000000000000000000000000000bfa7f8b7783780a2b0f5b9f1b10da77cb5904618b8c8a1d062fc94aedb0fce090d8c4e65515c0d05a471f2261d0063c000000000000000000000000000000000f45747e4b0bffddaa13c7e03b6930ec474735b6a0e779d3722330828ca26a07bb731a5d4884ed3eecc710356a00a897000579e1ad83015c8f02a9db5c38d0220368a80b309ee45bb952cac824817b6b000000000000000000000000000000001245cf167d097de0753d29ce6018b7777b1befe43b5709e8217b9f380d958e3e9298347673dce432e57338b313e84950000000000000000000000000000000000d697bf8ec405e252588e3ef6d979bfa60ba174da03266c3a2efdac176c1ec1341d737b16d53bda6ddf8be6e1f433ff6909a45c8b78350e3ca21697e9f56d5fc8fc2a01817b78a7f5daeda487768ed1e000000000000000000000000000000000152d7f1e704619bbac7e594be6e105120b76d9bbc711ea40beb1063c2996fad70bc8f77a915411f3601e75af2f2059b000000000000000000000000000000001622a6467c13c534ff1fabaee8b29452d689e7f9e118e050cb91328b8078ef97fc82321b80d28d0c02f2b0a7b66f04a36d4e2277da617f0ad530b6209df6264e1288122b1b4d92da04fe334be17bd8320000000000000000000000000000000001c118fddc8df59e2d4ef9865d69cc044fcf870f296b009a2a471b1f74692f99e392b455b8b03d079b1f39b09e5fb720000000000000000000000000000000000032c05dc9eef5b55857956919f7a51b5f5225a45ca12d80208231304e66c77b24707a934cb9814108b44427e658d143dcba6bed6b8c42240c01df5fa0ea81dd96168c6d98ee9d5d4653edfa5172eb280000000000000000000000000000000012da4a2c89951f85757c59a2630bde25c30af955448c972d256f1a6a259793c7b2bdc3f8734f4e312897cb6a3550800d00000000000000000000000000000000199939ffbde7b14b5f23eef23d4a660bf3f561aed38205e68d091ddef9679df9230a59e8cb03212df2e99788fa2595bc23d168e01657e5c2da89a27e513bcbc6620b8c6082bd39880619bfe2b3a7317d0000000000000000000000000000000017a61df7581a341f21da2d1768fb41bb89847c88b2a0d7b61aa3275e376a46672dcb919eebf20b242ce83493c83335680000000000000000000000000000000013edc932b7755115f530d1d044c4afe71807a6b9810f555432910b54b0fef441b4618652fc4bc2ac5b789a75d2d276aa2a76fafc5e8e33852bbeb7ab8229305be84f5474427e0c6d2ed35c7bfe99faa1000000000000000000000000000000000c73683f328a0aa252c10bc3fae9e786ccf183f1b606a4596094fbe10630d4418a527509c93d23e62dba263d86f88951000000000000000000000000000000000260c9dd70a1ddb422491a20293c18e4749427cbe9841aaa3370533b6e5d6fcf882f8bd68b7161434bcd5060716fdb97e3c7e4e95167faed1391e269785918a207490c6d186bf2537c02e52e414d564e000000000000000000000000000000000bad0e395f46f714ac9d40865d588c06adb54b12439bb408a9d546b0a8ba5b3098c242cf5c17d1e40dcf7b384e81b444000000000000000000000000000000000e595304cd73c8c2a0bd1dff70e89edfab22be69bafa16877ecf669ab1e1160c9719952bb6103f31f2ff028cae0f0ea45d335e3d96a9b25be7f3916e92fffd75abeef5b91a1ec577ced52a96f6a9b10c0000000000000000000000000000000011f0037c9bc2bf953a3eb7d8a0a3c8d991e6eaa5f13dc1978a31f0eddb550432c70aad096cc0b904ee540e5d2d1ee4730000000000000000000000000000000004f8616cc7476fd0b95f7bbb7fbcda389aab60a88ffba3c819868f7ed6cf08e7c0c7da0958bcd957e0429b9a7fe120bafa563a70780837ffcf9a84456f0b4f6eda0d60cce6a8538ba10960eaf17362fc",
+ "Expected": "000000000000000000000000000000000e87aa419d686c55b1ed8ebf6e48d8f218d7198edcbc7db0dc3bb9581bb8dbf891dc383f27717536dc5fb7265ce1ffd8000000000000000000000000000000000a00646bc197307a7416aa9e35db9ce7eb81d762a065cf8d2e07f6470e424d7d59021be049b36eba2e44750a902f3124",
+ "Name": "matter_g1_multiexp_49",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005d5e69a8876b82b1de0b2d2a0d808c739b361d1cadf3ebc9c6096afbc19169f237774be6882caeffe47e86e3b8a33710000000000000000000000000000000017bf0fa8c247af0078d486e1961577d7977d0b4258ada3e158822d995188ee374d900c4d8b1ef4887fb03d8f6a4bf1776e2ee781da12b984e7a08730a60f50c41cdd7c7c8b3f1f30f721923ddc34fb79000000000000000000000000000000000e6ee0b0c7bb7c3f62284efda6bdbaf38bb5a72b4435b76928c5640fedbf9d4144358a20629403359fef5bcb99a795eb000000000000000000000000000000000e72324fb2decb0b0c7fa18061a41bddd6e2c55f901554de9be8ac7b2263631fee8bc77773318f6b13b2db7eb1ad0f3cd51e0b65be993ddd2892ab8f47eab78352b177be4b3fb68f47c65f5c59fa866000000000000000000000000000000000102df0d54108666e7aa611fec5c09b72d269c72e6fcee7787ece5f33153a3999ba5f22adfafa461aeda64e113b795dbc000000000000000000000000000000000b77ab3de0a2d91b8c24a47a27fbc5b2281cea40d87872010b94e895d9589880385f82ff53fad55af4f4e462df1c9ef6fed4dd284df98923bfc3c41496d6e64a10815a8c474275e0cdbc9ed26e92b0ae0000000000000000000000000000000018e8fa3c5bd83b51b1af197f0dee78e5c912c742df0cae1b59ac44fb2b903ad5ee1fe9750a034d18141f09a2b8298f850000000000000000000000000000000001526a80337eb938420cf2e825e5bcf3152e90e448ae3b40ee61929117d35f694eb5ce9133b2cc664c520fa9da8ed65a7c36ec97c1eafc8a20a772fb7887d75568047ea32458b9ce74ad9ca0581299490000000000000000000000000000000007f11b03e06ca74a35cf702f19fe29facac855d7f5adac59bbb8c058b1eff7d4748c886eb08600e0484aa976269e5d0c0000000000000000000000000000000010a5b0f723371690f6ccc5fb346874e58071167947d45e54f9d5edd035f2d68b4ef9e301f26ef671634121ae6145e44e41b2c0354d2f7d92b05043f193b718d78b457ae76e19069c8e1c2b77d7999d65000000000000000000000000000000000db2e2ef96ea61075e063629eb031235543e8f39f012fd006e143eb137524976c5a81eb26996a4ec3619a7fda051df6d0000000000000000000000000000000015d39e93da2b392dec64c58e73740376552e69caf87ce9162801466e75dd1e25b7d5762099112b21411e8d8bc18806fe5615370a76bb0a5f64d61b97bdb045b9669f6a0b7644b101d21a50483d8b04dc000000000000000000000000000000000e048ef3ee3bf3c41cc10b89b7d0f8b3f27c89fa0ab25542653155dfb7f8a7e8488a737bf2f6dab558910c9ae98aea33000000000000000000000000000000001357eb0945e2c4933b358970184a21b3369dd7a43a88841e94c3a388681f338770fdc3a32862c3a52eb251721b2979e9bcc38cfd3c6bdd32ed1d583f2bd14e175d61448c627f195559b751aab1ecf7cb000000000000000000000000000000000c6321bbc74b6b3a9f0c9470461c80b1713a5092871dc54dd022d3ade73845852315b3e85b53b74ce2b31d1780939d13000000000000000000000000000000000cdef7351c2923faedb211e79a44e0e02ebceb8103cec2ed7541a54bfafe3967791edbeb6d4b0da1ee37b9a5d77ac8f194c41471a2e4edf0f688c2f032036d41ef5f8a966871dd099dcdbced8b37e1c4000000000000000000000000000000000b925015af89d42f155eb1f5104db1128faa23101fb9bc1a9757266a2717d50e908c64c502a8d19bb1e8c01dad554e41000000000000000000000000000000000fc8c5cbacca685c24188e8f936637c7c8010f6126e9b9b49e7d38191af1246c2a3cf7ca45bce6f1e11c404919da61c3dd297b192f1c907914ef949fd27a5ea5659aab659b83239c4433f7a4e24529f20000000000000000000000000000000013fa1374d37396bc60386d07a441a7d21fb808e3b2ea0c39ca78a6dd70c473a8feb972e2981e50cab6288dd80c40c06a000000000000000000000000000000000f35c2a2897b35cd7417aac29ade18f86d56ba24848aed78a31513d5115bd964ac6711c5f71736490195bd97d2d5b507d30fdb174a3f5c06b78cbaee5b6e7a4c90551083d78c5164de6bb45ee5de23c1000000000000000000000000000000000799d71ab5145a8a4726cc5567d99b344971eb8bd6248e41aae02bacc358f967475f64169e1828a66905e4373cf5c9670000000000000000000000000000000017c680c55af98789584e073c3caf32373f58bea6ef7f839f1d5c39e512058360efe80a884ef5822bd5fee34869d028d5aafc42f7fe6854866cb954367fa65c8072bd1b60173a2d45077421d6e25f2bb3000000000000000000000000000000000b4be422e3d3e96f6a6821c55bd2a37ba57de1bb59c8f4855b1f4b6906259de6be1c1be40523d5370ccc426b89478a350000000000000000000000000000000019212f598150b576c17c32a8f374db52c19431d7a60b99379f570189b3fa15edc75b807adabbed712268087cd9b89a8a106da5f98d5e7cd9f4a1c8d6e50ea2236c2abdf1e08a0eca54555a59bcadbc6a0000000000000000000000000000000009df46395e64ce38bc79acee751484ce1bac53c5e5233d3545df2ec776440e3f5b04239d6de10bdb086aa3c462fc6e820000000000000000000000000000000009a5c816b2abdcca7a916b1eb015b3d1c01f766e01264b5139e5a34a82a874c1efa8ef097d23b9e9441916a2f5bb17b4c971deeba2f757970bcd4f5548a2767bd6c43e63f4c5fc4b157ef060a1f45aae000000000000000000000000000000000023537e0238470f4d513d56d4ef8e244e3d853b3b10a893928547675c6b2d409ef6bbfaa299a726eb472067c48f056c000000000000000000000000000000000b48f21e01e72bb6ec384a1e8ab35db6ca032e4476f37a3282214efe483b672c34989e6d5c99f69473eb19e472d984bea5262a021977dd79ab96606eb24a7c5ed650300dd68bc79f4b8378f58c6eed490000000000000000000000000000000013f1ad33a2016874de5265565049722929528a1c66b84c1876f4e4396f22fb2583d025c481d4d9aa2877e0062e842d7c0000000000000000000000000000000008a11522b3e6982a4b46ab6f1f6b07d33443780c914d4bcd50ef7ebcbec6ad944ab88b82640971e890a363dd92c71531083b3720c20044fa41712039b6e9e776197391ef393c0935a0e9990fbc1b7a460000000000000000000000000000000019dfc9ca394e105c6ad51b130aab8a043ee58f26a0d8efa5beee59eb1543c2c3d33abb5cf2b23b0882a409d32f845b1400000000000000000000000000000000143e219edb6fad7dbd64e6aa82fafd05ed92bb46e526468cc3bc0d60c89319d3fa2032b5a617691ca2f136c9f7904225d6f846581848f5dbb9e8d220b881d0327c4f3f5d4b79fb2c4dcbdb9bcf44b02d",
+ "Expected": "00000000000000000000000000000000027cfeeac9c1606a0942a95068faed1405a5cc9b5e631c25a0010ea14cae5b7a51b406fd0b8a9d9ea7be9a8c0f76c86c00000000000000000000000000000000106c07dd0d4e6f44fb1c3451942bf10060d16980f50b63005936e35b5add71e1352c48d1048e5d77cda79a09f86ff213",
+ "Name": "matter_g1_multiexp_50",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000065d5c6ad252823540ff4a4639cd42443a3cccd808d40d8bd71379ef939b47c3027ba5593167b4dae93b62b2bd498f910000000000000000000000000000000012623162c0f025b16dfc1c7e5fa02f8af7b7fb0f2d42d6fa0fb01af45621f00faa4ed6da6f33c609448bc027cd6a4fd367c44f7c8513472b51f96d526422bac628aad4c40c521cd7cf9e86eaf92838fd0000000000000000000000000000000008b3c274f83f49cada0a1bbf0f56f6fe0f8a0873cf13efa42ff65dd6fda913102c2034a31a1a92cd154210d27b0120450000000000000000000000000000000001521dda1b2c9b42d7dc9822c64bec62e71c629d61e796165d9a18f8ab44056914fe5c8809f21663bfc70e310ddf5d952d6f95d4b6216e4226f78e4fa5011c9becf98fe45a17dfd740fdd0ef36d8ba9400000000000000000000000000000000109f72caac5abd41a228bd82b6649fab639e4d22cb3a9a060ff7577de61f33d32217a73014f5cc2c2a76582a6b751ae200000000000000000000000000000000059d0e9e64b10cefe03daa146c00c5040381ce6ac63886b5fcf19a0555a22a395a0cbe8b49c510c9bb7a308813fb482958c25d36216b811ee42d0ba629ab7a0f9ce7edd7234620c28e37bb3df3f042e70000000000000000000000000000000001c5e132707520c525045a08626e014a84d8da23dc27b6320d5915e328c3bb0df3618cbd7ace26834920d4a8757368050000000000000000000000000000000008f5127405631bed295596639ec6091e97f16ce5a3062831102be951aec98c9ad34721489f65e731026029ae3eb13aaa50a5c6bb6b87fbe5ebfb0d182d425ee173973c6f2085c556b0fe60219b9f3c3200000000000000000000000000000000146124bfbb9a3d253670be419f80998382895ad6237138044c55764f0d6fc07da5b70cbe17af3ad0c4b0dbe33f869e490000000000000000000000000000000011cadf640e78298347115e6110d3ed63dcbd251c48d3e21cfba4bd6859b0310041e67d212b54e63be6d68d2e7fccd83b3b4bdeaf6643ed159f4a3e23c33ac486b33e1edbc5a097a47a6c2c753e5299d20000000000000000000000000000000012ab7e51b87512007e1baf2f3c3473cebb553bc2ea3d3146358688ea3167817a449ab9a7e0b090e00f47846da7f46340000000000000000000000000000000000702c1e0df68bee2666abb90bd593a17a6f9dad02a7d66102add9f3a525a1b4f1fefa3abe262852fd5ca357d2e1f02fd1d18596bc392dd0b71e1216bbb20a0e5e2559a46789c36a146cb78c5aa8e39210000000000000000000000000000000014635c8b9cacbe976733bcb1245eea410008082f240cc8d8246200abc0eeb6b7444f38da3ad93b1e029b06cbb12d42f7000000000000000000000000000000000d9aa00397e1799a82d73040122515b98be82052b784a4b385417f6e260e555c7c0c48a32ca1fb28224f75f887fa4bf86fb3669c0789ba6a5b00f14c14fe2edd15d37a742c9e36cae9ac010e632d75a40000000000000000000000000000000009a0efefb9daaaba4b2beabf6c381c27df7c32d4021a4d722118886405414837cde5c55933de23ff6769a0a42933bdd700000000000000000000000000000000101c9941d98dc8a146a75f2fa48a8650b25ae8f6d943323b1c10360cfdcbebe220494660f4d6f7921fea006942e122ac06c2988dd6b8e9aa116eea4e1f63dacf100019844d37d163c047567e8e118862000000000000000000000000000000000e5b403702a229f36c9b83bab9335cbb4e39fe8f5e9a5aa4bace70361dd05c87ae356a40720c4a8214765d028cd161ec0000000000000000000000000000000006e447c61bce31b4843530e504fa1324657eba731a272ddae680c202a7d017ffdf0ad0656dc0984a1fa297f5e32c2740fbf8322f706b1972f73fe4e22a3dad29c4ede09163561b2810cfc3eb2ffbc7ab00000000000000000000000000000000135fb22eca115779ad1295f8c7f149a6eb4fe046df664ddaee976a15e11a7a59db5e2c44b4a82c8ca1d17c0043f41ee0000000000000000000000000000000000fd9c1dceb20e85ef80bc9ee44e483cd0e2714882734a561ebbd0982d6d08e9c41484ee99790c20e83d051dad0a1b1e04a46618381ba6b991b2edfdeafa67aef1cfea066fbffdba24db25385963326bf00000000000000000000000000000000040f65cac81c01f04db3e331659d6bbaac8fa01581b1bbfa62891c1bc95a67182d254650019dfa3171e16ce37deef29a000000000000000000000000000000000afd5e22abd5d5cf78764262a91aadcb8b807b2aafecb2aa3d3ba5a187304208e212e5df46a4dc48d6150a733075bbaacd05fce871e4ff11e7a4e834061c65a0aab7bfa8a0128d460a493337c6e63ebf00000000000000000000000000000000051046cbe6862c5e37cd2f3c14dfc2825d5c32de69b40f29140fd31405615edf6c116d384bdf1552a33fb00c6c65cd97000000000000000000000000000000000a61a19fdfc994105f03aa3e1b907f5177409664b2e50243cf7e0e6e7e74c7bfce582929e5670a351b3d7b4034f101ffaba9e37ae0dbb733af820743d8e307fc02a3ce9b40032b16d0e9466903de9caa0000000000000000000000000000000013b76183fa2e01d10a3ecea5be65ffbcb04724ed30e4655e26a7ac94d5861f0f308b7d4577789d2f4892eb89202d84100000000000000000000000000000000012c3fbed77d9c37c47c838899aaea0fb6585eec54801c3ff2b486086e33040aca6baf6192c33af59f7db1d489ddf7d086ef151662cba4952416eaadebfe5e0fa0ca1d31380e1540c2d5e0181af9e317c00000000000000000000000000000000195c1bf8dc0114a472cb4daa31be44f22a162d22f2968b7909374fbc4d0883614d2911475cc3ba242844ef1c046885e70000000000000000000000000000000000d03e5bc3acdd01d174e1d2308e3f1ff3f103db8e2804210da44c47229bd983ac127295558dc5560c0fb2ea34def196f0a3851bd52ca52919dfd21efa6efc56f6dd5060ad969360b1a731e8f38f0f5d0000000000000000000000000000000001261cc24d5e69fe8a7747fce45086499ad54f7c138fe76fa665517c58e475683c5a219df303810745dc554fa3c096f300000000000000000000000000000000122fc4c068c079827635d29e944366516c1d7cdb1ff62968d847f4882da8a4919b59e57690f6e0f6aaf083af0a04b2ca32b41960417047a2258b6e9e228f3cc1130b296cafbb75f58731a81fcfe8c83a00000000000000000000000000000000050b5493fdadda15e15b2ad6104274da831753b1cd247f1dacffb6f896b9db7190bfae2ca202907d36b979b668540ea400000000000000000000000000000000141245d4556c7f1032d0ccd606e3a2d3338ad753fd7d0a3c1b8ab38e94d8618e85c22a269428537abe003f8de89f2c1171a6f7f091a6a21dbfffcec2eecaa22d05252b60bf91b56811a833dde3fcfde6",
+ "Expected": "0000000000000000000000000000000008bfa9c347d937e2ff2d77ce7127b1af4e7adad5f1aa6d71c6226b64c62c955fb0dd0e36a5e87472d6979b656c8a740e00000000000000000000000000000000032de435000391e441ecb7e777741fc72f4676f64cfaca6fadf030e12ea6374a7fa988c443a38595def0b434b185c75a",
+ "Name": "matter_g1_multiexp_51",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d0296528c7b2516ea73cf14c5625a4296c311fc2e09722f3b381279da52ba9482e43d3fdc1694b96c3f62b7d98d6951000000000000000000000000000000000da2aaba37d0955c5fcf31152926f2fb345deba744241bf66511da5f4ad9fab8a1cffa270c4e838c39b34bc28fbc08b02e56b63fc6ba87cf021c2f92baec248756ddae0a4f070df840db281283a4c9b200000000000000000000000000000000175c976baf0205ee7326c84c49cbd2d7c3db91d1ec92d87cca896ea09a7cfe4ef8ca45873f86e28afc4b525356a68cba000000000000000000000000000000000c442d3edb8b614407e0d138417f8a6c028b29dc1beb5825c928dff3a08820c5a8ed5de643068bf4d239bbcc2dcd0b7612a50af55f47fdaf176d4885e4910c54428c8ef433ea0cb1d009ea7778355947000000000000000000000000000000000f45bf893109177d3c336915c5e28c338ea28468cbe215ee6fc6f6e3c9aa9e0b7120586e42c5c087b55fb5789a4a9eb2000000000000000000000000000000000b6ad0cffaf555f081ec7a6fb354d6b20950fb6fee059f2f571430f86a7cb9996b5f655bc7cddd14f3f8ed37c7fd278889a012158b3c18e19471fca6d5aba5fd004a337d49ddef5db177da187c8cf1c8000000000000000000000000000000001944f2fa08357307df2271f4bb57cd07a998df56425f7b8563902aaa0330070ce260b6d86fc38a5c6a284788d9cc0ed700000000000000000000000000000000165d8134931f7a4cbeb5114a10e44172aa6a0c250989dbd88282f92fc238a8e1e21221b04b239cfc597e2b74700c626d27dd109f6df1d9851dae28bcb9e552c6b1e1b2dfb331aa955d3d0b6c4862253d000000000000000000000000000000000c7a02cbcc758fa7b1ea5fd30b3b88cdda7c8661b3712ba5bf924b441e056fb9bea804bbfa1850c21cad891ee253ff7100000000000000000000000000000000012202a151fcb86875b4dd2dbeafe5ca484b63408ba01440007164fa2a2b7ebbe9d7f738f382a010508408d26a57c566ca96785c1ab66cc5c8e434f59cc1ddf76bd78b6fe660f7cf74cfb79d7f2c7f840000000000000000000000000000000017d02a3ec6d45e9b49ddc8d1bdee168f71c32ba26d4de8c1bdb328cb4c46286328387aac8785eb5a7c71d0ed59810f4e000000000000000000000000000000000d23ee9c9fc914404ff46d0f6ee86984862e97a777ab516c2b84f5b5a7c1807d64e93fe57db53c7b95257fe46a7a15495aabd1fba36142bd768339e091b15b7f5b4ea609b57947a7187c498bd9833c2900000000000000000000000000000000040ca6ea6cae1be17996106cacbc5d9f1962203fd25917dec2c053816f3200b9853b218a07db690d8261ae3cc85679bc00000000000000000000000000000000097e8f4b5a24b010382888ebd7ab7cb71f471bca00c1499486cfbf1bc5ba6af169ac27e1ed8cf31b5d9600361ad13663fbe608fefa5472c7d1611abfa402d2eddb1e54542f45d4012db8ac6d1e5016100000000000000000000000000000000016f95e3e24941c2745c009437c1b2f5ebf690c9c76e269f877bbf73ddc6b15c6132d424c26a3c7bdd9c5302dcbab171f000000000000000000000000000000000cfca2fd001c0da52f231a60288b22a134c7e16aac8745129c351dd96fa37b72a9ef3d93d5e8e45cb5fab9e73ff188e128d57066cce439d8d0385f647ed5e9b29e8fd0528c1ed8455f37dcd81f4b6224000000000000000000000000000000000e2bdbc906c10b04c5fc1e867af43bea7ca43cdbc43cc3574a47b2b0670716a92fd863d4f423f3392ec8849e74850eb9000000000000000000000000000000000ae76847a2524be3a04bf85e096a1ca4cd3674459698fe326db2d71799c8906022e15bcadfbc9ddcd43dbee3443842a81208d8d328014a6b2c8b2b9edc70589cdd63d38f4e70abb41cff1b7693bf9a2900000000000000000000000000000000035d66b8b8b64bb0d3d1ba6bc1bd34c326ce6abac3a97188f82be38d1756f14a63bfedd531d5e19813b668012f77763300000000000000000000000000000000060851234e4cfa8c168db199bea8cbc337e685b565a6faf67e07c463632a6a163a2d22acf9fc6bc6a1f7ead5d288fcccd3a2044ed4f938c17684413625bdd281f685abea2e375bece77c03d697c82cc20000000000000000000000000000000010e398f6c9ded2fef3cd95cbef681c5335a1e9d08c05dc05b6391f65941cb3a79df9e1cc4ebd3fce82d36cc628b7f65c0000000000000000000000000000000016dede30728c57650952e9425b6da1ec8ee5702e783c69936eaf6857f199bd9ffae569db3cbd61483d48188633fef7ed7fd81e27a577b5e79929614c069d6d52146a6183822d25cf1ef84d8afcc1f6b40000000000000000000000000000000005eb3a914a78b4bb3041a32397bdba3edf6943ed474ac8efbf9c84a6cdae5d65a8f55ce4ad141b846f1bcb5df1206417000000000000000000000000000000000c20828a5d8abc2c8f72809348e770649bdf4bc0991f45979501f31d9f31e028731a8ccf07f0cc51bf8b59632897c540c5d47ce35d4ede84a83c9860322f582ec00c872b4b035d5d340981fc29884f1300000000000000000000000000000000122cf863d9ddfdc627a0993dc7ca5810e84ab254ff8147a220d436043c0a695b0cceaa374842c335c14b6ebb273472d800000000000000000000000000000000150fc0b14e30ee797e3b9202533c681ca9e6b1b43347cfa11da59ceab439c9e5cbc038a50917cd9167a0fd591d8175e484ae256d47de2d49b1e755cb0e972f3b614f3e7ba779c65ce175ca3811021a7f0000000000000000000000000000000002ec5aa74588f6a7fd8076b9a846ff3542543dc7a3c798c423326eb06ef92edb8c35583785cfff21f903f08f692d6293000000000000000000000000000000000df140c1539cd3d94b5f9d0aafc38294d1738c5b3c1880d8864e83909b152de0a469742cd31e5e8f5838ad793ea32649a09d0136d4dbb3abfabcac55db48b1ce302067f413283fc1a21744f1c16ef7b5000000000000000000000000000000000a440f227be209dd1bb816a4dd8c1abbdbd03d97c243ac6e48c4efcabef4d7a4b5bf65ea7bea6f4a1da985bbb9fac626000000000000000000000000000000001431a99e1243e57054d2b43217286b35bbf37afff72b163ad40dd4ca92439f4b513284551b0fb137f968f9f59a540cac650a6fba1a5eace6b455ee780ff266c324f49801832640856a80098f0eed0b7b000000000000000000000000000000000b99ae325f1fcf4f3c83f251183871d1b6048a43d15da80650e0b5c1b671031cc9af63a478b5939210356c4c2dcc7aa1000000000000000000000000000000001382d6f0550aad61dccb47a66d004ab3801445d55dd320a6ccf03577b1c1c915022a955e7f3fccbbdd20e4175bd0ae38282cb1f8f6d6dd81e7c49176503a76837a96d7f2b084d29d11dd9c6548cf0a57",
+ "Expected": "000000000000000000000000000000000c62c70aac1893222d967bde4fdffc565cc65fe29387825224b8571367ae8fa857b63c32033faa564f6e12d409b5cc060000000000000000000000000000000015cb57fcbc876f5aeca01d90d55ea777aa1421547e8aff0de69fe5527c9a575f9cecd1235a37648c7509d9bebb4e6800",
+ "Name": "matter_g1_multiexp_52",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000123fa54665de1ad1eb74d400f93b70f8502bd9386a164ef9ac7549b3693525e3fd077b2b2d8b15ab0c6cd5da30f8317800000000000000000000000000000000185921a0fb38ec1eb6804002b3bcbd4d4bc759885e9c1fafe275d51840434382df783518ce768ae40e736ad2ca8fc8803d7f8fbaa4225f3008649eebf42315785ccda2b9ce922170e606876881825cb9000000000000000000000000000000000eb30c8da4c7eb16d797f24b5d8e210dfaa68684939cad598518298c84214ad769f6a2634fc290c2c267c8f3a2872f020000000000000000000000000000000006452f211931b8d7ccd8777b2407e5cb073097ae9b309f1e95633f39d1a5a7f5843a6e87473b4b9c1bbfc17971108e3de71e6cb3d4e19f4a70a4465df6eec6326f558ee1cb99aa540ad2a73c363a133900000000000000000000000000000000162c0325ae75a81c92a8885f14e2f7b9b8bfb249fb9a352d0007cd8bdfce2d8024f1e4674614cd0afbded99472d547000000000000000000000000000000000010d8497a5f31cda80af22bfa6695b4e2c8fb5557ee74581a33fbd0cf8cb2e0b4ca3ecc42487cf957ea81a5388d9871fcbdb2b3c3b8e91540dc2724537526fd8c0d4b85d2cc20323d71fa5a4f61b3f12a0000000000000000000000000000000013270ce7a1b4abe3026d245df9b93061a435ed00d0464d8de14675247c7f2f1cbb6e21c8282e71d2fa28eca1e3f5863c000000000000000000000000000000000b87656d14cfe98c2d3f34b03de0b9f08207b00aaf6c5a4a6b9b4989744581772a2d6d1923c3d07b784853f7b2d789b9ef0c8574167a3bd3b794f057ed01865ea69c38023dbddb0afdc55dd9523ebab700000000000000000000000000000000067296630285ec7da7cfdeedd387d52d905ec39e183b87479c8f0fba967e840f8394cb518dba4f4b7d4e2cdc00ca62c3000000000000000000000000000000000ed41fe0f04e0c63f3fd7ec7560d24974fd06a1566e8f129f580251227cb9b7e10ed6e60c2e7449721d5332709f465973ccc75501428d3be8bb469ed0f2df7dec10e1d205e11a907cc30c4a76eee3cc00000000000000000000000000000000006f7bbdc3c8fe2f7da9533a3f8a3c48c630d6cf567c75dcf89e13852f7a8691e2625ca24517ad3b59ed3513f7d3b4fb20000000000000000000000000000000000a2e63715ec49b06a78e014b98effbb03f99ce61b464c66108cf18ea49def3e1f035a8b88f37b453b31357d2a2a48f4e5e403f555fbc800f1342275f18a73dbb679bd31873ee87617090912a52d6a55000000000000000000000000000000000a9e51eaf24d2d0fcb7f1dc7ad985ecd4da3ecd19fb75591467edb0f7fc7bcef67c1c272f39c31ef36bbc73d7ea6034d000000000000000000000000000000000332dedca239f4d1272db77dc388e07005d90f44311aa889b42e931d08c2669c3f4aeecd9052d3f2585b2a4e41c8abbf97ea57a38598204c15bf65e7270a175460510848540ca4004286f3ca09eb5926000000000000000000000000000000000c6b189ddc86e2d6722ebabc445190cf94bb4c54135aae2601c957e062d351d0c9fff19cbeb45cfc5dd05eb3543a660000000000000000000000000000000000133794839bae14fa041004f173506fff511526313da5a8f4e32c895751a22ecf01cfba564006037326187b899aed596ac54dd8cbe68d5151e4428d35ec2d5b5cc7f5e455207c0788a695c2d7fff67352000000000000000000000000000000000a15343698b916965009f1894c8b74a790d59bc39b7f0de01095275ec002c97c66e7a6a970b4b9091cdc54abdff1cdb800000000000000000000000000000000045f084e0a7c0014e58c9988e72e1861bdb4f962ff9869d444d5ba4094178d52f9c2aa511feb6e8717098cc1f09d49eb47ee5651c127d7c8ef65ec68fcd97d1dc228bffb5bf1278aed3eef8115a5ae72000000000000000000000000000000001656928ad3ee67675951e2d2ddd6a7d9c629a3148face6d1269f79c3d0699f95350e83a6ec20aa3be78a2794c3f250160000000000000000000000000000000001b8c9e4c818774dbd2416193e795a429a22881abc94ebd9a8b42bc4d7069a9778e4bdf7270180784d914bc6be99b41c14ab6a1d0d3f87e7c9df0c14b6fd2f9d0cd755d5fce5f40bdc8174790901549b0000000000000000000000000000000013d779138ab03fafee1e4bfa2a290c4f20d2b57854a5133cf5ad7817bd32bbf2945a02b4fd5c8489e704e60ee937f962000000000000000000000000000000000aa058528a4f9bb583295ace843feac4dbce24a22ea6bf412be019f590c621bdfc7562e8dd49afcc337cab474d9abd0129b12cff5a72f27e15032844fae50e3cabbe31a69568bc4b5cfa884f62e7e2040000000000000000000000000000000014f30fdaf2f81f9d941af33d53e2d9e3162f62f47c60164e9b5ea3a5cf3a681a80b66ebfea391331c231abc4341cb94b000000000000000000000000000000001854addff23c2f53a21a6d39c72f91ef0e8d9a6d6468f319200466f78854c41be3e914bf7f966f00e185b44108af30f092c1b10d980826351c3d193a0f54a7dd78a3995efb02fe5b4525fca8791b1c4f00000000000000000000000000000000188a1934a28c7571ee94f1aa5c161be611939e52156bff158170d5e12a6480e3b9d1528082cc2e537ae1734b1847f8f8000000000000000000000000000000001728b57eca86cc8fcd9dfc65a8f5f055d51d300d8781839d744a1b81a0233221cd353f642b3507703880eb0a33afa05c8f715f35fc967837facb515ebff3df502223c29e7089fe6d2e9120bd3ecfcd120000000000000000000000000000000006c99e6c8b554d748a3526da79e8a867efde15ec50ff62e43f691748996dc087dbc538cf65820ca065f3adb5884e2f0c000000000000000000000000000000000c577c42243b95b4a613c485026306513685cce294333b72388d6968019d04214ed4bbbd5b64bce78fc380115a4b067ca9e49fcb12c0b1e9bcdbda52e9852ee0e98fa0d43f7476b3d65ef5370c9460a3000000000000000000000000000000000d7b48e69a9807c6fc867f59c894d5bbfeeeacff500a3ad4528ed4848f5ce501baf8959f822c259b712236529dff0b0a000000000000000000000000000000000e7d7932084a0416a4bafe237c923d1390dc6662e7842829ab6747024378f284af07ccde9cf80042bec56e7429ab3acd80b0d6316c5d62d41fb0399256c5c46ebe2a12eaad835d2c7177bb7325e21d3b000000000000000000000000000000000a1f74acb627d1814ef90b2d756bf76383075134c1b34dc126094238eadebd780c1ab8a3d1f4d9566dbef1c706d931920000000000000000000000000000000009bf8c2fc78b1f7af25941bf429059e9f86b34a36ff865b33e918c8435a766d897df83005c54871ad0d3e82308e368501b96434f34fa3e00ee0cfe548a2d2ca29a848cf1c52f940685caa9a227e32a61",
+ "Expected": "000000000000000000000000000000000a912d7d352bdd182a8b431672b496ecbf18276da61d6a8eb066c41783b7cf3df287796b34b165db186e815c8847b3ea0000000000000000000000000000000002881de241ed8109f544f3a6262eac1aae69de7a7e9953812eede9e63a970225646f5c441b7de80106d53cb6dbb43f10",
+ "Name": "matter_g1_multiexp_53",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018896a4d84c1ec1a20e1b0e33f159de4d82b55b6d27d863ec7cbefc2d9c180beed2285aadb34d29ceea681689dab06ce0000000000000000000000000000000013398b5f6f2c0c9095af94796572d603de02d41c599e09d3e254b326fa1575e0c6a2b7263a196c5150440daffb0d60e810e0acc22c43080ab9cea11a60866feedd57664bbe6c3f0366beff177f6631850000000000000000000000000000000015b31d591dedde69dcfe9c23df11782c090c443e505d2edfa217121a1d51b6883d782917b2a082a41ce698ecd95ba95b00000000000000000000000000000000164b18eaf53165842e50112c4a8490b8246376b58bb6c188fc929160f49cb0b68ad2f13dbeac8466fca75e6f72a398b8cab0c230c354cbf1a3c13c23a36ae5f2d5d084d7aaeb427c580cb6b9bfd9df600000000000000000000000000000000012876e247618c76af5221a50780803ab64970fea8bdeefcdc1ef4c9a160718fbaed9dc6691502433295d54d4030ee157000000000000000000000000000000000cfd8dbbeecfd176cce05ca1663930be8cf3b300a287ed053e36f64618a14850a3e813582da1f54ac7e96ff61ae57c86290608899cce4b3d25f57519cc881eb748e9ee7e27f7b21d69f5d8ab3650c3e800000000000000000000000000000000085c5db53c4abe188f44f084bf17084d3ae409b753089636d3c528162c2816b9b9ef3c0c8c05e88189407d7ca95d40f9000000000000000000000000000000000015d9ab325a8ae365f173821829aa395db9211015903c08491375f82853d9084d8aa2e35c2634a296ba14b50e34c1feb71debbd9f3be5d6e65e837bd78605d5653fe63025c320cf49c035ae66d8ff570000000000000000000000000000000014bc3ba096662dc560e88ea6b7b4363c427d038fe85a49ab8d9d63524940f26106447ad6e3d7495ca562c98b64d445880000000000000000000000000000000018bf745fde497914d81d1e3ab96630f24f6ed27ebf1208f7a46ad9fb893a3f183982c0acfc001984de34f617841524f9250f62ee2c2972e751b36d95a578efd2fa5e0a2c1e29475a3cee48a28080cb0b0000000000000000000000000000000019b15da994067a017c3040830b5e5f7eb77ce0cf0674e96b209b80c54f1307cb04799624647fd1fb990c61092682ef730000000000000000000000000000000002248d31211c2a37df59a0a4ddb0cc7880dea316519ab7baf1c614b26e2673f03b00e387fd537aee442cfc94f734aad8ad08c3d2c36085212542427c1760c72f22838be5286402ef87403f816f4fec950000000000000000000000000000000003a499813ed2a3878ffc11d27dba4d55837d1114049a72444b6db0c8a7d23a53af765d66b5017695efa39bcf7d1c97ba00000000000000000000000000000000011fb1a989afe2b093fa2ae3c0405483bb1a52c21226acbdf2a52e2e5fd5f7404776551c2deee87f431ff39dfb031d716ffa16b6fc4cc9509a2b8d8434fa0f4f38b4cb4eb1bf7f545f9f43b9190cad890000000000000000000000000000000014540330ba54d2f16a9bdec93a0b7ccd58ecb44361c67f209d36d2a42b5d5a4f9b9dce0701ad0677d6d6ca83a256e8460000000000000000000000000000000001a64d5b128c07848ec579df1d26755e5d2f70cf123013ac249a4d188b0eb56cd74cb12f7de2db69b3a0f9f4ece2c4201271d29abc5f972809461a1afa5eb186dff5e28f20311a1d8416f8d54fc4b2d90000000000000000000000000000000017783e019baea183ee5d9e1f671a23108e403a22580f5c203dd6ff72dc0adaf802d031a236e72463e0fa2c5f7c6e68b300000000000000000000000000000000132d32bae3b92b7212dd7db16c87360274a409f46199f66e572bdb21c4af24af62758978e6d01af60f5fb87481d9f4f23ce55b3b32ad29dca1a0c99771fc8f7179851995d5eac804458edede9b8dbcd00000000000000000000000000000000000a625f252a8185bea7f1b73d1c7c9b1fc7f4ea5cdd017afbe9e56e7c12d58d893ddc387b7c2870f4a975b613bef0129000000000000000000000000000000000aff6dcf60f78bc908fc4c2466270065766792a05d8629fc7f5d2b61ce4882644947fcc3600d63bd5f49fea5574616bcc6fa7aeb016b3e3f599846af83f426b9ab85b6857f901c49554d03d27a390f5c0000000000000000000000000000000008ee6e9521f32feaa034b533c0b7c749f60d84adb53d6943d3974fb4b92ce3cb3f67fbf52fff27802c893cb97e587b930000000000000000000000000000000012000b50d1c9628f822c41d56b29e21f3f496f00bcf05edb234ffda56767bb33dfae736aa9fb9a84ccb6a0e21131c5887275a8d16c02389795d54ebdcb70a39fa885320d00cd4e5aa15967916e46c6150000000000000000000000000000000014d9d3051d073d24701f01631408b7dd1d37f0855baa64a13c493c15f7acf36da116595fb3d69dc386cc611c998f9ea9000000000000000000000000000000000b33438dc1f84da6ae50b1aa76fc52f5ba0e547fb15e8f655db9e0e26d6aed15c5cc4e48412d089d1ca6fb7a550f8eecdbec9767ed2dbde21fd8f315ed6292b5b0b1bb6daf2b62665c34daed00a679cb0000000000000000000000000000000008935c4cfe2a1620a0c895feecd91ea7fdcca3bb06fa514bafee38ea5819b7372e75a106904b9c9e8af268c9f5e5a45700000000000000000000000000000000114e9944fbfc05ee1ed75603bb9b79301a1f90d3b5209ea14989fdd16f5deeb01e3474da2b4692a3e0b9625d3bf9b4b2ff634fd89223733f407c242e52f034691036c7ca69f30e6cd444c561de9ebdaf00000000000000000000000000000000105268fff23696890182b5ec307b38ee1cf28336e1c3fa28b9b697998567035323ccc91e974f63c55c928f64fabc2ca0000000000000000000000000000000000ac2f8c91fa31e2d950385509b86d512c80f0d1c73d223f71b26040d58822e4269a85e82ae390441853f8169177943aa461d349e9711fa701b92b62dd3e3569d1203b6a35ac8600367a4df9a9484bdb0000000000000000000000000000000000d5a5c94375029e5511a6c6ca40108377db43e4e0b03cceaf9fb77fac7906f71019c1a85591719bfa5d9349f1089ba0d00000000000000000000000000000000163bdfc6d40c96bd24a3b83f89037ec9e4191b533e36dc699a32c854291b0823b3f071464654eed00f08a691aa68636bcc110fd7a6ae46ef78c0e26183e707eb5e0a2944e3afc09e435d56e91584b93d0000000000000000000000000000000011654611997b772db3111d2d4edf92b83689451b1e7594a7a4bd40d85820df6a1ab090f6a1959acb322323eef27fbd86000000000000000000000000000000000b905fec9e379cfba09fd502197305ae39b48facdb01f52afbcdf159c5674234ac9723643830ab8e2639e7a0d6bd979267de5b9bee26b26b28f81d96e880a3f07dd04eb56c15314f1a789436e01adcda",
+ "Expected": "0000000000000000000000000000000004de1528d78645a4055ea348ef2618b85f8214c1dbd21ee08ad164abc02cbb2927202302dcd142c65e12934dec409e18000000000000000000000000000000000de34a6fbb73c7152f1636e5c02c75dbbc5910c763bb790d78bb56e48cbc6380bcc2ca14cc11ae139fe009135c81b243",
+ "Name": "matter_g1_multiexp_54",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000184094ad33f83f5b229643d9808f5b3b7f3e50306788f8485472405c79e57e489549c0901c3d1694b5f61f74d87afe9600000000000000000000000000000000007ec616b56868e00563d8e8bdd36de3b5d1e314be0d81c4ee97fabab1641c89cc21e70153a4d3d4e788b04ffaf07bad624ab43047c02e30ba2ec671511d06f869bf736a9866192c5f2eea6c065acea40000000000000000000000000000000017e7c08cfedb74bf88c1a80762be0e0754a86e5482c27b41240f4ffa9d014e9e8560e172519031eecccd897b869c365f00000000000000000000000000000000115ff96d404829597f16b9b97f8ff71a8eaca1a76bbcb72d53803d35335d8a8c1cea58559136f9b254c28262aa907414edfdf850c0d3e3903404fe3e0f523cd230cabc45946c4fcb6d0e5e05e388c235000000000000000000000000000000000b5450038d49c91e4e5a40a31f1f75923c7e1599695b829d9975ba7d845ab20ed5a62a7238d6a6479b2c6f9249068aed0000000000000000000000000000000013066cb8ef171bdfa11e70ddf83eb2447c4169fe38e008be5787c38b1b8a946fc474e07795765ca17fd5bcf64150fb04feb34852ce0f3b5730962023418ad6cb860716dcb526dc53e8ab6a74a6a3910b000000000000000000000000000000000f19fc0ba8a0ec5a2cdb9844002601f580e0eb9b2265c86f6efc4b633079d43461d6bf241ccbf422eb9d7c00ecca88570000000000000000000000000000000012e744ae937ff9e8e4f611fbd1c9896bd31bb1ca36b948d9be89960fee6c0cbab3264aacb916ae3596f110cc1b26bfedcf25e64093bd92a8fb394511215a3fa674db86d7329ac5ea70ec77d24d4ac58e0000000000000000000000000000000006ca09ce8c07e89e9e51e208b5d32b5ab61f0de60484d9185a26911b56a728a7473b70313fd18c893ed3453719b074450000000000000000000000000000000003d372a5477fe7fd84a58f6f2eda8f5c61aa0c357c7fc1708f7616b8cdff249e7d2910d753c2e531a278f5853fc065970b40db4f9e5c27a3208899f4f536880b97f4c69e7d889c0726d87c3fa27e097500000000000000000000000000000000152ea2fd1934c32c3c8e27a6ffb278741b899c5e296549380d019307875629d57ae44580a944babeecef73753e30c92600000000000000000000000000000000161a77844c90a6e83ed2c40c937de21fbd714a5cde60015a71bd4c960e894d3cb54a8d1e4bb4cb0a1985d4469814a991730bc7f68d8d371d0bc51d95f8a5899249b8db5cba0d21fd88ba6f86d8691659000000000000000000000000000000000a959b12e3af03cd4629f5f6f412b7084eec6aa55369e2dd2f355c93ea984ea6f2a7a01e6a10146849503d230fb08f7300000000000000000000000000000000161340908a38e4ff5373df643e3cfdc459d872b5cfd41ab34fd3297b10c37dbf3088fc23fb71f2a1751a121bcf51ee36ef06360717cfcab15be966cba2836b97deeedd20a52f88c73e2a583b64c8e5f00000000000000000000000000000000013e31a4f0cc29a5ff7f4df39db999c95eac789656bc9c6b91d0209b8a5ec2dbab698048fefb75a3dfa48066ed5743215000000000000000000000000000000001851e72741707cf96f887d13e01981f1e3db5834185eedaafdea99eeb11dcd3e90a9985f40886b60ee2a779b141bb62082b7d8b8b9345bf13d0e113b662141f5ebfc5888a5ef8ea06f7d5d137324ebef000000000000000000000000000000001501f155cf6f053631ebac7d2c57cbb101a750f98b6e11df79dbb24ec8804535b1b24942022aa64713fc60adb2017bff0000000000000000000000000000000012a08f9b1ab90531a26221b70751efa598b4046a5482c01d72f506ffbb3430d35016848755674d01e16bb78a44f8b6882396fe15751bca2c4a651445cef236a865269849908df53551802dd378b892cc0000000000000000000000000000000008fe1ea18cd8e1d2c620356430ca43782f844a2efa6a285a7c9c086e972b12735faf6237447759bd93d98b6dc7c42344000000000000000000000000000000001731f36e811c640f44adce6bb68fd71065f440eeada278ebcabfb9bf0291e551ed302c592aa4ba7e3a502cf58e3eede69a5897c9596223ca4d6628ca1f793a000aa21a739a37faa28637692b754148f80000000000000000000000000000000018e3a4176b543f2152bd7f72ca358af6226f77b5e10f3f9006c8bbe4283776ac31e6d10e838e89e8090215a133e2cc510000000000000000000000000000000000f88c3eab9ab32fc165083ba1650736e04b4e8740591f6e3ffbf684fb359fc8d82513c25a9ecf4d46faaa14d9f13a3ff20a2973faf886556e5329363bd9b9c96424fcf2e953df90bfd011ec07bc66eb0000000000000000000000000000000016fb47b4497cdcc75c0547f4234ce94f45d160e7bbe199902b2af5a5896e7d46cdc866d0fd730f568449032fc3a2df4b0000000000000000000000000000000016c2da30ef51e6728c09c3b29a7abdbb104f1a4fcc8960248b9773d2ea7f1bd161bf17203a271edfb235e8b0be437957f4ddb773155a27badba330ae5d26096f350e9ca2811feb227c4eee09d2baf32f000000000000000000000000000000001992edcbf32707e92506e5cd12662e730bc96b5f33bb88c5569fe6b266aecf63548be20b03fefaa078231b17424ac98d000000000000000000000000000000000f6179cb8878214222c2353a60e0ee210c86e306e335e929050543f084ce7c7ef56ca8444eee59856f4107e0d8cf997b52e4030b5a4bfa767ae20cdea7f464dd2dba51c9c698556d24b8f3d4d1afc82e000000000000000000000000000000000d3ff341e9b3821ac23ff7a87cc9dec3fba38ab8f2bc0f58e4c0135a9d66c6d6731ad8bb97468ca44538ca7f26fdfeea00000000000000000000000000000000053240b8429fb290453de18000ac58df56b5bf3c279e35d9cae8b350b932b0545b6c19ec7ff186c2123731d971146df1d32e0429e7934faa526475c5c7fb977c3030ed74e145eba21af2d2cc8461580f0000000000000000000000000000000004b424dab429bb3d22d18b52c4f9412a65eb7e8ec40b5e308f65fe6c0da1a1ab55a629ef8ed57adf108d146b46e6261e00000000000000000000000000000000057b7d5285194693a7ec1ed9ee3dfbe8598d9acb670baf03bf77c7799227ea788052de690e229b0d28c0a6cd79d22b0c1f700d651c67ca5b8d95fad1a8e412befdf691b074956bb8092938bda2ad2694000000000000000000000000000000000ffc202d826607947dd8f63b227a06d8c6b04848dd102da57723fe20e9b06b7c125f0ab2d2f53e14cbe95f1031624f99000000000000000000000000000000000880400b425ffe1b63214509f9acb0255d089e9de8e4eb643fa3b0383aed760f4c00babadd32f48af724a2c80a8223b383052a3bd7a13bb1ccc22b9519c7ab12d2dec67924fd9f15f96069de22e7b692",
+ "Expected": "0000000000000000000000000000000013c0b89e259f71ae41cc73ffa3c900ccea45a8a655353db6eb17a87582b00bfb971ba91d48526d934b95e9bb6a0fb5a200000000000000000000000000000000042a78ec26bc1ac4165c36d84588ca132b7366a3fb548801810da041213ee84c7e6aaf5ba02ac051cc1c5be5dfce0ea5",
+ "Name": "matter_g1_multiexp_55",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000083ddce067e21b219535e477f77ba100fb86744b1b82b4ccd0c72aac69025038e719ed173e70805c025b19bf7ba5908a000000000000000000000000000000000a9eb816ed60bbe55d4833c0e91ee73669aad116ff793d941223c17c86fea3ea434172c3214a4620d4090915cfb15d11c40774f67a651ad70f17393b386e9ea9e81682ffd78db7fbc17cc5084f3c705200000000000000000000000000000000050bdd7d98b9df55ec0ab87e757de009c804880f06be3ce13c5e051c3080df45bedad4f074812a698f50d6774cd5921b000000000000000000000000000000000a8dde7b81feef753cf16f0818f29256391276847cb832bc2940bddb329b249af4970684e95fc02e702f09a84e7737dfccf1e36e063a5fdd4b735dc18bf07703b80c6b72f987c05641612d7ce73562c0000000000000000000000000000000000d989e383d1c6e48d14332a72a8efd89260fed65a47c4baabeb0c0cd8322e26ade95b8be9f532b4813153cc39e7a9402000000000000000000000000000000000f6f7ba41c95beccbf59ca1ebb1dd43348c51de617a09ab8a2d67d3f7065d3f4699b1fc31197275e5b895f92dd106d667ea75dd2f54fa6413ba77f10a11e12abea3a4b947116e1e7c9334a0a37c396310000000000000000000000000000000013f3c3eec6fd2d4c830458cf58d5e18f0367675c47d38fd5ddce1e8be3d6ab04f71d09852b987d2db64652b3255e874d0000000000000000000000000000000009c0000761e1fe517eb32bc3da4f7a933e77db6f960f5405b64d9088776b6ee8e23743cb4a1779e8d0d93787ca029d7c6855c61bb7d72b022c16290c6d3ca9c1255cede8e0b827b43e40fbf018403978000000000000000000000000000000000c7a5bc0249717c1e39a4eea37de1b423960b409f5e0b3877e90d5278cabee197948383936739ee3f25b4bbf7f32e18900000000000000000000000000000000113d6fdda1f4b2a20d98e1d458920658c762303ee69fd7273a8830728f79be00358b3f3000927bc4d26352e5b9e6652b7fa8503101f392a6c6c27300b6992af3fcc48d47f73db67615a44de883770d4f00000000000000000000000000000000108fb7a97ce429fc3ba1ca54ae841309e2ccce748dca953cb7dd9dee3ad9d919e3f8ab635b294b94b939cd80d3435b5e0000000000000000000000000000000003af838ba4ec485ec2a17e6f592fd832d05133952f273d1b472800b210c96cc503caadc17b38d3d1e978606786d9ffcddd947617bcb7ca1c8fda0d49e6d950a84d60230bc2411d42ac32e3651f48524b0000000000000000000000000000000004cef28329ccf221ad7ab2b851e869bd433116753e0d8bf38d22ca46fbdc71fd9d96aeb9c0df69c47905a99c96fef0aa0000000000000000000000000000000012ef5c40d8b6469d9f3921eaa99446fe494a55994551fd1996c453a4e5cb4a2cbabe20671ff51639710a5e45a57271aab4cbbc6d537ed2b69c2c32c84f3cea3d2db180b64861859368e98aca32bceea6000000000000000000000000000000000c81313e8b5689935fc01b5f999de2fbe9852bdccf484edd0771e8427f2a194e29d0af09db1152fcd91c8f7b665f6929000000000000000000000000000000000f37dc7f87b8de48441861ce0c88b1a24f22aef2c321ddbf385cedec7810c20c7fee3d2c5a04b5390a5fc24612e4b3e9457bcb8c44a2d9d1facb39ba7ec8ede5d5962b3256d9fc2e68a1ee5a733ccbd10000000000000000000000000000000004ebf9f75e92ec4fb7168bf71215c9ea8ec17dd9ab392c9810316a30a33b4ace8d93ab75356baaeb51a7f47b4370915d000000000000000000000000000000001307c68414b73db43bcd9062580f7c814c3c34545ad5d943685ed8df26acd457823ed628e4b215875a9008a406fadb5619f254dbf75f1c42046343b0060e71302bf6c94ca2fb8aec74fe7a47a3c9c3ff000000000000000000000000000000000cb5860f081e314d4fa3bf70a5eb18d6fb7f5257a708f1b1726b539115050754724ffd6a34d3b5c95359f40f41f2390e000000000000000000000000000000000c392d8603c2ef93d2765d98c695dbda8e4b64ed90c4771a4e69fa00a77d788981132336f870a3a93765902fd8fe8763f08cf27a47d89ae6e2ffb27870d613b9ae586857e4ea00670944a2883ba325af0000000000000000000000000000000011c802516f42e267c0f9db096fdfff77d676eb301ef1ad440b6c2129c5b5722c420f6e479443cbf43d48803f7e32d8470000000000000000000000000000000004a5ef232d3582724c3eda67cf2e69b26ce44bd927555359820efc3fc67912df560edfc4d119c5595e1ab1fd7e2a262f50aa333bb6b44086fe6211e89cb70b8467eccc228c09aaa1d589cfc24771a11b000000000000000000000000000000000eef1e6400dbda287910c117ba17eee1137377e262f7f5cf13710b521bd26eca2aa9731b0a1cf182a0d57a329369125400000000000000000000000000000000188e925365fe7cb96875e85f711d8ce233cadbcdd4c892eac52d9c77f98082662410db4cb6b24889b21f162eecd10f42d9f7f74a5ccbd01afd985d3259739023cd012cd67fba3a4ab5597e94d8fad434000000000000000000000000000000001307849ed4d685815c670477ac54826e94465aed0b70df9683d09ddc62597e7a0a7a4b2839fbec735eeba08bbd3e821c0000000000000000000000000000000005dd74ee1018ff2280c3dd8faec3c97bbd00bbb7cfbcb849bb003b590a999b6bb3a973ec96bd9d825206eb353086283485c00be7e66e318bed8e66cc41e7fd0593004bbca20f0dbc28efe4441acfc9ae000000000000000000000000000000000458181a1019a65c34835eeca4898b88b0351da7422bb5982616c90740e8773b5a03272646f26c3a5801c6c16be33ec900000000000000000000000000000000101c2091a08179eb0be41e20a545f5b53b8ee39365dc9b57f12d75b2beebdad488d63e857ba5187c8f92af447f72896ebacef63d90ad11bbdf0c5fa2db2838c238ad3049a3f47b7f67361825efbc6526000000000000000000000000000000000cb8c637a9b8f053d5104b582ca03ecba768425c639fef23c4b624f31523e0ac669183639991728135474ca19e0335160000000000000000000000000000000009e0798589417cff12eef14f00e415c51c30fc26461e92c4e3fb4a5ab1a653ae791f05f4cde0cfe2132c377175cec1c2473fa3d16e6431da14b8639d4fe316692db087a167a2c4f07307e770bb9e35ae0000000000000000000000000000000008400ba7dce60413ff085c0904066b8e9e9ae290781132e739a5a8c7bcbda322fe1c8d0fdb0e9b0abe44ff99d4ca22ee0000000000000000000000000000000008b54feb64f59541ba3b7c6f86d24b69fa30ba057db890cc6d958e3a7de8bd379257c90a413050f7789ded9ee7b28bbd2774741f87af1d6942dc4ed79b70b2d706f3db6b6d083eef0475334ef1e2410a",
+ "Expected": "0000000000000000000000000000000017377baed9953cc7fe1868baa9e2f6c87edfab1700bd1f60e2644bb97cbe2dd1fe031a986fde6555930d4c464399f1f6000000000000000000000000000000000ff69a282658b49c270e829b326502d83a82dade820de50764a7df957e94e7c0a1f0e3d9084b45d9a875134bedc4a0bf",
+ "Name": "matter_g1_multiexp_56",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000d1de82c29aaa76b17079b2e1000005bf37df08de2c5ba7a0f9a14870e0ac327f46f59a116c72db57cf5110aeed6c76000000000000000000000000000000000a8ff0afd1cd7f541775567134a889d82727e893e4f57d1b5981fabd4bbff59dd3d3995a181efc9b5fc078eb3d4cd0e7d10ffdd3797ad13e65a1115cab6529d0f87b91eb41d6265e694eed8f026672140000000000000000000000000000000018120f0d0dc908dce4adbe50b24b66ce12e710fd35e5a8a8c357dd80c078d6854f20b12d40279b9d6a895460d8989cda00000000000000000000000000000000064f4e282ec5cac74e1a12f678391730663c83afcc0b415fd21475875762de2224e389d607cba84788a16d622d2ef5c13e5da5568a9427e0cbd7973a34c147ac2f3577d06f68280caecf8588ebf1591a000000000000000000000000000000000dae339b418871e2f31ed380824412acbe44e6c73ede9b4c52c054924297aaee1f7da749374d7ca44b138acb85dc182f00000000000000000000000000000000155cfb670ac94e7d5a095d2797cbbb5b8ad3e037fd246246f8e8c2278f5d4e53a773e6518ebc3ea5aeec6383d6fbb62c145b5f1f156f3c823cc129568e7602694107608c1f9545edaa897df58d27b18f000000000000000000000000000000000c1f7aeb05294c1b496de11f743c0c7aa4255211e1e36389bc93dc8d0e73fdb9af7bfbcef2c196a95d1d449b9983b2020000000000000000000000000000000011251668e9edb38ad147f22cbab7d280d436d11039d9fb823a19dffedf2c6a484f112560623cde7e5525c85b4f5d06accf6760be82cefac2843265be5fc0fd6d308c1ed06fc684c4693de25372f09ed0000000000000000000000000000000000ad488f5b9934adcdc834558c8db1d62574e1ffcd03da30eed865042abae4dc03d69010e7e591d9f0a8e421d22cab23a0000000000000000000000000000000002cb0a8e0713dd3c4833af74767ce46aca6c1efdfe75d09a50fce4df2eee3fbc031357691e23ceee810d30004d03f6b9d9fca4d166149ac9e6159ce95a06f790a96243662373637f0c6a59764b77b45e000000000000000000000000000000000465d95750a3c688f560ab9ca6fd1f77457592a0d5f54c17904a222010444d048df2be3dd402f046b1375d75de446d2500000000000000000000000000000000166289d948aa518167e72591a011b3f5ce209bd32ce091543bbdee1e8776269347ed711e1e9f1193f818e3045761a75141733039312347a0c9d760c1bb9a1209a34a02b359a9c52a57eddced157586700000000000000000000000000000000012abc4f1c56f9ac3760acec3d79b77e9ac71bbfe4d2a90cf43da3607c99035e550a4d0fda734bcfcb16ad08f773535d400000000000000000000000000000000030953a6099532f7ac352eff43569914c3f8d736b8aca89f778b4a67c754ada78e121dff664feb751532a41c8081380eb21b18d883ef62084ce4bd353d7434d7e220e9cf6bd0e8d0bed1ad0a4ad94c7e000000000000000000000000000000000138cb559d92b392e94cdd8666605cb5b05e585dccfc023bb6f1abe82fad35c108fca7a41afa49a801700dd8ef89eb3b0000000000000000000000000000000018cf89ad3e05492ac8699ba0723d5ce43e81b0166fc33653c967da921faef37f3ee2e8e3f71f983774966ca183e05f9eeafb6aa11296facbc13936bd2ba09a2cf9bbd9dab6ec8cc5f73d78c90b471a3000000000000000000000000000000000129c48a05e3d6bfab6e6f5200fbb90fbb743b045509b129e3622929712939c5d15126a09f1a650489c8afde7ace8baea000000000000000000000000000000000abff3803d605dbd63bb8453e304335a943bebd224d2d8067d76f5591cc6a2b954b9156a243b0c23d08424fb9edb52383d39a61323c07f9f4656a6c5e6ba139da8175ebfb8a641de50cfa2290884662900000000000000000000000000000000194e6f217b863339824d95c77253ddef4ab97d9744d10392d399b1f165170bb8c13ef1b7cbd995c1c1dc2a9d1b87f0da0000000000000000000000000000000019fbdffa8df167a5e891d09aa1e79049d377014e58523c0eb453f5f072a468809dca8ce0aa22b45bad4f8853d985be1df6374d0849a4471eca96c5e715b10505c4c49664f341d04705fc688c8479cda40000000000000000000000000000000006f0b72c2a934e430e4b773a61317007f1ef02c5f978b3565d623b6590b6cfec22f98b49f9d7f7efcc6913c139fb27a60000000000000000000000000000000018ea7df5f807d4c4981a9159d73d83ea84359d6aa00a5ef019b0dc307d096676c0d16c6b167fc55e14329a858c044c5c0b7cb52b99abe10d1367f8d3def38221c18657a1114ceaa1c0673ab13a6e108700000000000000000000000000000000130fae66f6b4e1a9b0b39906fac847f1285a7d37bdb0d3ddc2c2bfcc6320ccbad2ef1f119f2663e3a45dbff005a469a10000000000000000000000000000000019ba2ae0c371256e4c3dd6f9ae2568386d3a8bd90a57ff982294eae9194494add18958dd516ca9dda6a0b334391cc211f49b1fa80a321d4d100069b2c4b94cbda255d8e9f1a7f14ddf4762b76e4a386f000000000000000000000000000000001152651000a16809ec599f2fe9f330b0782685f6302254450884f0ee61ee2dc2cc9211f69d5d9dbcd7fe3345542a0159000000000000000000000000000000000b5c017e7ef71eb089188ed85331815b40c37abb6ff73d76f40fd8dcc6d2120c6a52df0da042b2b63dfd0da7db2bbca9ad3625b0839cc1ab8c9798b2e9706ba6d7aa623f3c0ce0985bccb2ee5c05a3130000000000000000000000000000000003a6f178d8c63765b2c8df834ebf7e96a4f451c6e05692f96b71c8be2a6e9af17a5cfd8b263eaa254592ea9a898488bf00000000000000000000000000000000185537df1a10c4c12fbcff08de45b349a90b0cc8cd17827df87abe160e84b661d58a1fd03c669015b991225ba08e171e150e53fb45ba8ce5ca917010f26451220be51141fe21cfc1cc06a5557e8e7afc00000000000000000000000000000000085475c2fd70cb7caaaa7c5c1fb17e2346903a962fa68536240d041f2f8cd3a7b83aa79a77f713bc31f7becd347d18d7000000000000000000000000000000000c98414bc318b350113186db9e965a238f1f181b00a2265638d914d263e4a71ff643907ed8dca814e5b8d5713baa8dc9d69ec73df67feb970f1c7a3880ee84d948eab4d8672a6c1481d61efc6cd7100200000000000000000000000000000000001064b94e868fa82c892dd244c6247063a276cc651e22d09695ac6e73d20bb801a189e8fcef8a711ed471fa3b2c7d19000000000000000000000000000000001561503962d7314fe41f7b2d34eadcc985fa748cc98479a06749692a00a46fb2fe5b5a68f7001a0f89f20f7f42f4463c38f8acba4782dfbc02a14d4b1d7b2b0a582f9bd75642169707a475b1a7d2d7e0",
+ "Expected": "0000000000000000000000000000000003e62892118f11065ebc66c58c86e2f0d3c79541aca8db33bd0e12f034f0e106a76f0aecd537539cf2d793cf823ebbbe000000000000000000000000000000000067e42ecf23e1b0590c30106b0720c806ca71fca0601b499025b58f137ff22aabdc6cc5eeef232fc9a20fb9c2bdee16",
+ "Name": "matter_g1_multiexp_57",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000184a661b34e18b637bca53ba60c891da69fe743d5336d92e811649094c15ecf2445736d0c1577bba4eb729aa7204b44f00000000000000000000000000000000129a348f7fa726585badc23f5dabf49ae095d300056b219bce0ce15f1f6a9fc5c8ebaae56362c3501af3f3de19515143cacfb05e5d10c41b06a487e9f8afa38759eeb55f0a5bc8640164bbb081c1fd2a000000000000000000000000000000000badd515b1e0959e77e0f00c7420b46bda5fcb6db59cbd431a1b0ca68c291c6dfe89ece299434f83a980613fe73ab7d3000000000000000000000000000000001266343ad330fcb2cc8242e30a8085cf6995ebd810780115ef881516d4227c6051564d7343e4a5d6bfd210e2e40b91069a0b88d946231cc484550a87a548719f0a543c0698411f230a966cf602dc4de300000000000000000000000000000000085e7c22d51db0a45d8db7d5365de9541eb87b81c237fc47cd25c297da4435b4c9b8212c76c929b7c8f32e8d9b11374c000000000000000000000000000000000a4b0f905b48145f1831e453d0372b7861f7be6e413182153cf77d737450a58f378652255cb4516a482d166233dc88c574e3b5ff944bbbbf808f1f469a3380ee7dc37ebecdd8fcdbbd2f2561e0dcd68e00000000000000000000000000000000086b97f87625356425a79db717f940debc7a7e932370ea315d1f94b1ead853e3ab6edea6302b6b5b0eb4e4bb3c7fd14e000000000000000000000000000000000fde70203ac7a82901250e9798ef1c671f8d5f878fa3bc83556437b9b98e77f7fe7d3a0f31b8cf05ff6332df0424136fc23064970a4ae4ae648a79edb193d98208418d3489e9b5b8517ebe99cc32b4d7000000000000000000000000000000000e629b2d9a57bf96cdc6871ee7dd7675257cf62dd10028201448d8e5b1c0abe777190a868fee83ff5d067252312e82dc0000000000000000000000000000000002102d461c9522542acc185349ea93810c3e2412ebb427f8556b947efe198d616fe00818bedc22765f697507d7678dad972fb60ccab83b6ce042c09ead82fea3d2cb891e21ddc5af7b5d8e334d5a32640000000000000000000000000000000015727f52d46099c0ba041be660ca312204afb0f927fdcf0f1afa4cd3448cf3e9fb76bce7ce0da8b4c0048f76f0e7b1410000000000000000000000000000000009dc4e213faf0a8216061b59dd35a135b364431e2be37e42d065a42fc8e42eb8669d32a5f5ecdfd9234487479543471bdb68c389b94c82f006fdc637696d8085b24897177d2992f504d4bcf5ff04d173000000000000000000000000000000000afb691289f877e1de6fbeb38cee0e36fabf3daf904256d5d6db6e96ce555a9304219bad41400ab6278727e5fe2faffa00000000000000000000000000000000165a54d6db7332b12224d59d8b677517190744c039d9bb401c2e3c4437dbf230b67308fa2d5ae2bf5de282c9ae38a3fa4510c100005f2306f4b474d3843b4a79d04f0171afc5c66df70f631b0481dd3300000000000000000000000000000000032dbd300fa383541e5c40c849addae3def5a4f5392c44b9e96981dbcedd02252f9bfe4100de9954ab34fae9b2ec21ce00000000000000000000000000000000185e62adc2a44462019c86028c617ddf59a6b1c16071624de5ca755f936e73c47cba00f552d2d79baf60a1796dee009edc682a2be4d67852d119795988c52230d8273648cc176ddc012a4b4da5a8636b0000000000000000000000000000000008a574ccaa24ef76112a25b990b5d3b462ff9c43589c9efbb617b45a87bc26eca6dfc6c9e58a12650c202a06d3c86fe60000000000000000000000000000000011f41e39dc0f0bdde1b9e1879741824b20d9237dd7b462272115e8ed44a1e6b7bf82e8ae481204dd8662418fadc63bbf8af6b200fc8e6a57a954226d9a0254c8bcbbc55fd6c3db5cf8532323d4c50b4b000000000000000000000000000000000efa7f183cdfcb25cc5516bdb45c409581b6f2a5bd8ce8092dbf9050a20b2ff57c6add39e96a6f1c8d2134a5a37778c7000000000000000000000000000000000a8213977e8512648b6aeafff2cefcd17a14a052791d20236a78e0b462dcac81db74f1625e787540d7dc279846983f647e2036f73e8cd5e42ad86914e192dd969465aed0c3b752986b84a0c2444c90b8000000000000000000000000000000000287e0add9dcf33f37a10a5ee89cef5240313af0bf0dc183d0c3d6b919c88b979c932c7f141ec5faf012a7f33fe56fa4000000000000000000000000000000001313f591d1da8f6baff044857d2c04f01935b493f5b951cd3538054756d33a52f71be92ef908f016c133aafeb9b9ad2470cd5c1545e76027c389645da1089fa88f675b5b6ef9217b584d7202b797f85200000000000000000000000000000000192d02ab0a323e85e9fa6f553eaafe0d8ca2de63f0fec8139e24805f0785cc85b39908756ab4eb39354ecd8d9440d5260000000000000000000000000000000013997cf706bc8d40b019c2dacf6a7d269e0ffdf8bbc1b4b39e75b48ca5e5e6eba0007b8c55b59530b34b7ebb4c657c57244041bcfc21ede8023ad80b6d4af4b2777c0204ca5f61854e6da34ff5e1145f000000000000000000000000000000000a61b3cc7913e45c132cfb06a26fdb1882bd700b32361572fc79a3d2c432644392f341cc70905b86cad2ce52c30e2ace0000000000000000000000000000000011bb3d958600993ec04d9f98ea3f29df0dacbfe6557b36bed865c564595a64132e4036b6240c97cdb38a60533d5a08baad7572da641373708bef008057aa5af1cc76ccb882bacc50a77b37d7047b1bf30000000000000000000000000000000003d2bc11fa699b284b37d1b45c8dd6b41436a7b2fa09cef316821516801afaa4e1282d717d4eb3d46e54c0208548dd9100000000000000000000000000000000123f8cdf2bcd7d6eab31975ddd610afa79c3c95fed2a6348fa6872b74a6e2816509c71f11d1f272dddb59bafc0f48fc454b51c78093cafcb57c4c1f172d08257c379a9caeb5b5478cacb4887119a08c6000000000000000000000000000000000982c1cbcc39867c7c8c4512392af1489a5e6aa01ecf56abf4cd9050a33536feeb1866421958b929096d2c3f6923891700000000000000000000000000000000104ba4defb74b35d15db80df1f4029650f00b306d702b5934c1705d226886d4bd22b6c88e71b862109f8dceacde3c6d2ae3bbf55186a89740af4da6c073d8c0e331542a2c972a49dd3bf65261dda6e490000000000000000000000000000000006e5fc17bdc786eef8cf2140bd8002ea859619d319126fcc5053be9c28526e14e0bc8eb924fa242305069226d766f71c0000000000000000000000000000000017ee60b0dc932806dfefdff2cdf00efc4d5c81a1e84ce48a25db1d49ca26232d4e4cc1f37b34c80375597587dc183b4259b43915b15c509ab8930979312dea2ec9cfa9f679b004ee526aa5dbb25759a4",
+ "Expected": "000000000000000000000000000000000c3dbdef90052dd5bdb70f15963091c8fccb5b8720a16140ec96dda18eb6cf003b6f5f7c244d25cf6da34f2a1703a9d800000000000000000000000000000000187456c5af42c3de3d5e08936e8a3f411fd6458d017ec508e48f2b634319155428733634e22883492d7612b2bc38158c",
+ "Name": "matter_g1_multiexp_58",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005a912b6b2b00c2b2c90ab1aef8c9240831ea9ff2ac3a92753054f159f5ee4eadab8ef57eb5972e3169ff9649b886daa000000000000000000000000000000000981b901734dfb3b5f63bcff802536492664ac13dc695960ad89342ea865ac67d00da7130833126a33573d55a9baf128a53d5989b63ee5f157cc44c684ccc7cb4c74338b12fbfb534ea33db341fa6b46000000000000000000000000000000000b052881b3e27d232ec980dd99bd0ece4e861cecff2496472caffd741f2954718d605de98d9c27dd3ff473ff12b238400000000000000000000000000000000004de4bb9e5a4cef93662cee72259b88f7ccf8a495b733e868d76cc25e04c53a65a83c853c98a25f7a551641d54ecd9534d840680013af06920dd06bacc0ce95cf0cf79e8ccc0b10027f2d28c1d0049980000000000000000000000000000000016e4d257db25c08a68943e6e0065b375422fc817539d2874279e2b41428da449627e6e04087fd448f651a23fb01816ba000000000000000000000000000000000e80d041b65789b3289a94848ca4b1109028c9fb314e652486e650221945ef4224ca03a693e062b06036898eb664fc211b67d661ebc9008669bb4e5cffef81a32baabd71667a72f1d202ced823f09c74000000000000000000000000000000000542fcc8d668a827daf3726bd71d7ddeabc440a6fd0c08a4730803be6e76613cc0265252c41123146a5d7aeae93f485f00000000000000000000000000000000109a61920ccf34a0a71f51f4fe7c882b3d6fe449a8c67711dda64f9eb684b4a28cce6e8bfcd6f3cb599adbd0771a132dee495199ebdebda02179432d42d5d9c76eead4d4993cd09a93d46cac997716a50000000000000000000000000000000000a65c746a1206b1250598823b9b6fe5df3dfbee21cd31000e50140893875d1ad9fcd4fe12bce0758544ad8cb4cf5ba700000000000000000000000000000000038c25d3c35fb34151428d2f6bb8a459f834902334d195da214ee9fae4bc6099d225588a001f8fddacadeff0d3d215463e038e473d6f965751ebc5f69eea6f37be88cf001de0c4e4b700823d8326f17500000000000000000000000000000000158f2288a667f475c736dce9e404ed37b18d677f984b6d9dafb051b87901e6fc60289161bfcfa46a3fdbea7b4cc3f795000000000000000000000000000000000d7faf96c636ee38347b0046d333e72d601e20b018d554d50ed63e30c62db7fa20e29b3ea57b1f31e0d7544ad711c96aab2af2590309c9b9177e4f6f0fa06339fa720cf1c9fc7c001785d7145a3c9030000000000000000000000000000000001933815ab2d8b6cef8790f87dd9750bc2b7a75a9d6c425a3e84cd109f5f5ea866e171dfc212f6f8641252e9421fe3aaa000000000000000000000000000000000f8ba799ca5dd885046a4ffce1d26688d0bc6936f3a5a943dd54f89d991500908c81ec4f9b116e73f74d46b67731421bc9551f12084ad7d4ce346f841fef785d644821b5c2d3c8db3145fc26e65666bc000000000000000000000000000000000d4ba404254175cdf5c47c08ec158ad83b6ff5b8dd32b8cb9753fa157726271f343cc0cf5231e7e31583877d2591930000000000000000000000000000000000191f45fc4b8c94519d13ab28e5f84e22dae2f82550b44be737728a695865973ff5060a639e3f03904d74717963dcd764ef5823541696ecb88d0c71e00a15282c40d4826220a202be09c47fd6891b93ba0000000000000000000000000000000014d348b7dbace24bfcb258c853b19fcc1637d7ed9b0ec00d4124cdf6d608c6849e8d2f9858afa83ff356380afa1376fe0000000000000000000000000000000008c509beae3cc22f0da64bccd2e0387c05d7613460942d25182605b3eae6ce052540142d5975733cb6554e6da9f473b6e32d695dd02323d40ac1eb9452cc53376ef941237563b1ee380c9824a565008d000000000000000000000000000000000ef9aac66681015bdd9bf287caff9aee89225e30a7976e9f503a1712fa863c8d6d46a80952a1d94d96a5e0496f64ce5b0000000000000000000000000000000016c66018f43bf585195b256ca106f47077f977701d97f42564223817ade0a520aa3d7f06d868f1e91705232b1d2440d9f5e23ff8acf88d18e53bb31476f10fef288e20e818431f9f0d2ffe1265e8ea8200000000000000000000000000000000042d1d00a946085dc6329e852342573db7dda7385e6a50a2660a924ed6202968e787559fc58a162a775bcb115bf1fcf800000000000000000000000000000000162b52027b08b7d91fe0814c7be69414121cfd452f4d0407a2300bdfe9ba81a4561af74d8067e929b71a92947eac4fce71927817449ba5f053d0ed1e567b53b1179c6b62a554c8be6764d7ce203f74e4000000000000000000000000000000001598949030cc21d76a9c69305f023bad3cc761d5f857bbccec4de6b0f7557395efb2d126382731aca994a5020039acf5000000000000000000000000000000000dbea8852edc6bef41dd317e7d70eb2a5416d5087ec5207af3f5b3fec39a416dd9ccf4cfb5400cca152f173e66df05f75ce5d6f0e44a20d0a0e2f1cc523455b001dbeef772d84b2599daec66b285027f00000000000000000000000000000000081e898b02838558c1c9d7ef9f86fefe512e2e7364ad824506c886b4cbe947657c5480353e4f72e237da013d81e5eeb10000000000000000000000000000000005353bf2dafb1b9b4f2cf58e16645aa3fb759eef6eb8f516db068d2768851e7724fda5cb85241aee62b4404de2862dfbd37f7bca1a59f65982294755ddf8af7f1c953b6e482fee854e0d89e9b269e0e900000000000000000000000000000000028453aa48ad0302804f9cac568467668b1dc0dce2cbbaf280810ead2c0a94e156420f4fd2566ee7f629e57c3741b8960000000000000000000000000000000001cfc5ed80924f7088ce6a5414372d13fd8f6eb3dd83c66d8b8e4dd1d4db2bbbbbc6ffac00e3a880d8a8fb5dc07fb23f06d0535e3728b9e358d9ea82df4f1137db7a02f79c0cd0dd672e24092bf7f6b4000000000000000000000000000000000a236833fafc3da813b95f4562804361aaabcd8166780a4646734e4b65e3a1924c075d402404b52adda4902bac7a2cbe000000000000000000000000000000000def6beaad6a180998c4c70f9a8dd0d948a79524b31fa44874908058e9e58caec2e23d5a0787f1ca05a359ca276c840ff56d6810620e8da932c202628c2fa9f0a9f3fda3aa07c262924aa51685d2c9af00000000000000000000000000000000188bb3e69bdf0a5f31ad16751a12c767c86df80f53f6688ad74cb2fb32b81bbf9d60be1182ea1b6c0d6fd12ef73e253e00000000000000000000000000000000139ce5ffa569548f1bb877c3d573136a8eb12e7c69cd21a70526f8724bc67e0b37cf7149dac3f78377ae7d5bf4882a6771e7f672ad398f5c02c989b475d12ce86e6e242d36784308e56178f2a6a1517c",
+ "Expected": "0000000000000000000000000000000006e5af407ada013abf1451bc9d5c08e5ba9cddebff0cb77175b152fc19bbdc48e1498673ae4698dc74d039a671ecdcd9000000000000000000000000000000000c8783b3ce25445209b9f1d8bd3ba539c01d230c07c4fdff38ec902467d5f7e9e8e660d8997939684e119fdfcc963836",
+ "Name": "matter_g1_multiexp_59",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001731f73d2ef1f87fe1752c9d6428de241ba71506c76f31aa9697d1c436af51de363405f60110e8e69ab268280c20f92d0000000000000000000000000000000001ec6ede05f60685e39acc7e105f60602f0fa3c4a6da7342da755eb34aeaa5adbbac4c13197a2c93314ec79f5da8b90177f9a79850b2fd5a281b22f52de085f12bd34e56808496e1c1388804f534d2da00000000000000000000000000000000158d295d41540fb1a27d8200ddf51fbb9d31a70fcb639c42b7fafae4a95b90ab1ca777125092aefe20f856e3291e528d0000000000000000000000000000000019670ff04a77cfd367c5f0c14218b5d95ea2eae8577da10f27d96e58039b7dd7e9f7f75c32f99dae0920509733ff9c96630c1fdad9338fa5236f817bada168a737dd3685b327fb59d8a37329920af4cb00000000000000000000000000000000052f8e8098f9e83eaaec1c2638aad30b043c2359f2551a02b2b95816e1c55d37bbfa6e284f280f15dc174d5f03a7698400000000000000000000000000000000034bc698f07544952274c21f416d8f1281ccdcf6bf53ad352afb15a3412879a10b37e6b8b9fc5f46ad715f9ce7b46e3d0969599bed4899c3c47e1d4081027203c73233536cc6e45aaa78a4f1150a5162000000000000000000000000000000000c2e014d5068adce3049cc326d36ef92f294700ab64bfe170260727117f098727cef2e28dc10fe473a46c98867c618400000000000000000000000000000000005b3ea9c12179a47f7e69690f3303ccae614e06878189b40264f02e9bb26284dde846d704121340723bfd1fe5696410dddd438de35651328de7183dd38820ea2983488ba31d401094e59cacfcd1d031900000000000000000000000000000000119e9fe8723883d9ae8c61efdd3ae961795d79409750dd39aa6f0f8727ca2429856f977697c4f81894061da278a0f9a9000000000000000000000000000000001438a4dca0c786062aa9cb21e26b87e92f90dcc0bfa014f654b1734cf7cdb8a2e62fd3836a802a9917539dd068c6b4b1191f2b2cc76d848e456d07c84c0826a8861981dc84bdc671bc9b5882d387a41a00000000000000000000000000000000012872f4dca3a9f3fcb07d67c76836c23eba3f7957bb77950a4b43ad9c7ee54f53187a742b13e026f8234df9e91659c400000000000000000000000000000000078b9d597bd9b5ed2f7e0d5f8e4a518012591b855c5352fa1450704a33c3cbd5695a0f8da235411aa99aada88086f643aa76094782d0c06f2080d699b81aa04a60891046e0053d2fa757c7029df8f8480000000000000000000000000000000006c414c6611e00c6e98b370bacf2ffbd7ebeae890278a0e951d6aff7dd3e5fb90f82b4e65dd007a3289f97a9600786a9000000000000000000000000000000000cae4750f99ba13f03d3e0769cccc879a4832210d6a2f25b2696099c0cb184398b7d432e801d23200166a4c53a3e70f3049a751a406657dacceb3721461417571a0104e11c1e00805becf71ee77eadf100000000000000000000000000000000122f404ddd6b34938d8e57d9d6ee78c3fdc1b771dd7392944ae88c625f81df63915a87ac63dbb69adf8fdf856a92bffd00000000000000000000000000000000197c20bf1392d4d68efc6ac3bd5d8b53b360e305a501dcfc2e350e3738503ebd44a574e478757240236762db2f23d4310502d56084d1be7179fb735e233978a5a3c2756d780cc0ea6a8aa92b1d1f7c4f0000000000000000000000000000000019195a36dfc449c19b172ec061b4825e4de85fd5b9c633c953ba7a5617973e61abd0de3d59d441f49264a0dd2e781b20000000000000000000000000000000001430f743ee98a2b2f37d9ecf2a7d4dd4963707fd4cd6ccfdff55c3eb189aba2fb295877bc2d3db9032af26eff6485e459787a6720b8db1b4f0e1d535833ed20b519a0e4d2e9fef75022aafef52371375000000000000000000000000000000000be5d90e5fa172a2034667160f635ffc190fa495aa9af51b648125c29bcf9b4b31fea7a7e4b49d91b4a8d081c9aa2d3d000000000000000000000000000000001721ebb02265f698528ae1bdc5bd4500d7612bcab9ea939f552ffd8e9dec1d267dfd25ad4d3531676e2ecde3d2170c4810b47b662e8cc8dd005bdc81dc6d98d0eb98f86b46c0c8f24481af9120e84a820000000000000000000000000000000012b7607bd9f1701ed002b6f72b2e832dad7c9b2bb6eb6368fbe78c48bdfa17b2546574d7876425cca7986fa6839b6da2000000000000000000000000000000001975f41ed7cf252a658e80634872ac495e4b518349487930610906bd396f7fe4af3c97acd0ed3b3f265917560b13e6ef072460e3c5349c8fec9944dc99762625262e84c70f10d0a92077a351335127470000000000000000000000000000000014ddf2cedfda66e12e999d0b280883c546e00dddc0bd17817d6df90b7a614c472cb2840b133eabdc7be39b63e50cd9ae000000000000000000000000000000000b86e0559e27a6061aafc091f93b744a8273032f0e8b1c8b7071baf3ac7008a8173b71f51b27efccba27cb018b25257ff3177c4d865caebf1ef6565bc85e0b0bd51365a6f321e26b97cce887bc3f44d60000000000000000000000000000000010f691744e7094b801c180810b24f6a29c21a13514bcaa6303ae49067bdd001213f13c6f980c51b050a684b525c2dabe000000000000000000000000000000000e4e4cc3769cd3e0e458ded43b5c7c481c17efd3283972919212b877c21aa7abd31cf86ee2bdfd3cf0ef6d730c0907db393654ef7ad8687c8878c55a8240ae9df04805d3e2f194e960d5e498ae3ca177000000000000000000000000000000000b5e86c2be33255bf6f2f2aa8b17109467543168c0bb92a9ce19bb64c5f84188b2e9f93ac85d948c76989d9d4dc9eafc000000000000000000000000000000000c5244fe670dcb16d7994b7db8f933ff98744e5c6dc124e057c05d2697881115a99f983be480e30ae3e0ce75081b261edb9f942124a381b150f00a59e4579d0a2b7b728f62715633288fd03d01dd12dd000000000000000000000000000000000df7f56643536b20f65cae1ce4c67c6bb6def8c9b514d6edc92673ae743a2f4e4906aaf7e3b048f88f08a4f5c9f85c8000000000000000000000000000000000176cd183f547a3f38a86d604f8e76261755f72e7222f3734a456a3bf7029590848970e8836b3570e9a4f3500e54fa3008e6eb65778a328cf899f66581ac7a4a89e0e824c15573bc68c02cdaad89cdf240000000000000000000000000000000003737e58505d0f4c6890c7e03d5f252aa682c110f5bf5dfe8bcee9393104393f4a6a22c34c773e1dcb78881a31b33a71000000000000000000000000000000001988ab3430de7a463dcc2156db572c43b68e58ac2ee26f1ee1bf8e9889f6cd3250e5d7f9464a8eabb127306af39c13140940e3620c59504062e4e98b5d4c8cbccdb017c47a094d06253743c29465731c",
+ "Expected": "000000000000000000000000000000000d541103aa046ef53761e929d50c88796b90b3284668a2a75ecd461ade103f086fc443a3681b6440e6b8a8b9558870f20000000000000000000000000000000014120e26b160a37f8e18faf541bb863ebb425fbd0eb072268a12657b6e5ff62d4c0e504691b3d09b710741820f747b85",
+ "Name": "matter_g1_multiexp_60",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015c91ab58aad72af3364a3d05e2893c756a273b2c731ef421c0552dffcb32fdc4296bb79afcae2d3c8aec6e0dcd27c17000000000000000000000000000000001901b4fec7a1324a34fe403dcc51656145fcbeb4eac94f955f4fcc5ad6a016eaa436878e85dcebd8992e1a177c5bdbf80f2f697ef6783390724e04b81d0e18dde6533eea9f72c1e10bc72c7b954659660000000000000000000000000000000016df7578f74b1ccdfd537a074d71f2dbdd581f1a2f78875a7d4e1c3cb772aad0d02bf4935f7b08aa5163e82e5a747bdb00000000000000000000000000000000053931dd0624377808705d3fc6e12c4894414c8f6a5662ffd71251bc7725e6d23b7781286b8be1e35eb615bb1efeee9c34680b934e67bd7518f0d6a3a809dc7faf845eb71d0247291d61053d5cbe0ba200000000000000000000000000000000056f0c5d78c5d4e97fcc7d6c3132dc4cd802eaa1bf18921d039274104b56e8a701c25de6ad33e57997b2e8491d7cedee000000000000000000000000000000000c87632eb73c464f53c15ec127cc5c72fe6a413e74313e80395b55e122108e2984eee6f53742ce4445f455108002398fefc024dbceb522c02b88810ada9a814bfd085fb63d570663a64bc0658e5ad02200000000000000000000000000000000040f1ed7a9f7c70a546088822088c476f8954681f3741cffb7e6614dcefe2963253599acbd263b988af3764331a273030000000000000000000000000000000007f9d150a4b34b9a6f872f9bbec4d2e0795d02c5411d6b3a844ab95ea87f9330662c8b0789e12a8f6dafa2f7cf2f13a12c136f00c97a515076f6a0b63faf7e378f2cf04f8a90ac942fd70e25e683cbe70000000000000000000000000000000002890e211b1969c72a15c0f24b21dbf672b2cd33ba9ab79790c07f0734709bf13bbef4f54bf17db9629cd7abfcf1fc2f000000000000000000000000000000000010f13eb17ab7ccaa0bf32b8d4d38760b72fa0fbbabe04017d9d8283f6dcc5500a336339400bdfca06749f7c1e08f748b033f2270ad2416d03dedd4bafb78ddc598810768fafd349a42438923ddfc93000000000000000000000000000000000f7e328026c07b116dcb8950273579e0c4af027bd3aa442a41d279b1b7d87d672154d2513669428e8f401db490404e6d0000000000000000000000000000000004208901e02756c5a2430200d562c0ddec0224446b3fca62cc98e9efcfb3508f50794301b026d47eb99aee210dd2f898202d0d506bbcd56c92bfc6fbab36bc96716de1af02aa166e7db2e2a0a4c19cd7000000000000000000000000000000001309e8c1cd6ca596ab2c9605ed0e356cfb97c4079518b0241d40a3e0e4769a8e58c0ec6a7bda173fc427aaedaa275ff7000000000000000000000000000000000143b1d1bb451cd56d800d71a747173e56b75cbd6fd28ff4abacbc1dd87653abcae715882af29c29a1631850694c5aff8329762dde1c4c91043a740a8b9639e83e809f749fc8c4853966cb2ea520620a0000000000000000000000000000000013bf8880a6c95a8791b8ec37c2188e4c0c2cf188e2fba01a9e7e4b81116b10da49415a0588385156e4bbd45b168467e3000000000000000000000000000000000be052be3f3278259b6e01d9d81afb4d4215b0b738378e56719403e2ed31bb6e15e47c9986aac19f79001a76f35e4162ea46572fdb37fe282203172c147715bf0a16e02a62bc79f33cbfe36703c95a730000000000000000000000000000000013b27128d2e8bde36f11503986c226a1613ba0779de9b25686284d12bd995c83e0db9eb0b2ea759ee81bce0ed2c0c2ad00000000000000000000000000000000128d6ea67c8cc9ce6eb93111780989b4b33afff45a5075691026ebcc607e61b7a48e2549ce8286cfe4a72b182073f373b9e49472b9b74cefe5a951febe595b0020c43fd54150445fcdc4292c5ffe65f600000000000000000000000000000000137033427de6a6d23e0a2fc17d396114f8f4ca3e56e42936c96029c5b829b3b8b7ea46fa47fa39f6e5dbcd804873d3ab000000000000000000000000000000001986563cad41be453d14ea3f166c2ef2d89ada32a345554ea7c7141f6b1306af815579d7399c73039d1696fb62edcf80b6bfa1ec877010aeab030b96e80d2e27b45a93c6a99e2aeb3ccef22527c6e472000000000000000000000000000000000f0878d6eda3d119eafa0e5cd0260cd5c9bed5fd3251f0eda5a6aab6b475ad8982b55a0c8c07b6921de77c4e23478f2f00000000000000000000000000000000181d4cc9e77cc1e21145457948923cee50db145dde59520e6ddc2da13c3380188856c220cbace98f7ac4bcd7dcbfb1812810705458845232e851b33fdbcaab01966b8ed53b455873a966c1d6b8936389000000000000000000000000000000001267b7c2a91132c46ec835a5c2ea1f1c1021449d4ab3c14355777f1b7771787ca8b72b61563dc7587db6318c2661551f000000000000000000000000000000000d9f7257977b3f207e889678b72b584b84bf736bc23081d1267145a886e2dd6b669bcfd8b58414def71c27cae868f39a175fa4954e56dabfd1808f93d2686e0b4fd285bcb78b80d15e10e63ea8c7b6460000000000000000000000000000000017c223749282ef77696136edd0b30041b7743e40c2cadf8b491c2dee0730554e39ecdce41e45d647340e73bfe77407d900000000000000000000000000000000025924e40885fe566166bd4c5de6e5bdb3ab993c154ce908afeded5614cbb0c00e6ddd648263f17ebb3d81bd6a4f79afe7dda7e5373d0e0afc3da1507416f47ea8b467a5b6c2fbde484aec8777ab7559000000000000000000000000000000000730c41758d12795c7e5540e4204e43c75a01dc6263833f8db435117429ddff6cf4fbffd6cc27f553b8524710aee9ab000000000000000000000000000000000154c3ac230c725594a3c985b7ad71d98c172de8764926e74f6932f5a5d40543b5060c5d604877e3a8df093927b0b171c6aa731f9393d2bb32adf04f19884dd1a5e7aa36e46408b847222a153da95aea50000000000000000000000000000000005c6852bd3eb4db383e9aa8c74f4c158888ada1c9ba07ab8c7b4abe9c05bca51f0065a29a814892303a42a6f2736043800000000000000000000000000000000086d733e758dd4f0f911df6cae3d678dee3500a53d8a364986d88c50576ca6bdcd10fd31f3cebc7a35f43de1d90ee4bc985f367919b0f3c667b1c1cacedeb0be1f9cb175c899992ef55f14e9b7aa6ad10000000000000000000000000000000008445e5c464c4e10fb0a10c97023c5a9b169d042971597eff4380821e44430e3790683c7c66afb89921f06199c72c87f0000000000000000000000000000000017e55467ed664833131b82a2875e22fc5b29a3808639e90741b731d4efc0420b4934fc75ebc2048e8196be55a600f9bca3041cc52c6f1bf62dee4c61b1c5e35b72ebff7e8e89b05353388b551eb10010",
+ "Expected": "0000000000000000000000000000000004f03dd7334a0dfbc7cd3b74a8e06ccf23fad0802e44c95712e920a2b227f09ac3d62429f40bef8241abe41575cc541c000000000000000000000000000000001092b20e8618beabaee18b4752a5b320307d22fea2125b3d23c6ad178f0cf2af7a1a1c0af3cfc669929087235e2f8960",
+ "Name": "matter_g1_multiexp_61",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000121d2cecb2c9892d69e6a15561688edb5020dc39fba96eac835c0577ef017191572f8bba780a608c41d53544d24a306100000000000000000000000000000000080c59704a5ef9251654458bebe25d949bd5c7793c438a50019a9a7cf26036f014fa3f024edb767d233dc09710d53daa709a2e80dd96eb12edc481e3d58893bd0d789a499d5289072d58c2ea80b036cb000000000000000000000000000000000012be549d6b4efbe6e8c17393390f3cf190abe4621a16e951203747dc7faf6d6ac831582fefaff20c952502fe43e2020000000000000000000000000000000003112e26ed614405376dc1af80b9f1984439c0b67863f5cee6d3c44f74f320e66574aa1501376cf8f924efd83655a72b9ff35bc510c86a9e72c3e9c6b49d2abca546f7a62330156ec09c6fe6847a400e0000000000000000000000000000000013b6249bc071ab2f9f048531e6bd27a1b8a45d34c66623268402bb37f6be2d71bb5127461221089ffead4a9f6c708f0200000000000000000000000000000000016a321e986c6301240b1e9258423bb8f38012ad533b42cb487384d9af63713d4b84c383ebd4512145b3e518e0c935b1391dd27628d0808d4a0773509737597230d7849418540e1fe4498fd70d39d16c00000000000000000000000000000000069ae7a90e9402d4f9f1b4a8a799fd5bec30002683692a700ac3a25f8f0a8ef9fa9e6f34844a6c320877f4b4883f36e7000000000000000000000000000000001214fee37b448c79b5c3097dfb65f8b181f16f0daf54861d4e5e7297db7981f2ea20622d12acfac04c066fcd23169f0294f11b10e4c45f15d811e3db4b947ee6414e262965d7b5c23a731b019e63d5130000000000000000000000000000000006e8cf07f48627571ab5fd1a6f988723465ea3f741b71b9aa9156c50e13d5481d66f7fe4006a54cb283c6d43eecb4ff9000000000000000000000000000000000ade4e4a949e6dcb45cfedf2eeb91abe406cccbbc7b4c7804b77d04fd7cbd91fd44f0053196bb344fb8ac1ffa37c83d470f7a0ee05cfc3f63d46a3151c20da53604628bac70d7b521b3be65d7b2abedf0000000000000000000000000000000006b130d66b74b99a2048127c24899ea6ccb0a53c4404f36371f30fc1ea99d02853d4555385a9fa022a552b85422daa71000000000000000000000000000000001824d4d0eebb0178947adf316258d297698ef4575d8ebc2bd300558df914fea04f0269fe67205db1e3dbbae74c0db22bbd991eb5e8ac8ad7cbf8fe64a5889b715a2409305f2366b278adcd2144d7be8c0000000000000000000000000000000012ba5b9c8a86cb99337a7c4955b1a1b459c8a1a7eb6ea908bf27d5f7e41d5f3423c1ff44b4615c689df14709c703e9ae0000000000000000000000000000000008627851a30e33fecf67dff807bfc5430a77d0a85f1e4f8b790b2b072fb7b86d5e81b934ce197fdac6aea60414a616541a9caeccc2a2058c2f5a271c09036d73320f9bcb31b7296a796ef94ca4599757000000000000000000000000000000001051ddad286eaf9c9ae5b3757c53e324acfcb6a1a7d5b490eb9479e337c9824bf619167bf8f2aa5c7f175da534e91a10000000000000000000000000000000000754b16cc6cc813c5c4d44eb4488b04abb659d89cf0dae5fd5f59f257cb396e139443a99b71079c5aa10f8f48465fc398ed4eec02c2af286ae19ad5f05642587cb9ad93196756d269c783a11f23393bd00000000000000000000000000000000035732a9fc03435f3dc3e31af693b1d1ae79110cd46d07541a35b956b928cb4a2de2a16cb8295aa8e8d0c74556b8189a000000000000000000000000000000000d4e762f40fcf43635151631fd6238ab3e1dcf578dcc84d462dbfadcdb621be918f1f0a7015377b5ff9c182494ae149c26f20eee9bd019f9e0f5c794e22e770128737198b5f5dbaf5b7d18040443a0bc0000000000000000000000000000000018f1eb31d3d4e915cd1e0cec33b4838da1401c6667d8ea25209e4c5683dce96b1d7adb4feae7fdb80144c30145d7f35c00000000000000000000000000000000050693e8b9c90d12af4ded25e05df86a3e233425e2f77c7ca9e99b0868eb8d9337186113b078f8083a4273c9411ac1dfc470a66cd3428a44a7d095ef410126257175597a333cd36ce6c9822d1ee9bb38000000000000000000000000000000000e1ca58d3eb507f977257ed8bdff474a05dee19a00818754e3a85f1cec882b8e3e0296d5c3788b101da669a716772936000000000000000000000000000000000532526ecf42eb00da76db02ab6236dc51a346f0a1271f1e9d721a40a4569d46fdb63e0211f7986b98475d81998dbf8be53fa8fb708204e619c221b8ecee14fdbcb1f94731ac2c858787ab33906c92690000000000000000000000000000000017bcd6bf54d51fa12356f3428f02ad8ca31131a77951459d32c554e2dc2487be1bb9f10450e5d1f38af3cc7de1096a9a000000000000000000000000000000000b7b5ffa4d08175916fcc542660c85063e8420987b2e16ed2ef9464adf928a4c0b8e6d5dc870b4f00de8bbec6f0dbae3abf8de43c54ed59b936e1d55032eab5c9d9e04e83e4696d969c24167b4239f6200000000000000000000000000000000151e2e32203b03a054459fe391ff4a4e962ba5e10ff93a1592043ad968c9f968a6e50b5943e50815268a4abe055a1a4a0000000000000000000000000000000004bd116c6857c2f4efa087272df160b765dfdbb842a342f9cd3e5cff006030f32e5a8b60acd8a376378096743000b2fe95f59041329b6c3e6aef01d3410836852f79cc436fcf23199e0985c56f65c4f0000000000000000000000000000000000ab6c3210ca0b70b2b3bb916f31e17b8632513b15a99c7cc61cd21181152bfc6ba6ebaf8e96a05d0d2d42a9dd3b61a53000000000000000000000000000000001308a33fccdd6cc8990c21fe7ed03bca42e3ae24bf07aebfe6878c2c8316a7a52477c929fc7c67a3a13ed811a2adda7b740e4a207ab5dd4a0621fd65697f5d30b8ee1440a5f5c5e74a0dbc6b6391c1b00000000000000000000000000000000010db7de8485e5504211088ada8924386b36b7dee37170f73469bc77212d56c3dce9802c7599c83c5cc5b18883cca5845000000000000000000000000000000000ae8d817daba71325b57f81301c17f401a6870a13506de2a443602ed44b6b0824e6cb763ef556908f9b3f30010f86394f49a3f82d25c6e0d69207e6dff010d56f0d99b28fd986c5711878dcb6665b1f50000000000000000000000000000000000fc19f1ad220ef5bd76cdd7d3ca08539a97514bb21429af5b1774d4c58a7e4ae137505fc240dd0ec01d1a9eb06a157c0000000000000000000000000000000017ce712d74d68568a945fbe2e0b21c180c58e9297f1f4dbfb0775a133832d4d8aa0688f031385190324f1e8ed65bd5378390fa1b452f887ef3afc7129ad8ceb9a8397f7625c2b249d7442566814ae0a9",
+ "Expected": "0000000000000000000000000000000016cd97de498b8809f4de87bcd5a66c41c231653fdec9bc1ebae0ab3b8c56258430bb13bf400f5f971a1ec558ee66ef02000000000000000000000000000000000cf57701a5038ec26e4027c3cc5a8cc298c2d86e9425ae027dacea92d4d475130487b2743c64459990e88768d8b7a4e0",
+ "Name": "matter_g1_multiexp_62",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016fb67277c28b5665f1b7aaeb1bd70f679b507a6b30f956a1fdc0d522e430cb4a9c089093cfd14714f25cc9498f89b610000000000000000000000000000000018ddf06c643bd77c953a0bde77e80e77334410d76910dfb587922e6dff23e821ebbee2dd546e65591726f9743defaf9a414ca9894bc15e6bca798544138689b2471f8171a5dc48eccfa36c83af142b7d0000000000000000000000000000000011d630f01000c6e1279f330893a18b903b7246031d7d05d80d4172b08e1da182594cd42934de3d1418445a76bc9c8189000000000000000000000000000000000c3e335aba4402bd3c711569e466293c15d89f4893ba91d8690e4eaf4c7962da458471e8c7f22c417abec313c2fd223399eac8ce85a1bc70c725a2f04aea3749d75d22c0df7c0755a5e76ab4d82ef942000000000000000000000000000000000c38e3a1c95f0faa10980976f83d85954813faea27c120fc3102de51096f6c3ce89fc4155c6fc878fbd18ffb32092d7800000000000000000000000000000000178d0c64b3b7da5b6f57c69bccbf73e329b18e29e9187a7af31b9b8e480b210dd36589540d77b3041472d9612b05693a49b25140d7967b0438e49f59a6b04b75bc8745b84d7350605be548c6b4b3aeee00000000000000000000000000000000146c5b46bb4194ec04b5b63f09e8066f24e350cc62fce016b8a25ae57877614162f2733a5df8909eeed2df30374004ba000000000000000000000000000000000cbb312823ea25bdbfc4afd00cb65748401b47ab7dbd5a40905162c1ea676268745af11a2770509eb74aad45663f7f5b6e30a51d55a1ac94089d0f3217c3a2182da6b02ce70ce7dd8e2d4e938bfefa9d000000000000000000000000000000000ef489c4443175873e33111e9ebb3140ca0796f13ce8d34b30d8fcb7b9130ea0574754e800fa0ad15d71c35a3584e11e0000000000000000000000000000000018bd8ba66d5b67537a03030f5ae56c01e640021ec2524a2cb4b2005ba267e737d27916dde1e94d1f15b6d3e1d480ad82d3da3db6492ff36102747d9d663bc6e9cf8f75b1cf77044989c7af3f11d66ae700000000000000000000000000000000182acbf5e02a0b1344779f7ced01961f418fa8ce94f939025110823e5d5116d771328362498324e1067a3419062341aa00000000000000000000000000000000174d3a7754b18715722a07ecff5ee3b7f30606c3c573770c88703b6e0abd9ff4aa4bd2879c4c0512f879af95554f47316de8753f3df8be42b6d6ab578096426f852de4ff545d2e4ac12c3943b044b43800000000000000000000000000000000178c3a28f9333be85ff364329fe897660261092d9bddb36687cdbf5a7a450f27060a3aceaf45fb8acfd123116f195d8c0000000000000000000000000000000015e0a930af79ad263b115dc733560752cbc4453f111550fe3e9448b6818a75babbd0044b9b4f133bcbf16f8fb7586055a28f7ef4b12c5097a15fa6394a4dcc3ceed6cf3c6240ec2ac949bc21a9f6447f0000000000000000000000000000000007fbd9b191af6a797c68ca85df2100b898e3a4d9569c717e3d02c259eb4dff3a1ea948e56001f33a3ee1c74eb966b6260000000000000000000000000000000003b892510d5073bc3597f8f513908077814a7efda2df6051c08f7347433703496e522d70ad4093f76a3e5288044ba5dca3d0eff3368b10d00566f35391bf43c9d204a4444b7eb91017f1b2d8a762d90c0000000000000000000000000000000015d26d3ee6fc5f98584c206466d2c1a4323f597e0ad665b289e76184770e81856482c9f45ff8c891622d8de353b172e80000000000000000000000000000000017fe0582d363a30677bca1feb6d7f16be6b07d6e5d6b2a2080d07ca306d5cf733103f20403ceb486ec703277804e7971b90d76e660389e570bef756e9785e39b9748aecd7a34556bac8399aa5564d12d00000000000000000000000000000000108de390a69c6001124820072eb5d9ed9eb5b5a6199c33db1ab0239c447e009df4296f5324660e7ea1133df0c8e6a9de00000000000000000000000000000000040e7b3392a116c7289644f393bfb24d84b76d8378c042d86cb4af861af42374b709cb0ff5341e3ae9d21271c32c0a5914f18dae096e4de75de3da284a5755efe51e912e180020a20adf1f5de43cb5180000000000000000000000000000000001ed57bfdd0542efe8734b0af448c025eba4d60053b7b45baf682cd310f4c2ea07e708bccaed390c2b061c89c2855c9e000000000000000000000000000000001496190ccfc4bf428706ac344ed691fbcc7b9d6a456f2653f0da421a44653d4b1e9e967954b847a4e6014df15ef48719e32d4645ce0172000fd74f30937261de89753caa716dd03a8b3269747f2349a100000000000000000000000000000000147e5056444c7ea97a319bc71a3ee4188f68b517b92c64f556d22382389c5bab95110728cbb7d525499cc3b2d70541b1000000000000000000000000000000000f05b91c8d05b31ef6497595ecee6a6766f03a006b4c2da408f4d7b7601915cef64be69735c269007fa23e5f91fb07148c8722e3e929ba21f1ed6c51fe5ad4940fb13d63e0293893135d0da5e6e038930000000000000000000000000000000011b1b7c28754f3dc8b21dc823fe02d617374bdb9b96dbca572eaf8897f98ce9409ce8a63eafcf5308d8236bc3c18b4960000000000000000000000000000000012360ef03ee4dbf0bad68232b8454a26b666d827bebac03da314b2631a45cd365248316f72e991004d0158f89ba5811839bef6ccc893f6eed62e68f5f2a07812f2d3066b89653431e7e39e8596bc36520000000000000000000000000000000008b563f6f97fee7e2852b44d8e39ca314963b517116733924d2f57d9c4f202b47fb3fdb85fbca42ffedcee290050ef0f0000000000000000000000000000000016112f264c2b3c838b02b78822d27f6351860d10da3ccb763c1650420bf22755938cb45c7566a2df0e4aea4f0281262ac395ba8f2553e3eced8a42b221a710a5cd2a5ffe5834d3084dc260ae0f51698e000000000000000000000000000000000a8397b009cac789cfd496f4f1237e92ae570f67b4bfe7e8c80171bb9d9cb53201c2ce112473b74646a4948d7c10c338000000000000000000000000000000000092b7425031fc7c328e3be114916a06305b62ffec8e7e93a591fc5f4f9022333cc664057ff6983677cfb998defe249553ef5568a766b6c39854ba059f3130b75d7fd870bfac2b00b626e2d71c4968e1000000000000000000000000000000000df6739202d9f1f13145b697d5b78ccb84845710923a0f3bfd5a3f337e200b3ce5390aa185ddbbe8088462926a7f4b40000000000000000000000000000000000d00ec3648b2e5790ca7b05ff32c6bd3249296bd693f520f6d8385f15dbaa9f808d770f9ba28efdc4aa6bcf862c17c4abadefc3880ca8dcff10b8b763f7d15f88965c2261b72ba879e3540a90c59effa",
+ "Expected": "0000000000000000000000000000000002665808cfac4b9befb1f285c590d639132adf9d36a4fd460de0b3347303aa056a14780deaaa02072fbb08e1dea06b940000000000000000000000000000000001ef22acce32662085c53b2080df9354903f151089faffa43c5f6a1a306d2254fad240bb1ba3dba4927ea5640347bac4",
+ "Name": "matter_g1_multiexp_63",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000194b906ed067bab0e26b9ff4c0ecd909c6aa23b5cab3a90d1761840b784bd2af6e9f9ca570ba6643d4781885553f3e4b000000000000000000000000000000000e8a480cf75e20cceb6e1d9db5594d19849aee6d45bb3ca7c0311bfbff8263420e0278b7e814088abb69e73bab6368a92c1a5abbddc02f453519563d6b6e05959d8de5feb493f7c58ea5e548cfec2df60000000000000000000000000000000019ab570a48bf15ce6f007b528d7113cf423e1c04d9af9497dac47a69deaff52dc9fc4d202649fced07378b84fa1b0054000000000000000000000000000000000e3c2971aefe89a629600a243c7967ef001ee17f9ac452a8131ea44815ecb6596f4fca4f47a316f62234851dc485fc50b406eb0c097237556228f3a48b7e770c1707fd583b91b4b6b70f398b7dbb0d3c0000000000000000000000000000000001250315bb81e9ef7de73e709f18003018fc1c55f694c0e28152fdb244b07dd2d7812c3ecc4ba362fdda0707d02d697b00000000000000000000000000000000188a852c5850f471d4ed207d5782518f189cd08d63279c4cf19c76122df0e4663217f1cc8374c7a02d99bf6d59a80457ccc30cf1db4c6be6dbc5830ee37b5782c6dad215334163a9d9e4deb962186f80000000000000000000000000000000000df12b5c659c17c808d8e875a1b9c125396cdc3d8a2bd6f99def15d9fdd1fc7fcbb309333cce1b778612d6114bba63b500000000000000000000000000000000019f11577152bcb0229e168a8e97804e8e00a58fc236c8ae59c575c07d6a3c1864b7c8132f245aeec55d999d54745cab99461c0f12019b344a7f322900b64fe81e0d8a052c0ff5e977f58753b1b6edc60000000000000000000000000000000004b007a33b0ddefa5ca9379614f698dbdbbfc6bf8bedaa485dc360cc759ffa4ace304fc64071e8f228a8882d5bbdce22000000000000000000000000000000000927e9f018b8cbc2f21b72f0f19994705197d4b6ab3f03e231e51b9cb3d899fd8f8b71feadf3c9be61994936535c61e8338ef9fa825e47b46483ed8fd2df64bc7b56da8aecbae704b7eff2e7d426f27d0000000000000000000000000000000005decc41dadef7dc4ebd8911af09974686531907e41dfa16c857fc3a2451b96069d06ce1159d47e6f1c97cdd932486d4000000000000000000000000000000000151d369a147cae5d78eaf7ed99623675491f20aa2cec9700053f853551208fa21e085962342072c96d79233bacc7adc1dd6656a34f3b12e5568b9c348fbf4ecf50d65a89e63ec0936591f01e6cc7a4a000000000000000000000000000000000fd41ed8d5b7e5ca6a6feae98592217dbe676accaf6e73062d9de9eced8af59563f7f441a50ffbb591b8a987c47988f80000000000000000000000000000000001199e002504726f2ce429cdb3da304f9b54a933c1937e8dc39a3a416d068cf46f411b207d9c6862a50962516b2867ea5202f32528e795e0fbe6deb4ef6e45efc70019520b01fa1d71d5505e42faa69a0000000000000000000000000000000017cc9741662834dcee7af988d3e4de2c30d4f9e90f2b3f7ad07f756acc793c58acb2a04c2726129d0f0c959f1d3154650000000000000000000000000000000008052061afea4c307df56a72530effa73b34beea4d731b1562de1e985ef455d39b0d6c57008ec092241262dd611ec598a2b39f2b893be03ab4da77ed518ef35b2e24278d707a20b67ab4d1e5972f97220000000000000000000000000000000019adb959f4807d3bf7e0616a8a3c02e9babc94b8ee9f8898f2ddbc8fed7a5bd88e83c70c5a98afa823a0f46560e32198000000000000000000000000000000001189adca458e0ef67fc686b5a94986be37c414cffcea5b4fd44430c8d5902512d84200007a93104048160ca3f5bbb9a8892eb7c361f05e114a645caffce9437b7b43fa01dd66c1e75b30f3abd0209bcf0000000000000000000000000000000013d55a4b466ddafa04c5690628dc29deb0ae9115a4549767b2aa22b8aa02a13f1db82dc86fa3df85a6a15463fb0e7903000000000000000000000000000000001488a03340fadc9e8f7552273699870ad444ea513cc7bb91259ffa7cdd5e7377d8fb5510adc2502fb8124d7914af85d5fdafc3f57d6116163f1da9e70ea645243c5911cc4ad4a969a57c46c6b5c73acf000000000000000000000000000000000a847c98ccbccdec67192529c3da593f1d6de5d7dc0bf4452e4f09e93c2c406d6eaea30431ba95568c92938150a00a05000000000000000000000000000000001201397edaef2f9b89dba7f67b22088cb954f95b9db3d1c11bd77aa0dc94def6283af2866a64f0028fdd87b587669f31660a77b2be50eb72fd108644d913b9253209972fdec2d107213ba47357c96e9e00000000000000000000000000000000017f76412c8e679676eb464204348d591221ba17a1c90a22b2482991deee6b61edd7520ed10b0105426a15fa3282cbff000000000000000000000000000000000c65a821d170a9726e947868d861717e8cbcd2438e4d4b8ffcee38eaf033f8f3a57af68ab6314a52952a305db54ecb361ca575cca348dee9adfe68f8a78d39bb998205da2a5285c12141a77ee7af84090000000000000000000000000000000000b14fc1d34bd7d85fa96a4d12ee99a6d327347dc63608f94bd750e2096dcf11066e384ba3c68610c70dabae795e668c0000000000000000000000000000000004f3ac3e885cadfaa565b1ec15cb81e3fd4d561b2a8d92a9287bd0de893563676118d34a9ef3bb3112aa534605219feb2e1e4537f855eb478274992cba4e3f50fd9e944f6246cd52dd1517b55bd7f71f000000000000000000000000000000000979231339f20ffaa38ed21cfcef923fc9a4ff77f7d6fb4df212a530ff456a32f50a77d2e7f6d87c4a58270c006e68070000000000000000000000000000000011ff95871a91385ffeafd8a609a0c562bbeba71a110081e5db6c8035d8176067a528f4d1c6d7dad43b3bb8d090077e1357f9a729aa01c8bf0271052202a077913a9e0c87201a367845f9b271c130e95d000000000000000000000000000000000e2c7c67fd50bd2cc8ab18808a69d62bc2d3f110ef49a02259163f8fb152da6ca9cc771d1221d7719f9bc349e68594120000000000000000000000000000000008393769453eec7639d66525d6e875bbde7a4a28c434c82571468d496c4313e12414f929139c482569c003a6c0dccadf3017593cf311989ed8fedff72bb1f14f72cfe5bb7446ace5274d8ded54c1372f0000000000000000000000000000000012cfa8448935a292911ae6fc175f3049eae5e30d714b3439f55be9970ca959f218157097bf9837125bc8f772968b0d52000000000000000000000000000000001747193c5402daffffe4b1ba9034231321d01966befa174f526014d6c27fe3683eedefea8690b95c8f71fef1152929bd08bbe9e7a307e380c238ec1f8e2010a95fff8b03923ecd9b012f99e56c77a5cd",
+ "Expected": "000000000000000000000000000000000bedee9e836b3e046bba7fca7632d09a5a25fe1f0fd25cc6ae1d1e07d98ec52742a60bf346285488dc84b2360e0db58900000000000000000000000000000000071ef77988eea20a38fe33564689a39a7113b1715dddc1b212c6edab6bdea8de54089eb7b49b63296792bb2f4aa68733",
+ "Name": "matter_g1_multiexp_64",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000b7db363585b0061a4707a2ee67d6d7220e9209b4eb9a59c02aa6e177c948057826780f292dbdd824d67ca9f78864cb000000000000000000000000000000000a31f49bfddb5c48730e1cd429f128a540ff44b6a5031e7975ec0c6661f9f3f2b79ccd2d13cc1b50d50ef9c7f658d412cc5e9d01f6ea67dc3f943d57d9d8b5791d823592f7fae6719804c1ca097e651d000000000000000000000000000000000d4fb266e9fb18590037394b18971cad5840bf89047dc11e52c90284642be7e27007c62a1e331a2f90ae67313efcbc0000000000000000000000000000000000047b518cd6a7d7c4d262d1f9f5f11480e30c626d45fee2d6caa274aa1353035a3c42ba96b5875de36442aa5d4b92d6d257b8fcb85e4dbc1969805d814e75b2b80f5cd1e5562bfc1e28becf731aadfc58000000000000000000000000000000000cdc9bca5cc807710948d5189dfadca2cdfa6fca5496234f13024efd84a37070a2fd51a609c4ed6aab54f8687ac9700200000000000000000000000000000000011bc450e4222090603ccfaf7c1dee67bbd59aadafc3810d3aaa8362fe43f48952320e25bebef482c5d21a541400df5a03edc53ced9ec5d7f302216fd30a81c3554a3fd04994f62b5e3da74c8b71bb870000000000000000000000000000000000015d20abf274edf0c9d45c2675e4af7987e98005b2a0d128ba7df6b16b88784a7134d37d0da2da02557f88d26de33f00000000000000000000000000000000190adb20cb0f5902f7e92f79dd6e7d214eb892834611ef222e9a80ade4c7cf96e0b5f9382b61715e1701c7e9cc4f4ba5976568ab779e335b8dc67a64f15b947e69cd3896ff393f51fbd3c3e3a157543f0000000000000000000000000000000017dcf175327086e058e4696d689f2e8a167aca5616f2317b7673850a2272fd5742b70eb362b37874d573cfefa25ce3ce000000000000000000000000000000000e5e1af08f6174641aaf4f1584ac40d53c393314dcb1c405263e8689558445196371e2858a4f44d605550fe0f15962223aa5eeded490a17b1cfa66d409811741643b7beacf312b9d6c8e7e7e63579c830000000000000000000000000000000008456d980ecc64b04a203d61bdb78bad67b4568b2dd9a123634cefbd7f7077cd9a4c038c0aa3654915c12242dc594b37000000000000000000000000000000000adbd582b0a8ac28ab21961476e163255089c2d362bfe9daa7007a2c9d8d261593eab22a6bdaa9740da81efaa24cc3d5f9f1f9313bf966ea3b8f09bbe9dcb66a7f9e3e94e2024c49a72ccbbe03fe4662000000000000000000000000000000000b02d326ecb5c04ccea4cc3d29f82117f3d97f788b8e70cbb346d43d27e674540c7a94d242d290e55d992eebac546c9b0000000000000000000000000000000013901f8dd68285d73093c30b37419ef8e4b28371474a040a2ea293f7274ec4d6ced0f32686405205324740884306e3a693be64fc3763d06111961bb208a2b858aa1ff181781dda630ca41f0d45ef2a9000000000000000000000000000000000181bf2fe4bc67a1d10335a0ca9427f603610646de485a7cf039f0706c0a0858ea694db3b3e5ca85317c98b5cd75865420000000000000000000000000000000014b1b652e2ec7d05956705f692860b83713c5cc98c6532b3df50259f27f92d485e8df846883a4af4e46020ae54038d955d2a2b6008a3b4a4cb3a8c28864214c7fbe154fedab1f9ff8c96eab6a5f28fd3000000000000000000000000000000001084f77ef23ac990b43363db38d652f0e6dc04a4bc395c8018083fae6fa6e42f463af7748d71f65b14f94632ca0eaaae0000000000000000000000000000000004ebfd75ecc9cea5e49082e1adacf6b50e4f14600d9343f6459900605c5f36ee51e95408a3005c0c1093e41794c282a0854e742ef7c76ad438cbf30c30103741f57ebbcdca4d6c4f14e554dd1ed81b2400000000000000000000000000000000062a062d2ccf5c131e1278a63e713ebcf8a221e429b52b3a7688f7e68a12558fd0f584e03835daa3988233d6a84010310000000000000000000000000000000013e9330d29635892fbe0742d1a8c96ef527b78ae389385a366b6dcc6a04b8cd1d5b8bbb79ea649179e78fc061d23cafd6f4f00b2494a32844e01d0827ca78b06f5eb40b6769f36a04f20eea229c305f9000000000000000000000000000000000b131e0623b7f30bad70145cc4964257053f2ead992d28aa5b24c04bc316d479d077af0ff409cd395a86b808bd3e4f02000000000000000000000000000000000380fe6e79e5e0a399365d73244f2962facda8b7b381c111508819309ec5b1d3d8783067245dca26641a966969dcd0ab191e47a0b0c72bd17319063abde7df51498cf0c980c46946bf80ae4c9864e2e20000000000000000000000000000000014971f46efae601309f3d16c15ab5c46ac48d2199431fd959cbf4efb768ebcc4f410fd66de04d3280659004a6b54e64700000000000000000000000000000000113e6438dd8088e73eed84d24ec286a45ca51f0fda88c7ae3f1e6a2195f6b11877e606773bb9a8db19dc92c3b0729754b7baf8816db56c0a602cfb4caa9089136ebde05722ad4838671e45ada5c716f20000000000000000000000000000000006fceb59d8baea4a10aa9f1e825631e28bdd379189eb464a3c6d2482319a09337a78173f9207a58ce15bb1c518b39328000000000000000000000000000000001609e1ff34ad2e4bea4cfc4a993d8d52a1a8676679c91544ded432adfd7fdb5c016f8d825af1c6b8207170d05c10e04a7d9ac1699117bb9b8b90e2fb709eff4ea0f7882bdf6acc6885c9458703cbfb3500000000000000000000000000000000069e48b113b822cdfc02f2f0efa02724193a5f032dea902b189290db91c6e4550fb33e2915eaa8e56ef329d6c61a0d95000000000000000000000000000000001426fa2fe7c160e8e32c3252383a7c7967b3515c3f76eeefaa5c76f02b3308d86ab95f9a3a0dfacfa6dc12eed2f3a5e8a22b6c1a24eff71f0fc64b6aee8d3d2dd0827756f5c959f68f1216c2dea58503000000000000000000000000000000000c173c6c949a7f21df4431025ce16c18b1008c75b8b1b23d03122c7c6ef714b5741804ec7aa5ac40f6b72a1a74ca5c340000000000000000000000000000000001b32d54f8f9839dc39e08bc6a5f0efc5db9bdf487a60004ee135c30efda577d187d9b9e68bdcdad558f2028d66e935cc0431e6877166686239f014008959332d9d009a801be6a1e68c2de52ee264bfc00000000000000000000000000000000037d1cbe4534b82ee79b2c957a6eb19d18dd3f3f6faf3313b0ce12a98953190aeb55f9d494bbac4f56ca6986c65f7668000000000000000000000000000000000734f505be94516149bcd6302a2c9f2f9b952c9e614c8e90b5466073a7e734ca203fcca242cb97abe1c532d7f59a783aaf833a784d22b99537236fb07ab7b59918783e35b89fc9692d7f76a03e024c94",
+ "Expected": "0000000000000000000000000000000012de1cacd791ab81eb49d2e259f36abfd90e8c7ed4f9f23a4c95cb48cc7bf9df233951291342d1266d016a7fcc6b9d53000000000000000000000000000000001938d574d02b8802a45ddf8488340f2397e93125678400cfbd8e64cc3805704bd5f85f8fb2f64a96ec1089b03d9d1c24",
+ "Name": "matter_g1_multiexp_65",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017387ec261c6dea7bbcaf4537182de1620adaa5842cf52c8b5b6cd851ca3c27abafa584547db7366455281d82d3f83ea000000000000000000000000000000000246dc1cc9773db7151e05d131398146b28850e97f6b13694d696be374095fb153b206723afcafddd4b3b56bb15bf778b16c1bc60e1a9be9a82c93b7e0311e7516a57d687d8907599918df77b3b6caf3000000000000000000000000000000000a909dad5029834df0202c298a577f897a376b205812d79e0bb58b91ca11262a766dc396f69fd2b199dbfa52670515ea0000000000000000000000000000000003737873dec25f011b24543071a61590646e4319a2128eed87d40193a22c47b1a6c0f807ba3115a7e45823e5a4bb433dcf301dfca76a83c70552c9cbc9c80cb20f0d82a70a9d887b04b150fa0764ce2e0000000000000000000000000000000002b959df6a1badcd306209c1f3c4c496cbfe4f00995cb4403b04ffa6b9f2c8dd9875a2747354a653a74fbb605eea50b00000000000000000000000000000000004d6b15939c8e282a5995c8c0b67fcba3171b35ecc039fcf32d1e96671698d8a9fd2cbcaa7019cfd01e56d68cac64fe51cfb94c4e029a2126a9cf5561c677687f52059e4b7f8b7e7e73e5b1dd7f421290000000000000000000000000000000006be65e97560a40394d9295fac0029a0c889bf803f09926359a1ac40deb7777cea7dc5d2c4a9600328605fb994f87b5600000000000000000000000000000000128249d2137f7ab1c5622a8eb1c59ee8ed792fe6b09e4d868c9d9ba900a8d28bde5b783ca591f79e1d729c99e10d5cf6d8386fe6f4303959e58165b422e98c4813b1bad7808594473e4e66df09698cf00000000000000000000000000000000002244c1e55324a4aeaa07c414cd3f9872290e729c1cf1c05a5b1de3443e12b2335cd36f0e84f11f04b62af37005ce0ad00000000000000000000000000000000151684aed084d38aba7127434ea73e63219c4f5b4b92017142d19d0330417fb2806e31440e0bb7c9fca2bc8dec73072f02e1c432f3b55ae87ab815647f196be3e138b2f6e9fe7acb9459650246187eb90000000000000000000000000000000009f0c959d995af6cd0d45750cb35a28461d0f791e59b2975ba4edbd7db015858b41b3b7c5c2da0a4c6a5d7b4e855329d0000000000000000000000000000000012d495ae3096c2399149afd00f640f8840c3f8e5dda5835b62ef0dd8bb7303f522692efa72c37190bf6808ed3d4fe8e89b0cc0ac499dffd627f5d19b87817dcd67e87561d5244a4b5698265f8c5b767e000000000000000000000000000000000334cef31670360b5ac7550b55cb03b770660ee79816a2742c059b2ed6cd9d5c53c5ca54793a9912ddd7603d975c3f58000000000000000000000000000000000144f221db562b0daefb20238a527a10ff1ccc279eda86723668f8ada40b41a2825f82f5ee5d619fb193b9c2b4180d932f3875f81fd39c9b3ec74eb269903dba4173d8eb0e41a196d3131252207ffa0400000000000000000000000000000000037f14fb2d51b25cc04768d50fe26c1e156a3478b80e32da980f7e8d5692a4cf282f75e5d8be325ccb4223c7ec2c04af0000000000000000000000000000000004eaf2c069c96dcf18051a2c1d7ea876af67bf344070415894c07b3dd69330d8ca18e1313ff57d83b70e5cda3c9ea8582d8d4341822dba68c6fd58cfebd07b134c1d0c4e32ff63f7d59addff4df1ec3200000000000000000000000000000000104c1f5bdf874c91020d410d8fe74834cf15f341b86e66ac693003766484cffaef2c57fab5888f02f5ebfe1b9ef2fffd0000000000000000000000000000000014a2f6d185c2989ecbb766179c0b0d0713ea9714da2ac555bebf0522ff00766ea7e39c8237f8515224fd096d2b1ede34efa3dab1d7cdf949bd938ca6ac371f953b3bbef1aec7ae76bda37db4c940b3d80000000000000000000000000000000003ebae6a494d46ade2dc7d4630a420b519df7086b57a33da178616d4242fc20e4d02d38b5d00675d2cfdb51adc1921f6000000000000000000000000000000000edc56e6eb4aa8556225d928408702042d49cf3e1410e1c78d8ed5832ecae449d17c9d8f2a89ffbfaf01bfcc85ebc1669848d3c53632dc461619c8c522013b83550ef3dc7fda197ba37c9cfe4340f5a50000000000000000000000000000000000f96864832e7a9602196f0abba78f456300796d5afc18b0ff0c5c23b61865256fe5cfb960bcc8f73231c21b1084cf04000000000000000000000000000000000c59dcca2249b5b01c1b54be0e4114ae8228bc150e5ac7593bdf96136cd7cdd7562eb936ddc5c9e42bd93abe91bac5b0cbfd192e917f2e0c4d6253c4e4755f30812149d1ce1ee4ae5540faf1dbfbc13a000000000000000000000000000000000422c390e56fa27e3d7d5da1b2ef00a29d5340026becefc095d4cfe830208d3b94cbf5ae6f4506ae45d04764acc8044c000000000000000000000000000000000d1cc7c147cbedefa854fb9764352a9689fd157cb2540fe070ad7f6f3eaf761b4670ab9334de4002fa811aa7a01aaad479eaf11b3a30c7771ce63cec214416d798de20432670280d997b2f0631007d6300000000000000000000000000000000018000e31f0ca43417865a1cc128f33383106f5bea71015e9e77cc5320cc3e5704e437ae8d84d96f2c4530c41bfad29b0000000000000000000000000000000011a74c3779c8f351d39db6745210972f4f299009afff643e944f30dbc4367e17271c688e1858e6f79b6636787fa56e6b43077447b67f65e16a8aeb3564b2d13822e478dfb4a82a15a1c8fb7cc8170cc90000000000000000000000000000000002a6c7367526da989ae093350b7c1ee9013f977d6e75563f996e1f15cd4279932a3e4060a26262f27403966a7e0111f200000000000000000000000000000000038a85281b09e5e68d7e31bfc323c9c250b42248cbae47f9c018d72f3e69ec572779d7f8fc6ed3f027499741565274e5eb64479b496c17d0587f6f26c62752881b6a9228643e8c43f21c441eeb643107000000000000000000000000000000000b788a0d47da0daa1f0d802d340e68f9bdb5ddf91875732b4ae82f1a89ebb5787ec1c9f539b82e3c94c36a5df4ddb4ad0000000000000000000000000000000016f46ff55e9f1e19a332ba4ba43d66d2a11a2728a484a719ddfc9e223b54224db55af162e73a8f5c3355f0127a6b7cb652b42f75aebdad1bf433917c025800c4f4e985cc077db3ba36f7484f95764e89000000000000000000000000000000000379d868d91304b24e19694937402bb685f064ec5a89b49e243e2ab7eff5ca0a2023af9828c4ce9f768a1d6488c10e110000000000000000000000000000000011a9b9432ab253d47e8dff776c8b5810ecf7f7aae2ff36ce06b87436b4e20c22596c7713def3886549a36bb535a96fd1e83106e9ea63791eb192e7a035bee27bd049b3a37f080076146eeeea6a769384",
+ "Expected": "0000000000000000000000000000000001a50ddc4d4542aae264dce69f5f5e93353a9eba30b177b33c2f74ef61149a301599beecc4d0f78078dbb9638eea526200000000000000000000000000000000160a2fd67df885232b06d3dead7ffca93cf0434a3e9a5412ed3b4c342819b44aad5385bf5ab60bc2b7191722d1372183",
+ "Name": "matter_g1_multiexp_66",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008788a699276abcc2d8e4a35a9d0ddcbd8006a809799374ffd56ee8afa1a89461602d92fae6eba7fdd4045ba34d917e5000000000000000000000000000000000c8e03ca0da00c6829e2d7c49360e67e46ce12e0c99cb3d957119bd9c8bcac8e03cf32ec71db2a18568157f4b44cd4dca4d710d2f632e3ed0ef69fa0219e16ba30d3efee99386f1a5c921f4548ebf64b0000000000000000000000000000000001373b4a0653f48c205b36bc50541a43abfcf35974a584953bbc40f5cabdc3ac2047bb86267cdad1e8f00766682d2e6f000000000000000000000000000000000faa8c977b4db7a3c9e65d9cd5af4ffd2d7d67fb038d92c1096124312a98d94e6dc3f3b8de73eeb057cdeec4bc0e0482bd9ae4597aaf582857b40096360ced0f044ea172551c6f9fe3a15e0ce290b56b0000000000000000000000000000000012dddf5b96d0dfd2fd619b634b086ba5d5f25a53e93938559a7adef7b988749ca27d14f2ddbf5a9e7e6c1914403a45b900000000000000000000000000000000044b5c8041fa805cf2ec5a243814308369e5af534729cc9608fd17583a48132809f507cdb5b76fd6597fcababa865ddaefbcb4bad99b419820eec388f6f62ac8d87866d7beae6d431dfa48d4243b4a4b0000000000000000000000000000000017c5807458fbb875593ebfe83c49ac2493ddaa15671a59032528e0464360c64bf564f9727959108940ccbdb8d01f329e00000000000000000000000000000000121dcb798111976daed483f4efc95f968f5212cdfaaf0497eab0419a1b55c7ee4e2ea26716d0c1a8aded4804228b8ad860d89acf5b49fd1f70fc54756c4bc1972cd8818e36efc37b422ba6a9318fa134000000000000000000000000000000000717296a20594f940a05ed3ce4bf2b7779c428b33a297087e08b2283b33228a7d4d5b9c49a71ce036d6f2a078d8344540000000000000000000000000000000000fc78f64a461fb66ca081ff4d67369058e57e5ae0e284562161fc3244bae0b9c70ea6abb2d0da6cea4942530c64ea0e386af376b9b393dde994da419d1f7aab60023546647f7b069ede939386bd6ee8000000000000000000000000000000000584bbc0c537e7f37ee64604a134d5fc21d838c51a89c608ff9e3684357ed7f931fbd4fa4a5a56d20304d6f6f072316600000000000000000000000000000000191ea3bf1016b6402dca2856845017dc49c74d06bc3c5f10de379e04302c469015f205cfc97fa142727ba7e2439c15575ffca78eea65c00e1128f8dcfc96b39af1c4472b461ba5262307003bc972023d000000000000000000000000000000000f1ff007860ac58bb04d992d639a5f882c3c647e76e2d6d96888a55648f81ad8b7edb3dc2b0e56b6f2dadca73db7cbda000000000000000000000000000000000fbb952eff64505e02e0ab34875d7a79c72ab724cea7cd8f28df2578b50f78601b9a9eb4170e1b7e8d94d9db252e23c592837b4314e63ef5a153ea2ec4bd373cc3cecfa3e892c3a12aaac8ddcaf5905c00000000000000000000000000000000011dad65f38b4c24527ce87f8893c8331a32a3d058cddcdec9f8708a3bd1e31871cbdcf944ec14d5f101b8d138b2a46c0000000000000000000000000000000012a6981c5100177e643dc421c5917896455107c5995b1e969bb18b4b2752700a18281f732530af9684db180290dcb138127ef2309c699a3602b0d86a070baef0eef90f539aac3cb6ff42cb19f284bd99000000000000000000000000000000000bb4dccab7abf3f5393a338a3a07fc20d337ba2ec3b33227e8c9a832900f347d582d88cab123dab489daf471191538b20000000000000000000000000000000008589985e2952db000968a793cc0fb5bd1764ab1ecdc6f278a11dd4a1de87823016e14e9fdd682e6c489192b154cb997ba0f9a93c2fe35877ddccee5da39ce5ae60a6a19e72481319e3b3fa2eac6148900000000000000000000000000000000056fd39f2a5356870a3ebfedf35769710c16b2f2eb4a061c936f6de4f9001990769795b1c756d7c67623ce3931ea1b5a000000000000000000000000000000000b7fcba295d34fc38739c4b36689653731fa46e6029bf8e38ccb6af5ae08ffc09c86abe0de62230844a66cbde876f52663da2f227d636f10e814e360c2156e686e26ce3401dfd15f47c4ed277d05353f000000000000000000000000000000000039b08e7110b0d17c41709378f75844379c662f7f3dc480bead6bd4996de2d8889f458aabca142d50ba0e34c0c327970000000000000000000000000000000013363b0da7c7dd343ffcf6cc5e9ddb5b51480b04a472c38f90ee08cc97507f5dd665e15a160860c6df4dfec154c1504bef79e3b6ce752d140c3dfb2007a08221d989038c921efff3bc4e150a6155a33e00000000000000000000000000000000034edf693e1b201be14c496860d508d12d9180b62cf3bd2407b8ff95b93da67dc0c4c43344614dfed516d7828ffda4b20000000000000000000000000000000015246f388664b1d817fd17831f85d84cdaf31212f093820835f201c3fe6ac99d67cdcfdda3c2d74d75d5114e32c65cd7bc08091af8b8c6ea5c26f1a7d795132521350d774042d3a8c0523e86fdd23a3f000000000000000000000000000000000982b8886abbfe18cfaf4c0e16c2e7045973f5efa27e5cdb56443a22f5434e2456cad041bba3e6deafb072e5fc40f10f0000000000000000000000000000000016a45f684caf0eec143cf8f31ed5111750d8c4f1092651a471cb88cf534e81df117e3b0e8238270d3b03aeedf04d7a9f70363101b87d685aa7314f6569fca0775bc6aaffabe136e6c336e8fa43dedb8a0000000000000000000000000000000016d13da2900e2b2ef8f6ae295bf16d100d451ac4709455c55323988c71ea6aef694de0fa5a33cdd7fa2512d3548e39a70000000000000000000000000000000005795677001cab950d1a7b802bb14f9203036f15fb335daa5f0b0ece4bcfcd3b31b581b439da46452e4e688f16685e37997ff3852cd97c3a65bce9083ff66197fd5c70894641195514d556102f091e88000000000000000000000000000000000b7d422ac85798cb5ef5548805bd6d3de20ada4994fc38355e92cbf0d0c9da356a5e9e1674a50a017643f652f71226e8000000000000000000000000000000001715616f53a501acbaaec470121caac29827b6b7bfd7e689d8e48822d2c464ae50158662e69c1c232ecd09f5ec946a7a5ff95dfa306f91196849d752569b35812e1db7946708cd06df9db9ee75447bc30000000000000000000000000000000010e7530ba600fa531878ad0f798a0ede2d025f149ca980bcdbb0e4316e8d2e7d2b248619369e36d21dfd766aba5918070000000000000000000000000000000000ecfa746f1cadbed34fc1ee3483307de400ded69af4a7dbb598802b7908495519b0cd4c1fa98c9cd8e82daf8b3e836e03c4308f0467520343825a91c0421f9c9c9d06957fa2fc051970f14085339e26",
+ "Expected": "0000000000000000000000000000000016bbc2dfb25ff6cb9cd03b0cc91f53c6ed9be933746d59e78c7251080856cf47c12bbecda442840675b03a812aaa5d98000000000000000000000000000000000555b0683640ef1795c918f5d10e8b3e07a09030fbf26eb34bebfbeac34e13c93ecf53d54dec5c8654cdedab2fd60570",
+ "Name": "matter_g1_multiexp_67",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f08b9765910d97ac42bc31d4b4c8bad5f3db3fe5374f11ae1c08af41ee226bbb4b0869b039fa81a935025de11b1d1fe000000000000000000000000000000000ea29999ba91652e2e6dfdf77595b44da8e5cddf2e3ae6c782dbf1f972717833d03478bb8651bc0cc7946d813371aaba2849fab097a4f71bdfcfaf435994a0c6ac3671a4a9ed0402010be83ff95228fd000000000000000000000000000000000997b39892bfe0c67c296135573975801ddb99d06de02d96853f44336fdaa25dcfe253708583f415d882115ec68dbaed000000000000000000000000000000000a88e2f75817ce91c7dbe365d67aca52186b5e94c735e5893bef6aabc61f015f854f9bd110d3201be6f35147f9f9b8fce6558521e301eabf09e80a509b46cf8ec118ee8586f4e46a7313a96dc37ba6990000000000000000000000000000000012a730eaf214a874448e654a06604c4b9218f163b979bd3700b7a7fa3856b814c380532afce59b6253344da5bffd684600000000000000000000000000000000182fb293f9a63c705501aa0ec7ca72698d7d4d50af3a0f68ee849cd3f82ac24aca2e2ee813f68e708991a97e58f2d03d8f2f7c525fc0f353700fa823a5d32a93189699206c5ba5ed271a158ebb47674b0000000000000000000000000000000015bbe08935721cc6199f9255379589a4512c178bbedf69c82a0d9cba22b285730d4f27a3629d92574b2c24dbe09300de0000000000000000000000000000000007aba01238f2c4ef0192fea78fbccf2e669f802a2822baf067632daadbc1d07e70095c14bae959a0f706092b0be10335c7e8adc0f0a042a32c733b5c3356cf4a7d648be51c1d78534ca65dd43a0c13e40000000000000000000000000000000011727d6d6cff667f5bdec92a3b502f9d9fbcded2ef12ac058ac51ccb4064443b7a2671e9ffa2fefd9b121d89bb4ded1e000000000000000000000000000000000960f8ac1e52246529fcc6f8f7cbaf42677297c00022d312e0deb5fc45d3685bb33fd68c193758258439864ba4a073e5650081a6720845a20164ef7c06ce1e73286a32dd64efbe57fe46765008dc9dd50000000000000000000000000000000014b3a9296c87b54f8f51b935a8d9ec0af44d711e3109e75fe34f07d0705e9ebf0ba5e81dd8b7e3c4b4f862570637a7f80000000000000000000000000000000005b834857b8629cdbf514e5ac2e0e2a45e4374c287bab5e4c163d669e7b1a36c72cec1ab7d857e28f2633a6e5f298f55c067d18b95591f7f14261f95513e1990f5a4f6908f94a015a93fe379726d5120000000000000000000000000000000000ad8c626ba39823a33d17a4f06cf17d29e9e0ae3f28db0b369fa0bb4b7343115fb3ded39862381822c3b2d74ab7f70e800000000000000000000000000000000117230d8da035f40c181b50c12370f159748955f63ee1eb61e8242e476575e9aaf16bd43b7e79a35ab4e2da20f43fd92b448bb01a1963bf74e0fbf99329005af8e932074358d855ff43c213e02bf26bd00000000000000000000000000000000027764a17af5328811b305c21b0fecc54a3f225eaaedbf453ea4c0724fdbd481873d84b1a7ffbdc7f1cb07c2d1efaf5c000000000000000000000000000000001090ec8d750ceecf682de76d4794f9a8bbbf3a3f4ab591fe882613c1b6db0912696974a1f2ce349bd8c79acb4891719d441fc4cb1ea8f86af8839aa40c35c0706f3a159b4bc902347009f744b73cee350000000000000000000000000000000015e707430eae84b75946f21e1fb0b6ede203b843671911923efd9674421a92ff13cd900bee1b27d70b8e8cbeccb165930000000000000000000000000000000001263ed28f531d8197606a038d7d7c3e1d732690cd69f52533470f6fbef193be5e63d5af0dee3aa8a73a23253533f8223020a1ab853ef2018976e43cce2724105a2526b28d23b0226c49ff3d4a03d40c0000000000000000000000000000000007fe70102db7df6529f732b5cc2b1caef0fe03af9824a5097922dc0b07e5ff32bc195fbdfd7b5e4b2bbcd75b1badc6ef0000000000000000000000000000000011b40afd78bb5e835227e5a08f94f7c70b06dc010f5a710a025f589521543eaff27d789d4de10fd4020879b45bc0a9dc82702398b8c95c3a8cd163a8a3cb2a7a04030ef99404c325115e9a9312e8c1bf000000000000000000000000000000000e4df86963d375710c681c5b3910fe79446e73e00613bd554ee20f47fa9e2b0cfb6c14a29ed6dab0a56c49708fc624d80000000000000000000000000000000010029bbd62162cbca140c56354ea070ae3f1028e438c70dce31e7bc8691541e59e9168e9b689c19d177d4fd68f8b1081338468a325384a9367c90bd0450816a22849b845aadaf187c27b3f09800e791b00000000000000000000000000000000097f3f61b164193da313d88429a4f34b0ef2f864ad8fdf7183c3e1da02dcbf0ddeba9bc04a7594516e6255ed59527e110000000000000000000000000000000008133f297b8da5dac5e1ac3db3073587b92a5d821949968c125e5c9c79a19b5945ab47fb0ce5d6f4269231596b157826d29136cbc4764346e7ae1af92fe64560f453821f96f32a42a2006b6edee7502100000000000000000000000000000000028cacc78001b805c3e43e92fb8c4477778ce81fca9068240e0088e344cc8201ed5bba52e7ee09d5ea6f982f30d6ea2e0000000000000000000000000000000012c5db0995324657574a27c48313674d2ad3aa931cee78ade96408c5e04e6f5f8eae88018511ff156bcc787970ec40ab675a59418f1462247d3bddda5937553e96d854b5df64a68145a193b2b1a7eb25000000000000000000000000000000001768f68b0ec15fdd37c3ad9445e53a582ab5546f9eeec590b84e11f5a72585eada71129d1b93a72b334bec4df57ea4c40000000000000000000000000000000004d6e137e66243b56bbaaac98717061b36545c1c3e24801e6e054bdaaa6d28d641821a51233175f5e5823b7d2b7b42cc544a345719b40f973398a6fdaa2044037cacd7f6c361921c62053cd51f2e5ff70000000000000000000000000000000008caba9658e420fa17950c995efd00447bd5074af9b57122240d4e709229d382e371d7de867005745a35a2a7d68fee8200000000000000000000000000000000072e0c25435616f157284b48fc8da4a3fdaefc4f6d484e071cbe648fedf30b5da4457852d7715741615317e21110d4c2bb38b4cd72eb18c3ac87860aa58b4b439712562f742f112b5d769415e9c19d0a0000000000000000000000000000000016c418a3b3f054188d6891ddadb19c00ec629a3ae0f49cb1b6801a9db0afb1b5e473c75cc8e9f352adf7ce8ac738ae0100000000000000000000000000000000110b8099a39e40541dab01e10314a0cc10fd2277c8766c7c73d32d7d0c6edd3ed3984c8bce249de4776920dfa28ee86994a849f6fb5a53bd5957e53ade1baee05702185b4d0fbb7c1cc0f46cb75614fc",
+ "Expected": "0000000000000000000000000000000011104fff0cde20e65e73185321d26defcbce9c9d3c27923a2366730c1b560da80066734c61e0c42bac1da45787f39e2500000000000000000000000000000000066efa830182669715da4dbafc6434be27a2e95140cb39738fa75cfba2b5786d27fd727df4e9b0195b49be2dcb9c2c1c",
+ "Name": "matter_g1_multiexp_68",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000188c13fde41e3c7d84ef3b5d1fa869dff4bf02cc8448ae49c6b72cc005bd06916a5d0a74fd770bbdd3d2c58839840095000000000000000000000000000000001637ed432b4ac6b5021aac0c9d5f084e1f6c541c101a3d650861f7d860572795f04e986c4a890ea0ec049da7c6025fa3f5b9d270fe31c772e9a0bb409d9f08a07887f045f906f30e2653d293b6c2c27700000000000000000000000000000000063a1afe2f64f1d04f7a5aa727cbd0e9dd9b66234120118db1f8fc3b90ae50cf493c3c4a48949441cc1e46488972d39e00000000000000000000000000000000049261c42dea531a6e8fd82f77605ad0cc9addb23e429f03f1aaf2fb8d9dddaa89101bd5b5b169dce793de9bcafc3b5ddcbf4fe86140c50618598be9185830bc1da11429162afe0528f00eb6698ec0880000000000000000000000000000000012ecb0f3bb6fbb4802479611a25781ab09c81ff7175170805ebadbc5f25d2c40bcaca855ece57f481160d49af008d2b3000000000000000000000000000000000bc4bccd65e010b69676d3c226057528dbe08271d65f83a918b06969c1d5303cb7383645fc19548eadb83649ecc54a551d7fb7121ef0baa85046567014620e1adfb9e8b3bc95adccbf2e0b0ea8f37c67000000000000000000000000000000000e3dfb86c2eefe0b25f117484a9d693702496124fd0dda80830a4e917bc418a793519dc269fd4932236f73506ecc949300000000000000000000000000000000140faa4b38ace6e80e5d3fdd57079c215792672ce651563eb013a90e66665dccf6bfc9f9df145d34894e3972eb524f86310d3b0535e78d803b477e5dc26c71bb18acfe66bd5ba5892d924d265afd6a160000000000000000000000000000000016e70554f8580b8e9c5e421c6a6495df7df846ad67d5d4334e9aa89f7e3fae505a2d335d21624e66aa542dccf38081e0000000000000000000000000000000001090383d5f42c056c291a4c4c6127315849c647783a556aba3dc41c52545549d67560bdd697fd1f47dace750483ec9b72fc9417e65cb76aa0093a7deb3d38c111c68f461a4aac57d8f09189f94407ee8000000000000000000000000000000000e8ba15ec58e5de08935384a3674418942311beff3887d7b5b81da0d03348791e4b17a06397e33e988ac6719f4d6f5c300000000000000000000000000000000159841665c915844ed85abdec0c1e78f178df2511da4d3be989f27063a8e572fe746b20e3aff056a63f4832d82a7cc75aa0b2d714aff175a0be2ba9e675a2be8936c42f15e304a146622a95dd6b3e3ef00000000000000000000000000000000167848a43b68c8f4c205613e1440f940735d7d44eb1b046e63ce50fe8d7acc5b2c020fa936d6e07347a7858be57870e5000000000000000000000000000000000aed7f9b7108aa4e7445be41bba256667ce7587a867b9b8ca70d3c42155521ea3bebbfe01bab038969721364eb758be10227c3510ed6e4c7f84b11ddd2d6caa55e0e79ed59e1cc0cb325d55b5d145aa8000000000000000000000000000000000699a81c47bcab8342b11a207af072cededbadd374aa79f6b401e4bd5d429a0443234522a8955b3a62a21ef6697410270000000000000000000000000000000008ec25a0e0dc6a3c8906a1b3413f522440d56f67fb780545fa022026c6faae016108cb6eb23d6d6d519a4aa790327ae6ad930000a9f82e082d408999b396aca2b0e435a66faba1d95e10fa0abc0625cc0000000000000000000000000000000009c2158ea44c3b590df30e15f97ebda263670c1bba0d97ceda7ea674af0e61f0b5928fe0bdcd8f18efe5340525259b4c0000000000000000000000000000000019a5534906413fdacde78ffb03e6564d8beaa155f86e4f19be2188854a8709e82d2ade21621934c1aef8be723ea91a141a6799cab8964c7b79b80e76be237ef49c2bdef5c99a38ea873af6e9d49790ec000000000000000000000000000000000165b15830a84e786d563cc3c5117a3e7dbe9dda178bafd225503467ea4c9aa894294c4fda58734eba9864796974a016000000000000000000000000000000001285a2be50f38fa6a068b75386d468d8fc1c11405291e794d5aa5157cc81d7d66c1095f2fd9289f1306f74596e9b5c21b206dbfd70e4b24bcc09ad35ce7b3aa62d17f18347f2bc5f15730202909c93770000000000000000000000000000000019d5819c1c4f10c83ca6f1596e6cf9901611c1407d6d7abab989333b37a8c21cc3deb039722a51e2dec161c38f3ce74200000000000000000000000000000000136d05ff33253260cbbfea0390e78cf66845afb4ddd0b684b928da017fbdf6b0e840431064e6e6d5bc8e417a74c811ab3a607a7301bb7dc5b9c82d956ebb0bc54568d0654d725d4d5f13ceb6231e862e000000000000000000000000000000000593e66a323cf3efa13fe19cde7a3c254c90b23bc836e1f437f4a4b85790f325f0746147aeb1d0447022bb138178bff50000000000000000000000000000000011a4b1222d0b49a27e66cd34a12f252296ecd1aeda435035f06c059aa3e6ba69acd1ae6d7da394f32ab78538f4e50a351231e0fbbc2d98bfd1039a889acac471110d568b0a24ddf5eb3501adcbaac6fa000000000000000000000000000000000613bef17f6b6b39f9f6bde785a82d2e4c368ef231d8cb89940059ac2c16bdd707170b660c0faef9e927ff7a72f6712e000000000000000000000000000000000fc85913ebe30f0af146df556c6984ab442b286fa70ee00d39a802f4c76c3e41cee68802982ea42fb25d4bb04593c0b5393c5c10d4bc4cd1567bca6960051f818e5c53704ce44dc4582767fef1092a870000000000000000000000000000000003da5997b7b3677f6cb03fe969e328549b1c0b083a6df457a70f1276d10e01d65feaa5a36cfad19dbe41cad9eba2fe73000000000000000000000000000000000345176bf6a03a49ae0b6d89d07548ed47dd67dd620e5e29066d09a00a7e3bd4b7fcb79b114a046dcc0c705068f71b50d412195e347b680430c4528987859a1552ba8383cdc075c437ef19db6eff6e1a00000000000000000000000000000000105ed7acf8c7c116842dc159553499aac7b8beb36dfd7eb717c571ad4ee1f86b82b736b72c2936925afdc3c739e0ad56000000000000000000000000000000000618b8fbf8a2aa2d1030c6304655b1df3cf8e8260b7b2d97639bd857d58606d0eceff7ff0fc1a811396552719407daee5b6701bc11c1ef3c9389710e4dd090e3db481c5400ecb91655c20694207a71f1000000000000000000000000000000000eabffb8ece92d4b22ee47560984b3efc33913953dcdf5e22771bb8db2cd8eceea21a2b14d70b1d467d692371ff499a300000000000000000000000000000000143282a2cc502f477be295d5fb2ec847cc988e43f72be848464eb4c1dcd0b1ab66a6cc30dd4b465050f6c37e8b8e08a7ab45b07c059738ead9709bf36ab20b09fd3368f7aa12c6d9f3acf3f145c83fa5",
+ "Expected": "000000000000000000000000000000000378217eb65cf5ff48e40ebbfbf03c307aabb63955f755a93bfbea0c176e90dc986a8202c6ea4e9ecea176068cfc62440000000000000000000000000000000012ac5e1a0c75ac5b96af3959a65eed134dac6b35559cd923facd2062ee06cb3ae2018db7d27dad2927b3e9c2e3dada33",
+ "Name": "matter_g1_multiexp_69",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d6ab2022d950cd2ad2f0087a079e435634a1e24008d12a349836cb7297defe857cadf3adf061e8b55ece662dd36ca280000000000000000000000000000000007682f1ced1ac2aca6ee9de682c7a6743fd32264eb0a087eb1df7c520c5748cd598be45213b398b073dccbb6bd67b44c3ca13f8540eaf45ffdab5182883d32a1d35e7cd956092221cc40232efde6cd1e000000000000000000000000000000000927b5590892a4b897ff2d6ef6d5abe32bec8233bc5f35ea9ace2ec516037a8f3d162b0161c91d4e06d80d73528a6ba400000000000000000000000000000000064d3d8340eea43bb2d54dd6f5d9d49fc2275ca1ae7212329a11ed9a94c70c80584cb6ccc1eb653f001a1c1c4306e702b3c8b045ef559b76005875bce09a66b36f295070a73ec8dc66c86bca51fa5d4d000000000000000000000000000000000322791d0e53364128288e40b621e6c47324dafcf86e9a8590a79eddc8d3e6c9d74cf9721115550e7e33868ced39cc4700000000000000000000000000000000112a246f82756d88f30e74b3f5df21e18ffc9cccd713e6509572338ccb4f52cbc0c3a6d5b5c112e304f90ffb9179238521953ea264f74bf64378a339461bff41c5193e17913c67be7e2a249c9737b8250000000000000000000000000000000010bdece8fbaa604439e942e2c78aa5904cc1a0532d5bbf624794d3f10f4b64df30838799e374982feaa7346c039c08ad000000000000000000000000000000001085372e79e1046c870b1d49a2a8ea83bcddd6bb8718c7cb340dd3032739319c54eb947d518c7e17d6e603dd3539f269505655d72f1128ac0204539f0d823f076cb3a57a7e74e896b5019c9161d6486a000000000000000000000000000000001551cb2abe299a01cfba81bb306457b662ad57858a30d55e0ae0c0f5851483123c388ba06ead8ec4fad0b1e4f69ddd6b00000000000000000000000000000000159e5ffc459d38a6b1e49b30647939f37c0d4fc02b83f9dbac123d64535752977005e0cb1232ebaa7cf0bfdc203ccaeac4c861cde3f445e3a78d1498d98b2b947056cf578652e19be88da4a786af196f0000000000000000000000000000000004111e81afa9fd09e39df891cbb99d9b62205777bebee33b2914e24570db46f75db5dbe2e9831c50f9717dc317f05ceb000000000000000000000000000000000a999eb350750cd505ea9de43945cfb0c9c4ea412cb0f0e769e62e47d08f8d50392d3a5e821f1e9c947990e6398b5ec699762c5189cf154e24238e4b157caa1d8759002f69b289cfbf3f24f5dabf20bb000000000000000000000000000000001496d3b0062e9e7166d777d90553545ee7dfdbdacb355fa7ecfecd65bcb96321aec0fd835b32c8bce462c87a2b52a58f000000000000000000000000000000000ef77e6ddce1e0eae50a1c663374c31a0c5846d6c2d777bb2f4831ecc806ac28591c3ab0222a6cc7821a45ddde1ce23e298b5f6b43074b8f0807086b03f5028709209310474c35c7ee232eec8579147c00000000000000000000000000000000194bd82f02047bc08871e431ebde41327a60e838d3a1ce6eb5470ba21a9b863025c8663f7d509a73847ed41515fdd3ac0000000000000000000000000000000006c9303814ddedc68b0047b5b2f0333cf226908dcb14ccc0aae4e14456a0c83eb4f498d559a649bb64bc78900a788a4b177bfb0218ecd8cdbc6dd9484e74e41be6971ec2911bacc8b53b9b4b8c70e573000000000000000000000000000000000736fc761eca44cd197ec6fc680de349f96e5294e42648825ce9262fef91766a8d7a084e5b598b5b47d947548e0c61860000000000000000000000000000000018eedf050da521b9af0ce2007cd664e2760320056e14ddb162db5cae78ed7ec859bad03fc60caa06081f0c24bb130ea4cac52219796226385aebf9e85f5f179362d4149c33582a97b7d2aeb05a8e6a990000000000000000000000000000000018a8e4887f0c08dfb7a741858580a1e0ba7e7ee1959284ad0955beb186e84a5d503ffe4000d5a8641575540b6b7a3885000000000000000000000000000000001946ae0b124fb60fb4dd32181783564dfb8ed0616a220d5650fcc1f6968ff70dc74535c71b0cf1019eb038c19cef0caae03afb2efea85fcd035cb4ba09977b2e1c84a0d98edf88e9f8d2c4f116d0f5030000000000000000000000000000000003cc2093935fcacc3fbe4429868c7b31fe8c8b12c1184e2181dc8da4d56b9b3ace85ad8d6b850deccd047eb002acc8fe0000000000000000000000000000000008cebb95902576d96a3a257ccfe76bc727174e08d70492dbc2132b9d5f534de3b6a7baac2d90338278064565aa67b22c804dec43760dab29c161b8f4bddc52379a17f3168f684267cfbbc3505e32d5f10000000000000000000000000000000003a03e6c183afe6aae9bee030f46086032e9d81fe337e7e1c77ac6c903fb33154bebdc15e81422f057ba1853c1f7cf110000000000000000000000000000000011f5e4fff35ad1d6e2d2d4e30ddeac28432eaf13fc7c35f5a90f7f8a17de0f61bee21529b3db3633c178006f5c5fc403ed2d3daf616df3f0061f58c925e9dfbbf6e9cbfd4b0b3896a596919fb3d243db000000000000000000000000000000001986f950d86f35d45dfeba6c3e484a6da296ccda2314d03adc37bdaaab374aa9011e07e6c8fe056e66b9204c5e16fc990000000000000000000000000000000003220ebcac8189b30f6efe6051a2be1001b85a7f94d9ce289bf6e04edfdf2ff17b17702a1ce116445d763ed1c0dee645e16797ed90581fd8c3cef1f30abaed10997f13461374ea649b29101959fd50640000000000000000000000000000000001000e0934c04c36c621d9b308565cc75ff58f6c1c778b8e0926b4d22d58025edf8a853139667ab3d3616c33d8a98afd0000000000000000000000000000000008776b843fa3b1449a0879616b3a37bd5eff5c809c077fb0274fccd67d645439a79a410fe2c2db44f52887ea7f20c6062f9f29432638c033ca84422b12ca80ac4ae85fa30ff56c913c5737aeb2c84d04000000000000000000000000000000000e7b037fccbb3fed299960355ff2c6a51562814ac797ed6b4b770ec565bae5ac998eeba19819cf2b3d4e91591e7f051f000000000000000000000000000000000143dd07288b59a279de228ea59aecfba3275a87fd8307252e6b5d567bde87088a8a8f52da57cba4c0fa0e2aed423241e6f1e5df7ff90c4a4fb9a071c0caf3a3997569538ab9837ed41d9d0a8d730537000000000000000000000000000000000b41b673bab477cdb21ae5f1c04922f2b8216d7a1423a6f6b86d4c33f0b4def9c553faca2798cba20a31ee7d71422b21000000000000000000000000000000000b64686b90964104f8e79bf9527f452d25c3c8e9d53e715d884e795d26e391dbf510d72fb2850fe66e35d31444814e650cf3283195707c30880e50ff5ef605b561c3c3c354fbe8108f93b36f212f9ef5",
+ "Expected": "000000000000000000000000000000001673148063c4f68c59d371410a8ef20cc4516c579523e2d7d2ba04b03fc5a481a30fdc6b9ebaee1138b28a9463011227000000000000000000000000000000000067e9b23610ac41d41e0bfcabc455342360d4ae4c75fa0303631e97f702b9cb660b84b5d422e8e9a74890b803c944ea",
+ "Name": "matter_g1_multiexp_70",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014cf7c57711c1708096cd33a9efd4f907112a3d4e5bad1767ddc6fb408cb7ac3f866143000154d1270c07b4294480543000000000000000000000000000000000a20191e6786d94721067d6942731110df277047541383ef9847fed9e4b8599723fd7cd7e2ca2186d56986feb8dd24d72063b046a71c2674e35466657a85d8e02253b42517b033619e31a53665917212000000000000000000000000000000000cdb0c20ac2c22a458d2370662d665005cdd8c662e318bb8652a2123f2d65d21c8e150daf51d7874c69bc039bb6163710000000000000000000000000000000008480687d726eefe93d5484ca375557e109fc64f60666e1b8aaf440100aa15e76aab6f821fde170046d2714d8986a1fe92fa325cd07502c6576dfb93ee952fedb304022656597bf3bb03a2bbc471b32a0000000000000000000000000000000011f20086905f64c21bec021e5726c05158f892658cd69536945a3337a8075994caf4fa16fe66b85e3e0ec71ae5b4c09c0000000000000000000000000000000006d71057aeaf26fc685bfc0ca071126a81224692b3eb90e37a1941782b8f65d45b6a31567c6e3d2935d38e9e02ba08654484e688799c3f0a3bbe00cec7322fba6245570685cd7df0d744473b72f03df80000000000000000000000000000000005a186d0ceb2535037b22a6455c49b6227e54c6e6dcdd98f46d996f23301b208a87c4bcd0608972961b67c523f01c99100000000000000000000000000000000142367fb02fc6b2cf52a78e4cb1157d273e9fe13ca721e0fa725f2a6dd0b4897ffe7affa25925da47fe851362700c31bfae2ef61a024e4d8c4ae277f6b1d834193df655ffb315da67afa4ee4ddcb7fbd000000000000000000000000000000000a758981a1524501c48ffc9990b738d51ebe38a0ba07b2b049110c7aa439253bfb0491a66cc42eb241a47d5e963db75500000000000000000000000000000000082adfa66bb46b97f14dec70b970469478d73d30216201e7467a927ae4ab9d93747b07ea69c406dfef789226afc4240a3168a1007abd42bc398e317484149f2fa61174243fd1748deec6cc75e7c720a2000000000000000000000000000000000de8dddf04e0c2d9ef1887ea598030f2bf3bc7bd98b8b218d19f661ec4c9a47cb087639f72fbe97afe9617acb162bd1a00000000000000000000000000000000127e78f1f41df717e5f76692b9ecf21ec0fbaf9b1d56e51b37cea02143f3b91eb1f16a65046527339dc65d29435a2874f1525bba87baee35023d0976b4a2d87524ba74158f000e5501c6d06aed04adda0000000000000000000000000000000009c37c64ffe9bbf264c475076ccbe6638653574ea84b30f4eb2601f1990f73fb5708af6007f21e4dd52f23ef5041cb3600000000000000000000000000000000170177e891c421ac91eac0dfff8bb397d7fc531e0fbd275c17cb4d894d18278a40a6c3093b92fc537244798f24eea4e92d3d7c014416f33724acaa46412348d350f93d334588d39c77dc0b8ffcb4cb1d000000000000000000000000000000000178d45abe2415895e0a550005c76522962c0ef0193cc7475a52f4d9cec9d4789406b7afa2872485722ec034df4446d90000000000000000000000000000000005e4253dde4284944b2083e07b04940cc72cb24d9866c953564bc0e847b72da59888e7a08cde7aa7c0753cda94a6e97c53bfbb1670b7045b6df689871d5d012dc93e8be65faa4a98a51db8501a4b7677000000000000000000000000000000000e48f11dee27507acd407ce1b810cfa8d0ff4414380fe26aba6c608784ef756d605c8c3ba92592ce342baef8aa927bd90000000000000000000000000000000000e604525ab4ed10f3a9a688774c6b27e679fe456190e67689959da296b650dbfb75610dcf54b30ab891c40784a9b90ff944ee8d294d189226a6cff17456e2201d17d4dfcb78f58f8501870377a6e43100000000000000000000000000000000199b1367bc3aec710e82f98d3564debe9e01ef2beb878935df4ea98e3725391e873d2661e2a27d778bd29ce6f66a9b24000000000000000000000000000000000e77a3ca6bc4584cc1c3df35b18402b75936f68f0f70193708da21649b6def59f1baec4d6d1a2733c369cb5d9a6b39347de53613b7a31583ccb214726482b770029c0ed42f9528fa74da7d2d1dd915e10000000000000000000000000000000016ee4a1a3f99134ef55398e96b86a21708388c3ddbd86746745e24bafb062a6283c5bdd771f15eb501df6a19920162d4000000000000000000000000000000001001936f457d8241a4929aec1d3769bd1955433b340481936f9443c63a6c6ddb3be4f4e1ffbf62a5c4b154fa9f8acba3b0a9750cdfe0910c544668bc9b11ecdedf1b757ff69b61fcc838c502c2911bbc0000000000000000000000000000000019aad23ac037d496eeedaeac9248842b0dec15478f62ab61d000a402cbdcc240186248ed931fe3eaae5a1d7153d3e135000000000000000000000000000000000fc1c74c4d8488edd92b42ca7c27e22a4776761829b06efb0d1b2cfa37738efb276cc5121d926665b99497841afcbd394aadecb1111ff43894123648eea9e57685dcb7a25553233a374479c24f2f88990000000000000000000000000000000014c557c44a90fa9d958d2e701cb2aac1c0204246fae4ba7b060e74e5d4ff50630fdca918c47323f5d0eff118c7595a040000000000000000000000000000000015821312dfed1e0bc2cfb23536baceb7ceb45c6c5a5f15ce0d4d67ef261a30ab8154b873513e2c44f652b93989cb6f1badde66cf749daf69a30f41ca00d251f7f1e93b0e7f916a1ba6b994d946b12ca00000000000000000000000000000000001ce81da6511eae9d2e155efb4f999a5d75faa99eed8fe784c7a398bf4b0e135bd0e8be8d9dfa2aa8ce9c63e091cb44b000000000000000000000000000000000695ff4e598b9e469bc62dffa214418536a6f49fa5f05680e09783b2f29bbfec5d43d42c969ad3b62c25c6192e328419b2f9b44c73a1a6dfba6462e1202166b63727f45dc3b8b3b73b5d06459a1beec20000000000000000000000000000000002f155e83bcd838ee8840996a3d8b0bef77334b0e8e75c8e4278411ae1012bae06959e8394dc4d1fd4ed5f07804b41870000000000000000000000000000000004daf1423e319b18dc57753d39777bb127b651f5294fe03a15dc4974eef8cffe337704c7f867fcb4c2fbac382e444a2b0cdc89e668f7cbd53a2ef6597a48b93d7d9a78950d4f821f3935edf72649e00000000000000000000000000000000000162f530647fc6290626d74753efe315e64dca2d73571dbd4416dbb41b07e8ddba40b3dbe170922c64fabbd937c961b1400000000000000000000000000000000021ac62abe15b0f1318063428d89f22d2090050b913973de571871125a391affb1cd595f9c596c9dbeb6025fc8392e48e23b377ed80bc90a4645df09e825509eebf57f59d7a2aa1b9121ace80926ccf7",
+ "Expected": "00000000000000000000000000000000127c2a1365d966520de7aef12e66e55d807b1a3e2305ccd5a78547fad6e6112d60a206412bf56866ca1b0af1b422c7230000000000000000000000000000000003a613a2e2abca1f42d3ed594a3b99a6cc51207b249aee2b5829aafb1327cc7bbf99604473b4048c4b2033e1befbf14a",
+ "Name": "matter_g1_multiexp_71",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fd31933662cde0814cea424436ddeb6a668e20b69259424a652bab722aac70b3582cb641d53bff963ead87ef5dfe1090000000000000000000000000000000007d17925b0309fd8c92e52c1ad67937efffa7ae3c783177a82f1133c8e3aee2b8fe71095b6b88b01576c5203d7dc8c3f75888762fd1de395fa80b6d8a751f280eca568de2947e953feac343fd6bd592d000000000000000000000000000000001782f625bc3b25168b1f5b388b7963b9d158c09abbc0bc4c0bf5332e1817fc083d3d55124532fee2665c536b6923fe3b00000000000000000000000000000000118650bcb2d32f4e83257cfebbe8209c2c9062ab0eb805ae2977f79ef48af6fd78e7512b331933edd087054273eab52c18ce7941da132adec1eee8d81facdb5012a15ddfe0cd6751ebbf66ce6c4950430000000000000000000000000000000014a69e56a173ed13a9e2568a8af49d74c74dd67609ca58744f96f9213197b45de6468d69ed084ed8b1b29104322ac517000000000000000000000000000000000739671cdbdf98251ed4bf13d23c675500cb66344731ea6aa66ffe401dd6daa8157676fc46b413378b8325ed4cfe804a24a0497c642dce3937d883ee25b0ea577c729366c7d67e2e5ff1ccde3b19a5dc0000000000000000000000000000000005c95d722f8e50603951c21421e8532eae710929e976d76f28c050fb2b093618489c5f892198ca822d3f287fea6eb83200000000000000000000000000000000077a07fe1348e4b6b2a46f444137eb86bf7c58e320afda3d75769a9839fefd9142cfcb75da1d1aa0e7ce84b880ff1b3fe4e0ad0d478ccf5381470a3fc9b882639dde4a0147c7c82e50bb93431b07a135000000000000000000000000000000000efd66388da0825c846b6437b13ce5014b94b20cd3a713bdbb41a80892820ea7b12b6f6720fc7aa6e6756d496ef5ffdc0000000000000000000000000000000000adeb6281219c324d14ab4dc29841d52f3f21b512ef0a784454a01358747684afe22b34d4ff1ed29ea013d47d9059c838573db9346a3c8de41af54048cc51a0edcb86f36372859d0d794f7560c8525b0000000000000000000000000000000010367597f1deb2ca9338b59ddcd8d02440ce8cc34c71a6ff93205375077c00f3f1c22e00ebc9fb60de7475400976e1860000000000000000000000000000000017d148179e9671959bf03fa1c95ab608fe2fb8b9b1a650f524a070d7857dbb8b14a67a813ba1b22e4b71df52e46c42c002257ed12262d00e78bde574a9ebd2664484a446c03fe8cbb855bf92e56bc163000000000000000000000000000000000797e0eff7ff579b0c5161c8ee06a2b99ab44e515045e83438952226046bbb4adf3c8d0538a0bcfe27a533444e2bfc9f000000000000000000000000000000000c556867cb0238505da3b55321df66611e6a018be4e181a1ec121dd55c509d501558af880a2bcc71fcc641edcffdb13076b9d21a3da0359a377c11a6d0a18bce7ea81d4128dc1e7618e6c35b9149d5c8000000000000000000000000000000001357812e6d93272645cacde880754514ee42aea3690d9d5d67e3bb5ee4444b7a3473ea2af0fc563d246b4c3e8ab5525200000000000000000000000000000000176c413594ca45019a174848f765f69e138e70dde1e184515c6f3012df4c5fa39a28a7e202c6c563db7681b0c4f8b3a9c9cd895d5d1ae0ae704e240c10d8ed4a01b319598d7885f7c3fffcd9b491f5fd000000000000000000000000000000000c5f9145b11f6af0895eca18ba6338408ce40ae1b25f8c04b40c0410a6c69b0144541e2ca1d4303c4c55fc407ca11b1a0000000000000000000000000000000010f2a09fd8b6cffae5a06bf50597a9c0d496bf5529c8925c1141cdb25ffd3afc6b51cb5d21d97c99a8d27281c657bd842467604875028997efdf5139180a8d530a1e9f18c62ddac7753cc370bf25254b0000000000000000000000000000000000c16911df03f532313d162bae1eb57c947059fb5d776ce3bfa661bad92ebacb51154697593e2321bbf85d43ae7ea567000000000000000000000000000000000564ac0f20388ca3bd483033994bf76b1ba135e229487e0c8aa10dfdec1887c62651f4cc0c05622de6356edbfd9abfef2f47637b64d28fb4facc31d5bed34b22e7b270431f54a689cd0fabd205e001ae0000000000000000000000000000000001f6de29a7cf8a89e3cb5befc926eeef59270b929edb68e9b0cd96feb5286e130f1f7c0e0d46cf2a411e499be21d47a00000000000000000000000000000000002b4c8ff1040a843a0e1d691adead4fe3d5306f89f83724a891abffec3c742a3416fe54c27c97bd131730ad364373ed0474c3ac61d4fbece967fbd0599c9a92c3fe0e53899861f044308b0ea8df137880000000000000000000000000000000005d07fdc2e2afd92d5f0f1ab6541313b5a58868d1707ff0cc9e4ccdea0c105cf9cf1f6e52d0dfd22c70aee1f7835ee90000000000000000000000000000000001229bfa1d5c5e4aa5ed0f6753dcb40952fc5446b0c5d0d90b22a7b2abc388cc18e8ef74bb2370b6ccf036f09040f62dceaf9da65e0e1752a982601e9a070a7cc77d5007eb641fffbb78d2a1b02dcffec0000000000000000000000000000000019f4a0cb264a617986898fbfb53d1bde9cd82c092ad86e608750ffa990d6926644c717f6a63279f8061b066f0c4e86fd00000000000000000000000000000000082f1b79a9ccf56b743e14caf0cf18b94f1978d164d9a95fbf87ce15c3a9b414b098fb09654c23ed2981249233e8baae5158bfe535fbc342e31f32ab4723c0d9fe95a2c64cc4e59bd41d13a08ac811780000000000000000000000000000000011c516cfd059a1b8ff75df3b9b6b135c2a52371f1a0dad631e96d8673f1b26daff9e776e9dfb225e9881635a28dd34c5000000000000000000000000000000000bb0dfd476dab29ccc80781a92f5a998b8ba2464d76df001440240957eb1237d9d210be62c9187d7f17891e837d52635d66f5a8f37a7c6a32088897abfaf5a98bd4722c411bf4b52f0f5b5648e89df29000000000000000000000000000000000928c4d78abffa6517742e617ff8efcf59b48efe0b55eaca1d93a434b84c42f29683952dd08546dc1b88bb63a35b49c7000000000000000000000000000000000d63b1f625ca9d33aaf51f8251a088642211a474deac9931c3ff8ad45f80782f62f71f014505606cc4a96f91c79a25709acdd24190589ae7823a42e8b59598eca12bf13b97aa9a0eec17f5f79a01e8df00000000000000000000000000000000131c7e90e794b09da6c4936747e6509f94a467f38ac7f4bfd0c5da88d1733d1b6871a9df498b265c65695ab3ca889f9e00000000000000000000000000000000190e566597ec19df03c473b8ff4ec0cf24168f47c89525b31b1f3592bc7f87540caa8f91e2eb2f415c05502f72673dbd0291be87a213b0a24c92df5ce42381ca378dc4b9aeb4cb9b6918263bea827bf8",
+ "Expected": "0000000000000000000000000000000015610fcdfe0bc92be1f3ea82eb0b0512ed5f448e0000951fdcb0e637ecca602f715674aab1b7555c8f8bdf886d3aa62b000000000000000000000000000000000103c3ceee1b45d9d8912887c40ca16dcaabab3dabf56b8f77cb3186b267a74a5193048ce4165c419cf727d6e9925ac3",
+ "Name": "matter_g1_multiexp_72",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cda9f382fd65f5ab92cc560477f1e3b69d0efe355e40ad3bcaf258509b6ca5e179deed8348836b0e723d5f7ca4c43ea00000000000000000000000000000000037011fda0d188f8d17436d21b9bce522cc9f8e4f473965803b242694f403ecee29d2abccbf56ab0a1f2fe5831c14380b14c6a38cc998df3583228080ea10f215a6e6a4b02ddb6d43e8f459d494a1ec1000000000000000000000000000000000f591bf508a5076b26dd8ea3b0f7a92889131142b34cba3f35a9b861cc6deeca7378d5728c0af9503441144bfc82038b00000000000000000000000000000000156067cc00e82414150bc05ca2d0c0ce1c19e5276e00434754616c9021120bbf9d1c00df6a42b76c3ffeb6e32f8fc3eefee8614394c8109338432ec72f2d9babba06f1e7b826b0f2558c3247c923b2350000000000000000000000000000000002a8128978ebfb99e20ac99ff5b3088e8eb95a7b6b354d46e775dd1662a27d5adc9513467690f377d4a13766276bf87d0000000000000000000000000000000012ba903800e9641de498d8e286c7ee48b48f7d36255823b88a24cfb67f8d2b7b6411ba3304819f588fff0d730cf130e428728d06cd90050e44a827b44f14ea35e83c9b58ce4c3a7a45aed6f31c94fb96000000000000000000000000000000000b107e62453c7181b26a3accaa624a612b7498ccc50eaf0d47bbf350b3c8c54e940266cde786c608e42f59d793e45eb000000000000000000000000000000000194c2c3717a8284051a29586e540bd9e456c0169eab0412699865c12226521796a55d598f60280cdcf37b54a24c931040fda665c40d1da93b1f132070e0b7c8c2c0ea0e66993b5a3d7419a33d118d25f0000000000000000000000000000000013228e1a6346683320d8acad4a5cb1c23cfebdb9d9c451ab81335d27e8b82297b38e1fe2fd02651a8dce3838144cf650000000000000000000000000000000000c6d54add7bdaf9ff8158680f35be7f51dcd5c26a698750c7eab857140b6329157bb7aca8d7c68f107ed9f68b3a076aac14f014117a74f21e0b698a257ae8e3d6091ba76bff7912abb6bd94d41886d050000000000000000000000000000000006e1e7c15fd14ff3bab1e9b8f8b7d6244c707744708db629ef4146b8cefe68c505ea034c180fcff95a452f7e1e5433e1000000000000000000000000000000000735faa57e1c4349be51395bac55a331a04851b41d2ec98072c5ac38eb7bb03e00ed64bcf32c3eac8b34cc6e26769c3ad81a1239ad2c945f1c560fd1674ac7e87d49aa41a1f4a5bfffeab1147c0ef7c60000000000000000000000000000000018008132dcbd9455c3932155a0b0c58066bec4803eafb0a2cc30a93b0a335738b52e6cff60b379fb04b5aad342baf11800000000000000000000000000000000149ea542cf34141fface44046aee2f6c436218374d095bdd46638ebc804bb0c9a7e1e3b01c0470bb6efc7749b8f70eb73a02689cfd2c353fc1b4d3913f5a43745fffe6a87a7c223ec3b25b321584a75c0000000000000000000000000000000003f12b0eb97856f3ead3d46a8321481351471e558add0ac4e1f285e7ee8a1f2ca88ffedbc8ed21df31d599e80b8f0e94000000000000000000000000000000001315ca27c955f3826da43745809fb1759f0f5d5674e4d94118bf2f2ea0411c7d9cbc65f054c41ffbdf196ef24eb9afc55af95ab3fd062088ffbef6ed887fd39aa1d527fe7633b876187ae12e736fcf2f000000000000000000000000000000000cca2b061959fb70d383f7e247c131f51920e048dc136036cc301f1ae6ce13809551d0a8074cc05409d124e2df6536d0000000000000000000000000000000000a9692e0263b563cda35f8497d182fc05e78e7bf88267aaebea1f5f41bd1cadb39c61431bfcaef208adcc9118d4dfb546541c6cf8217c2a95792900e8fc39581b177a57ca00162c57131ea4fb80a4c600000000000000000000000000000000005bfb5a43e3643846f92310e9d5439deeb4fdd6b5dfd3de2ab3a40b9b8b3461136b03c5601add616dd87b9a72e81856a000000000000000000000000000000000212c6c42e24a3f11c30b7751f37c0101b8a071a3d56f2d10b6c9f4f84ae12079d8c4f2d216cdc7ee93abf8b9d6973394b7c3f3c4ed10bced85f36fd6dac2646c65d3c810e6d2d116c38aa5e10b29c2d0000000000000000000000000000000008adf951da1f0b64c17f84031985bd1f3561ab44c80c339c4c753a7c2080e0f57c41b79b6cccb75662e8642ae0a94451000000000000000000000000000000000d9082079fa53008a03f58b87fe0aceb121c6c004493f3da7ab37f3236942c8ac01fc28db26b87bd2546f93b12577ee57e33f394e96d17efa30d34f57eecc45d7b4ca150a31b8d0484578151d6e65c2b0000000000000000000000000000000000f352ce042cbbf1adcc42030ba8e0dfc76b4ca313e82a5c5105ec56266977dc83626c9a9b3b5c25ef459a6feb2722140000000000000000000000000000000009443440da963a7e64d90e4642861f3f5399835fc2fdefa7e87708c033848170eb02407a6a9edadad27cb02793055140fde92a31e571ec03e509ac8a70ed5788869854eef0bf578efe6c5e6468315553000000000000000000000000000000001699cd7355b0a0be2946f8f49648bb04a90c6bc8ee7fa258a357455864022db999793771a2e66adf3cea5a54ada82d6e000000000000000000000000000000000a3ebfef4ba72cbccab5e93155429a14fd61c106ed6d2c0db0694c4733b6f1730cc9f34a5e9598c60e189b8e4943efb56f7de01ad0f7b4dcaee1123bb80a71d3bc1e63ca577a12b14ae2a11d8c0fde46000000000000000000000000000000000be5ac701c69b81cd75fddb8da92066cfc9d0d2aa7f01495afd87e44076f9f022179b7d4b4781d0b5c6c52b498b63dd80000000000000000000000000000000006f2fd1ca9a34fb09d922a76943b43505f2aad16489a138668f08b9f388c67e46a4d5df7387a1c3aa23c76954913abfae2c69d21d40813ee40a718f0ead36b51f3a50e9e4e4b2de8acd33add62bfc1d20000000000000000000000000000000019489b41d8b1f2e8ac09cf3f0930e092afd74405e213454c458cfe44e5f393a88713b62715097a1aaf01a188e8ab07c00000000000000000000000000000000018471d616eb66f1dcfaf84b7d49f632e0a5306888e44c70710bb61d4afd440e5f692eefad842b5d37762cab649fbef34762d89025196aec4f87da2fcc5a9188b4dc7b1c014dd1d705223bf9fe1e7a7d1000000000000000000000000000000001088372334c452709f81b57f5e5c148e0f88dc29dc9a118abd6911c46ee83d0c6b58ec9b854c15f519d33d281ac9e21d000000000000000000000000000000000394a7e49f32e4f7d27f276892002ad034dccc8263591b5d941eb2a5e60097e757ea67dcdc5242b755fce30c3b3b64cdffb9f3e1d43aece3af1f59319a8228cd81e668b1e250d03350958dcac9e23843",
+ "Expected": "0000000000000000000000000000000009e68140307d9309c32763e4de857372a61733060ac582922e3822e46c28f67bea87a75bd98248466e8938abdc4ef54b00000000000000000000000000000000187dccf66e6d0593ac8caf6723033db545c43cb90a5f5486418325860b692ffdf8dcf23da9103dc65336d3cec2577a4d",
+ "Name": "matter_g1_multiexp_73",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000083dad213737f1789595316285a77c859c469b9bd0cf08c61884456e4fc5ef0947847186bd420af252d822419b1de3ef000000000000000000000000000000000795a6ced1d34d91bf5ddbe77fee452699a1b32daac270b4e8661259dcacbb9c8c3776043f2e149773427fe109818c87be285a119dc8cb32b1a0c5380af736114a32e9d1ca870abdf278dfa84444f70e0000000000000000000000000000000005db83053f9824116b9d14ce0173c2243a4a8506e161db7f97408dd6fa77b65d0e0a32e95062699f7aa85cc9be448dcb000000000000000000000000000000000f20953295dde557a078c981f0b988cd9da8c7469fb7fa3361f2386c7dd609bf80ccf91cefd797eb3a4f849b2cec4370bc0535bd504d7b9658e459c2e79b86bf4e718baa82b8d6e624fba0eb141c726000000000000000000000000000000000000bc3e40ec1b6e863f75e4adbcb8b504026d0634d1d3769f7795ed2956bd450e68aebb1a9d11a71fbe5b51bc79d97aa000000000000000000000000000000001703e1fde7f2c740ca3224c1994282e633292f86095be38dde3673b78729db84bca33ee820532aa92bfd32728d9756404f3fa09243c01748954d84f4deeb460f3ef78f9c34296c6a092952bc463d72840000000000000000000000000000000009622c13e8924441b0043770faaead6db793ab818532c7323d9ee9a8d118cfd2a578e1c13723c8bbdd049b1d8aaad9ed0000000000000000000000000000000009da68565c05aa28648c0d0a0e185335b4e58903982fd361fb57f544c1f253a55e8a233b341537d78c4f229ec5f935a85d84733ccc41f71a11d61852fa336df566109c5538c2c5f5cf2af961e93797fd0000000000000000000000000000000005818b813993d7c346cd70190e1e6410974e64e08fb0a70721a0ee430dcb0d92d302943836343e274b26c69030226c0d000000000000000000000000000000000ee84b6b251c9d4f7e7abf843c73f0456968e23e79c54d8742cd5967737b9cf9ae8c6030722134c376c7c9433b749563feeb95c32362014caedf2a9e066a775e2db0d1322edc86759faa99bd70c05b580000000000000000000000000000000006870d696789986991a222b988c3623ffb51ce96ee35140e817887ea37068ec77d8131a97579f2ea29a5b45ab55ec5d90000000000000000000000000000000016b203c189343e67e10928c2a45259593cedb1a016491e94435a0823522010469729bd69af9c3bd6f4e71e96c7d8ca72edee2ea28b93b2daf4ff927991769a9c69ba16490b5676074e64f5e91fa994a600000000000000000000000000000000191a7f7469739ef4da1fcfed877b875c4b0af45df7aa9055b7d5f0c1360e4c4b7b67958d03125fade281c663923670040000000000000000000000000000000014d5256c242839e0951390f00affb226ee6c906214d8d7dca7e4fba7eaa8b1944fe4f1f93bf6ebb21b4a8585e000a76b7a07e50c1fbf1b388e9264c762798c31fe76761508d070f06adc63130df07641000000000000000000000000000000001968eb742dc0e128c94c1f0dab2ff3b0d300966537293ea16856e5f3ce5e12164d9c52fa59e08481bce84f3f87dae8f100000000000000000000000000000000098ec0e7bc53314fc8729f4688b99c3d87e7e2770877a30898c37c68a5e0a4459851b8fa390cab18e7cf0d325d906ce4f0056903b4508cffb6334bb5f645cb553a8cc61ea6765283f933686f172f8360000000000000000000000000000000000064ef5e6fe9de3e86ccc7a8b809cbdd945eef98e8e6cfa82dc64ba94070cc107090427c13ddd3bf25d542696d5de44500000000000000000000000000000000116b4babfc4b1a7a36405f597d4afb478c024805495e1a412a3ad5e9ec5f01dc47411ee6e81a9477677b89291e91c2b68031f363c8b0062b34d48f4c2e5bdba884005e52f77ac04c2f29dc7ef10fac0c0000000000000000000000000000000014d07ad766b50a6150a50decabc56f04559d1b196b713be88b5543a673ee3f4499e42b58c532e38dca0101f639aaa9fe0000000000000000000000000000000001678e7e66f44cff05163ce249df65063c4ea2d2517a31f42dfe76f67041d7927ad4b0efa4b30c33156b14f5127af190cb146e27a9d36dc698e1982afc945af9500fc5aeba719d06d0c4e4eb245034c6000000000000000000000000000000000745f042a917dca8e35c8f0301612ce198f75144e145a3c3041f4ecf893360eb0b7fdfaeefe78733bb88010d6a7b9bb3000000000000000000000000000000000e8879142826593a2f1214eee206ba69b7962e9a10ba014af5daccc1e4a2d3c893fa47eb533cd0c0a9fc1c09d389db19d983f98fe5112a55c23591bf4e259d072f893944741d9941a00f907749e3c9990000000000000000000000000000000009da4fdf5b86facd674ffe6d91d03674ebfa3aeff5ca2a659777be20109946b1bbd759d4dc2d9e859d587ce50ec3bf01000000000000000000000000000000000924985f655b00fec0bdacfc6914eedab676a962e21ffedd83be646dc17f5cdcdd3f43a9ad7ff9d976e4828b4dd219b7a62f99ac46f986f2f29f0ad3da0310f061e691955c711850a2816ad7464614a700000000000000000000000000000000187414507425106691a2dac49fea1eaa14783b2a5b79a945fee44957619793be1a68aa110867ea405a076d30568ecf3800000000000000000000000000000000034e932247b81bda0a54568f2887824028d69767b9131c106a4d204c0b2bfb929b9ed7b3fce1e354e405aeca8a28d92e7ee01b0c9c6a6ca1fdac35d89c803bee3595f03d9d200affc5292d8a7c6720b800000000000000000000000000000000027361b6341bf8985d79b6dde029a9ee54ef441894f34d60a3324edb502bdc78ef60789e5ce342c240db0fa91bbbfd00000000000000000000000000000000000bea3c850bc9d0860241fc6de65c203d5a11e6425faa503c37641522fba6fcd31643209329e6ad75a3dc5e4a4790db4a297fc700698c56877be6764f48a836d210bb33e99b5735da9837882269af9b45000000000000000000000000000000000fc7095889f943697577c8867b411ac925ea7182e47a7cd19387dcdd48fad5e558de3d80e3036992ba5fb8dd7925774700000000000000000000000000000000160f1fbb346c48a6cab0105d343c55b3714899e931e7b4e0abe68c4fc7067189181afb9c040d41e4c1f7c4e2f1b8a63b1b7ac02db15cebb8af459290c35eb5a86cf98b86d8336764c6bdda6698b49b64000000000000000000000000000000000bf1740d01ece251c0f0ee4f798872eda7f5a4ad3152d86db12844ffa88ca52835799f0b2601ed1bae6d4850cc889940000000000000000000000000000000000557f274109f745af6cd965d6e706b9ea1fa3c295cbbdb203ebf049c1070595ab820efad6652b1f1ba4e2d331b5bc6da5d1a3f78a2c2ab7b85cee68ee670f50a176e988a341303afb7722917f442fab6",
+ "Expected": "000000000000000000000000000000000c57ca082c662618951201a98d88170a9aa076fd1fc48c8ababdcbb09b63c793725261acd370d03d28ea47c0ef176f1500000000000000000000000000000000110234e4c6a99c6d1ef8b43fa897990d605af9b469045dcd0ead52b03f9f90dc441f7fe5e624349788746802e4f74015",
+ "Name": "matter_g1_multiexp_74",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ca64fb3ced1d15f94e9b234e6f6fe59d805eb0b50ae29c9b31514ea5c6e79542688e871de6ace893868fa0eafdf46890000000000000000000000000000000019c60ebb5ca4e605e3b0eabdec53f566c9b96a143631be93250260560e47a2ff6b073e432cb1f9104ff913616e7d81c834aaf86eb77ce03f1d8eacab84d5ff98a565fd33a9a2c40f2a19d7c041a7e2a60000000000000000000000000000000010c867a070e161939458694cd4015b76bc4c76eea884d9dd309d6642436a82bc76ab57b2c0e2d3ca61f34645db65f2460000000000000000000000000000000014d9df8b34369bb23fbeac29aa8c35b346992d847fc2b9e3b96345f4a2245fa8eed505daf17edb4090726052be75662308ab2065f1d2278caece0939cbbab4bcbe3eacdc80cfae6e4500a5195883de000000000000000000000000000000000017ffdfa10cc8e1a8b3751312e5bcd09772462618b8bbdca59a60701a96dab651fee0dc755969e1c3a1d2aa4c11e48d6d0000000000000000000000000000000005c2aadea5a4b11077a2a1641eef2d3bc40c2d8001e9853e44bcead87cd968ce41ca50644ea0fe1d0ec4c2d7eda9dcd058c69b55bac97a633f3ed7816e77e2a26cccc029f7e7429c86145ca4645eb4150000000000000000000000000000000012bb9b8a1537c2856d4b2bbcc6fdec6d69eb6196d795bb0f1f49d8a886076e7fb424f63400134622941b2b88ea61b8e30000000000000000000000000000000017206fbf293f1ca1f2a0971b920e702ea39996058111ac2c041c12f58f67037a3840955e1185b413859a6f845b333b58ae7faf23e841bd53683521cb3cf215577fa51f0f751714b6aafe5c740f66208c0000000000000000000000000000000005eadaee4c48dca28f9469e882ca8ccb71f82bf1f2cb5b7f50b2e63a05e78415b3c5d0767a27f19a0b1c88400116e5310000000000000000000000000000000017e95e480a145b5e897c7a1ecc1b21c5a000248f87e74bfecc21a3cf8a06c04fd075612a62145ac089f208e567e4e12072022cdd6d942158bad47a53a9b0c3be910a41036874975724a5cdd22c0128710000000000000000000000000000000007b834503ed3e1cb74738db29c91f415beeb3ac5b75bb2cbf11f4a9cd1608ea6080dd1bd50c195dbf5ab6808fe9d6594000000000000000000000000000000000eb32afb90ecf9923ec22a483ffeca3a15d358013e64e521aa42d3db1ed0397e07a85321492e0693f8f041f4f8346c6c800ae0b956e38bc34cce55bb7e88f1370a30fc8ed0e3f1126c68c30792a2cabc0000000000000000000000000000000018f208e26fd7c03313df686e27bb6ea09d9a998764e805fe6182ee221cb9ff1552e4db5feb91b3b2fa595bc32f81898e00000000000000000000000000000000137c06c3f9eb27f1c0546b3c7ce879218a309dc37c0590fc3e151d9f7fd5963f0fda201faab489dce0043c3180abf753a57c3322133d6ffac661c888995e7cb067ca1309f3e9178a266f1a410a79c0130000000000000000000000000000000016fa49bb488a35ecbfa9e714235790cf6e7c3ea46e6a9a424f59c63d018206740e9467b0575077e86091ad6e0f9f56b6000000000000000000000000000000000197185b7c82ab9e6dc8e2a71c94dde328c923eedc6e305d8f36f4b636e7662e501917b89b33877cb2094b523c969dfeebe67f3d067b0d011abb31588d1b2fa9fdf8a56bc46b1a0196e926d4ec7304050000000000000000000000000000000006b797e2bb8c0c2a5a6ef8d9f08241d42299efc8af049245c254a2e4bfd122a01954bc596750942bf7ee467b22bcc528000000000000000000000000000000000a655491c6381e81473c23565082544d9f223042c82e241b1cb8ba48e847d98a373fc68b762a600489cbbca612defc61fa1d6d0d1876a67337d66c596fbcd7eb22ee308e4a5f66cedff584f1441be6a7000000000000000000000000000000000d7b7ba451334d1391a51142c4b7cecf0032fa6d28fa7f36d2d43ba39c6418946244da3cedeb2bdfadd453eb4d54d05b00000000000000000000000000000000127655a7acb4e3271a188cfd287cc1af890756e340eb4648bf3ea3e469644e6d21f63e64f81ccb55b9b1e0a62ddf58b5f0c4ac919efdf3d0e649126da7f8ca3daa30b6ca6f3be6854c0f447a63cf211000000000000000000000000000000000129442dedea08bee8661b558bdf8c22dd391900a501f1841c77359b20c1a1ff8838829baafd2a6ab5eff31e3f9ee884c000000000000000000000000000000000ed7c27bfcfbf9b41c833fc0d8573d7b28a6d788ea3cff4d96900559cc63969ac1d5fd366fa705357626eacf402c2ec560d8bf380bc2223efc779a747c0a36f8c2b18c3e821e96163bae14b18f3739f90000000000000000000000000000000013a11df012f8a55c263c5c55df0fb682e685a5feef160d77d26db7125ed08e6605f3d67878ec78fd064487f30228f4cf0000000000000000000000000000000019292997c874c72ce7c432f20da1a338e9dc433f9257b7353f99b5b531a9997bc3a3405b0aba89ab5a2f1cda98dd8199006c3a7b5ae971e4b0ec34a1007a02cf8c55f067115ba00c5967f70a7dcef9d600000000000000000000000000000000006a56b816898a1fc9954495b711c493ace881e3989207b2f862dc41c5fe346fc2eee18adfbb9db67e774055561af00600000000000000000000000000000000013971cff1e9a6ce35a7ae40118a007518bbdc5df5939a90fb263a9c345a70f4eef2f94ec671ac6964390d0478cfbf728f29e330b48230de23e0393bf1614cd26685cafb899db5a164497955d3e98be40000000000000000000000000000000004962ef115a4288177df2f0e4665e5d1976fd027f7f87a24ccdd0584e265e2f5cf0a7490dc7824f5eb26c9569bde9d6e000000000000000000000000000000001544f43d961320d59c65563d5f04341a8ec3e6e64fc2dba7e953652232d615c90eef2c859525fed99ae6ede2c39f510a861ffae8f62572938925593f7271a56e0f559b56bf97c454c38547a2185e2ce70000000000000000000000000000000004b250ff8bea739fd73b3c3463617eaaf3b6bb9db11c2b915f7435996bb4cff3561fc268d2cf0db1705711de522382200000000000000000000000000000000001c428a889955fbb5fcba993f2defa5906ac7b6a3fee6c07f52de8d54b0665cbea84e89a0af3523213fd19f7d37944012dd907071c2d39fe710215d174452459cc31d36007a1b5570a27ca2e42c8be5500000000000000000000000000000000106fab277085c88a7d664587f67aac8de95aae908177dc513fa24c8115fa23db44eafa7075b036242306002ee6918da80000000000000000000000000000000009e832e0d01bb5e89460e2cab772c308da07414ff8b880288c7b55d6390360924b806c71c9f9762d84d8d3cb3c2f6a6199893c06db2dab559f2c374df4298707dc1815e55034dce920ae7b1df2ec8d23",
+ "Expected": "0000000000000000000000000000000010224cb0e43534025f8ba7a7c426355a2091473ab16a752a9819d8e5f3eb5b1b5c0891b1c0cc0017655dd8aa7102cea80000000000000000000000000000000004313278c1bbc33ae2c3010c50be0120bb3ec794d9ff77fe97154438606e5f6f04c1dbf8dc01b827643a31899342e1ed",
+ "Name": "matter_g1_multiexp_75",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001812b7bdac748d2c0f05f10edaccd351e35347a4a582671762c0567f55e411839ec0a776c18cd71cc6de0c3a3b8bba820000000000000000000000000000000011afad9a48c42d8c3bf74dde15d7b744c6c141ea57e133c9dde7fd762636115e0296a647fc3fbca8144048721902973fd8555388bcc6791802ddb6c0f4cde44f45ac0b5d7ecd918bc34fb9fdedb65b94000000000000000000000000000000000f4900ffdc92661bb33e7561d08ce7757ae71a2b5ebdf6427922454044c6c6695e249069e83f3053e8a8a0adb5d3d3d2000000000000000000000000000000000be84ebce32bce4d58557422c7a8c4020d1bc643a99b00231a4d4a06d5dcb56bba61ead26fbf07079e9457dd4364ab6d33e5999498978d14c9de06f7beb2fd870f6f16dc42125fa496606e65c7466c0f0000000000000000000000000000000017399488c58e24c6e1f5e9a04291930595389536480ee6dc493cafa7f0e85410bccbe5c5841a1a0e495830be7e32c0da000000000000000000000000000000001055ca833e53172ac1d2d3d7c6fd625dcc72556e8d49bb487a83e56deabee4fb672b6cf7787d1231c760c2b7e9d4e55e7894a51dcfe5a8fa4da1745a696c870b353fb03a31238b8744840a78084bde48000000000000000000000000000000000c57fc0c785d6b81d4831ba71bf27f9af318a730a9502917a68397678c7ba22f21335ca2fff5bd495676faa418fe21a9000000000000000000000000000000001012cef9cbc88b838492b6a0074e0e5d24635d36d669288acebfe446157a202443fbaa5241b288fe418e1fa50eb3e65cfb6a294589c816e18859cec34262df6490a2af6acc7daa3de861198c5bcf4b13000000000000000000000000000000000a2a4bd7c7a79c2336b05bd5e0558736697c435477d4d0dc790033366ffcdecac3bb9cf48d1341835f7a42e17af833c9000000000000000000000000000000000ba384bfc6aaa8402ff869d78973c68ccc36c20a839da8d570b6890614f692f3a3316f0eb45e4afee0cca078cded752e83c4a3460caa35fc0e7342dd2da5c7b6aae818eeaf5a2cbf4794387180b95dfa00000000000000000000000000000000143e594b8762b4f821a6cd294251a114e248974494bd16a66f27192d3c2dc56c19d886b6305d420f8b81b22a2ce4faf10000000000000000000000000000000012fff0d7edf98633e1b10ba09b3c70fa0ea8674120160933689115275da6f95a8cae1ec665f89ef3c5454dd91d291ba4d2b65c1580bb46e3a4cd9d9c4eb7dc998168c66982448abf3a4e08cd12f612b100000000000000000000000000000000159734584d9cceceb9a27808a5bbc1be9acc15c6d2edad81759312898be4efaf85420cbd004102f7b051c83b27bc3fba000000000000000000000000000000000eaaf5b8e35ea5d52bbba19087520a96348b418159e043d3b39c451fb77d5b98aeaa43cacacadf3e6ebb503f49c5ad4c120892aded230949b83bfb2dbac054b83a9dbb852bd0ad85dd1d7f715852306f000000000000000000000000000000000c62de2a514ba6a74f66312553218cfcf49828b6f01ed05561b54d5f2a87806694ada45b80429e60fb985d9cc39e9c4600000000000000000000000000000000146b134c46ef783488e0f2d6d9b7039971e8ab7f3c29fbb2635bed84b44013159f483df0e7f0afd038b64f9e5cd105726af9777a58539e5aa8b1fce0994e0e1cdb5877d93ed4db715c5aaf74d6a8bb1a00000000000000000000000000000000189f02eda06f2d39974098d874325e4711a3f4dddf78c1b9ffb025425c8abe6dbcf5a01de0ebc802816fd67b0a9882fb000000000000000000000000000000000b378df4be4566190679691561aabd7182e68dba4ba05cc67ae19cef483fae99f4cc54540b5a5180c3854f5a82b6fdd0f37e2ed8e96921a0f9bff8b43d432b382d7b59938e269c381351ea49b8c1ba2b0000000000000000000000000000000011c0ed482c1a1f030fff7395db725633a60875028e2a7763a1ac801f00a8f4aff5e19e556516df899cf5e798197f6880000000000000000000000000000000000fa7faf03f2f636ab340a9d27d9b5a66fb8daa9c083a32904a4407d408cd3a14c17734d7a14abe3655979230e1a93e4d23f4a77a2c34a370a9b59ab1cfad77212e433464d0195f0d2fd20c69141389f500000000000000000000000000000000101f93857688bc4e4da2c5407d8bc68b9304d27c89a44daf7cebeef81ab96d89c83ac34ccd0dcd87297929551810e47f000000000000000000000000000000000457eef8e4d47638f83aa2165c0f2581e6a0886595f03fc41319d6ba71da0193a4cf9f52c39c79327a69037b11a382f696c59b0bc6dbf66f42cfee34413cc4cbdae7a61e232757c75474818591764d6f00000000000000000000000000000000110957948a78ad9c04b7abea4d1caff1de20b5615909c2f5b8ab7a1dbd02b9cf2ebfaaf3b21908aeeae55e47b9a21b7500000000000000000000000000000000168f08d45ec66fd4c9a94d82d9533aeaa251186478851a421f097d00506fe6dc0392114115e3e66d8874e0aa4b15cca281c180924f1d982bf4b6a2bb1cac590cdfe84198fdecd87364e163dd988f9b1c0000000000000000000000000000000015fe358a596150d9eabe6f18e06d562f9e6c42e9df7ad9ef57be8c47c5764e408efbedf136059d0e04f81d4838713a83000000000000000000000000000000000ff7a343274892ba23daff40f5f8c56db9a4788483c16a4a0495a1f696d3304c6276ab5a6d7b3cbdce14e9711b033582e44748b9eb1f44b5fb143cc8deaad23047bc5ecb8059705e7905c37625d5e2d30000000000000000000000000000000010d66f27b2da2ffe49b7540da57c25f0d36de0c43d04da9b123c153ba3eb63f3d26d28d4cc4cfef2c0652010be2f9eb10000000000000000000000000000000004d4cf53935c01bca14c75d1be55e7473d17de6c5a2d69813df90c7612aa4815ca6ea982222793ce66bd1c69f6e456feae04d7723b7c9cb0574ba744bfed8f8a347ab740bdab99136aa71a6d635d0d980000000000000000000000000000000008ece81bc19694eb40ac3ed089d8fb0cbed88371c7e314ece92547151165a017b0a5db4eac06bb2679a8d82b296f522b0000000000000000000000000000000017732041d736996351f132c92fa7249483612bcd79532156694314834c04d3b99579d44628c52eda270ec7c3ca7c3e576a794685a342ff25dd706e4df725e3466889d8f08a27ed2f32523b117f01a84e00000000000000000000000000000000026b3730efe162d58adc8d4845706f9bfe8ff54116b518d6c3b2bc6418997a44e98071e83566a905973a2d512878cf1d000000000000000000000000000000001449b0e28d1c43ced7cd687a550ff7669df47e80d3f2ee621b791848f1f7d6cf6272e39c66e8a69c81aeb67b06c630b2ed3f23c51953e46d400802dde46c374178ef379d5c1b04d25449891f0d5623e5",
+ "Expected": "000000000000000000000000000000000154edd700b8cda3a0532b2d6e81cded6a9662547b7d638f229ac44975d3b4b2f19816eb664e6208f33bf6f8d070fa58000000000000000000000000000000000a41ce7605d7ec592ec3a030307391ac64be5df9a7f8ff9b7ba15f7f6931353fb824ae8aa76b31466b7e06cb89fbc1e6",
+ "Name": "matter_g1_multiexp_76",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001227a5d20faf2f8d9242e1a7bea89b5d7c41c3e0d8f2629b4004269f9babd2521a97cc23075e13a53f4c66a82970ee76000000000000000000000000000000001726ad8abed312a369001f53270b5e7ad8f3f2a031804ac055ed4ddb2f40eadf9142416efbc90e84f499e07a307994db8c8e071da1ae8f615631759cf33fdb876ab289a6bcfa6fba2693a58f8601dfd1000000000000000000000000000000000a07b5276098f9b3767908192f91473c554eaed23b810d3b464a3677089c45e2263600cc8d84766c7c67d9b5e6a057cb00000000000000000000000000000000175af857d5b53d195a17ae246208b55f35f4ff193545ea5a725a70f11fdd34ad2fe22431cec7835d4fe3c401c82a93fd8371fff9230243d2e6cb6bdc4cd97260a8cf0362d18b9ba8df512d2a6f5563dc000000000000000000000000000000000039e109e0c2ccb5e6cb4c5451125047bbb854488ddd74fc4360430fd80f16db3498a8be9514099d3ad50ed4376bb5e50000000000000000000000000000000003dec8af7f6805ff9df65c39262959c3c80f271d2f0e53e7e719fbb16080d7d90a1211a6b4d0513c771ddad7d3dc009063016c9a9cfbf336ebda090d3f2a1a1b265787e1917f0148f82a9c0b66b21dc10000000000000000000000000000000015a00f549c3a050a5ffa8427bd0c8b90a788c6f9150728b037232ce1148c02bce908f60ee367b70d0c9642114d6e657d0000000000000000000000000000000016831ffba7d7d0bc239563e9e62990af4f740e57ca56d0d8826a9738338e9a1d2e8dc2b8869d62090b06f5a3f68bbcd36c9f679167d5fbb29250834c9f65d3025606e2af20aedec309718f95ba01e90c00000000000000000000000000000000165e447cc890b383b46f251531cb6d29cee835fe2a0fbe14c65f0998b2911ba86337ba79decd2701a4db1916e01ff4bb00000000000000000000000000000000007bfb52f3d4a281238eb65565af329b3e043e412588ae00342144d168d903cdc9131775ddcb5217ff692b0f922504ddaaa3300f5a2fafab132f5f4662c1d288210e7502ca2472d060aeea6f2eab2d71000000000000000000000000000000000ef8ba702c88495b63ac012fd9ce54b4a7ed67b5f7d25bcbedf951455fcfa95a8c7775c5ccc875ca5bafb9bfa1af738e000000000000000000000000000000000e53e18a3e7d294b508ec4084cf57557dd1a96ece8eac9873d35e4f1ee812a1380bf56569e5e797ef54202b1ea69291df6608f7c036c8fdc335601ac55e869215eb4e626f52bae813d45b827df2afd4900000000000000000000000000000000021ef16de941ce6394ebd484f6b9de12787aef9e7921292106e6c1b18b8de5c640e448f53abd536953b07dc41db21ec0000000000000000000000000000000000a5d482a1c20571e03501b89d2bb4c6d3251bf0b015f23ecfec87dd7cfde705f946c311483ffc84381609c394c83513a0cd68c59b1371c7063dee5732182961be90b95247511a5b564d7eee8d2c7c6470000000000000000000000000000000019c277726fc9c53de1ef3aa2ae6e15b360a98b4a2b27f9057f91eae5b2a308b2f5d618d8e458839d1d60105e4888e7920000000000000000000000000000000012ea8dedac124f05ff58ac72fc967e325e00e83aeedf956adee447720f491ba1bcee564f52e4f0e53faa106ed8088d4cea52329555d9b79eb1fd6d186df80b25245ba9225553f402cfa6037592f0b10f0000000000000000000000000000000000483da14288400f7b27d712ad849fd7c068db47709f78b297c746ab3e15f17f20130b415c9a1b024bd5b24f74428f0e0000000000000000000000000000000006746bb7d3a38fd833187a16d5500d394303e2edf7d5341d787257a9f811411a5cd586b300b7b4398f9d266bcc27d9cecaf39f2a517d432d1653c37fd9a6c4a8a811107dae428f4b2af3b12e4b6acea3000000000000000000000000000000001700795ca26c2cf7dbdb64034e45362295b7e9c60753d728bf689239b0ad7073b29fb872aff047605509ecd10cbd4fd2000000000000000000000000000000000266a09604de2ccb74c5d97dfe4e9a74cf89d3612de9b2d2d39dfa3362b500be127b83566a61df49e639d548a0ecfea7ff0bad6dae80d5f47dd8c208fef0f3046cf1040112d18c596eeb934762977cdc00000000000000000000000000000000146b2b839ff63d376db418a51890c46b0e3df6848a5a39a26a02673e93ea8dec5079e89a333c85785eb0cd1d67b1e101000000000000000000000000000000000f57e8e4cdf2670dc35a12072923d334523e7ccaca66795e3a762bdda8efe5424f88ef7e4c48b0d6760234ddaad4d7370d0c40e5d422685c5c83716380eed82392ae1dc6074a7edb5759fa34a61db2d0000000000000000000000000000000001989144efb1979a42399f93fa80bdf256316f6365bd82b89e0e2371de79ce9de2435a6cfe9704ed710bdfcbc8cc2bcb000000000000000000000000000000000084230cca1eb5defbf2f2ee29fb2c47b417919f220c25bdd2a017b514840466a45b2c00047e9628852d48a057d6335ad7e93a16a443d5f981a02f0b6866536dadd276abc0998bedd76b168ebc8e31b8200000000000000000000000000000000128df806a651c43c7e0a3b2c5833bf158ea40953fb0efb02620cc4ecfc4c32a409a8bd9e98e82812b54d027b6346afc70000000000000000000000000000000005e28760f1e574aff9664e373622147c08538ed45cdad72a546e4b5840758f5ed442f8cf24cb0ba35902e64d084406f32a1d13a64c03585715908744481c79f340b5bdcdd88d685ab8b91722ee7ab719000000000000000000000000000000000289520e710e7ce4a8a671cb00a015dcf40ee2a69309cb89b514f6fb2c6e8fc92a49905893e3e0e9567956fcc86dd89c000000000000000000000000000000000d1329a4174f802680dfe8410fb45e23f96eef4649579ca8e29b3040de33cd6bc485d1339afac9593097c70a0312f5162bc6979fa2e386abec058683c6d74de31af3cac21283cd5e4244d7edd94da96000000000000000000000000000000000175f1ed2dcd584f9c59c9c747ea1841792bfd9a64747f84dfe32e256ab5a48eb2dcaa337990089c86b3dd589d276e2ce0000000000000000000000000000000014d8bb6e278ae9bd9df2609690286be593eeb668f5e2adfe880e1d34276ec3bf4ab5514c7898a6504da63e0ecfa49d020f1937936cc3766184e47f39acfe5af4497e8edf77ab34083135a9ced61d25ed0000000000000000000000000000000018adcc61d9162790bd8c19be058afcce08104a952b15efc276af8a8807a4d2edcf8557aa03a297ca01d6a3869160148b0000000000000000000000000000000004338e5f7a12f2ffdc8158a51b14dd36934f01d7fbfe45e18276f2432b1b8210ba6bc5f246a52646bdbf99ed91f2f48f639a8b60a1849c71688a11e612b315439161717f525b5deabbce75808470166e",
+ "Expected": "000000000000000000000000000000000c1f9b78641053cdbdd6545691d1a5238389614524365bcddb07f9b9c6c654e58a40047084532b8473c7d541ebb187ee00000000000000000000000000000000028eb1aeec5e4672c41eccb45b356529e5331bb5fb0ca8f9e10b20a2ef1ea911f03af896ecf7575613bce5eb8a0b0837",
+ "Name": "matter_g1_multiexp_77",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001242be79cbeb2176ecadb07d205d532bdaaaa26bf9103371f2c4d86ed1df72ba8b6d5c76b7aef25c743ec4f43e5237fa000000000000000000000000000000000d2de7792d0655ebcbdc123ed6093ba68948b8ea156a31b9f23d1abd948f4b2ef2f27a3cbf72b9e5b3e966576e9ffbd5f3efcda934ec9d2ab05f25d618e5a483e830d0452a88e980589fcd7cfc39e5d8000000000000000000000000000000000fa50f78e45b1b7b61f8508bb5842bf59d0f41f2a8192cccec6e56125ff94b402dc47d3bc7762f3196a163fb148105820000000000000000000000000000000002933cca4d82c6f89ff8db5f9239ef8fee2efdfdfa22e0b4d0fbe223910b08060a77eb4328a05ddd31d205861db090ae4507a696cc57c0bc49fb4d1686752c71c9c816d7d09bd66910b23810d475aa02000000000000000000000000000000000c15db9d1dcf646bb4c169490256050ad5e408d1f45221a9b4bf02f7651fe93ffb892c98d19d730bdf3971281c9e2e3e00000000000000000000000000000000150a6d1978ec63013ef3dd3b258ea3a716c1e564469d2aba343f3d15c30cf287b706b9eef8363351cccb79ecdf5aa189518c1259f23de4cecd5e3a40abef5662b497ebaf16240f40ecd651d2ba50af07000000000000000000000000000000000f7e810001b9e3a11a535f6744a0dd357cffa585baabf065f1e72c9bab5484829a94159c72ff2221406c8b15de465f8c0000000000000000000000000000000009d48808fbf21370420cad4df7a269e1eeac98d2aa5ad5890ff362d91cca5ab1b57fb079caaba3a135c15515e98c6b175561616c195ccc1345421d8a6efec48f0a4dc8e89ee89599839efaf95c38655100000000000000000000000000000000191dcaf13a62fd6de0bdd16151b3c27f54b40ad82da1299164da87d0cb7b4c769f941c39fb4b68a8915fa95a5ddc0e900000000000000000000000000000000008b0ad7fa07edefa61ad026d42df18273b6628b65a4e655a98b705f588494d06c37153ecdadff83d94739bc254d6d8f837c77734125181c72454bb2d37c3725cf1f9b6d6f42b721bca469fec154b3e260000000000000000000000000000000005e3001f37e840a9edba48b3b436dce520203b0b36c3871933464be1c41178f7a8af9b14000b713ee8fc0faf5cc1a870000000000000000000000000000000001732dba0dbadbe7db31ea6af17520d791feced0a7bca298b932f51f3dbcb355699db533cfc8b61d35d1a346ea5de8032981483aa66e04351f4340fd2b461165b9a9983e91c148da78d3c8e0c69e77de400000000000000000000000000000000072e4d38aa0e168255f1d69ef129642b4b1b57289e630455b147574b03d17e3cf0f32326afb7c45da468e0d8c2276da9000000000000000000000000000000000b60685ad05be8453d5d272c73365d645dab6c50c820c1fb7fb50d82eebf9b03ad3c8f711140ddaafb2bb128b7be2e6c9913da6f756005ca8ab900ab686484483af07df768209a16d807f8b88b9334d3000000000000000000000000000000001401e023aac71de3398f89893102efa8760cedf47938a655983d73ca8d394a239f37959e629cd908b4e4f5e55955b153000000000000000000000000000000001458e304efcf48594d7094d30a804742b08ec94ae479cf5d4e0575828ad92cfe8e11847d6078f5eeea4308a8f0644172188fb33fb359f21bc5bdfc85d39676c2ca0a1e619bf8a8e8de62da8818bd6cfe000000000000000000000000000000000d446202ebd7a7995a4e8aa7fcbaf6c4c4591c4bc40b374720752a150b452b461f59b775e3088733ca967854413a9f0a000000000000000000000000000000000d5fcb5510c0f7ee77c7584631149cd494a5fc496b325ba93ac5f801e34c815fe562be4758212f32ab0978930d142adf5525ab4c4468a2ec0beecdb7fb072f28260ebb3d9da1a4c274b2c11a087e814a0000000000000000000000000000000000e034e4027e846a8608680995860b2673854d8fdf0e61e2663d7e0d904b6725ff28bb4593e7bf5e2c252d9c9710e39c0000000000000000000000000000000010bbf60b95669468e5dbdfe912dfeae9945f44454df62ec116b097b867b14c402349af692490269797a30639177151945ab5a55a5cfc49cf6c36b5718e108f8d006bf7fa1ec3dc7a7f9c02a2d1e3fc5700000000000000000000000000000000095e1315b3568e8a069dee00c3676d5d6ad94a2164795ca5f1418cff4a25052e741530c0df6d50c5cbcdd55a084227f3000000000000000000000000000000001993b036a3225289827691296b51ea4e42735af0506b317932b6719a381a59c89871a2a394f4a9de0aba3bb9a2b881f86ce7aa7dcd01c1b7059ad3cc0ebf5d19ceaae633160a968c33aac5dc6adb94280000000000000000000000000000000010aad99bc8570d83847a2a2688fa61d5d0ecc978ae842715a084d99392db343f581290478bc1bfeb8bb692e0d6fd58ec0000000000000000000000000000000004f82c0527d3e9329a6b460f1d781f881073b87711771699e9cc8c4229d5112d91d4357380c12c120313d2c9eb7bb427854bce63dcdc0cf408b43690abbbbdacda5f3ebd9d9e462f89f9f50a9f7bd44b0000000000000000000000000000000008ec7244587110fd3fa0e1888427fbb3942d0885e002e4f846fb749bfc4a82bd7edd15cf81af454354006a2ea85234f6000000000000000000000000000000000fc7a19df5adfb5a154f32b9022e54b1560237f4319160c9c945b7bf4b55e45fc86616d3ec3cecc177c9f6bc54dd2cdb7603824b834a83c1c408243b51cd2c2d31e2ee763d69e2ad6d369bb6aa2396fd00000000000000000000000000000000037ab89247516909dceeb59abb90d6968ddc3ef3abffac93c68757f3c9309d145cf9350e4d8f85db810cc5f156f8f126000000000000000000000000000000000289168c6dfdc25ea10e1839e10ddffbb25522be7ff80ef321241c6cc887fc7a42586dd9c1686c6c5c2e4caff0278155923c86e91c48582f19409b962be361da5936db02b6862eefc288f9a32d5f5476000000000000000000000000000000000523020b4c34e867e75cdc668e541cfa25f2afc35573b2db083987fc585a487f1eafbac1c4267d2fdfdc5d2f94c51a84000000000000000000000000000000001581bf2744d78d680c9bb38a3f0fee76b6f0231f011b3f7ab3fd59c1ec6c99fac518857dafd410bce2e8610c6e5efbb1e1b3071b561a80aaaadb5cc24b348a2b6012340d3aebcca7e2f56983a8a13bf9000000000000000000000000000000000615745e737980a923e87c3ef72330f55e38434b3974c1cc997a9d1136527de9bc21dfa73ea0d33d27324a53f12bf6f9000000000000000000000000000000001164b6ac376ef24ce3cba8e2ae74eb58437bbbedf68b4d0b6e8b7e213a789c8c3b7f173bbe52150faed93fa83bce0a9db6863b755d3dee61328a60f585531c436663bbeab9afaffac49b6f0b57614eaa",
+ "Expected": "0000000000000000000000000000000016e6cb1f899ee8f3db4b934c1facb3928b08fabdce74f569a06ae6eeab201925f6acb1a47ffef3c608fed32c949786a7000000000000000000000000000000001796fe817d2e4a69b4e8c539f6f2179a802cb02caaeedcdb316b3ec6571c13c349e115a7a05b296d6b182c8a618ed918",
+ "Name": "matter_g1_multiexp_78",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cd7cca90c8742e7f541981a13b177a4e639195af5f15cee2ce37b01d50fb8478a3f0d0abe4312a4d92a201b4dbb030e0000000000000000000000000000000018e2a69bd1cd9bb7ea75ceedf28ac9c9514e8d28223af69dc991e46a03d8d272d267842f30552583a1f08a07188058ce13ca0cfc742607bee58988df361d7cd5d809ba4fddb209c898cd555369fff5660000000000000000000000000000000011cbbf1ee7e9cf8deae286ba67ab0eeddabd2471d2ea15e86c77c4f2f23ce38e17ac3f3e3c2a40a1640bb3485be4e59600000000000000000000000000000000108e9f887f86f03dcbd515501f69a5983b4a6d707c26b69cb9ea7a387c5a914612ef645cbe81bf29ba91d209e839c72abcca8ab454fbc576a2b910f140b23c23b14301c19e1f47989d78eeecf279862a0000000000000000000000000000000015c1856c661396f8e3a477932e1eea7e124b2e9ae0dfb1df67c4b3928c462cfbb3220c4c2fbd755fb6435e144a2b937e0000000000000000000000000000000011b114659fa71c3ac2412d5c2cc1e184f05a45871e5ab08fbe5eff68ef9e457c4f3e2bb4f16d10e91f7ee2231bc3266359f82ceeb6160d3256228d7a41fb3caa6f305b23142ab979e728356a13309e27000000000000000000000000000000000b693c93d4f06be5bc8a84157c6f407c3db14175c56310e7d041118ec869f3992f75809b209f6dd01085991deaae2a96000000000000000000000000000000000ee21d90cc3825b401e6d452e27814672d849386eccec7be992581b1fb9f4ff4f3892d63e124bd669603e6269f099452995f7d2038ad02deddca34399e5b5653fa471d998c52bd52241840cdb9202b2c00000000000000000000000000000000013b40cfe91492dc53089325be73b5d404288e8056e30cfe4bf3feb6b854eb7d0efa3ac4afa822162ac16608555ccc92000000000000000000000000000000000576146711dfa2ee08bf08121c30fe63ef0ca4448b28076eaba9298ab925c615a56d497044be803f73e9586763aad52497b67e68bfe2d7fc256e6aa610dd91dc1b02c64186d24702ad8fa9f715b582a50000000000000000000000000000000009d66d52069b0d23faa33818a8c9bfc812ae6938dd02604e98a422f50c085a5641a46272dc9c8801a9c76cdfc2020a0c0000000000000000000000000000000004dba0f971336c813933bc6386e55044f5e3d3e5cf38ede5811b4e775fb41cd09d7f136d9de6fc36f2f435b8cdfdc26198115b9f84e3ed6947bd6f0e3c65361cf360a65bc059515da852a72ec5cd17810000000000000000000000000000000005ae8fd5c52fff0b80a2c5c4fca4bccad28f580c94edb7e28ca2ce2390cc2fe476a2b11f63c3c8759847e647d5fe5d1f000000000000000000000000000000000edbff5012f6efde3a9bcad65c805b1c4ac0899fbba5fd760513c673ce8ad18d3baf28acb3344f511fd4d9785afea33c27370e1037b709015e0bf178a41ac55774a813368e11ef7a764eb48abe75dbf50000000000000000000000000000000009d003d4213a46812ea1565bd9a6f0f3da1e69e289f026e619911354cd7444dfbfff1d842e3d9c61c305b2154851b29500000000000000000000000000000000070a1387dd16f9d8b4306ecfe0e9ba7aaa5959ec917e06da4ddf90c992fc569a56c61f6372bd26e21f5cbe7d720b68c66bf5fb297948e0ddc60ba26e49ef2892ca008e64a22ff2bb21ff70c56112f7100000000000000000000000000000000008fccb033a3e10a0015b11ffe2ed5f4c96ea2262d06ca4b0eabbc15c9b299a5220444345c65e7092501b56599980bd0d00000000000000000000000000000000127583566286e52f2f2c7809cea1170a49993f171c1c217b82c17983e02b7e69cb8c948725c7a613c41f96e80c3f1aa96b488b6b63cb8bf34efeedd9f95dff4d3d8c067c0d807bd1e20bd267748275d000000000000000000000000000000000084501b09915fa13908466d6bd50a7e0d8b39893bfcec9c6876b7ed8effd100b8f0a459d754efb6b110af2becd882cfd000000000000000000000000000000000373669b2a03d3da4e907da24c61f5e7928c5fcef4e6c9ad4303fc4cc2cb641212680f7c33605212de8914caa58732f44f661845e91de1c09f581c7612a25bfa0889f77c2add31b493b37d20bcce110700000000000000000000000000000000010608a9f87f46e528d782ef81493625f9a47134832eecca6471d2113060703750b679e64179e7a1c1c81311c38c493400000000000000000000000000000000032a0c82e42be6203415638e6cca4dc1621f87f030a9d742bc77862f4f10ceb44f1ecd377acec6587be0fdc33d8c17c98b3bf8d5e529912b1b6e445f592a6d151c6f5d01d3b021a31a2669df4ce02aa300000000000000000000000000000000126f62cc3033b7235be5778289fc568a1c474b70cba2d35a0b9fdab5cf239a2d4fb03f0bedfa84425b142c04284da058000000000000000000000000000000000dc1f91754d582f57b413fde9b837cbfe3430582b0964620b02bf854c6f666914157d44a165f16ca1d7204f35caa7b0630e1c8f222019b877e66df0b6201b5bfc5b6c10aae340c55e74410a536ffb9b20000000000000000000000000000000016d277ee7864b3af3102190cc99db1cff9fd1b1d6e7fc039040149c5944e7837895532ae41b4db50e29a5d6bad7ceb630000000000000000000000000000000016c3f6e29114782c84734cb927d1a89b7755c3a8fbc99076ce3ae17f7f1d088e5fb9757237773fd4e14c2855ec12b93723a258d66f2296fa1c71065cf23c994eb8c6c35d35120d16790fec791ad215fe000000000000000000000000000000000dc8f59e410ef7145d636d2c7d43fc4b1c903d6c8c0efc3ae162293c7c65c48182f9a25c4e5f111635881533cc558cf7000000000000000000000000000000000082dcb0872d815465131953c69e260e3a9ae44d16975f361b5effe13ab1d61c18f050108e73f50871221faf28fd79771ef4055b85f37b548dac2b64608d99ca293548bebe1e24355393520c34eda60a0000000000000000000000000000000002536653a945e03329279f382937d72bddd71ff8f19053e1fb19ef83d9751eaf101676249ac65fc61a0cbacbfca3cfac000000000000000000000000000000000806ebe4d62e62904ead05f814dfa6e8a392b887bab4aee61552c6f93ea5ffec6593e9078a33f4cefc96393a667c934c212529248c51c95b5b26961f27e6d44ef1c2b9233bb2ed32c3eee79ca6c6eb750000000000000000000000000000000018fe7f7093e0313737b8e0c6ba2fb0c93afe1e8241bc769f14cebbfdb4c73aa578fe3d37ce1221f21aca8af9ab99201c000000000000000000000000000000000ea0f2ff4c8ed0a51fc8fedaa056a369c5e97e347c6883b215d0f7e019960c0178a7962415c220766c16f4596d4b9d8ce9888dd839d9b8c236394c44d358f452a4588ae65d24ffe2bd345fc745de9d37",
+ "Expected": "00000000000000000000000000000000184197d1ebcdaa25c041e95424bb891fc9eb38160cb0d91e702ac283280c6df697ae85674eccbd0fb130b6f2e1c193b00000000000000000000000000000000015593ed27279ca601616dfcdc493b8c7bd68260f97f8a9f10c03cf871b17cf8f492518d2f8569d60056721723a0172dc",
+ "Name": "matter_g1_multiexp_79",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018c31653abd67897b3bf8f046712b12d35ada1799d1c18071182fb61273b7bc506779ff2d774576a725f2f1035431c82000000000000000000000000000000000011b2fab972f183c75df3bfb7968dcdfeed0755f71ec118e56c61203e97064355200c5f016b9ed66040fc886062dc58f812322dc2a7d5faa9e4877638faf8492d84e0f4c4c65ca3aadcb7eafed2106400000000000000000000000000000000030d7e368c99113318a6657deb3c89424b9acbc5e3568e03dbf629333ed3a5cb45ce6988a3e5ef79e5ee91aa6b990b1d0000000000000000000000000000000002700af33eedebc8a4847d6772cf615413149e6d98ba3b36c96e43c8d97619cb01117570f263bb2f7579c7da67f40a25c1f6d538c5b4ae15c84581f8fd4c61160ed395816557fde197e1a013ba41ba0f0000000000000000000000000000000008cbea0d07e870d679cd20b4ad088bf3c5c23e83266b20e816f69bb918824c9bb4d0b3216f8da5a5cdc6f43359e02d06000000000000000000000000000000000d1c9949921e37e73f95b0e4c444e390bb71fef0d893d1b341b9338321bff4a23d1da4ffdd5d7148fa9fe9cc52ebbfa8f2f6a4713eb692f7667fba2a3dc35363c3ba163519d95757daddefae11a958530000000000000000000000000000000003111c080876670db10abfc439b17b32f9e96758b057d3344c7823af1b0320037906b1a9d8fc42cab9e9e0e8449aa997000000000000000000000000000000000e0c7d19a0362a173b70b6fee3d3feb541c7d2ccca71f1f01f8bd105a18024fab05e0a6d448153139f2777b189ba0fe41022e50c3fe7b2a65aab79de6d9e47c457d197e145592dd0611b1dc39941513b0000000000000000000000000000000018bcaa4869a5c6ae46e6f5fd5fcf835965d21d48871010245e722bead79d844e96e10558d71e425377f4adacb3f74074000000000000000000000000000000000414d616a4207e7cf79352dbf7f319bf554f043710cbeb48aa502235db7d30f4983b5381269f34ad6ad4fd5ff56d9586b80011c7a4aa905d4db6d4f6ae46eac9eb8bb18613d4ac5e5567990d7e8fdd96000000000000000000000000000000000c86dc8b8f38d1e4281269ca252adde9f0fe933d4cc051c7aad55f96252d1e6f9eb6f4f876e153c11b61714d985d318c0000000000000000000000000000000014113f8e2c3ac4919de334eb5c04c909b88df39998e58883a5393a4d760cb6d07c65eae053a7b2100ff3028a786782bff397789685a736375ead2312874174795586e12b230669a90d072fa636128c7d0000000000000000000000000000000009b4437230d9dae44852d88dba2655070162501702998ea5a035cd88eecb64ad7c9ccaf696545dff98d778cd7400943f000000000000000000000000000000000706b196155640680b257a537c836507d95e6d5cb7f163ca340dc0f8b80859721b7b2a2ba51dd4d72ccc4c3cb91030c928e325fea39d61269c576626984f85ea43cd683b08c3ce111aac0005adda39c50000000000000000000000000000000017bf848757da8e7ce5e5e69574a9b31d35eb628102897922d4c996443fbc970374ebd601b96b3ca9412c13f50943c7590000000000000000000000000000000014741c0b49e4f02630a6cc1a723cae1a6a9862158bdcf996b46a9614dd34527a859db0b5718788eaf2caa059671f3c683cfd9bc41303803a0b4edd121b818a126bece309dfee4133aa5314cb8a91d08d000000000000000000000000000000001269325967fc68b78cee64d0386e1fa6ecaca1f85d672f8b63831a1adfcbdbb40461a77ee0e59b1fcccb7c1d543f08a100000000000000000000000000000000053a22e8c4219e4d68a961c2127201a23443d8fddb02e3756cfdf74e616dd4abe73c4ac498ff5f6a68d730c0050b79e18e08fed30e422868f37c422d1efdcc93912d55b0a731479af863dca4705e0c500000000000000000000000000000000018248505148876ab5a5ec3be7e3a6cbac30798d52f437bea7e966921723e6a4a30a0e53518e109d1683f3a4b3432136e000000000000000000000000000000000120602fd461206973e62ec8a3f1cfedddc1e9f9e1769ac06e2a1024a9af19d402f40ffe30f9cf77b8704497d3cba4a3674ecdf795b48d62f0db0f9cce057fe570d15c78f2eb7a77b66e4895a45804880000000000000000000000000000000009cf2460e5121b15d177b8ad803c045529933d1abf62205d04726b67d64fee85e2008b5098ceddc42d5c8d95d39147600000000000000000000000000000000012749abe2d8b47bd9c899b6726ccc749bab2786e9568d32299f0e659664ba1efe764944c4087c549e2bb717c87c6b876288fc80d07393f629ef2732879332a253b49d26ca7b2bef7cc49ee40530b2b340000000000000000000000000000000008d764f80994fd37a21f6923d7fef255145ea875c892888d45efb7a37310182b04d2c16d4d91a2e7c41164706afdb617000000000000000000000000000000001156c016a289989510f1c8b39bd6a8c358a1c5611bd2286e9f15983f984e89e061e60717f1b700abaed57076e148a8a956e69f4ce8fbd8f86f546fd6d129f9760edce7c5e178dffaf987bf565e9bb7e9000000000000000000000000000000000734cd0d73ef7d79fa501b98b7211d551127abf68c473c1c72c591180b605c938ef71f66c422bf2a8bcf16c6c8946c050000000000000000000000000000000008ded96a9fce61040c1acc71d6496cf72590c63c3514c4f1f77d4582635af9eccdfab2e60749ed24fd3b6e30e3576c58ab40e86212189e6f5925df810141c132eab20c123166cd8d3c6f40f5dcf1b1cd000000000000000000000000000000000df9ecaab534bbe9c8531f813a95a7733df6a4c8785575c5ee89647941a6984cdb5a33d2eced340c683339c18f5da32b0000000000000000000000000000000003632b2377ab368bc9f735609452e0ec9fadd6f261cd5352e0a5ed6a37b25ff7a49fe57452e79e7330661b81d7d80a64b96a5b6129c58113bca713e6905c026c0bfdb6d679c203cbe2b256b0a49ecece0000000000000000000000000000000006bc4871c0271394c9d6099667ff68e1dbfa9980976075bf81fc18f1875fc91b50a0e3be622882c90b1594419da7dbcd00000000000000000000000000000000168e1dfde47d19280dc213bba9fbb61fdce41f81d4b25b2a7abae0404bbd7a413cdd89611966a7f9bc32617dca51f369d9d8147c4453cdeed971242d316e350abead3dd08e93ee54738a4a5aed23affb000000000000000000000000000000000132a2a6832653eac18e2fcb2c336292dc7990fa1a004404973029a227c9871181ffdd88a74adc3edc7a8308dee803fa000000000000000000000000000000000b230c171d5739fed98d32a3b27584bb0128434401e9e05ae09a4dcd7a017d1cefe7a46dad2db5addfb389feb9c846181ba8e52986d3bb0421eb53b18ca8c21b9f7e631f16b99ec56748baeb541b32e5",
+ "Expected": "000000000000000000000000000000000cc6517e655697449988bef516e60c8202fa48c3573967491ea2ff2db9fa0de3f542f656228a5b90d7fc1e5eaa8b06d7000000000000000000000000000000001191ca6ef2791726a31f77b0431ebe170d8fb595cf6e6b9b33b7fb0d4acbecf2d171884c392832d2a91832e982c5c0f4",
+ "Name": "matter_g1_multiexp_80",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000111de2b65f5f94851aee2861910898b74dacf013591772902239ff7f71a9cf84919bc4a84d6936f9552e97314eb52e7d000000000000000000000000000000000db96af045180bd4d88dc8c40f8cd918d2195c2f3651c176c1ee3ccb583a7363e2c2c900f2a54f26a881938cba98565f7d39b55aadd47afa3cd35cb85a89e729ca236ada965b99f64ab302a84952babd0000000000000000000000000000000000e48144181d956ebb37d72c38c062958f73de8944995c7e7568997b04ec19949b348fd80e810632462ce43c7c6571ae000000000000000000000000000000000b4a19556d8c21206c4198059adf5ac2b8a0e08c948a8a4d7465bd31c5ce5887a069df5f80b1df89ab868ca53e16c730c41ece17a6d8b4a22994227b37a9d73e17a88859683afd5d226e113246e70cb10000000000000000000000000000000010547f218e33dd9f9425c8e7be4136e65ee3dc23e0cdfd5f1caa8986162cc13b77d30259b6b9c359ab0faac9ba29bda00000000000000000000000000000000006729e532ba87a77d1e458663690110cf63eea96f8e41a5a338493ff71b68e78e78b9c929006c0410c3739b15ff2810069700dfa3b6e5fba735d1fec3b3adc90719ec301c406ac40673f4e5677da3227000000000000000000000000000000000d3630086b7e0c068c60192be8724ab4d18409fa6ddcbed02b52fa776e84e2115457c40cac7e903047fc435114150d5c000000000000000000000000000000001066ce26d2e940899e80e9c0e515ce9d5810a4048925a7ddfe0cbb24b3d8d654c6835c6872fff5a988f525c648661cbc19e8eed297661c06c92075629e163e80a08835254f7af8c0f179400be114ba7b000000000000000000000000000000000ae73f595bc9d22c8c959eedec4d1301a13c9b8c643f4335160bab4a99886694d112ed6fbfbf082629b76d1e2509ed280000000000000000000000000000000013dc07950689ba36736838714eeb28ff3be77ef8ba181718ea7b5229e01d4e036c98eb9ff7a867c017857c029f7f13e3199ca6fb7f6df8a2e72971c5738ad75d84935e922587acf3a6b6debf3c37bb5e0000000000000000000000000000000016e11b169dc405035037a10180fb368988498b6e209ad62260c7ef45e9bffedbb0587fe282d193bbf88311f3d2880cf500000000000000000000000000000000090a277517ea7a1a7cbd68598aa1e16977cc57c8d095f66a7cd3f67814c2b8f35e17e20d7a26fa67274dc5aecbe778648159c6b98bce6ed31c30957280d8f7820e9376093d1ec9ac68ce0777d02b084b0000000000000000000000000000000002ea8cba4bcbaeed7feaac63caf21645ddc97daf9250ae29994fd04e798f94dab33bac6e08eef8e6c20f122bc5f88996000000000000000000000000000000000f7a0f6ac02bc9821a883393c8265ba748f9d7c3ea763037bde3bb0178067e93aea4dc70d25e5bcda642d06f41a7f18bef1bc580e0b52b10b049f07d5115a60ba96d14a39e48ddee3c219f11c3b2a82a000000000000000000000000000000001618ee9c413dcf713699b7910989c20bffc5ba1ca03e973005f49084aba558797e7f9ec20cb86f308d737b97c08f42a6000000000000000000000000000000000db1daa5ed21250c696ca4da3e82f6623c54d643d773286811e21c09e9ef7c9ecb9d84d90b9c76ea9f65e04a29f82750d06f6ed682c56611fd060ed2b3b1dc48974769ed6dc504ca3e0b9f68b77e63c50000000000000000000000000000000012aece7d9e7384ae79e047ca4b4fe72fe541a825530d6c38b9a8fbbf8b801883ccbc3cae7c33e4d811198a7b7876c92d0000000000000000000000000000000013fb42fb1b4e7785c1b66364de150d1e38fd9fe3d8f209b7c168beacf4b26c35fe0fbb4a41f30adabe4314b20b16319561d7b314ae9d9e78f628ec5a207d12e2dcb690688d256fe46e0affdfcc9775ae00000000000000000000000000000000033fce20f9202b89411dbeea59a5b1c632435eaf29e2739163b0837ef9278ee3903ae569931e70f79a9af5a2abd29749000000000000000000000000000000000a50360c73c3f735f97d7d71b21b2831f7d7fb59c594e85b604dbb79ccc884349cba8eab9ce613ed60416994322916db03a0c47621401fc20d2c78f7e30814de9a6f838d4328a5b5be628b833c31a6fd0000000000000000000000000000000014d9a7dbc453effa7a76c774a289957b0ccd72994e568c0de345b482ed2b6db9a3a3e56e0fda159c25acb43b4a6765d5000000000000000000000000000000000b916f28e3fdc62d296e421b1684efd4e9a4b523f79dfaecc00872a1d17724e1e07e2386b4bc6d76b157ae94559d0bcde4ac6a5e740e073c5ef8af389e70c2cb8ee8c4c04c2ab4c48c579e83e181005b0000000000000000000000000000000012a4670c5c2847bb188464dafe41360f00621ceb3b5da0a3dcc16732f4baeb0491664ed8c2f95ff9b44e2b77e698eb3800000000000000000000000000000000077b561ed2fe5c91b30a12a2df71e76cc4ac882301d1975c3cb176e22874e28868655db9d0c91003442b0277eff52669c1e20d8003fec60f68c03942185fed934ebc197c2863174442d1a1c8d1424d31000000000000000000000000000000000570e1a0fe7f82c0d3cf38d90f77634f8dc2bf9b58ac473d9bcbe7242a4bb76d11f36083c90588a680004c077e957a9e00000000000000000000000000000000038ac2b58a16af0a3a0070faabe3969025440d9781e3ebc22ff873dab532d6ca1b0bbf21f32eb9728a322c158f5390fa7713ea72a2ee99442232472ab3dea9307a02fa1279129d994af5588af4fe7af40000000000000000000000000000000004a3a287fe4401c48d7dc804363941b5836cfad6490b00dcb0ee830e876fa05a42d6e2b036a4e213bbf5b6ae5a4e31ee000000000000000000000000000000001877a91254211b2af54ea910d9efdf4b4e829fda5bf6b0c2dc849903c357bfc6f55b45c7437ba538ab6cc795b71e95796f128420cf6ab4616a05b287191105f25c7212f2c39c3230fa56bc27cd06ebfd00000000000000000000000000000000159bf4b0dc89cfc9d1687d8552489b5c3e2ed059164197028bc67c51ad18b341d04e4b8be660880a76a44ef11e785ab5000000000000000000000000000000001643a41fe4104ab0bb96200472ca67064635bb728e6d909fc0026216a90083eb612f11bd5983cf4d7fe664f1c527b96a12bacb3419c34369dbfd1c968334f76bc50885028758a975cc812a04e6feabd60000000000000000000000000000000003dc904709f1da618b6a623888015a875b11e5baa5c10eb6d750354c09359b180858bf29d24bae18e7c78c81465659aa000000000000000000000000000000000c61dabb7085a1937782433ec46b0a063a34e102ae9a6b6bae7d82c94e93c3cd05afe19f0673f729761462bcd0d9ca5e5b00f26af6f59620c7130a6d12cf2091b5f52a6b638484fc1f242dc1773be256",
+ "Expected": "00000000000000000000000000000000109dbdd05f92274f3edb0232b827a4abbe115bd4d51f8a1e7b8ee609511125ecf35ca60991e75a0b7973c4085b7d4bca000000000000000000000000000000000e14a168decb6893e9c447b4366247d997701471a33bf8f762bde44473d516d857d1825255d8b4cee8d04736cb369758",
+ "Name": "matter_g1_multiexp_81",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009b85ef81b184c6383ff4e2695a8c261ab252ebd81bdb518001f110b2ba72fbf5014214f816c9453319934d8a010aa0d0000000000000000000000000000000013ce486b15a77cede98a46f66ae51d17713bef6dafbb2ff34c8f441271d52f4fa27fb88c5695f4af6d43e32333e68130acc5a8ec806f2f273120457865582b08697904a2c6510bfe9ea21eaf682fa4fd0000000000000000000000000000000006a10f5973fd2aa312ce8f30ba5caad0ae6028bca5c186e4fd55ff4e3f5ce00220b94683e440b09a9fcee238af140699000000000000000000000000000000000ae8e9db6953ce2461bac3be78bebf6c4df8bc57bc7de375aa652d793bdb0899477464097514f0fe2d0badc9027baf3898c15a259b4dbb8c300a39f0af558a9827112f6b4c5eae3d43bbfe057eb113cf000000000000000000000000000000000c0c430ee1e9112d901b82e43a25ce4e5b61c81ed7ac7220d88bd10d44d28c1bd20fc8e1ad85f9b6eb43fc232594b4f1000000000000000000000000000000001233dee860032e2f9a67d7b3d61cea99f18b91620b76f8bd178295ac4fc3b8d0db4c4ff602085c7a897435a283e2a4eda0e68bdc97fd642581f7e62ecf134df2c05570713c96fa733d3db96ace88f0f000000000000000000000000000000000061e9d3a919bdbdc42500b7daec837506bf0841caf35aaac34a3670517a59bf52343b47b46e8212208cd6fdca6b7140c000000000000000000000000000000000b87f7efb446cdba6e619d5fc04ca8dce8e57f6a76faa4a773c03ddc0666ce2d83682f24d8463d9331ae58e8afcc5641e5512cac411cd103fcd7497fdf47d1221999bcecdba30467f06ec356483484fe000000000000000000000000000000001606311f79e836a03da5cacc4e1c3930695372f8f679c8f910627f86af15d1612d653c76d88b9d33f848f94bb63fa1ce000000000000000000000000000000000075b5d9626107a486079315a85991f3d77461b45e5c8aca6876287f624694c8ef1a4f5f0a5b65eefa8d6a4746fd2e5fa32f6861298bcfd4668653544b4551d7357d64f733365a5f08ebf297a09fd4ca0000000000000000000000000000000012bc152cb7df01fd9ca35142806664fdbacb881adcf443051abac7c979d09a1c887fcfb8cad281f376ea3f6693812914000000000000000000000000000000000e32d4d6aa1f5046382c1d5e6e2f97319e8c6887b850b3cee498c482e35319a4f062be80f7f48ff3d1160ea6b18cf67824301fc5c3ab842d7f6a278fcd32249f1daf86a31dd254ab9a21941fffca98a1000000000000000000000000000000001599c2c489535375270f0d1f370c6416c83c4043dbdb4999256f187e29c198b1f6c5bd1a52c997f01ebd3622c40feb63000000000000000000000000000000000b60ea3ee221eeac4a8a364eb52ee08579cf5a907aa5642971bd5523dee5dc6d6584ab993d33d9b8ad9de4a1a4f0cbb117a920aef58100de67c482ae1fabf7ec87cf3447bde1e19d9aaff82569570674000000000000000000000000000000000b85c776ed6c9c78001ec7bf3412be495f40b0978d0582ad4f86ed54464fe562f9e699f727f36b2fc753f4328f0b2c6b0000000000000000000000000000000006e11a826fb4a8f0ac32f5c52a531508ad1363bf9b09919ccdb61ef25baa7718a4829fdd10fb6b680321cb7ef12d0c01d76d5eebc3d099448ce4a8ea6dec047b0f062c6361ddb9e95ec898442423a3180000000000000000000000000000000013539f96257faa2ae642c15f9c04e8fa7b2d6d095f7ca285e0dd90f022ec4a8fd74cf48557afdb57bace088b017b8ec20000000000000000000000000000000006cbc3e4291f373ee280eaface275e0334e46e54f65efc4e18b4ebb8ed1e61941d9c859903b56ed0d4aa3f4f3152b5b4cd4cc1453dec7ae335db989886fc0964ee73e12bab69ce1f1458d1416471176a000000000000000000000000000000000675b4dab12db428a14afd8e696a64c0bb352bbcbecdcf2b064428b489194112f1cea4a383788e0bb0e97b7f88b817700000000000000000000000000000000013273075195b02abac630211c5870727a42e11bd96a2e2c6057d0c96bb60b73db72dec3135122865cd520c525588664a6d207c08e51d64a9a47f5353faac77fbb184e1123d38e39bbada85534cbcd3150000000000000000000000000000000000cb4629e659d5c2d91c5f909bbeb3381271ebde4f8486f76c1903e86efa78da06af752404ebddb3fc5d1a09ed28b3aa0000000000000000000000000000000019202a57e95d8d2623851973c324d1ed64b48b15388e052761493b1cdd6f3b54c6f47d2b312edec23e9da4c815f02e172e1910b704d39b6a64cc7a44e44ba3e8b7e64ddfa90dfa6b5ef571f9ff7d7f0b000000000000000000000000000000000a80bc4a39d62ca891044795e2b78f4eb82a3bf38c4ccb2e6d24ced4526db7c57ebf8b1951af0707af5ae5929f727c290000000000000000000000000000000001cbe991b082e840d8bd505a2eeeadf034f8f8c2bb530c742d7953089da1447e090d82399bc332127f14f1521c95f0042eda0eb154d5f9b0e25a828c6f77541701004cd0293c61ae4d36aa3038d0f18400000000000000000000000000000000112e7894d90a5cba2a8bdd0fa750d6e57c0a9938ca30526eb5289b4a59f92bddb33f59ca22a51d1bae03b850999180fa0000000000000000000000000000000016cf6b093a188ccbf1a000aa860fc794546ab0cf261784e7b7bc5750848f685d629ba55f71f2266edcf24d27667d2720caf6dcd51a851eb200c7f5fc3e106ac5ffc432f756b942b1b9a5dde31cb2a3760000000000000000000000000000000005e2b8ac9124e8ccb6665842d77a2e9398e5b3519fa4fddfc4b10acb5eefceceb1cd6cc733e300ff95ea80d09e3bbeba000000000000000000000000000000001273d1990fa922276859d3921bbd49a452c821a9746c747734692d12c6f7d45533c0a7692d1a2d95e2d2be6dbfb3f6ad106d4a893a68b7fcb8be96faedef65181c239dc2cd752c85ae7800ca84fc2dfd000000000000000000000000000000000dd2c7410b5f5ee63ad2a9ff3a96df2bad103caabe00a9892cc9b2ed2cc3bbbb53724b2ab63cabc44da7097b619f34c3000000000000000000000000000000000f695edd4b67f81f09fa89104c81717577cdd16db30901f4f04ac97e2e0749a80d34422bdfa85b5cdb65c042d90515742b9e1cfbf140f4a3b1d06be656ad6ee5169a9cfa7cbe6efbf8173843d406acd300000000000000000000000000000000113c8f77a2409e0c7ad34186119833605f924545821895a283ec83bb6cc38c549a356b205c24f65be66fa627a378eae30000000000000000000000000000000013038ad87e3b3eb6545a0b5f7eec060895deafaf509ff6687024ada75f700d466df86ae5f95463c05f19750c0ce6cf56dbc68f77d40330ad5b8cfcda42edf57899454571c6c6465c4107e662a269aeb5",
+ "Expected": "0000000000000000000000000000000015a7b2803cd9b078d457d3b7c62a2418f19c0cfa006739cf3878844c9e1ea115fa982a02fa6fa0cef74404bcf145952f0000000000000000000000000000000018ea40f019b9226cb0428356483f842ad73140a8da065889d81e35a564e99aacc5d5d833d35fd15713ec76c65f9d3307",
+ "Name": "matter_g1_multiexp_82",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000163b380ea90b97146aa11c64b34de710e41b2ad54036a1a98659046f0e051e5961f30ea5ad78d8052f4a5d2a8388c28d0000000000000000000000000000000012afed5aa2e8c75e437fd796067e0c610a8a4c2f3368752413e6f179bbd4db25b18d5b3f8502186259a6368dd4321148ebb3c942d3a1a15cee806fdb0fc3635483743a5b0ee9c40a48700bad5da53ae70000000000000000000000000000000001bd4abe425f0418c86716516075a3ad09812650908cf383ec1396cbb6929bbc791f5cf65dbd95b51690b58ae3cab3f20000000000000000000000000000000008264362c7fa8021dec396c8355197ce4ef70e7b8894fe23d881d34b9a1b883cba1eba0e54d928b4eaa27aabde0df9b3c193d751c4f24f4808621979f07f03b2eabba75f08bb49682b9df2da7a85a77300000000000000000000000000000000032112872b64559a03629b7ec8b32344b7d5f044670f6099d8e8b1a1d47223f9a42a072975c821d03b30d0994d782d830000000000000000000000000000000016042f6baa48d7c571e1f6c7cf3c7a0887bc4e2b2de51bae133d266dcad23c579e03d3284c09c83a54eff7f2151ce5b3dee4eef524f133183b4af95e4445f3ee5084b96c32e284ebebc5b87f3d76150b00000000000000000000000000000000028ea1499ad8761d908d863849ab4bbc155edeb03a7ef4bb93e96e25ab11c6dd0c21a6f06537a688189f08a00aa33171000000000000000000000000000000000ca3ee57dbe627ae681b12e0de4ed602bc3c09558444f38b0dee27320708549491a4482f7f101e8a722ef85e3fd742a5da514f21c8eab0edb2405e673297bb595edc21027890ad680f1663fd960ce4780000000000000000000000000000000018f397d7c84b8125844e874ea31d18b8705a75027d5324390e2eb7c9962d9de07add34a436db21a34fa7fc7898ef04aa000000000000000000000000000000001591f2cbc58c0841e5eeb8d9c75d8dfa0f2dc5e479d136905abb772a6170d131c0f2c9e8e55ffa215a4bd732c2fd85556aeac9a669c962817c01069cffbd948d9d8ce764e92859f31fdaf85f5aefab7700000000000000000000000000000000135452f0f8d4559ba041dbd2ac45f15416070b1674c9d8094556a289716814d2a4efe14857aaccb82c5ada5d6f0d15ca000000000000000000000000000000000f1c47592319db60db724c9d0649d0d713320be7dcc28e7318517ef80a3fda71fd1f4b722633ed7ab7df06218ee593e940273bda92c9b1b677edd905d76d75875e5b77841befb2bcaf1fca7674dffd5a00000000000000000000000000000000003c75767678539abf7a62dcad5f90a3b4a54354fa70206e789a1f9b5daeb5fb6d9aa222476c68cf9db8a0789d7ad43d00000000000000000000000000000000139bcede61bcead99ef0d9554ee1c19db1869fe041671c199246824a923f5fd94e1da04fa17ec921bf6e82b14f126702b77e16276f9464fa2063230d6c1a4152553536c610062f18565c030e80b5cb5400000000000000000000000000000000020aadb198678aab5a71cd6dc33bd64c47be6d080d24f2f1bab7239808c10867ddcec65e27977b9eabef64455cac25e800000000000000000000000000000000141e58a9f8c9bd92d2de58bf3bbe77a48fae9290815915d7980f4835d805486d678ceee9676ab4fdca51d0fff411ab1b0be15b654ce22ae4e32987babc4863ffe2bd8a459d0f01f68fe84a75326889900000000000000000000000000000000017abf5f132e8e466d2cae445d75978645c3b24284e1b7df7773c256ffc342d1484976ea1046aeb5307f735a69e2fd20a00000000000000000000000000000000087ce2fc44b9ed797f29c352393a8ea109281514490fbc7dc489acb55753fd5c577c4af0ca6c267c83408cd95b355e26c8f1fe94bce21966427380b6d357a3599e9db03a7694159335ffba26fe29e4650000000000000000000000000000000000b106b2b94858155849ec36741c7fef4d97ac704baa6752e8230e172da7208b7e9f187ef0a6cf054d00f2cac99235b8000000000000000000000000000000000d94c6e2349941a20884b9c2d702237c5b5ca2ed277bfc79e53452f1cd6f9f49360215d20fa06df238a7ad4ea253c93ec6d34471ed00035a484f97f4e8123d40ca23b017b94df65540a5551b905e57b30000000000000000000000000000000019b33665a81d0ceecd43f003eb34e1292945da1361adf118f36aa5acb71bd821a6732758a4aa6988e29d4cb70004df45000000000000000000000000000000000f3a244e578c66a9263f020e2f6ce49dd655c7e40a992c44cee40e1c874588e464f6254ba644e46adf348a26025d6d3ef3abd467168bf5e57f71017b5779bdd400dbf416f34f105fe747ea2f8cf4a2100000000000000000000000000000000015618db18e00670281adb20c975f4774aaf169a653d5f583ff6966113fa773075db78507847586fcae82d6a468302706000000000000000000000000000000000301b18d0fe7d0db7793c62b3da072f4cc2fc3425583537110306e31cf63b228cb8c285029044c7b9439c1227d4c7ace2809801eb18d38a61ef8a80f13086d6b1f85ba751cdb8d17fbb9ad5f8d0f835c00000000000000000000000000000000053001a82260b26e34e05a203c8233095da1da58c5f804da9cd6cffce07170e39044394f379173e1340da055066d320f000000000000000000000000000000000bfa2bc7fa0476eeffae4df98bd814db751eeac1dc67205c7629c9921928b55c70c2abe242728bc078bc2685690a38503521c9cf035b094d754db994fce3161842a9509ec8288699680c0ac7761eac680000000000000000000000000000000019a7f78102671f6d84ece4a5bdc54e59cbeab60a8c6c15a708e0169f42a52e98bbc1f8ff52f34959befc859d308fea250000000000000000000000000000000016b5d76caac944612d1dc687c6dbaf10ba60a12b491b17b6c1c876a5dff933c4bd9c6f923e2ca4cd1dab38fb06dfab6a9c8c2998d141b9cd3a82507b6dd97e8d32e9e759169c575eb484e9a1559427da0000000000000000000000000000000007741d8f72a5ddeea2fe82fbce4b3d0aae61e1ab9243ae6a3200711051ac74f30a4dadb597130fd8389353c230b6b7d3000000000000000000000000000000001809f1cc2fc23be0f05b3d12e6891a6aacea121e6db77400638031065d75c7b3fd9a02ded481eb3893b2449aadcf53d6dc83c1ea9e4f4fc12a7190e6c71c4f35d1a676d39e30fe688a05820dd98966400000000000000000000000000000000013d9fdf041ecc7f2c728fefbd6e9da3169d872406b6fa77a52e342fa8852358b02bb2ae7ac77f83e2b25f0120603d0e7000000000000000000000000000000000101ae8e945d31a98c4dc3ba0e01592285c0c92721372bee6b138d9148883970708ad5e585a1b81d82ab0656a3b03a2c00be1b9098f1873ce155a66899877c7b48ddda363ae1d2353cb3816f1ab15ef0",
+ "Expected": "00000000000000000000000000000000193115466c33711b07826d2a021792b7c238ae67e3bcba00b24026503d818f912c5635f85e85402e3a6b2a8152027afc00000000000000000000000000000000157fcd63d3a0e48e25ca0196b7ade453fcefea33f09123434f418cd1d65bba65a789e4c7d6ddc92d4fe8aaf6bffb1ef8",
+ "Name": "matter_g1_multiexp_83",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019f625f232faeac09266c2c4881f92c980db551ea236dc1250189c1e71dbeb151cf74e43b4d5f465c6ad92d75457d10500000000000000000000000000000000175ceb7cef0f8144fd4dd82428bade99833023125d34fb296f198673f4848bbbee343f2f2137b55b5f8c5f74032c1ccaa9cbdaa0ddbf854861eac6621255b2102e5343666c735d0384049d5680d105d4000000000000000000000000000000001353a419548d05e568f36adf72d40ba8b30be9a78732660331a5196b0f81b52330ed70e5c635acfa9ffbf083e46c8ea40000000000000000000000000000000013ca17c0dba35a747bcd314d87d1c6558e9f569955aba3d958cc5736db78d16132c9dc8f93d5eaea749a0452c13139da92073d958260a55b70b580f3ee27c42553b5b858b66f6928fe74b4de91c34bda0000000000000000000000000000000019a1bdc1f5a43fe746df46a7559bfa0bc5292f574fc424b134fb8b2d971e191b3c5d222d39515dd145819d56d5379d12000000000000000000000000000000000a08d0b7c7f5d71222e984bf574cdb7de76a7b3c61ab5a3ec202b295c62366dd958ffd5bb5a5c6c84584342bc76199c62117f11d78dfead915a94f11fa7e904a96204ddf1835d3501639b83cd5f716f50000000000000000000000000000000000f2c85f34994643712207fc431219b925f4e701732fce95bfb387ac26ff95c9b10408d24aae5005e437bbae924816b2000000000000000000000000000000000d4377368df00dcde448d8399ceb7508a8fa1c17e9d9a5e09c4fd7c09c253529c07068e4484c7e7c6d3ed6fd3ca777fd9087caa1e89e48f05bad1d720477199410941a6105f911d589e1f94a851e0715000000000000000000000000000000000d1483ef230a2ce75a59e07f83091291d2524b5d043db8d5583914a6775ce2c80368d9441aa2dd53061a8d9121a025ac0000000000000000000000000000000019100e75a72e07391db9574b3fc4aa1c669436fa802a1a5d71146c5f4b7fe118a5ee71a9df50ff67633f161fd151b947255603b470c056b3dfb3acae0dd45bcb3d014765a5181760336deeabff3f00be0000000000000000000000000000000003a88ed50b36d92aa4411afd0a340497962c7740d629edabd505d6023ecb8f9daf0e5bd8ab9dca26ed2ae3ecdfd98b680000000000000000000000000000000013d9d64ab16ce9401988db4855b26b994da09481a339c2a2597401adb72c80718a4df242776f09ed208a8f34ef7f67e6e0eab0e2486316956291feb44de6389b20f8bafe9cc890d86d27a598bab0f3c40000000000000000000000000000000013b16751ff7f6af64c06f9ae6f59e1eb6c3ac76355e6192e6eb44bd1a9f866705eadf0d2907e2458462ad731523bd340000000000000000000000000000000000ae691a4fbf3d0fc72c0e14d4b31fc19c52ca07a81db0ba93949c56a9b75433257d784f7bf0611259dba8af77403f536fb9436456262e5149d02b33a1078e198bbb681699b3f485625784df444bfff670000000000000000000000000000000008ea61aba918d691a0d04582e1f48d671df39bc7de29a6ecc17b31a32d485fb1dbf499e01a9aae5ea21be5d6ff9808de000000000000000000000000000000000f7e8863a541be553b36b8424ba6ad057986a9f78454aea770449a23de70fea8eee6bf8aa30e96e90df9a373917452f70e2724d3501e3d79b85266fd83a2a6156eeb48e749a61676a1c92ab9bdd6b8990000000000000000000000000000000010d41968ddccbb34b3faee226750e99301ac068d8e6f13e72962b53fa2d019da108af82bdadb3cfeecfb85f53607400b000000000000000000000000000000000a90e50ac4e0c39f579a19d49e6f64de6bdd5d6a3f9a91ab654f5be01b258af8709ce1c5a994501177d1c70b25e474a9a49344fe6ea9274a103f323f3d9381e91ae48233dd579944e12afdeaf854000f000000000000000000000000000000000e85db21593e8d3d86df87ceeea7d7853758d69e15edd53fd7da52f0328805db785aa9aa5db25417d76d796200a37d1d0000000000000000000000000000000015d76c5317e1c8cc5a58a0cf0700ff73d92e7f60f4094030716bb8c657d5c75262825fc0683a88278018b4899a1c1ffeb44aeaf3ba8b03e7ef7201415de7365365b828f2c1a38d09153e51432d35b9a70000000000000000000000000000000014c9d6aa24bb34080b9a99d31e1bb431e911b2ccda3c8dae9c2c2114abca597b3849c5b3dca756d0f9ff97616c0b724600000000000000000000000000000000050224129c08fbb2f2d16596f83e2d09a09526851c4d52e8d5f0afdae7001af0006edce648efe7d94b6712d012817ff753961d33104649cbfccecc7eaf33b7a2a486c77dca363ffc9fbc9ce4e8c1adff000000000000000000000000000000000da4574f20849e04bafbc41bd361e8f4411815b9e7c2fdaa9a3ee70d4f608f89166dbe9e1cf4ff0fc9ae98f27e115c24000000000000000000000000000000001463727b23e6afc17101cca45de7d08b78358605c7b1ca089fc52f6a3c46f590210083103e51a122ed0768be2adeddefa04e97c20b42dc265271740f27f1a833bc5b324bcb843a8f9f8a68231c663d57000000000000000000000000000000001363808474ae9481f54d40fd35ed90c23d4349403d43af0dd603f1db6f5fd5ad8b77d21426977b78f1f5397df17f0bfd000000000000000000000000000000000118560d0cb0eb2fcd3b2d51fb2aa379112b3075e1d4c20757ec241a4877af271700d3412a8fd6f3f5a3dbdf4dc8cdc9b688426bbe9ae054acb6c1fdd4195f8a113727f5617642a5b3c0c65566e2252700000000000000000000000000000000040c13a6f53ca485a578c6f3f49d917b774f7b2d1b15ed3e748a47b0bc0be8a7809f0ccf509f09121fdebcf8af46023b0000000000000000000000000000000014fc7869df366473b2c4adc2c0b12acfffeffaf22b4856bed6ec6d15f0f080596b81f3aceab9360e99f35ee7c43f1e2fcf365a86a8d08db5cd95f239a2f3d22279556975ecc3baae0b774b0323dbb1b600000000000000000000000000000000177b54249c613f044b40a11047778c86f09b20ab387ecb8165c83b36a1af046936623fb00764740a90aa232b7f7ae6bc00000000000000000000000000000000040a52fc58007717d6e1dd8486cfccb1f75827c2feb2b7d59b927c4bd23e5ea80d120875f611bed4b7c12b8a5c929475528715199c9f47fd6337b6b0e807e230b1397885fded024431c70e453f55f365000000000000000000000000000000001918e41c557305934aa72aaa361d15843ca77c747ac16cb4c251a2f0d7c218b60a5588b0e5fb3573e8186a48d725e50f000000000000000000000000000000000cc4fa5302c177f9ef018445ab722e568347f4f970dd893e3227756dde9dc8cce3eb2bbbb4c3cd98af0ed4a45c022cf1c32e8643f38f8177b788b8c2bdc25b668308d914fce35c6f9023a769334a51d1",
+ "Expected": "0000000000000000000000000000000016da14ee1ec80ebf06c0622a500a8eb5a560dfa3439a8e53a19b51c6c4576c31a5486c4c49a8050cc1dc30287f33b5b40000000000000000000000000000000003b04355b2d78266675927706874bb7fa67d441886972a8190a45398942622f09ece67ea74d49bd97827fee82d4a7a37",
+ "Name": "matter_g1_multiexp_84",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e0ae8df03e4d6e36e1c156a35425a3b8189b56e8ce90045d16cfebf7fdd973d207db6391dcd007c311af34f495cfe0c00000000000000000000000000000000198e58d5278b2a82606af16a9af3f023b7182b6b5b2d685fb667714e9fb5c7a3fd5c98dbcc84ee31fcbeaa8f832d7c854f8bfa3d47ed33a05fe3da738797f18ca5d5b8658055de5a9f85bafe6078f7fe0000000000000000000000000000000007a130c85d67f97fd0dc2159d35be8984bfbe94c28d9d96bca8bab844dffd9a6eb3052c619646a4e564c0d47864b31cb000000000000000000000000000000000e2b8362ef5fa5be398a3589413ea69e98b15cdccd203119b79d96405c2c9ae9ca8eecc7533512a25421e1748ec3a1b74b0d302be94d437b8055586aa77ec1fe616e30552b4d7d3471ea219c148be069000000000000000000000000000000000acec379756a1fe9fa72f03da4dfa18de1fad19281f262ff39fec77684f0798b6d8aa895db93dab58165b67a875572cf000000000000000000000000000000000a246df19a23260961ea578a68ab4ae8811f9f391f673eab2b6fdd56dae8ff3b059e5b69052c9216529603e7eaf4ff306765d7f1079b142e513e604d577e7caf82cacae59fb98c6f8990522372dc906f00000000000000000000000000000000001bf749b61d7081f1e6141380deb6a5517d64e8c290363306fa23d6ba3b4e72ef53933f15ae77060758287a5a5c2bd4000000000000000000000000000000001661c564a5bc4dd852f35660d1e7c8193d76a48d1f0f3dff25adf312e28ebe9ce8972366ab224a95a7c1f6146b9f22412eeee02d9309af8c74c78e21836f4e6a7a6df5406617e2b4e9d300e37d8a2bfa000000000000000000000000000000000462a37cc68530a1c45001cda667e1ec10283b826b52986adec03db59a266cafc18ff76a666c9de9fc2384c5e336404b0000000000000000000000000000000010736bad21840f49466d9db82f01a922f4d6ab71f8d8ae246765300531b2f806663da2a8c16c644cf871a877b210b9e3f8449caedd55f0a08825cc1a9e985201c8a7a54d1c4dd96f0ac54214743941810000000000000000000000000000000013ee85b0c8f999c9d0682bf3f18a553b64aed8addf87e4baba55c6ad88de9c9955b82155caa83b8b6b7961d88c16c7dd0000000000000000000000000000000011bbe00b5ddab0b579375e2014021e3bfb1e11b7ccfd774b8679896c0ee34d1d19890fe5cf10e33e3332283b3a3dceaa28ec5f9dc48931da70ba0cfa7251953e24c4c95cd019e00ac6fda095c1302a01000000000000000000000000000000000fc3750c957b3eb656ad552c3997755bf28a54fe4aefafde15619133ae04a47f7c65122c86ef36fedac0c8e0d93c3836000000000000000000000000000000000f7f21014b7a9f07c2212af1b85395ef3072b84ee5e59ae675f6fdb9cac858b6213a264a202e29b45a57c69be5259470dc6046b43e6982f11f39412cbdef14f8e330d37fbe6dfa9ddf3656b86f4f60e7000000000000000000000000000000000d1fdcb6768654b6bc1b4d885039f1649066db8037f212b2d699c02606257388000b0543d25aace7cd1426462ec25c6b000000000000000000000000000000001386eb9bb7d8be5cb9e74a37759458091c44eb814dc3afbdf017a891359831ffcaad85d00d8e100886cb5624562ea0390adf4625ec80149b7810767c985c2aa0187987b3649cab8c59a892404ff2aeb2000000000000000000000000000000000f4d6551f5587cdb4d92e13e3749f977f5bd35b5b71667edd79b5006d4b0943331a0b417f669c6125edc42099bea22be00000000000000000000000000000000041b8ec8547b710bf2c15ff41ea779f996db7996911a5b4ae9f23073e02b2c252592229af738f684e9cdf48aaba0512a345fd17367ecb06b29d764b22dc1e262ba1a339b6f0e0c77384245e3d41cda970000000000000000000000000000000000c4a3756f2affd338f688ee90501f4bf4be43a4549ad8ea6aea69e5a4be015c97ef088da1a39d1103f866f1675f401900000000000000000000000000000000023e5d0bc92794536d59425c4bdf18dc5a208841953e5d45ae91f25d3c61bf66e704a8ca62a574ffefaea854fd23b8d65ce5e62dd15958e6298cdf4a4e899e53644a48494d04fa6d1f73f2dbd645817c0000000000000000000000000000000010129a00ea1c30e98c40a6c86090327d0a9b6c25b488cb0e369bc5a0e0658ec9ac9305e5d1469dd43395f72ef8a0e7e80000000000000000000000000000000006d2f5d4f3f8169f722427dbdee62f45f9791e55988910fefe188d6535fa15e2aab8de5130e81183e6ca25a8009be66f853396021d32530351deec5c266a65519471dce2087485781f33a1423755ef3800000000000000000000000000000000005364313c0d2220ed57bf22cee05b77a53c24c97addae502c7b3275a19522b8ae8167194929770191b96b957b19e5550000000000000000000000000000000016ca50cc1aef3890dd338c8a89b906812ce26e0ef9035d1a026f686b0eecab718f6b0ba401556423ddc99d96dd812d566dfc62eb59bb84b3b6599bf3ce7af229096a8fd5925d4743a5ea386a26c9a6d00000000000000000000000000000000007dc52982caf2f5efa3e1a21e22cb8fc53cd0355f2777272806710a96a22f8e896d001bec053acac6241c7637df158a30000000000000000000000000000000017e9f4fb0adb96150095ad5f0d464549d1489d04c4556576865ed3045e0c477beea3115a6ce63910f797fef29f75bad521d35ee6d29ee4816b91d1664b5957767b4b8066775b37c3b3d08729c949d6e5000000000000000000000000000000000695feaefc8fa22f81bd48a41e6c85acf38fa542e96a7562b8d65834c2f64cf5770ab6731ca85b0c5a80a73622acb83a0000000000000000000000000000000003df65226205511218c263af6fe33a09fa3db22e636da54dd967741657e9da6367fefc5e33a370947f2003dc139765083d283067bac390f556891a531dfacfc4795358229bc9a651c0aa71d601bdd56d000000000000000000000000000000001588a4aaee74856a9d41305023b7eee367648085516c8135fca8c0a6c9cbdecdb2d7b44317286f3a06f92b9eee2470170000000000000000000000000000000005aa06c47bdbcaea82e910b8a2c43c13c23bdfe1897efb2a57d622f5251f0db6293ad21d988c3ee30e33f3a40865fadf873724ba35e4e8b731db36f5067aeafd33f2e966977bd0962fd57cd5ccbfe87b00000000000000000000000000000000140d9a251d355cc6a8ff9fdf2223df59747eed11ad140297b6189a8d49a711ec748447ddcc45733a3c36a48da8cd46880000000000000000000000000000000008ce7046871c0b7f781c667958ff22da6ef5447bd319b2df36c9fae9f5597c020c12c7fbc733cb75ca8f9d9dfd942954cc5934c02b63797010cc8474e90fa5dc88d73dbe5f9be605bf335057fba47ea3",
+ "Expected": "000000000000000000000000000000000f1abe4dabd68ac4443ff50c0ecc5425ad60973dfbd2b29462254ad618b303dda061d80b28117803159ba503214b9ccd000000000000000000000000000000000d3da8a424576cdfc147e18fab66de0d1f93c05c0dcb08d9d5b2a9f5dcda76600b771991bf2d67061ea5b96d20a45c14",
+ "Name": "matter_g1_multiexp_85",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004d4ad5e9acfcabc0b93eb9ea59a778a37d7beca03e285382d10d97803ad63e11aa2e3cd1eabf72383d93528e309c28b000000000000000000000000000000000855cbcccda0476699ad3de8d58b4502f9e61bce8d7db37e9fd26ac4649a4cb831cbb74ecf044ae6014c21148382cca3864a1ee754f6b0a86923e5501d54e6f47d7ab9e1483294ce98be13b7db52937100000000000000000000000000000000156e86fc66a8b684327a4de77c31abaebbaf2ee5f0c4d5f9238c7d4683f08dc78d59fcdc25928d180a6f292bee23a523000000000000000000000000000000000f64634ec7de1fc93959639991df42e7dc621380f4433fd7efeff72ce75f6ac7738396a912f78ecfe70bfc4d0ac4239093064d187f7d21b8b0a7092943de13b96c2e1ac9b578637a6e64331e2d40f539000000000000000000000000000000000ae2c40a49f6539bb257fd759c2fcc9f7b09d00059c7a7fd41422ce39aa0792413894bc716d66dc79092223b63de6ad80000000000000000000000000000000017a82c6a853fe29f98129998708f0d4d2b09fb22b07474395050d87cfe4d3bbf94967e05861c20680dabf3f4367135a75e676b40c09f80be5d9398a9ec20cb811cf6819a130445203d792a4d34fc3e950000000000000000000000000000000013b950aa9b7675322d7b39e81b13b14f2480155f74bdc5793425a02f7de41dc1ebefe4f07accd3719feecfe366e93c440000000000000000000000000000000003378e83277e4b02c3b517d3a8cfbf2d2a6585d028c723b2a263e6ba17faf14bb9aea301cbfdfb73f84709e2af99867693f63a87972dd11f5239c35ce269e4b9239e3ae906ab117f1f045d3acfd16ca00000000000000000000000000000000004d87c87f8f05a0999c712756bcaa0572b70264166b16eea7fc4785a59cfca18d5b819f0e65e193dd7ec38d0756b84f20000000000000000000000000000000012f64e2dfa3f00ad8f7f68e08b24aae83a049390fbdbaf570a7973d8516dc90e9c5c9211130d5c6c09f5b29183e24201145e3456d5ca6aa5910430e5a19567c327b757377aef98c4f46fe9a1f52cdc5e000000000000000000000000000000000851a636dfc668d1c5d5467774deaa78283a6f56cc514420fb2b6c58ec831add57b5203e31377a57adcfd9097a1cde2e0000000000000000000000000000000008828c34d4e712bdd5133e220167f3424491b9f47dfd95406bc833b3b030037c0ac0d2c84b06b4a2891c8181359af350ce27de5d3a5ef941d058a458f3ad2a386f1d66945789e51fa330fd65da4cd5080000000000000000000000000000000011021119ccb1cedf88be6f72d3999df899efc4dc28f828831be911582b61894aa37302f84ae9269b97b03a2e30d66c93000000000000000000000000000000000c373df4c0cc1d8a75cf2b9a99b5889811d3ed42850f55480d891b2f44769a371fa4894cb5bf78b7e995b4912cf47dad87bf5c4624e86aaead712987f313e5db8f2fe6787fc33481ed6e5c4d3e96d5be0000000000000000000000000000000005bbd2831bb4eb8ace45ed719056b95dcf5bda8831bc1495f763ff5e82be9708a004a00ecd102d4fd084579d892e5da40000000000000000000000000000000004de171bf5fab4c89783ad1d0cc9fe697b827f023ea1660b0fa2cab108fbcdc80837d46f292b6062761dd865bd1f905f68cfa3fd0692c9ce56538bf70e77e2a47534d9472ac702c53f2dbe68217d53df0000000000000000000000000000000018b36452aa579eab36db9b0417c999fa334292bc7174bb88e4bb14025a20c86437d5cace5369b90640c81edbf2d60f2b0000000000000000000000000000000014278d1cc3fd07e947419a6a0d7f7bd5f9e13fbd63779ffadc150e3d5efdd1a3f6f6e5ba8516066b75e1925282d0e644a36b13ef742bfe88882a4e635b5fdbd9b079e1adf3423dd4962835c68c9617c5000000000000000000000000000000001365922301de7c81b839e970775854881955f35ef7f718643a97e54746b9d9867ced3fb7525caf5b5bd0d382de02fedd00000000000000000000000000000000000d37c4e106e51c4cb65fef8460846eab04fae7e5ae1d1dbaa1e0bfb2eab7f2e27a9cd5c3cc942e38b021ef71827a0224c54daa7de8446e5a26cdbd6741cc90bfd26c544fdf221d47d509c978723c3b0000000000000000000000000000000003b9de0464ac24606ae840185d2ca6cc78773b674688a028161341b88907213e275d7dbcb8d8bca15b483922a09297170000000000000000000000000000000012ee2a578c09b7563508d0d94ce6ed75d277ebd89a7f1d6095f8992c0794b4de12e33ee24547c271e17b7a045eb3bf5b17ff7a416011549f144a3a65238d62395f4f76afc09496902c064b27739c6d0a0000000000000000000000000000000005b7aa071b76f93c765f946b96a972c1d11a2c44244355e90cd77ff069b930b2e8171f7cb1ba29f7ca6e62d88cb83c1b0000000000000000000000000000000012cabb25e52f00f89f2758790f9a81d0e336ccd7bdff06a79552a346d1966f54a5157130e5aa8db175aa64a431e19e494615de9bd7aebf1acedd9d40fddda34e4a85bc253c5e92c20d984f6c4cec533c000000000000000000000000000000000dadebc30ac3e033f433d8d012ffc70adc146f4d9574e5431360fb4a8ff0891c8a9f38a8754984a385d704086c320ca90000000000000000000000000000000000238439bc4e8c7dabe260c7b40d317014463c4728d79f521e7e321346747e9aa65bc6b32ee5920969c34421bb99bee9d38f1a0417a5a366dd2d8f5ce229afb6f34c1b663ad6eb1d9ff12f38412f00f700000000000000000000000000000000029df69b4ad5cae9fd974da7f58e4c55e83c61eaf011b5f22e1308b56e2c31530c170b304d39eb3e8a3009b67b308c6700000000000000000000000000000000140451659b4d6eaf05db63be5a7b0341612747eea7536b958b0620bdfd7b9918e8bb76c05eb2a528bf4727e38605f99a364da9c6b07aada98107447afbb189626180c5eef31f7f2cf26d5d76ab0c745900000000000000000000000000000000062493361a1a862e63eb8f20b0610a78d30ac8595e4c6c3487cf3add7cc38613870c2ecd0cb5a869110a99b76fb9055b000000000000000000000000000000000d8918e018ac5490c91cf2574e6a6962b69c17883caf2caa473de172b14961780fb237236b56a236ce8c674dc9001547031aa8d860e3b598ad0c4e9f93f26d153f8a8d8d0dd614ba868ed055c517532f00000000000000000000000000000000016470ccd107b2afb9ca03a0efb958bbc165304871e683fd606d2e78f65e34885668c6ccb655d4fa98f5776280e63cb3000000000000000000000000000000000982eaaa34f9301fe0ba1915cc5632329715c506528860701f5e52d1d77b8fabc89706af2c4ab3b729251b9472cde96f290c467c4827c9252b82ff523633ba116c52d15df9cd4e3121ff0e9f754ced5f",
+ "Expected": "00000000000000000000000000000000112fdd661f948495ae2b9200d959ddc873c53c96ee4ec175f6748e62d76d61d6b15970d3a3a52ae9bda30a822ada25b8000000000000000000000000000000000f5b38208d69b5b842bc22ec9d91eb6b653acea5cb16569c61bfe0921f2d8ad613239e87d48c6a9b29ed6a5f43578987",
+ "Name": "matter_g1_multiexp_86",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a9494f10e6187fa12d88e350ab84ab5bbf999554924e781d6470e700c3da78e411b8627459b3359d7363b088bbeb0da0000000000000000000000000000000017edbf1108591996f28ae17beadfd6b52340236c2741bf8474dd7471c19c1f62a0f28e8d8692cf3e700ddd86a931dcab4aaa57782608de34c6334ce5039c67767f6da7b315dcfc772f03aaf3dd1e67b900000000000000000000000000000000052f9c6ecc29239c614936bf9ecdfec677afe80de019230180d0fe529a2e82b9e15d6e081b02475e2bf812cea3ba6c640000000000000000000000000000000003dd0afc91516b50d9027c0b132453fab92b165c08428fd5c2cb994646b6b1cd5b82b7c3f7924e4a5cf8b45575e8dfdc22c1cde67b0e8ec7217c6ec72f36d8a1e73794297819de9ef6f1e52acbd3ec4a000000000000000000000000000000000da6e13230b2236b2bdf671bd5f3f8bb47bfc637d6e3f1796b555a95e51b86d04fd310f3d3198dee604baf48f69ce0950000000000000000000000000000000018d209b03f61056147d6734003daa776011b70a57e1ab17d3b92e2565b31a846d8fb7c3fc6fa1fff04552800b73affab895341f4363b688c4e9660fb0cd17f6c111a5c92e732205fab0d0da0175f683200000000000000000000000000000000116c72b5bd9d30182463c592adb8f73c16d22bb4a22832b8d47b683da5f4b8179d4c80d361ce69f92a393027ab29c18900000000000000000000000000000000026dab8d729338903d46a219004fada41eb666a9a90d8ba115f53da9e89a7bc5d824d7f4071c8859df52b3ede7b7dfaf4c5718fed7503c5e2a97fd6ab0294d6c42b1d35067e9d5ec1077176a4bd3126f0000000000000000000000000000000004e0627475a0d4da458475dbbebd6c36f4ce771bc2b2a8c6adfe9d372ffed05afbea207476af26974476c0cf51a9267900000000000000000000000000000000199ebe83e44a269752d92629810d0c5402f53a1bee03ccafe0b3299a9968ec45abdb5a74a6d90cb026cd9b28cfd2b89f6d055ad484f5054e8bd0d073cd556deba05418ef1235d08ecbf8717b550933fa000000000000000000000000000000000b4918f4bfad81349edcb45439e148af7af6664094412c9a51b887271cc3c46e34147c8a306a19f08922bda9c7146c61000000000000000000000000000000000afc3d1a7c4b6d899149801cb74a7e64a126631b3e758a73feda92a2867c53fd3efd9adf025ca6f6c762029c57706b0b4cccbb062c27a67ae2783ab65a47ce166330cfced1f11b85f87483e0250b1384000000000000000000000000000000000a093eeb354ddfc5ea3090b20312788923c5db9d78905dd31d5bf15cd83521f2f186fd284de0858270eea05d21801aae0000000000000000000000000000000011d047410dbf6df20f81971327b38996484e0862a9f71879ff63462e189471c1ba391496753456f0b5379a3b36380e1296111cb1181f048f51349aa2953bba2af50f7b7b5d2328d435bd63a7df5cfe5c0000000000000000000000000000000003d8e8e3a442f911e23b353e9efe396b746360254c14216c752fad17d96d440988d5a25f044afd37f12d74c89c8cb2d700000000000000000000000000000000179ba95a3d3b5ddd3d181e2312385f4ad7232d9af0c28f375e2036157e4603c1a01aa6c9c91496bb28508e5885bc2e599d7f0c0c7e927bed3fb930fe2d0109f58678969ac8e14fabdf4ccdd0823f706d000000000000000000000000000000000f56dfaafea0ce3152458b7252fac14ea64483e1d4a00a44f95bf3932eda2f2c51f0239e6a7a503cfdbbdd88aef2f4880000000000000000000000000000000010e02e9be7c1b795ebaa84f83bd27eba4f12dd49b146db0d788e37835338d352445e82060dd595f616b4f6d2d03cf4c911ce517fad2609f2ab8d44ae6263623a7903b2cbec683570949a96fad78fc6d300000000000000000000000000000000010ccd262b0cda9ad39177d31be0725b83e935c690fa8e07bc7f24e26f8b03122173f4ba43fe8ac933a7fed79f4496c8000000000000000000000000000000000318da543dfb04005a3cf6d93d6bc4058b4b93c4cd84ef978e6a30dd85d60e5e359b4f518842e73d182567ec4fb236b8b17d28cbcb9efde6d9cdc4c9cda385ce598ac8468d4fc94cc8e98ca3bfadf4400000000000000000000000000000000003dbf6c0676cec0202e328bf408a8fcc38758db1adba3e8184cb3904ed204b7e18db2183f5a1833737ad8eb089afcafc0000000000000000000000000000000014d9add10a0c739dec7fd09c57b3e959f3b7551eab8423ec5bcab4b14e63b7a27f128758d63f8e43a22eeec7bcaddd41a9516e93416bc7b0f3c5ef5da6112abb73fc285a14093ed19d8eddf2411691190000000000000000000000000000000014d0230f7d5c51e6fff6490c61972e2564bc31fea4a6d1f293424934f75629cb96f189c80ab32a79b2e988582d0283960000000000000000000000000000000011813cbbc0cae4cf6a8d5d58859f1c3b75ac53819129f92abe0ba9123a1a277b55231e1a24745d0d2ba6242ee758113c87fed462636eb57506f870ed1c8f66e211758327f4c19bf909a6419312c5894500000000000000000000000000000000006adb1e972755f04cc57170d19414e6930d0e6d42c09f587e490593a5c01ce6e827a6dd1e21570ba11c7e4277d532e0000000000000000000000000000000000ef599058025f40c9f77ef858aaf314faaf8d72277cd319a84a9d7038d81b76aa260df0516dd38633b22f9d3996e4761c373d64034c78482d6673c6906553151887c8aa28ab2930659671b8cb98a595700000000000000000000000000000000008190fa5e3d23c0186ba502a5892b76cf8faf2c15c91ee39d51b269b6bf4bd3e7ea395787d989c1a14ad88f3702cd6d00000000000000000000000000000000118d2d1b28f9180155277b80f1a7937dc7fe6be3b00cbf6a7ddfd08cf653ed11a4ddaa44576e70b27cacb7646a100d03f29c901f9769a42610958a8cd53eaacd9e5c4656106fab536052518b49899117000000000000000000000000000000000d28e7ef8433f8d5399ce3cb847f2633392bf44ae9fb2d402ed8e7e6a22de35c39e4f09ea0fe673ae3cb652f75ec80bb000000000000000000000000000000000ebf2ed9df06e2d5688d0ea812b7f9de78fe292584476b20bd62066977f5e221dbbd8f552547f06a3e821a53aeab83c1125c12599e84b7e648aab52cd68fcca7f1a5f56c854f3c36e0445ab7e2df2b740000000000000000000000000000000000e162f9ba960f452c269bd2f9f06e8bf1ffe737788d6364b1f75ea2788fda7e265dcaa907e45bc6ef7a31c4791b470e0000000000000000000000000000000008a778bcedb58f562c7b69ef3073c81866a395d6408829816be3172e1e825ca6b88f156ed2b2ac5a8784fac62b893896bb9a1d051e33a617c25e17b7ca8ae6b02f16c759cae0df7fbd403372eb2407f6",
+ "Expected": "0000000000000000000000000000000003f6acb4e1f7856413fe9317bc7cffa45f2053ae62e3b5e2b82ad57b48cbeb4110f53dfcace08bbb1955c21b50fc636f00000000000000000000000000000000172cf1d257572562f9fc390f96f2c39dc5809765b0b94240a554f8bbcc44e3658f22e81d1e6c43742ef24882934cbbed",
+ "Name": "matter_g1_multiexp_87",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000013d3d80910d9f43a707ba389b03bda49b65081f65096bdef3942f0bde2122ea575abf810f400d47ced92c45dc73837000000000000000000000000000000000755b4f5a055c718f268cf3a74533fe8e8ebf37aff3045b58927ee6ee7a862c8c1cd61f00dfdaf6cccabf981fff16c7908c35887835bf4497d673936f40ed44145c5d5009fae16eb0f3ee9168831abf7000000000000000000000000000000001530565bb621f7cd530c0eeb4cc41c2587ef8123c552aed339f80711c157e1595baa140434385d0977e9aed2629ea76b000000000000000000000000000000001806c5a90120fe65450e84ee0a56e0176e944a3fffdd2c83bf15d7dca875790d2f842eb31f640456a1221e44035ad33ca0154f7f8d52319c9e5cd59052e91b84640efe83ac814d95370e46aff4334cf400000000000000000000000000000000143723a10965da7b47bed0d0b5bdb6bfef5b748f6e185ff2efb73c5756d41d77b8c217a6d92245ae36e0add4d743e7e9000000000000000000000000000000001274e8842cc812435a576b2ac19edb84f72d08cffa129d7f4e44be5cc88b3449ecaa719b4d76aaecf08ddd30f7b184ddc252ac28ea29b5459cd2ae5bce4bf08a102280c093b9962cafb481016a212709000000000000000000000000000000000379e08cc1f47014f7eede433abbe881818c0c3a9cb02bad8cc86242aeb9f9542aedb67313f494fd19971a0a15d4ee1a0000000000000000000000000000000004e83a0e52981faf6a787d0600ccc457ddf3bb81c76117265c1bd011e5b4f3237383e97dad3b019623521b3c94d67df36d3bb5ee3410dfad575b0fbe71ac5df2048f74b52e777fe0955d6e244d434f3b0000000000000000000000000000000009ec14585b72733f621a58f35ab30580f131c93db491d4d704c8da2a7a0a1146e144575083bd963238434e2af48d3d57000000000000000000000000000000000ebd1a1c160ba7c8e3c20745bbde05f08d7f3189ecaa831d05c6a34562d6d3ccaa92472c67bdebeac8494658abf2c0405c30684c596976bf46384e6afb2bad6f821c4a62338d7a6eb204ed75070b197300000000000000000000000000000000084b7f967b141c94df69804a723169f69e05629c97a7a8c60b140787f3361ac87458372c91e04c08da2d01fa96056ef8000000000000000000000000000000000d731a1a900551ca569b8066af85176b934b94332679aa59924eb7d9a5fd776a55b4d7e5ef2413c53c244c848694b06411009058bb8e23b0a4294b5cae63aff10265e729d3601d85dd7f1e8063ce260a0000000000000000000000000000000001847861de1064a4226435ca43c1cfbc5d4660fcac177654cf5d497ba9aa5a6322f1156adafba852633e111576698bd00000000000000000000000000000000005ba738972bf139d91f0a426c96fcbb3b77a01af0f2316f2427a20882b5f355772fd6d6016ed77c31c13f88b26c628763e5489447bb9a5b661bcff2d9a4153a5aad975abdec380301b6d4ce019bf2cdf000000000000000000000000000000000148907d2335e046c50fe213b717fedac86eb3920099526a62b4466749d435f5ce11a45032b60bd5d7b26799adc63f830000000000000000000000000000000004bdc2bab60cf6df6dfd25c16f04edd96d5021b97ef38cad02cc1fc7f12494098eb793d99d15b327185718f81ec0ea620444d520ee01d87407747a4ac37abb7bd4e4c4f1735ca7458cc2e4dcb1d6297c00000000000000000000000000000000145ea0ffc3b24a623d74c27b84a390be062542795eb93a2f71f9358b44b76b93dfc0a2ae507f07a8a07edeed2410e5c10000000000000000000000000000000000d407c6c245316b5cc6b62efcd082829354d7e9e69ad739ae0ee55e6096ea08a48c59ded4595032093c32634576aa132035cab8f8120ea8e91389707a290db4ee69875d7429c6857e74e8bd40dc736000000000000000000000000000000000123f333f3554eac47c8daa1d4b362e42de1834ba9f55e4fee138eaf1a057036aa6ff9f50cddc78dabd3d5557b05b8bd1000000000000000000000000000000000116d786097bcac320327d7d56aa734d76d48a677e9c02ecc0bce550d75082c319f568d94b41e1c57c6075ee994e33304bec711286827f0941ffbb451a8eba871239341a60e3aaef23487175c9d2e826000000000000000000000000000000001012b1790e287a6328cbbcf80eaceb2c518a70e80cfe17143a41c4045e8c6c5317aafcb34f4f56494b401a8a9f21b5fa000000000000000000000000000000000613a88e513248538c1b767ba4d3667bca7aeee7974f691b7e4f012ea9b2b32603eddab0943229f53324c51838d18fe3369d91a4d575d4c142b98a53115a792ec50a290608ad316465487762e83f3a86000000000000000000000000000000000c31aa6f315a1102ea973d13e858d079221087edf178d98fb05701ed0a159309fed05942626b29ade066f8cef465535000000000000000000000000000000000177a3468b7de9612a93b9f2bb3f07acf505f56c63f798b4dfc38a25d0fc133c862e90ec8b40dc94004cfdcc9da197ee7ee472561535a7710db521976cef0c92a4ed89861ecb397cbcfafa477756e8e12000000000000000000000000000000000092095e7a431ff3a8e51e26c24dd4a5fed6d4a4a169b5ef79e8822611da8aca5d7c27139a911d5473442db9ee1529bd000000000000000000000000000000000c59f5a649682e864a792ad50fad57b7cd14cbb19d1feadc3536515f01053fab26950f56bb78d5a51f4368e73c19062f2cfdcb8240f183abec526344e8ceca6a007c35b757928803f854225d3a6ca3610000000000000000000000000000000003930511780f28217a125f524ddef656581a4ba2d461730f0837d1846d63258a02e659b25b882a3c3d077c880a64e3cd0000000000000000000000000000000019c682245c941c76605502785b1f79d37f65cf9ec61a4558092973bb2514de4e5852fc757c2fc7eac1b01d414248acdd60659743dc1977a698371cc302b7579b6d7d13632a31b47df369365fb02aff7900000000000000000000000000000000000edf518026cbf2dcca1d46340c24fa947261bcef36e3c8d026a09068a10a5afdb0964b54b70bb3b27e27c4d2e0bf9b0000000000000000000000000000000005cf718694ca47202be8c0afd56c88742e2b467d01e7b2330de778c434a57610fe7b8bd6071836a58f5d6b2876cff05a652a5d4fdf6d6703c857fc7b10a741b95fbce91fe823d827cc7203be3b3bce0a0000000000000000000000000000000013db13bf10b6d8b1ce5dccec98745dab635b8bc81d03601785185cccddfe2dfb3f3f9f6ed16d2c1a7a6bd63264b094d60000000000000000000000000000000001080522766b6cb5c90e6e0ae11ab4ded3db3ea3c7e69d00f29155283f7b25f762eb35bfeedf00caa83dcf04f22ee72976a30abda185e7d280804952fc0c074ad907fea2aa54da4c3190895270169b20",
+ "Expected": "000000000000000000000000000000001975e01d64d38cb8f852b4177104388aba62c167da2a8530bc59f510a990ed57be0c6ddfc92622234a121ca407853dbb000000000000000000000000000000000de737b9097065462dda93321d5881430f50631f6f3deabca4c41cd491f1e441139bf8ceb598393ab2a3424b0acf290e",
+ "Name": "matter_g1_multiexp_88",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001624f6ef9638cdc5f0b16b47ac8c5465cb479333a4ee4caaf6d2b656464d8f84387f01bc1811924312e6cc1e29a590c300000000000000000000000000000000012b3bcce18f60c4b2159df93a2d536bdcadd675439371acce011ac5b542fe1bcf89161fc3b3644679a395aed31dab569f4db766964c7855daea58d1205fe8da572aef06e0ca64912cec7c87bcb2f51f0000000000000000000000000000000005d49b4ea69c41ffa7727b98db08ab3fd3ca0c0261ef04b426ef29e724bd6158b3f3242cb915cf0992f2a631fd9b4421000000000000000000000000000000000f635c26698cf5dffbe25ff496f80c5de6b181f94a907204b79b548c1fee8c7dd426b49e9eb9eb0b17e34a26628c38e71deebc727d98bdec47b5a1fc48916dca1e42345ff5474a5fd6cab0ae99e9f1080000000000000000000000000000000003a80767130cd3c3fff0610f215337bc1b4a88886778fc0dcb6bd3cf7bee48f4c23c974c8883e2cf32fb01a84f9e148f00000000000000000000000000000000173f518f3349c1f704fd200747158940ecc395b04b4c476f406cc27836df182c3f1b707aa05767ff1bc75de42dba2a824b964d74259c216c1eccd7f2b52ffa5fcf151d47bd69bd2768e6466b32eb4fe50000000000000000000000000000000011874da4371ee8bddb34bc92fee6bf51226878e4550aa33313a434b75243c1f2296c1d62d9f31f6ffe2735f4f26a8082000000000000000000000000000000000f82551ba2b803e35c7118f4294626c151c7137eb4b97aa5265ce383f7ebc5ff5fe381776eee724aebb963d2bcb3d9f6124ceb1dbc8004a4b1f8b422d394b0480bca7c0f38aafd8f06ba090a98a1d3c60000000000000000000000000000000010501308d1a05e69700111431a0ca99aa41a991555b9a53df9c38413c67fa1b1836853bda93bbd8679e7724b3141a8d0000000000000000000000000000000000b033cfca384e480f73a4f8f79ceea706d7390e5b702305b79e30890e158ede03814d1a0dffcc3608fcb9926c5c65eb65a2bf15b2ed08b33056a0733c920741f86730dcda9c06aa0e3c135a844cef916000000000000000000000000000000000c7bf31a1f30f8e0de1a4a77b8b6c115d1a5d825b51875cba3db857a9cd2c589696ce2abe5a87acf8d6604c1f1f89ab70000000000000000000000000000000019ad7a6190a69fe1df07d55f8c792fc72cf2be11bbdd83c06325682bdfb5c31efef11fcb819d39f25bb1978570a250218c3c919f31d72ab414f91938089430bbbeaa53ad7a73224fd3f204b80fa1ab870000000000000000000000000000000012befada1cdf63d34ee2334ba2e42d7e69ffed71a39714e7ed89a86fd5cc1c65a01340c986abc37e7e3ac5a22a2bcc860000000000000000000000000000000006e5b16316867dc33a9770aa2283691f379581ff2b0b7986003174d4862d8b73bcc3f325c9a90097328f881b15f877c7f749063165c6db0eb038cb9f1a573de25bf377e1fee94f31df5987f7b2450aff0000000000000000000000000000000008e763f110c9415b63baf27236f1c0975e7bebc04bdaf47ea0d3a2709a455ea48ffefb7551a73c9d599bc5c9fbbca78f000000000000000000000000000000001492e70f2831c87222f7d7a9d00842870b77aa68e87b8cdc9d8ba61f86adce6ea514bf5b8f9d66937b1b640c43b02fac22d292cbcb836843acdd5a3fb404024174cd5c1cef632d1b9b6a73f2c5f705a3000000000000000000000000000000001685898af1ad3bfd350980872e6438048f6cb37398ceab33d7bae1d621b5b2859e6a07b4e4db891af37e29881cf573ad000000000000000000000000000000001084663fadcf81b9818c999c26a84c6f9a3a1f71a0a2982b5c6d01c56c2974656c08e4ba7833d1ef8bcf9af53d2f0732e816dd1bfe025685f2eff0856f9c162d73a58fdeae0dfbeb5ce076e9f9ec1a700000000000000000000000000000000013b077eb9130821bcecfe9b366c7a14f4487121095d325e74de44ea206078a6b1ac7d29a4e80f75c7714b6053cf2995a000000000000000000000000000000000b825b95b52382195416477f0bce73f06167db02bbcb91944e9e7534f804973bb363adca8b5ad80e77b70f4f1b9654d004f117d41a011d36f55d0cb53d4f98de3b1a6cb55dc8a76b29d393bc21826ea00000000000000000000000000000000014c48b3b2fb994920957b046643bfff19533dbe533df980dc60d9c852a3d07b8cf67454820a89ec9c7ea73a209f911ef0000000000000000000000000000000019b19e64d977d40b95050e4af365541b6c815534dc4abba7ea0af4b0a7e6bff0495fbb347250f5b5a48020ac20ea61cb6b6f5ee0549b28a1bb317cb020ae0e031dbc381075772ff582718fa49db486d20000000000000000000000000000000017fe39b732e6b815bde4078cba9f926e117349e3e49fcfb6308a0a09296fa27da4580d8fd18b0ecfd0ca68312cc0e5c10000000000000000000000000000000018a4eda1862c5c296de2eea0e720ba13f8a60defc65870f0112ab394e8160d6e1a0beff5db8c450d8770792b7efcccba05edf9812adf95c9844b2da06f75d96e742c0620d1cb0d47dfd9b68d0bb76128000000000000000000000000000000000e65750f3b9690f25b5bf80de0d76da21752a0daa8ce01b2bd8d172577f6c7d46c119ed20e73617ea163575705343c4c0000000000000000000000000000000019d0f934decb53a477b37d894d6e651a8a4f25b9375bac6b6d3483ee8d85f56b8374bacf74bb8550bd26b3d326962666f64a71e4e7652860038df67c99d97b1e5a063370e65217531253419bf2e6365b000000000000000000000000000000000907fe95f32e22ed75f94d96c191bcb19f88355bb84f91a8a535441da04dc211376435ccc60ad2089835b51e79f24b5900000000000000000000000000000000071e35d64ffa38024f4ccf7c4a713e22d8fb4b8450ba7b05ec5e759c2f8ea30e7d9e71ec2c90b8c667370131de785116059bebd962501b8381b67c22055ba01667d916932713d7ca427cd80d8f76b419000000000000000000000000000000000ccc90617f386ee2a76da43a745972066955c8e346d3de214834ea79423e7d95a008a6c119d640491d515b801034452f0000000000000000000000000000000002588711ccd23b65cf2f63b2d602b1d7dbf97cdbdb159e02e3bdf84fa65685e14d4832cde3662950a7fcfd11e68ad40a47b3448b9b404e184f7ff20466aef3dbd4e08375673ca31fdb303c88243fface0000000000000000000000000000000003b5acf5f4e39fcb32a267034c5e905eb3df32f2f6f7150d94cd17bf16e3a9fff9dfdf75a966040a6af5a623787a40170000000000000000000000000000000018e4b8d163e5176bc9a45da14fabbac696ae6870717bf5f6c00b5c73dadefbe329d86a761935b18e81d65ab6c48e241567d9d30b38b252a0661c12dc69127ac380f3f756144801633e99bc2ffa2f463c",
+ "Expected": "000000000000000000000000000000000905fd0b04e8db7657431b5f69f1d896e79ecee300cd67ea8fbedcf51b0389506da0669c28ac8158d5357a61fbc3976a0000000000000000000000000000000003235ff6d1acbceb35cd29c5fe524a452064a6e51d1480ce1e57c538b2ab6ec4f98c3bac676817e25e2d92e701ba881b",
+ "Name": "matter_g1_multiexp_89",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000688d6eaa2964e33cebae16623e228256937ce9a7721c4fbc85233ffb3edad5d6349d9c8a00c16faa0efd9c54827f46a0000000000000000000000000000000019fa249ce7be07208cdac9f9927163bb1b79b40b320623fc1a08a299d5500cacdc55386ce451173f683a9ce3f006c1e4aaea75e63204e177d404898aa51555767f813c3f3ed283405ed1ee829b04c85c00000000000000000000000000000000078eef7d7951f257b17c579fec05f3efe332534b2f56a953a701a8b92664b9a0b37959f7c3dbd77ac18a5e72d174b9f20000000000000000000000000000000017cb59169aee6caa1dbc3c47c29f977a44a81d33f1cd298d5df3e9469c8543d919b985e1b588a96a9268cef03876effbdb48a90ddcd791e6a9debfabcb1c71c88e7ad98f9e739ee752b381b28d7656f200000000000000000000000000000000025bae0252e5d83a3b76f2a861ebb1312bd344e3eaaed5e7169de248137a929ab94156be11e9b16ff312180d856d93900000000000000000000000000000000013c207c57a4876f6bd6e8e87eed0021d5e6b2aa3b2a323572fc2ad521e807c366fe31ec285c8412f89328cdf09dcbc99ad1795823d3834496b0a1c2c07431f9d76071db77834005fa1228393ad4ce3f4000000000000000000000000000000000ea93e5fe055ed1ce77de5d298fafdc4201418489b64d10c447de3973c1b98c184c0cae1d95831742f3d50613c5cd8c40000000000000000000000000000000004f2f3d0a5caac826632ee95dd1aafe181976552abdcc7db737f5693f3d08d3c4a85365e05e369365a37ef1b3df5cbca36d56e38fe63e573b02203be04ef9e1a044e1754eb2db50c6f9804abc4a40f460000000000000000000000000000000004c8b69c09f67ad17e8fb9fea4b7532c7c5bf3edb7669e26eea4f9c8f0bc10b0b1895acdee731da5999318d83095ef5900000000000000000000000000000000054f950a1ae65dfcd40eca15e5fbae984e7672a23ec030eea0cbc0424cc8073186b8442e0d71d6a4a77cee37c1108f941a6b36f4674ab19202037d59fd8e14369e5d3d71acc3c76985b813d81ca6e24a000000000000000000000000000000000b69b6b7b6cb1569ccbcea029dc71560d54b8bb88bd33af1c12a09d867fbeada2e58585385f1fe508a0dcdf8d2143f71000000000000000000000000000000000277561e6ac810ddf4c46288a065e5441ae0fe2d7ee79ebd6cea8712281a36f812c0bf49c21beb63a1f5cb670dd37d03ad85286877fa7e5a9a61dba9df5ce35083beca7c2f5ecad13d226fa32b9720e9000000000000000000000000000000000c0f4206d4cd564be1efcbdf57f99ce43b97d3e170017fe352ed3ec60862f87730d4d9d9d56ea0aac4f586d2f1786df900000000000000000000000000000000073202e8c73d14469d15a392589db79f3897b72bdb2b788da9012c7aaa167a157f85f3431161d35f45bdfe0f2255b6378fa5387c5712832b52c9c72e10c6f69e9c1c5b278aa379140e75e404c4f50a2c00000000000000000000000000000000191cae6012ca07ddf511ed586ef19e9f0d913d081cd752f033c9f74c334c6f5d075b4f6ec85467caea7836f51d0159af0000000000000000000000000000000016e65314e34e1c7ad577a36eff992abe6f26fc5349d12db12394bac648cbc1452cc366aff69e8cc4e2e5bc85db237a863023298162ebe7f4ae6aee45a8a6ba602c3942a8bd6b35636fc6b85596a582e0000000000000000000000000000000000bf583ae5e3a7827610d91c0d2433c8d358fbc12c016c59be8454c039197971f90191737993bfd08aa96d7838b7ce6dc00000000000000000000000000000000046fc386c5b456bafe03fc84b4f98939f9c736ac74cac507ea036d2443066090118138547766f637537425f64be9691b8ff2430d2f82c6d5e7424836ecea15af0ba2d0bd6498e65c65b6cd281a7b8f28000000000000000000000000000000000f08b3868ea056ff8e82fb7e22a6522985e92df1df9db77f787bcb3ed701bf8c90badcfd94e9d3e3b3b68ec497b9fcc700000000000000000000000000000000002e6f5e9eb44fcc7aa96a43856a707f5a82cb4c14c99b21df09e666d4802d15fb50d535184b63ae246d4ad77b6c4851415eea22058493dbf6ac248fd2ad8b4734ebe33761f2177089a3feda396001c000000000000000000000000000000000167e13cc54e9e9866bddff0c37e942ef8393a588ed3c2e90da12d0a8360edd6c3980bde808ff16588a57100d1a8898fd0000000000000000000000000000000014b21a7a106640b55cfeb19d3c23aabcf1c0be78fa554613e68404978b78e5d34b6b6378c2e87d0b8bf1cf3444d0db31ff79e3ef5d32a751b713180be37d44ae55c59c5a8121c132c5098ff972d8a9740000000000000000000000000000000002e8053215ae6894e8df09394353fe98b38fe4b17b9f20c7b48c4baad91519587f63b863e4de79be71672e1fb00d337a000000000000000000000000000000000c2ef9251a148f1ba8cd75a60ee18ba6328e1c3a6780c790cba3bc91a2145f44cb8bda5257c03890d5c5674e4d09296d039bc7274a3ab172285d853d368da0950203a48ef61b3c7564644762279c1ff3000000000000000000000000000000000aa7fdd550eabb1b734db00400304be9663c008d322d67fc771a85991bca6413ec07ab3adc3cb40d390fd41021434b97000000000000000000000000000000001994d9be11443f0a95a2ba4f7240a9dbaaffbc70256aebc0f10c322fc5b120feb2cd8492d02c60578f8becd7a8e589c92c47d0b1fd24c1c66a3cb0deb7d51ea19f0fc492f637ed5d4d03e102cbdd05550000000000000000000000000000000012b3574c35288c63930be8024afcc91194b30d2b486edae832dcb34778886af5816f7478df166f0a7e4752d8c12423e30000000000000000000000000000000012cd382d17ea10ad3fbfb40fdf4f3814a19384e302542a0f5731920443e4498a1f8f4d89086764beff079583a672b93bab4aca860ae4bc20d33808533c9a70108b153bc4b2256003ad4bbc11dc92898500000000000000000000000000000000117294ca9961249be6570ea760bb1e562cbd587f78be482263e4228171d9ee3d970b234455912299933689096f4afbd000000000000000000000000000000000029f88a99c750a388eca5dc6939082280ddefbf7d23997cca3653aaaa03a3ee4677fa8291641ad1f46fee0f8f1268140297500a2747f9a68b2d8d9ca5b0390369d919897c53d422cb76c5a283c38669e000000000000000000000000000000001006f64c279f074bf036897ded9deaf9b4ca380a9a7542490be675355c3979b2925be09ac4613fd6b7a4a8bb9e357f70000000000000000000000000000000001537e170e8dd88a92a6bfedcef69bb370f7bc1f32c36d203f5b6859be9b60fcb4d1e3948687ac7791d867e7c200967eea87ca4cf226c212c80f3db5e4e781ad7391fb73b1124d01cf893169d1c50ca99",
+ "Expected": "000000000000000000000000000000000603f6b2d8b806c5e399c686878eba299131204084e2c31c38640d757e8a6e5b318da785d54ec8335398610e9e3956280000000000000000000000000000000002abafc5839180e8aff2bbac4db043e8839ea25d8fcb7f6faba2a1c0a567863f256f820e846e49b3296a754650ca9b4e",
+ "Name": "matter_g1_multiexp_90",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a2eba2e26da82458a494738fcc816405760f4991616d729415ee502d13951c319be796cf35d88a8e00e17fa3c58126900000000000000000000000000000000117f6b75a6e25a786e860df05505f8e107b23c6f4338b2f87ac8740554304046f7cbb43f2193da35350e5fb39077ff3f9abfe7e05e8a210604355a77f64386a01323407d9f25397769cc6dd141bc6643000000000000000000000000000000000f6e3064df312fc97c4f30d3cab398f7921453b933d428a4162a37af5ea27c79d5b21d1d305a9609c994e61e56db226a0000000000000000000000000000000011edcb47b9d5339d08f24be87e52eabbdf701ab15f7799a5ae26cfca9d49e0e9107d9d1f09c711039d096a5745b89c9164be08e7c2fd15ac0116ca941b85615c6deb38fe85e2c0fd22997e394b8a6769000000000000000000000000000000000d6bf9e905e907ed86f5d3a4cdf61c527ef43ea0befcf6bb7eb1bb790b3dbdb83e0b958836669827251da94db1d07c420000000000000000000000000000000007f85bbbc54af3eb9e1c7e4c4700b4c784b8d2e6b2ff6a981a534317766790942898b4eabbb8d6c893180a436faf88870c391dff1c0c303c77b2a1fff24f50250dc793338f7d7f8f1d54bf7d87ab37da000000000000000000000000000000000b17bd374136dc1717cff915f7c898e049e892ced4ba57a16752a6dd875cf1cf9a2005dec3e3bc6f87b7a257d5ce7ca6000000000000000000000000000000000874999db06d15bd4b2f60e9b61d195747d12f38b75b74f3089d5b47735e9dcf79ebce22505399e16492c4a6e0f83abba2d728e013e5fc3e1ca24c105a0c268cbb4f152a97e318f3aae33186ea6bc93a00000000000000000000000000000000179108aa8a7d8443f69b7c906f9a4869ff4c724aaac4fccb5f52cddec86e32180b3ab2f66ba76d57f69416b70334a0f80000000000000000000000000000000007f83a847f4c7e7b35fd091249120bc59719ede5b6db083b33f5ea6249f9e13457511db006f416e0fb9614b8d22d51e1e8da0c8da19dc441f53c54551579fec5d820ce2e3599824b24b7c5bf1847c589000000000000000000000000000000000154b40b3bcd0ef04a5e1a550215c238adf07f92757c227e4d32e42893ee8e7e4fa9d7169005220d89b11253cffbdbd10000000000000000000000000000000018daff3cf04f648e59d00df4b86d8ea5dc74adbbc6fe4f080ea7a84dc6443d8923517a11f264f700e209af9bc52f759c76e90965adfc2fe52e4341895e6b6154fd7a097e052b59e4935c8267a6f0e63800000000000000000000000000000000163cb54e83a9935be82161939360356f7f0cd0219f446fd243d05f6333c68a1aca8f5d2dfa2b54dbc07f81f756ed6bd7000000000000000000000000000000001667e7a040817e83896d62adfc4a9f3d329e87f7d598217c7d2195c5b0c3eb58047d4b9bb640e3959f7ad1242e10783f7f3f352c7b7a9e2eb6c87edfc99e2df3148966760168f6abb13ee482f223a01d000000000000000000000000000000000222ed79e925d64fb58bf0cf105a2087c538c9538070bd742f7acf5e00ab371766d286fbccb3e708bda2d227523a40cc00000000000000000000000000000000126a9569e9ba97e5c41cf11af3a601560d037f1594f2e352ac86c744542618e9d2b6def0c7d3bb6a3707b80cdcb60f15d35c4286f19a9fe8117e37132ce4ce76e28afee25ecca2f66de3cd5e1c83235f0000000000000000000000000000000003786245c244c9508ba94e994dd510a7485f4aed711c75a2f509cf01b784eb12ce2f3907156aa15675e36b4b2587e9770000000000000000000000000000000018de0e75256cfcfa2df959f1491d87dd5414a1b51b6ff02ed5034394ea636fd0bc5d3b3a3b84fa7156ca7f97aa65feea3c2b40b7968a39fe8e4f24acc25b6c727887c3c44cc89cf62eb14a78ae47e86800000000000000000000000000000000026828a6409635184cb929a5b3fbb881ef013e8342cc9b5123ac82e7ce24fe7aa6a507ec3c017bba10126ad9bab5e63800000000000000000000000000000000132cf4a23eac460fb1a3db9aa43b542ae55d19f6bb2f408c399a570c1e479c4dd0462f9573c95c953bee07a51c543c4e10325465403dbd4898beb740884cc325923ec3e1d7483540377d8bbd02c1138200000000000000000000000000000000035220c800af6a330df6b6b6cbde47abef2e5fafedbb7a0feb84a317ca3cdb79eed934847694e85e2873ef97b31b6ba10000000000000000000000000000000011edd4c17352914beccd8c062aa7b95b913f35892c7cc5dd8f736a31a33d33a98d8f9b4be97ffe608531eb7c9643f32109545b90dbe35b0d5764bc72d45717e0c3aca6aa77c73178fa8a3ee9fec9cdb30000000000000000000000000000000012148b58f805c38bb862dd9847f12aad21d1ed760a022d2f619a0a077a0bd79fbbd6c066f0f6c58517ee9e912c60a37d0000000000000000000000000000000018dd847881616f7410f29d4e68854ded4e97b31d5112fd46437739ed62e6d78fab89b078581d052266b7c2ce403d3a79eef0f8014102664a300ea9a30fdc7afeae3cc338fd45cd421a1bfea98e304c81000000000000000000000000000000000e36ce625adc496ac94b53552effd651a73ed0c69abedda36e88d408ca7bee73777fd87b4f55e2e8b567c2fddbcff3d50000000000000000000000000000000008a209510caa720f20cecdfc9b0bd71d3fd4015627d0227a027aeb9992ec8030056a5046feadaf149d2392fc98fd60bfc8f1e08cdd72ed200253211e3b9947cb2a5fa24079b6920b4a4d3f1fd78146e8000000000000000000000000000000001373edf053517ee79eccbf02cce4b4b67d6efc53917b7cd548379c3f78b447ae5dc331285a28bc2aa5863befe2d26f4b000000000000000000000000000000000fce7f982bb8e937802fef7b3fac517054e6c9b288b03ad6497734d78d4b9074e22b1acef45938a08440948dd8b88683a7e25b1a60b6c6080ccf1bfdc37aabbc2bf92079d9356844f7f12867b3e2b2800000000000000000000000000000000001ac8ab3b3918836a5ba14e3d7c44eb8a0d909dbfaa2772cb9d7f8f517963662b5d4209e9a5d44ca0ed897412792792800000000000000000000000000000000169f8127198935f06d26ad8e4ca3ae5b95ad967aac69f7958fe9fb9c5b1f0e98e596fb73a0d8bf90174ca21a02a3e2c2dcb456eaad2b7c71ca32277206c1a1dbfa7e0e84950cbf14aadd455fb58e398a000000000000000000000000000000000c1cfb4660400ad5d7ba2f394cefa878c6a8fc214823dab539c0aa6d08f36ff1bd706be273f25ec5f1abfb06bb57e8160000000000000000000000000000000012ff9bad1a1d71fc49e96950c74d388229d4e4c68f7fcfafa42329ae06d4dd3091b5b1c95f6498743393b6e3ee794e4ea6e7b19245341fdfc5927cdae57f59de5f3fc8c37f8653e5aaca87db682034ce",
+ "Expected": "000000000000000000000000000000000630b9d9da596e60b15251aa74de850ee74c7804414e3e4d7113cb3d5ad6b985e436aa67bed66c36f135050d66f91f75000000000000000000000000000000000ab084fa126c573ed007f983e01737453b3dcc99ead0a74cc0e8d7cdad89ce81489384b311b7ec4c34736e9520b37e1e",
+ "Name": "matter_g1_multiexp_91",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015fec44912af2bcd34f1ad42ed24b6ce430f6d07b311d65ffd8b6d726ca23f5bc4b7437d158a36bd1790e806fd5ab448000000000000000000000000000000000c4a4de9940c7c26999773a396a8f9a6ff4b86f0525189426529d9cca037d504385dcbf1c89eefb5ae2cbbb394be42fc92898d9cbad829a5346c0925c15b585de18869adfe796e46cbd56828540571b7000000000000000000000000000000000fa1258cb0d8a37009e8c56228bbd11aa854a4695bfe96ce205efc1c9f32bff8afb64df0fb7863512ff8db6b091f146200000000000000000000000000000000188f128e662e8d28be612c8a17cfbf28b965340487df40bd3f0312187d027cd23b50e713e21f8595bc790ab8011919cfc193fe87634fb0bdaa1700466881b557c470a62464e8521be311a95dff65eca6000000000000000000000000000000000c7b39bc2477597e37910b1888ba0afe5ed03e809618bca0e543add93519909b6cdd6281e2afa65a9b45627dc1c6334a000000000000000000000000000000001335cbe866b3139dbe22266c4ed5f9fdbc15a1b338a290a590c03811b6448244027c12d118e6f829dcd352a419bdd8283dd9c99a5aea019436e3c91030d03ebefbf6ea6ac69222f1870fadae32f55ae600000000000000000000000000000000178ea2552d03f645fc3060a61b35af6e3e12095ec65b2e9972a5e346ac1019593298925a887e59a94af2adfac7a8361d0000000000000000000000000000000013996dc427ba51c4ec1f67b30c95659f35c8e71a225bf357f636fbfb428140f9b9e5602eda78bb38e87e3ab77495e505e74ab390c3f73c62eb1435226e9b4f9b921ea1918a61a614b9bdbe9eebd1cd790000000000000000000000000000000013555f26c2e10b79f8f2a4c397dfda0d8839a35a7cc15673ee5da34578f3fc4d38bd0331a5c42665bf40fb2cf693f31e000000000000000000000000000000000bb16b5b1dacac465a751a68b99def392a69a293377a22194fa4d4d6662b912d3ad804cbe51a4ec4792229de57923ea14dee3e2bfae3820f611c30df232c1d9c6bf58d40b3530858c79f840720d78d7200000000000000000000000000000000120183e73d23355da316783eb47ca687ecd34d85e800aa65d2c95aa5f8eb730a33d3273307cc05d81fdafcee5138a080000000000000000000000000000000000171f5e63fd3c71200720cba782ab863ace945cf405a2f961baf39ffab2d3283c26347ba297d16c3f2567814c6f9914e795fc8e20dd30622876a94afce1c1a76e3b689d6848903c21103cfce6a8a956800000000000000000000000000000000095ae1795306c8a8c48730987a842a05fcb263d1f9ea49d3f3c0ae70c7ff636fa4e7fa33a35637059c0b11b1b1adc6e000000000000000000000000000000000185e08447394763607d6efd8660118429469a1f6e7edd03a7a3e12ef99c2a15670d1f7ca664a8a14f52814db9810ea2b25b49f325e76733eb3c1a2cee5467157b2ee80987abae43d2c4b93e5157f08380000000000000000000000000000000012b0afa7f55ff9131a9399cdf0fbf2da69dae7cd504a0160665f0cd74a02163b8ad7ab05cebf3195495a1637134cee450000000000000000000000000000000002a130747763c25b9b6c0436390da91f02c9d5b24178318717024390a841baadae6a9f933e7f87f7965fc96bb498ade5df49b30dd6aff459f64906eb1a9c9b2067d4f1b75057874b2fee17923bcb906e0000000000000000000000000000000018911ed6adc5f48db7221656c622c6cb981b1ac1bffd64e30662035c0daf4bc5accbd53cdb1fe8eb60628262584de15a000000000000000000000000000000000b753d21d823d1050f109683c7c153514dd06663ed0ce118e388d18d36686e94588159e5afbeaa492d021a700caf2dfa959e0a33b1fa12e0ba960761b09921b81746b8df23e808a8de09e7f5cbe2bf41000000000000000000000000000000001107292ce4d57209e9c1e2c396688ccbe005699de4e77b1a221f9004585ae6cf8f901da6811ad85a88cd85cb819d040a0000000000000000000000000000000012cbe9c273a8a9c1404abe51af4a647f6c89e7e177efc04233586d70df6dad3aacc9ce2a9fbdcf2ee5c73396fe4e498d26ca68383528f6a871c237ae5214b49c18c4f3e2f3ef5dfba39e69eb181143d7000000000000000000000000000000000297e52ddc42a7da1025d43f46df11009ee035a9ac45e09a0902ba86fcfc5a4bb4c35ae8b0e0c9b86a8ed7e5ab751947000000000000000000000000000000000319c082c39ce4e59b952941dd7d14f3fec39a9eaccdf7bb41a2b935f876ebbb6778c90e1919c1e5804df91abd3bd9d5f1f95a9d1d4e8e7d0f17a954177253709d988c3a77c77d35b8bf70294bb358c2000000000000000000000000000000000ea5a9d96509cc5675e165e3a7c9f99a8c6b7be9c33fe5fba895a2d96a68e922271c90badf3c41b3ff52f359f5c6dae300000000000000000000000000000000106614bf5ae42409881f4889a82c6a3bc8000bcdec23b093ebf29b24cad128aaa7aa17566c4293f67af010e9b5950028b481f986998d863c98e55a7661136a8f19d7d4c57f6036cd642ae16c82cdcfb300000000000000000000000000000000145447f37207ac8d58c706af0b900dfc1f2638f840a0b44fa65245b5e671ffc6c008951ee17217e010ea6cd5e8477d4900000000000000000000000000000000187c607539f8d2b6afd15efa353e2fd1580cee48c469992785f02b3ea3396db5359e0d6743ff8d41648fd8680a4a8c2bad872848d72367467094675a819f9aa6107183aa0c8685d5d84c27b3aaab33c10000000000000000000000000000000012a022fc2dd9c201e9d86a0983fed4a71abd086068b8ab8c9586cf51230acafb084d559239d86a3713aef4b87a04c09b0000000000000000000000000000000017e02d69776c705bdeb9fe06d412a67601c6763a19c840f15f96de0fecf782e3a44118def54286cd52227361f0db3bf93c2c60541fe17fa8e71d58184a055fa8b1dd0bfd16ac2baa912b4472c6056122000000000000000000000000000000000e09d94291ce5e8310871aad89e0744e6b319b4fb1089048b0181cb9e885aec881fb7577fe0e80222793068deed473560000000000000000000000000000000017c8676e4b8216a98d9e9a05891ccb74e64d72a5ae76dba1b5ab2d1c4eb8291cdefe7753abc5fa59efc4a4834f815488ff07c19ad4f10ab47e73b6698f9febf3f28087614759e082e6e717588c1caff70000000000000000000000000000000008902b3f9b3ed6f0dba21e5d6bfc13fac8f003b3e11de4b883024c3eca0d2c4614604d598d31d9e328c7ee4a9d9be6100000000000000000000000000000000017a918bcd38986300bbc7a401e09b9ae20ccd382280b4e79294b6c8ae7bb1dbe2f72a582e0125381ef2b4fe24998e72f240c881fdbfc414d3e85ead1cdf166ed6929d0b2ccbc35f0811473757b6b41af",
+ "Expected": "0000000000000000000000000000000015e9fb1d1a586288f07f399b87c37a085df405bcf88505a7d2b0ae6609d4baef7ec358f70edf838d3bb7291c6e5a413c000000000000000000000000000000000cc7d7e2d372183766a842f5c14c1f2a528d502f1bc5dbf5dfc9d812c56503a0b7cf1e6f052e998aaf45cfe24a261551",
+ "Name": "matter_g1_multiexp_92",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002cdb1466c13290ff0c55c38ca6afe33efdcd09ddbdf7461d6bdb3e36fb5d8be851458620a0bf54932c4ddc1778c97bd0000000000000000000000000000000012755c81c142c5051ec64de7c89719cb59d9003fd8785ed5b36993123418e49cd3afab18b599deb72c969936633a956114d5455ff1717bdd545f4daa37e145121e7bd9636d7a2b65633e5ca5a63f2d9800000000000000000000000000000000067b3a33aaf3fc4b885035e60ba7f3afc7ccfff469cde1a67f48fd8cdf4b15b7beb9e2fbb13daa9283598aaeaff5014d000000000000000000000000000000000bf43cb79d63db544b2db14ec18c11bb9114db93662e8e6e7858d3e4a99cc332890ce90775b6c190d5ed418571fb907d82cd8da62bd901355a60b37ca14ce65d427bcf9551203cae7c346a49b4fa86260000000000000000000000000000000019329a66132ba7ceaf5c030fb4ae9a599895aab7df2a27fd92b55e3a52b99ac51107e798175f2af83991eb63147901d30000000000000000000000000000000005c71bf6552c314dda4bf9f2b4fd8aa368c9e88c0cbf4b1c2bef9137d608738636f40579a360bcaee1a3f12274687063ea2c7fc2050e9c1ebd05d15f197b4b1be61c6820c8d27ade57d85109d7f9824900000000000000000000000000000000048a258134ed95f91070684d04b83634c2d4c16601ad259d41e7d27292897a4d4ac76eb73425583ab1718b91f151019e0000000000000000000000000000000013a0b600765fb760919bf273a7b88bba568350ef82fc382babafd40a7e006e6808a03160f3747878368d8f6b31c619b1e3bf7e661d54796c71437354d7d3182770f10ab450827512a423d3dc82d5b43d00000000000000000000000000000000069d94fe286a9d39b64756e79669add0f66db69ead7db5b5c2fa1a9e5338aaa9051457a3a744c3b08d3afec8b87d2e9b00000000000000000000000000000000105028835bbeff46cb7d9be4b21f07670dc5589603d0d695355591ef5f7ba28c04c8e6dc40f0bdda031bb54a5710b4c0d3a364e7b217dfd649d1e08f76393372d8768bb0fc85c79ef4652417ef1637fc0000000000000000000000000000000015e6aab154e33627f92560e3def26d936a8876c52490732c807749cc28e34cb98fe8f86addb30e129f8149c504d1dcaa0000000000000000000000000000000005f6040a129df2340f3c3fd0935c02cfe162fe1afb58dba7699e7e08851b3a3c3fba36745bbc769aaf01a4f9a401d038eef7b05d5c725ed31269ae9c56dc7ae35048af39ab114319680d4af69be7e7c3000000000000000000000000000000000db5640083674fc75c0b0d1b2d6eb2b03cafa2e63d7a65c894d9a76b196d92916ce85c708c6c451aad65e0b439033d9b000000000000000000000000000000000ac8d6b508ff6797668ded6ceba4680443516d601a155cff48a51297e321417bbffa6eee042255e9ec054d837bffe628acecaee3dd4dc11e341b3dd0073842d90f641d4dd467a6596f337a6147bd30a90000000000000000000000000000000011daaf23ab5fc0ad7abbe7d5f1dc26c8ce388491cc049f01f287eb9b133e52f33d40f8693921d330ae57853539ee30c20000000000000000000000000000000017594ae7ac7f6e4f02df862b6d4ff946ac1a47085b554ebaa720ad3291f576ba720dd455829600f930e3964a44e5c7f30cba585b847bec40515a257cb839c7e5d677d17b7313c258e83d630e65cfb5d200000000000000000000000000000000174b5b9d4ef01fc9d0f05a03612210690d7d57ccb772aa53175f11b9623388de8019ff2ae1d564e7b30ee06bafc37a84000000000000000000000000000000000e4c03b8dc45b0567e9ddaa0a085d169799d2a595c03f2ac679fd858cd59341393e6a0f62dfac0e53598af4758843673b8cd305c650d2e1cfa91ef0aca9dd0d785d7570d6fb67e61fb9b6817116a054400000000000000000000000000000000197f0ad6576bdddb48c58adb1c9b2115cd9b38368dacbea9220d6a86bb621dba93325b676071e38aed2338273c98c4100000000000000000000000000000000011514f08bb28c37f078a47b6a0d53b311d5975c8a3c8e2c24a25f34bfdcbea53bcfa14b7f23adeb20bf440c87a251a66825e5f9d81273f306a065fd064ae24bc2c5ce8dbff6b22128753663a218da8a3000000000000000000000000000000000aa5f3a29c47fed2e4a87bb4c2a46a5a17102535aba9426235d42f00007e35d1c902b43c1068af279cc9a1b689a0dadb00000000000000000000000000000000056d9729f8faa8e12027b993e8dc41a340d61c64e4388c3166482ddecbef8d04085d6ae3764f0d9cfe76288929749235307ff9660ad0c24cbb139486638a2556687f88fb93a290a1d174bf87d780b3fd00000000000000000000000000000000070e376dd57cc8e2146d49ff08c6c6ada6302c36c4eefc3003f0cc3d75040d73599c7e0c2fb9f7e24484c37262f0eb330000000000000000000000000000000016a272b79edcb7e7fa92400bd55fc937d6389f1f0d3d2168656815845d92ab1e7b555fd4ea311802a62cb6c94bdc5d58bfa8ee3b44c70ba2512c00a1aaecede2180b08ac3ac8c550d70407f0c12e027d000000000000000000000000000000000bba6375b28ead3d49197ec9d3662e34c70735ed0f987f05f439da164afcbe98f25d2ce7a5e1e32515eaa4cb7f5a1f98000000000000000000000000000000000b1ec74ff999ac5a7a3ff2c91e93e5f0edf5f296b063d80bca22fa64198a798fa6b6385d25cde65b789454bc2674231058aa85b50e5f4ffe375599cbb912f41d35acbb85a324880148f9b9003c4265bd0000000000000000000000000000000012fadbd9c50f2e8518dc15d95a59ccec0c9886488ed4601b3fddb2bddd77a4bc861f2862c9c4666622e42a5dda7138ad000000000000000000000000000000000b2aa31218a13b4ab0b00d1b76a9ac7bb3d7e6473a29f2f0d137ca63bf7f152954e52182d32d3de31df0e6ef0d102c9e6810c6cd59b14ef4f6a4c2702cc53c65b3dc84988372c1195980417c583fd7ff000000000000000000000000000000000076846443079520c5b1600d5faa5a6d500998ae355c84b9393c79f83f1a2485b1809058bc53cf5f8a1a46bde6cf2e300000000000000000000000000000000012027dd1a4fbf6078b70c507fc2cdc0fefc9a0166694c796eb26e9838195e68fc76297e66e2a0e9e069274d110efb095c5ebc09190ba3df49d8ea55cfd18370b9d443f9d9084cf84f2236ef4723d2d4700000000000000000000000000000000183c019c306c08401b4f2c1d852b29dc47b56bce8cddfdb66d4e3d5385e4bc75bb9806da1eab476ee02e25ca2b4d41c900000000000000000000000000000000066d56711b80dc8725e112e4e2af6c939977aa66c931c6febb21735d78f5afca4bbaddd77387e52dd5bc9c29cf26923613a56b176fc835b7e825c817d432b9ec6d51b0a66483dfbf12166ee979b664cc",
+ "Expected": "000000000000000000000000000000000f75ea9863e14f6151c452f7a4268b099f97d076b249d02d72caf5d52635bca3c686070d4a4bf997b753c283c82cec600000000000000000000000000000000014402b3e738bee3bda4e62c077e9d355ad8a71b0830ec0e67a4fe6dc59b1f3f7809ca7d07184f53c5afed32db327598d",
+ "Name": "matter_g1_multiexp_93",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000107072809eaa84dfeba5a95f94aecc2c985c9e5dbc49a741811fe4b2393ba7f6597ac99d8e80c0fbf715a164099e9d5100000000000000000000000000000000124d1694bad88200cde42f1e7721f3390df8dbe4745715a2f0b6f11cfc78996c6f342693acefe88b3d83736cac6e3e05dedf65658ec3cca48fd48e844337159af090c5d1f5e9d713ac6d0fe1e1f193d200000000000000000000000000000000188a853e19d512149800bb0aabcec450561e5ad08b5159e0879422cca1f957ee15bad2b881979d7c8551eb19693bddf3000000000000000000000000000000000dc097932535d21656842615f08e7016f55752556da3be69027d0dea621ef46cc65e335873e041a3dee6c7e5b7589dd5db65ad6bcd6f485eefebda0badfc64e9e7dfe7e911f3ccf4f4fb9528dfebdae6000000000000000000000000000000000d3a53b9865082b23226042f69ca71b99978fd6dc3c8553e33ddb12542d05b026345a23c2b24dbd934be2ba3cd585162000000000000000000000000000000000b0832950405431722c23cc78bf0b9f33c6e2dfecf10e6d503c8c96ca9732c7e7a29251fa5b5b161d14b7155a50846886e0fa09884a7ff4c801ea0722cf6bfa58a46fc3d36058e8c395ea8fe56d9fca40000000000000000000000000000000014e19a8a203bd2e9e9601cf6feeac5699a3b2d2129b6e756b9b5a7af0cd9228083de8c9a2a0ebacd636ab1b662c8c0c7000000000000000000000000000000000faf049bd6532cdad26403b269d7dbdcab6c147ce0ddd6285ad9ae0e8ddab4b6706bbf038fddd7f63e6dc9a766928ec327a3377d7b9ff3aee2ce1194a22d7115b09a9fd53fcfa5e7f76bd9fdd35559610000000000000000000000000000000007e2e69d6c96b1841340c48e8ab070c67054b574bd5778a8e38a9873241baf8b85deb73695873fdd9e3387fb1fec3b6b000000000000000000000000000000000fd151202c399636a360cc014c90caabaf3b01d5a6114e078eb2473bc2fff94f1c24597e39a3d2298a2e9210726bb48e446a62ef5760c995cb3cd0984d607c232c1eb0df5516a501ce448a189a3134d8000000000000000000000000000000000ad0e842dd19673bfb8534ee20591a9076268eb203940212f702131fc6a3e7b226a84324954eb4bcfa8a007669d2317a000000000000000000000000000000000693801615c5282a327ae034c3a1480de0e1c471a412f194178a59582509ac6fe8ea22c8ec8e98034348ac465527f4b35f0c1a7c2dd281f7d2f006497f99f65d6a1e22f1d9aacb08724b3576aa19e19f000000000000000000000000000000000ac9f4f22670b52e0e85a37bcdd729b40c45fcbd6e8aa78626752d736771ede9c570991e347134f95385bd77e404e4700000000000000000000000000000000005964a351f406083b14726ced542fc6d95dcb8bccbd41aa3ca9cf0395d8d29143b897c66c78e2fe56eedf17d4d6f6c1f94c1476ae0a62c502aa096a371e30ca885dc13fc417e3dc9bc00bcdf516764100000000000000000000000000000000018e270b6208be13c23cabf52e31a156209abcd7bab03694fcb7035b453bce8464fa1e090d59a1139fe451d8c699669c800000000000000000000000000000000158dcfe7736f4fc63071a70923d81db9f7d2a03512724dc41ca47a873132da66eb0eda58134312fdaa63ecba7ab529acb677bc9f1f7572f808e969aa50efc519192ab8653c71090e5cf8cdeb1a3544dd0000000000000000000000000000000000a614d7a53b7a06e71aea4014f9b951bc19747cd8822da50f7993c0821e05100dc5fc8d043b2cbe7cc4dcae9837679d0000000000000000000000000000000004e0495281282aeeea480fa47f53f8b521a7df4c5619d4e58f730fe346a6deb3d501ec8b55b581489f28b4d991ebd90cf5ca580a25a5c87015f57f7c23cc51a0beb5926c84d44659e45512da51aa0cf4000000000000000000000000000000000edd664ad8b77d86bda4ba772f677d34c9341ce2b4d2af4b2680383bce0fd4468e936841dd57753d06c50a3357a47eea00000000000000000000000000000000063eacafb540655984104f60569720625e4499f048ec7849577caf240634ffc42612ca7ca92c17e3e50aa627059cddf2fa1cc45c35e266a82899d8ea0c9c1f96f96140eace41a8758a87975b088f0231000000000000000000000000000000000a9d9bea7d8a058cf254d2b7e10f6d2e8244cf131c6f87c4e25b5febcac352d02b1b45ba347e0b891c8b08e7b5dec82d0000000000000000000000000000000001d256cedcde615d01e15cf526c4a8bc8b565055567aa1de1847b524fa49b4b9f654f5b66cda0a78f414848aab42b05c93d2908aa9266844eb265c2b1c17f8357a5ff039836ba83c837909f6a9d0bc03000000000000000000000000000000001519b05b59250c72c9db7f425954694b29b36af21d9293a36d7bcd1ffb53d0ec55a3ceb7980580ce6f9fb6a0faa7bf3f0000000000000000000000000000000009e7d045b69e2dccad22dac427f5938974a6394c9fef84633fb5f90a0d09d437219f1b7ef7e7bb03eed106948eeb560d3b94325aad8a2c80971a781bf6f6bebad63ee37405ab7e903fb7094beef14d060000000000000000000000000000000017cac7707469b98c6b4d24fecf6d818dce6c8b9eb44bb08d6e475e385c30fafc81551e74ee98cc854d38d77d15459e750000000000000000000000000000000019d5bea3e48fa7bd273233bd6325bbe38267e4950dca4fd9ad051f487e7933a366469107258d69f0603b2f9a8dea2e4f5143a8e734824840346078aec03d6760564870c5ee2b2dc13f8a39ac452be9f5000000000000000000000000000000000b993d9303ecc19122654d5cb10d488af5411c451b39b1e19e7a104477da50324472076c55c4557576a9e5d7755a381900000000000000000000000000000000172b34e576f0539e32c5025b3a8f25b5bf407f3f3dda863b194a9fd97d3a6facc00902c95fe076b91713bec162f61cbf0dbee37fea759c2a58cf360c654f85298e8ff44b3f900e8229c3f838345d053b00000000000000000000000000000000170d799ffc4c0abf6c582b41732308665d790900ef07a74183826e48c9f0fc500b09109b2b13b2b33cc17e6e639d2969000000000000000000000000000000001943fe62329fcb67a45b5155da7f950ee12fcfe0e8e9ee15868409ae44adaa5f03c330206d7d97fa733c9e93957755a0b92f9db82d0976f4c379622c4028002ede2ab17f647bca3bbfb159045cdb342b00000000000000000000000000000000078681739039a022499219b298799027a341be64204a34a97a8115e5e10486420c18664825b764fd7bb931343c2558a60000000000000000000000000000000003313d3482f952c6f9cd4ec2f2b61f28ecf7d8cc7e60f17e9aac8e63ab25dd6bf2da2d67805debce0dad8fe37a36625298df4ba50cd5cb5a02d5f50b3ba23e5f5b0172a46cc315a0a94fed05551a68af",
+ "Expected": "0000000000000000000000000000000010aaf24dce0b05179769031ab81db339cda85cf68963640b888d3aca310a6de690150166c0943d658e51524981a1f391000000000000000000000000000000000d1af37c2bdca5886d73567cb00d5a9859755267800d7239cf39c291ba83b1c67e6a3532a2d8e8590c1bf2d845001038",
+ "Name": "matter_g1_multiexp_94",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019401d9118a5c2b0c6ae40507cae6180083258eb6c45cb8bf2fd5d2703c95fb07c031c82d0568a395e18015fe0a48a2b000000000000000000000000000000000511b992882f75fe98131fd35276b7a1de527b94718549bb4f5c9980917b6301a86e45fb7c7e3ea99e54158e49c7e60ee49662df81f6bd455ee554704ff0c7d5a589d91e017d7ab4c500d36378c17c89000000000000000000000000000000000d886eedf2a2b33a50dae5ca6f41237c9425b0a4daf08bf4789a3ea8c7f598d53257916d9c03df0d63f12a1a804fe0990000000000000000000000000000000012cb777812e76378f04fdaf2cea12456aa9e11b4c3ab0f12e63fe7ab11c716562b07b3864cb9dabb7970c81bc1da324c79eb26c79d78ab84c4d7e48e56889a601fda17901037a74fd79355e7536f39530000000000000000000000000000000009f09107ccfc5c4ac9b7e0058d6a0c4d7dc4309134d5fb972de3156a554211d4a2fbe639bb8a93d86091137671ab8447000000000000000000000000000000000b7f9955092221c8a2f09c6a9ffe6483ec0f8a0f6c555ec1772c260fb62c4ada6dc7beb92e29620afd15466b5f025cbed2918ddc2bfb7f7cb3d7e74b43b9a972c5b51ac20ea83f41d5b51034b5714c0b0000000000000000000000000000000009a22492a1b78342b919f7b5c8fcdddac408cdd3e8af4d6de5a4b1e510fa3b7e0e6887bcbe074fa839f2d0dc892db631000000000000000000000000000000000e5eac3a77c7a3e89e9324abcc0203046948f3d62e40156a5e1b1d9a274d408d6cb49e06b8cfcd21b596923f86c02c6be9a8159fd7915c15db69355514d9dd26c66fbd14af969ee576401b1b782fc6d30000000000000000000000000000000019914b405a24e72896b3d231582f0075fa7e59b0d0bc796d790754902238943ba634dce66131260efbb5dfc3925a1d54000000000000000000000000000000000352a5a986c500e41d2fa4f65e5a917061b3f9449c1e720caac187c6bfd4ce14f1b49ad414864a1510894530cfb4a768c818ce6e33e581595e83cf8d33a62edc26ed38c22f20c6949a94e2652bb954cc0000000000000000000000000000000019567f8de70c4cbbb25335e69154ce48d4106c8c9d0027e17c67777dedf758203b0a8fa3863d4e7812311f6cde36a6640000000000000000000000000000000009947f7401d03fa8b0801b130b43f729d6a71c04edfaf7b9d3265f82b039131fa09f20f9b4565d21939ab7dc7dd3477e9ab338e94b31d22947dbeb20fce3150127249d2db6107d95bdd032eb24c496450000000000000000000000000000000003c42ae9653d1d1f00d79f8b1a0c53d0f2d7f3ca52ca1960a621fc1bead7ab31cf6e5bf30c5cf7877c83b33b6b5b54d6000000000000000000000000000000001221117f45dea3fa1f832bb8280512841ad1798b76f1dd16dc320ea7c86473f6f8c98ce007ebc3ebc39e7a860be987fe96acb797236dbd0316fdd355f07b9b45c9bc626f73105e87c376af4d7dc075d30000000000000000000000000000000004340b7dbe7c27014add4ecbdf310de758ea5dd1100508a96501ae3caf9955c877113971a61f66e3691d09f0a259d4ac0000000000000000000000000000000001d5f83065f6d178b4dbbe0f00f0a88edf0a90021601bddc2cc27fb0ccccce7e48c6283a1e641408a20de15219b5553e60bc12a8b34e717b2c410d026660c14182250d7c66f8f88dd4cc94e550421caf0000000000000000000000000000000017679efa923688425fa9cff1f8e89ae681245371017f574f4a655aa780bd11009579d7daa47249f503592bf0ab79e67b0000000000000000000000000000000018f57a1ee533981c8df24895ad174228330ea361448ed63e522637df44cc1b888e969ee94d7b44bd532b655123f8f5d8537f0f732fee8b882d254a81704d2310c05dde186232f3cffc05401fa9830215000000000000000000000000000000000bf47631b34b2694ff7fc5d1e25de2195e606daafec34fc2c8ec86c0a325214d874002422810a81cff654eda187076eb000000000000000000000000000000000931c54d05eb43195c3ff6b396e324b5878c3fd507637c316c62b3b6e2d3d84cff9f33cd1046f1939187979330d3fc431a22bc0bec2501a505cc8e00a24792bb380ed451ab6f56fde07ace8b6c9348a200000000000000000000000000000000138adb70a3dce09176914deb0be17821cd0212c6ab554f7e200804dcade06c6cb5f7b084a1d6ac0ef8eeabc7cabe7717000000000000000000000000000000000a4422c569aced58938abb7bdbdefdb27cb06677c1066d17f98a59f847928d1bf2343acf8b5d1717aa38cf81959ac1acc7b10c801fb9d929432cbbe994b404d3baa5633628f396d20d047fe2c2ac2914000000000000000000000000000000000fd9ff095adf9e3f666d3141717ac4a96deb5b4f92dcee35be1d305031d06d51ecabf863a41cfd8dcda0fc94ecf79982000000000000000000000000000000000fb55855aab9e557046ed53421cd3627b519859e26338328d7da249fdfa6a07fa533f748eb5dd564f9922ad911121b2784f2f3f31d9869799ed8bfc2cb129dbbeeb096d771730ae2863c4ddece66158d000000000000000000000000000000001054ff028d2e2875330e3d0ffc52e2a83ee2ad2adf024ee294f695113d9d645f0be2a3d3c70f758f43f2deeb542aae810000000000000000000000000000000009a5e96cd08d3ee4e740e2f7b94a4e390ab5f6f572c4a1b2d927a7ef2365557ab9be65b8e2388fb571a3765892a96445c62206fadb762c23bf77f69f69bd492674bb92edb39248ad2a432f819304e6ea000000000000000000000000000000000bb1de70113edd86e5304248fa2f857f1620dc8a6bb28680f537e04029aee158e2ead4e0eaa373b812f6ca988dc40e7f0000000000000000000000000000000012118b670c9df77af087ad01e3b766d4a2b7c2b2a319cd733ed6c02ec36d9002036964fc442db992bf730c57a7d0a407a6f950de53d07fda75ab43f73982c2684edb06317568df15b8712dff2ef782830000000000000000000000000000000001968aed17e572c0d99e4e9262f239771976dcd9d7df19c20bfa94aefe1d4f3a3117bbfa4a6e329bc6b9552731446dd10000000000000000000000000000000004e64ce59b928e8cac2f744bef119018de8395b712013b0c69855fbf2bdc6a750a947b1a81c9df959c78367ed0e1575d95a373fab5176d124f783a36eb2346dddd5c4eba9e24e4c0cdc4f925e2e24cc9000000000000000000000000000000000148cd980512e0aa153adbdef262f098b1ece801ee4024b5561e261d39b495165851781d519d75f83dc5f298d40b4e9e0000000000000000000000000000000001dd43f37950976e50071226b6aa47c229085807ce9634e6583f5a2d47eb8547d4de0669b16a2771791c9ccdb4289cd9319d855218eee020f9cf8e4c0b6004902f0b16eedba8a1c911476af34f65dd40",
+ "Expected": "00000000000000000000000000000000059c7ca50efe2d0a64b55a560a08976b437c350860f9599fd30370d1cbbeacae147144c216cb3e63afb2ddcf34282a5f0000000000000000000000000000000018f42ef2fb8eb6cc8c31600a3be37ece06ee567ce0c8b8c7a54c910041b8c25b2d94a94722904de079737f06e817f380",
+ "Name": "matter_g1_multiexp_95",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000172bbfff135f33357b0dd0e8545da99c4ee74d6414724c2aa66ffc85f3a9d0e35ac80850436745a12ca6f1c4ae5c0ecb00000000000000000000000000000000152dac882023cce1a3e1fd4d8d5aedcdf6acb2ca9628a94ce92a4a551b1b7268589b52b2c90af6e4be9631eebc2ef8a62a397c2f19a8c4e66df0e062f179be2f45a0c5e104588222a1a78447512f299b000000000000000000000000000000000c40d04b3002c21b041ea8b8ce967056435fadb479fe1fe20c373b2e2c5b568b7a38d031424bc835bdbd85af8ed1d0380000000000000000000000000000000005e7357194364947c8dc32fd74757a3f3014e914dc25f42b2dd86230ca4f86981476e6f10b1559694bc17d014cd243d7f193d5a575c80a3e7599923bf5a8ba8a48e8f98322d1d8eb1da42e446d518c1b000000000000000000000000000000001474002c92db026ff5bce69eddf1d8ff8e6d2ab9427bb82377911597fafa4d60256836c094cd513a52a3a09797afbf5300000000000000000000000000000000176a7b311a333c2d4f6eec66e8c889ecd7becca75fb35a38bcccae52f10ff69630393fb7d87c3b6d97cd648be099c56507f2013742ddf2d35448feb80b6b7aaf2925d3975ce28ed2b1ac789886ae26e40000000000000000000000000000000009ecbdc4836c6c0cb4ccd014f9e582112bce0d0ab047115f38ed5dd51c54de5a43321e85c9b3e9af5fae0caaf2493fcf00000000000000000000000000000000034425e05f0adb1577f7b1bf9b9b50a76bc894f5ff0e9a8d190412eeeaf80d0bb96f21478fe8adea327f69c9137f57094e637a80a4eb1b2caba68b6828aa18f956c62baa7c5e9e591a15156c5abb6050000000000000000000000000000000000ec3d4fe1b5e1c26de1558d7dc51eba3b6c37ec037de184e8a6f481ae20b830c92221593e1bbe4ee76a85cb10b33e18b000000000000000000000000000000000e51f811e16f00626d934e69024b55dc29fa4ea363916cd8f44f928fda6e3ca4947eb15de24ce1952c39e9ac52d2739d27671631f9afd9d2e86f263f5c17c3c11c7f6e43efb6d75cb2cb8250094f2289000000000000000000000000000000001205dfd803ff3688c2023913aecb10c138be4d03756e2f05a63627973f511c2635571469d4f630758627f7977b418729000000000000000000000000000000001186b9c0d2b2073b495ef9c233c275922bdbf4691e8be085051c09e245242526b13b7051782a80726b381a72b5ef9d5ec2decb1f482f3eb48e7f52b89f6452b659812ef79bb42fb25f03aa9969faf9bc000000000000000000000000000000000413f6ee9bb25469af4298dde67f0a4a26d2f528848ac6646764703922c78d65e046204f891ac94b0b4c425110fe986e0000000000000000000000000000000011860881aa871fa3a6693b23fd7b1da0bcaaf044058ea0700b786f12f1074c615577e572e33faf8b3562bc285632696d911eb1de54fa8ccb746336b681504fd08f995c864a8dae2aa866862f81f0e7850000000000000000000000000000000000010e8fe8fd7863c2807a4bd717fc4646a0e4f99598b9c6c2cf0547d039d58290a367e4ad851c7a67e8dd546d5e328200000000000000000000000000000000063ea10e84e4f5824ad7b9b68398c9154ab25ddc4043a4990d80e09dd94a890dbabf9c3d93b13c4f40bd7b1ff32b14b2fd0a61dbcb0c657e824cbcf4670a31a95ecbd47a9b93812cd5124f3ac9450c1b0000000000000000000000000000000011cbc725705b809ad69c5ebb55ade0039989728e7103b684feb35c8142b100175235c2b395e37a20aa40845ebe2dabcf00000000000000000000000000000000057b5b5a5cf5f5bce985295f8a50252967aa54e934e87855097eb083a59863aba19ffcec4354a5a831b747175ba10e878118e9c70cc5def8e7d258e05273937c514131f39e0cc9fd2a3620dbffc7ce3c00000000000000000000000000000000041043cea626d6ab553b95c6e09de597454a3a3d1b8a75fc9ecb3afe15bdd8b5e73b8012ead8777df8957701fc9c9022000000000000000000000000000000000185da96dd1d54bb7ca5d7dc2fbe4cbd8ac95f06fe85a7a26e5e0e6353f6a6daf73b74117ee62be4f3fb268fb4c86275c445931b79e2b826aca02d1bfbb00c2dfb6d30ac2ef97a4ded18243b1afce773000000000000000000000000000000000a06b91559964aa8e8628946bfb720047915ddf08d24fa34f7b241e16bb163ef67f1e84fd205485d17725a8386a7016a000000000000000000000000000000000ec787cf5134bbd832d2a7dc1ed87b8c824552d92fdb30a790e1c73b22c753540a9747eecaf14dbf867d9667b7b852c7982ae6de98df906922e660d461009ba6c04cc6497f3645a66385c775b21b210b00000000000000000000000000000000053bfa3bd311c1780afa1862de6ae8a475b8eb9c61fcee2b63dbb6556022d703bc7eb204fb038056c654dfb940e7039400000000000000000000000000000000074ab5797d3c39804dfd5359b69a4bdd2b738670d13662eb2c112eefbc0f90da85dd1a4b6e0613785fc66b100d129202000674ac5d09c6c599173bbe9a43726c120c3a60a96d43954727a2f33ac4320d000000000000000000000000000000000cd50ddae4f053bf5b7b3237701bdee2f5167e09d824d260e89ea498fb3b593e5053b781c159302b0433ead35f072c850000000000000000000000000000000001abe8539a4215a3b7b78c79c306dcef7334c83f571f4d6836e1c1839a65c8cfa9a0811395e3c4bea26b22ac2175757e773f8e9637886d795b75e7ecaee512005c1780e7ab17b9f20ae9232595478bb20000000000000000000000000000000001e6e0709869922c36e073fdf1404a973e0467cab3a04a806361e743d67468f0d66de28f6c0c7b8cf92954330485db0500000000000000000000000000000000084e96298cca174344b7b86052426f9316a15b4031b9e42677253fd9355b1c99ed9ca3eb3949005078ba228d4167f8b0759d0bab12ac790cc3a16e88f1a108e670681f117d4fc7d01f8c5a2d6ca7fe8e0000000000000000000000000000000002c5e399eab947a52660807752ca662212cf3a201c1127dab3586cae88f8ab6dd23deb0312387178e0e9526bc8fc7b8d000000000000000000000000000000000ad86b21dbf58098fc4f758d7ec9204bb16cbbe680b58fa42821456d4fa508e42b53c8988dc0d9a4d6f6a782a5fb90b6cce865074a8a41f8a3f40228046c5be68bdb50ced10bb73ac8472f052530293800000000000000000000000000000000181f41dfee6effe70a28e4c53bb6cec52f232caee076f680fd63d73cae24b44709fc63ee3782a36278edcceeb7b32415000000000000000000000000000000000088d9011a9db9294bb4451e9981e84efa595462e26e5dbe14e9c84a8c5ddeca94f49857cf3b8a70e6a4047ad76d234585e2f9597c9b687150864e90ab042f4f012a54d92cf9d2ece09e4a081ec9773f",
+ "Expected": "000000000000000000000000000000001170d9938910ce68e56f9e84be6f6ad284a244adbf26daf8d42f6411c9794b707454ec9300442fcb7a0f08eb91edf86800000000000000000000000000000000043679c7a917148d141a785e65b0a067e35a016c24bf7639ba374e21a817819ad67d317ee70852bd13a1fc3a373a38d2",
+ "Name": "matter_g1_multiexp_96",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008d9cb39df5b28781d33d996039da8c94cd810bb85aa5868008b4267ad2a8670924d4b3ad7898b33689aab2211bb9bdc00000000000000000000000000000000007a8a6f888722e4717acbfc42ef1907206db31603c403e0a8c1ac0af9b37e63124d4645a506265487e5f9eda09c8baf85431a1df7678e49ee049b75ea968ca255ef456dd58cce57b64edffac1ac223c000000000000000000000000000000000db6af04eccb3ceedc11378406a26613aebbbc2201a9ea2089848c7af3b34e46a3421d5704242c4b333f72180f6baa0200000000000000000000000000000000105f40c8b702f0989a9e20f72ff6a4f7310d81787e87638c33a61985f02116e106218d64976d50bcc61cf5bcbbff7c9eb6ccbc0b600f11f1b89061d94c6fbdc9b1d389244fb29a5d140dab8842d44eaa000000000000000000000000000000000a77e39abdc9d64d72ea4b321e3310a145feaa5d342bc1a5b16c0143dd01caeda4f18909acccb3cb5b43ad999a94f91b0000000000000000000000000000000016fc4a4f6b488fd1f45a158d941d7aeb5d431821589ee845c64eb198ff10931d586f8a0678237be2a394f5976d895bc854dfe31190469897c30ac3736ab166220dd3702df5bc897835347713d03a8d04000000000000000000000000000000000d0ddfc05bc9f89eed488752d64698bf00633c83cc37931d95a599d6be6e4c5d611a4151839133e86f74bb91aed1703b000000000000000000000000000000000be3dbea501c822730ab0176f64903931aa46b0179c59556ee7e1ba54605ed8da2eafed7eb2254a7ddc34e553a9b6d59eff1ceff9e5184dd9fea44da4f07529823dc9b100f776cef6f6881120f7de11a0000000000000000000000000000000004d6f288744016f15b21da736283af2ed1f45df12067a3a70391f66fff3ce3953a51169eba6288cabd84ffe7f597c9fc000000000000000000000000000000000f6556a63def531a940269b073ea98be79558d832123dd681bb4446d4c11e2fed59a2f97904797abb07ba53e0d48e923b273e4c6266c1f5cf022902fe1310d2191af91c47995486342bc61cd361eab850000000000000000000000000000000013e692a13e79c734f3758780fbdabff86fe5936bf6c60f2f155ec4d1c49cdefb97dc02c1f1e4280c5ebb055914d93f9d00000000000000000000000000000000060898a9365ae49697e5ac23e320261eda04d818c5f1153f647844b1910bb3430d3c06df9a64af8ff9dd25c18cbfa79d1342b5cd4ad3179f406941ef6ea15d0aecdf9f6d96dc334c39b7dca89d256d4f000000000000000000000000000000000a2a4d92ad63dade4d666ea949dd64d5886eaa3c7ce466677356ce9f65520591c1aab590b48e9fe1eaa0f0f3e306cefc0000000000000000000000000000000002a2bfc836409b33bbe078a5f89c5142411bde621e9117ddf9f81f37bd546c3e2ba94975ab4652fa0858d5a2361592715b36620f65ed84fc0bb344b4b73f4eba4b1680a47b28b47f6d10f9ee8239812500000000000000000000000000000000075d3ebb18437feb21f94ad5e2ce96cbaea2f6d68885483ed54ee67f2dbcf8cfa39f405afb46e45d08cb804a7aee3b8e000000000000000000000000000000000d42851366ed4694730b7c58450c3f9ebd365f15fa4dfa3fd226d180aaa921a0d897278506ede76b85decddc9580a365249ca9bcf879a770b0a054422a6ea97ae795118ae45532c1523c842696de6d17000000000000000000000000000000001722e05d33728260ebf5e4b48104cb2c89b4bc3073767e56fda373bc0e29261c9a5c53e5768b453b116494c1109cba2000000000000000000000000000000000030e4da8620007236b89103b215e54751ba2f2dce19b0304997f450791880ad34f3e43cc4e6852aa599fd65ef72dd9a5c014a0aa616e809b674390b4553bf2d9bf325e73d3a935eba94488dddee4e895000000000000000000000000000000000c4e7e44e8e0387bd99311343d2ff3a080ddad557c8639aad64c4f6e47d64f48b91f9de2e33b4b9c182a87efce5d4e0e000000000000000000000000000000000e7cb49fd7aca3daef3c0329c950c832e1d007f21a4f950f367eb37b5d7433f5d6f1ab1c206232b2ee32137b56b53967ab722a1c20f068b6955a44073914c418a082345796912ca634e79983a24ec4bb0000000000000000000000000000000014026b8dae20a1913ecb45359e9ceb317137244e16a036ac760b47363f2d389ef6cb12cd5f5fb9e8e31ccd39bf114f8b000000000000000000000000000000000f07f9e76789dd937b85e02a9c346f81e87637bd03bd5f98a9b18ad6d109100b540aaadf1fec048530bcfa35dbb5b8ae8b314f83cc3ad501caa44b4c3ca8cf68c70ff6920f445d3a7ada212b6a19ba3e000000000000000000000000000000000a0249c354052094cae5a3d77313360a8956839af614184696b5b7fbd2af6555c6ae14a150220f01d624484b9096eaa700000000000000000000000000000000043098df38ab37f42175cc9f9fa9ecbde75bb344776ed078632b3d8bbfbf04103adde27ef0d361177bb3814cbb8bc54994ffab83099c69845cc87727d459ae300a5725ec53176424ab0ec8bd3f80eaff0000000000000000000000000000000011e90effb7ae193b47afffe6fcaa0a28c358222cbb087ce479b7fe88d25386c5a9c9527899d7633eaaed9d982d3ed4e100000000000000000000000000000000174877f80e5e9daf2cc219545ce67b904319f75c0284e41552662512727c1e05b364364c4c8835c1c9c6fe028ae45895b1d80be637e2abd98d0433150e14b629d98fc0918c7dfc179204669ab465e90300000000000000000000000000000000170e754e54f64090c4c7520bfed82665b44728904092fe3a4fb2fd2d3667ccd4ecb796e5ed9fc4dafd315c0b6dc22b86000000000000000000000000000000001081e62ee7c502159f7a8e28c5ee45fb7fc5b301f3a081899bce10096c74d1bf7834d12cb7fb1301b986e9c6f7501d53e670a57ce4dcfa680e60ef33ba99c437e4fdb160ea1012de36f4b59613a6af85000000000000000000000000000000001434584d8d1cb34eb29fd1c95871f218f4dc46f8b2ddabafdc7049e88f54fa4b80c88960a76411e365aa65cbf77f01ce000000000000000000000000000000000e4e2e1318c5907a07a7ff154b07e959d681a69c066585ba046b8889d417d01c503b32a924500944d43e68d7da8da35d54a999fdf391d3944318c54680e69b58ce3778683b6f2c607d64450ed32c6d89000000000000000000000000000000000945a9d0603a3bd0278fce30f0cf97274319a760291fea5aee143c364cc0bc60e59dcd1093aca1a3ef64696ec47845e1000000000000000000000000000000000a77cc690d55763a94aa48c210610833427ed3176b6dca184598755f539359bc7302f8dc2cc941d447d9b5b68fa716b70563ae7b444cca7ebaba36b8d59aaa5c0e6c1454a4a2907866247e752e640a7d",
+ "Expected": "000000000000000000000000000000000ac708f97c9e9fef4482af7b95c59c2ce6b8826f6b046b5a29ee2224ad66648a8d1f9959ff434c77394199fbe75780db000000000000000000000000000000000983fb55837062305d7fbcfe8c76cce1c431067a97392923720a6c4f963839d7d2661e2a8dacad1f151f505748239798",
+ "Name": "matter_g1_multiexp_97",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ae003001e3173dbd17f4d6598fcdaba9966f1e22a06ce747f7d2a06b2bd37579d093242a4940bd816ced07ec1917365000000000000000000000000000000000b27db470845f285c792da64e870b818a7598fb820313e075ec72e78f59f3903cb0860b749bfc67540a8bc80e844a8de5b59d128b5ac47106b4114cf225dceb621d177141ef5783943f40a54ad94e9900000000000000000000000000000000018a33b2c2f1ea187672612b51c8dfdd9e86674df58ff4f77ff3f71628e7aafbb80ad22f34ab4203c42bd39a4f73c3d6d0000000000000000000000000000000017c3a68d8782a479ba9aa829e3f261a3e1b832595fe3922d800349bdc2bf58e0c1b523eb0924bf0996e38aa83267f570a057c0405e24b7373f67197b2109b633a02589711b6a92ff49ca024f893d7ecc0000000000000000000000000000000015347adf6539116167ee71557b78d8fe13373512ca7d8d365179e25ae8ed2c6a65e1f643cb0ed677a2f44eab809d5b640000000000000000000000000000000002360dbbe0b7f8e97f6aec4b20a7e6525d83056975a4228901b4f19259c9ff2d2ee00da9bb9085232fdf843e5d305561677b05905180182427efeb848b2ba2eafbabc7519ab33db14de0746afb6071910000000000000000000000000000000005b62380515d49aa1427800077a11a8f01ff00fe7df53a13a9266910e4038167ab747bbd0705fc25ae2cb0e2451c893c0000000000000000000000000000000008de7bcad1c67d7f1fb5cfb9d20ac2134006618ce0d22f4120f5396bf8164c0effb0e3ebba7959e9dde757973080a9cc53e7f69582f4c106ee5bfccba1d5f557736c1b75b6e3777cfde47d552e6bdcac00000000000000000000000000000000185bee837e3212323dc40fd471ed9a1a58f2aebfcf7f07ab761d40bc1ed77b385a134c99385d07e75c5f8c51d6496482000000000000000000000000000000000d7d42e4e18040da671799f981d404085fed490182d397685498e80967cb9c080a766d5c8822152d78920fb388b979f534c87bfb629b817e7ab97def7400b0a83e47af8d628787ff814733fdf34ba8d50000000000000000000000000000000012961da3be1ecc774fc9df2dcd87c337ee50a99df7c4821fe08da7327276a24d754be95b6e916d5c63926b6e44b74310000000000000000000000000000000000e44d11949fe33bc3a0ddfcc74c5b0fa79cebfc0d4a00a574ad7659c7a5e72c728ae4ee031af57e9135a3eabd93686edbebb60069acf431e1671e3d00e4da0d70fa11ed4099b21d45a2b811f99dd9cca000000000000000000000000000000000f03c013d5554584c2030ea02cb451ae508fe6dcba72bf7c49cb47a25d3d65eabb2fe043b9ea90e03571aa7b64be8b11000000000000000000000000000000001479789662864eabf677d2a541e48e5ce70f35a2cd6c0a476d4179d02955a51123e75c650888e514aecc85d67781c8c18b1ee2765e762f1b8c2451270cd5a755758fd733d7922a537aa9f1fd7d0c959600000000000000000000000000000000139bf8fb623dd156a3fcc46eca51e61155cf58e2dfe8edfe717effdd4418c833db7fde2031ef27edb4a70f9d60d67440000000000000000000000000000000000c352a16159eeca4dc9a86601973c02e39f2a11c8a0955ad52236d7e46dbc405147258ea8558505bef0f09ba92527c76d5009fd559714d5692de5500ec8cae9c04ae1ab1c7c6e08c8738ef22da19ceca0000000000000000000000000000000005b8c4c2782a2a2a3abe4f99e60db6ff4179399aef4b9e305fe037e1a14a4c03ff59be1e91f55e5bf316356bbaf876af000000000000000000000000000000000eae605cef3beee4a176a0589f2676b3e212edcd7ac5834ece3066bbbb587bdb6bbe46663acfd9d8aba2251a238004106330c755ef708d8eb129475785f24be9e7836385ac918c60ad36e80e2f3281b8000000000000000000000000000000001038258f67b0097ec51adee244cc15d63c4d3bf1b3b3e64ef8ae6ac15a7c4195fe97bfe8c5a42981a2463ed1b39032de000000000000000000000000000000000a6f27fc1f2dca48f6e26456de5d9fb840e4ed3fd9ff12372e51130d7c439f4ceb4fa929da2dfa3ca271d34e9aa0985ec2431888d05cae840dde4c26911db1893659fdc345d5433556d9bf75e51fe374000000000000000000000000000000000373fbfebce5c599172ab017e8f4f9813b0e6aef3031faf61c336aa7d6b64c8986827a27605b476bfc1057a0388f864d00000000000000000000000000000000079ec2c41547d98277c60dc46a61ddda51c9df65a8ad2d0a64d483eb245986de36eea2509cf7949c5fb05a77f9cf3bacc9a72369cda74e5c86c6559cbc4f4db1b3ab24c5150c7decea862ede3c02c505000000000000000000000000000000000d50821953bbbdb494e48c59c940c5f2ac2b902f4c2ba2b2ad50960a51ed7eb1a9d592bb903a03b0b90d8817d10848ba000000000000000000000000000000000bf0898bd20e08205aa218e529db578d5118ae411159ed372eb8968cd773ebb1619f92107d2948020bb3c721ea63159dc2f50989b04fc29c4c4a0090fb11e860c15f89a66f3bb8281e4678ba63ff3f9a0000000000000000000000000000000006bab55b7648be3eaec947694311289f17258876d74a7d92f22b7807d007fe142a71210684593b1aabf74579eb1b1c17000000000000000000000000000000001016b28dadfe9b65d86a1f843f7ff4b774eab74431b68b079527c2387ee6cac69e95ca564346fc54237edd3d2d31f6ed9fc9abf1c76ff11ab538f46ce768ba597eb5f2f63073ec67e8de10aa1d666720000000000000000000000000000000000c0d5ae44a0863ef3d6d32f1d8f32f2c5b89112652e2e3d6ce620479882fafd73cd3627f9f11315020c8fc9341c7fb4800000000000000000000000000000000197067de9d61733dc0367d91f55a57ae268d5e7babe7882c1fbcf03cc38de7a2dc41acfa16bac0ae63418fc349b9471cd4167723682bc0e7476797b3be5e14b8de3e4e23b4ca33c50a2096cda8766dd7000000000000000000000000000000000c3964c79741fe8093ccf2f3d118b33897a18d920ca242ae153118bc17bf0102fd19a9e4000698b256930a2f415305180000000000000000000000000000000003ce4a6877879ee56299ed27f634571126d9f8ca8ccb1e67100064e7efb435cacb1ada74d7c7529b495957ce7a5dfe709644c3727f78dd12811092190d5d10adcd5b9fc581dd783c97d4e7b5130f309a0000000000000000000000000000000018e6260c0cd6cf806ee82a047c51a85e0d7023883cfb05993ee81220e0871b122c12e65bb99b20787322d93b82089e98000000000000000000000000000000000d5b66fc46b7fb60fe8efb6659bbe948c6776d7780633f007123c5c49f5fbe7e3defc0f3d896333d0ca01244f2b6effe0df9846c84354ab7f947caca7800e12e38d8e6651527e6831f4d8b1bd66c4f3d",
+ "Expected": "000000000000000000000000000000000c7aa8aaa848c068104b88d0757551612285327ba5fbe35ccb4eacb1bc96a341786e4548f5f86f6ded789b712a4be74b0000000000000000000000000000000015c9aefc358834f21ec85092cd69df37e0036ea6ddf23a3ca052a669446b183e5340ec7ce894ff6575f5e6531947c84a",
+ "Name": "matter_g1_multiexp_98",
+ "Gas": 64128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004acd4cb6bcfed3219c3aee9368feeb58d77a7ec81d19bea11402015f4bd0ee2d7afd86fa7ae9dd320910ca28eb6d98f0000000000000000000000000000000009fe1b0094c0c2ae80a3c5accfed5d212ce39f867aa2150b781c193a0053aecb04d06e005fbfa0a24595e5968d024be18a71abe11a893fce872f6b8a020b6d84241df03eb934b50cbf3571df4800a8330000000000000000000000000000000018cf9bf39549c35e94211b4e2d0a0157d73e1ce8a17cd724eb33c38281dac07e12eec61b27b440b220c4f21915a73a52000000000000000000000000000000000fca6d956989db84dcfe58b0310fc21b5bdc82a32838c8d9cae912d683dd9c67f68e15b3fbf9d7b430ba239c8904fdd2bbf28e5bca314391550d3a0fce50b1220965860e72c8c3865a2d4c599d31d3f1000000000000000000000000000000001897956bc232fd5a9b0ed1b533bebef8ddd9e97002513eec71d67ce1086ba8473f2c013af7d8ac548290453d9f71bd5a000000000000000000000000000000000796da5c8ac165d416c8fa36d84e11bcaa80c1bbfe18efde4b4b2c71d6d00fa24f3d51eac312cad9e854f094dcb6ec7458b208a6845aeb2bf31999042c59b7b130a7ce5297e88023953b1aef63616fe4000000000000000000000000000000000302240769257e92899da03fcc4abe1ad3944b74c3046e790e4e950f2958426b5fdc691401a1c8a531f42185d382fe5b000000000000000000000000000000000053750b58b6d2fbacae94e22b397261e541eb4abf4715b3f528dbfc3388122918b1b4b506f2fef89ea936efdef0105b3b53b6cf9e0ce1661c4960283be790abf956c2d6433529b8f3a32b92b227aebe000000000000000000000000000000000168a635a14f61734372f4bdd2fd564d77afa8588e1828d88c4c90bb50f57473b2c20585dc0e93726b84e73c61f29ef1000000000000000000000000000000000e6e92355e59304ad35b1dbfbb98db803d5fadabdef4fb1b2a54080ec9a33a7147ebb4d5219acabd949337bebbffa793b049228435ade4c4c565e65f39f13a84c747c312afcdaff352560b9fb3cfebcc000000000000000000000000000000001797bf2ac9b490cd43a346fdc64bfb22301a0a0e371bb4df8ec02342b4fcc99af43b4735665c6b1386fa04a3dc5406e3000000000000000000000000000000000fcc20f4aec04b7896ddfd86f58c2e1e9dc6f863ec3b477572c073c0f4fb07ee8dc0d5a843321446445b6e7846fbc5d556197f5ad17062d2ecbdc8887bcdd32e5ed4c48cefd9e14d622a0b800d9703300000000000000000000000000000000013ddb8ff149222a5a0a997c0b89aeee36a6ff2540de3cba8bfe6a2a64fb505f13ad956a3882082ab85bfbe72f3a3a6b600000000000000000000000000000000102c1a1085f60cd5326966a2dda0872290e1658002ff3ed95c47cc0345565076bdecdeab7082bcfb439cf7f3e445faaf721d9d7fe10104cafcad71307e785321ab87b2b69593535caecbf0e166cfda5b00000000000000000000000000000000189515e637d404ce6db58d24774609cf946074aa22066d808dc022824a26b381bf09148005c61156a976154b025d71c90000000000000000000000000000000009102e313c4517cdd3d07a66e0013eeafc996c21fbf5f0f3e7d232ad5adb781cce1657bd5750193cfc0357ff55bd012a461531ecb61365908019c1e8074a4c322df2b356eea3f3eea9aa1e0e1fc5525e0000000000000000000000000000000002e166e475ff083faad64667b683e546b2358f945b8656f9c2f3f6e87a40dc3fc087dd94874bec1c4bd5929b7c96024a00000000000000000000000000000000022bb4ba4be638d8c14a16c94522c41cd3b3ad917daa454f820b8fa35e5a48c676266feece6986e8fe920b2a5e43e4b3569c1c1ae2d18bbe36ed50db1bf30957802b09a982fbed49d4968815552e010d0000000000000000000000000000000004947bd8ea8cc3b116fb7320c573fff0f107913c18cfdba2e7e9a4c8715e334a431156f384548508df8950d681163aee0000000000000000000000000000000001e9e7494c295248184503344b8ac7bfcff41a4561de03d78691ac47980f14aa47c1eaa3cca80103f0f2ba14a2842aea2061d33b2f7e786effbd2e93101a56ba1bb62c1a773a08b72ca82f5183bea35b0000000000000000000000000000000004789b01538cfc54cad0e99538e874d13eaa7f07199af29d460927c3e622c74e0bb4185afa12c53446f56033348c332f00000000000000000000000000000000154291a8bdefbc91445ef1fe123f326b8aad652c8c54502920d4dfa912c2f42d784fbc5a16d08468d2d6ee56e7e8eaa24129b150752d2d5551a622231ab067931678454aaeb23f76168219406f0d50ee00000000000000000000000000000000029048f227fe8d1b7247a82cfd3e1b4b60cdce6b52de42c4b96641bf8fc5ba9b077e33bd4c4fce9a51b63a6a2451b427000000000000000000000000000000000c83518e1b7700d68966d592cb2e3295a2db5226eb6fef972c8a84721d1e49a30e4a8ee3494ed4bbcd2a6877e1ba597d366c32d5d3c132f32a6ac3cfe1dabb649c59ae224338f747ad98b193e83467290000000000000000000000000000000003e96431aae4330d3d204093b7af21343ace4f1960de951eeaebea51e778b1fee43ecddc46667d096edbc5ff4735586400000000000000000000000000000000183a282f4b0513be661b1b38eb5f02b51aadc591745e0bd5d2d4e5545739e26470a9ec20d78ec284268d9c54c8e4f7b6d997516cac28a3968ac6946b5bffaace0856a52e38fdcca11ddfa16cf5a568f5000000000000000000000000000000000904c85edd36dfa18ddb4e1809607708142f3c0861570f2bc8fff14c462675661f2111c10a01557fb21f7f38957bdd840000000000000000000000000000000012a3a37f34ebb23d4c9268ec9e1d53aed4747aaace497695e6ea8fdbdedd58031cb479003e8bec0d14aa1d062fa30f2ce881ec65fdc2f58e46d3ee45a06d0c5ac844ee5b62872c7ba21f6b48621a337100000000000000000000000000000000148532bffbbf8bb1688f6448854214b4273b9d5adf132aa9142c1605d1882879678b6cc70638713b9438532d427f447c0000000000000000000000000000000010971ee30d83719e10e91aad3f1f201fe35ba1a057531b1905bca3a8391a3786cd077ee0f104305eafb3c94f4546da9edcd9b95e49473277a665ca0f9a8309df9ed6ee4f25d803aa967fb8f688273e65000000000000000000000000000000000f73574aa5a06ea569de88e48fcb96e822039af296684933c1b417dde95e08d2ac9c6ad4d525b0734e24807ee99ba88a000000000000000000000000000000000523deae09e75121a6d89b45161f69f0733a9e43d88d8527a03cca8cc126aeb7a680cfaf291554403723e20440b79437334582482a9038ab906880e43a4a9d39e73b6c63604eba0c8f6399eb5c288638",
+ "Expected": "000000000000000000000000000000000db91871e4cd84b3b58216b6c2e77a9521f3080182e78d3f66fe33f313013f06aec2dc5a6d483f35fadebde873bff9490000000000000000000000000000000003b9685de062b09b9e277ad5cd664d28af59064448af2b1b2b2357df6fc88e3ee7e0ac837100e0b7593944e8db43ab0f",
+ "Name": "matter_g1_multiexp_99",
+ "Gas": 64128,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsG2Add.json b/x/evm/core/vm/testdata/precompiles/blsG2Add.json
new file mode 100644
index 00000000..64ca2006
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsG2Add.json
@@ -0,0 +1,730 @@
+[
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "Expected": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3",
+ "Name": "bls_g2add_(g2+g2=2*g2)",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf300000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e849",
+ "Expected": "000000000000000000000000000000000411a5de6730ffece671a9f21d65028cc0f1102378de124562cb1ff49db6f004fcd14d683024b0548eff3d1468df26880000000000000000000000000000000000fb837804dba8213329db46608b6c121d973363c1234a86dd183baff112709cf97096c5e9a1a770ee9d7dc641a894d60000000000000000000000000000000019b5e8f5d4a72f2b75811ac084a7f814317360bac52f6aab15eed416b4ef9938e0bdc4865cc2c4d0fd947e7c6925fd1400000000000000000000000000000000093567b4228be17ee62d11a254edd041ee4b953bffb8b8c7f925bd6662b4298bac2822b446f5b5de3b893e1be5aa4986",
+ "Name": "bls_g2add_(2*g2+3*g2=5*g2)",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "Name": "bls_g2add_(inf+g2=g2)",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g2add_(inf+inf=inf)",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000039b10ccd664da6f273ea134bb55ee48f09ba585a7e2bb95b5aec610631ac49810d5d616f67ba0147e6d1be476ea220e0000000000000000000000000000000000fbcdff4e48e07d1f73ec42fe7eb026f5c30407cfd2f22bbbfe5b2a09e8a7bb4884178cb6afd1c95f80e646929d30040000000000000000000000000000000001ed3b0e71acb0adbf44643374edbf4405af87cfc0507db7e8978889c6c3afbe9754d1182e98ac3060d64994d31ef576000000000000000000000000000000001681a2bf65b83be5a2ca50430949b6e2a099977482e9405b593f34d2ed877a3f0d1bddc37d0cec4d59d7df74b2b8f2df0000000000000000000000000000000017c9fcf0504e62d3553b2f089b64574150aa5117bd3d2e89a8c1ed59bb7f70fb83215975ef31976e757abf60a75a1d9f0000000000000000000000000000000008f5a53d704298fe0cfc955e020442874fe87d5c729c7126abbdcbed355eef6c8f07277bee6d49d56c4ebaf334848624000000000000000000000000000000001302dcc50c6ce4c28086f8e1b43f9f65543cf598be440123816765ab6bc93f62bceda80045fbcad8598d4f32d03ee8fa000000000000000000000000000000000bbb4eb37628d60b035a3e0c45c0ea8c4abef5a6ddc5625e0560097ef9caab208221062e81cd77ef72162923a1906a40",
+ "Expected": "000000000000000000000000000000000a9b880c2c13da05bdeda62ea8f61e5fc2bf0b7aa5cc31eaf512bef7c5073d9e9927084b512e818dbf05eab697ba0661000000000000000000000000000000000b963b527aa3ec36813b108f2294115f732c878ac28551b5490615b436406773b5bb6a3f002be0e54db0bcebe40cb2e2000000000000000000000000000000000bd6e9060b42e36b57d88bc95b8b993da2d9d5acd95b73bad0509c2324212bcf7a94a46901932c0750535d00008a34f7000000000000000000000000000000000a374afd32bc3bb20c22a8864ce0dafe298bda17260b9d1d598a80830400c3fd4e8a8f677630eae5d4aa0a76a434e0ba",
+ "Name": "matter_g2_add_0",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d938800000000000000000000000000000000192fa5d8732ff9f38e0b1cf12eadfd2608f0c7a39aced7746837833ae253bb57ef9c0d98a4b69eeb2950901917e99d1e0000000000000000000000000000000009aeb10c372b5ef1010675c6a4762fda33636489c23b581c75220589afbc0cc46249f921eea02dd1b761e036ffdbae220000000000000000000000000000000002d225447600d49f932b9dd3ca1e6959697aa603e74d8666681a2dca8160c3857668ae074440366619eb8920256c4e4a00000000000000000000000000000000174882cdd3551e0ce6178861ff83e195fecbcffd53a67b6f10b4431e423e28a480327febe70276036f60bb9c99cf7633",
+ "Expected": "000000000000000000000000000000001963e94d1501b6038de347037236c18a0a0c8cec677e48fc514e9fc9753a7d8dcf0acc4b3b64572cb571aebbe0b696640000000000000000000000000000000000d9739acc3a60f6dffb26f9b5f1fd114a21f2983deea192663c53e012b9f8e1cabd4942ad039badbd4745ddc0a26a91000000000000000000000000000000000b4206dcdb80d62195febb6773acab25fa2c09a2e4be9416ca019faeb72f1fad1dfdc51e8cea39b371a045b18947d40a00000000000000000000000000000000100758b888fa27e9258ddd5d83409e8aeac576874bc399b33b8bc50d77fce5358cb091d42f9a1b1ed09be3f200959989",
+ "Name": "matter_g2_add_1",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003632695b09dbf86163909d2bb25995b36ad1d137cf252860fd4bb6c95749e19eb0c1383e9d2f93f2791cb0cf6c8ed9d000000000000000000000000000000001688a855609b0bbff4452d146396558ff18777f329fd4f76a96859dabfc6a6f6977c2496280dbe3b1f8923990c1d6407000000000000000000000000000000000c8567fee05d05af279adc67179468a29d7520b067dbb348ee315a99504f70a206538b81a457cce855f4851ad48b7e80000000000000000000000000000000001238dcdfa80ea46e1500026ea5feadb421de4409f4992ffbf5ae59fa67fd82f38452642a50261b849e74b4a33eed70cc000000000000000000000000000000000a69d6d9f79e19b38e6bf5a245dc820bddbdfe038d50932f76d0e4629d759f8ca6d573fcfc39256305daedf452f9fdf40000000000000000000000000000000015f5949369e58487afcecf8018775d1b0a73e913bf77e13d2e5a843bbbeba7d1978ca27ae8bfc87d30f567dd396b980e00000000000000000000000000000000182198bb38a0353b8db25389e56ab0d8679a1bda008a65dad77e4c95bc6804f6311eb16c761e1a5e2a5f87cfada49fa4000000000000000000000000000000000eb5483959e98c30e71db52615f63521378b156f142d46f3bb285b94aef39d80feacec335b797c5a68dc17ba89d43e0f",
+ "Expected": "00000000000000000000000000000000079e4fc2190d3441fa76c2d925d23b81e353e09e9138fdde51234195e564a32c98aa0d240f051298bf966d17adc2d6fb000000000000000000000000000000000aa327776fa7e15000dd548fcdc3a1cc6f9d0ab33046dd4240a3002962131b738ffed579945a348c795cfcb33682cf3b00000000000000000000000000000000179232ec56602d1ff79861cbfa2edece34b296541483aa65fe0cb493f520b7722cfffbe04294dd054770a38bf75d927b000000000000000000000000000000001826b88a6b411330757bb304a380487a02f7cf421115b84b3f468d11a83dbf304ce7a5661f4f01299d3c7865305a0006",
+ "Name": "matter_g2_add_2",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000149704960cccf9d5ea414c73871e896b1d4cf0a946b0db72f5f2c5df98d2ec4f3adbbc14c78047961bc9620cb6cfb5900000000000000000000000000000000140c5d25e534fb1bfdc19ba4cecaabe619f6e0cd3d60b0f17dafd7bcd27b286d4f4477d00c5e1af22ee1a0c67fbf177c00000000000000000000000000000000029a1727041590b8459890de736df15c00d80ab007c3aee692ddcdf75790c9806d198e9f4502bec2f0a623491c3f877d0000000000000000000000000000000008a94c98baa9409151030d4fae2bd4a64c6f11ea3c99b9661fdaed226b9a7c2a7d609be34afda5d18b8911b6e015bf49000000000000000000000000000000000286f09f931c07507ba4aafb7d43befe0b1d25b27ecc9199b19a9dc20bc7ec0329479ef224e00dece67ec0d61f1ca5ae0000000000000000000000000000000014e6ed154b5552be5c463b730b2134f83e0071dcdadfaa68e6c7c7f6e17dabb7daf06e409177bc4b38cfdb8248157618000000000000000000000000000000000f145e998dc6eb0c2b2be87db62949c7bfa63e8b01c8634248010fd623cfaec5d6c6c193331440957d333bf0c988b7b10000000000000000000000000000000002a1ab3eea343cfdea5779f64b3bddbf0769aded60e54a7507338f044310ba239430663394f110e560594d6042a99f1c",
+ "Expected": "000000000000000000000000000000000f69e3616e7122bf78230461bb1f4b194988adc6149372691d8794d0086fba0870a2255a2c79cc3426e7ba4d032fc2ab00000000000000000000000000000000174752301e05dcd62f7a3ae3357344e64d1c94835b2b742ac24449ee2728d693a0df10c3beaeb45d1b4af4ac2bdbb8b200000000000000000000000000000000051a761a3ceb275ec28a2a269b5ded1d9fd11a617c958e73c07de3a92ac480aa82c7d2a1852d291804e734526277f5740000000000000000000000000000000009bec9045ea89d5d16588e3373cc977f6d975d0e2213b171403a9b2ca460b3b2e1106b474185516d4200655b17a179a1",
+ "Name": "matter_g2_add_3",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001156d478661337478ab0cbc877a99d9e4d9824a2b3f605d41404d6b557b3ffabbf42635b0bbcb854cf9ed8b8637561a8000000000000000000000000000000001147ed317d5642e699787a7b47e6795c9a8943a34a694007e44f8654ba96390cf19f010dcf695e22c21874022c6ce291000000000000000000000000000000000c6dccdf920fd5e7fae284115511952633744c6ad94120d9cae6acda8a7c23c48bd912cba6c38de5159587e1e6cad519000000000000000000000000000000001944227d462bc2e5dcc6f6db0f83dad411ba8895262836f975b2b91e06fd0e2138862162acc04e9e65050b34ccbd1a4e000000000000000000000000000000000d1007ca90451229d3780d66d3aed7c9d8fc82e9d45549e8586600e38eb6763f3c466e2f6ba6ba1dafd8f00cc452dda20000000000000000000000000000000001d017d920a262b6d6597bab532f83270f41526409510e80278d1c3595ceabb9ceba8ae32b1817297ff78ea7a0d252e8000000000000000000000000000000000935b7a59d2e51bbb2f9b54ccb06ebee9d189fa82f0e97d10c8020badb3de7fe15731b5895faed8cad92ae76e2e1b649000000000000000000000000000000000792dadd48a20040ad43facedc109747411895180813349d41d0e5b389176bfb15895d41665be8d1afa80835ef818eca",
+ "Expected": "000000000000000000000000000000000c079610e6f8770d65352f911863b6cb4fcb25cacc4a42f75e34e29e977c93244a6241cf3d5bd1040ce7d8987996f87e0000000000000000000000000000000010d08d8f6fa8ee7042c0891ea0c3b9b59a79da52cf3a91627c79d456212e3f6f39e1f69aa0053bbdb4076a3f7d05e5dc00000000000000000000000000000000069047218b0ac1e07650ac8f4a1b9235f68408f543517c4ae3c0ec47c79b468713c704ff3680edc8abd1bbed7a5fa75d00000000000000000000000000000000137737706162e02cfa75ce2154d57c9a3520818cc04626654824769ad92ff7977942f3881a28284ea47c14f353772d0b",
+ "Name": "matter_g2_add_4",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019c31e3ab8cc9c920aa8f56371f133b6cb8d7b0b74b23c0c7201aca79e5ae69dc01f1f74d2492dcb081895b17d106b4e000000000000000000000000000000001789b0d371bd63077ccde3dbbebf3531368feb775bced187fb31cc6821481664600978e323ff21085b8c08e0f21daf72000000000000000000000000000000000009eacfe8f4a2a9bae6573424d07f42bd6af8a9d55f71476a7e3c7a4b2b898550c1e72ec13afd4eff22421a03af1d31000000000000000000000000000000000410bd4ea74dcfa33f2976aa1b571c67cbb596ab10f76a8aaf4548f1097e55b3373bff02683f806cb84e1e0e877819e200000000000000000000000000000000095353ad699b89ac82ca7ef631775b2b3a6e3ed8dd320440cdb929baa428e63cb902a83857cc0e2621470544c69e84aa000000000000000000000000000000000892559ade1060b0eef2cbc1c74de62a7ff076a3621e5f0f159672a549f1201f2ffb3ac12c8b12cb86ae3e386c33e219000000000000000000000000000000000750df4632a7126ddb08658a4001f949b9764d9cc43a9393cc55d8fdbb15d4a1186dd87a6433d111888a7804540ad9fc0000000000000000000000000000000017554bd444665df044b91b0b2614017bbfcd7acc7f8c5a16cea2861235578ce2b27dcced9fba234999fa478cd3f6e42d",
+ "Expected": "0000000000000000000000000000000004dd5dfe38fa70625216ecfec60ea8d38602552726f0fdfb8f392362ce845fe0fda76894d0e456796e08462bb941579f00000000000000000000000000000000195a85cd0685f4053ee539de7e04fccd2380819b291f89cbcd63d5a0015b3214500284a7c6568a71f52bbdbc38be410a00000000000000000000000000000000107c211bad49c7dd8555e30f2500c67e7175eb98a8494f3d5309c65a93cce89572b7b5489428eaf3f0a5c1be323c5352000000000000000000000000000000000c11f978150ac35722679cf79443b3706d288c968116ddedc1f1d0fca8cd746e3c92dc006330be14886c53c41feebbf9",
+ "Name": "matter_g2_add_5",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000147f09986691f2e57073378e8bfd58804241eed7934f6adfe6d0a6bac4da0b738495778a303e52113e1c80e698476d50000000000000000000000000000000000762348b84c92a8ca6de319cf1f8f11db296a71b90fe13e1e4bcd25903829c00a5d2ad4b1c8d98c37eaad7e042ab023d0000000000000000000000000000000011d1d94530d4a2daf0e902a5c3382cd135938557f94b04bccea5e16ea089c5e020e13524c854a316662bd68784fe31f300000000000000000000000000000000070828522bec75b6a492fd9bca7b54dac6fbbf4f0bc3179d312bb65c647439e3868e4d5b21af5a64c93aeee8a9b7e46e00000000000000000000000000000000175dadb6ee656ec6aebf8d0e5edaee3f119c74e0ea64e374be9e8ab9fd3d085fceeedf4ed8de676ebe9065d83b0542ad0000000000000000000000000000000005cd6a875329c23e4918976cf997e93e403957acfc999f8159a630d21ab6f1762925c063784237262bedc82402ad81bb0000000000000000000000000000000003274bcb8db35e50164d136c2a98b5a6d2fb5f9767d0ee11c1358bf7ca5ed96d9122f8c1051ba3c658cc89777d03dfa5000000000000000000000000000000000380a240443dff85b6542f75db28b87c39e278cdb8d9627efbbc63b229e6ce783f6fb0114c8e91c2fd6ea71c95bb99a4",
+ "Expected": "000000000000000000000000000000000fb33caed4de22cf341bb3e04d41c0198b064c1d371a24f5cf59595ab4a1edfd379916a40cc405d35f0603b2f8fb987400000000000000000000000000000000131ad6172c20b3a1cc2542db037de1324086fd9cd140ae97987980f260023d91b24504181af6fcbcfa242f48e99559320000000000000000000000000000000004a0404c00789459395f5344544041785d10f2fe74d4bf484966f5e9b6b4c4c8cb113a811a4fa82a1cdf8e3242bb418900000000000000000000000000000000086ba6a914f3f07bdc6750fcf6baf76124a17964bf9eb9a12982e8a28ca04360da3544b69436d5663e4e94bf7189529b",
+ "Name": "matter_g2_add_6",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000690a0869204c8dced5ba0ce13554b2703a3f18afb8fa8fa1c457d79c58fdc25471ae85bafad52e506fc1917fc3becff0000000000000000000000000000000010f7dbb16f8571ede1cec79e3f9ea03ae6468d7285984713f19607f5cab902b9a6b7cbcfd900be5c2e407cc093ea0e6700000000000000000000000000000000151caf87968433cb1f85fc1854c57049be22c26497a86bfbd66a2b3af121d894dba8004a17c6ff96a5843c2719fa32d10000000000000000000000000000000011f0270f2b039409f70392879bcc2c67c836c100cf9883d3dc48d7adbcd52037d270539e863a951acd47ecaa1ca4db12000000000000000000000000000000000834cf1b4149d100c41b1bca0495e455002eb6596bddcb94ae48d0c65957e8b313372f8e0d6e57504664b266f38293150000000000000000000000000000000000de2875fbd14760bac4c2cc7d3f239177efe9f7f61f767be420d44f24c9fb863efd60dcd732986db8c5b72470617ea60000000000000000000000000000000000bc9535ebf11c2dcc8c7d3bcd09d7d14035635fccb5fddb7df29ce8855e79f99809781d6ffbbcb33d1227314609abee00000000000000000000000000000000039bbfb4d969d702255e3be7f255a97529a19687ce38cb70637c37894d4102591feef428b0afe8c9ef50310ae3b83091",
+ "Expected": "0000000000000000000000000000000019c8a1a206c0006a3033377abba4c31c55710a094d8c9dcef7560818e90411861ce7d189e2763f8fe69bf75e719e4efe000000000000000000000000000000000cccc6bba8691c210aa0a67d26584a359fab94041d853160abd9669893c0d398c805cc37fa3c33bc5ee5ff915b985c45000000000000000000000000000000000e353c1993c36763acec2a75495560e743d099b565f3de195e011afcacff3d60502801f47695da7dd589af81e772eb7800000000000000000000000000000000100c6123cf08eab6c59d78b414fa504ed10c204851289b0598b40ac31971fa12cfda4ef7cd2d64f9797d4d2b193e0bd2",
+ "Name": "matter_g2_add_7",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017fae043c8fd4c520a90d4a6bd95f5b0484acc279b899e7b1d8f7f7831cc6ba37cd5965c4dc674768f5805842d433af30000000000000000000000000000000008ddd7b41b8fa4d29fb931830f29b46f4015ec202d51cb969d7c832aafc0995c875cd45eff4a083e2d5ecb5ad185b64f0000000000000000000000000000000015d384ab7e52420b83a69827257cb52b00f0199ed2240a142812b46cf67e92b99942ac59fb9f9efd7dd822f5a36c799f00000000000000000000000000000000074b3a16a9cc4be9da0ac8e2e7003d9c1ec89244d2c33441b31af76716cce439f805843a9a44701203231efdca551d5b000000000000000000000000000000000fc09c241899fa6e8cc3b31830e9c9f2777d2bc6758260c9f6af5fce56c9dc1a8daedb5bcb7d7669005ccf6bfacf71050000000000000000000000000000000018e95921a76bc37308e2f10afb36a812b622afe19c8db84465ab8b3293c7d371948ee0578dbb025eed7ed60686109aa0000000000000000000000000000000001558cdfbac6ea2c4c1f4b9a2e809b19e9f4ba47b78d2b18185ed8c97c2f9c2990beadc78b85c123b4c3c08d5c5b3bbef000000000000000000000000000000000ea4dfdd12b9a4b9a3172671a6eafed7508af296813ec5700b697d9239ae484bcf7ab630e5b6830d6d95675be5174bb2",
+ "Expected": "0000000000000000000000000000000009fc3870f88288c680b43d63d3bb5305b99fe461e59c07be981b8819fbee0d1fdfae0c037e830fbbabc40cedac7919720000000000000000000000000000000018bdd4903da4d14fa28af4c2cddcb708238cf68673ce77a04a3926c4aaf17d39a831c5401e84dd042d6adf595a1763710000000000000000000000000000000002c398f0e8ad9752f4aded980bc5de2d91118db06818d815c11e818ead47e7065823737db8e304bae32969cab065d1ff00000000000000000000000000000000180642a633c3aa402e5c0b18fcb6fe8c115575b863abda59b5d91997ab01014faefc975d0aee994f98cf37ce79eb95aa",
+ "Name": "matter_g2_add_8",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e25365988664e8b6ade2e5a40da49c11ff1e084cc0f8dca51f0d0578555d39e3617c8cadb2abc2633b28c5895ab0a9e00000000000000000000000000000000169f5fd768152169c403475dee475576fd2cc3788179453b0039ff3cb1b7a5a0fff8f82d03f56e65cad579218486c3b600000000000000000000000000000000087ccd7f92032febc1f75c7115111ede4acbb2e429cbccf3959524d0b79c449d431ff65485e1aecb442b53fec80ecb4000000000000000000000000000000000135d63f264360003b2eb28f126c6621a40088c6eb15acc4aea89d6068e9d5a47f842aa4b4300f5cda5cc5831edb815960000000000000000000000000000000000b36d8fb9bd156f618ab8049d41dfe0698218764c0abb10e12fae43c8810b8e2a5201364e2778f6f433b199bb8f9a6800000000000000000000000000000000000707eb15411b63722b4308c0ed4288320078d2463ae659ad4fb3f9ef8124f379df92d64e077403e50727388adb59ac00000000000000000000000000000000158e1249d5b91614924acb23899c6bae408697dec0982c10d0459746499f4e6739afb9d5129568106ed1a1caefeaa9640000000000000000000000000000000019e841562e4aa75321143f8ce1e5ec6158fa5cb8b98c839a486188260c18ee8a7600930f23aa39eac2eb520d6a0fba90",
+ "Expected": "00000000000000000000000000000000199600699a6108599c638df8f965d73b5de4ca74598df281ec95c539de2c7eff9767569692d8e0ad120fcbb3d9335b95000000000000000000000000000000000c42b11e2585ba93521b3c968e9dee07e4f5168c11087d8d750795555a105df70c969bfa79b1ab4e5fc8d81657235d08000000000000000000000000000000001370daa4699daa99e9940fe04f69150e6f752798cbc0e66c91c3bd46149d935c1815f32d7f14b510e16d475044eda9cc0000000000000000000000000000000016c7a00be10de5732795cc3ee2951e58cb9d42f9b05d02fbff1b83fab5d3ad830cb8178092b76172108d7a53afe8c539",
+ "Name": "matter_g2_add_9",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000159da74f15e4c614b418997f81a1b8a3d9eb8dd80d94b5bad664bff271bb0f2d8f3c4ceb947dc6300d5003a2f7d7a829000000000000000000000000000000000cdd4d1d4666f385dd54052cf5c1966328403251bebb29f0d553a9a96b5ade350c8493270e9b5282d8a06f9fa8d7b1d900000000000000000000000000000000189f8d3c94fdaa72cc67a7f93d35f91e22206ff9e97eed9601196c28d45b69c802ae92bcbf582754717b0355e08d37c000000000000000000000000000000000054b0a282610f108fc7f6736b8c22c8778d082bf4b0d0abca5a228198eba6a868910dd5c5c440036968e97795505419600000000000000000000000000000000186a9661d6fb539e8687ac214301b2d7623caedd76f4055089befba6ef2c96263d810921ad7783d229f82783c9def424000000000000000000000000000000000447f3e20caa1f99fbaccab7bde2bd37fe77cea691ebf2b9499f95bbbb77afe72b7039eb0c05970b61360fcf8ade73730000000000000000000000000000000005e11f828eda86c10a1d7929def547ac06885da278afae59c5d95453caf0a2d8ed186fa7c6d0a7ab6e9142cfa4b338190000000000000000000000000000000003d954e61b6ab71042b19e804efccd4956b56662f27f70a9255cec0c464b86c0e83721ad3785dec62dd4a9dd3d6d5d53",
+ "Expected": "000000000000000000000000000000000669cc8a3acae17f99f805afb9012a38851a9e8d4fd9895a9946c29fc859849c24d7ab7b6278c449cfbc5f1d7ea1fdbd0000000000000000000000000000000007a9095be808d0ebc99bce94e851d2a7cd3e1977b923064ab5bbed2347cf18f3343e60120fa051d12fe27da3146cb423000000000000000000000000000000000f1e7f75887651f67457f6dc064d7c11934035d15fe4dc40bab970160ed1b1aa230a3fb84dc1da08770d847c0216347a000000000000000000000000000000000efbc62ade1678cd70eb38c644038bf19e52b0859f65747068d9f3124762d951e4a6ff05f34b6d14919774f8409adff5",
+ "Name": "matter_g2_add_10",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f29b0d2b6e3466668e1328048e8dbc782c1111ab8cbe718c85d58ded992d97ca8ba20b9d048feb6ed0aa1b4139d02d3000000000000000000000000000000000d1f0dae940b99fbfc6e4a58480cac8c4e6b2fe33ce6f39c7ac1671046ce94d9e16cba2bb62c6749ef73d45bea21501a000000000000000000000000000000001902ccece1c0c763fd06934a76d1f2f056563ae6d8592bafd589cfebd6f057726fd908614ccd6518a21c66ecc2f78b660000000000000000000000000000000017f6b113f8872c3187d20b0c765d73b850b54244a719cf461fb318796c0b8f310b5490959f9d9187f99c8ed3e25e42a90000000000000000000000000000000002b94534aa0ba923bda34cbe92b3cd7a3e263741b120240ff5bdb8b718f094d3867e3fcabeab4a7be39c8f8c4fdd10d900000000000000000000000000000000048711cf6a82534d64d072355cb8fe647808e7e8b2d9ac9ed52eb7fe121647a721dd1234c71ecd163d91701eb7331cac00000000000000000000000000000000141ef2e23a1ecc7ef2ed3ea915492e79cfffe60b5e0de8441e878bd0653843d79c724e3c5ebe2321361df99f8932ddc200000000000000000000000000000000085513b4009f29b3e00a91c2c4be418368560802ba4194cbd2f4fa3d72a55fcae547014434514a8b2a8fe3e0b28d2773",
+ "Expected": "000000000000000000000000000000000e25a38d0ce2aabd2538c95ed463f226e3f29ce7f10e1be27af2d3db741926d557178c4b125af8789b40480d8beec0890000000000000000000000000000000002a94b7c57fe2783d055a537004a3b67e41f5374da0813094f5944fbabf4d27eb576dc8b21ccc15f8339df14ff8785220000000000000000000000000000000008b9efd8abfa4fd71a8eafdba9df38360ef0b0a117c0052528d1c24df5032635eebc7b201439f5de858514666c68cd270000000000000000000000000000000012a2fde51f6f4a98435c325dc3b1ae846bc33a5ffb3b13fbe3fde2f74dec0aa815fa8e42392b3dbf798cf547fdb4db0d",
+ "Name": "matter_g2_add_11",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000576b8cf1e69efdc277465c344cadf7f8cceffacbeca83821f3ff81717308b97f4ac046f1926e7c2eb42677d7afc257c000000000000000000000000000000000cc1524531e96f3c00e4250dd351aedb5a4c3184aff52ec8c13d470068f5967f3674fe173ee239933e67501a9decc6680000000000000000000000000000000001610cfcaea414c241b44cf6f3cc319dcb51d6b8de29c8a6869ff7c1ebb7b747d881e922b42e8fab96bde7cf23e8e4cd0000000000000000000000000000000017d4444dc8b6893b681cf10dac8169054f9d2f61d3dd5fd785ae7afa49d18ebbde9ce8dde5641adc6b381731734598360000000000000000000000000000000009143507a24313ee33401955fc46562c9b20c9917df3b40ccbd7ed43b1349d4551cfd98a4976d6fec5fc289460c8d89900000000000000000000000000000000060566b79df5cc975e669da8ca3a7fa91bf3f5c9fb871c3d62f4a3e79dbc341b89d38b588e5414bc385d5e3cbf3ab9310000000000000000000000000000000016bf40b8cc4c01a87aafae0c4439b623a51ba9a383756a550b69d627d6f45209f0d87e4f9be9edff35c986f7b9c49e3f000000000000000000000000000000001842d9172bce51a164fbdbdb108d0faae07e4642f21c80e40ac31e737657472ae3dfe552b65349629c210a068c4afc0e",
+ "Expected": "00000000000000000000000000000000067265782d58b04a2ef3dd419cee506e076e49d1119e28db1df7f0e22cba9bbdabc560084cda50bc8db3915fa9c489a30000000000000000000000000000000012448a61fb2f6fd8e355111b671f0e888304284b72d5688091f2ed00edf7ccb7e5bd8a733a910d6964dde07d393798470000000000000000000000000000000005f687356ff6c634eb46613be8e98540107e706714434faff54510234d4aff42ef7752e154aed63fa8ff905ec0af628f00000000000000000000000000000000180dca84a37c964b30f5cd11a090e54acea102f1b884319f8d1252a37bda005512ffc39dec8e33af0dde0d37993f846f",
+ "Name": "matter_g2_add_12",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ca8f961f86ee6c46fc88fbbf721ba760186f13cd4cce743f19dc60a89fd985cb3feee34dcc4656735a326f515a729e400000000000000000000000000000000174baf466b809b1155d524050f7ee58c7c5cf728c674e0ce549f5551047a4479ca15bdf69b403b03fa74eb1b26bbff6c0000000000000000000000000000000000e8c8b587c171b1b292779abfef57202ed29e7fe94ade9634ec5a2b3b4692a4f3c15468e3f6418b144674be70780d5b000000000000000000000000000000001865e99cf97d88bdf56dae32314eb32295c39a1e755cd7d1478bea8520b9ff21c39b683b92ae15568420c390c42b123b000000000000000000000000000000000ab19bbddd661e9db8fe4cb307ecebdc5e03efbb95c5b44716c7075bd60efcfc67de0bfd7c46ad989a613946c90a4c1000000000000000000000000000000000120800e7f344cda816299fa37f603ade06beb3b10907f5af896d6b4e42f7f865b756f14164db84411c56cb2ea81f60be000000000000000000000000000000000f688ddd257e66362af1437b6922d3397a7c3dd6dea6bca8ebd6375e75bf2de40bc287cbf3434388191e56b92949c83b0000000000000000000000000000000005252465784aff8c1c707da58b5808c69583bf852d68f96912bc53f8dae4536b09ccbbd25a49d9e744118992b92b6792",
+ "Expected": "0000000000000000000000000000000012a29d35c9af52f172787c90c5a3e77ed29d66feabf5d7bdd6bfc14dd9a05d402976b84d44647628c908d1816f4e7100000000000000000000000000000000000caf3c372e36de557ecd7eba02e6a79b1b4cff30343119df7a23662c8512095e051ae2dc27e577635c74a260be2b084c0000000000000000000000000000000002ceca293a58bc9beb4ee9a0679eab037f5cf7b326d65c0efeefdbf384ad8e4bc08a3a75a02e6b9cba8963e65d6e76ef0000000000000000000000000000000004631773a6590bc89b49a75bbbe2e732f9466ba259ef7a04ae69b6aa5d5a2621c1918eb213101f6f7eeee4656a7b1472",
+ "Name": "matter_g2_add_13",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017eccd446f10018219a1bd111b8786cf9febd49f9e7e754e82dd155ead59b819f0f20e42f4635d5044ec5d550d847623000000000000000000000000000000000403969d2b8f914ff2ea3bf902782642e2c6157bd2a343acf60ff9125b48b558d990a74c6d4d6398e7a3cc2a16037346000000000000000000000000000000000bd45f61f142bd78619fb520715320eb5e6ebafa8b078ce796ba62fe1a549d5fb9df57e92d8d2795988eb6ae18cf9d9300000000000000000000000000000000097db1314e064b8e670ec286958f17065bce644cf240ab1b1b220504560d36a0b43fc18453ff3a2bb315e219965f5bd3000000000000000000000000000000000e3165efe00f69aee84ac56d2161f07c017abfaadeaad34f8c96799d68bae0e6f9b557bbf9137e7826f49f29c58d1ef9000000000000000000000000000000000de0dce7ea371ad60f21f2cb61cb582b5072408a7efc91edf05b36a1a3b58fd9e6cf808d75157eedccc8f1c93a8ae07d0000000000000000000000000000000016d911943d80427385ebac1d1b293914a9e4dd9db06c1d6a758192d63c8fc9368e02eae7fb0e3a7859408f215cfa76ca0000000000000000000000000000000007bfdc6afb8acec625e50ecbc08a5cdb7862b795866323679885ba5cba3fd51f181078e03fe35e96e6383c077eed1bf5",
+ "Expected": "0000000000000000000000000000000017f155ed9911ec56d71d63d57556de071ebe89be36e6bc9943ec068a70dd5a6f045dfb9fde5c1e29d52c9fc17579452e000000000000000000000000000000000a60d62ea549edf4b11f62f2321f39d41bf11f3c4f858dc7db85b1dab1b7644e27eeb1d022d6082f59c65155068d2c390000000000000000000000000000000009d309145fad15860e556ec4b4aecb415865954247c2034d5bc96026e4d6f7612af6e2db99f4e462acee2b303134b91b000000000000000000000000000000000114ed157e3d020c5397cba7e10cb864aabb47461f166a6724614e689274ae74c505fb6ebfe3e88da0d6c272a15a0527",
+ "Name": "matter_g2_add_14",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000018244ab39a716e252cbfb986c7958b371e29ea9190010d1f5e1cfdb6ce4822d4055c37cd411fc9a0c46d728f2c13ecf0000000000000000000000000000000001985d3c667c8d68c9adb92bdc7a8af959c17146544997d97116120a0f55366bd7ad7ffa28d93ee51222ff9222779675000000000000000000000000000000000c70fd4e3c8f2a451f83fb6c046431b38251b7bae44cf8d36df69a03e2d3ce6137498523fcf0bcf29b5d69e8f265e24d00000000000000000000000000000000047b9163a218f7654a72e0d7c651a2cf7fd95e9784a59e0bf119d081de6c0465d374a55fbc1eff9828c9fd29abf4c4bd000000000000000000000000000000000a68dccbe3452731f075580fe6102b8ee5265007ee19c56d95bcb096a3a6ac444f4145b980f41afcb0a865853b279bc600000000000000000000000000000000164767ea55a9038ac2dd254d8c8a4970dba93dacdf5416aecaa407914719cab165e7a32784b2c41652a86358737d831f000000000000000000000000000000000da9441fbc6578c85fdeca49082c9ebbf183de894d67c65158380ee56132d3cdb44b100d72b6d3b82688defb75d2aa390000000000000000000000000000000017d570e4f6e46550679d5d12c347414da207060f594620e2f8db66df8e0b06c912290b207a268e782d4b45db19a199db",
+ "Expected": "00000000000000000000000000000000118e0c81f9157395578f0fb83b179721de2af3326d13189cb8f43911d8c3268a11fd9702f09f14c115bbdc43d5fbc08b0000000000000000000000000000000016a548df8c87f432c31e4e32c3e5b4d48d6f29fbe391d1181174be9dddee450e7e96bffe8c9f23692ccc080116592944000000000000000000000000000000000eef72a5c698c58f1d2ae9415da256b54d7b1ac37a1d1b88727c0afcfd854a41973c6cb10ecbc3a90050fe3d8d3ce8780000000000000000000000000000000019b16ca8f955dfd21830a3f7fafcc97d7de977bafe1983892988aaedd430d22674d97897d24c1643e99bfa6256df4bf7",
+ "Name": "matter_g2_add_15",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000eb3c91515d4a41209a73564741a8ccf901a624df9db22e195a5d02d24b7bc0a12756b15b8d006cb991a7e088eaef1000000000000000000000000000000000704ce8afc808b0161f6f61b22d990d713ae398779e6e74e9b5771daf006ce0bba3a8088edf75156f0e48b92ee8409b00000000000000000000000000000000018fe81e05aff0620f4bdbe4a715e015650497afab62921eba0ab86b649e5a2fd3d54041868928519f537e36448688a0d00000000000000000000000000000000162bd97161201ea3c26f8dd1204a9c6b61b762bdf573cb5d20b6b255f30208ca7d96aa47b46fb8c6bf0922075f1c1ca800000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e",
+ "Expected": "000000000000000000000000000000000f2bf3f69276d390c9fc2c15e9f5f5d0b3cf9a6eb028c44811b481f376ab60e17d33a04b78348e46eaa94332c5f16ff8000000000000000000000000000000000bedd0437fb3f4baef87e56f33c77fcdff6a5512571cf11fd9605697abd8763315f1fe4bccf04acc6e971d6aeefd9c1500000000000000000000000000000000067c3ff69733baae2fb4ab77cddb7563047c428b40a257a375f8cf8c9d230a6619f7932b86e0836fff0c1c60d2c4dfd900000000000000000000000000000000057526faed8d62aa10e89add5a338320c748ca1f96ba5ceb579efec69d17475571fc4ce6fce3a93398ea88340f0e969d",
+ "Name": "matter_g2_add_16",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000135aee0e30fbcad798738c10d4aebcdf50c89ce516325f655fe763dce54ffedf94dd74168611e5ae879b5bf5598d62dc000000000000000000000000000000000c728e672cd8b3bf9341bca929c34118b566cd3a80452d7015bee9d5cdc001b1f5c678d4b2cc4f7cac353e7bf326ca1e0000000000000000000000000000000014809aa22e2051e463fba6d49fbb060d0c7f599a0fc5409d34e71f34817e7beb1251810ae6eee1848c60796fb8647dea00000000000000000000000000000000145a4de777d86025d50e12f9a6615ecb9bdd41489992d1b643dd9aa549acbc63b04b0bdfd14b6e45c70f165e9a8c91be0000000000000000000000000000000001c2d8d353d5983f22a5313ddd58fdc0d9c994b2915dbc87a9b65b7b98ff00b62e140a27dc322d42b3ad190c1b3728dd0000000000000000000000000000000010412f3625947b38bb380a6ed059f1677b7a7afcb91517837c563dadd0e285b95740a200ddff6570d4d92bb636b625bb0000000000000000000000000000000015f4f9a480a57bd1b2388532ab045a1ba93d2f6589a3022c585fe06a1d611165c99d70be06251812405c9c37d6e9f7730000000000000000000000000000000001a78e6c5062a6634a56e9853ff5afacb2e7cf31fd0ea5f0d8c8ac6174c88133cf2f63450ec4590544c9a0e37daac1f9",
+ "Expected": "0000000000000000000000000000000004fc19f8fe47e6acd37567016704b07f906e8741fcb196f697e1fc24b0204292693ff424bf1c5e407f5bcba5a3b1ab85000000000000000000000000000000001816f992c3c461fa6d2014ced382a35b0d70e61927d72b4d661434efff3dafe2f4b6cc91bb1a5dbf809f10f3ed7f36de000000000000000000000000000000000dadf7f7223ccedbeffef31c97df7e01f99299da71b589c8828b65715012aa343d7e041dacc57b34a6b5f84523a7938100000000000000000000000000000000167f7e73e22df81bd2a7a6f14e940a401bf414e5d18b3aa610b2a82ca8f46aecb5721d0092b27f8968b2302c37957268",
+ "Name": "matter_g2_add_17",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000009a58b7116dbd6f550f8ca98071813130ecaa9ea86d5275eebc36860690fa048c9ebeb46600b2b63e847bff3e38ed0d00000000000000000000000000000000113ffc0932c041e0e34b2540c485eb74f5029b339cb60bc88a8a749310f33f330dea137e5f340044fd689264af66696d0000000000000000000000000000000002642da3c2c7b6688aba0b19ab29ac72e35caafa044863c364ea8833fca850289de52c0963bc33d7bba40cb5f568718a000000000000000000000000000000000552d35ca054da2f148c119454f6760607b351f2441921a2be17da2cc10902d71571c5554f132e60df79679428fa07e3000000000000000000000000000000000818e567aea83eaf3142984bb736b443743659626c407987b604a30c79756081fa6ae6beeb2e6c652dbfe9cf62d44e3900000000000000000000000000000000193f0317305fde1046acda2c9491e376aa67244f68ef6495845d049e1293082af91f880be935d9d8ad0e25ad918caae200000000000000000000000000000000109224b8178be58ea4e4a194ca66bef9d14f6fc2c625d25feaa4f32e0f4d72d91024d96839bc96e6a624c5ad6221bd94000000000000000000000000000000000e42decf8a987efaeb4ede37236b637e61249bf6245679be7fd4d633e2d814ed4748b73890ad3c4fcbcfb4960cb67ae7",
+ "Expected": "00000000000000000000000000000000041a5783c748247f05457d30d16f93431e9046a236d5025cc07a27b9f2abaaa556e2df65cf0f0015107253fe94d8b4dd000000000000000000000000000000000193638bf69c7508c4b12808a62e89883c34f97ded6e1b5dcc3f28191e5c7fd901a72a85ae386acccc9865f8144b1bd500000000000000000000000000000000180e8184ab583da58b77b8a4d108a366dff3e3b336ebc5c9153fa815188edc95e7067ef25f7d79526c295d634bc98f5100000000000000000000000000000000125b147100f6df0cede8e22151b3423b1dd364899fdee103c71a44388ff002a367627a2342e15833644bcde61f2ef6b6",
+ "Name": "matter_g2_add_18",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018fbbcba3d4b1e548ceaec4a48db62a2420ff29a67af332ee7ea3f902f84e6c375fd33abc33d945c5bca25603979f9a400000000000000000000000000000000072ff416994364bdc6535f36c82212afa822cd94fade69f11eb38dbdcd37c7e22af55fe05e6a826dad822073656eaac10000000000000000000000000000000017bba179b847278a4878b6faeaab3b1f4bd7540d22817cd9aff95557497f8b9d286657b6162c0f89f7820becc637dd550000000000000000000000000000000018e2bfed71aa9b11fefca2f0db8bd9b8c69540267de50bec4fc90a6e9741891465c9761d19282e1100b3707eeb598b31000000000000000000000000000000000ca0d865f8c8ce0a476f7a6edb3ce4bd5e6c3a8d905d8fb5a10e66542f4325a9963c2f8d96f804f4d295f8993b5204df0000000000000000000000000000000005a966f6254f0ef4f93f082a97abe07db56f00c2ade047d2f0027edef6f00a0dfecaa24d50faa778fa29087302211f7e00000000000000000000000000000000121c51da366557c09af1bbd927521da88dfab3e2e9a95b6effb0a968795486f281f0c887e37f51837557b9e3808987130000000000000000000000000000000001a5524975400b1e88f3fff8dd34dadf5d75564cfc0026df31ee9c2c1d48b0f69a48e1e4a48cc4b7db61f023a7915780",
+ "Expected": "00000000000000000000000000000000095fda8adf3981f4468fb82aa0ccf80e55138c922c6422cd8e67f53ee63e7a390bc345469e9211a1f8d810cf4ba27d0a0000000000000000000000000000000015c19b6af21f75e8e53fcefbae1c8d7f97853a8aae5fa62e606cfc92ae71890702ef9dc5609d3ca8fefd415fbd820c04000000000000000000000000000000000007b7e908766d34c5d99cb7cc76d5d5ea83c29ae1d9b83b163741bc9962e293926b1e251b546ce0c1268def728da78100000000000000000000000000000000084fbd6253211f7d66d52b7f14360729d54b2f94c52f2b76e521dc3961c40b4f19944923f64c6425a44eb158a9727a4f",
+ "Name": "matter_g2_add_19",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019efd37727dfaedf697fcda7a59847dbda8ca7cdc92f34e68691d682e20ae6545ac104d6660fdb8f64a051e69298eae8000000000000000000000000000000001225ace0fdce456dd888c9672503b68ef77b2d11caf1265a767a6ea14911e3ca03fc153f18dfe9d95e0cc68b7b8a3a8d0000000000000000000000000000000008a6b059c1c4da046cc0b1b5d7f33270aceffa607daf6d0d078c06f940604e1a0b4adf01a4091306e3c7eddcf3d95101000000000000000000000000000000000f79bae5260a2f114ffbb9273f3049d3ebb002500a57ee0a7d157d86957f43f87a2e026fb9892dacaadca5ee04fc8e170000000000000000000000000000000002b51851ef3b44481d13f42e5111fa4fec04be0bf6acc7e59dec3a8c8113e5bb7b604c6dbdc5e8eddc2a1ffb81bc2baf0000000000000000000000000000000018ddb483ae75402852b7f285277ff7308ff78a3364cca8b0e0e1fa9182de275fd55c1e8ec3dbde180379c4280787ba8000000000000000000000000000000000170539890c89a4f91acd59efd413b5d1059f0c8fd8718e8f722e865dd106a4eb02e6fb0cd71b34ebc4b94375b52e4dd60000000000000000000000000000000001c2e9392f5d4b75efc5ff10fe97f37e2671cad7e4710765866e92aec99b0130e6ff1314502d069fb7b5f86bfce4300e",
+ "Expected": "00000000000000000000000000000000121e7f2eb906d0b31b8ce5cc46638428b6ee57a1ee70e4ec3c2bc044230b9b86875abe0862145b442c0e34308efc690f00000000000000000000000000000000139120d0a10b82737561d0b3fda01b6df69d9beb7dbabf3ddda036f9b4c317f3ac1eaf400013fe5ad664bea44a73b336000000000000000000000000000000000a923184b381027d8cb3f82708802b204566b2b8bb6a72767aa396324d8a26b4e0f0cb92fd1914d77a4e9af2f1ec31e3000000000000000000000000000000000409732f2225cb5e5c002bef17512519eb1a18bf6c3d7f834d0c7ac8a38433c88b550b3f443d259313eb1133620ebf0c",
+ "Name": "matter_g2_add_20",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016d2b73eeceee17d3bff3aacac9df9ac1c4248d9ea7d6a503a757f7bb22fa6970bb6f5cb5ec154785f7252e1508b382e00000000000000000000000000000000081edc68bbd8db7b10be06ee23d090bd54f9ca07ef24dfed7df7bb05f8cc26e6889dbd40ea203fd5cca5cb588199f9e40000000000000000000000000000000010d3478508619ea9493b4330e2fb9150024cd32dc1378f824788a884a4a30fbf39c630f465557bf0c6d69b4cbecf89f9000000000000000000000000000000000f20c9b134db5d8b7756800c031bf5962fc560ba95d4bd9157b16179f1a37ae08696a2be455ad8d018aead6adcc69b710000000000000000000000000000000011bbc566a10eadf16009c1d2655cfae6adfb0f56f5e55b31dc000414be1b4cee9a0b9f7d9eab4c6829037c327914d5640000000000000000000000000000000009b28329096d8644dfcba6e92477eafff29f7477da4581ce76d1493f03034d7f5d3acaadbe42c76a83ca51db79d456d10000000000000000000000000000000019f75a303fdede5d97f3e521b03ef6b9d7c008d770b59ce3ac38900b340895e008342701ad1b41830b9c010936f4ff1700000000000000000000000000000000161aa1853edbb56fa3bd685c9c6b88e466dfa3c4f194f6774b4d9b1f30b016993bd0d65e8e9d6dea6caa196ff735bd67",
+ "Expected": "0000000000000000000000000000000006a200642d5cece5eaacacb36000b4b897e8d8c661c8282f90495002aa515c7638183cf1e80a0b35e953adb92b6bb845000000000000000000000000000000000e88d4cda34e98df4d727fda79b67961b5b8efb1b125ef2a8eafc481a2cb2fa1530e59a091f31c25cc49d38f545491ff00000000000000000000000000000000082f38c1a1c35981f537547dc3b59331ab8c5e8dd261df58fe6f0c44ef1e65d0cdc1980e1a62f6248f38d0afe91e5627000000000000000000000000000000000eda1002e202e9ee4df5354cb87760d4df32eba1eafdad27cb0636879370a8f93be0bf2a30f15f2fbcd7e52c1bdf6b05",
+ "Name": "matter_g2_add_21",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003dce67181d23af9729e9fb0653d7f79c890fba27de42fada93123e112c4a468fa889921192db8047d86e4db77c60266000000000000000000000000000000000869a1e39d42d9bb0cc0568fdad16abbdac3194af893ebd8dd8f8c2c3c855abefa5fc215412168acadc88e658e83f5570000000000000000000000000000000001ef139a75194f3c4b1378c2b66dd304d179460bac0a289405cd8faa3ff66a7b6e54eb7b8742a68150b1e098630135c40000000000000000000000000000000003892b5a645af916be2c6c7fc0bb08fb5f39341d3c68598940554e1be11e1be75af920db0c8710ed13c78edbf683f17d000000000000000000000000000000000ae7289aa9bf20c4a9c807f2b3ac32f0db24e9a0a360c92e5ce4f8253f0e3e7853f771597c8141d705062bef12d4fea80000000000000000000000000000000001d2f610d79110f93145faad2e34f3408316b1dc3a72852e811b324577d9037035e24af25002ddd100cd9283b70ddcad0000000000000000000000000000000012947315d5c0ec670619125eed0de3dd259a008baee4379b82accf2391e70a2bdad264cda04c3bc1b5394a62559fa0ef000000000000000000000000000000001239e687c4d3417c3c9b655035f8d8a649c255f9a8e6f03b785eed0d416a1cd6ef7c8b45563acb4616af24f64dbccac4",
+ "Expected": "000000000000000000000000000000001341cf3316152ae8d57ea2194224f04756690133d2e02d077dc271aa577278e346e0ff66e8a49ff8c983fd34546e1f6f0000000000000000000000000000000016c9093da650643f4b4061e1c6e55da6ebaf9f234bef8325aeecad3863a0a2f53e1cdb2d54aa8b075ce6e6632fb4cd660000000000000000000000000000000011eaf3dee010bf2a16c5fbb1f7aa559cd4d831f087d9dfad4e157a6d2b6495e370d9791cbaaae19339a65726ebfc3b910000000000000000000000000000000008476d793305204be414819fce2ca70754a532682876277bc0586514f2096ba9998ae848c722ead6722d5af9395ff77f",
+ "Name": "matter_g2_add_22",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000264dd4b477f5db65edad28c7153ed919a863c5c5661e0125c5429b323e055fd69c33142dfc6ed9c87082e2be4675e1f00000000000000000000000000000000046ea088a2ec94d3a1f1f97949f1ebc49690c453d316cc46534fa253b34b30323b6071d147d64bb94e02fb4db07bb0c400000000000000000000000000000000013692a33bb1348486eec40a9e93a4ea3810c7b4d3188cd07e235a2c898aa87ee0d17682fd24f4d978f9fb028fd26e2900000000000000000000000000000000115f8b64c00cd5cd344a7b5edc0ef0bb85a3e8f0f9dfb28f8ffe12db3e0d222c2d45dcdba0fbdc161c5d558bc71aa097000000000000000000000000000000001179ee329771b5913d07818e70f6ce5a58d74ea0b573eaa1bd3d97e45d3eeb27fcc7d37dba127af7a38354cb6ff48f7c000000000000000000000000000000000c898abe6eb76ef99f5143cfb8d840a918bcc9096ce25caa45d0bf5d20814cb01b024f1fd2cbecb6bef65d9456070dd90000000000000000000000000000000008e2a4fd746e86f90484f9b9b7b47b6afe5833762e515ccb276c554f00df88dd9aa0fb792c5f419dda0465cfed838e7c0000000000000000000000000000000012b5e6f7070c0045ade96f548ed6428c5030fa20c6f6f37a42fde9dbb5cd01def0fd8585bf8aeef913e7d42b9ef22efa",
+ "Expected": "0000000000000000000000000000000009792d98ab9b90c2467ad0d070ea44f382ec7ad5290a59d889313c5a55d7b8e837333ad7ecfd97221d405cd6c549dc8e0000000000000000000000000000000002b92dd07b61faec23f48b8a7893dae29509fefd688a978bc2e870d4cd6f963d708a0611b4aa65f5644fbc6ba4c5e66b0000000000000000000000000000000011e46a283946a8e033afbf7c14ce3162a05867809d7de94a090c8cc2cdca8bb79add21f6e2fa8d7f39ea6d26cd37ea850000000000000000000000000000000000fddb7cdf1f1126e7a6780e4892601121b289a386ebce0caf96cd392ddc57c47e3f9284889fd8a18fb330d6c40bdf67",
+ "Name": "matter_g2_add_23",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000014c83d58d90db4821a0411fab45f83fbc05f7d0d7a67ce75da3ae568978d15f4c1886c6fa6086675c0045efb30d818400000000000000000000000000000000001e68691123451f4c3df6dae62c6a63855ec3597aae33a8a10ee274e902e9aab1460cc9c79726312df0ee0ce90c8d3c00000000000000000000000000000000018a39eb3e3c6c7fb8ee304e55d15e209afe2fe278dda93552a7b9f51fbd778da1502eb6775cbc3f832f8320fa0686240000000000000000000000000000000017c15910fad1ca5749aa82a5a2fa98b0ebb37e92912547fb1741f18c34e0d5fc3a307b928636c25f0320d71cb9d31062000000000000000000000000000000000fe2e61bc8e9085d2b472a6791d4851762d6401fd3e7d3f3ba61620dc70b773f2102df1c9d6f1462144662fb2f15359700000000000000000000000000000000031f160cde626ca11f67613884a977fb5d3248d78ddbf23e50e52c3ba4090268c1f6cd8156fa41d848a482a0ca39eb04000000000000000000000000000000000eb61ba51124be7f3ee9be1488aa83cbd2333aa7e09ae67fef63c890534cb37ca7de3d16046b984e72db21e1f5c57a8a0000000000000000000000000000000006bf6f5d65aa7d19613141018ac8bf5d1e6fe494a9f30da215a2313a0241779006bce33a776aeedae5de5ea6ee5a9b9e",
+ "Expected": "00000000000000000000000000000000054dedc002c5f2da8c6e0a0146bfe5c83200b276b074e6d6f2c397e1208f152d3ea3e8f0da7da62cfd2a028d4c94fe5b0000000000000000000000000000000012ff307f86e266e7a212484a169d3e81df98217c6f715176913b0d383cbe4e790212da7feca0cea66df09d92544fae010000000000000000000000000000000009c211438dcf8ccb664b535e73eff304b92aa2f568aeaeb8e10ec142f92b211bb8147b250dad77d508cfe353667b6f150000000000000000000000000000000009d1734f4ecc88fd56f412f9243c387b9da659faa3fe7295580a6b7519b1980bd074339fa9b0bef44dcdd0cf0c4a629b",
+ "Name": "matter_g2_add_24",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fa96d9fe01c18732e8d6454df9bb1f482c4b9add837ce9c354c72d49c2d44ec694674aaf0e6d6a095cab7ebb57ccd9a0000000000000000000000000000000001f8ffe3fb7e9e311e0f6949c07c26a0febb181e37b2268bb5e125fc3a100323740d1ebaa5e635dba3770fdc2ce4ee860000000000000000000000000000000012ac42095fdb677720ab3f14bf0afc55c95b43d28d922a5f8cb0bd841306b978751d24546e3a6474976961d0768f29e9000000000000000000000000000000000baf9804d99039c9fe966a696c64bdacc9673b0906b4deab108d34fbbaa3b0905d50892278570564017b96828c7e1ac900000000000000000000000000000000196044a5cdbc5300ee837dca745a44379070e9297697f5db28df4a37307cc740abed45cc778a3f4e3b8c9890ab6c3c70000000000000000000000000000000001176f5de6a3577ad67863bd3d9152ab9e8184964c6ac276e95946788f5a76394047580077c0971d874a40d510eb0443e00000000000000000000000000000000147dd55dff69213c5760e8d22b700dd7a9c7c33c434a3be95bd5281b97b464fb934a3dff7c23f3e59c5d8d26faa426bf0000000000000000000000000000000019efcf03ddb0934b0f0dba3569809d5b48b863d50d3be4973b504244414e1e1db56adff51d33265ce102b320c552781f",
+ "Expected": "000000000000000000000000000000000896a38ce734c550c178786092292e737d44fa5f503d6d3b66c75e6bb70b59d1db9e8baa1ea3e256e2dfd8a942311e75000000000000000000000000000000001231db96a35229a4c7507b0ec193491446a0b43115c27d18b3715fcd4aea14d4e5c99db5934e73bb0b86f1bb91ee96fa0000000000000000000000000000000000d6f95d5637b29ea889c028dacdcb484d8ccdb243da4d5ff49e5ad82f234d414dc1484e9ed6cba1b5940eaabd3066860000000000000000000000000000000007de052fbb76902e06e1783fa8afcbb54a5069b4c5e9cee78d43da2cf76f24843a740a9eec6fe9b8f9bc4ac9baea77a5",
+ "Name": "matter_g2_add_25",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014ce6d88a7c5c782562aa101550f1af487296adebd9dae8252698ba04fbd58b92e2216de6ffd474d5992f97d9f22800d000000000000000000000000000000000ce92a04f5c8a99ca0e93992448222519fc454bda5d1d8638a7bfde968386e4ba0dcd1da59cd81d4c4dca3e584be0275000000000000000000000000000000000cb570796f5c8f7b8aa02e76cb8e870d3365fe4dce5df07ec286a0a821f922b4003d5b69c0f1588206d9544013e268c400000000000000000000000000000000098056a033d9cdae86aac02de3a444471854b909680719154b44d4f55f30087294e39e57643c692d6da725b8592390800000000000000000000000000000000005d8edbabf37a47a539d84393bb2747d0a35a52b80a7c99616c910479306e204e5db1f0fa3fe69f35af3164c7e5726b50000000000000000000000000000000005015082d6975649fbc172035da04f8aeb6d0dd88fdfac3fbd68ec925dc199413ed670488dc6588f9bd34c4ff527f149000000000000000000000000000000001312d53088ca58dfc325772b8dc0e1b20cebf7b2d5b6b4c560759987b44060bf4a59a68d1a5623bbb3cc5b0bc3986b810000000000000000000000000000000012110cd462c6fabf04f67d652639d19640c46f51aadd6c4f9a6dd7806cffb6192d95c198f4c8284151feaa2e2a0dbc1f",
+ "Expected": "00000000000000000000000000000000156914a9137e52abd4579599dea4c0f857eed0457ee1d80635d3a6ccf0c766ba8ab1b6f989711fbdf125c4ff06b597ea000000000000000000000000000000000c60184e8ab32019ce20d2d137130f657c8964406fe4abb26da232c9c5dbfab243837d700c88d6b9ea4b8f0a2f514281000000000000000000000000000000000dc3e6e3acb898552791431859943d0a83fb4ccd62e4ab2a971370a93a99a9dfcdbe4c42535aa063354e0f2cd48308c300000000000000000000000000000000025be02da875d4990d1f0be626ce634c4856ea91f88f636bc27e313e73897c9c13a1e3ae70c1227dfd4fba97f521d6af",
+ "Name": "matter_g2_add_26",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001214aacb0a5e6b7a40369a83c07fa8cf1786ce7cbde2b5a501d9c1292532df7822d4fde10a31fc0cecce3a7cfe3311850000000000000000000000000000000004f9669d8fe4f884ae93b2505710e6e45b19b7aa5df8cdd811f09e547efc27d21024cba05e2dc9d057055f30ec72d9df000000000000000000000000000000000a852b821b31cd27eca19712a636aa05ef2cd82c36ac1c2ca240edc7d0172b42a72c42d3cba583a5b5129ac1c9486e270000000000000000000000000000000007bd8419e791a5cea04993509e91a980d3ae4987a5b322400b6e4a4f2b636891a1c7ba4de96b53426dd556532403d5a300000000000000000000000000000000117fd5016ddb779a6979d2bffe18032d9a5cdc5a6c7feeaa412381983d49ab894cb067f671163ccbe6225c3d85219db6000000000000000000000000000000000dcf01077dcce35c283bea662f4e4d16f871717eb78e630d9f95a200cc104fe67b0d69d95f6704d9812b46c92b1bc9de00000000000000000000000000000000121f212cd7251697ef6a7e3aa93eb0d7d0157cf1247d4411430c36c7277bf8acfccc4ed8590b5e8d0f760e0e4ed7e95a0000000000000000000000000000000007d22d78b486f575e01e21e1239cbedc4628ba7e01ecf4a3459bd78a9716e2969f26ea3f2449685f60397e1ab2aa7352",
+ "Expected": "0000000000000000000000000000000010124c1c1c10868b570d2969ebc3bf5cd6bfab13ddc93f0fd2b8a1742eb8e04d31063bb81c52b92e253128d4cb4413a60000000000000000000000000000000013f89997cd2ddae00cbf24cb66a92146c553c6fae41cdfaef14d49078729f239ad2661937dd0d4d6ffd7076b03e0aa84000000000000000000000000000000000ba2ecf990cd846c95b35ab60d4f97f5814c8189190df9d521b3dae462f2d44db006a0daecf6b82c1459006bf82ef7c90000000000000000000000000000000016dc129b83cca5b3c699628d081306c5fa61faf9dda5e92894931714037628fb829c595bf64d4a7fa295f136ae244601",
+ "Name": "matter_g2_add_27",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005ef88bf38b2f998dec7302cde829076e6cf69df23aa0bf6bbb39fc0d3d8b5eafba74efb928b1de0eeb3d86ec82612300000000000000000000000000000000011f47e9583997b19c36616e4bf78d6ddd6d67937f493986250ff02aef6e6e7ff074559af2f20a5bf1d67158e4a199cdb000000000000000000000000000000000007777c8eb259a836e6459b7bdb642f878d869fdcb31b105d01f280938ef5377f2775874c099dcd394abe70f17d595b000000000000000000000000000000001607379d1cd34e2d0ed765a339b21433e9aa489609b92414c6b5a05d796085269c288d739717def9db3502e055086016000000000000000000000000000000000224cbea61c5136987d8dbc8deafa78ae002255c031bb54335bcf99e56a57768aa127506fca1761e8b835e67e88bb4dd0000000000000000000000000000000018cbf072b544df760c051d394ff68ad2dd5a8c731377fa2a5f61e61481ad5b42645704a2d083c7d45ed4774e5448141e000000000000000000000000000000000740b8b7d7bce78a51809713656c94cf98de72887676050f65f74c57cbe574278dd3634c44e057ea95babcc3d230e3c40000000000000000000000000000000006696058a191c7012a4ee7c973c2005ac51af02a85cbb60e3164809a583b4431dda2b59e1c9ceeb652b3ac7021d116a6",
+ "Expected": "000000000000000000000000000000000a66f36f2437db57473bd8b7670994f1cfeb8b43c0ceae358e63a5e4e52b737fce6b3d24cc4de593bcd44c63f2c5935900000000000000000000000000000000070b7ad970f03a38c8a31452cf11422159cd3331d746031781a5861e26f54efbaba63dcb1db8bab997eada9c3dac39cc000000000000000000000000000000000ba4a9d7350adca1ae64e722df11baeea77c5fb75c5b52c8c46b9d863a70bfed1ec47888e907213f4ed4dcaedd37f20f0000000000000000000000000000000008a64244f1870a1dbcc4bd4d5c9eb5cd5225713dc73aa22bc46b1cea36c88a66f85251a8a9ba7279c88bd5dd37a06f7b",
+ "Name": "matter_g2_add_28",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d6e3068c082b68312141aa68f1540ea1415e93e7f1762b6f06ff408a9995542da1c727a13355c19f8f418a44de1a95d000000000000000000000000000000000dcfcf2ab12b1a0e521ab402aaa4d32ff649a5a97892eb6ad98487c3c73c35601c313b8130ad12e9098d16eed3bcc2e00000000000000000000000000000000013777b1eefa4af03dc44e4e054eb7a3a980a9c55644900b80346be84b970e1754d1f4ab771adc9249e4accf88a23fb400000000000000000000000000000000002f53b231f1209c6f8b52f99a78bc2147c951ac89b341495f4a60a6572985ce2bc823625099ec214bc9ceedb2deea3ff000000000000000000000000000000001522e0a4ccd607f117fc6fc8f9abcd704e9850d96adb95d9bfaab210b76bfb2c5dc75163b922bd7a886541250bc1d8630000000000000000000000000000000018a6e4327d633108a292a51abed43e95230e951e4476dc385ceea9c72ed528bf3e06c42d10cefbd4aa75b134936e4747000000000000000000000000000000001198587188e793ad2ec2fa0fa1d0da9b61ed48444fe6722e523aeac270f17f73f56b1e726ab811bb54a6e42e506d70a20000000000000000000000000000000004bedd94182e0f16c71223ac3d68ab327d28ee0ccdcd2c2db07faf69e1babe3fbf3ba09c28b146eca7ab047b59294703",
+ "Expected": "00000000000000000000000000000000079f89f2defd1f97efe0ba1db28523abc88cdf66efd39918a600a07c5ed5b72ab9d3354a172735e7749b5f6814a48f4f0000000000000000000000000000000009e361b8609be8057e5b3c99eaa1727fdac17edc59239af17f55d72c8b8daa89726f4ae240c742ec4b02fbd89d45c46400000000000000000000000000000000121b475a2ab50357ce80fe01fc461195029de20f61474b0773d80434253adfc268a775e1a0e3b7df5e85d1ff8c5008960000000000000000000000000000000019a76aef4e04136b1ad0d03586a3d8608ac4573715f18d5fd6907d03e5fec7c5659e15c19fd87f242da972b651dff5fa",
+ "Name": "matter_g2_add_29",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000161c595d151a765c7dee03c9210414cdffab84b9078b4b98f9df09be5ec299b8f6322c692214f00ede97958f235c352b00000000000000000000000000000000106883e0937cb869e579b513bde8f61020fcf26be38f8b98eae3885cedec2e028970415fc653cf10e64727b7f6232e06000000000000000000000000000000000f351a82b733af31af453904874b7ca6252957a1ab51ec7f7b6fff85bbf3331f870a7e72a81594a9930859237e7a154d0000000000000000000000000000000012fcf20d1750901f2cfed64fd362f010ee64fafe9ddab406cc352b65829b929881a50514d53247d1cca7d6995d0bc9b200000000000000000000000000000000148b7dfc21521d79ff817c7a0305f1048851e283be13c07d5c04d28b571d48172838399ba539529e8d037ffd1f7295580000000000000000000000000000000003015abea326c15098f5205a8b2d3cd74d72dac59d60671ca6ef8c9c714ea61ffdacd46d1024b5b4f7e6b3b569fabaf20000000000000000000000000000000011f0c512fe7dc2dd8abdc1d22c2ecd2e7d1b84f8950ab90fc93bf54badf7bb9a9bad8c355d52a5efb110dca891e4cc3d0000000000000000000000000000000019774010814d1d94caf3ecda3ef4f5c5986e966eaf187c32a8a5a4a59452af0849690cf71338193f2d8435819160bcfb",
+ "Expected": "000000000000000000000000000000000383ab7a17cc57e239e874af3f1aaabba0e64625b848676712f05f56132dbbd1cadfabeb3fe1f461daba3f1720057ddd00000000000000000000000000000000096967e9b3747f1b8e344535eaa0c51e70bc77412bfaa2a7ce76f11f570c9febb8f4227316866a416a50436d098e6f9a000000000000000000000000000000001079452b7519a7b090d668d54c266335b1cdd1080ed867dd17a2476b11c2617da829bf740e51cb7dfd60d73ed02c0c6700000000000000000000000000000000015fc3a972e05cbd9014882cfe6f2f16d0291c403bf28b05056ac625e4f71dfb1295c85d73145ef554614e6eb2d5bf02",
+ "Name": "matter_g2_add_30",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000047f92d6306bed1cb840f58fd57b5b71a5df7f86dbfa55a36636cb495e08715cd57f2f3e7cd99a1efc28b1d684de1cb0000000000000000000000000000000000f4eb02d687a1a6105b4dbd740e2c7924689d558e6cbfee768dd303cc8dd0fd887f5eec24b54feccf00f473ca3f54ad000000000000000000000000000000000edad68c4d536912816cf6ef039c3dd0535dc52189583270b3b038e2c67b213d943bf384ce69c4a9dc526d7ef309f25a0000000000000000000000000000000006ff4a6b5129ef026d1d5704bf7fc0b474de92b5cf39722f165e73f4e7612d6d3bb40743e4b7b42d0dad5d5d6a2d4881000000000000000000000000000000000805892f21889cab3cfe62226eaff6a8d3586d4396692b379efc7e90b0eaad4c9afbdf0f56b30f0c07ae0bc4013343b30000000000000000000000000000000007853f0e75c8dee034c2444299da58c98f22de367a90550dbc635fb52c9a8f61ccc100f70f10208944e48d09507fdce100000000000000000000000000000000064afd6b3ef7ff7ec34f1fa330877b42958a46a7698c6d21adf73bfdfcab7793b312e21e5988652e655f2d42edb8a673000000000000000000000000000000000ea8a2217c3dbcc0f6e562de9cb2f334c896577d0b3a7108d96b1aba2d705dbf531e870d4023cec2c053345501324233",
+ "Expected": "0000000000000000000000000000000013f8cdab447ef9be450b87f941c96d4e93d5efd811d80c6a910965728f7dc496dec132f3fbeee5d1e84ed7c24ca9c2a8000000000000000000000000000000001537d5caa13ddfac93f0f86729c743d9a68175a78c730528b581fb54b1f4d020473b3b766e3882a485ce5d02ab381c33000000000000000000000000000000000b370903684ede24f3df80e3834ed414a765cdbad98f20c49bef8663a82a468d3911d6bbcdc021e22c252e83a857e55800000000000000000000000000000000100cc8d05f071904753776c6092a38db84c5de751bf93216131a0f9a50bf78a722344a14b3be2a9207568d1f669d208d",
+ "Name": "matter_g2_add_31",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017b32e613cb38b41dcdf3c8bb9187d731546977fbffd79fa7f66e3d6aaf9e1af6eca2fcdc260c8f90818d7148ba2f4960000000000000000000000000000000007e4d26606a47c874c20e8480a9f5815e5b577bccd783b775d10309eeb3d2102c7a0abc3324679e44362f09e7a4ada67000000000000000000000000000000000cb6f12ac8b49cfa36b957591293c87b21af0a949c55a28a90ab0fce88fb5cb7645e20ab2edd284f0ad1377dd95ac10e0000000000000000000000000000000014c96b5dcbd3150eeaea5c2bc27750cf88b30a91933a3233a4d1d9b357a80cc20d135e43a344e718dff5c79045c31f860000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f0000000000000000000000000000000004c56d3ee9931f7582d7eebeb598d1be208e3b333ab976dc7bb271969fa1d6caf8f467eb7cbee4af5d30e5c66d00a4e2000000000000000000000000000000000de29857dae126c0acbe966da6f50342837ef5dd9994ad929d75814f6f33f77e5b33690945bf6e980031ddd90ebc76ce",
+ "Expected": "0000000000000000000000000000000003c5498b8c2d4765a270254dc927c6edf02acf0759540ddad951ea8c097bddb949ea0bf19942accd615bef21e8572dff0000000000000000000000000000000004c17bb648909bdddab4dd86560cb6b341e96f58c515ce471281f226181bded16b358b56d72e363f9ec491b8a9dcd92c000000000000000000000000000000001828973958204f8ab8cd13f5af5f3529f368a149bfe931a8002b61a61895457fbcb0cc6874631bb55799c884b998d8b9000000000000000000000000000000000f61460bf61bbf3ce38917850bfd3cece1e3955ce29d200c6f8aa89076c70919c02668678edc0bcf94efc9e9ff6a650e",
+ "Name": "matter_g2_add_32",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001ca1141ba9542c56de8991b313c6ae42fcecb6751b0b81b8cb21ed70d5008f7ffe831766b89880a7fa6dfdb09a2cda3000000000000000000000000000000000e6766b17db165bba564ac63ab88d3f8f5eded07a40b48644e60d3223d30458e7dabe404cab8d6f9fe135712ef0b1a43000000000000000000000000000000000dda3e6c87382fa762510e5cac721fd2b654f002f5b9a3767a8c6d651ccc582e80e3f68d6913cda30f9f51ebcfc7c98600000000000000000000000000000000059a7dac5bb6b504f2bd603d486700fe22c14f25254537b2c9079c2b45d36c7ce56854c5699cc7649b533194f51a9045000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000e751ccbd475fe7eda1c62df626c1d37e8ae6853cc9b2109beef3e8c6f26d41a5e4e0a91bbc3371c7ab6ba780b5db41600000000000000000000000000000000184097644c9b44d543ebc0934825610590cc9f8b17ed08e9c06592bf85591d2702b18cf48a70b378926057e541eb8ac5",
+ "Expected": "0000000000000000000000000000000002c6104b3494fdef86d53f87bea68d313188c0908b935fb3b9f636ccd401c6e9cbd33bfcdd437e1a0150d0e4b9c3a881000000000000000000000000000000000bdc88396f807d1ba8d4d6e284d008b5e40445ce32c23a0178824fdbb6db3c5aede7687eaa2f12249125cded57052ad2000000000000000000000000000000000c7004365c1d3027997b55bd258dfc61ae07a762666fba2a14aa2ca116673fc03a6f694c069f53cd915fef6d37513101000000000000000000000000000000000ec17688d8f53e2c92502091c859cef4fe9a57ae984cb1e72686bf1f0656b10246293cae4b96214a38dc76cf2709bd59",
+ "Name": "matter_g2_add_33",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000090f4b85961ce97cf7f99c342d3627105d790f611e19721a43d8a0febd67ae393d77a02b999108efb56f0397dac22703000000000000000000000000000000001112f23595d1613c47486eadc37f9b1ac3b3c3973b3fe964d3b67c3996fe2eacd9df5c287b0cea8e9475d146fabcf9e70000000000000000000000000000000018f46f7ba3c9af34c1025c2d460f0be966e68944928dbd55cc7fe00e5def598d80b0e3801e48a74963c974ab4727a52100000000000000000000000000000000096845338d5cd2ac44e097607d6a1a05c241eda1941991ae9edbba965d9029032c46da7218b5b2338e6c58898bc4a820000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000001869606dde1688e5ae9f1c466c5897fce7794f3735234b5af1ad3617f0688529499bbdc9f0b911840a3d99fd9c49150d00000000000000000000000000000000001bfd33df4a6059608ada794e03d7456e78317145eb4d5677c00d482ac4cf470053d33583cf602feb67b6f972c99739",
+ "Expected": "000000000000000000000000000000000a44e6a48ea0a95667f607ee66290cb0094c964baed779bd6656941db28e30a7e9effe49a617be9ab376af4f535cc28f000000000000000000000000000000001933b87310bf5fa60b1abcd13bb7ac3f2ec0a278f6a0a70c953a2905ac1d3bc5a70cf1da885af45d1c7680bb4f7ff74c000000000000000000000000000000000597ce9f1bf7efacdcb0250427d0341e142226aaea060983175ea149912c5c4f3019fe87be6d87d186a8f562fc3059eb00000000000000000000000000000000198b5a891722a237a5e23e3004798c8d3f069af3267152508e283b4549fc5e8388330343f80e606eba30af51c99c7020",
+ "Name": "matter_g2_add_34",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aafe45ea7cb8b450a51263eebc28c1ded662972bee512e24fddaf64f43b74b66032523b3b104a4e9f6b62394436c6710000000000000000000000000000000015cb27e1fedfba2d1679f78a388f90b22bbf3e7d090f0ba972fa8e72f6e31c446f628fff929953712ef6e425d16eba5c000000000000000000000000000000000df9931893cae713042bf722db6ce394b6f346587278a154c271d8511e690417eb6dc47efbcebb7c2fb9e77f1de9fde800000000000000000000000000000000106ffa395ef170c99bb5742428ae88fa4fd7a94476985c099e3b700b7403d083281fb71a19640c6bc2321e27bcb33fe20000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa520000000000000000000000000000000002c536dd2f05f4a7eaa33fd884262b22a2ab2a88e7b63cb08ebb67fc0f143da7d6b18dd394c424161f7cf703acdc82f50000000000000000000000000000000002d1d9ff74e20ea9b03c478784f57e7a58a21ca2b1e552319f33305f367f5ae4daf8138505f953db4f86c0ec1d96d5f0",
+ "Expected": "00000000000000000000000000000000047c2ccda315b9c013e87bc9168b3b8dd6d463403f1cefd824fa9f93a99f4c4f98fac5f97e4237f76b1ec91042f99bd600000000000000000000000000000000036861fd0a69cbc851741475905441b51af12c5b2aaee6ce9a27a01a43db810be9c7d6fa401406e98e327703404b83a5000000000000000000000000000000000310cbdf53f6cf8d87e2d178869bee4359a8dd666986d869761a79963680a33ea3ecefd40a1e558acae5ded2ca04447300000000000000000000000000000000108bbb28c73ed7e76a51a78e4d15a2c88c25e05c7127ae89d4347cda00be231b5e70e0b0562caddd4a7083efa4516722",
+ "Name": "matter_g2_add_35",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010b1f8b1c492a56936da905b8738affba6bd29ae5fffd40ba6b31325181d3b489a81b23dcb69f6e71bd29bfb388e5a8f00000000000000000000000000000000116a115303b4774da59844e457844232d088062d920db67b2a8450a194be7e5340ebd4d106454fd9a03c8f50dbb1e119000000000000000000000000000000000eb521edd61b38006cffc43ab72d395d669dec196846fa4d6d43521da6c2fc3bf0994ce7556a3cffec7751b3bc5703ff00000000000000000000000000000000073cea36eccaa1c78deefb6029903c2b6598301bdefa9759719c3b590fcc5a6a4d3d4d19f552b33f4a3126a6e6a84486000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec350000000000000000000000000000000018db123e05404eea8707f9356f417c3966312b9e41765a6fd8449879ddc4c9850c38434481b235a5bc35db1b8ee86d43000000000000000000000000000000000b4162715717e9065a3849a9294cfe39b351e57ab5a6790f3e725ad9fbf0e4b9d6a3554e872af9c37df33bb896dada5c",
+ "Expected": "00000000000000000000000000000000137d23ed3fa0d7e5928af8d1f4bdfdef08e0b4c0f3bf6f51ed28960ce9805eb8fb254233bb18cbfecbadba95e112fdb80000000000000000000000000000000018615147d7a8cce1dfed6de25cf2fb52f54a243bed4913e20e66673f47ecddad9c5e4ff9653f522180de4b90ddb3ad17000000000000000000000000000000001521f12116b13f785b5211aaf438aa6668bbfa318cf0ed6d91aae963f6f00d32cc5f25d3a02bd902ccc25f847ee2db830000000000000000000000000000000014263b23396f4facdacf13c79864157823db724350bc640abf8fb6d62663cec1069eef9db56817660510e2417b51c616",
+ "Name": "matter_g2_add_36",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e3925fa085db73c1e67b29ae90f8773f83be5ec684402e8e2360ffee8a8368911e584843e42b0d470de78591df6ea6300000000000000000000000000000000075c7efdeeb16609b4a47ea442af4d75238fb7534fd96cb236a7886809d6adc2b62c8ff72bdb041bc51c1a71b68219e300000000000000000000000000000000088b4eb0dd185e51b737d797334590e982b7b0a5f109fc7d0524b2465c2c0457964eba5a6d2d4d99fb628f21f15a776c000000000000000000000000000000000fc79f6b38f3356972669290eeadcd992a22bc1191606b663a1e148aa58db3938f0fc65e536bc5811c50d9c7f03d3e370000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000f6adad0a3bab3610165be2fadb1b020f25488a0af3d418b7d7cf1165812e17aefcbc23308ebcd31d22ba4ca5773dd87000000000000000000000000000000001657ff792e3d89d5d35767bd0cc788411b0420665a5e0704f4d2399b9d9a5ad3c027ee030fdf495e5a6e2a4c69d05712",
+ "Expected": "000000000000000000000000000000000038f9df6c14f84b8ef8045010c8973e5c2f8d2e37268f6a674298de7b15cae82361ebbfaa00ea1cb2653c5d00886b45000000000000000000000000000000001376f7e2d5621aa9d6f7ce45ed11de7e0e1095ebeea976f78eb83189c6852ee199840c14059c233bc3d40efbeeb5eb36000000000000000000000000000000000c7b0e53adf4f0fc5172f903e3fc479539348241edc3e277f30ae6b4fc419aadcfb73a8f8a09a1ae1dd885a6250de0040000000000000000000000000000000007a00b57ecc8b056436ecacd7e0fd346b906b15042e9a700f54f8c3b1d251c566e0c55bd34f7a9e30f1566b7f2ab16dd",
+ "Name": "matter_g2_add_37",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b87c47605fc060a8e3677e84ce9d14b9309360a13c80d040c625fbf0108f829300cc1fca409a0f9c96311cd4a9a21e60000000000000000000000000000000014c4088f1e7935cf6a1d2475b84497ce6a250ee2c0c991fe51a2f2836388a354824b02d9cf215328dfce3f546713e21100000000000000000000000000000000120e59be3ecf35674eac6cdc559599b273f13f28a529770fa156f8e519734c451eefb35023639f32049cd19ea0d945a3000000000000000000000000000000000f97755b62a8cb8f861ea02c77819f0b58181aecf612d92180ba9b475f0b4888b922c57f6a1c619dd5514620a1cfd9e2000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c0000000000000000000000000000000004cb55008ccb5b2b8ece69fac7283f5a9ef9e622e2a0e42bed5bdd77faa550882643afc1759b1a327c4f2277e13a3d4f000000000000000000000000000000001690dee40c6c824dc2588fc47dbf93f68ac250b9357e1112db72ded905ed7b101b5f877bdc42d56afb5b6202403a91c4",
+ "Expected": "0000000000000000000000000000000012662e19e41bfacc0c792f5183596bc7f1986f9bea72c626e187d72111b6ef3f36f5afeeb640cfda99b7044c0d0b846900000000000000000000000000000000050ba08e1b9fe95dc67e6ee1ce60664b291c80fdb59729cdea75dfd18f22fb88f837b439fd119c46c996787d3008194b0000000000000000000000000000000004ea0f488fece967675abdd3c42f8fec25b547cfc45d42fba14bbc55ad7e1a75296a679113d0671cef0aec0c2165f4a0000000000000000000000000000000000f617f51800b09150a7560505079c785ab45cea4705992fc0325edaf4ceb30e1f0bec35a31898db5f810685e55634076",
+ "Name": "matter_g2_add_38",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005860cfb6be6720118623d2d8ba05e686df22744b948421dd3cc1b1691e00d9b5d00d00195b4acf7a7b043f764f3f1c70000000000000000000000000000000012632a3313dd611e8d969bddd556c2d79ff387603462ac78ded3a842981697bdac34ee6f1f4744ed2ff16100874ac24000000000000000000000000000000000112b94c317586e343acadeca611c485c3ea172bc10dd39158c1e678007130062a921b53826d7be6286963ff822f1066c00000000000000000000000000000000040de8c0dadd2a6c2a7ea0fa43e1a5f2f5a6be3fcb0de6875d8cef1ee2daad87125d12f6869c4dd3d931b296f1df2fb300000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000017078538092ace26cc88b94360871fc9a6bb9992172158ef3a16467919955083accf8d55d48c7ec462a743dbbca7b448000000000000000000000000000000000289b703157a02fc1d687a5aa595495be8bbb3eb0d70554728255a44b7820e0ee82d984d5493c800f1d9d8ca0c9381dc",
+ "Expected": "0000000000000000000000000000000019c774e968049bde2188e844c3413203bfe2c4355edc8cbc2cf6f977c34c0a42a206194e6eecba3c97b24558048f3aa700000000000000000000000000000000081ccf6f111575a946341759b9faa13f3608998fbf4ea3b547804737e30fc7e33495caaf2aa328b19bd48315c5c7f9e2000000000000000000000000000000000a4098536041cfb808176c7cd8e980eda613a2b390e8d63d607caaac26db02fccad6d87412b90cb4b3e186bf9ccd31be000000000000000000000000000000000d3c784c6587b9f786c06099a62aa639f40535b512ac2440912f04dfcd1cb5851b7378f381fcdf02d4e58312eb7e442f",
+ "Name": "matter_g2_add_39",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006fcd2c4fe848e9462ba1112baad39031c210952adbdd06293a622ffe2d1c6e4fcc8773ec8913717018b97bcb9a554fd00000000000000000000000000000000130a97442f3273b7b35464545e7351faf71ead9b8996c63889a45945ed82bba29bff5014776c6185219a5234d8475c92000000000000000000000000000000000491d571bac5487b866022a0714be11b38bfb296233845cc434a50be1d35f516b8c6b046fe3d0a8f4f95ac20eddea01b0000000000000000000000000000000017e34b04e6fdf152c848f2432b7bd84b3dba3915f06eb77efb8035750aca9d89e92e1d1bc4871105c440d639e8d8b05500000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b600000000000000000000000000000000048b3e4ba3e2d1e0dbf5955101cf038dc22e87b0855a57b631ef119d1bd19d56c38a1d72376284c8598e866b6dba37530000000000000000000000000000000007c0b98cda33be53cf4ef29d0500ff5e7a3c2df6f83dfc1c36211d7f9c696b77dfa6571169cf7935d2fb5a6463cceac6",
+ "Expected": "0000000000000000000000000000000016fc7c743c5ba747640a6494fb3c30caad5a1e9719a1994d0ca73bd1645fec118a2887acc8876d105102241c10274cd300000000000000000000000000000000058a42a0095a7388fba7ce71dbef4ecfd2018c3fcdde14afd2be26588de4689d8de757e1e3ff22645fb8c17aa60265850000000000000000000000000000000010bb622f649e346834b95e82f93ae83c71c0a65df7842c4ba88df7f6eccb0217ca9377167a6d14777e0474c24821f8d70000000000000000000000000000000010c180c685ea3d0146eb82c007fec3efd129880f18f838f1cd2f80181f5a4884d6b5cc8247430fb0c1701a57f9d1d485",
+ "Name": "matter_g2_add_40",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f1b8df4e8fdfe32eaf227f5af9f2befc85073468f10b81d32d0e126fe2b0cc8e8adb8afcac73213b6ed95e8e843b97c00000000000000000000000000000000004e3fb435ae0fb2d8bd091f250aefe5922b353a64e16abd75627737f3bc56639f8b40652cae69c73ff1969925b0afdf000000000000000000000000000000001003aed7cfb00efce49d6b1a8eba27df87479a4d37bd7fda6121549483b669a1a761204b0dd28262bf27e5c8e180540f00000000000000000000000000000000114fbca7caf782b3296d0b26b4c362bf50acaecb8bc5726b2c99f904ec3d092d5d40991d0d30c8e79fddaa45f04a75d3000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba000000000000000000000000000000001172684b21c4dfe02a55e13b57bbf105c954daec849d4c6df5276b02872c004fdf09d24f4eef366bc82eb72fe91bf70d000000000000000000000000000000001151aeb9441c5a8fabe80867b5c791420645241eae1400bbcc064d75bedd39de2ef585138fe9f65725efa1b1e5888d03",
+ "Expected": "0000000000000000000000000000000019419b635c3742cecffee02ee7e2b1f18ee9ff15e647ca0abc4398ddc421ae7e0444e3c1ec377def9e832d8e64fd40e2000000000000000000000000000000000d9b4abfdaf3b4c7bf00fa07579befa10a3418d8fa0f3a9c31e59ae48b0de50fc8e6d583aaa4d0fe6048bdd1a9c60eb60000000000000000000000000000000003c96d57034ec97c4abef1c2c81f4d4b0f4b6eb1e9dc5464bcab28572555b9b874df80325941501c3766fd7e06bfe7360000000000000000000000000000000002dbb3d72385b562ddcb9a80400ab3770f00d22b880cce2fce1641042b9da669b22b2fbc97617648c25ab644e661e2fe",
+ "Name": "matter_g2_add_41",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017faf481fd4cb0c373d21d7caad40e93d9a86e62d26136892fbcc6f6e48205543aff00c45e82fdd1d3e0e733de91e7000000000000000000000000000000000012e14fcb9ad4d9d15347cf004745ed4bd92097eeeb41c4cbcb728a234616363589d8f5ad4cbb61d31a8aa27627723c7e000000000000000000000000000000001513dad1ff27e053902e779e35d04cab648939317830144ea775c435a4b55e13fa2fef03a1256abf5c187487c25a774f00000000000000000000000000000000139da29de8587c7d0ca9237c37a116387385e9cea453b9e2003a37ede7aa0a3f4c1df55255897f5975b662be33622dbc00000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e000000000000000000000000000000001995b9d697bded656236430e78726f0f6ef963db9a5a24d455c12db38aeab0f8629e5dc2d04920156f2a057d69613096000000000000000000000000000000001119b13caf82c18fadcb65c9c166914bfd822534bb9def3feae6c9e572c97c84e97fab3b345cf59358436a404075493d",
+ "Expected": "000000000000000000000000000000000d32b00154a5fe75c576c098419744ac36b911ee800f94bd598ff9b6adcaa39c836bc158c5d6af72c9e715a242d0fe710000000000000000000000000000000006e057c13885d6c05f5d92061fdc4d532f10d31d472c371e71367fef7c5fdd3741e665321d1119b895660fba3770431b000000000000000000000000000000000bfe695c3364e15479741e974f838649e789a76d073e552aaa60981fbc6d185eb7b297fd59e51535965214a02f5cd67e0000000000000000000000000000000014f0a27412248e3163e5f82fed02a25d953b336b0201692f08a3e8e9a9d223b736c70c1a39826a0888fb02a314e223fd",
+ "Name": "matter_g2_add_42",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c118b147ee3489f30c6ecc0256a314ab674110588e8b69ca6d265fc270c3e5b767817f861140cca5d7c6be4012d1ffe0000000000000000000000000000000014800790654726959fd876b035bade0da744fb36ee5b304f228663a531345120267c55ac19fd66022752010e5bea7cb30000000000000000000000000000000000193ab7ac2f151750356b6e178557460c9c2672b1736d19a20e3fa28082479ca60021aa68edf2524f1aa826ee70b65a0000000000000000000000000000000015cee9ac55ab45abbc57d0ea6ec9ee49f6c59f6b94f99589dbc08ee877d3a261ad77f5473fedd72ed7206647eeafb6ea0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000001bca57e985906695e14882f2aaeef75de5009e8717eb59962e978aa11e9d0a4d9a9e203df774cb1e993b1c6ecd6048c000000000000000000000000000000000695b11cc32740c91546eb7d554ca8b1f3afc942ad977345031be8b94b78b57a87ab049ca2d3676e039efccbf24d0c47",
+ "Expected": "000000000000000000000000000000001566022247ce012b7de92c8495876b4de91c36448f4f7e00f6e154185d38a735e701dda989ae9e37d332a5e60af5d06b00000000000000000000000000000000065aa42560df7990df2098827a55ceaabf3ec592c53d2f20e5dddc1481ee64381accbc8e58601428d33589b3af78a4b70000000000000000000000000000000002d9b0cf8bfd1adf76bca80ca351a4340f02434090518807e07ed76440497042f13a0cd7a9c30086872d6f145808fb290000000000000000000000000000000015daaa131431e3e78a6221091640811fcf88c835ac975a041a7ab50bc1d06b80e6a3c9ae77d2390fd14cc9bb009b47cc",
+ "Name": "matter_g2_add_43",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ef203fab794a0ef29eb2ebf00076134e5932e27c99d6d445695b9df2afe7563602e318caf5d44724a21790ca0ab0d180000000000000000000000000000000013b9b1b1d3e98b61b0f1a0ef3a1a4ceed57b6c01849a4ad66a86332b3d27022cfccadd3567e6709d2de5b23b23dba43f000000000000000000000000000000000c1fbace49684f4be32ef6178ac3a95ea3f50b11494340fb73dc5391d50bcacafb3bf0f2631fea9c4ec47327d644489500000000000000000000000000000000040f82812855aa3e3aaba826d5810c1049cf44e86e44e23cc6da437971b529d2f2676c73e1fb9da52640c981fbd710be000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb8776600000000000000000000000000000000135b3db43511dbd8b3bd5a91880d6da1a2bd1383000e0d6f0a521bf88a5836a3b5f7cb9c0c02aa861a1c2d339f3c11f20000000000000000000000000000000000e1337271bd3302a1cab762161ccfbf2a18b7800e6efe58cf897d4adbfe4cb3bf14f4b59307fffc548179bda70c18bf",
+ "Expected": "000000000000000000000000000000001290bff629c93d992ad2cc709317c48980b0e56a32fe239258c7aec75e4523e0bc0b81319e100d10568a44847869a8d000000000000000000000000000000000055d9098e08eabdf2b883df35efebec9f6afb16d651ebaca1067e2129146268664ec51c8a4f28f13a250f3e9883053780000000000000000000000000000000002424dab6f0d18ea8bdded2a72bcf87c13307d27d53e8ec35e91eeab97fcf3398135fd436c530c609fd47a3508472bad000000000000000000000000000000000b25d0db1e28b98d4f9d3c77c0b71489c51186105d93be7fc2cf8c72b8abd8959340114635e705e698b0f257855ea4bc",
+ "Name": "matter_g2_add_44",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000060d7a718dd02b147c265f71eb136d1f31781b12a41866b4f86d7374b93dd10058c192cc0fba928373b1526e1a5d7d7f000000000000000000000000000000000cf29275373c0573ef22bf87919faf5444847203c7dc6d2e18986152cc294be04a5b1a4b0536797158113a15276c4fc6000000000000000000000000000000001016d5b9d4d200d7b4b7cc3836b85d6697fe14db350badba9978c7b56983dd1a7e572640ee0372b0a4e2079ff4c1abf2000000000000000000000000000000000f2768d104d895473ddf8c6b3cd0e7c22458d0037eca6365c766879a07c95037ee0de00d32c974d767080935abbe0be100000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df70000000000000000000000000000000012c5b00376a1dd31378ec44f2dc8e321e17185d903cfc5c15345a01c33f2f151b21b938d31816550594a7a1e7216c5b00000000000000000000000000000000013d79f825c44775c68e90932d0496a5cae53f04a1edb19f8abeb5948a3dd325dfec4a8b6f58c7fbca9cf3c09b909d8b2",
+ "Expected": "000000000000000000000000000000000cb2998b4e634bc83b5585b0683b7b561f260eefb826719bdc3c95e8ae51f8f7b442d75d69e0f9228dacde2ce80ef4e60000000000000000000000000000000014d30d1c02122143868ea01b454a4f33432d875f8ba66e6bb1e02fc161bb5f9298e673339a9183a15759f8b94b519cad000000000000000000000000000000001068bf3c768e8c9e9058805050394ea820b5f60bea6d271f8e1fb665d3b7931ab0cc03dff4cbd24577b2c254a956e8200000000000000000000000000000000008b7f4148bd1f4926d2a84497b60a48701057ea08855bb9a2f838d2464e66360a59d058d9072f1416023cc72045af558",
+ "Name": "matter_g2_add_45",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017b9ca4349fecaa43ce911c0b256680edb8a0906ef5460fc4d2004579336df1e19560fe960a7a7cd74bb6e8272e08960000000000000000000000000000000000d5b96dae738db59cc67a51c61bec6deaeefaaa51e3259243fa4b142ef59676231229ae386ce699fbe18c4c00bf9d49400000000000000000000000000000000111b79f4b68dad16550a13334d09dc38336a75a5da23a17b5064e2d591aa3dab4c2e982a9f730a7633070504663a24610000000000000000000000000000000018f6d3616a7eaf17c805a88c9710039644d01b61aefebf76717ddcda6f4bb34aa15702de1e92bdb27b27f3409638da900000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c743900000000000000000000000000000000101e143b838c8a3f5f80fb1412081091b875230f1e2f9cf374d4bcd595392f6daa9552dbb6d5834e27b1b3dafe061ed300000000000000000000000000000000072463400b3e875395a1cdd31d73d51396e34347cd86d9f6f43f42253b3cdb24b89ed7434b1522af95ba1ee2d29ed1bb",
+ "Expected": "000000000000000000000000000000000a7843a1d67360b8a6976aeda2e4e98f1ea229a4d84b947dcf5ed8215173d5cf783920a7714f5b048778df30f01a0bed00000000000000000000000000000000035663ceafda9e5bfe934cff725b36b258f12afe749f907a560a06da4abf8380853f8de31adf14d62cdb310d8740e29b000000000000000000000000000000000f210d576aa5d4cdf5aefd8e55be099c422debc217ddf0151b8801f7d16456c97d1e134b40e6d71d296ee2518e50af9d000000000000000000000000000000000219efb35c68540c6bb0ef224e68dae6f7d48425c2908440072f5f63eec3c8e750b559c73e33464d0b5cdabb50fc4d3d",
+ "Name": "matter_g2_add_46",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aeb5c087644595d0912879f61959d2731ff55260c682ed2bc5fc55c13964ef7c1f70aeb55876d2264d558c31371ca69000000000000000000000000000000000e173848f4570525b03a2b2c86f4dcdb8b28dd6d18c1354cad31028eb1b8b44432c2346edaace093e3954c7fa6d338a4000000000000000000000000000000001949b0902506d111ef6318edcd7a58ca4d69f5804a028aee73c3786cb2db168c6a73b77194f7a021ae6ae43ac78ade340000000000000000000000000000000017c5e28ba6103d97e2f3d3611c0c78f06406e0da8a49ae29c7d460b52f75136920784cd500aa3593858b877697eb8424000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000eb731bc99cdadf7f2280385c7e17d72d34bcbdbdc725d5bc94e841036115e8cb95df08084221696f9be479821fbdd7400000000000000000000000000000000143ba7d3f66445249d9a81a6949f24ff40e7c4d270fa044a8b80200a4369b07806c5497a0ef9e9dbb87b9e63694623ee",
+ "Expected": "000000000000000000000000000000000ce704e650605f747cbc0bc76e82de8569ba7b3d897eac2bf5f79aba17ef4c989731e959c0bc0b7988000a9b0aef39430000000000000000000000000000000003cd3f3d978d6c85d98812ea0e3d21149bf4151ad1bef966ced124ad62dc7cde55f16e8d08bb1ad54d3a23bb73795d8f0000000000000000000000000000000019d37a20fcf6244c2898b271535e3b8f279eaac5d8fb1ba142096da383488eba28a21d038d7a9d3f9e8a008d6d3ee1d20000000000000000000000000000000001ba9c1720a4ef07ec752efa1ddb629505b3586af415c916fb0ed2953cd8943d9343268f438db860f0bced3e690a66b0",
+ "Name": "matter_g2_add_47",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b9900000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c70000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000068edef3169c58920509ed4e7069229bd8038a45d2ce5773451cc18b396d2838c9539ecb52298a27eebd714afacb907c0000000000000000000000000000000004c5346765a62f2d2e700aadccf747acb3322c250435ce2cf358c08f1e286427cabace052327c4b30135c8482c5c0eb9",
+ "Expected": "00000000000000000000000000000000160d8b4bef36fc3d09af09dcc8357067c22e421f3811deea66faec42a2f00fa4aceca8725cf99062613126a9fd7bf7210000000000000000000000000000000004e8691a42c8f3ce0e7c0470446689e9d2b3cf57d55fad7387d624857f977cb9c6864c87bb4b6a2c17538478ac5fb5960000000000000000000000000000000015e20f6baef033efbd38081d5a10eeb3c67d89ebe5cd652110b778313c9e86cffb45231616d5b67e9ec8b7be15980aa9000000000000000000000000000000000af75dc221050256015fecc2bd8113b42afc9c624e5d28d7ff8312af499e34a603d66a4304f263729b440b6266538316",
+ "Name": "matter_g2_add_48",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f20a07526a082e88630a0256d134a8a5e8ada07b1cead39ee838dcbb30904e9016107fcbdf1f8ba182308dbe0b043d20000000000000000000000000000000014fb7732f67abf60c03ac902577532d0acadb5f3db0d6397a42ba693526ad74f2c61a0195bdc9704aaaf12e65aa6d88b000000000000000000000000000000000018cec4fb81c85d304588d11f8b9c51f5a053df11463e5812a1b2e6c7144522ba36bb91adf219892d0007cee470032e000000000000000000000000000000000b8e52d958a12a9037e8be9bc0d5045cade2d6ea05c6e68462b3a30b5d4ea34e5fbad173761e4e216b2e6958c8983b28000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000f6fdc4e5dceb555c9eb4c912fedbfb3cb1b842345f73ded02cfaf8d397c4378809721094aa4a4113a368e0787effeb500000000000000000000000000000000143ac06258c579c11c05569669a2a10babc63ecc86f85c91791d8ea48af700a2067c5f13d2700b8d5cf59bcca8fbf7c6",
+ "Expected": "0000000000000000000000000000000013edd8f016f6af49e9bc461ca14c438a32eaa3d1270a5acec99a666aba3f0a7e7eccea81720971cf4432bfa94cd18392000000000000000000000000000000000dbea5617e44c82da828844a5a4a1426d43422fd0158204a99f53cf9821f82f0bb0130a2123297a6941f695e172d9c5e0000000000000000000000000000000005f65a445e9f2d57dff2b210209f9faeb1c8b446454de4724d990aab20bd68362dd7ceb5b95de361c129855abba83f7e000000000000000000000000000000001219ecae79d62d3039e642369353993b1ece049331f06be256f06b01a1c3b0c617221c8d8f0bf4b6a0abe1191a3ee8e2",
+ "Name": "matter_g2_add_49",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001468cb35a60898ed129f30c261b8431df6a154c250ec16d85a22f8717593b2c21853d123da86d977a7938c5ed74ef23500000000000000000000000000000000011f4e28e31b5f9e6877192a5e632d8c1ed7ca0c42e6e9902ca68f1c2de0f648c6064436012c5c7b14bb8d1078e02f2c000000000000000000000000000000000b25114b2697ca7eb1e6effdd1054893a188fd382d387ec098f846c1137a9b9baad01653b963a0b0bf3cb50c3ce3563d000000000000000000000000000000000c1d241cb03e642c1752b1e1886472477c19a2801ec032dc220c3243952f882094119bb92b621b654b766bc900d2d4f7000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc500000000000000000000000000000000192f3e8ae2588f9223de77f5e872115f1edec96d6a0f403a47879410c2562e79853c9a706e423b83fbf3154234edb6f80000000000000000000000000000000015084258d58fd1a07bbdb2e90df5a56ae15a787037eff4fe55f660e45f04820c6fc8982303b5e82074cf0cdcbde61307",
+ "Expected": "00000000000000000000000000000000158da32df45fe3e9102010bfd7faf3fde936bb8e52f68262ef479ee825a0d7169ff753aa042883a5403103a9bdafd2be000000000000000000000000000000001800a5776a47f52d2af08144364a6cd7442a0e2fc214a2d8d285a29bb7bd3a0293e89f0a1856223a527100d0abf12899000000000000000000000000000000000a6079d18ff3367c47fa61a57a967b782f3529bee93f452ecebd4f5c404b3e1769c100da9b8aee4258b5191ae1dad9a90000000000000000000000000000000011d3188a927e8f13aecf7f8637be6ddbbce309393a94fef77923c286244f8531d3e137e031d8c1af829891425afd53a3",
+ "Name": "matter_g2_add_50",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c80d4474390fa791ea5f2f16b41506d8ae13ee0993c8d31a07712687298ee7978a724999500c42400d2f788a5a36067000000000000000000000000000000000592705cc5a8875750a4e6ceb42aa3bef5593eda9e8212702a2e08ea70277a2a66526bc5237be33c8449301544da35e60000000000000000000000000000000000facabfbd15284c6433f17b0e6035d4fdd84d3ad2dd30a27d52809652ff6e7a684d7724697919100567ad0c3e1a26320000000000000000000000000000000006a0fc4e2af69ce15a356656f5d182a2cf213d76a6047a05a1a3375909d245f5316b91333d2141c0817438f0d87bb52d000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f000000000000000000000000000000000477b55bd7fff14e0d1807bfc21edb9481be01c12abb1460d78b1aafe42953730167e32e694c2ddfb0d442e8cea57d460000000000000000000000000000000004b884c6ea36f189dbc3c0e9cf88f08baf5d868579998f63b752e61fcce3cf2c901bb9b51959d3597c4ef53cff41fc26",
+ "Expected": "0000000000000000000000000000000019294d87be784f0f8fa29de80d45a697bcb694b32f3f6d7641d4b08d8a7ebdad0ef78ba5ccafd6b7f240e1cbde019c51000000000000000000000000000000000645f7851644e1e7e255d0b3dca769b987ec3ff2c9eda42cab65dc39be2f9858c31f307d59f6a2caf9dd932d873d2b08000000000000000000000000000000000e8e93f39ce05a11d40f3b52262980c79ecc52939dd02b94df3e5034a57061d040b0c8894189f4626f37bee485712dd00000000000000000000000000000000001e0b7c9c3d7456b2c0ad842083e9ce2a00da91cb1aaba371ff4b9370f0f2c08f4b53b8e5a3030c99b2957cbe5f9e967",
+ "Name": "matter_g2_add_51",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003f629618e1fc3018bb836301ccdc59022f0a25cc9c5de6e4c31fa08feea525c83256235e4ec8364e77e5df478f5f62c000000000000000000000000000000001120d6af221ba6f4351bbee4c2c664a769adb17872646df2c408f70c99ea991ffced4eab50fa98be1bb9426915f125930000000000000000000000000000000015cd16b028ce3d58b10aeb84b783475d894ab3f0cfdf7104ebb4f3417a038107128f07518dce548271061cb8c97e88af0000000000000000000000000000000018379875b68bc26107f9a068e5034f29dc2ae7e8830f8e9ecddc53fe7991206646cda33d37b31a47a977b46be58d761800000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac800000000000000000000000000000000183b7b917aaaa94f0ea9959273ed4701102346be2a9d72531bd18fef908ecb0579a6ac10ed42a91f1147fc3a05b2e81900000000000000000000000000000000070983b1582a97d9797782e4f960a298aaa8ec509720495acdbf176d8ecb9ec9e041c2b5ed6b7dfb46fdeaae3fb34150",
+ "Expected": "00000000000000000000000000000000040f355021ba50c9a3b2b4267668ac8d76dd88991be984ab5bab9c96faed6dcc6e8eac78ed29cd6f7d687dd55cc5d5b70000000000000000000000000000000017853cf0a39332e3c7d75b08b2940d693ac7cfdac46719787c22b55a2ab1036d6f95b68075f1c585942843aa486f17bf0000000000000000000000000000000008696feb333417a7262e8976d1546b6d0a9d5970095485b18efcdee8993b16f42e6dbfdd08d30c45fe4af6a5e203de07000000000000000000000000000000000ec26926720243124ca505c0e04923f3cf5eeca2abfdaf4388960b87c6c1713fc54cdd1c825e2ea359cc67b3bebfa2f9",
+ "Name": "matter_g2_add_52",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000036570783711b381830e35878fbeb187b84884a9a0e88c38e84124515b470e6ac18157e1499026b27f4f731a961eaf330000000000000000000000000000000008382838c18d56c046a8db495babf8d14c915622d7917ebe10cf7da7ecb65f174cddb9e70d0262ada961b396c5511b410000000000000000000000000000000015f63ce982aa581dad5c71fc79251b7f6336c4e78a4a0f4cb6f87167cabd31cbec987d7af4f11dc6d693a0b0774864130000000000000000000000000000000015c001372fe0530a3f50fb8b30e75ff4b264d673e0448211d082c7a9018f583b4d01790019874596c59c68768cfa3e69000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b0000000000000000000000000000000010f7bf9f6711ba723bb71a004a90109ee22be6643d56d410da18103ef44a1b3d50f10c4b94222c7f05fd3c28acbdc8ee00000000000000000000000000000000007af41f09e6d0adcb1935d6a93ea1f6156fa0157a63f265a3a7ceffe82f6635b8511e7e8f21e8f3be7a73513ff597b1",
+ "Expected": "000000000000000000000000000000000f3dd56c416db1c06fd27e18fb852c9e1662fed42005e253230a7a8f7c3e0b8ce637666e1d20952c219cd2068d6865f1000000000000000000000000000000000aff045afcbefcdcb5255805a86e8af3de881e5482188c487d15ad1b799cf551c1d48c7665028b05ceb2e82e15ea4ae5000000000000000000000000000000000e0e6ed04926aed1f8c6a4e13227bf2a99d9d6d349a9c86214373be693db702a0011b4423defdb7d842bcb6f722c70b100000000000000000000000000000000148b1af285c65b12eef498f1c9e57a673e7a3803088c56e32aaae13dad3977dda8d3e27809094f8d8ed607239610a1a6",
+ "Name": "matter_g2_add_53",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000074d78cdd35ea17a3013e2301fe9f80f2d20d270a25fdead37eed7697a52d152612543781763e6035fa5452ab12cce25000000000000000000000000000000000e572236e1c203a1c0f99e6ec978458c1a143a6a650eee27cfbe406bb2858fe5f30222f468d119703c2f442bc644ff3000000000000000000000000000000000125384343fe132e16a9fc15efe1b3a9e47289e0afc4b44d492e33a6216edbc96d66c1ca66944a8296e7695f27f414c5b00000000000000000000000000000000084c2cbf0d7c932c3098ded7c70d4411eed882feb0f79e0f7f1c31f5fccb6d53fb57de179c3ba5754bc5e532c3784df10000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a0000000000000000000000000000000003a6cc74cc398f38d535b4341faa37c968daf2009c3f05ace1f938b33bbe4002d81d18d30c2c856b21afe7a22b83c37a000000000000000000000000000000000452d1b2da6392f9df1bfd35e4575c565333703b2f83f56e0a88a0c8195968c5321296b07f6750584e23597304a5472e",
+ "Expected": "000000000000000000000000000000001220b3da7e7d03823458bcdcee82db56957e5aec335e9b543ebb0f3cf4fe3cf6ecacb6198c886b9abbdaa42f528b4963000000000000000000000000000000000138233b166547e9e9ee9d11048e2d2579b2b111af5cab372d36159c4c45e28d836d733a1265e8833da64f461c0a32cd00000000000000000000000000000000005f860a0c72034f1a928501d9f549e5c2a9dc72670272fbf35a0b301025c0fc751d55ef6fc2c5bf7ff42df7693f3dca0000000000000000000000000000000012c73105adf97bc0dfec1f56153c57c6fdb9d68341f4397b72f5b6c667873ff7ed5cc841451b391e33290cec256395c7",
+ "Name": "matter_g2_add_54",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004d46066439c3ac559cce863c58316883651023990180470d2efd06e443a7caf3a514b54f15ce6e850d32779215bcf4a0000000000000000000000000000000019ce904b6c9c3de59f7d5017f60f1978d60c564f94a0f1964c24c876d1139a7ffbeb6d0d4884bbfaf5f2f189af6904a50000000000000000000000000000000015f1989719e69be95f25dda9358fb98aae2819e0deb7e2d291e2c01e85ba26a9da421896c6b6e2ed20f609b533154694000000000000000000000000000000000b287cfcf1dd7c6d735c1358dff15393ddd6c82e7a33c5d8005c4234cdf823c76a4725fd74cad74b3ec51df67f09af0f0000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf780000000000000000000000000000000007a9cf48dbe005c5c59b2c731cf4117e5fadc9cb2cd8f486f1ed58b2909092ee8f36d88b8f719db94715641b418ab4240000000000000000000000000000000004ba40d4766b91bf8da1cc2526f62791a1b5f6fc24ffc54b522dd30cde2d29a6a6f81e8429d518710843d43705f3b4e6",
+ "Expected": "00000000000000000000000000000000014933a0923416428b5fe5be7120bf399ab62ca091b07d03da3fd2ff080b9c411c3cda3bfef40c8450ae31c412dc5feb000000000000000000000000000000000214229a73780d4f260364649e9eb2ed751ad3f687a832a3738ca2cc81a3acf12757651e88c4bcd79239bc0b0c40e5a6000000000000000000000000000000000548f20fa375e578084e085ee71df5f8ddaec1db03a1415938d9521b5d9c914b5295835fc07263cdbf49d7802551156a00000000000000000000000000000000063ecd9efe55229a76fc848728e940183c23bf47363cb34c5a49837e6df8a5f0dc29d7108cd10ea08e82ccf017d246d1",
+ "Name": "matter_g2_add_55",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000006b37e2226957d639fcb0bcd6c20b3c7b8372e7347a14b970e01c67c1859fa97c754ce588d0f835ecc053549d963ab4000000000000000000000000000000000c6a5fae8be3a32e3f70a4202a1ab6d97183964b9f7b9a084c49922cd9e0e952b0bb66c5580f0e0c417e079493bcdb4e0000000000000000000000000000000017b6132f11adc0d5d693ae7f3a0f89f5779708083eba23e03b0c9265e4e60624e1fb6940e8ee49d31618fa6389b1b50b0000000000000000000000000000000000a45c5f6df71359648aecb6434bad1619c39f10e279a02b3cc9725d0256bcd126843fc9ed29cbe02a32cbbe79774a330000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c7952820000000000000000000000000000000008ceb842a17953578013ceee519a28ef1b37f73e13564def5ffe08a64dc53aa680784e26138176c89269477ee003d16700000000000000000000000000000000159791b6f2c26ed611ca40bfbd2059c15cfec9d073a84254ad9b509ef786d62d17fdc67ab13092cf0b7b3482866f4c32",
+ "Expected": "0000000000000000000000000000000008a71a08d2c4e2ba3d8774dcb42d3e96c7f72d36fb3b880a4049b078d8257a7a9a51b0b34c093568baf4aa6de70e709d000000000000000000000000000000000daf83b5ad4b91b557982fc4b9b7dbed2998aa39fc4658ba671f5f27b3888dfec7602949cf626c9e6ef21171acb185600000000000000000000000000000000013a7ffca291d9ba8790ca0462c54c147aa22e03a2413b756f27583155932aee65060924e46db321b3fd6f22ff7f54041000000000000000000000000000000000289d7de10285285279aee024e52476fa6fca85550f7af183a161e395d72e1339b629c64127f96bc85858d80e73dcbe1",
+ "Name": "matter_g2_add_56",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ffed009c78ba9af8cd33af7b7697ae4dff863bb92365055baedd2299b7f5b5e8abb84ed434f7223c3e309ca53c08aca0000000000000000000000000000000003b2370c837dd6291818efe7c9af62dd51295c418739ecc509d42c92e2c97d12a9fa582946e176e8153fc9a273140b2f0000000000000000000000000000000001e63438e8b4a0462cfdff64a281ab4a7f48d51b51325817139f8ee683484f8695f1defc0c3efcca81d5fbff06cf9c54000000000000000000000000000000000192fc391cdc1ed6ddbd317f2f366f2ce25ba27b8c0f09c733e7bc0c0697544399a3a4f1186d139a8f6399ffa88e89a6000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf000000000000000000000000000000001272c63693873e1dabe2c2739310f627d3d9b5bcaa615402c3849ffd8dfe72b40fea4a068064655f2c8f46f074e6518d0000000000000000000000000000000000161a8e5e1de10938e5bce241ae73d76173022127822d744b23e656095c28f2f8d142ceb48b72a1dbc36b6143f8af95",
+ "Expected": "000000000000000000000000000000000a4ed8d613cfe4f5dbda1d0c6812d0edee45ffc2667323c3828f8ce4ab55c119e92a82f2c3d06afe3adaa4aaccc18f8d000000000000000000000000000000000fe10c5e185f3f8ba81c93754132d76e05eb3543d8aaa8a2d0c98833ce5fa9e2b84420d6e3412e005cf89d11f5400a510000000000000000000000000000000004ac5f8cc614e3833b3b6dd9eee9ac29501002ba9054554314a4c516bfc8cec870995e811f7892811346574f3c58b2ec000000000000000000000000000000000a6bed54d8ed4ccb09211ae7773c604edc6ce51a05c9acc94e8167026906d387af681fb33a40e72e85cb076e072db7d9",
+ "Name": "matter_g2_add_57",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000002e105e0eaa418d58019a849b89accf665a94ffb0bdf308a11b99b521de7af8ddb150c0e3b2e9c54cf5456b6105bc81000000000000000000000000000000000691a3b3986fbe1c0ea22329364454f37f645d6abe9310e883b9191ce512347e074e18e28b88c2adcc76190a549b80b40000000000000000000000000000000003f3a37a763c8d0d99a3fe36923843a22cb0fa18ced48493b2510fc99afe5b7699bbaa6c2ecdad8aaf72969354f121a1000000000000000000000000000000000f4bbae00205f54eb10c83d928d908fbae342b76050e33c51b6e282e02b3c1f132a4728dee4ea95455c25fdfc112f254000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a220000000000000000000000000000000018a236ea02b1971d6e193a6eb92e1298956679d86864042fb6a0c36dd91c0e385944d779dedd0149fa8a1b3d6a07949d00000000000000000000000000000000048eac7d116b5a7906bce070e2b51ee7c4c493f1415abdb6fd2d35676036d3b741d14b7135419645a6906018e9d3f150",
+ "Expected": "0000000000000000000000000000000004d145ad2575313a922667b897052063139eef8c61dd375eb055c4a5c52cfbed35391a85df915e1eea50d000b9b6bb5700000000000000000000000000000000071cc73c16a234e99faba9b04fafaca1a943f2bdbb68dcae0a1742acfca1f90c5f69464aba42be6c18be31f79ce30791000000000000000000000000000000000bf725a2f4d7d33c66fefeefce13fb5649a68a93fb7086c943a7bd5663b5788a5ceaad7fd2a219ade832dfb3c0022a5a000000000000000000000000000000000fef4a2610610afef43da2161b86b25a8f6e30ed90053d57f5ee0a10effcdd2af769d32ef6843804b2b6590f95eccb4c",
+ "Name": "matter_g2_add_58",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009a3e98fe4a98582ce9f274965f376cb45e8583775dbadf626cb1327c1f8a25b293b97e7f8f31ff72ba7e8e769ff25ef0000000000000000000000000000000018e4785ccb76c4897087c8a4242ddc744c6a0a53a4a844254153c23d6f16d4ddb945252d13f93101613f4eb0b1e2b8320000000000000000000000000000000011b81d344eac04d3471b1edde5e51f31f97bea3396580839fa094db58cf6bee371bbdc045fb60c3ee5c6cd5d3f6d3c4700000000000000000000000000000000073476bc5b1d52ff4ca89c3afc099417f473543fab6e59cf9de8a19705dc4bf2a210b1e6de4dfbde035c312be0c70c5600000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c95384000000000000000000000000000000000003c96c6f20d7ac31ee7ca77d11e8d25ea78cdf13e5f4d317752320e059e19196f14c15b5a18ca712f3a7cc6f09be6d4000000000000000000000000000000000ebd71f61fcddf1652675f577bbaeec26b892dd954965b057ffb431d6e37cc5425a2a42a0059482c2bd75adb2a120b0b",
+ "Expected": "00000000000000000000000000000000151ec7c35a67b878420e198ee7bf359d0668ab61ba1a0bc2e5e57b1b7b18838a015464f9910b659fb7d1e10af2801d86000000000000000000000000000000000511536f34067fe931c6e829e22443eb838f0c938eeef6f839eb322d72e2011dd1c33c504dd044e3cd721065d7075b520000000000000000000000000000000010c486f846242024f9bf40d805c8e33ecf1b44cfaa04455d5584db7ebc32c0d29e8742c61886d4ebae93f22c518ea87300000000000000000000000000000000072e184c836a853fd1153eabb1b645bd35ef72eefde4a52db169acdf2d8d68499398599cb4002994c6f4936de1da75ef",
+ "Name": "matter_g2_add_59",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c414b95b298b9c673001173ba7e5ee3e03926f28068481cfa0b469ab556f8fceba9fd0a815180ae0b82c265fd4c6b7e00000000000000000000000000000000054a242c1cc1a9c710bc23305d09c2d613ee8eb3840b37943bfe83f9c1db456ab4436ad319fcdd8684db129d76c95320000000000000000000000000000000001683711c0c7f02e67374f190eed1ce6559479d6d199f43fb5b0ce7df7774a5cb21c86b3b3498855d9b69c5763acd8c4300000000000000000000000000000000062f87085dfec847af518bd71c078f994b090c3b27c6eaad79772ab58afa43993db52fb08649a32629d61c3db12c87310000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e4000000000000000000000000000000000174ffb89d7715866562d9882acb81ce40758644ca3e0decd546c8f5c349b24fce88214956e7540fac36bcfc105cf34a0000000000000000000000000000000003e06c5f607ccf1e2991828034fcdf91106295e7174b4dca21926169451ee58e737d535af45073e2378206e03c81c421",
+ "Expected": "000000000000000000000000000000000642f215b772d17a3aa45ee3aee607321c02b4f7a7df3884259a25ce78c73e9536d46333fa388e506fdc79c708bfd9de00000000000000000000000000000000145864ce36521fdb641761be541a27bbd3f4797b923a870148bef1d5b4b0d463c0a7c8ef07954dad464510d836105e05000000000000000000000000000000000ca038e667fe68111b583dfaa95f88d3b9e46c0798abccd1476071435067e6c0e2fa81d25db6e1175e60efa1705538b9000000000000000000000000000000000cf1cb1b155e4ea47077c42a1a99c3f11f8b27516a808b5e73498ee12363652bb46eab7e55de93513cc2d6272f26a537",
+ "Name": "matter_g2_add_60",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000083eea9b5b2d5ac5f7ef51ca889a4317322d098a408a741827fb3419eb12a51c07c788c2798cb37635e224e99bbc894c000000000000000000000000000000001312ec00f4b3a4305700b44b3f215779a9a8bfcf5b5d3a7f237a33c5484099ec9bc5c8537fae768e2c0ec62168f383d6000000000000000000000000000000000cf1d5d05d11e1d07074dd34211d0f00eae1df4dc550c55bd2fdafaffa1ad36abd5da30c5d3a5aa2845b1d95a5cb571e0000000000000000000000000000000015223baa9f2ea4b04fdb05b05bf3a94dcabc5e64189aeee39c380de9a34fe6b4253f5795f70bbe51b80e1aec1eab71960000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000b15d92f2301075ab0e3215aa72cf9b130bc8e1bcd9fa36375c4b9d7da430ae3e2b24f417336d8729f44542ee7f561d300000000000000000000000000000000197d90090501e8cdea28eb7963231f1a7b5f716cc3a086acb6e7626600d6544132cac943e8d5cefb5daf0a2f8d400629",
+ "Expected": "00000000000000000000000000000000128c909854a20ccf9e8e396b617b36f233909a5f6c3524c93cc659d22afe0e7058a438a5ee4345bed914288c64802e29000000000000000000000000000000000239fc43718cd27855ee5450cc9be5be5d9bca8188c22601242a1bb4269ca0fe62ad5e12b2c65558cd3dfc89ea31205f000000000000000000000000000000000a0aec9527febbd35bf041a901b0b35e5e0d48a2d6d733bb557d0767798369a7ccf2f1c278710eb764f721821f9aeea300000000000000000000000000000000194931bad52daa16a648ccf1ba9a4768e5e2900fee4f9bf46ae07d1aa605aabbfe96684f5d2233c0b254cb4ad5517775",
+ "Name": "matter_g2_add_61",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011a960cf1978aa2ce1731b857fd91d2f59d4b8d7c6871ef6f4f85aeff549a2f397949d11a4793926fe7be37f3a83d11c0000000000000000000000000000000001954f056834d6e3b16043ef1acd0a47a353300257446e9a1db7e58bd0d7c4bc9ceb3db51ae01cfed9de99621e96934c0000000000000000000000000000000002e2fe460e71b65595ed93a0010e5ccd1a2c16fc4e0d345e7226c947f29720d2f3f54282f79cec086d3fb1999b9629b300000000000000000000000000000000060dd8a7ccb613f1521168a8a322aef9f84d9708a893f704f4fc9a19e2493f25620a47e0fff1bc1e212e65e92873b4f20000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf2300000000000000000000000000000000005c35f3372f1ec9845bd04ea722fbed2be1388abf59e622dd3dafb4b3af49bc5fba9e20235e7e58973fedf4b8b720691000000000000000000000000000000001111d18d621070509805d306a31c109701288fd55d4c0644349deb080c6591b6e852b4f7e009b80019513de7f2fce17d",
+ "Expected": "00000000000000000000000000000000189ee5ac642bfd0b612058f96e63acb1feb6b4dce125bf0ea1e56e846775af1a8b0864d4ece6bd96c3b5dbb04e2f6c33000000000000000000000000000000000073d57ab79314e38267ee8015de3156f2c1d5dfcb6655a150b9ab4a3bc9eeddf7b37b3681c49611e02abb012770b3f5000000000000000000000000000000000cfa1363275c7bc5bbb9bb7c03e7bb7f6d6d365e39fccbe62cfe0bb93280527c9ea99079fdf9871abed035b62079856b0000000000000000000000000000000010048e4e96f26710d254110650de36460be2a8302badfc2da8b26147da498e4620e79b4329033fc3f3a9c99b1e12aad4",
+ "Name": "matter_g2_add_62",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001472caba61c2f1fe4b1d0912b114c25de103ef4351668f22f3a158d7a347539a7b6656044bd490f036ca3e29dbdded370000000000000000000000000000000015f8cdf7786410b409f218164063c99e77d8f72f03882a6c9430ec725ae574547d3ea3cf30c3ad2c9c3febe6c30b1272000000000000000000000000000000000ccbbed85c2809433fbcf22d6490457dab800b21cb4de414c7dd1804a0bdeb7142f8ffbb2de921c2c9eabee6a6351026000000000000000000000000000000000a404f42c48e3ca408d3f92079b99805004da928f128206d8904ecd7fcb14121c7d9a9e7fb69accaff921315ef3d5372000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000000e7e532ee4b892af39f8a3db7a05cc77a6eb0b3d977c17076bac4a52d5ba003a0ac1f902a4257791a45370eb88426a70000000000000000000000000000000016a556050e4905fa74b5061e3874f05cc7a6c5b049bd3bb7c34adef5a77c393239a600542a4401c3e61978ee6515a30e",
+ "Expected": "0000000000000000000000000000000005889133be5f447013d779f2b9b0033667c5af87e1c8a16d239ca3ed238920004d87e00119ded46658026c26988ee63a000000000000000000000000000000000d4ed8fd88f7e1394f2b5a65588bf1c461a292acafdb77703c2790ef249f2de695524293c826252c94967a3ea4a3a28500000000000000000000000000000000001b5ff0aa278c7e87a89d4748aef13b516c49b7dc9f7cd5e0448dc6fd860a7a8af7183a198eebe6c7dd549fef806db00000000000000000000000000000000003c9e40ed44427cc3cf886ca2db341ae31f015c542b857f6702d25cb5036e3e6abeb8d4bf9a0e203281ab85ad89ce0da",
+ "Name": "matter_g2_add_63",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b52f05365c4df20a7290aee71a7e030615d1a2a971167884d835c24e756a0faf6ed0552341c561446c7fd3d5e887d830000000000000000000000000000000018718ef172c045cbf0bb132059754b62414097eef640a781db6ad521af5a24d78c622d9402033fa939f70aad0510a1ac0000000000000000000000000000000017e969e44b4910304b350b5d442bb6a0b71e1f226cb4603cc8b4dd48614622f3f4e1ddecb1894046649d40f261d94e030000000000000000000000000000000004dacaeb9e05b9d60ce56c17312a092cb988bff426b8a718cdff860186935507a06eddbc4a1a29e4ef88db83fc4b6e77000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f",
+ "Expected": "00000000000000000000000000000000093b692a68536b16913ef38c3bba7b19ba94a6af1c36a2e54b8ac1754a29c29882107cde142deb95365af00f2d1f537e000000000000000000000000000000001035e70852f38f860a1a04f33081e84f3ed17d83ad894a6800e7b8b9259067b755fe7e08d4c1b297c6d53064ab8209590000000000000000000000000000000013d38db0d8575131865bd7acb6cbe994812bdd8bc7f51b810bc382a6eb379d442c47be20a2c8e751fb08ccce8fea68690000000000000000000000000000000000bd114951193e3bd58cd0025e0b0c807ea073b1c1f7bb04a2a00771b6442e70ea20e1124572ef5b74d2bd87c93c82f5",
+ "Name": "matter_g2_add_64",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019829d5799eed5a081042e4646d46fb6bead6d3b9893a4240867b25ed6af6a3e154514f244466d80e3b9311e060bbd7100000000000000000000000000000000156157a654db2813cb9c1b4da0a3ee192fad076bb2767020fc5fc00e967c1a35a367ffa375703e1181b3705ace9dd28000000000000000000000000000000000093385a6a9dd0ab996df54b23f47f4a49b3f379e11bc8331016ecee6161fcddd22f6d49fbb21f098873f1e17424dedca000000000000000000000000000000000d5b5b0f2ce81e755b4030b33fe3a8bdee38c2c60ed3b4a88bffb9207cb762c0a5c699ff424c000ab080d763abc5438d0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d",
+ "Expected": "0000000000000000000000000000000006db1eef1f614613ada8383e63d631484015224902ca38f58ee384a70af0a0575b0e7063675d2dd997ed8a140e2598470000000000000000000000000000000010d7b833f050f18ff4e3a8d0df227a9494dad9cbde88f68802b23e87387622a5333dfb7bcdcbfe2d4d137cb532ef4a150000000000000000000000000000000000c9c40ba972ee0be2823625a23345fe352d701cc8bf9a153d5a55c205ef1b7e5544d0a7f65aaa24bde8d77cb4c31ab3000000000000000000000000000000000402f170c4c3ebb9b1e7d64765b66ba9b8d45b2ea9fe9517626f38e00a11d180e1f8872bf80f6322bdf3a8dd90732ae9",
+ "Name": "matter_g2_add_65",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003af8c25bdbd0dc1cc344d55366f15555709a74e1f0d8d7050cb6b487759db6200401b7868fca3c2ad26e6362a30e6250000000000000000000000000000000013f8b6ffe30f9a133fafe64461d305cc6b2cf5aededf68ba396d4e00df651531c750a3d94dd77bc5c6713b939b18fa19000000000000000000000000000000000dde97855d7728f409d873b83b6879b45ace5b73f317687fbf478e594a959ce21d4d751db646ceb20432e8311e67404f000000000000000000000000000000000fea997323cf29710cf0e3d44ce682e039d6cbda155e43c94dc8cefc5e94000de4b9525123b9615b5f1019a46ef37ad300000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0",
+ "Expected": "0000000000000000000000000000000002dccab673b26be02d2c645c82a2c73290f0eb053e07d4f81d4d315d9483e57c58b65cfabeb0172934b9fbb52ad519210000000000000000000000000000000011c34a27c850fe319fe89399e7680064caf6dcbad171c3a23c45b9883ee06ccc3482b2b81e5777759ff81b16bcc1b0f500000000000000000000000000000000119adca3e2b052c045124f021fceb03c979e6eec0a270c7f4ab13674e461839a4d3a10fd48da4e9ae750a238a2649ace000000000000000000000000000000000fb5210677e1096cb5448bcda16646d6dd29ff8a0765c5aa51d83fc952a5ab8063aa96e97f33abf701cb8688c989c363",
+ "Name": "matter_g2_add_66",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cdf60e3bb018407eab162822468255bcffd54cad9127054bd1c30705a4ebf1afc7f539cca6ba4cd070b44410ec751150000000000000000000000000000000009a2e3e5993b6a7007dedbbd21737a8c0aef3ecd4607953c4a24bb3fed97ccae01ae1cec024443f300b570a66e9ac3bf0000000000000000000000000000000008a21fed19e9ec2a741ade7767b0c9f39b79c3fbe34aadc9eb3043583768d893bf927d26231759290c7dd9c4f158d5a10000000000000000000000000000000018eef4ff88d63149d2632c9db586a4af0606644b16c82fbb0a3b869f1ff924c59acc8efbfde7bc604497ff68939cdd0800000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec27508",
+ "Expected": "00000000000000000000000000000000056489b2248ba672501069ab6742016cc8ab2af50a119239bbd3c0a4b9b56e014402b78bf62b2b37bf4645c3bd3d95b800000000000000000000000000000000046956432001feaba6d230da27a72e8db5c8eb3d52f00616f87b55c951217095f337a302562cda789e5714c4391ac27000000000000000000000000000000000172c2a583c9563fe02d43b2b767c4ee4e3990fbabe4ac536d64cfcf059f0e38672876289bc86915b6344eb398fbc4ddb0000000000000000000000000000000008915b0edade80caee9b386e4a560ff4b9dce33946ee992649466315786e139e3ce241ebbdfa7ee28fad7e6214e65666",
+ "Name": "matter_g2_add_67",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f5d47911596c46c0c08cac5f5e7f6d0609874da4ac1bd4e0e59c393273a5fe31a756c7cfff2a01d19e79d209d7c6d3e000000000000000000000000000000001010f864eb6624132d4436d18db7f5b34727060dc426c109886be88031e3c155490cb3fb09e1fbccb7912875477c6d840000000000000000000000000000000005cfbf1c2ae1b80a8c7cfb2cefedd907b0552794f4fda101ca1a723b18de8cbce30eb54287e1847cee3f416cd8b45f2c00000000000000000000000000000000084fa63781f7eba9c7e911ae5866d485bc7e90603541c55d1ffad8b3cf7547fd57fb24b14002560e58410b828513e1090000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f",
+ "Expected": "0000000000000000000000000000000005b81843ef3f98c6a6686f1fbd26f77248497ec3d41aff4be5968d13ba86f86309b0ec4792d74220ad8ef147bdee9aa90000000000000000000000000000000019825376b243f3e374b6e9e7e51e0c969bc72b39cde1dfa09187a3c7c5c2c752ee16fa5a4c8fcf94464287419b3a3845000000000000000000000000000000001308cc0c77219034a9fc3018f1d668a41e6959476aaaa5461ec73d7155c6a68fb08e1fdf8140e18270cd338c266a83f4000000000000000000000000000000000fee2a6e245e3bb570c3b605f7ad805bcd68e9a1f2bb2282f92e2a2e83b69e275b21b923f33a65defa8c4224934aa588",
+ "Name": "matter_g2_add_68",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000124870cfa469136c638e0cbf15802f2699aacb66d7e4c2965c6759dbca4b7e47941ad9ec37a84db1afeeeaa65a7418e4000000000000000000000000000000000d4503049a6a53536bdf41dd832a6ecf3f10554887da7e389cf940394e1d88db94369b7947436546eb6c6e82c48dfb9900000000000000000000000000000000053f9a6e1f05b67cf553073358009a172e2ab8b43572a974da1f3de85a29103b13d7e67b2a359297172d27dba5c61439000000000000000000000000000000000abc29f50ddc1c113c73700b9b9796890cbf48818ba981fdab2db27ef1c58f4c2e4595b99eae397d40990ce2f6c9317c000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b",
+ "Expected": "00000000000000000000000000000000166414455bcd0e8e40397f4cafa9628d1a092beaef62d35211cf49779ba98df5c1d692f650c1fcf0893a9d4ae1926b1c0000000000000000000000000000000003dd898d0725ee899b913042da8566a1379aeb4dd5f0222ac784205b4e74f32858ae490f981801b166a01fb96266dbeb0000000000000000000000000000000019f0fe4f12b113b337361b977aff7cc7dce50bf37c2609b9f311ce340d30225de178999b73345ef49625518e52aa4d7800000000000000000000000000000000090bc07c6270901d706a8d28d512b07fd0e03013d94d4e43eafbee59677998bfb7c2a58aa93571fb49c35518b6331bca",
+ "Name": "matter_g2_add_69",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007d2aae9794b7a7de97f7146c0ee8415e09e56fd42535bce6773cadd6f7ac09c4eafe2e926cb7014377e54c703eaa9dd00000000000000000000000000000000172a4a33ccf99eb0473b2c44d30bd53159afae0c7706ad128bccf6258974d5e5761f9be43e618cdbd96027aede7fd5860000000000000000000000000000000012601bce2171c6e4c2968a3efdf1491285f9e4ab37cf973ab5c8e224ad5b40e1b6459ac89090c73deb8fc79fec7fb8e200000000000000000000000000000000112a6443116e6f98ab348e57daa3971b5fa506e40515e1611fbed3e7dd64c5c1e991e0d2539a70eb93e3da0f573d6b22000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d",
+ "Expected": "0000000000000000000000000000000019ce0f31d9ebaed0ea1d12d4e232bd3ad48373fa465af44f1c8015102b624d2f8330d1323fb2fec524e83de0f6699ad7000000000000000000000000000000000915d65fef96562ea3b76f3152aa1b8e445ef50fa66dc487ad0c04cfd7a33b5ee48aed919eb81fe83b1f4dca59b4990d000000000000000000000000000000000e4731ec887261f29475523f7dfc5d21cbbc1b883439701a33cd58bd24f5d447267707c2b60ea38b04510be7dd10d72b00000000000000000000000000000000146a679d7a81aac5952645b2635f24b96393529ab9571ecc1078c4c20a77e59acc4591b9f45df00428250c5e31b1a8e9",
+ "Name": "matter_g2_add_70",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000030372914b83644fa4db1958831e9335c72ab7a811fb337696221a3290e4c54bc10c2225f8fdc3a9f62632ba2f1594500000000000000000000000000000000114205926609470b6022d24046a1997c048e6d2cf6043397892c967692161c0ceedf409bf5e1199a64eabb1ff8de23640000000000000000000000000000000017cdecbe73779855b7b94920d4bc8ad057ce51c5481a5579650df8a5bbc421030d2ac44568217c4dbb13d7c639760236000000000000000000000000000000000f194fa814bfa7396697bd812d9449d06fc61b580d7a86429fdd1ad376e21ceca139356d7d13964c3c684563675711c60000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f",
+ "Expected": "0000000000000000000000000000000016790155e57f7103d9e325a1f3a64c0b8a1875365eaa0c01c515538b64bd8265e8392e755a2f7314c37ec09026f13d290000000000000000000000000000000007bfe690fc4ab166b29de35e341e8faec4bc3c2d4ea2d42c9f4166c0d748b92b743ba646c86ff9e570612c75bcd522a9000000000000000000000000000000000c11b9ccf990162b772099fdb4266716b11dcf46c5abd12d03caf222c571e2a9e28cfb47e11db05162967ad4b430930e0000000000000000000000000000000000bafe02785607bae144d9ef5391fef02b9f2fd5dcd436e2506bd40866d8726eb83c223e09c00f3b8895181c6710912f",
+ "Name": "matter_g2_add_71",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015d4ae1521acf897344c3a76261754ff99742585af4a0ee86dc473a88fd408091404df1da9d8bb291db68bc9c07d6b2b0000000000000000000000000000000008ce160213875c661163990f3f7ac219ea295db5e828354864517ea8689ec15d35c6df78ff14cb276e0c97ffd7fbc09a00000000000000000000000000000000038a3ee211e777d6d6b7ca6c7a0d2130f1a071c030eebec412c3a0f14c3584e7c5cf15de254a8f141a8210a90249ee5a0000000000000000000000000000000019f7ec6b2fcd8b3190ab37a6e843340d3f3fc092f5772a042edbd5bdc967b96e8a1dc9e435b8463496aa1301f87d0e5a00000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd",
+ "Expected": "000000000000000000000000000000000965966a8a463de1f3bc49d9873668e87f54d95612231458dc8b885681cee8e2835482b4bfc476153c41b206f427cbb400000000000000000000000000000000183639fa14dd74c33e8696496a3ee269160f88e5daca4fdc468724d9b6af8e7d0706867cdb1bcc608029b89b94c531a800000000000000000000000000000000026257fc32efaf241c7712b0a7e9f881763d8fa0711a452d9b71ea25e973bffd88433cba768f1e5b3ea15bdae9cb9428000000000000000000000000000000001527afbb6594dc0f472673606fb8f4797fc855bde4d308ac1acdaa26f19a70f80f2d2bbf3498b53b887b79fd6273231d",
+ "Name": "matter_g2_add_72",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fa7f8fbfa1d4ef5f001a451c55ed261dee344025e599884b29d086e15665867932120d33bee579d5eb1b7e6c7299f310000000000000000000000000000000001f06356f793350b17b47a623059a068800ca1eab6089c7c146182990063e8e23bbf40d95a42bf6e976224b680b75bfd0000000000000000000000000000000008807f6606d2302450bfd8b38fd4147b851ff59762c1ff48f9442c4d7b77a32c5e023821eb47fca839a27fde60e5f61d000000000000000000000000000000000c5b92f1ca9c20d4b6b11d794a5853824cff20d9267a20a7aaa4bed8bfdc728c4d4d50feb8f0b569757b97f473138db100000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3",
+ "Expected": "000000000000000000000000000000000018123e82a5572e6b6c62d5db07448838df9db7f7d15dac1adba1fd924892c8bb3c417354e838f706564a9ac282c2ac0000000000000000000000000000000016613fc38997d39b2761aed3485de4d7c273e8392e434185605e968ed942b9d4712cd0d538ed5ed1317870d0cafcae27000000000000000000000000000000000354365566b6e43f8b7f4b94a6343146f35ba3abf61a204e9c976b1ad1a90d4d493494c957def69ff270371c1c8d953100000000000000000000000000000000066adbadf1b69dd16cf19349c82e362be4a3768551599b81a4853ca524a24326e6c9dcc38b5a60ed6fdeb3cc4e7973bc",
+ "Name": "matter_g2_add_73",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001191410ec6c5ff628bd25d35965f5e9fa7f3c3d8c0a9a1ee7ae37437a97c25e221110d892e2c7a0e9c8e386774eadb80000000000000000000000000000000003be30c25a18cdab139277232d8888f6d13112c9556895af8030f1893114d5845d895df9afe3c6f9ff7ffb1919adea9200000000000000000000000000000000197f6b4e38be0358a3f1722664c61e62587ecf5467f8aadc3a236b47682a75cb76bafb18a5c556b321d5da49cd4bfd4e0000000000000000000000000000000002e4ebf7f22d929b7421a600e67fa2e64a59edd87a2e2eb9dce1f06d3c793f1a812bcdd510e654d44fb4c1de8c64ba9f000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d",
+ "Expected": "0000000000000000000000000000000018ba8af47c5cfa552374cb1b25ada1ac785381f2da0501f86c9e7b11cd4417e64095a5c4bdc2480ee10d215ae2296063000000000000000000000000000000000a2e09eff98280f6a9863d8b8faf8871b44650496eac1aaf90fc2b256f88e937101407d722c95fa76846776d4e6bf0dd0000000000000000000000000000000003824f5bf25fa4aec5a9e044703e5564122bec11da155c01ba8ab8344265516c1063983235863d826f68bac455327c65000000000000000000000000000000000ea72f8c6768736800b141b477610e37477d926acaffaa1951a5bfebb042c94c065e984a8812430153d529dbf07ce2bc",
+ "Name": "matter_g2_add_74",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011c6f1dbccde640f63ad7d40089779d01075e26269421b4ce12fa5341f58ee9110f17d08dc1052426f2d00da2dd70b4f000000000000000000000000000000000740b147bcdf06705971c113a5cc12fb37345dd59f2cbb5ff500ce2b347fc5a8199cb3007a871670d5093f28979cfade00000000000000000000000000000000046563ea98b5e85b3c42222d5e0d8481e6aefaf077a1b99f2b4eefb397ec846aa3659aacda569054c9c8b9b69750272b000000000000000000000000000000000812d887943506d68e3525ced9b979354539b7b14003a3169e0084c26326b92be67346920c9a99ef0f9638e8991296fe00000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6",
+ "Expected": "0000000000000000000000000000000009f1339cff0b58b00a871add058929ffebdc58cd1bd8a9c2c965c63e1843945b28138008cca8bf7b7cc9afb69a11767100000000000000000000000000000000011f65b337710a4043e1fa58bb41d80d505e2aee434b6978129c80fa1b124db89e61617e89bc0e596507566f4a484e9f0000000000000000000000000000000017560f768496ed583b3522c4a013f8b96073197e5b53e9041db6dc935a266111e21d8c54fa33b7bda944a573f6e1f07d000000000000000000000000000000000168a0742af91f42058e6501e122b6fc50dc966c2f5981372704694544aaa68fba2b6483752fa2464526d5072f84d8dd",
+ "Name": "matter_g2_add_75",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004c8078fe8567013e8d05a546934026cdeee7d485e30d739407db16fefaef53ed7bff0f9adaaf064aff014ac919d91c600000000000000000000000000000000107cc17f485af7f22e07cf14c5cad6368323f720511fc9dda677b360567f769e47a77f61274927ef9b7be48a77357ec40000000000000000000000000000000001487f0880a6cbdac33ca35b9b65e4ead9d8c2e9180c993bdb2052060325aff8c62668c643f0cd9b4bb1f06a3dc74285000000000000000000000000000000000d4b2d062e31fabe8d2a329dbd6417673a519f455739d140246f2b3e43e20f390088c08e545bf0419d796ac71aebb519000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be",
+ "Expected": "0000000000000000000000000000000005daf8338637bddeba63c788d78faa622e014efb84d3ac1d655d15af06317fe31d1782b2990354bd507632844cc87f2700000000000000000000000000000000185550250e2d9eec798e8b8c483dc37e2a917b304a6036e8ee518a0738d6bf946d99f6b7ee352b1a259aa894d53a8e1300000000000000000000000000000000105a4865d66ed4bc4f51dc52ffcf284615593d573b6beac490c3ee8e08ab83a529c8dd062d762d1d70b9b3290b6e8bd50000000000000000000000000000000014f598e5d0e40090f29aec1ecaccbebbf2a2d6889bbb9439798924db41b70c0cacdcf1e8ff6906f61943e9a8a1ae4fb5",
+ "Name": "matter_g2_add_76",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000811e9b0acfc10830c074c5a4d9f4d9382461eb523a61dda0b77f1c43b285fc5c1ef3a1fafd923addc9a6e904505a255000000000000000000000000000000001113102d015dbb509f0b8d0d0ebb4d3711c4f0e1e3d55fb0af247dd24be4fec9d6fe3ad73fbdcfe206891bcebefee4dd000000000000000000000000000000000085aae9e58fb97b96ca3c089acab7bdbd0c3adae141bf61075f5c13145b0d07113f1075dfb959bc7c2d3d3b3a06ab2a000000000000000000000000000000000bb5eac8125807c10270d94e5bcf278241d6fa82f68e41b5529b28aebc88870af55881db526f7bd221a8c4c0b29a1b7d00000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c",
+ "Expected": "0000000000000000000000000000000006b63929ce97554659ae731d60d11abe858383e39a67007877f68233cba8179777c0dfe511fc730448da3f1c4347f85c0000000000000000000000000000000016d4df414c287b0871c69f9745a9ae68ea3a1ff41ecd17d87623338bb8750bf12be52caa81537bacee06cebb86f894890000000000000000000000000000000007ad72c98e2428b90bead3616f1b31b26e978cd3f9b6b759ad53056098c18932c48ba78d3da112d7a738d7a9ba21d84e0000000000000000000000000000000010dfcfc53d0458296686fd7e0555593e0378d2cb176d456abebfd8322012bc9b408bb180d4237679985457e689131705",
+ "Name": "matter_g2_add_77",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001335276775545fbb4c701beb57cb34312108c9f1d46b4aa4b09a16faf0e648b4e80848bf5e75ed8730715f0107afc9820000000000000000000000000000000006ffff8736bab41b4ee5681b741a81fc870e648001027161144254d04c678e4f954e9f191bd8b26201aec681cbf0654b00000000000000000000000000000000026ede90d14fa0885baad21f9631bae058573251cbef5757bb8cfad061f3bdc78834fa5862dea19a2236c014b0f1652e0000000000000000000000000000000009844d0cf7f6f3401145d8d720defa577ca46b49e04e39c4c139ec6811a574e7dd5ce3acd00d1ce9496f10dd15c6d94600000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3",
+ "Expected": "0000000000000000000000000000000009b166f124b5b85875834b5b0c088ab79a2dcf262240b284f57722e78b6eb56a192cd32544c1bb93ef492fe6d7a6216b00000000000000000000000000000000189b9792982b51b13cc3fc1691e0569b6c8d998168d3a3376e63ca60de4b30a84ce8d04fb265bdcf73f158d8e316bdda0000000000000000000000000000000005b99948b635750040b5b59568f0e8bacbfd512db2ae52c5032cd23eac18ad58d83b8f78cd26ae979ce2abeae8e1f3c3000000000000000000000000000000000d0b6561a49c358101b30f714563bfefc72e0febea857b1ce78cfeb9508b0108c2089c9b35cd694bc8c0ea8afc8d047e",
+ "Name": "matter_g2_add_78",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010192b925fca096682acf138833b12d96bf97c9a2e69e4266eaaae1785b9008f36082e23e2d42341427edce24449935f000000000000000000000000000000000d5b24a94adadbf542aa663114096bc670e1b6c99f3b661f55de121922452534faed7f68d6b431fcf6f3e379d7acf6b6000000000000000000000000000000000acdbcae49206b749d8c0d21017a33e689ebe26804d1fe7c863a2ea4210c3559805dcf73685702bc56e644b4e02614a9000000000000000000000000000000000092309d684fcdf44bfa321d473060dc2d8a8c66c51419894a3fbadbf1b56179c31dff25403b970d543f1dd0e19e56cf0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a88",
+ "Expected": "000000000000000000000000000000000bbb59d3e6b0b4d86ffc89bbfcf543a5b8ff922f1999a1e06c501a734b19dabd54632132c865c53e5287f69f06942a58000000000000000000000000000000000a3bb94431530879a7fb46b317d4f3d65b5a790739b396c78521a20e1cfad9c44248c9576be11c70970a49a1914ceffd00000000000000000000000000000000198df068ac5d3cfb9bd6896ab64495f4b9933a72872679ac3a46764478f043e9fddf17a7ef85fb72a8dc1a722804198400000000000000000000000000000000155c1a9db0c90634a6d214e996b13252bd4db3a4ab84ca7456ac3e7899e6fa096904a90f1150026307a1cac8de00c6df",
+ "Name": "matter_g2_add_79",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014441b14765eee30e8131a7ef62c3b59370f2f6f0dda20fb2a3654fa09492bf695de1d1a8f250bfde3c7d2ed805ffaeb0000000000000000000000000000000019d813f8be2519e89d42a9fd3fef09d44a996d6a4713a9c224bee10f0ebb196370d6231fad810edf9cb4c875f08357890000000000000000000000000000000001a5abea13e909bbefdb51ddc699614366f271b2f6490ac8efcca7759833f3feae11057ab1b9ea32311e7b6ea6de110c0000000000000000000000000000000003ac2bf3c5486ca176e34ec5212165cbe04fc9e8c375e3e999a31fe014eb824ea3f2d06b9cf8b86ce3a76960cf2eb4d70000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff148",
+ "Expected": "0000000000000000000000000000000010684ea0303f0e76b60eb96c470e1f0466f1f2b073bbedc1a0c0df1d2f6c66d77cb90ef9bfa4fef6a6a9eff8f5c66f9b0000000000000000000000000000000010e7ced79bbf01ae9f65d26894c73a905514296f19561ab4d00c0cde31737d01e7b4e8b8e6050054a7a17e8acb74d49d00000000000000000000000000000000174f771a98e262825ff2db7571f5f5475007d2f73a2c265f24e2929671bd173596b8b163abd46b868a644dd464dcc7cc0000000000000000000000000000000001cbffc9bb3195672ea2d998b169f853d3d4b4e147379329b1bbe69ce76d08ad78f87fdd876af227a050c31884fda084",
+ "Name": "matter_g2_add_80",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000598e111dcfeaaae66d1522be2a21131350577253a3f33bdd74a04b0bfba2940e73b62fefa8f0c34c4aa91b633f6bdfd0000000000000000000000000000000017fefff7d94afbeceb33714e9b5480c3a2f3eabf9d7f6e8507ae54cb65f69b21cd7d04d23f24e3a272c589f572b91864000000000000000000000000000000001652e3f5a99ba8dfbcd1f90de955ef527947642054be603c1b84b24bebb579b78e2a0be426ec21d32783a0e55f0178dc000000000000000000000000000000000a6c9ec91e8bc86ab198416cbc76239f0ac0b903f40310ee1f2066b01b08191538ca913c2736f53f23ef37fea13d527500000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f",
+ "Expected": "000000000000000000000000000000000fa306f630d06c801e0203525c75fd6065bd12bcb3c4d45c7e02b597f85a53fae1e65a969feedca75068433547e4632d0000000000000000000000000000000004b1bdbc29f19f6484ea4648c70eaa47cf5bb07bbc255bb72dcf68a7b661de433dafb682d51321369cd3372288b2b9c400000000000000000000000000000000136671654b24e1ff2e8223ba747ded51f5c826b6e2c0f02e2865fc35d15045f41952835800406f60f966d1f241914726000000000000000000000000000000001007b5e8ed7f0d25091dd959d89732e9df02561a829ce013f5ad1adb8d6d828a8ce87b52d39fda1b5dc2b581ca420e22",
+ "Name": "matter_g2_add_81",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000072e022c168461905f798e87425f2eebb517e473cef98c255d0fe434863ef5811920af65bc946b29d489b5dee1066c56000000000000000000000000000000000e7a9872caa82d191f6014c845e1b3ee4ea1ee89852b546a2c85ddbfa3c1d4ce99002e3d7732ccb8cfbd57d550285ab400000000000000000000000000000000144be65db373f6401d76e0ee64e51076b861e8fca596dd6a7f3b5735c23b0cd13248404fa0969ecaa701663a1032f48a0000000000000000000000000000000014c9e9c5cffc4518889f7742440053678ff1d9fb1a1a103d0c1f762b10655bd5849ce98f4bc5eae80bdd9e767aae452300000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf",
+ "Expected": "000000000000000000000000000000000fb74d9ad4de11df81c48d10b9a14fde8353ac47dc902b4420be4c086332be480552e26fc42b7c0f30e34f740bf9a4e6000000000000000000000000000000000612a7e23bbb525f91084b122dd4cfce4074c9e6eedaa7cddb58a14e0b1eccc2f08296baea3eb3e003e576fab7c557ea0000000000000000000000000000000016dea145df47a2c5262893c273c6158ee14d44c3740981c161624a6e9ebb982a52c1eab6160c3849f2bf3821d953f4c3000000000000000000000000000000000e920661772b8b737f1a663badead0e89aec4cbb86e6dece5d4db8a673e75b844bfe81662dff671658cb8386c16a7f3c",
+ "Name": "matter_g2_add_82",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000948d0f0c20715f8658e1f2b4f9d32d851e584287225a2f47735a1f4c241b07f8d7c5dd8c13bcdf84e97d49817d4d88a0000000000000000000000000000000013c064548cb756b48600dd535af8eb5b9138f984bac0391df2e90a204fcb6c36017df910031864d802a2ff719856b336000000000000000000000000000000000000b7eeb7c9a01be88e573f196c2a531635baecbc8cff9af385455af3757301436686596ec7fe3618af26953c49f7450000000000000000000000000000000001332f4dbd5461ab9e2c8b3c19c6ff407a071018c92d2c17c1d1d481c24565276c0f55eee8692016c1fd76d70f44627c0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77",
+ "Expected": "0000000000000000000000000000000015930559743b21acaf390b557fb960d3021f3cde80630d8867a063d445f860c8a01037057de1929be16d879416b12a6c000000000000000000000000000000000c6074c54c83f717700f61c5b6bfc641502121b59b196a1f8c5f2945e5db1bca0d7a94fdae96bfeeb6204c8c3f4d048a000000000000000000000000000000000b3a78454479c0990e4c65e4f831606c7eeeaef0faa86596350c9e43e84ae959a0f32c8d03d1f631d9b2ecd046efcda6000000000000000000000000000000000aff797d7572f20b06bac75bcf8cef879df11599ba7f8b86eaa28692d1239cff22841b66e28662309e81a6a599e79ddb",
+ "Name": "matter_g2_add_83",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d3ee70610b5029a28e586f0f3e65bb19a263db3438710fcb8073e1b25f83db50eb5bbb9d75cb20952a225023f747baa000000000000000000000000000000000682f7d5cf9d182b20ee88683f3915e8c9b03074a373e573aa57232de4e997bf155acf680e365aa0988989dfad102b2e00000000000000000000000000000000143962963e230a9154dc328f9583f5be6923a3b10ee7b1d0cd5f5cbff13913d8ff78ca315be7387900a50b94449884c0000000000000000000000000000000000f4f934b42452d41cc20d7b1ec547bcbcbcc10f215364ccf2b864db23a09d06e94c7a87165dcb691f4975323486757ad0000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee41",
+ "Expected": "000000000000000000000000000000000351bad2f1fd9adc84280515c2d9e538b69dd63ac93514987ecace75d6bc4585199b742eae0d357d587924333721a1d90000000000000000000000000000000003e495b544aaf19a6415d5558170b8686968dc922367c5c8c212fa1f2785535fe0e71498b98b9a39c8b1f2384956170a000000000000000000000000000000000c7040f34872eea5f98ddc78737dd01fdafe75081cf66ad5c7c900674fa90257105b4f4fc59103dd5b92727a072ae462000000000000000000000000000000001312bdd27ef038d4a89b12c86281975bb34b435d42642fe0732709baf55e9a0ecc0ede8a4775a33e880aa2e1fa7b7ed3",
+ "Name": "matter_g2_add_84",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005f0fd4080e26971ab16d33aeae04220ae23781da3179e38190082f1d167514bd73bc8ef976a2f333570e9f56a6c05e6000000000000000000000000000000000e159905d29b52ba61575c3a263093017783e1028b3701ccf060c165ba33a765b5265a9b1681c1759bfe2c9c401275e9000000000000000000000000000000000c5ac0bc29a49a7c37d772954da850e6b5e301e230552be9a94017d770ebe2cf4dcfaf104633623e024aef6db57892900000000000000000000000000000000002228e7f42a9409acab49cca82cacf306f6c6c29fd9f7e2ed12fef2d16383cdb7bb2b39ad598b301072c615232db1fa800000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f",
+ "Expected": "000000000000000000000000000000000d521781f60198341d116fa5cd9e2b5c2fe51f91f6c8318f351df007c96086f6c3baa5cd2b9b4f442305695dd9b01ac70000000000000000000000000000000013454fc15b1d182bc98d75947547b3bbebef6d5e2d38ed7c67d76eee8da89ea2be19280af4760282fa7576412d5f2107000000000000000000000000000000000d866015c84de74c24dde252542d0d3823f435203c71cda140af235d88f3f4b736e9d75ec32c09ab73bf74083e76866e00000000000000000000000000000000147dfb5f53a9cc61b6788c911dd8649c09cfffbbba368c1872a31cfe3bd6d6427d7b00163d39f8e0b81fc4c40dc60b87",
+ "Name": "matter_g2_add_85",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000180569ce03e4a0155285e733adb18fbca71225507a7adf01cb8e8648891525305e92087f58378f4fd8455d5632ad660e0000000000000000000000000000000011ab84e42f10154e306a568d7cf7bc381000f0add0500cb508f695a3b283ea69d140aa0ad48fce2d2d6fcafe60761078000000000000000000000000000000001136c3016474d6f475609606e8d0269fcdab9fd3188a512681cbc41eedeadfa3b3d9355e5b4503e8b5c3665e49fdf3ab0000000000000000000000000000000003f56cba1b9cb4302099b16b09c2602dfab80d1151685ef78e5054cd454b319adf8b5998053a5b9fddcffa020595e3bf000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c",
+ "Expected": "00000000000000000000000000000000059fffdf2d79b4a297f6912e3035cf0b07db9372f3485150e00d60bbe2e7d86f45b5c2ef062dd92c7e8b1e2be5e9bd140000000000000000000000000000000016acdc57e7231b020268373ddc8b8a7318ead02a8c7181165ab045208409373eaf57ace9a6db1fdedcaa477c7a0ff6f40000000000000000000000000000000012fe630f7de8ef5a129b99faff2de080849bf3b59aae1af042c29b1cc49c8825a4f28c4ccffedc6d568f306416b5bb90000000000000000000000000000000000d86ab3e49ffdc7c2485ecbd00256af83e7f3f064d212ea91245d86ca75e3c7f28b42fa9496a5ccc0514cffc60c9fb83",
+ "Name": "matter_g2_add_86",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004d79dab9eef873f3415d66172bab7166ce0c71f322529bdeffa915c1b0d3fcd645c91dd3450ba61593ffecb95edb91e000000000000000000000000000000000d611a207d3222bba199fa083d0459675cb5fa00839fb4c9034ad868fc1e79d653c18651771431d6fb6b6b5ce8cf6f7a000000000000000000000000000000000ce802ecb106a4f0ca4efdcc058dd0e29deb6a5d30a2c15c8eda896bcdd3ac19053c10105328d239b26c5ddbdb3a95fc0000000000000000000000000000000001073e142621ecbeff6f81453660362545751f992ffeec3a83477fed3e6215a709ffe0d17b65d3369f8f3913bf000e84000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb1",
+ "Expected": "0000000000000000000000000000000012ba9a8fcb69d15eff147f663a5d7927b6f3f79330eb9ee625e0100b146597554debfcf97a3afb51387a73554522ed0e000000000000000000000000000000000a63a990d6454d4db6d58642eb3489f79e517fbbcabc06f2eaa00c4b6f9a07aae97991f169d90af3461b7a62db276e00000000000000000000000000000000000a95203a1628a6ae2551df832f7ab94ffcdbf985e4c9744e244214c8e8b8079af05a9321d1e49b7240c2bdeeb7b783280000000000000000000000000000000001ec747203be73526d3f943e0af814dbede34020144bf247eef9a6ac2cfc83ef63f18a73d3baae18bfd8d5e83d0519de",
+ "Name": "matter_g2_add_87",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bd84f04b3858b1138b1b429c7216d5d1b1e99c1e0fec26440d59b1ad79788c2d5583122c2ad769fcaa6d10d816a1f1e000000000000000000000000000000000387977ed1ce5da51dca230531bba53d17d3de5d593ec576cabfe6463d5164d7153025dbd4cb3525c4145c4f6b85fc76000000000000000000000000000000000a19c943a90fec6921367a2edc5bc38a5c59839cdb650766a2d2d068242463dd4460bd1d0e7a7fb0e3d2104704b8b3730000000000000000000000000000000011d99d44b200feebe00bd42809e3f67a23cce88a07165416cbfaf4db14420f99e54d62db4280d2c99ca0bc3dc41eddbe0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc",
+ "Expected": "000000000000000000000000000000000eefda9046a950c232c6244a79c33e7135d0896bc57839a4f971030220e3ca8196cd0ad75269f3cb5586a384dcd17f9f00000000000000000000000000000000195ce623693996f5ce9e45b4e285adb969e6771e6b0701fb5c95715523c8cb93aa641583821a3b360ad6f4ea1aedcc9f000000000000000000000000000000001553a4d0f965d26fbaba56294591935bed63c84abfedbb9d5c61f3d43484ea71600935fe3c8b6b137d7a9074d907e86c000000000000000000000000000000001673c42c88e4acf8ca38680694b80458f988403a4bd667468506452303000d13649c4f610b738a94ff88b65053731c08",
+ "Name": "matter_g2_add_88",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006a186aa584a466a860849c78e4922889c95a4ac6f39c99029fbb422c43d699a8baa51aa4ef51ff99557babeb3e9506800000000000000000000000000000000065fb15b5a0923bdb52dbefc7e9f1a898e32f17d610bac829235446fc5e1913fffc8176e0fbd33091505761f1d06d8920000000000000000000000000000000008bd358698fd073f660ed608462cfcef1da9a59b10905f1d98c4fe66958e56802814906430c10fc25a4d351d91f91cb0000000000000000000000000000000000a53638b1b6c6eeff468e099446300ca7c7bd899c6494682d14fdabfa9cead0bb37a0325d99e7d0ba6341cfa1d257ba800000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed",
+ "Expected": "0000000000000000000000000000000007145ce58cbe48405392edda6022ba8942df055ab582ac402e7c9a0a951cc6a38cd147903f042273e736f30849996cd10000000000000000000000000000000011b457ba464ce818a34a11afc3c0007908091fb528836691e6eccaa9a23ea90cdc746769c4b7ec73efb1f2878413c3b70000000000000000000000000000000019ca519fa6a91cb7e83704daa9b92da9bb70b003f9e9bfe9f323430bfec9b19b01005aa9fcd19d5b1ac59dbdab0c0d84000000000000000000000000000000000ae356f5e5de0d7662bab8d947662bf87d792a3438ed477cf6ed4b27c935b1dd76a5aac446d4dc36db544d4aea40b505",
+ "Name": "matter_g2_add_89",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001070b98c6348a67e996626ec2752f45e4c007e9c9668459a777c03fab633c10236a1c5be99f3fd950542d5648ef9e88400000000000000000000000000000000073a564401cb1a3a53334c0a55da261814d27b86ebf40b02a76b20973ba2db92e42c138ca7790261c2d70401c984bf470000000000000000000000000000000004212d8a9e4b01f5c6814a88561c2c6143eea61327b031a2e0e4bd056c12dd7098fdfe4d1511bb441ad42b55b584a7bc0000000000000000000000000000000005c5d23824b0fe05eb962194550681c57c1566b315efa8ebc90b3593d7d86ad18328baab8118c9f47eccc0757588591c0000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c5",
+ "Expected": "00000000000000000000000000000000135c42c10ef97279e3d152b18cbb8dac11ca8c805dd1d80818851424f592e7522589ec7df6748b5c72d0808399e629cc00000000000000000000000000000000083ddf3843434937e05ba9e101096371fd8fb34f226bcd517716200003ab9855f7aea94980c57a6b933494cc57afc562000000000000000000000000000000000be9215d936a49538442189c9a0bd3be07d4b0b1d14aa45afcdebc1fde17d33b66f7dc36da1ea5411549577f5a1967ff00000000000000000000000000000000176a4a4962c4af75a712e5093ec2cd5cb5c0433aa0657809dffbc0bc02b1ce303ac084f39a5721d482d41412d391317c",
+ "Name": "matter_g2_add_90",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b1b3053774ad5515a20bd4c556d2b3ba95fe74fd0c955069c7f933dfd718ede90ac295f5a675f1c29dcd9701978353700000000000000000000000000000000145746ce88686021a0635bf6f0aa2f77c48bdb364cf4ffa804a57f95bd69d24eead05fbee24021c1ef57e1c7c7b894b00000000000000000000000000000000010ec4795a0762b86f3b83de1198698af67fd1b1be3ddef48f35cf82bc96d886fbb4c75064f51a9cfc5f61630c95d0ad1000000000000000000000000000000001465e31f58892466b8ae4b76a239d9f8d1ecb1834886344013cd1df0be13591798868d224d38213a6d75b02a1fde0ff200000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de",
+ "Expected": "000000000000000000000000000000000bcd916c5888735aa593466e6ab908a05af528f34a7901fb60feb1f51737c73612436c192dfdecf927019724ab2a9b7900000000000000000000000000000000187d4ccf6c22381d0c40c9d7820ff8efe6298c6dad0caa25402412661737cb482dba2719c3a50ec08cd022230952dfc600000000000000000000000000000000164510d4f2cf1e14e039561f1baf82bea678d0065e378d5bb7443fa782e6ab2a3bf7e4ea125d6415a8277c60f5346468000000000000000000000000000000000281f2e28b73eca4db9966456b75de9ae3830c74ac928fc4c36b4aeaaffd47ee587d948f68056df2826ca2775415a53a",
+ "Name": "matter_g2_add_91",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f39e731e6ddb7496448c912ae314e833d28208252c7f8e27bcf7eeaf1da6e2310538b4ef0d55401c6552e91fd70691600000000000000000000000000000000069d3612f924961f827497028737000513548ad8e104acee28f014e730d4752a583cb9a893e6169b71966a1c4a4ad2dc00000000000000000000000000000000090899907edcbd336bd4fdad0dd67c578ced4481a25b864b32aef920842689a2c23265277a6e1d4a1dc1b5047a9f79a000000000000000000000000000000000055ba64e2502baf68e46c759fca30247a080464eda2b32e7cfe539e545d6aac6dafb731c2c45749e50513979cecbeb5400000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157",
+ "Expected": "000000000000000000000000000000000cceccfefe04f94e0b67b29b5df8007930665006cb5a59504c3656b8c0bfb52324cdf50fa2722ce15b0ded0efa7fc85f000000000000000000000000000000000cdf34c330c0125f524f0711197639f8aca3e7c435f8c5ea30b78e9622c4bb72a7e584980cb4c3c6ecdd0689daf36b6a0000000000000000000000000000000004b1505d7fb65f6c06ef23aef85b16f3d991218187c5782fb635ba805da463cec9cfdd670c53d680c603adb827a4460a000000000000000000000000000000001104af6bef6482ae64b3b6b39664ec06c39bc18fa91b7b4e5bfcd444c827bab30ef548b28ef5487582d88fbc6d7983cd",
+ "Name": "matter_g2_add_92",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000042f1c8b9fe81cdcabea047d0998a1354ce09d62a14f1d0e9d188e2f35f2e1845c2b090c5e157595b33108c67e6c184c0000000000000000000000000000000018e69d3564d4ccc0306e1e6b227b0f961aa9afcad59d4ee1737f980dc876609c59a4c6a3506f987467beba0764b857000000000000000000000000000000000012ce5883156588cfe0f4838f819f985b09f1eab40a5ea8e30fc5d70d029a01a4537641248f4c21dd203909e0170737c80000000000000000000000000000000002888eb9778a4045feb5899dda258657b9f41345731ba630fbbf186b3be4b58ffc7f48abb65b693b573a73f85440a7a70000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc0",
+ "Expected": "000000000000000000000000000000000e1ef3003fe3181f690224cbc7008856e1251430ce3cff56a1965c89a892604398f5101d1bec7ff1590b0cc3d23b854600000000000000000000000000000000185b4d4b5fd8313c31542bd1bac034046ddc705b41a034a00570181503a6ea4c2d808bba0478900064270fadf3d655920000000000000000000000000000000005bed63ab9898b89f92027c04ba256569e6285c851753e12760129c98899bcbab34b62172906a1ea4cb056d4d0a5717c000000000000000000000000000000000961129a3e212c7412018d7407d7ad16412feba8c138f4f6ba69daa1a25c6b23f3466bfde6f5f0d09ab67248a2abdc68",
+ "Name": "matter_g2_add_93",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000051982b46a819c74105cb36da871fb2415328a1531d155856f6551bd043eca62ddb61f24af429edda830fda31e22cd340000000000000000000000000000000006449e5bcdb5619aac542f6633ee3e06a4fd56a3e1ce4034efc608131ff6ead70ca63e70f494f519d5c577ae7119c8c200000000000000000000000000000000153f4f5dddd5801fbf7f88a735b9170d24d5b63861d50cde9644579dcff277cdb0d5fbfc3b3b819a1172de05afb9135b0000000000000000000000000000000010fdea84983fe6c08cdc4b4ccd462bae2ba791ab5209363b10b3ef342c9a5e92184e9d8be1419e3d88402bc05bad5fa2000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc01204",
+ "Expected": "0000000000000000000000000000000001504c47ab0c410b32d5f1fe3d3996dbf1b21c5ef5aa3a2862a9d561b419f818f0b32b8e931c65fffc393ce7beec70ee000000000000000000000000000000000217e9fddd2551a171a13183ae3aba6bc5ce99e8f3587b92a7cffc738b478d8293b8c71989cabf9a55c5f5077249345d0000000000000000000000000000000003874de865d93650a95af4e153fe557c45bfdc4837bd6e209b8f05ad12b8fdee6432675cd92fd739b7e98e56e7ef16b60000000000000000000000000000000011303c0c7ec1f434cdf07c110da5f0bcd85935c3a0ce9fdf5546ca61edbc2d478562dbd9aa45a5f8d96e033feac2fdd6",
+ "Name": "matter_g2_add_94",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009b011f793d9a939d916d058ffe91b58138820a646cc450389b3074ae3715d06ddec1075afecda71c65c7ca085210c740000000000000000000000000000000003d4d20f4b93c1e90a0a06bd534d8b4fd64e4c4aba77ae42cf4c5b2bd95f8b02ec4069ea246ff46404e6c9eac632fbac00000000000000000000000000000000051e88c3adfd4d6a02d3f03812362a6cfba3a6c69b9aeef75b51106cc7f1750293d61e31f0ea29b5d7aa56debb6d2aff00000000000000000000000000000000086d9c4ea6769cdf49ffbbf7351023b4aea640e8c90f9291222fd0b5984bca4d481bf7e10df921406a34804e6a09f99d000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6",
+ "Expected": "00000000000000000000000000000000101ed22b16502de0d83303134a97db17ce956faedf47256a9ac86004bcd3ed112a71328a58f98a85977a7f22eb1352c3000000000000000000000000000000000e841a88d10493f301af54c5fe07a31ef90de106a6c87d5631b6967fd017f561a56176a5f3544dbb34b9f94040ebd2770000000000000000000000000000000001bde3c0076f26973651cedd3da97c7eda24451bda856026d1e22d3b65c66a3fcbfbf506b4b664b5fc06fca2d712d8a8000000000000000000000000000000000ce553ee3b7d5389798cdc5af8569aaf477b5b74ca1138454dc61badcf3ecf5e0ee8457e374b5735d0b8408b04fdbcdd",
+ "Name": "matter_g2_add_95",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010d48bf523f3909cf90aa58a9517ef5421f1212accd5e8a0f830aeb15a587e215ca9c340bb846b1d0474e43840b2af79000000000000000000000000000000000cc1a3976caf97b9d59f448f6d9f413eef8904f360c0cf912fe942b38d7fcc637a17038973a133608ae769d3e389b18a00000000000000000000000000000000069a6122c6f0ec68834b7617c755a7eb33a80a25acf95859da5ff03316447182f122d20d993b04e79b6fe859b7adf5a8000000000000000000000000000000000058c6f8c297524319bae6722e0a957d1ba0f75ee3a8aaf06148641c67925d15780e419a38ed7e07410e82769da74f2d00000000000000000000000000000000030dfbb89bbe5c14a7a55e68edc4fc38eaee9fb539a6b2f941264c7dc295da5712b0af0f2bbcdb74f785dc9ba038b0aa00000000000000000000000000000000132b4e02fda605a69251a4a6289c47536f9735dd90908ed1fb619b3ab808b3a1f1ca3fcc8f4b35c9864ae311c15747f80000000000000000000000000000000005858ece0bb09e55e012450551025ad2a6d93a15d29619433742851a62d987e7f8bfa6c6faed76493a27060ef5f51805000000000000000000000000000000000dd6b393e6d1b8d546e3f5ce69bc1737399e6ababc628f25734030e10d82b5e9370edfb5da15566d80e23d2fbf8aad5f",
+ "Expected": "00000000000000000000000000000000182f90f5d3ce3f5ff2d91430376144583247def83b3e83524094d57c0f1be98b1c4946964deccc25fc303d6450edfbac000000000000000000000000000000001844806f711735c5ca18ca48e559a9e327b87b91d22a5ef161da7874668130e21a9499728fbc2c88366bdb59f8ced0cf000000000000000000000000000000000815e7cff14b4ceaf26d1cda5c267f432fad294b6baa239b65d886ffb039321f9e24330ae738a35298c6d1ec1ce1c95f000000000000000000000000000000001188a4a2f0920ddeccde1a47a0636aa7c404fd77fb9c828e4fdb5406df80ee6c258c2d4a89dae5e2a2b05210df9100d7",
+ "Name": "matter_g2_add_96",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000156ca5e80be8c8c03a5506ce9abd22a9d4958c372678c0caf6f1329898507dfcb1f06a9464cf080bc6881fa5b7df1ebe00000000000000000000000000000000088174d486b4086b931010da298a399e15b60a113e08f571e096d3a4e94b57b3a684711318796eeca9319119b201abb30000000000000000000000000000000000b96ff68505c088cc03a1c2dc363b05bc8544728a12b29569bed137780523123eb17e68f4632383c252d81bca0c5ca9000000000000000000000000000000000486fc6e5224c5fad56234c41856e60bee4a6c1046f673bf7d5c1bbb603b141fc91074da5f9d3d41b796a2ebcebd9e740000000000000000000000000000000017032b16be8656cf23bfe0abc8c9e6aade223fa9bea6fe25f95a025da79cea6adf38536eae3859b25ad1af1756b639cd0000000000000000000000000000000010975ed27cefbb43bafad0fd14c87ada8e84525e1d199fdf1e77caa0b718214b33e547a42a040ee3bfd51621a20d22fd00000000000000000000000000000000133d29aa41f92de37523d281eebfe91103f017e5fb390f6bad9a2a4419fa4702bfa04847edbca1da96eb1ad563a92c8a00000000000000000000000000000000014af850de7e800ebee4be1a33c7e3b30aa94106db7defa148568ca3c8d82edc97ab5769ac40162d3728687cdac201a5",
+ "Expected": "000000000000000000000000000000000cf42f2ccff2e0cdda7e5f1d7652680650b4afa523c8f9a554ec18b905c837a189fff73982cbccf903ea492ea902b87f000000000000000000000000000000000d38219770f669557cdb623f2476b5f3f7478422b016123bf86a17bf75848548d1a1ce96a292637b8d52481321d80fbe00000000000000000000000000000000170d8722b824e3291b570ba8e4f9279c1dccdefb95cb5b7a94d27ad8a93513737f12d18ef3153c4e12b530bc457af34100000000000000000000000000000000021aee9e5f578328caee3177a4e08303c3b5533e288dcb75f94992db3520a6da16f4201e60367240b29c48d175942cef",
+ "Name": "matter_g2_add_97",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000121fe97c62e068988ebff21d8129d52aa903afdbb62862c7fd99564d9ad72182ab1f3a1100223ae486cd76f6938e123f000000000000000000000000000000000968ddedb04f52140160061828b5f88dfd09aaf37df625ee6f66b9500d6608df31c7edf86296eccf8f9918b051a5e4df000000000000000000000000000000000b7491cb8f6252e3861d7160feb0afdd736d27886863ec0909a7cc711a9b71aace18b17a00a2999dd57ca1a74f148516000000000000000000000000000000000fdb280093ef45b12b694ca3390a865ee18e4c04b231e2c98cc28706d4cefaf4e654582ee03f34ecf1dfa9674489d55300000000000000000000000000000000185aefe71f24281e5b03dd41e6d6d45fbc8975beb175118de7568bff0a9ccf917e9df97dc26bca16e8da06b0e9a8e7bb000000000000000000000000000000000015b326d401b827fdf556e4a24a3dd6c8036b1c849751b5ae3c3728cad88f931b06e3a345523a723481193f7afeb67800000000000000000000000000000000054ca16b4c87293002c31e64ad303e8f040e11de8b45c5fb9aca9dbec59b29dfda8532a8ef5ae6a92ac8ea90ee4303e0000000000000000000000000000000000b65a233a7731366cf24c801724265215a8626b1290d86c60bf1e74b021b0b44d7d6552f936fac7b5e60cf1feaa1d82f",
+ "Expected": "0000000000000000000000000000000010d1b2f595166929347e06c1debefead06334f554dc31f320cb844abdb1810b5f7c4b933ff8072dc03d303f4a6d0d09b0000000000000000000000000000000013ab41dfca0a7cb0c58c2c19e02f675a94d9e73312cfe2999dbac34e6a80bff9472506b48690f24ad3171ad495f445420000000000000000000000000000000015bfd0db53fd4da538caa3aee7a90a669cb84460365696ee79b190d09a6d4c3f08965de7fff4efeae435db52b97d213b000000000000000000000000000000000182ffc4304b911b47b092ab678edd63ed5f5e8a9069daf9247f3bf9c0dd149cc9992728a13b0a236fc9b37714b35882",
+ "Name": "matter_g2_add_98",
+ "Gas": 4500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010d001a09cf5dc3276482185f26ef3f75d28cd6d2667eb08a7fe06c03b99f3b6c4d82390739b6867a314291cc642a8b2000000000000000000000000000000000587846a460b1f37c2e7f491f9a097b4e86e1943d9cd0999313f65627b3907f09b5d5ac1be376a313a959dd136f7e9b3000000000000000000000000000000000af439695556e86b102926d3b40e3e54cc84464e120de3b4e3c5541a6a5bca44151fb0594009663764c1824518b13f020000000000000000000000000000000003bfd9418c1e57269e222152d321b83ae090f216cb422956dd1fcc464f68526cb4a05cdaefc7bbe6e81d4ffe27d64db400000000000000000000000000000000085dd8bfc00ba517dc8d7ddb49d711d35bd36f9fe3843689019e779624a032d2f023533b8184b73042d1a1953d2885e50000000000000000000000000000000009ba8d5d36e6efe02097a3206bbed68529f0cb9875ab81deafd886d9243bfec8b403d2abe713a2ec929b93305dd2da220000000000000000000000000000000007f8f90ebb2771136a92023901ca85e87fb7c8b1a40f88ae564a124bdd0ff0bc27ea98612a817e2c871fb4bcea3bb06600000000000000000000000000000000152de417d02f1d14e5899201db8fd5db8ecb40ea8d415dcdedce8ac70c28d851db68e9aef94506a50ec28145547a2d68",
+ "Expected": "0000000000000000000000000000000017555399f979745302f08210de5311a6401b6b181100b3bc6b6d450f0f62079d2f02d7badcb164f50dfc46a975cbd6720000000000000000000000000000000014aea86c06e4c1fbf0711a8cfced2544c7624abc7ae7906cd992bdf575a702540c45c2117e221446ba09960cbc9048ac0000000000000000000000000000000002fac56960c4989a84e02ce36e8970c2e847ee45579d31ca77f042bf96505af574af822da084ae64b22ff876610ba9a5000000000000000000000000000000000a481cfea2aef8975c80a297ce5a185dacd25649d41f8466d3c63d786e3c264a8e4ccab5ef6b80ab1260e86ab6d5b3f3",
+ "Name": "matter_g2_add_99",
+ "Gas": 4500,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsG2Mul.json b/x/evm/core/vm/testdata/precompiles/blsG2Mul.json
new file mode 100644
index 00000000..886b0c6a
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsG2Mul.json
@@ -0,0 +1,730 @@
+[
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g2mul_(0*g2=inf)",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g2mul_(x*inf=inf)",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_g2mul_(1*g2=g2)",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000011",
+ "Expected": "000000000000000000000000000000000ef786ebdcda12e142a32f091307f2fedf52f6c36beb278b0007a03ad81bf9fee3710a04928e43e541d02c9be44722e8000000000000000000000000000000000d05ceb0be53d2624a796a7a033aec59d9463c18d672c451ec4f2e679daef882cab7d8dd88789065156a1340ca9d426500000000000000000000000000000000118ed350274bc45e63eaaa4b8ddf119b3bf38418b5b9748597edfc456d9bc3e864ec7283426e840fd29fa84e7d89c934000000000000000000000000000000001594b866a28946b6d444bf0481558812769ea3222f5dfc961ca33e78e0ea62ee8ba63fd1ece9cc3e315abfa96d536944",
+ "Name": "bls_g2mul_(17*g2)",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000039b10ccd664da6f273ea134bb55ee48f09ba585a7e2bb95b5aec610631ac49810d5d616f67ba0147e6d1be476ea220e0000000000000000000000000000000000fbcdff4e48e07d1f73ec42fe7eb026f5c30407cfd2f22bbbfe5b2a09e8a7bb4884178cb6afd1c95f80e646929d30040000000000000000000000000000000001ed3b0e71acb0adbf44643374edbf4405af87cfc0507db7e8978889c6c3afbe9754d1182e98ac3060d64994d31ef576000000000000000000000000000000001681a2bf65b83be5a2ca50430949b6e2a099977482e9405b593f34d2ed877a3f0d1bddc37d0cec4d59d7df74b2b8f2dfb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e",
+ "Expected": "0000000000000000000000000000000006334ba1e361fd94bbd98f44b75ae9ec00ecb4d3467b5528870b1a1fa9a7d04449f12af90bd4c7a1e3f29e717d6d19d3000000000000000000000000000000000bf4cc1626393956915845ea7ca43d30a59c7196fbe309f2d5ee6de7e40c191d29821dd6aae46abecf634b904de8f7490000000000000000000000000000000014aeb09e252cc74610ab956057d4ac5af95cbea8a6baba9e5062643dc037d6841044cb38b22d7dfb978fe0b58f94cc3a0000000000000000000000000000000000fdcd73452fc1ced1c06e6271410a48dea05afbe889a692905e1baab8d72418c62531aab8b74842b51016f0a9cbb93d",
+ "Name": "matter_g2_mul_0",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d93884d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d",
+ "Expected": "0000000000000000000000000000000010e70bef8eb893377e7ff92168d7acef11c9efab990fbded728b173b94e1d99e471a8357f16625d353287086543551850000000000000000000000000000000014043c1f00221c439e5febd12724a9224bccf0389914461644daf329208e869b1bf149880dccebccd440b1748d15e944000000000000000000000000000000000f7dee1e7d122e410b29a9eb011ee700c2f230cf8f611e196ec66e153c1fc331175532a8f9b060b573bddaa705430c2e000000000000000000000000000000000e1f659470eab7c0741bc8777ac9fc8dcd11a6f1b30ffb4265e96b879e795a4dbf851d1149429dcab95464e89f334627",
+ "Name": "matter_g2_mul_1",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003632695b09dbf86163909d2bb25995b36ad1d137cf252860fd4bb6c95749e19eb0c1383e9d2f93f2791cb0cf6c8ed9d000000000000000000000000000000001688a855609b0bbff4452d146396558ff18777f329fd4f76a96859dabfc6a6f6977c2496280dbe3b1f8923990c1d6407000000000000000000000000000000000c8567fee05d05af279adc67179468a29d7520b067dbb348ee315a99504f70a206538b81a457cce855f4851ad48b7e80000000000000000000000000000000001238dcdfa80ea46e1500026ea5feadb421de4409f4992ffbf5ae59fa67fd82f38452642a50261b849e74b4a33eed70cc973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be1",
+ "Expected": "00000000000000000000000000000000119a5147fe9ddca7123f721b5662c1a44b0964c37a214cdf3a4fd34166e3b25210344e65220c38ec84d0e3b5ccc7e46d000000000000000000000000000000001642dad5dacf4295b871fe9b2787f0861f158807b2b6c01c2dce12ab053c9472bd3cb98de5dc33f40053ff45ce5c9af40000000000000000000000000000000005bb5761602b6639f2ecaf79f2d1f853fbdf75f4b3852b90808b858993a83f8a0da8a2ce7072aa91e3b6b3ffd0b3d1e20000000000000000000000000000000000a75143b9551d4ae41fb8bd71fdba7826b994c65904d9189a5ac5130a59cbb9d8dee0e016735565148fc49823d3969e",
+ "Name": "matter_g2_mul_2",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000149704960cccf9d5ea414c73871e896b1d4cf0a946b0db72f5f2c5df98d2ec4f3adbbc14c78047961bc9620cb6cfb5900000000000000000000000000000000140c5d25e534fb1bfdc19ba4cecaabe619f6e0cd3d60b0f17dafd7bcd27b286d4f4477d00c5e1af22ee1a0c67fbf177c00000000000000000000000000000000029a1727041590b8459890de736df15c00d80ab007c3aee692ddcdf75790c9806d198e9f4502bec2f0a623491c3f877d0000000000000000000000000000000008a94c98baa9409151030d4fae2bd4a64c6f11ea3c99b9661fdaed226b9a7c2a7d609be34afda5d18b8911b6e015bf494c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a",
+ "Expected": "0000000000000000000000000000000017ebc9446f8c8e17dfeddab9188d0c808565da29c0bdbbc4138a44ca3196c4564853be28286b66660cda36832d6940010000000000000000000000000000000007f29a9583b4ae83d3913dcd72590a3f20f39eb5a6d36663c1ef433058e76550085b9c01bf797d98d0eef45cc22ff8c50000000000000000000000000000000016eeaeb123b12d1913ff1e50f974228c79f2b995609d2e3835c8e1d68773b0cd484df57b86111cdb75de1e19eaf062e500000000000000000000000000000000002f5688c1286aed42309896bd65d1826dc64dda615238fa9043669806968b8e0e1e3e77ef192b7df540aaf0ed282a9a",
+ "Name": "matter_g2_mul_3",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001156d478661337478ab0cbc877a99d9e4d9824a2b3f605d41404d6b557b3ffabbf42635b0bbcb854cf9ed8b8637561a8000000000000000000000000000000001147ed317d5642e699787a7b47e6795c9a8943a34a694007e44f8654ba96390cf19f010dcf695e22c21874022c6ce291000000000000000000000000000000000c6dccdf920fd5e7fae284115511952633744c6ad94120d9cae6acda8a7c23c48bd912cba6c38de5159587e1e6cad519000000000000000000000000000000001944227d462bc2e5dcc6f6db0f83dad411ba8895262836f975b2b91e06fd0e2138862162acc04e9e65050b34ccbd1a4e8964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b89",
+ "Expected": "00000000000000000000000000000000042d0c1941ae0ed5e8787437ad5e2753bba02185317848e8ec2e425ac954e0efb1bca534725adfe87e8507851ee337af0000000000000000000000000000000002db55ae8126cbe86327aab880381a81205e33a351d172c883b9cc184799866a8db5a6b4321496e05d3ef62d00416d9a0000000000000000000000000000000012c45444403dd62d7be3e7658dd85909204751dd7d085f6edd38c0aa9185d3c32407d8c95bba371b380f788d0dc48e0900000000000000000000000000000000111421c6dd0db595ab731adfb4bc76c84a61197cb023b6f17e7176c443f20a4b6f8cd0a00cfa61e831ed20b3c6a84d98",
+ "Name": "matter_g2_mul_4",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019c31e3ab8cc9c920aa8f56371f133b6cb8d7b0b74b23c0c7201aca79e5ae69dc01f1f74d2492dcb081895b17d106b4e000000000000000000000000000000001789b0d371bd63077ccde3dbbebf3531368feb775bced187fb31cc6821481664600978e323ff21085b8c08e0f21daf72000000000000000000000000000000000009eacfe8f4a2a9bae6573424d07f42bd6af8a9d55f71476a7e3c7a4b2b898550c1e72ec13afd4eff22421a03af1d31000000000000000000000000000000000410bd4ea74dcfa33f2976aa1b571c67cbb596ab10f76a8aaf4548f1097e55b3373bff02683f806cb84e1e0e877819e2787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c944",
+ "Expected": "000000000000000000000000000000000ccdb2a0b670f199a9b61198e6a2ce2117075733e6a1568c53ca493dc3674c6ae85be2491d2ed983f52e2c7040824afc0000000000000000000000000000000004f52450d7e041c561c00200d5b142b32f2df2e2156e4f6c15d6c00e185e135037a1ed6be15e2ed920daa00e2f9bc8da000000000000000000000000000000000f39c38c18f03ce6baf1d016cf32d7387269940280f2e8d21db4da33dbd2d24ebb93ae3dff9f79b015eee25813d677c700000000000000000000000000000000189df61f7f1025fa6fdd0a4708ff1d53db7d414019c4828de2520af3d36776062350061c2261e46e746a6475fdeccb2b",
+ "Name": "matter_g2_mul_5",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000147f09986691f2e57073378e8bfd58804241eed7934f6adfe6d0a6bac4da0b738495778a303e52113e1c80e698476d50000000000000000000000000000000000762348b84c92a8ca6de319cf1f8f11db296a71b90fe13e1e4bcd25903829c00a5d2ad4b1c8d98c37eaad7e042ab023d0000000000000000000000000000000011d1d94530d4a2daf0e902a5c3382cd135938557f94b04bccea5e16ea089c5e020e13524c854a316662bd68784fe31f300000000000000000000000000000000070828522bec75b6a492fd9bca7b54dac6fbbf4f0bc3179d312bb65c647439e3868e4d5b21af5a64c93aeee8a9b7e46eaaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e1",
+ "Expected": "000000000000000000000000000000001388a59c57ec8ca5e68b99631abdafca1b71352ac35003a55bbc415b48b8171857adda31123ec86a6ed9e1060d56aa67000000000000000000000000000000001471913b1ab5bcf9336665d3d44232b4e58da70285b7b8eb1dfd7c54442afb28c339f56e6389f89b84db0879e1ee058300000000000000000000000000000000022101b4de40b7180ea17bb36bad0a668a8def3e7361a96fbfabcfc4cdbe6f607ee4ee80d0eb2418b848ad056520092900000000000000000000000000000000103cda694792af5a51e04b6422600a0ea6f50808ca54423cd4f59dfba633daa5afea49c85b900f52e182610efb62fe7d",
+ "Name": "matter_g2_mul_6",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000690a0869204c8dced5ba0ce13554b2703a3f18afb8fa8fa1c457d79c58fdc25471ae85bafad52e506fc1917fc3becff0000000000000000000000000000000010f7dbb16f8571ede1cec79e3f9ea03ae6468d7285984713f19607f5cab902b9a6b7cbcfd900be5c2e407cc093ea0e6700000000000000000000000000000000151caf87968433cb1f85fc1854c57049be22c26497a86bfbd66a2b3af121d894dba8004a17c6ff96a5843c2719fa32d10000000000000000000000000000000011f0270f2b039409f70392879bcc2c67c836c100cf9883d3dc48d7adbcd52037d270539e863a951acd47ecaa1ca4db12dac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c",
+ "Expected": "000000000000000000000000000000000cf5cb957a752ce9187940f63b13080790348814debf84b91e74fd6e822c2735941d61d50d492439475bb3ea7aa849ec00000000000000000000000000000000012e546ff33dee9875510a68301f46d89e6175f5cd9a6e179fb8599a580e9478fb8d92038982551dd29041d8185c7474000000000000000000000000000000000d52fb57bf2996dbbacdbcb4088df38e77e25598b91bcd5e41eaa27b1398eac150586b142f068d5b498e0ce458d3e8950000000000000000000000000000000012295e1d1039abe7a5fea51a04a34e9e8d44a0f24b8c032680703c119d54274d3bc2e548854021ab027b693e43964314",
+ "Name": "matter_g2_mul_7",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017fae043c8fd4c520a90d4a6bd95f5b0484acc279b899e7b1d8f7f7831cc6ba37cd5965c4dc674768f5805842d433af30000000000000000000000000000000008ddd7b41b8fa4d29fb931830f29b46f4015ec202d51cb969d7c832aafc0995c875cd45eff4a083e2d5ecb5ad185b64f0000000000000000000000000000000015d384ab7e52420b83a69827257cb52b00f0199ed2240a142812b46cf67e92b99942ac59fb9f9efd7dd822f5a36c799f00000000000000000000000000000000074b3a16a9cc4be9da0ac8e2e7003d9c1ec89244d2c33441b31af76716cce439f805843a9a44701203231efdca551d5bbb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd108",
+ "Expected": "0000000000000000000000000000000008e4c57309339400ac9b6b5df16972c272d47cf69ba7baf89afa4f4e72703999c5885253cc35686f6c8d277399da2a390000000000000000000000000000000018ad4e1f105f16b0dbb4eb089c51e709c25e407e54b64346224b1abbe15d62fabb231e36a69eb05a9ba7860f772634200000000000000000000000000000000019994d20a7ecc0f234ccb6b1793fa7d1ece64b3e157c579fb05a8c6cfcdd6f5456ac1f4c1beadb69206988ab543bb8bb000000000000000000000000000000000d435e74bed382442ab83ec90dffb91336137932524bfcf9753fa5ddfe038d0b98a045c8ec9deb53172e5662d3fd67e6",
+ "Name": "matter_g2_mul_8",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e25365988664e8b6ade2e5a40da49c11ff1e084cc0f8dca51f0d0578555d39e3617c8cadb2abc2633b28c5895ab0a9e00000000000000000000000000000000169f5fd768152169c403475dee475576fd2cc3788179453b0039ff3cb1b7a5a0fff8f82d03f56e65cad579218486c3b600000000000000000000000000000000087ccd7f92032febc1f75c7115111ede4acbb2e429cbccf3959524d0b79c449d431ff65485e1aecb442b53fec80ecb4000000000000000000000000000000000135d63f264360003b2eb28f126c6621a40088c6eb15acc4aea89d6068e9d5a47f842aa4b4300f5cda5cc5831edb81596fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f8187672",
+ "Expected": "000000000000000000000000000000001425890b6c46c5a07a79127de4ddbb751227dca4481ab7c2f601bf22b8f6a149767c73bfbf57ee399c0f2d0b12852a0a0000000000000000000000000000000012cce15f53fdfffb5f71de3567b0c0adea65b9321c85677c574787f7048c1bb5e2dc985b65fbc48115aa129e6000fe4100000000000000000000000000000000041398497f975289fb9fc6ffe671a19fdcd3753c82ffd3b2084574107bf7fadc8de462507f4484c32df39967c3751a480000000000000000000000000000000007514a7f246006e714d4a8cbb4e89d81b951b5c41a05bcf35f61283e888074fb3686fb6ecc1a66e491ea1e1ce0738102",
+ "Name": "matter_g2_mul_9",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000159da74f15e4c614b418997f81a1b8a3d9eb8dd80d94b5bad664bff271bb0f2d8f3c4ceb947dc6300d5003a2f7d7a829000000000000000000000000000000000cdd4d1d4666f385dd54052cf5c1966328403251bebb29f0d553a9a96b5ade350c8493270e9b5282d8a06f9fa8d7b1d900000000000000000000000000000000189f8d3c94fdaa72cc67a7f93d35f91e22206ff9e97eed9601196c28d45b69c802ae92bcbf582754717b0355e08d37c000000000000000000000000000000000054b0a282610f108fc7f6736b8c22c8778d082bf4b0d0abca5a228198eba6a868910dd5c5c440036968e977955054196b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea",
+ "Expected": "000000000000000000000000000000000b24adeb2ca184c9646cb39f45e0cf8711e10bf308ddae06519562b0af3b43be44c2fcb90622726f7446ed690551d30e00000000000000000000000000000000069467c3edc19416067f572c51740ba8e0e7380121ade98e38ce26d907a2bf3a4e82af2bd195b6c3b7c9b29218880531000000000000000000000000000000000eb8c90d0727511be53ffcb6f3b144c07983ed4b76d31ab003e45b37c7bc1066910f5e29f5adad5757af979dd0d8351d0000000000000000000000000000000004760f8d814189dcd893949797a3c4f56f2b60964bba3a4fc741e7ead05eb886787b2502fc64b20363eeba44e65d0ca0",
+ "Name": "matter_g2_mul_10",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f29b0d2b6e3466668e1328048e8dbc782c1111ab8cbe718c85d58ded992d97ca8ba20b9d048feb6ed0aa1b4139d02d3000000000000000000000000000000000d1f0dae940b99fbfc6e4a58480cac8c4e6b2fe33ce6f39c7ac1671046ce94d9e16cba2bb62c6749ef73d45bea21501a000000000000000000000000000000001902ccece1c0c763fd06934a76d1f2f056563ae6d8592bafd589cfebd6f057726fd908614ccd6518a21c66ecc2f78b660000000000000000000000000000000017f6b113f8872c3187d20b0c765d73b850b54244a719cf461fb318796c0b8f310b5490959f9d9187f99c8ed3e25e42a93b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c76",
+ "Expected": "00000000000000000000000000000000048ea2c854a0df7b10a2147db6eabcb16eba340644f737fc99663d1ef26d8ed688c2baaa7d7699c5f540d7605eb48485000000000000000000000000000000000c959efb835d48d3e7a8ce643764f27c365f6248a88e39092e3a6498f04ed851c55b796dacd62ae73d7edf23aa45fefc00000000000000000000000000000000114337b8caa68cea6f22a25c0ce3b247cadae24c63fb02c6a98a728b54f97b12b1473c8e23f55338326b9575a637bb2e00000000000000000000000000000000033167b0668ec650581815cefab61d13661f4cbc6e01711af0aefb699e1979b551d0031c603ee5f6dd4f716ea7aa4a6e",
+ "Name": "matter_g2_mul_11",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000576b8cf1e69efdc277465c344cadf7f8cceffacbeca83821f3ff81717308b97f4ac046f1926e7c2eb42677d7afc257c000000000000000000000000000000000cc1524531e96f3c00e4250dd351aedb5a4c3184aff52ec8c13d470068f5967f3674fe173ee239933e67501a9decc6680000000000000000000000000000000001610cfcaea414c241b44cf6f3cc319dcb51d6b8de29c8a6869ff7c1ebb7b747d881e922b42e8fab96bde7cf23e8e4cd0000000000000000000000000000000017d4444dc8b6893b681cf10dac8169054f9d2f61d3dd5fd785ae7afa49d18ebbde9ce8dde5641adc6b38173173459836dd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c",
+ "Expected": "00000000000000000000000000000000142f6b71471f3665ee6269cf598fc3587a62523f9753eec48a2461a2e313e376828cf6d1a9ffc9e64353c8a668718736000000000000000000000000000000000153647cc4a5aeb8ea52f845c415651e167ace9f331c1d73eccbbe20a4014f9e1158c281495206de4b841839438a595500000000000000000000000000000000151d07c3f83217e63b332a6c47e91ef2418e9c658353f8b644f23266f5fbc727562f0935b4d892db947cfbd0757ed61500000000000000000000000000000000035bce4bd2d8261e21476c325cb68e581f20513eb5e0e6a0ddbfd4ac4674bc323590b6f52d0cd50010c13642e7e03daa",
+ "Name": "matter_g2_mul_12",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ca8f961f86ee6c46fc88fbbf721ba760186f13cd4cce743f19dc60a89fd985cb3feee34dcc4656735a326f515a729e400000000000000000000000000000000174baf466b809b1155d524050f7ee58c7c5cf728c674e0ce549f5551047a4479ca15bdf69b403b03fa74eb1b26bbff6c0000000000000000000000000000000000e8c8b587c171b1b292779abfef57202ed29e7fe94ade9634ec5a2b3b4692a4f3c15468e3f6418b144674be70780d5b000000000000000000000000000000001865e99cf97d88bdf56dae32314eb32295c39a1e755cd7d1478bea8520b9ff21c39b683b92ae15568420c390c42b123b7010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a",
+ "Expected": "0000000000000000000000000000000014e83f87e7f66d8ed880ca46a76a5d3bbbacf2dafe1ee055f04af568738f4c6ddf2a93e1810b616da6f64f25c35a7b5a0000000000000000000000000000000003d14447254b61168d36f92710f95f7100cc8f278b0bc9528da763a18a5386b3f5b83b96f4dc426e4b0fbe755bc986790000000000000000000000000000000017f1a79ed64abfe5e960fda02cf3330e6ef5612c1b8639386959f86c970adb797bf077a468273d37996a65685f75ac30000000000000000000000000000000000d973499a7bf7132541c0976bf2e9bb26a2b6cfa5bda720352fa7a180a6b8fe95befcc13de5a2efe58be934cf7d8e664",
+ "Name": "matter_g2_mul_13",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017eccd446f10018219a1bd111b8786cf9febd49f9e7e754e82dd155ead59b819f0f20e42f4635d5044ec5d550d847623000000000000000000000000000000000403969d2b8f914ff2ea3bf902782642e2c6157bd2a343acf60ff9125b48b558d990a74c6d4d6398e7a3cc2a16037346000000000000000000000000000000000bd45f61f142bd78619fb520715320eb5e6ebafa8b078ce796ba62fe1a549d5fb9df57e92d8d2795988eb6ae18cf9d9300000000000000000000000000000000097db1314e064b8e670ec286958f17065bce644cf240ab1b1b220504560d36a0b43fc18453ff3a2bb315e219965f5bd394c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a659054",
+ "Expected": "0000000000000000000000000000000018bb69dd6db0beb468242265c382de5ac342d465b5f72d4e5a24c67a48272d9a1f3af28e0bd3712e16a854c5d91c616b00000000000000000000000000000000072fbcc86b7dee9c2dc177dbabdbbbddb630c98ac3bf3737fd22f99e2b2b690175d9c5aa4b577f78c545dc6a5d2d03c900000000000000000000000000000000161c4218143ab1f0387f19bccdcd08f9caeb2d1331ca890741799ff1b40533076b6a96a910714176c770b25d2c17715300000000000000000000000000000000063098cd9d1eeb899724b40a2d10ac951ba0277db09aad639957f58541dd391fffadc5d97833bb9666b054e12debfa92",
+ "Name": "matter_g2_mul_14",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000018244ab39a716e252cbfb986c7958b371e29ea9190010d1f5e1cfdb6ce4822d4055c37cd411fc9a0c46d728f2c13ecf0000000000000000000000000000000001985d3c667c8d68c9adb92bdc7a8af959c17146544997d97116120a0f55366bd7ad7ffa28d93ee51222ff9222779675000000000000000000000000000000000c70fd4e3c8f2a451f83fb6c046431b38251b7bae44cf8d36df69a03e2d3ce6137498523fcf0bcf29b5d69e8f265e24d00000000000000000000000000000000047b9163a218f7654a72e0d7c651a2cf7fd95e9784a59e0bf119d081de6c0465d374a55fbc1eff9828c9fd29abf4c4bdb3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746",
+ "Expected": "000000000000000000000000000000000e43672f1bc25e7e0e64a3fd26cb246bdbd6fb5c9084afdc87c888634916e6a6cc9a351cc67a6ac77ab8e132ed6cbee3000000000000000000000000000000000dee9612527c8ee9c574a4c51f5d3504ccf1d5781b59c78ea15294332c6acfdcc7bc68853e70f1f72524c930e4c3d2eb0000000000000000000000000000000017eba629eb14a0636926275f1c2109318ce8818d8171c69fd371751b6de47bda5b00a0b0e3765d05bab7b8dea9add90900000000000000000000000000000000052f0a4cd9b91695e1e58ead1da1480fef08cecef63896aa51ab16da373b99b3b91767a374645ac5932d9c7fd21d4636",
+ "Name": "matter_g2_mul_15",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000eb3c91515d4a41209a73564741a8ccf901a624df9db22e195a5d02d24b7bc0a12756b15b8d006cb991a7e088eaef1000000000000000000000000000000000704ce8afc808b0161f6f61b22d990d713ae398779e6e74e9b5771daf006ce0bba3a8088edf75156f0e48b92ee8409b00000000000000000000000000000000018fe81e05aff0620f4bdbe4a715e015650497afab62921eba0ab86b649e5a2fd3d54041868928519f537e36448688a0d00000000000000000000000000000000162bd97161201ea3c26f8dd1204a9c6b61b762bdf573cb5d20b6b255f30208ca7d96aa47b46fb8c6bf0922075f1c1ca807f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf",
+ "Expected": "0000000000000000000000000000000019b7ea673dad96c8352870136ea262c9ed105550cb403eb1e64ad598b2145fe1b95e5d61f1b5a6ebec47568c67b68086000000000000000000000000000000000f06ff9bcf2ba284e705b12ef2311f1a9b867ed742ee0737567b5c878547b18394b82c2bb97e16586515728245692cef0000000000000000000000000000000019dfd2d8fc4f2c989c7e1016e147f336174c84d380bab992bf1adbffe96d93d4d2d1d1dacdba3adfaf283b184478229800000000000000000000000000000000068d230422006004cd88ab0dd46a84af3905c7a1d329446cc23c1c5adb401a86a9fa76aaf577f77c2678cd8de8685ed4",
+ "Name": "matter_g2_mul_16",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000135aee0e30fbcad798738c10d4aebcdf50c89ce516325f655fe763dce54ffedf94dd74168611e5ae879b5bf5598d62dc000000000000000000000000000000000c728e672cd8b3bf9341bca929c34118b566cd3a80452d7015bee9d5cdc001b1f5c678d4b2cc4f7cac353e7bf326ca1e0000000000000000000000000000000014809aa22e2051e463fba6d49fbb060d0c7f599a0fc5409d34e71f34817e7beb1251810ae6eee1848c60796fb8647dea00000000000000000000000000000000145a4de777d86025d50e12f9a6615ecb9bdd41489992d1b643dd9aa549acbc63b04b0bdfd14b6e45c70f165e9a8c91bebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da",
+ "Expected": "0000000000000000000000000000000015ffdd83355978ebfc386e13987effac0137ec628fff1667ede29cfcbd05e31cf8323959dd0247c20cf28978dc242c790000000000000000000000000000000016b1f810da2ae3c2ffbb6b83c47ef03eb0f298ff4c304ab0dd7b97207949d62858458d789c86c0cd474c34fa720ad3b70000000000000000000000000000000002a2e1463d5e795e6a25998a848b079363efc7d0337c3803385f4f17f11726b04108adfd87a811d709cbb6750c969526000000000000000000000000000000000289a3f472799c06a84bb1f377a36bad910220e1017884545159fe1b2505e8e7473882fcf324ba0d9125495bcbbc7226",
+ "Name": "matter_g2_mul_17",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000009a58b7116dbd6f550f8ca98071813130ecaa9ea86d5275eebc36860690fa048c9ebeb46600b2b63e847bff3e38ed0d00000000000000000000000000000000113ffc0932c041e0e34b2540c485eb74f5029b339cb60bc88a8a749310f33f330dea137e5f340044fd689264af66696d0000000000000000000000000000000002642da3c2c7b6688aba0b19ab29ac72e35caafa044863c364ea8833fca850289de52c0963bc33d7bba40cb5f568718a000000000000000000000000000000000552d35ca054da2f148c119454f6760607b351f2441921a2be17da2cc10902d71571c5554f132e60df79679428fa07e3e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed833",
+ "Expected": "000000000000000000000000000000000b02ddcfbf391a2d6953261c786945093b09377352473a86cfac6456a811233809434b566b9301eea3105eb86922efcc0000000000000000000000000000000015430deba91113b841303120f0738012d77207e9408474998df5e68d0d61f1a64afb947ff93116ae766ca5325046e263000000000000000000000000000000000ab7094055919f6f707b458cda552f25104d95e4ec8d020ea4c17ac1d7efef5c4c3a769120718f1d5171eb8630a3018200000000000000000000000000000000161e7209f8c98e511a698fbf01735798cb632ae1afe00870654ffa0ba93a549edf4b97d60f03974ab0964cd39298401f",
+ "Name": "matter_g2_mul_18",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018fbbcba3d4b1e548ceaec4a48db62a2420ff29a67af332ee7ea3f902f84e6c375fd33abc33d945c5bca25603979f9a400000000000000000000000000000000072ff416994364bdc6535f36c82212afa822cd94fade69f11eb38dbdcd37c7e22af55fe05e6a826dad822073656eaac10000000000000000000000000000000017bba179b847278a4878b6faeaab3b1f4bd7540d22817cd9aff95557497f8b9d286657b6162c0f89f7820becc637dd550000000000000000000000000000000018e2bfed71aa9b11fefca2f0db8bd9b8c69540267de50bec4fc90a6e9741891465c9761d19282e1100b3707eeb598b31d411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f",
+ "Expected": "0000000000000000000000000000000006cb218607a1f66ce361c89fd20edc3f00421611adc9aa52ec35d45e023174962c863f740ac36c984c2b466cfc4827a900000000000000000000000000000000152b22d46e9660da8b1be4c5b14da613731e750ff7eebaf879f7074bf3c33e1528a2c8479e0178707e3855b49f85f045000000000000000000000000000000000c928cf78cee2c8b9da8215d33d189c5636df1e8e9bdaf143aba7ed40f29490ca2328b4a20cfc56f62e4ce49d9e77f14000000000000000000000000000000001574b7a9c3931933160ad4eb17400b6297210db47bca034bc1b5d17a0cb8c41834636b9123e625e5eb0b01738cd6b9af",
+ "Name": "matter_g2_mul_19",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019efd37727dfaedf697fcda7a59847dbda8ca7cdc92f34e68691d682e20ae6545ac104d6660fdb8f64a051e69298eae8000000000000000000000000000000001225ace0fdce456dd888c9672503b68ef77b2d11caf1265a767a6ea14911e3ca03fc153f18dfe9d95e0cc68b7b8a3a8d0000000000000000000000000000000008a6b059c1c4da046cc0b1b5d7f33270aceffa607daf6d0d078c06f940604e1a0b4adf01a4091306e3c7eddcf3d95101000000000000000000000000000000000f79bae5260a2f114ffbb9273f3049d3ebb002500a57ee0a7d157d86957f43f87a2e026fb9892dacaadca5ee04fc8e176bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc",
+ "Expected": "0000000000000000000000000000000003e17452a80996203fdc4037db072c452f9eb2dae689c77c88b299d7ba266d111ab2b9c4b24149968d72cd143a34fc4e0000000000000000000000000000000014a057d7a50c9b0f34712ff8008770080bfa671650fef43c82726257da180dfb9672b266d4c54d65fdc677d917e6c5b80000000000000000000000000000000013b452c980bfc4a484637b578be100753aee9dda9487d5ee5c017c689dda838fc673804369328192d780d60a9a3de0f700000000000000000000000000000000103aa86d1807de242a6d4fa4a49be6c91cd757df5808501acfca44940733c6a524b851ac962b99a9be41bfc8d6254478",
+ "Name": "matter_g2_mul_20",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016d2b73eeceee17d3bff3aacac9df9ac1c4248d9ea7d6a503a757f7bb22fa6970bb6f5cb5ec154785f7252e1508b382e00000000000000000000000000000000081edc68bbd8db7b10be06ee23d090bd54f9ca07ef24dfed7df7bb05f8cc26e6889dbd40ea203fd5cca5cb588199f9e40000000000000000000000000000000010d3478508619ea9493b4330e2fb9150024cd32dc1378f824788a884a4a30fbf39c630f465557bf0c6d69b4cbecf89f9000000000000000000000000000000000f20c9b134db5d8b7756800c031bf5962fc560ba95d4bd9157b16179f1a37ae08696a2be455ad8d018aead6adcc69b712a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c52",
+ "Expected": "0000000000000000000000000000000007c616472f9ac60f749979c6f870b587425d514395ed07558ed287fccabc77f0c90872f3885d0780bcdfffedd124eb3d0000000000000000000000000000000019531e9c25e84a2a968a85d9f1ab61a372ebc59ba5bb7a2bbb3c0d6e4c9d04061b28fdc719735e97ccd5f7243a58cdc70000000000000000000000000000000007772d3cff12bbee916a6569edce0c6dbc2bd8a794919a4dd7bc37024c8273245210511b8f6da551fe626b7b840833f300000000000000000000000000000000186a3e858a83a7ea1bfdaac65c2df1076059aaa193961559792373886c68acd2f9fca61b166a0ee55084a6ea122ec3e8",
+ "Name": "matter_g2_mul_21",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003dce67181d23af9729e9fb0653d7f79c890fba27de42fada93123e112c4a468fa889921192db8047d86e4db77c60266000000000000000000000000000000000869a1e39d42d9bb0cc0568fdad16abbdac3194af893ebd8dd8f8c2c3c855abefa5fc215412168acadc88e658e83f5570000000000000000000000000000000001ef139a75194f3c4b1378c2b66dd304d179460bac0a289405cd8faa3ff66a7b6e54eb7b8742a68150b1e098630135c40000000000000000000000000000000003892b5a645af916be2c6c7fc0bb08fb5f39341d3c68598940554e1be11e1be75af920db0c8710ed13c78edbf683f17d0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b1",
+ "Expected": "0000000000000000000000000000000008adebaa95d10b9fc0f1a1f0d52dd6741517d2ba23e3f9e7a9221039684ae226ea602dbb50df0efd44b2b5bf7495c0b50000000000000000000000000000000008e276e78ead2473602d37cb9f2f589f9c60514a1fc5c215acf487bf57c935467d29945d3d671b41a8e47c9495dbf5c9000000000000000000000000000000000fab06240cb8cbe9afcc4ebebde50c2881e4bc4d4f2ed09a1065e3620e6344fb3c5f3019250ca4edaeae4902abb7400d0000000000000000000000000000000003fa6c48ead374be1dd45c8417ca8234c15ddefc5039151e6cd7fb27f866e134cef2f59ac9b2ec1b26896eaec9213549",
+ "Name": "matter_g2_mul_22",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000264dd4b477f5db65edad28c7153ed919a863c5c5661e0125c5429b323e055fd69c33142dfc6ed9c87082e2be4675e1f00000000000000000000000000000000046ea088a2ec94d3a1f1f97949f1ebc49690c453d316cc46534fa253b34b30323b6071d147d64bb94e02fb4db07bb0c400000000000000000000000000000000013692a33bb1348486eec40a9e93a4ea3810c7b4d3188cd07e235a2c898aa87ee0d17682fd24f4d978f9fb028fd26e2900000000000000000000000000000000115f8b64c00cd5cd344a7b5edc0ef0bb85a3e8f0f9dfb28f8ffe12db3e0d222c2d45dcdba0fbdc161c5d558bc71aa0977064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e9",
+ "Expected": "000000000000000000000000000000001412bdb48546014adf3c4eac4dbe79ba700f90c8030b063828fb01be5977bd73107533a4e8030c8d9cbdde9bcf10649a00000000000000000000000000000000126d3e1006abfeddd810cb1e12c898cf5f543e414438e600ce4c94cd8dbd1e17c0f3b9831add397feda74362eeace6fb0000000000000000000000000000000005b3159638afa34f219513cbcbc51567b16fd5598b85e6ae0d232021133cec25a6269250df2ab7b5ace726e9e2fbf0b0000000000000000000000000000000000c35bfdd1c10e903da6d41e9afbe65b0cd66addd7893fde41dfda8e543a93938cdeab52cc9bbdbe61f93d651bd1c923d",
+ "Name": "matter_g2_mul_23",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000014c83d58d90db4821a0411fab45f83fbc05f7d0d7a67ce75da3ae568978d15f4c1886c6fa6086675c0045efb30d818400000000000000000000000000000000001e68691123451f4c3df6dae62c6a63855ec3597aae33a8a10ee274e902e9aab1460cc9c79726312df0ee0ce90c8d3c00000000000000000000000000000000018a39eb3e3c6c7fb8ee304e55d15e209afe2fe278dda93552a7b9f51fbd778da1502eb6775cbc3f832f8320fa0686240000000000000000000000000000000017c15910fad1ca5749aa82a5a2fa98b0ebb37e92912547fb1741f18c34e0d5fc3a307b928636c25f0320d71cb9d31062686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b",
+ "Expected": "000000000000000000000000000000000bcc781f144bc148687875789fd8c54dd820170984b6f8ae75855f7e45619c1d2ff85c330b7743e447b5fc831dce9277000000000000000000000000000000001409aaf3c94c9a6b5123c82a7f311af7c2f60e9b197d49fb5b010f84faff972151b383a83c106de43454f8097005f6c800000000000000000000000000000000064a91226da8b9cb587030f1f4afb0d422a51e4d55212f26c621abc06fc0c57a473a9be75518a5f4f9a7f8d4aaba69830000000000000000000000000000000002cf239343bb77865ceabfcc1fe34cc9be4a1ebc3a70f16f8b7cb84eed5843524f95673b01466d6cbb0d8d9dc00793e6",
+ "Name": "matter_g2_mul_24",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fa96d9fe01c18732e8d6454df9bb1f482c4b9add837ce9c354c72d49c2d44ec694674aaf0e6d6a095cab7ebb57ccd9a0000000000000000000000000000000001f8ffe3fb7e9e311e0f6949c07c26a0febb181e37b2268bb5e125fc3a100323740d1ebaa5e635dba3770fdc2ce4ee860000000000000000000000000000000012ac42095fdb677720ab3f14bf0afc55c95b43d28d922a5f8cb0bd841306b978751d24546e3a6474976961d0768f29e9000000000000000000000000000000000baf9804d99039c9fe966a696c64bdacc9673b0906b4deab108d34fbbaa3b0905d50892278570564017b96828c7e1ac93176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a6",
+ "Expected": "0000000000000000000000000000000006bbdabfe104b62d22e78bc8f3446a86cd5f10c4c5a54501140768b55a7e6940b9952c9a90a14d8fdc7c04600195cd6500000000000000000000000000000000172e718c926cd393bf303984518432693c304a2758174dabba303ff4c0289b5bf5376b61e8821abab322d53e88f71d480000000000000000000000000000000000a2f84fbdb5b05107a0a340e81b56ddf6d03c23848448f841dc44f07cbf8a575289cf6d53986f581fddb0f2d07e38d70000000000000000000000000000000005cbc10f143a9a1fe23f670a4c47d385f5c7069d8c46580322d6939122b2d39d185d6a8c2e51e88a1d40fd2e82d08b8f",
+ "Name": "matter_g2_mul_25",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014ce6d88a7c5c782562aa101550f1af487296adebd9dae8252698ba04fbd58b92e2216de6ffd474d5992f97d9f22800d000000000000000000000000000000000ce92a04f5c8a99ca0e93992448222519fc454bda5d1d8638a7bfde968386e4ba0dcd1da59cd81d4c4dca3e584be0275000000000000000000000000000000000cb570796f5c8f7b8aa02e76cb8e870d3365fe4dce5df07ec286a0a821f922b4003d5b69c0f1588206d9544013e268c400000000000000000000000000000000098056a033d9cdae86aac02de3a444471854b909680719154b44d4f55f30087294e39e57643c692d6da725b859239080d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36",
+ "Expected": "0000000000000000000000000000000011769e191fe258ffd1922295a9fe877ad5a52fde6e343730f8f5ec6cdcd584f8ed1dbe0f55b5dd81f5f78b7437f02abd000000000000000000000000000000001253689089e9192d10a45342214425de36740c120e49f596d24658941ce2b2ecfb50e879be0125e3d159088f88e234f10000000000000000000000000000000017b642d1b5a953f47fff8f0649263f16f41a0ec0397d5a81571174aeb85431c352e2bf6bafa6894d2e6cdb5eafff16d40000000000000000000000000000000017b3438d0ddbd2ace1e63802013b5bac00d31889dcb2d9653a6f6412d157aad2fc45267322a62129087380bec65ec169",
+ "Name": "matter_g2_mul_26",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001214aacb0a5e6b7a40369a83c07fa8cf1786ce7cbde2b5a501d9c1292532df7822d4fde10a31fc0cecce3a7cfe3311850000000000000000000000000000000004f9669d8fe4f884ae93b2505710e6e45b19b7aa5df8cdd811f09e547efc27d21024cba05e2dc9d057055f30ec72d9df000000000000000000000000000000000a852b821b31cd27eca19712a636aa05ef2cd82c36ac1c2ca240edc7d0172b42a72c42d3cba583a5b5129ac1c9486e270000000000000000000000000000000007bd8419e791a5cea04993509e91a980d3ae4987a5b322400b6e4a4f2b636891a1c7ba4de96b53426dd556532403d5a39915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc",
+ "Expected": "00000000000000000000000000000000089a07bf63b8029e0506393828d8593b94b73c750815552f9a3c74ef7470b5810bc27212ba02ca6fdcd97e1e28a52a1e00000000000000000000000000000000051a93291d4b912f0a594d45c0264a9073663a9ec75e6ee81e13e79383d96e9330bab845fd1e5163e5b28c41c4a854c40000000000000000000000000000000016610bf2b2006207046e489294a132937edbdf95caf508f0df3bf8502e641aab9c44903cde75cff3c1f86873e06cc58c0000000000000000000000000000000005d33669fd8a6256dc55f513bb93cce8bae62a593eb8903cb7d7902a7727efb8fb4bb2e5058441c30b99f146ff5394c3",
+ "Name": "matter_g2_mul_27",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005ef88bf38b2f998dec7302cde829076e6cf69df23aa0bf6bbb39fc0d3d8b5eafba74efb928b1de0eeb3d86ec82612300000000000000000000000000000000011f47e9583997b19c36616e4bf78d6ddd6d67937f493986250ff02aef6e6e7ff074559af2f20a5bf1d67158e4a199cdb000000000000000000000000000000000007777c8eb259a836e6459b7bdb642f878d869fdcb31b105d01f280938ef5377f2775874c099dcd394abe70f17d595b000000000000000000000000000000001607379d1cd34e2d0ed765a339b21433e9aa489609b92414c6b5a05d796085269c288d739717def9db3502e0550860165061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b208792",
+ "Expected": "0000000000000000000000000000000005aa23543088a9a833d773a71275e73fc3081e13c907b8a04a330df7d6c06618fe69e644e0ee55869e364d3561e40f300000000000000000000000000000000010eef9238d2c520f32243f07161f3e35b15fc949b9401baa1a9c5df7d50b2cb3bdd237747735b235862bb57322fd9d090000000000000000000000000000000012dcc16496c95e39ecfd8f0514b5ab2569d89826d957478cdecd4e827095034e974039b37e767a0f25bf057ed715aeb00000000000000000000000000000000000d0593865fd2172ebf1b94c7511ab7d433a276bf833515146adb6d79b6e09d7c18f4c7f4d3241c14d01a4ad0f31580f",
+ "Name": "matter_g2_mul_28",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d6e3068c082b68312141aa68f1540ea1415e93e7f1762b6f06ff408a9995542da1c727a13355c19f8f418a44de1a95d000000000000000000000000000000000dcfcf2ab12b1a0e521ab402aaa4d32ff649a5a97892eb6ad98487c3c73c35601c313b8130ad12e9098d16eed3bcc2e00000000000000000000000000000000013777b1eefa4af03dc44e4e054eb7a3a980a9c55644900b80346be84b970e1754d1f4ab771adc9249e4accf88a23fb400000000000000000000000000000000002f53b231f1209c6f8b52f99a78bc2147c951ac89b341495f4a60a6572985ce2bc823625099ec214bc9ceedb2deea3fff396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c",
+ "Expected": "0000000000000000000000000000000015785bae0c27680cca2097ab52306207a61ba9903723f574091ef5e57c2e871e076d7f46e6e39f65a01e183e7bd822f000000000000000000000000000000000071110a384248664db46f21d87b455a3ad3c43782c68304ce17f52cc8579fb2e3378995d6eb3b8c97665e5fb7de665fd0000000000000000000000000000000019153a01c2b3c5d481474a71e5c67f27fae3232a0c8f1655ddd4da6b4c79870bfb0b6beb4af8c54aaf7e9251ad41d639000000000000000000000000000000000c58375439a93e0763467c6a11dada3e579ec53a968c9b9c1a446cf3224ea0c89c9ec218a8b78de91fc12f087e722f94",
+ "Name": "matter_g2_mul_29",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000161c595d151a765c7dee03c9210414cdffab84b9078b4b98f9df09be5ec299b8f6322c692214f00ede97958f235c352b00000000000000000000000000000000106883e0937cb869e579b513bde8f61020fcf26be38f8b98eae3885cedec2e028970415fc653cf10e64727b7f6232e06000000000000000000000000000000000f351a82b733af31af453904874b7ca6252957a1ab51ec7f7b6fff85bbf3331f870a7e72a81594a9930859237e7a154d0000000000000000000000000000000012fcf20d1750901f2cfed64fd362f010ee64fafe9ddab406cc352b65829b929881a50514d53247d1cca7d6995d0bc9b2f0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa",
+ "Expected": "0000000000000000000000000000000004c7495c03fc3fb4d0fd4e0e660d6424de9e060eac72eee3608ba95bac294a3a62d246f42dcf3b575ee1cf8e20a9106100000000000000000000000000000000091140aee42a9dc875f87f3ba29beff95138790140f8bb522c6c15281b3545995f9c13b0b73ae691317e674295db6526000000000000000000000000000000000a945a215b2861427e0fbbfc6fea04e79edeaa1eb87df5db8e5e017cf98fde7b8d5a04a1b2129a4aadd2e3924ecc0bb2000000000000000000000000000000000a43f8d3d92a03b7bd4c8a34ce31729ea0b8e6b051c30241dca2db31a02b6e537071a914d8f0876f944dfdb613540c6d",
+ "Name": "matter_g2_mul_30",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000047f92d6306bed1cb840f58fd57b5b71a5df7f86dbfa55a36636cb495e08715cd57f2f3e7cd99a1efc28b1d684de1cb0000000000000000000000000000000000f4eb02d687a1a6105b4dbd740e2c7924689d558e6cbfee768dd303cc8dd0fd887f5eec24b54feccf00f473ca3f54ad000000000000000000000000000000000edad68c4d536912816cf6ef039c3dd0535dc52189583270b3b038e2c67b213d943bf384ce69c4a9dc526d7ef309f25a0000000000000000000000000000000006ff4a6b5129ef026d1d5704bf7fc0b474de92b5cf39722f165e73f4e7612d6d3bb40743e4b7b42d0dad5d5d6a2d4881915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c",
+ "Expected": "000000000000000000000000000000001821e14e70e12c7caf2a1ab651eb81dd61c4e1eec9a02fe4124abb865a7029e066f03b62e6ecfcf0fbae5151272b524f00000000000000000000000000000000044ac4a7399d6a67e7ee8cde3f5fe20b0a745462c870926f0ce8554061eba5bd62a8a08c798d8bfe30fba5567d47c7ec00000000000000000000000000000000178b8f061ad9282b3b2057f20c115c91df994ac40aacd05b7669e934bc7d650a0cd88f9fe17d7b766e34bed587ead58200000000000000000000000000000000188311eea279ddcf75f8dd82643ca3efd560ddbe6c8f2696cf7da03e65cc90d97b9f9ce99e29269644d8b881e624cca6",
+ "Name": "matter_g2_mul_31",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017b32e613cb38b41dcdf3c8bb9187d731546977fbffd79fa7f66e3d6aaf9e1af6eca2fcdc260c8f90818d7148ba2f4960000000000000000000000000000000007e4d26606a47c874c20e8480a9f5815e5b577bccd783b775d10309eeb3d2102c7a0abc3324679e44362f09e7a4ada67000000000000000000000000000000000cb6f12ac8b49cfa36b957591293c87b21af0a949c55a28a90ab0fce88fb5cb7645e20ab2edd284f0ad1377dd95ac10e0000000000000000000000000000000014c96b5dcbd3150eeaea5c2bc27750cf88b30a91933a3233a4d1d9b357a80cc20d135e43a344e718dff5c79045c31f86d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd",
+ "Expected": "0000000000000000000000000000000012496dd3c1278b55bde81f6944c4bdb71869f5e5e21db7b1425ea32fa1dbc8c301e7f5e68cd7629c91650265d1361e690000000000000000000000000000000004a1251591efdbdbeda21eb89165ca61a2e090a73426451b6933d939161364c4064a67a90f859a7713fb6a9c5321d5a200000000000000000000000000000000163bcd07d030fd6ab8a8e0bf39b136dcb34f03925c3fdadf55e94a90bfde0ecde5c51d2f4d06954aa6a96c913f2ab4610000000000000000000000000000000016dc065a852ef9e038d93cc583b4a71db9b96a7e7a819dc530598f1ae256368438f52e4b709f15f56279b9c7f9db8785",
+ "Name": "matter_g2_mul_32",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001ca1141ba9542c56de8991b313c6ae42fcecb6751b0b81b8cb21ed70d5008f7ffe831766b89880a7fa6dfdb09a2cda3000000000000000000000000000000000e6766b17db165bba564ac63ab88d3f8f5eded07a40b48644e60d3223d30458e7dabe404cab8d6f9fe135712ef0b1a43000000000000000000000000000000000dda3e6c87382fa762510e5cac721fd2b654f002f5b9a3767a8c6d651ccc582e80e3f68d6913cda30f9f51ebcfc7c98600000000000000000000000000000000059a7dac5bb6b504f2bd603d486700fe22c14f25254537b2c9079c2b45d36c7ce56854c5699cc7649b533194f51a9045c00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc45",
+ "Expected": "000000000000000000000000000000000a2397fb3a3891d1703eb2112357c5fb8acb070ba9f3a39050be6f05b49b8d2488e94adfbf849c8b4a42e287077e9fff000000000000000000000000000000000cf2c02a97addbc1584091e411f9a07135f1fcf989dfc8ae29155ac90b214ce20dc11a1fc75dfb697694891d934abf0f0000000000000000000000000000000018fd4af647bf0456aff9ef80969613829f8eb837205df552aadca46bc3bf9838e0ff2515d3fe869f80d78e2357091d8b0000000000000000000000000000000003c5671ea4723498359f29d49ebe974099da3dd59d21065a721f7a4f14dc7fb1de3a67a707bfa4bad7058312632c6113",
+ "Name": "matter_g2_mul_33",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000090f4b85961ce97cf7f99c342d3627105d790f611e19721a43d8a0febd67ae393d77a02b999108efb56f0397dac22703000000000000000000000000000000001112f23595d1613c47486eadc37f9b1ac3b3c3973b3fe964d3b67c3996fe2eacd9df5c287b0cea8e9475d146fabcf9e70000000000000000000000000000000018f46f7ba3c9af34c1025c2d460f0be966e68944928dbd55cc7fe00e5def598d80b0e3801e48a74963c974ab4727a52100000000000000000000000000000000096845338d5cd2ac44e097607d6a1a05c241eda1941991ae9edbba965d9029032c46da7218b5b2338e6c58898bc4a820f661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b",
+ "Expected": "0000000000000000000000000000000000676bd7ce63d8b58cc1e5399ced9b495baba4cef9503c44760f92d6d9e092d6d5308fa88144491eda6c571a8c308786000000000000000000000000000000000605cebb4c20bc9dff0258f75a825f55f23a32cd0804dce56bf3cf2f19a3504f0345e0f1b839d4d5920aab19b363ae19000000000000000000000000000000001512f95f60a6dc79dd9261c321328ab8e22ff314e7582d8de83aa3bf280805cba8ba6d359a620fa6f0564396a45ca9760000000000000000000000000000000005837474ba78e0700c77141d70af1d8fb95a97cbadc95996faa93c2e81b7c8877d08d5287f83219a24bc0080e630e39a",
+ "Name": "matter_g2_mul_34",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aafe45ea7cb8b450a51263eebc28c1ded662972bee512e24fddaf64f43b74b66032523b3b104a4e9f6b62394436c6710000000000000000000000000000000015cb27e1fedfba2d1679f78a388f90b22bbf3e7d090f0ba972fa8e72f6e31c446f628fff929953712ef6e425d16eba5c000000000000000000000000000000000df9931893cae713042bf722db6ce394b6f346587278a154c271d8511e690417eb6dc47efbcebb7c2fb9e77f1de9fde800000000000000000000000000000000106ffa395ef170c99bb5742428ae88fa4fd7a94476985c099e3b700b7403d083281fb71a19640c6bc2321e27bcb33fe2346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca",
+ "Expected": "0000000000000000000000000000000010b2a9b32e431c11ceb474942bbbd6915a3cff64a74d67570fadeb7447c5abcf1bb35c822d4441565322ebf75e61f64c000000000000000000000000000000000b75a0212232af0a59440482a1f953cc29bcd35272ef407925eccd70c1dc4705dc1e97d2da604996d3c52155d05d77500000000000000000000000000000000018751bc59f5907cbd7f1d503bc5aa266f4109fd3133a1c4c2e58e4a17250a40053b4489da4825b4c368b0f4947baa6240000000000000000000000000000000019b41fa1af9488596b09c587fc33e044d51674eb6087c647d5a762d85e38a587eb5482687d9346a1a701bd3a8bd36a61",
+ "Name": "matter_g2_mul_35",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010b1f8b1c492a56936da905b8738affba6bd29ae5fffd40ba6b31325181d3b489a81b23dcb69f6e71bd29bfb388e5a8f00000000000000000000000000000000116a115303b4774da59844e457844232d088062d920db67b2a8450a194be7e5340ebd4d106454fd9a03c8f50dbb1e119000000000000000000000000000000000eb521edd61b38006cffc43ab72d395d669dec196846fa4d6d43521da6c2fc3bf0994ce7556a3cffec7751b3bc5703ff00000000000000000000000000000000073cea36eccaa1c78deefb6029903c2b6598301bdefa9759719c3b590fcc5a6a4d3d4d19f552b33f4a3126a6e6a8448639a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc",
+ "Expected": "00000000000000000000000000000000054836eb7ef9edbe914bc16d1498e0bc3c978bbed2518802c2f8e1c0b59fee482cce0ae8e805c33861d4cd595f6b8bf40000000000000000000000000000000007dda36d55aa7a890aeaecf2528a390c98d9ecfc8a5c78c2a6def30de55b90ae408ab770cf9a9a4663ba601c4f5765a00000000000000000000000000000000007ff7b24c8ed9fca572069e72b1e93978cea87a0fac7ba60f54aa573d881f21b73012b010e9c0fc9324aa7697bae0c4a0000000000000000000000000000000002d9773bf294efe64021e755e4dd2936a5060bbea5688b6369ffa3b94eadcc58cc3986c74ff365301be1e6c785939b69",
+ "Name": "matter_g2_mul_36",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e3925fa085db73c1e67b29ae90f8773f83be5ec684402e8e2360ffee8a8368911e584843e42b0d470de78591df6ea6300000000000000000000000000000000075c7efdeeb16609b4a47ea442af4d75238fb7534fd96cb236a7886809d6adc2b62c8ff72bdb041bc51c1a71b68219e300000000000000000000000000000000088b4eb0dd185e51b737d797334590e982b7b0a5f109fc7d0524b2465c2c0457964eba5a6d2d4d99fb628f21f15a776c000000000000000000000000000000000fc79f6b38f3356972669290eeadcd992a22bc1191606b663a1e148aa58db3938f0fc65e536bc5811c50d9c7f03d3e372c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447",
+ "Expected": "000000000000000000000000000000000902c1082ff09bf93b91c9ef5e447bd6832fec9297cdb065f11fc5ee626e6e8834cb5d74775c586609a0394e6114e8820000000000000000000000000000000018e414a40c27430b98246fef556e74dd3dd7adc601e3c05b79f8c29169780a173be9a725df3318d71b6e82abf97930bd000000000000000000000000000000000f924fa88f43c86ec98b34379b9a649c7564ef0dc596c95df19522fd50fb3a37cae031e891a7a7aa6a5e6a9062c3726a0000000000000000000000000000000006bd3340412f64d02d0cb3ac44d1f31cdb1906e56dbfb66d86b60a74cd26c1e241963fcd8bba4109c428db0bb083e81f",
+ "Name": "matter_g2_mul_37",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b87c47605fc060a8e3677e84ce9d14b9309360a13c80d040c625fbf0108f829300cc1fca409a0f9c96311cd4a9a21e60000000000000000000000000000000014c4088f1e7935cf6a1d2475b84497ce6a250ee2c0c991fe51a2f2836388a354824b02d9cf215328dfce3f546713e21100000000000000000000000000000000120e59be3ecf35674eac6cdc559599b273f13f28a529770fa156f8e519734c451eefb35023639f32049cd19ea0d945a3000000000000000000000000000000000f97755b62a8cb8f861ea02c77819f0b58181aecf612d92180ba9b475f0b4888b922c57f6a1c619dd5514620a1cfd9e2c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d4828",
+ "Expected": "0000000000000000000000000000000001415fbd8afeeb5796460a9095f14a8f3f6fe0374d4cc4160f030710a6d4d3a92febcf4dad770de3a3ba1a2efbd858210000000000000000000000000000000015792220c7e53262b56224d230a8a4b32019c77548704ec16da5ce167854305e6cdb9924c248f222d6fe95a8383af7890000000000000000000000000000000001694329d8e0f41256b703a8bb6548f1d9e0749a55c124c9b60361b4cb1daee24fcf272327ba598022a92815764fc8570000000000000000000000000000000003350658842c5b6fc5561a14df27d950a00c5bcc13d6d9d014bfd6dc95ec1a030594625f41d439b90b05275a0ffefdb1",
+ "Name": "matter_g2_mul_38",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005860cfb6be6720118623d2d8ba05e686df22744b948421dd3cc1b1691e00d9b5d00d00195b4acf7a7b043f764f3f1c70000000000000000000000000000000012632a3313dd611e8d969bddd556c2d79ff387603462ac78ded3a842981697bdac34ee6f1f4744ed2ff16100874ac24000000000000000000000000000000000112b94c317586e343acadeca611c485c3ea172bc10dd39158c1e678007130062a921b53826d7be6286963ff822f1066c00000000000000000000000000000000040de8c0dadd2a6c2a7ea0fa43e1a5f2f5a6be3fcb0de6875d8cef1ee2daad87125d12f6869c4dd3d931b296f1df2fb3d4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a",
+ "Expected": "00000000000000000000000000000000054c6cb26c8b0a9a4700e0b95348e6fb1190c577eba03a44e84fe7744c543321d02c4d8f55c03f984b44ffbd899ac53a000000000000000000000000000000000e7ab8da5d573cb88a78f6a6ad2b307bf867777f79a643b6ec89d9cb208711c85d7d2cf8f8ac69a8b322000fc7866024000000000000000000000000000000000fbc5926b9dcd9e4d1ca1a2b43dab5c98aa20b37aff0868c54441de44eb014e5283010642717fafaa95000f4313e14840000000000000000000000000000000003671ee05bc20bead72f2306203dad55cf20b13d3bb2cca079bf4391411b85ed4df55e1426645d73b6935889d4450c58",
+ "Name": "matter_g2_mul_39",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006fcd2c4fe848e9462ba1112baad39031c210952adbdd06293a622ffe2d1c6e4fcc8773ec8913717018b97bcb9a554fd00000000000000000000000000000000130a97442f3273b7b35464545e7351faf71ead9b8996c63889a45945ed82bba29bff5014776c6185219a5234d8475c92000000000000000000000000000000000491d571bac5487b866022a0714be11b38bfb296233845cc434a50be1d35f516b8c6b046fe3d0a8f4f95ac20eddea01b0000000000000000000000000000000017e34b04e6fdf152c848f2432b7bd84b3dba3915f06eb77efb8035750aca9d89e92e1d1bc4871105c440d639e8d8b05541776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb",
+ "Expected": "0000000000000000000000000000000013fdd394635f42a926a2324b8cb870b5995772ef4e25ebc1da41dc5bf724f747da8d95a28dd703b5ed65ada5555c8b5b00000000000000000000000000000000118fd550962d1de8f1e60c312643ec7cd306f0bbcc932739270595537c8d290ca7e20b962fcde570bd2ed7ea43009fe70000000000000000000000000000000018b25fef4b75fc7649a489d078311dfb6da9909f472de7bd9bee9c3ee353f345c83119269ab797fabdbede41e0fe6169000000000000000000000000000000000b7c2a73741f6944ef4ce8fa20b2900612645c224818b7faccf6597827fa07f7262295f42be5f34a751a6400495f7eaf",
+ "Name": "matter_g2_mul_40",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f1b8df4e8fdfe32eaf227f5af9f2befc85073468f10b81d32d0e126fe2b0cc8e8adb8afcac73213b6ed95e8e843b97c00000000000000000000000000000000004e3fb435ae0fb2d8bd091f250aefe5922b353a64e16abd75627737f3bc56639f8b40652cae69c73ff1969925b0afdf000000000000000000000000000000001003aed7cfb00efce49d6b1a8eba27df87479a4d37bd7fda6121549483b669a1a761204b0dd28262bf27e5c8e180540f00000000000000000000000000000000114fbca7caf782b3296d0b26b4c362bf50acaecb8bc5726b2c99f904ec3d092d5d40991d0d30c8e79fddaa45f04a75d3fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c425",
+ "Expected": "00000000000000000000000000000000177d29de8a81db2e515d4241e5f7e3d35de22bbcf9aaa616b057cbf2dab57ab8d98213cdec82a2034964f3e1def8a4e3000000000000000000000000000000000a0cce8113eecb064a60ee2c470dfae8b3921f8da2c7ad8dc918b355ff44542b007add28a44848fa8d8f8671617431ff0000000000000000000000000000000010470fcc723286327e951e758fd0474de394778d0c1ec5fe6f263dea1957c60f05dc8f9d82b3c6a7d73b3e783f35ade500000000000000000000000000000000098a6ed331f03da7ccc9148f07b19b132152e15d9fdaee5cc092524b33795edf2b458b4e8383c5e29affd3f025094033",
+ "Name": "matter_g2_mul_41",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017faf481fd4cb0c373d21d7caad40e93d9a86e62d26136892fbcc6f6e48205543aff00c45e82fdd1d3e0e733de91e7000000000000000000000000000000000012e14fcb9ad4d9d15347cf004745ed4bd92097eeeb41c4cbcb728a234616363589d8f5ad4cbb61d31a8aa27627723c7e000000000000000000000000000000001513dad1ff27e053902e779e35d04cab648939317830144ea775c435a4b55e13fa2fef03a1256abf5c187487c25a774f00000000000000000000000000000000139da29de8587c7d0ca9237c37a116387385e9cea453b9e2003a37ede7aa0a3f4c1df55255897f5975b662be33622dbce7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96",
+ "Expected": "0000000000000000000000000000000018a1f1a60172a65abc8f2d855ee7510c1e0af9bada084325027bd493ae86ea2c62c15ace7f63562a82cb80ee7095661b000000000000000000000000000000001736b977fb52eb1b466cec3d42df7e89047784f0e8362eb6425e37adb1e84d0438f5a6e82c7b31d59b0959a5f4aaf9310000000000000000000000000000000013ea0f849830f8e48161e840295637d8596b32eb576560289620b797b14bd395d835e8140b69039c904ef1d07a82127b000000000000000000000000000000000d7f58873701c138cb7e18ffc36cd0e47b07d70448ddd9fdc4b947003fb29cba0775916c752d531e527ab744c277e5da",
+ "Name": "matter_g2_mul_42",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c118b147ee3489f30c6ecc0256a314ab674110588e8b69ca6d265fc270c3e5b767817f861140cca5d7c6be4012d1ffe0000000000000000000000000000000014800790654726959fd876b035bade0da744fb36ee5b304f228663a531345120267c55ac19fd66022752010e5bea7cb30000000000000000000000000000000000193ab7ac2f151750356b6e178557460c9c2672b1736d19a20e3fa28082479ca60021aa68edf2524f1aa826ee70b65a0000000000000000000000000000000015cee9ac55ab45abbc57d0ea6ec9ee49f6c59f6b94f99589dbc08ee877d3a261ad77f5473fedd72ed7206647eeafb6eac26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc",
+ "Expected": "000000000000000000000000000000000290fb3f38937ce4439ceaa21cf3b31db8a22f9f5ad9db0fd7d38ca978192bc05d41152f8f86ca7b2ee0bb58e125f57f000000000000000000000000000000001775913fc24699bf08f25fb946fc6527178ebb821c654b7bc69f6f86b5168fc42057a5d3bfdc53b3d57fa1ac05f7a0930000000000000000000000000000000017b9043cde8dbf500ad90463250a49f56b35713f2fd9a35d8391fc36c78c083e39674592a98cb857194ef9e73a62a397000000000000000000000000000000000e5e62e39433d443e7d2d32754d2ca2556cf6deea45e5076ac040e3d6de14e9965c53f8c65bd98ae7d17ad3a26f3accb",
+ "Name": "matter_g2_mul_43",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ef203fab794a0ef29eb2ebf00076134e5932e27c99d6d445695b9df2afe7563602e318caf5d44724a21790ca0ab0d180000000000000000000000000000000013b9b1b1d3e98b61b0f1a0ef3a1a4ceed57b6c01849a4ad66a86332b3d27022cfccadd3567e6709d2de5b23b23dba43f000000000000000000000000000000000c1fbace49684f4be32ef6178ac3a95ea3f50b11494340fb73dc5391d50bcacafb3bf0f2631fea9c4ec47327d644489500000000000000000000000000000000040f82812855aa3e3aaba826d5810c1049cf44e86e44e23cc6da437971b529d2f2676c73e1fb9da52640c981fbd710bebba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca",
+ "Expected": "000000000000000000000000000000000d9927347a9ac9b0290e68143fbc6a5f4476604c3fa5ae87e729a03ca055e4c6543f9245a4592e195180d88781e46ac900000000000000000000000000000000175e0ee8de4002b18f32f70f1bfa9e0be87288cddf1c436428c2969884112bef5db19e041cbaeb23596e25cabea3777300000000000000000000000000000000074ed9e981818102b9ba818d478ba27033eb38e3fa19cdeb9f5820e59a64dc451342a160359c54bc8ec7d866b62080ef000000000000000000000000000000000a853930020bf01e20816d3aed242e00792b0d0e78fb15403fc3cc255f0dbd99ea6ae1d59d5978e562be4862b3317324",
+ "Name": "matter_g2_mul_44",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000060d7a718dd02b147c265f71eb136d1f31781b12a41866b4f86d7374b93dd10058c192cc0fba928373b1526e1a5d7d7f000000000000000000000000000000000cf29275373c0573ef22bf87919faf5444847203c7dc6d2e18986152cc294be04a5b1a4b0536797158113a15276c4fc6000000000000000000000000000000001016d5b9d4d200d7b4b7cc3836b85d6697fe14db350badba9978c7b56983dd1a7e572640ee0372b0a4e2079ff4c1abf2000000000000000000000000000000000f2768d104d895473ddf8c6b3cd0e7c22458d0037eca6365c766879a07c95037ee0de00d32c974d767080935abbe0be1705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a",
+ "Expected": "000000000000000000000000000000000e9c290ba8a22f7bb3f7dfdcc9f5a221a5ce838d4fa85a00473a4dd830bacf583dd91a6a6f78d2ebb54a4c1bb217f793000000000000000000000000000000000dc51b0ae8bda6d28c51016764fc028258171d7c7646393228692aef7f1dda4a83e53553f63d6ba996d4c0a802bc967f0000000000000000000000000000000014ab155029dd35206811be9ca4efbf762a1673367e6b57528f79eb50008ce7c3b49a2d25da0ae68ac4030ab4bcc0daba0000000000000000000000000000000008cd743bb52e7908aa973c8518eaded75fc2858f4edb25fb7f2e09900f0abd3ac87e93cf1068bbe0c7d99619aa7a6b76",
+ "Name": "matter_g2_mul_45",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017b9ca4349fecaa43ce911c0b256680edb8a0906ef5460fc4d2004579336df1e19560fe960a7a7cd74bb6e8272e08960000000000000000000000000000000000d5b96dae738db59cc67a51c61bec6deaeefaaa51e3259243fa4b142ef59676231229ae386ce699fbe18c4c00bf9d49400000000000000000000000000000000111b79f4b68dad16550a13334d09dc38336a75a5da23a17b5064e2d591aa3dab4c2e982a9f730a7633070504663a24610000000000000000000000000000000018f6d3616a7eaf17c805a88c9710039644d01b61aefebf76717ddcda6f4bb34aa15702de1e92bdb27b27f3409638da90f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa4",
+ "Expected": "000000000000000000000000000000001746a449993b0684740630f3f0e46eddfa135371e33e8de4dfe553c78845399e63bb3da48798b35df48d27e1f991954400000000000000000000000000000000057e0fb1113968858981c9803166d8b3eacc91bfad320ea0e610fbc5b276da1b46d74fcc54183ba61d1b2fe6743097c90000000000000000000000000000000000b3a178ae3b739cae3e80f3f44db42d8c465a5cfe4943b449d4c3b7f4ad153916c6cf4fdfece14a00b271222c72764300000000000000000000000000000000041c8b293ded0c647f2e4d6f9b35304179b723c3e6e421a5cb103e561d1655b92e74877ce22c99f22a3700c3aba9ebb9",
+ "Name": "matter_g2_mul_46",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aeb5c087644595d0912879f61959d2731ff55260c682ed2bc5fc55c13964ef7c1f70aeb55876d2264d558c31371ca69000000000000000000000000000000000e173848f4570525b03a2b2c86f4dcdb8b28dd6d18c1354cad31028eb1b8b44432c2346edaace093e3954c7fa6d338a4000000000000000000000000000000001949b0902506d111ef6318edcd7a58ca4d69f5804a028aee73c3786cb2db168c6a73b77194f7a021ae6ae43ac78ade340000000000000000000000000000000017c5e28ba6103d97e2f3d3611c0c78f06406e0da8a49ae29c7d460b52f75136920784cd500aa3593858b877697eb8424807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556",
+ "Expected": "000000000000000000000000000000001103cc395acf81772955bda38f951a81c5a6a476c0b5e1543616a5a7a7be22dd487ab2a8586524891300adec5225b4020000000000000000000000000000000003479a08e2811ae9aab0301d66ada470935984d7466201f3fb28c610c0b5f67e7305f5ad3514cec5f30b51d0aae775d40000000000000000000000000000000005ea37a6d20c1ad0978da68ded3a5bfcc5ad8fe81e39b525fe7d1f2b2b1ab0be7ada80173b1d0b7fe1e06ab6354e64b10000000000000000000000000000000008f2093151a285dac511df1755e99a652a1cad0af3a019650fbdead1421ba8e84afc9eb0a4fea651f365d72f031a0ca6",
+ "Name": "matter_g2_mul_47",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b9900000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c7a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac7",
+ "Expected": "0000000000000000000000000000000019f79677ea0e011e5c9a892a407646798b05be05337c73135cb771abf101f450bbffd08e125f077f5ea989decc009b9f000000000000000000000000000000000ed15f35966024cf1de2926108151e976dcb0d51b2736b0877d79de81f6fccb9dd299d14855f4e257cae33ab7455b95100000000000000000000000000000000125e2fabb5cc95c0a7890e9ff2b70102a97a03f2d11d915cf4332dd049a467333e12ebb27955c0310ebdfe2afb3173ee0000000000000000000000000000000011718167000f9b749f1615610a30023db4b986364da5bbdc4506c726624a073548a94307b282590cd8a43b4900a1afb2",
+ "Name": "matter_g2_mul_48",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f20a07526a082e88630a0256d134a8a5e8ada07b1cead39ee838dcbb30904e9016107fcbdf1f8ba182308dbe0b043d20000000000000000000000000000000014fb7732f67abf60c03ac902577532d0acadb5f3db0d6397a42ba693526ad74f2c61a0195bdc9704aaaf12e65aa6d88b000000000000000000000000000000000018cec4fb81c85d304588d11f8b9c51f5a053df11463e5812a1b2e6c7144522ba36bb91adf219892d0007cee470032e000000000000000000000000000000000b8e52d958a12a9037e8be9bc0d5045cade2d6ea05c6e68462b3a30b5d4ea34e5fbad173761e4e216b2e6958c8983b28b473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602",
+ "Expected": "0000000000000000000000000000000005af8fd9e79568b46fc42b2c1bac62d115365834e509dab032f66425b7a571a4bd3bf702299d3c5f36c372750b3281f30000000000000000000000000000000018499089f306b3c9f7a645ca2f9aabc4e57c046992fff87e832e21e21875c6adaca050ea8bd7043afec3a36ecf8eafae0000000000000000000000000000000000827fa0f46134e2dff80088129841f0469ec7360fd8b9864e9ed99c5fd3458e6360661ab4c671846681d491b8b823d200000000000000000000000000000000120f829e8d0ffc360a14eabaf52bc653b1e90a36c0a8af806ca745fa306a9739e31435039a377e0748caf5e80c2b0b09",
+ "Name": "matter_g2_mul_49",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001468cb35a60898ed129f30c261b8431df6a154c250ec16d85a22f8717593b2c21853d123da86d977a7938c5ed74ef23500000000000000000000000000000000011f4e28e31b5f9e6877192a5e632d8c1ed7ca0c42e6e9902ca68f1c2de0f648c6064436012c5c7b14bb8d1078e02f2c000000000000000000000000000000000b25114b2697ca7eb1e6effdd1054893a188fd382d387ec098f846c1137a9b9baad01653b963a0b0bf3cb50c3ce3563d000000000000000000000000000000000c1d241cb03e642c1752b1e1886472477c19a2801ec032dc220c3243952f882094119bb92b621b654b766bc900d2d4f7a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c013",
+ "Expected": "000000000000000000000000000000001745500b00e5ebc6f71c779ba0b0f8d6601a065c550ca19de9562455423d2ccb507e659b0dce982faa841267fb1a27d90000000000000000000000000000000009c36b54f12d130868ff9b9b61b714fb1067dc91637c09614c51b5aafa2cbe3ca7dce0f3e366d4200cbf603ad4fd630000000000000000000000000000000000172e543708bb853712d81c000c9f9f2378e628b4d13b074317e95deeae98e11e7f917f91e02a0b18cfe9b25f1b83f16700000000000000000000000000000000189fc572ff6a8c6606ba0cea7da7040898d9ee85a58f12fade8c5a22031ff26c2f9cc612bc6e1b82a0999fa93c6fdfca",
+ "Name": "matter_g2_mul_50",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c80d4474390fa791ea5f2f16b41506d8ae13ee0993c8d31a07712687298ee7978a724999500c42400d2f788a5a36067000000000000000000000000000000000592705cc5a8875750a4e6ceb42aa3bef5593eda9e8212702a2e08ea70277a2a66526bc5237be33c8449301544da35e60000000000000000000000000000000000facabfbd15284c6433f17b0e6035d4fdd84d3ad2dd30a27d52809652ff6e7a684d7724697919100567ad0c3e1a26320000000000000000000000000000000006a0fc4e2af69ce15a356656f5d182a2cf213d76a6047a05a1a3375909d245f5316b91333d2141c0817438f0d87bb52da9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc8",
+ "Expected": "00000000000000000000000000000000013c6f777df97ad3ddab9b7486d54d1bacb3b40ad3035b47a25a66c02e8866955e27a8ee52872c8222ff7466c1310bad0000000000000000000000000000000014a5eb510d7c743e824f4daab21c43db4d6de8ab2e825d13ae0e186aaba828d7b4a2343a11011a8ec4ea82f456e394a70000000000000000000000000000000017a55d3827b78a9c5ea792b705eba7777df74951930791b17ff5b861e98a4488f83007c073c3e904ed4ee328b6f6171c0000000000000000000000000000000019bae02f8d6f1e31dfa09f4feedd5217ade66f6e8248aa98b273574f72aef83d5048534ed38acab9e0eb4c64f4389af4",
+ "Name": "matter_g2_mul_51",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003f629618e1fc3018bb836301ccdc59022f0a25cc9c5de6e4c31fa08feea525c83256235e4ec8364e77e5df478f5f62c000000000000000000000000000000001120d6af221ba6f4351bbee4c2c664a769adb17872646df2c408f70c99ea991ffced4eab50fa98be1bb9426915f125930000000000000000000000000000000015cd16b028ce3d58b10aeb84b783475d894ab3f0cfdf7104ebb4f3417a038107128f07518dce548271061cb8c97e88af0000000000000000000000000000000018379875b68bc26107f9a068e5034f29dc2ae7e8830f8e9ecddc53fe7991206646cda33d37b31a47a977b46be58d7618f228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b",
+ "Expected": "0000000000000000000000000000000006490c327790b4c451f93197d7db24211a3b4b5f573a6df409206b4bbfc36bd10d2d0c989889efffd8f4daa4a68b211c00000000000000000000000000000000168f224738db3f07af77494f52ea5e957812a1acd62615f0eaa95c1d363cfceff29be9cf3be5329bb41175a0231ced4f000000000000000000000000000000000321f06b55f7dbfd4900b329c914f9ab9be2794e51e54498e18f83ece5bfd205131fbc254bfbf624d57ec2954b05f6f00000000000000000000000000000000018ec54f3e09bb2a6b112b575f9481bf1c85666133051e9c0ab53369d14eb90e27d2ed02dcda1250d5d539df0d0cda37c",
+ "Name": "matter_g2_mul_52",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000036570783711b381830e35878fbeb187b84884a9a0e88c38e84124515b470e6ac18157e1499026b27f4f731a961eaf330000000000000000000000000000000008382838c18d56c046a8db495babf8d14c915622d7917ebe10cf7da7ecb65f174cddb9e70d0262ada961b396c5511b410000000000000000000000000000000015f63ce982aa581dad5c71fc79251b7f6336c4e78a4a0f4cb6f87167cabd31cbec987d7af4f11dc6d693a0b0774864130000000000000000000000000000000015c001372fe0530a3f50fb8b30e75ff4b264d673e0448211d082c7a9018f583b4d01790019874596c59c68768cfa3e699431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb511244",
+ "Expected": "0000000000000000000000000000000001641b4ad10da5089164809d82ae47f74e27eaebffc2a2ca3c1b924fc69c1ea80ba3da78c78e86957f6a24e7f75dcada0000000000000000000000000000000014e781e4fe79ea1654460f4b0daddaffb29b287efd8168cb20d7ac6c729f684c5f2a7cfa87885accee3a797febc904c200000000000000000000000000000000001c9a44547f0c5b1f4df190285644c5a31df61e3de7da085835ebda917d5e4163f2deea9a83d641a4759fa3108567ad0000000000000000000000000000000014c3d2a79d80687fd6e6aa423257644fa5d0cf641aaf6a7c5675a810767904166fabd9a2ced0727e3badb932e46fd181",
+ "Name": "matter_g2_mul_53",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000074d78cdd35ea17a3013e2301fe9f80f2d20d270a25fdead37eed7697a52d152612543781763e6035fa5452ab12cce25000000000000000000000000000000000e572236e1c203a1c0f99e6ec978458c1a143a6a650eee27cfbe406bb2858fe5f30222f468d119703c2f442bc644ff3000000000000000000000000000000000125384343fe132e16a9fc15efe1b3a9e47289e0afc4b44d492e33a6216edbc96d66c1ca66944a8296e7695f27f414c5b00000000000000000000000000000000084c2cbf0d7c932c3098ded7c70d4411eed882feb0f79e0f7f1c31f5fccb6d53fb57de179c3ba5754bc5e532c3784df12051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d83",
+ "Expected": "00000000000000000000000000000000129554de7de9a2b73340d94d96f0356a2d1c0524cfb007d76a75f462872e831f45553de05f5b6a1f9eeae37af7f6b4c9000000000000000000000000000000000b1ea2a649ca13a3dc7882f2423036670f68aa05792a8fcd72524420e37381a9ca80dfea701fa5e6da57afa534059617000000000000000000000000000000000b7ff27aba408f9759b5109600cff66c03cdb4bfb3dff64a4838d0516fa46bfcf429fcf9d5cbf74a27f70fdccdb1238c0000000000000000000000000000000005a99aec88967fe775c691d443e2dbd45080eec97e686ee6d7b32e801efe6563315bfafd5c7622d0543519cae4417029",
+ "Name": "matter_g2_mul_54",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004d46066439c3ac559cce863c58316883651023990180470d2efd06e443a7caf3a514b54f15ce6e850d32779215bcf4a0000000000000000000000000000000019ce904b6c9c3de59f7d5017f60f1978d60c564f94a0f1964c24c876d1139a7ffbeb6d0d4884bbfaf5f2f189af6904a50000000000000000000000000000000015f1989719e69be95f25dda9358fb98aae2819e0deb7e2d291e2c01e85ba26a9da421896c6b6e2ed20f609b533154694000000000000000000000000000000000b287cfcf1dd7c6d735c1358dff15393ddd6c82e7a33c5d8005c4234cdf823c76a4725fd74cad74b3ec51df67f09af0fb96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f852",
+ "Expected": "0000000000000000000000000000000007997a499b2194cab634750a189cca6783ff17d866d66f5998603f8639d2242e8039222c65b0d14001167a9b09afb58a0000000000000000000000000000000015050fe6b335884a225efcfea4acd025cfc05e8f5fe9a0e22a0c91b55664c118d79887de91f1ae6cbc081f6f55f0067000000000000000000000000000000000195b23c4c2c087082c30600ff00485d169dbd360643d163f1db363f270cd7d4f177c36b4c291d50da4101e67b229d0de000000000000000000000000000000000df596ba2350ff7d3e75b4cbe5f8d6b2cc0e14b3bd6dc021936e3371ba64031f6266fb1d2951801309f22bfb1c4b27e4",
+ "Name": "matter_g2_mul_55",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000006b37e2226957d639fcb0bcd6c20b3c7b8372e7347a14b970e01c67c1859fa97c754ce588d0f835ecc053549d963ab4000000000000000000000000000000000c6a5fae8be3a32e3f70a4202a1ab6d97183964b9f7b9a084c49922cd9e0e952b0bb66c5580f0e0c417e079493bcdb4e0000000000000000000000000000000017b6132f11adc0d5d693ae7f3a0f89f5779708083eba23e03b0c9265e4e60624e1fb6940e8ee49d31618fa6389b1b50b0000000000000000000000000000000000a45c5f6df71359648aecb6434bad1619c39f10e279a02b3cc9725d0256bcd126843fc9ed29cbe02a32cbbe79774a3378176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c",
+ "Expected": "0000000000000000000000000000000001fa243b548f8f5c2e5d7736ca6fa95b74dbfd31f95fd532b94f81a255c73e7c0e000e20f9ca6750cb0dfdcd2c1aea8a00000000000000000000000000000000132a893a2326bf61962e1855331a53667e6279ed7358bc84c4a7c218b6cff1d3f449954f56daea72bc2779c60f1113400000000000000000000000000000000000091dd23c75dd8266f556bf27ba54c95c3ccab06168e4e6d0747239722afb20f3db27454c6db3a88daab0ef10659a66000000000000000000000000000000000d3b2e3fd358aa3dae983e87b5d1fce6d5688e66ced6e3a2c96b8d48041557295d5932af6532c13965d4b383fb252518",
+ "Name": "matter_g2_mul_56",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ffed009c78ba9af8cd33af7b7697ae4dff863bb92365055baedd2299b7f5b5e8abb84ed434f7223c3e309ca53c08aca0000000000000000000000000000000003b2370c837dd6291818efe7c9af62dd51295c418739ecc509d42c92e2c97d12a9fa582946e176e8153fc9a273140b2f0000000000000000000000000000000001e63438e8b4a0462cfdff64a281ab4a7f48d51b51325817139f8ee683484f8695f1defc0c3efcca81d5fbff06cf9c54000000000000000000000000000000000192fc391cdc1ed6ddbd317f2f366f2ce25ba27b8c0f09c733e7bc0c0697544399a3a4f1186d139a8f6399ffa88e89a69c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da0",
+ "Expected": "0000000000000000000000000000000005095d1becff61df906815842112c6508d6cade4ef5f4b7418f5f01e8c5a383addc1c572237613dfbbb88bcff80e4a44000000000000000000000000000000000bd2561e7bfbda8a48ee038855e37b03fee805689452e9afaf0da4185e0c194e407ce7149b713c689d25f953da36dd1f0000000000000000000000000000000015ba3ae4d4238175425ac5dcbd9e6e9e055b8c1b7752931b524fb546f7bee8723ef2e69351450c6d1ba3c366a22355e20000000000000000000000000000000008c17d77dcfda00a1d75ea0087c58e74263ce5ce4066e979c66397de8e236708831c3a9ca6b35ade8038a28930655eb6",
+ "Name": "matter_g2_mul_57",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000002e105e0eaa418d58019a849b89accf665a94ffb0bdf308a11b99b521de7af8ddb150c0e3b2e9c54cf5456b6105bc81000000000000000000000000000000000691a3b3986fbe1c0ea22329364454f37f645d6abe9310e883b9191ce512347e074e18e28b88c2adcc76190a549b80b40000000000000000000000000000000003f3a37a763c8d0d99a3fe36923843a22cb0fa18ced48493b2510fc99afe5b7699bbaa6c2ecdad8aaf72969354f121a1000000000000000000000000000000000f4bbae00205f54eb10c83d928d908fbae342b76050e33c51b6e282e02b3c1f132a4728dee4ea95455c25fdfc112f2542ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd45",
+ "Expected": "0000000000000000000000000000000005cabaf39b93d7fe15ef6a7a3031df58219bce702a5a77162551a3d916c22e8ec9af2aa20659e7c4ce5f6382a5f82726000000000000000000000000000000000dcefe1a48d8c239164b54771118f7520ac11a7a6b72d8e17be1cd788cad2f26d3a0d9113e6536426800a744be9f0d4000000000000000000000000000000000199d95a44a4334c87aed273a0184be9602ba443d5b8d34f3495b04e927f4687fb88487f586395c7babb4f218fdbecf8c0000000000000000000000000000000010972032f9cb3e8f45447bdd06df82656fbd3ce38a9f7564c6e5d62ea3596c9b7e0a94046f1c65bf0452ca25b15a885c",
+ "Name": "matter_g2_mul_58",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009a3e98fe4a98582ce9f274965f376cb45e8583775dbadf626cb1327c1f8a25b293b97e7f8f31ff72ba7e8e769ff25ef0000000000000000000000000000000018e4785ccb76c4897087c8a4242ddc744c6a0a53a4a844254153c23d6f16d4ddb945252d13f93101613f4eb0b1e2b8320000000000000000000000000000000011b81d344eac04d3471b1edde5e51f31f97bea3396580839fa094db58cf6bee371bbdc045fb60c3ee5c6cd5d3f6d3c4700000000000000000000000000000000073476bc5b1d52ff4ca89c3afc099417f473543fab6e59cf9de8a19705dc4bf2a210b1e6de4dfbde035c312be0c70c56fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f",
+ "Expected": "000000000000000000000000000000000f250b5e47ef616be106a3334e2f516061eec8f7ac69f08f6dfaedecd76fb1c9685ecdac2c3ddd534e3947d007ab177000000000000000000000000000000000073819a6de38303725aa3a9e5a7a9122b4d1e60ee8deb3554b5e06ef5e60d71517c2279c5066af003b32cdf83b7fcdf200000000000000000000000000000000070721107ac6dac198f7ed1a7f84697cbbc3199a220d1aaf82e6f015963bad863f99190f18a482f730254cef753ba22d00000000000000000000000000000000169910eb30b8fe1ad8f84c4a132c6c74a6ff06ed6e792af3baa6619e3c8aa6cc3e6f687299467ec9554f9e91bee77aa8",
+ "Name": "matter_g2_mul_59",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c414b95b298b9c673001173ba7e5ee3e03926f28068481cfa0b469ab556f8fceba9fd0a815180ae0b82c265fd4c6b7e00000000000000000000000000000000054a242c1cc1a9c710bc23305d09c2d613ee8eb3840b37943bfe83f9c1db456ab4436ad319fcdd8684db129d76c95320000000000000000000000000000000001683711c0c7f02e67374f190eed1ce6559479d6d199f43fb5b0ce7df7774a5cb21c86b3b3498855d9b69c5763acd8c4300000000000000000000000000000000062f87085dfec847af518bd71c078f994b090c3b27c6eaad79772ab58afa43993db52fb08649a32629d61c3db12c87318a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d",
+ "Expected": "00000000000000000000000000000000106e892e336b2155909946ab73b980ea761cfe8c48b13ae8a5302eacea08b9cef3e60d5b33c6ec4033218ae5761433dd0000000000000000000000000000000015daeaee59f3b4cc26d3da745661e74db8fe1ea115d50ba49ef5e6151a9ac2f3135f0232235cac7a53e1e8a70eaf0476000000000000000000000000000000000ff494d17c735b934c2c7fb8f413103188fdb116fa8f4d4e43262968ab0fa1bdec23b0d4d8b1c2defe624092de36610d0000000000000000000000000000000008f70b7e9f2d7083774fbce3bff58a1c73fbcbcd9cb049cba71c0c3f0c363517c8956240bcacdfb7934d4c67b1bfdd2b",
+ "Name": "matter_g2_mul_60",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000083eea9b5b2d5ac5f7ef51ca889a4317322d098a408a741827fb3419eb12a51c07c788c2798cb37635e224e99bbc894c000000000000000000000000000000001312ec00f4b3a4305700b44b3f215779a9a8bfcf5b5d3a7f237a33c5484099ec9bc5c8537fae768e2c0ec62168f383d6000000000000000000000000000000000cf1d5d05d11e1d07074dd34211d0f00eae1df4dc550c55bd2fdafaffa1ad36abd5da30c5d3a5aa2845b1d95a5cb571e0000000000000000000000000000000015223baa9f2ea4b04fdb05b05bf3a94dcabc5e64189aeee39c380de9a34fe6b4253f5795f70bbe51b80e1aec1eab7196d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a",
+ "Expected": "00000000000000000000000000000000098f32b35e3b7dc1862ca1ca3c76d009f016c6b91c227f2cebe8f1fe87567d936bf1c54103bec31b3552c077c0242fb40000000000000000000000000000000005380a66d48d348487624a15b63d2ecf6976b5b599901101ea8b1f57736649b4397f6679ecab0ae29573695a921ac475000000000000000000000000000000001710c368f70a2b9cc92ec65c4c2ca35fd63440eb350f488e7c6646f9c42bf680eb62a887d533a91e47988221b46c868200000000000000000000000000000000033c3327da938dbe4630dbe16838229d7d427f3adf18dee6fa26b1c8067838922c1bce78cce08d590ee1acf2baebc7df",
+ "Name": "matter_g2_mul_61",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011a960cf1978aa2ce1731b857fd91d2f59d4b8d7c6871ef6f4f85aeff549a2f397949d11a4793926fe7be37f3a83d11c0000000000000000000000000000000001954f056834d6e3b16043ef1acd0a47a353300257446e9a1db7e58bd0d7c4bc9ceb3db51ae01cfed9de99621e96934c0000000000000000000000000000000002e2fe460e71b65595ed93a0010e5ccd1a2c16fc4e0d345e7226c947f29720d2f3f54282f79cec086d3fb1999b9629b300000000000000000000000000000000060dd8a7ccb613f1521168a8a322aef9f84d9708a893f704f4fc9a19e2493f25620a47e0fff1bc1e212e65e92873b4f2dbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad997",
+ "Expected": "000000000000000000000000000000000404587c60a4bbd8b5b929ca2ec2a9ff2ba4733f4f2877478a669b238d65ca130cba398899f2910d6de04615f8ffc99f000000000000000000000000000000000940659b3e6de7c3d8de9169a28e68dad433bda78de0991fe4a1d404e5f4babcba9d57c7f3d638aef264642f87c61fc8000000000000000000000000000000001676ce240e1ff70ab03f94f3ba3acd31725ec306ce1fd707e29ec22cf91746216dd998d03ba13a79dedf878fae38d68e00000000000000000000000000000000098a81422511f77191ee15d402614c86f9447ab78a89cc348414108f36857a1929f2b92ced78752ab3604f276861803e",
+ "Name": "matter_g2_mul_62",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001472caba61c2f1fe4b1d0912b114c25de103ef4351668f22f3a158d7a347539a7b6656044bd490f036ca3e29dbdded370000000000000000000000000000000015f8cdf7786410b409f218164063c99e77d8f72f03882a6c9430ec725ae574547d3ea3cf30c3ad2c9c3febe6c30b1272000000000000000000000000000000000ccbbed85c2809433fbcf22d6490457dab800b21cb4de414c7dd1804a0bdeb7142f8ffbb2de921c2c9eabee6a6351026000000000000000000000000000000000a404f42c48e3ca408d3f92079b99805004da928f128206d8904ecd7fcb14121c7d9a9e7fb69accaff921315ef3d5372807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a",
+ "Expected": "0000000000000000000000000000000010a4ba6952d22a51dbb6762a3f9bd09712c2be5a98bf0ef298d7a7e3a9735ab0d3bf39e40b334895c73a36c218ad24b50000000000000000000000000000000002860f38ef61b497bdaf4faeee7b406007981c17246cfa36cee906452ae85e1c1c6385898ebadc3b4ef8887fff25b8240000000000000000000000000000000002dbbca9034fb17c3f37727d44c027cdf47c36f3f628ea9385fc9fc371d23f22d983656caafbf1cd1f8bdeff4ad7669d000000000000000000000000000000000b7e71b65765c4113a7884771952268a9fe10576f745038912e6877c78372cd261220793b888c43accba1646e902fe14",
+ "Name": "matter_g2_mul_63",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b52f05365c4df20a7290aee71a7e030615d1a2a971167884d835c24e756a0faf6ed0552341c561446c7fd3d5e887d830000000000000000000000000000000018718ef172c045cbf0bb132059754b62414097eef640a781db6ad521af5a24d78c622d9402033fa939f70aad0510a1ac0000000000000000000000000000000017e969e44b4910304b350b5d442bb6a0b71e1f226cb4603cc8b4dd48614622f3f4e1ddecb1894046649d40f261d94e030000000000000000000000000000000004dacaeb9e05b9d60ce56c17312a092cb988bff426b8a718cdff860186935507a06eddbc4a1a29e4ef88db83fc4b6e77830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d",
+ "Expected": "000000000000000000000000000000000e9c1a6d591be4da37fd6dc283b8d899b625ccc96371dd3d7731aca66cd2a978810497171f2aeded64fa2b10e480de2100000000000000000000000000000000006d2ad7287847255002480627782d513eaf1f68a3d583d4762fc156b8eb40deae6969fa8a7d8f8aae923800091386a00000000000000000000000000000000003c7eae0eda08df9b9eee2605a44fbb486e3bf2e409aaa1c8f38c06f969ff1f74338004b01288dce99be26a837e45d3a00000000000000000000000000000000178174d2f569a9392eddd2715ceba8762c5bcc6325217db5e5f970d6fde069d0e48a824e5b6ca017891de175c92f6b29",
+ "Name": "matter_g2_mul_64",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019829d5799eed5a081042e4646d46fb6bead6d3b9893a4240867b25ed6af6a3e154514f244466d80e3b9311e060bbd7100000000000000000000000000000000156157a654db2813cb9c1b4da0a3ee192fad076bb2767020fc5fc00e967c1a35a367ffa375703e1181b3705ace9dd28000000000000000000000000000000000093385a6a9dd0ab996df54b23f47f4a49b3f379e11bc8331016ecee6161fcddd22f6d49fbb21f098873f1e17424dedca000000000000000000000000000000000d5b5b0f2ce81e755b4030b33fe3a8bdee38c2c60ed3b4a88bffb9207cb762c0a5c699ff424c000ab080d763abc5438d184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e3616",
+ "Expected": "000000000000000000000000000000000ce12c9010b4c4afbddb459c1b46063a8488277948188b4ec0b739e1cebb5653681d0e43a0d2c6b3f842bfc609bbdee3000000000000000000000000000000001123f60cedddaf4385e63758d64d4facdc443854176ec199ca0df0a9c258517f2512594f2441a4b9a68aa9a2b4a1f4bb0000000000000000000000000000000007cc6f77d181d13bd9736ee23a33b25b0bd969760642ee19004e095ebb8e2b3c0e09321eb15a2f7961803c0fb10b6ffd00000000000000000000000000000000004d8dbf2f0c14b07ebed2b9cb4bc87df78ac8a34ef0b05cbc2c6fb8e8156415399fa52dfb968ef0e6ec697030fb003c",
+ "Name": "matter_g2_mul_65",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003af8c25bdbd0dc1cc344d55366f15555709a74e1f0d8d7050cb6b487759db6200401b7868fca3c2ad26e6362a30e6250000000000000000000000000000000013f8b6ffe30f9a133fafe64461d305cc6b2cf5aededf68ba396d4e00df651531c750a3d94dd77bc5c6713b939b18fa19000000000000000000000000000000000dde97855d7728f409d873b83b6879b45ace5b73f317687fbf478e594a959ce21d4d751db646ceb20432e8311e67404f000000000000000000000000000000000fea997323cf29710cf0e3d44ce682e039d6cbda155e43c94dc8cefc5e94000de4b9525123b9615b5f1019a46ef37ad3a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af",
+ "Expected": "00000000000000000000000000000000172805bc715a8cfb2e25c384214f4005aa6d3b809a0ad95322209851ef92151526a9d01a914c4d7f0c120b9bf3837010000000000000000000000000000000000473ceaa092a5ac12f38b4065477672deacc08e553d8e9e6391bac0d9ca50015934cdbc340deb05aca916cf50c7915b30000000000000000000000000000000012e85461fbd26c2d0235acf5c8665750656819bb939e8fae77a8d526ca23443aee395a985cdd4b1eb700311fb87e91a7000000000000000000000000000000000246d45fdd88448c93bedf4799becfc7c80e67abd483f2a0aa41e8bbb3f38cbc900314436364f1db6e1d88595544517a",
+ "Name": "matter_g2_mul_66",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cdf60e3bb018407eab162822468255bcffd54cad9127054bd1c30705a4ebf1afc7f539cca6ba4cd070b44410ec751150000000000000000000000000000000009a2e3e5993b6a7007dedbbd21737a8c0aef3ecd4607953c4a24bb3fed97ccae01ae1cec024443f300b570a66e9ac3bf0000000000000000000000000000000008a21fed19e9ec2a741ade7767b0c9f39b79c3fbe34aadc9eb3043583768d893bf927d26231759290c7dd9c4f158d5a10000000000000000000000000000000018eef4ff88d63149d2632c9db586a4af0606644b16c82fbb0a3b869f1ff924c59acc8efbfde7bc604497ff68939cdd0845111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d145",
+ "Expected": "00000000000000000000000000000000122e1f2081cbde0055fc34d2fe61307bc333b35a1e0772a0cd6fb25338c89824bcf2f066bc7b571b2fb314ca7f45106c00000000000000000000000000000000027ed81b54372d858a6ba2faa65fdc132efbca6ddcd56c3625bd9267cf0ae04f6d342209b995060f584be8d40020669500000000000000000000000000000000002a03427a093a3000a1bed9eba91a82dc2f2fcea1a16a1fb8af29c4988b589abe6a505ec87a82864b3c683beaa6420f00000000000000000000000000000000134bf64871d69a72e42766c2903fb4589b84d7772a62f7d2f8f8d02a914f4d3a278c680c626ef4d69de8aa88b57589a7",
+ "Name": "matter_g2_mul_67",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f5d47911596c46c0c08cac5f5e7f6d0609874da4ac1bd4e0e59c393273a5fe31a756c7cfff2a01d19e79d209d7c6d3e000000000000000000000000000000001010f864eb6624132d4436d18db7f5b34727060dc426c109886be88031e3c155490cb3fb09e1fbccb7912875477c6d840000000000000000000000000000000005cfbf1c2ae1b80a8c7cfb2cefedd907b0552794f4fda101ca1a723b18de8cbce30eb54287e1847cee3f416cd8b45f2c00000000000000000000000000000000084fa63781f7eba9c7e911ae5866d485bc7e90603541c55d1ffad8b3cf7547fd57fb24b14002560e58410b828513e109c07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a",
+ "Expected": "0000000000000000000000000000000018fa44efeabbd1cc47dd9b1a1195ca921c99c77ed43a44502aad27b6c663f5ce2623382c3ddf208f42e3eea741281f4300000000000000000000000000000000138d11e497e3c5656bc8fc0ae4322a0bfb6fc20e249a47a103b164aa3d9fdbf7df4b1e3b0842b4b12568a31992a151f000000000000000000000000000000000182490d6ae35c1208c0d608984df4988d057f3ce5a25073c77cd5b224a5892768badb1ad5cef8f41d1d2022573098c320000000000000000000000000000000002a6e0523781ccdebb75063dc7ad1a9526f9ff8ea1364bae487914f254c0eebcbb2cfc3715fecb9599bfc2f5feaa62d2",
+ "Name": "matter_g2_mul_68",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000124870cfa469136c638e0cbf15802f2699aacb66d7e4c2965c6759dbca4b7e47941ad9ec37a84db1afeeeaa65a7418e4000000000000000000000000000000000d4503049a6a53536bdf41dd832a6ecf3f10554887da7e389cf940394e1d88db94369b7947436546eb6c6e82c48dfb9900000000000000000000000000000000053f9a6e1f05b67cf553073358009a172e2ab8b43572a974da1f3de85a29103b13d7e67b2a359297172d27dba5c61439000000000000000000000000000000000abc29f50ddc1c113c73700b9b9796890cbf48818ba981fdab2db27ef1c58f4c2e4595b99eae397d40990ce2f6c9317c29b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd0",
+ "Expected": "000000000000000000000000000000000dc7488491433d5b3924105c01ffed4f30b755d7253d867fda595e7d80197823e56e4d182d5ecc72d8ef1ba9bca15a310000000000000000000000000000000007bfeeadd6fc468ef6340a2b394c155bf50808cb11e89adb0de5499fbdde91760e9531c1deb23050286a15e5910f1d5a000000000000000000000000000000000f096db706b08485fd577f37b7bd232b5a10c3f80c25bcf82f7a3b666c6efaac8e856bfe5f7dafb7457e33eadcb4133d0000000000000000000000000000000004460d1f25159ce6df59efbd7c693355af4634dadeaee2ced68124b2a887698c10e9c4b40c4f4f9c8444acb881ceff65",
+ "Name": "matter_g2_mul_69",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007d2aae9794b7a7de97f7146c0ee8415e09e56fd42535bce6773cadd6f7ac09c4eafe2e926cb7014377e54c703eaa9dd00000000000000000000000000000000172a4a33ccf99eb0473b2c44d30bd53159afae0c7706ad128bccf6258974d5e5761f9be43e618cdbd96027aede7fd5860000000000000000000000000000000012601bce2171c6e4c2968a3efdf1491285f9e4ab37cf973ab5c8e224ad5b40e1b6459ac89090c73deb8fc79fec7fb8e200000000000000000000000000000000112a6443116e6f98ab348e57daa3971b5fa506e40515e1611fbed3e7dd64c5c1e991e0d2539a70eb93e3da0f573d6b2263d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf54258",
+ "Expected": "000000000000000000000000000000000f1aa4a7a22c568c41270d24824138bf9ffc763a5356b7c0bc1d051a0a0db12616700d9214972b63eeb2a398d27dc83f00000000000000000000000000000000020d0c2ff8f93db6b415c2a01712034e46bdeb6e665a5177a3877db9f5401d3dccb99907ef843062e394c1428983725a00000000000000000000000000000000088abeb6fc3ead45d5b261b7d684f168ca8f5f163cf338863e6b102dc40e2cd0ede97c47460ad6f560c27e95c8b71ca8000000000000000000000000000000000ca2e5cec212d581c737928512118e2f51a0d74070f40a998b7b06d22b9fc754bb2fa5499308058be9ab81521d057414",
+ "Name": "matter_g2_mul_70",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000030372914b83644fa4db1958831e9335c72ab7a811fb337696221a3290e4c54bc10c2225f8fdc3a9f62632ba2f1594500000000000000000000000000000000114205926609470b6022d24046a1997c048e6d2cf6043397892c967692161c0ceedf409bf5e1199a64eabb1ff8de23640000000000000000000000000000000017cdecbe73779855b7b94920d4bc8ad057ce51c5481a5579650df8a5bbc421030d2ac44568217c4dbb13d7c639760236000000000000000000000000000000000f194fa814bfa7396697bd812d9449d06fc61b580d7a86429fdd1ad376e21ceca139356d7d13964c3c684563675711c67a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e",
+ "Expected": "000000000000000000000000000000000cfa23c46881893f6c50d238a83669deb520a7fffab4f912f77df7cca43f6827a1a0ae0b3f36c8f116ecefa33b8bf37a0000000000000000000000000000000014b7e5c18d2f9bfe15b0c1af3bc6e230039a341e135837d123e91cde9cbcda298c66b93f692232c912e5d7d3d6331c430000000000000000000000000000000009c8984999ecd3a4144ccb925d3e5cae5c1662dfbf8871013b1cb2946482fcb075c489c61b8d6261f2574b44da3fc1ce00000000000000000000000000000000196e7feab383211e4825cf98219c63bf9f45a72d66030219cb585d5d25237a01a97f00e122db6a51325022e69e7d8cdb",
+ "Name": "matter_g2_mul_71",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015d4ae1521acf897344c3a76261754ff99742585af4a0ee86dc473a88fd408091404df1da9d8bb291db68bc9c07d6b2b0000000000000000000000000000000008ce160213875c661163990f3f7ac219ea295db5e828354864517ea8689ec15d35c6df78ff14cb276e0c97ffd7fbc09a00000000000000000000000000000000038a3ee211e777d6d6b7ca6c7a0d2130f1a071c030eebec412c3a0f14c3584e7c5cf15de254a8f141a8210a90249ee5a0000000000000000000000000000000019f7ec6b2fcd8b3190ab37a6e843340d3f3fc092f5772a042edbd5bdc967b96e8a1dc9e435b8463496aa1301f87d0e5a81b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83",
+ "Expected": "00000000000000000000000000000000005c0282830934ea09c9f51b52cb6dee75b874b155c63076dbac2cbbf220863d55557ff1b7d681fa185435df1522f49d000000000000000000000000000000000a1680ebbb185c8e7d8a197a523a7a5e618f97c46670622034d312b3eeef140150e03b00ae3dff8d9f1d872f3d3dca380000000000000000000000000000000019bd2eb4bc25f5aa6bce206f0683dbbbbb002098a118fcfb060c1353a310c2baa1063a782bafcf6ff6bb8edaf6f1597a00000000000000000000000000000000082edf49a0435e0b9f3dc7f207711d66004ae688b18f5b62fd1596899ee8edfaac7da38973d81f12200018fbe8151572",
+ "Name": "matter_g2_mul_72",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fa7f8fbfa1d4ef5f001a451c55ed261dee344025e599884b29d086e15665867932120d33bee579d5eb1b7e6c7299f310000000000000000000000000000000001f06356f793350b17b47a623059a068800ca1eab6089c7c146182990063e8e23bbf40d95a42bf6e976224b680b75bfd0000000000000000000000000000000008807f6606d2302450bfd8b38fd4147b851ff59762c1ff48f9442c4d7b77a32c5e023821eb47fca839a27fde60e5f61d000000000000000000000000000000000c5b92f1ca9c20d4b6b11d794a5853824cff20d9267a20a7aaa4bed8bfdc728c4d4d50feb8f0b569757b97f473138db1ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de07",
+ "Expected": "000000000000000000000000000000000b8a715c1c2792a30f7ad752a808b621c34af1fb7f1e3392a36ca9481a019108a21e3ef338a1d05f2f23ac3e2cc42ed500000000000000000000000000000000101375c9de592031c55a7a62189fd3fa3c565abf7c64724796dca3b1c7a6e6834a16ef1c4e2afd6ce2e69487260f0028000000000000000000000000000000000cd385ec8245431d3b1aff88453db7f66a5d7888a5c1e0dd0abe9ac7db752933a343b8be53b7bfffb704768ef0a3dc5c0000000000000000000000000000000015d55c8cddb8715e25fa260d1e1fa672ff76eca7c80d19d00678fb9d08759b810cf266ef0a7e9dd749a576ce07240fa7",
+ "Name": "matter_g2_mul_73",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001191410ec6c5ff628bd25d35965f5e9fa7f3c3d8c0a9a1ee7ae37437a97c25e221110d892e2c7a0e9c8e386774eadb80000000000000000000000000000000003be30c25a18cdab139277232d8888f6d13112c9556895af8030f1893114d5845d895df9afe3c6f9ff7ffb1919adea9200000000000000000000000000000000197f6b4e38be0358a3f1722664c61e62587ecf5467f8aadc3a236b47682a75cb76bafb18a5c556b321d5da49cd4bfd4e0000000000000000000000000000000002e4ebf7f22d929b7421a600e67fa2e64a59edd87a2e2eb9dce1f06d3c793f1a812bcdd510e654d44fb4c1de8c64ba9f0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b6",
+ "Expected": "000000000000000000000000000000001311de31229f1825d0bd2c9d726fd71e05828a20406a4705ea65f441537486338022bac4e552bf3c25e15717bee00ba400000000000000000000000000000000052e082cbe36c854a028a041981fed87d39fb218a88208aa1096e260a3932a1155db7f306c32d133070b0a5bb6d161760000000000000000000000000000000003269d4afd20002873f4305018a4432c1925eea28486d657cb458198ff2df9d304bdfc7455233243b1712d8663591d460000000000000000000000000000000013376fb98929cbe7f7d090d1c9d5c4f6332bbf25470aa03c35a70481931e4bc91c937029a5e11d2a3418eab698361227",
+ "Name": "matter_g2_mul_74",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011c6f1dbccde640f63ad7d40089779d01075e26269421b4ce12fa5341f58ee9110f17d08dc1052426f2d00da2dd70b4f000000000000000000000000000000000740b147bcdf06705971c113a5cc12fb37345dd59f2cbb5ff500ce2b347fc5a8199cb3007a871670d5093f28979cfade00000000000000000000000000000000046563ea98b5e85b3c42222d5e0d8481e6aefaf077a1b99f2b4eefb397ec846aa3659aacda569054c9c8b9b69750272b000000000000000000000000000000000812d887943506d68e3525ced9b979354539b7b14003a3169e0084c26326b92be67346920c9a99ef0f9638e8991296feac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c79659",
+ "Expected": "00000000000000000000000000000000021166263d1a443d5b2eee9aeca3678ae4c2b44d556a7cb9631d47e4fa3bb05ecb94d6582f4ca0cd787027fb5f2efab60000000000000000000000000000000015335d034d1a0ce78e1246a16e35e0075f73d4a392da1e05c11388084cf80bf31d499e57c48f4be6e72d3abc7b387ec6000000000000000000000000000000000deac4ae1900a4e1814624fb4b8c7a3149fa9cff2ca97f02e7d6765e034a1532a7b8475ef7aef5ebb851063cf4b9e79500000000000000000000000000000000161e3af03f226278a07ff3b08e5788f6c5029b2c8293e7a7e3ae11c4d78676b60dc0208cec6b82e1714d976007fbb389",
+ "Name": "matter_g2_mul_75",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004c8078fe8567013e8d05a546934026cdeee7d485e30d739407db16fefaef53ed7bff0f9adaaf064aff014ac919d91c600000000000000000000000000000000107cc17f485af7f22e07cf14c5cad6368323f720511fc9dda677b360567f769e47a77f61274927ef9b7be48a77357ec40000000000000000000000000000000001487f0880a6cbdac33ca35b9b65e4ead9d8c2e9180c993bdb2052060325aff8c62668c643f0cd9b4bb1f06a3dc74285000000000000000000000000000000000d4b2d062e31fabe8d2a329dbd6417673a519f455739d140246f2b3e43e20f390088c08e545bf0419d796ac71aebb5198586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d",
+ "Expected": "00000000000000000000000000000000120b4434babedbd8ff295a6e2ed5fc7af0548d7e60663110050be797584c0cb638988201ae7707cbedf0c8b3dc5ced85000000000000000000000000000000000d2de0a260bdd241a145e3f68a6de48da4c65107a500e02bfeae6ae7dc428026c7c3e9bdda9a3069d2744705df2eda9b0000000000000000000000000000000018a237906c0e277541c4f00c4c2feba7cb2c9b87709c18b62b7c36d78fc118cfd65c127765e01dc0ae5875b9552bb45300000000000000000000000000000000197485daf54e98e097b6bca24b0738682969256decbf3ebc05f6982e4608829f37e2877937b3f26b88efc3deeb4bfacb",
+ "Name": "matter_g2_mul_76",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000811e9b0acfc10830c074c5a4d9f4d9382461eb523a61dda0b77f1c43b285fc5c1ef3a1fafd923addc9a6e904505a255000000000000000000000000000000001113102d015dbb509f0b8d0d0ebb4d3711c4f0e1e3d55fb0af247dd24be4fec9d6fe3ad73fbdcfe206891bcebefee4dd000000000000000000000000000000000085aae9e58fb97b96ca3c089acab7bdbd0c3adae141bf61075f5c13145b0d07113f1075dfb959bc7c2d3d3b3a06ab2a000000000000000000000000000000000bb5eac8125807c10270d94e5bcf278241d6fa82f68e41b5529b28aebc88870af55881db526f7bd221a8c4c0b29a1b7d6e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712",
+ "Expected": "0000000000000000000000000000000005de82540aa67c69b962d292133b09e6593961da8944ce02557141abd19ac471f766b4083db85c67a44b65dad2202488000000000000000000000000000000000cd999bf3cb004074fe9f355cd8dfaa7b9d3439d902fddd2fd0688419b5b7f8c4300ab26b658936a90c0b8e1488249d1000000000000000000000000000000000f97ae779429a5afaf7a3343586eea84a4e76f00a1852ce42a4940babd565bc8d61bf72fca9b123922f1ccfb1db8c06b000000000000000000000000000000000935960fa941c27e74234a07857ee680f53c31047235c6152d1669724bdef37ba642cf4e0dd355443ea470e6430def8d",
+ "Name": "matter_g2_mul_77",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001335276775545fbb4c701beb57cb34312108c9f1d46b4aa4b09a16faf0e648b4e80848bf5e75ed8730715f0107afc9820000000000000000000000000000000006ffff8736bab41b4ee5681b741a81fc870e648001027161144254d04c678e4f954e9f191bd8b26201aec681cbf0654b00000000000000000000000000000000026ede90d14fa0885baad21f9631bae058573251cbef5757bb8cfad061f3bdc78834fa5862dea19a2236c014b0f1652e0000000000000000000000000000000009844d0cf7f6f3401145d8d720defa577ca46b49e04e39c4c139ec6811a574e7dd5ce3acd00d1ce9496f10dd15c6d94685cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a72",
+ "Expected": "0000000000000000000000000000000001b0aba02b0e907c03d2f4003083c824ce60f2f55f70dc6ec7c7f81f3d0ef4bf533b4c94833e36e8aa7aeec18b7255de0000000000000000000000000000000004fc227a6ae303f3006f75193cef7c653e6bddd28fdb843b41c7d39966a701ba8fcf611efa71abf059d7d98833480e69000000000000000000000000000000001077fddd0bf3d5c80eec653916f9095e900cf165315d74a872219285f62b5412536e43c4cdbc120ec5c7753318852dfe000000000000000000000000000000000ccd90e01c1d4a00f0d9e29a88e8134f2cf68162da66bd343645a998730190114a6921c9b048dda58b60b42a133287f2",
+ "Name": "matter_g2_mul_78",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010192b925fca096682acf138833b12d96bf97c9a2e69e4266eaaae1785b9008f36082e23e2d42341427edce24449935f000000000000000000000000000000000d5b24a94adadbf542aa663114096bc670e1b6c99f3b661f55de121922452534faed7f68d6b431fcf6f3e379d7acf6b6000000000000000000000000000000000acdbcae49206b749d8c0d21017a33e689ebe26804d1fe7c863a2ea4210c3559805dcf73685702bc56e644b4e02614a9000000000000000000000000000000000092309d684fcdf44bfa321d473060dc2d8a8c66c51419894a3fbadbf1b56179c31dff25403b970d543f1dd0e19e56cf5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6",
+ "Expected": "00000000000000000000000000000000185520023714580a3f235e24316478b8260565ffabd39670811519066844e131e337bd62ed2069bc6d2305e6638e539700000000000000000000000000000000055fc74cc7cd3fc393d5b5ab2419414effb783ff4da2516e5465a4acc195339c7b5238be4e0744b3d7fdbce46ca7f5dd0000000000000000000000000000000005f584a0311c02d611c15163529130a2fb3dc853083e7225b791ce5ff32d5ef7039c80edfff317ce9ddeef84443b5a51000000000000000000000000000000000f9d5acb355f767cc6286cc09f6df232532f9a0e9e4ed1fe28788abecb200e22066c23f3ac6c49c47071cbb023e70183",
+ "Name": "matter_g2_mul_79",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014441b14765eee30e8131a7ef62c3b59370f2f6f0dda20fb2a3654fa09492bf695de1d1a8f250bfde3c7d2ed805ffaeb0000000000000000000000000000000019d813f8be2519e89d42a9fd3fef09d44a996d6a4713a9c224bee10f0ebb196370d6231fad810edf9cb4c875f08357890000000000000000000000000000000001a5abea13e909bbefdb51ddc699614366f271b2f6490ac8efcca7759833f3feae11057ab1b9ea32311e7b6ea6de110c0000000000000000000000000000000003ac2bf3c5486ca176e34ec5212165cbe04fc9e8c375e3e999a31fe014eb824ea3f2d06b9cf8b86ce3a76960cf2eb4d7535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b",
+ "Expected": "000000000000000000000000000000000ceb56d75f3aa1548c50d7780ea1e33c3d069b2f37e7f96be6a8ec03266fa8d0868822afb3b2e54750722266f6032a8000000000000000000000000000000000080f15b7f9f2c22f1afacf558267b5b84f3a6d199fd3349eefa2e46c4f332849c0955d19d4513151dc0f3b566c0058440000000000000000000000000000000013305f8ff6080f7da05c28155c0c2bc1c78d855cdcff0bb2c6b82cd5107d7a070d0830e6705f6832ed5baf75a659c8870000000000000000000000000000000018f4e136859b4ceb230450f9abde0325a4d59db98279d7fbab710305ff53250dae1c8789cccc27586c9b9df5c0c4722e",
+ "Name": "matter_g2_mul_80",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000598e111dcfeaaae66d1522be2a21131350577253a3f33bdd74a04b0bfba2940e73b62fefa8f0c34c4aa91b633f6bdfd0000000000000000000000000000000017fefff7d94afbeceb33714e9b5480c3a2f3eabf9d7f6e8507ae54cb65f69b21cd7d04d23f24e3a272c589f572b91864000000000000000000000000000000001652e3f5a99ba8dfbcd1f90de955ef527947642054be603c1b84b24bebb579b78e2a0be426ec21d32783a0e55f0178dc000000000000000000000000000000000a6c9ec91e8bc86ab198416cbc76239f0ac0b903f40310ee1f2066b01b08191538ca913c2736f53f23ef37fea13d52756e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a4035",
+ "Expected": "0000000000000000000000000000000002a0214be95f020c70221fb4fb6856af7ce3845a4b607340f85127b52f8a204efcd94a152835860a4ddeef84946671b1000000000000000000000000000000001767777740a9922a91c39a36e2cdfcd544df902b31812ffc88418dab7321f73406ab142055b5bb264c187f2d4f2d6f9d00000000000000000000000000000000026e6941364c74997506df0f9fbe6b2769839e8b7c7293f4e63d13bd7bee90ff779cf82adc2f23c569d1e13826cdb0e4000000000000000000000000000000001618ab2ffd4b823b9c9776baf849641240109b7a4c4e9269f3df69a06f85a777cb4463b456023b7001adac93243c26f5",
+ "Name": "matter_g2_mul_81",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000072e022c168461905f798e87425f2eebb517e473cef98c255d0fe434863ef5811920af65bc946b29d489b5dee1066c56000000000000000000000000000000000e7a9872caa82d191f6014c845e1b3ee4ea1ee89852b546a2c85ddbfa3c1d4ce99002e3d7732ccb8cfbd57d550285ab400000000000000000000000000000000144be65db373f6401d76e0ee64e51076b861e8fca596dd6a7f3b5735c23b0cd13248404fa0969ecaa701663a1032f48a0000000000000000000000000000000014c9e9c5cffc4518889f7742440053678ff1d9fb1a1a103d0c1f762b10655bd5849ce98f4bc5eae80bdd9e767aae4523a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff",
+ "Expected": "00000000000000000000000000000000054ce66b9b0b3cff6637d6cfdd788719d4e33516b98402d8fba54725309307711fb576299ba99104d4e7df0deac9ea2500000000000000000000000000000000055e06ff52cda9116a98ad3709f788d39db53844b7db58a57af52848ce1c59ec2a1f083efe79c5994b9291a2d1020fb900000000000000000000000000000000040c9ad63698ec78d06b41bdd6f5eed089b67f106348f9300f822a2d61ea1e5d2ddda0efd1025825c99cb0e243573f7700000000000000000000000000000000195dd00c48186f8d1337ca857aea02c4d199d638133e9cbd2dfc5f633502f656343746ec2a416465c3c0d4e9d53fd097",
+ "Name": "matter_g2_mul_82",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000948d0f0c20715f8658e1f2b4f9d32d851e584287225a2f47735a1f4c241b07f8d7c5dd8c13bcdf84e97d49817d4d88a0000000000000000000000000000000013c064548cb756b48600dd535af8eb5b9138f984bac0391df2e90a204fcb6c36017df910031864d802a2ff719856b336000000000000000000000000000000000000b7eeb7c9a01be88e573f196c2a531635baecbc8cff9af385455af3757301436686596ec7fe3618af26953c49f7450000000000000000000000000000000001332f4dbd5461ab9e2c8b3c19c6ff407a071018c92d2c17c1d1d481c24565276c0f55eee8692016c1fd76d70f44627cbd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b",
+ "Expected": "000000000000000000000000000000001141b59af8fe6cafdf2e247fcb0ee4642a9b4022b6d71163ec9b6ac2f7d10ee3c5c0173ac686b03cd6a7086b039ec786000000000000000000000000000000000f05ba6973c5d865ac5c037583b65eb4eac826b5a04a7ebed1e10bec6ec7dca93b1c2eba70ee0189fd552d5023f2a87c0000000000000000000000000000000002e54475940985ad2115223c5ea3a4c95890f3e9992e3e1a6df2170ab77143bcc5d29b9dcd1ed3bf16e545e9be21a8640000000000000000000000000000000019acc4705955761518cea482b83e3726dea8d1f66a5f19b06cd7ff95828e15d1b139077e0d274b0e6fb86c027844d97f",
+ "Name": "matter_g2_mul_83",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d3ee70610b5029a28e586f0f3e65bb19a263db3438710fcb8073e1b25f83db50eb5bbb9d75cb20952a225023f747baa000000000000000000000000000000000682f7d5cf9d182b20ee88683f3915e8c9b03074a373e573aa57232de4e997bf155acf680e365aa0988989dfad102b2e00000000000000000000000000000000143962963e230a9154dc328f9583f5be6923a3b10ee7b1d0cd5f5cbff13913d8ff78ca315be7387900a50b94449884c0000000000000000000000000000000000f4f934b42452d41cc20d7b1ec547bcbcbcc10f215364ccf2b864db23a09d06e94c7a87165dcb691f4975323486757ada300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d",
+ "Expected": "0000000000000000000000000000000016fb5839fde95111742255b33f040c41dbd0f142d1daa8abc7c63008ba9f63f07381d9d6128240ae9b6cac5befad84e5000000000000000000000000000000000389a11727c356b8f3bdb6a73bc2f6d2d73d33d287365283359521dcac64f17810bd58c0ec5bef4db253bf630bdd9599000000000000000000000000000000000629a8af1bd0c1b1b6d7e447bb779663d7bae8e895e09418bc350e644d7022fa877496f30e2018f5dd1c9683b2715adf000000000000000000000000000000001950185d2574fe0c8277e3f93f59dc5628ec3487911ba9c3194a2f716116ff0bb9a39dde802dcfaa61633ad7657a578f",
+ "Name": "matter_g2_mul_84",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005f0fd4080e26971ab16d33aeae04220ae23781da3179e38190082f1d167514bd73bc8ef976a2f333570e9f56a6c05e6000000000000000000000000000000000e159905d29b52ba61575c3a263093017783e1028b3701ccf060c165ba33a765b5265a9b1681c1759bfe2c9c401275e9000000000000000000000000000000000c5ac0bc29a49a7c37d772954da850e6b5e301e230552be9a94017d770ebe2cf4dcfaf104633623e024aef6db57892900000000000000000000000000000000002228e7f42a9409acab49cca82cacf306f6c6c29fd9f7e2ed12fef2d16383cdb7bb2b39ad598b301072c615232db1fa833e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b33",
+ "Expected": "000000000000000000000000000000000024c03edb9b54034eacca4b321d51397348c57f406b074b16a9d6215e03f842380f5358f5c095fcf5bf3cabcbabdc260000000000000000000000000000000014e62dc442135d729f65090475fb408ebae132cdf2c2932582af887ed54696f3cd15b163f11285b99e8d8f809aa2e65d000000000000000000000000000000000438a2c99df216c67d92b99d9ee8cbd0e9751e538074d146767bde9675ae3a05bdae051efcdc6bbddeb1b7a8288370ed0000000000000000000000000000000007c462a8f5720e442e1917bf75fc3c3dafab6c39c80d0b93d81d1db4080f6e199be092b4b025e7b02efce4f30d00299a",
+ "Name": "matter_g2_mul_85",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000180569ce03e4a0155285e733adb18fbca71225507a7adf01cb8e8648891525305e92087f58378f4fd8455d5632ad660e0000000000000000000000000000000011ab84e42f10154e306a568d7cf7bc381000f0add0500cb508f695a3b283ea69d140aa0ad48fce2d2d6fcafe60761078000000000000000000000000000000001136c3016474d6f475609606e8d0269fcdab9fd3188a512681cbc41eedeadfa3b3d9355e5b4503e8b5c3665e49fdf3ab0000000000000000000000000000000003f56cba1b9cb4302099b16b09c2602dfab80d1151685ef78e5054cd454b319adf8b5998053a5b9fddcffa020595e3bfc48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f",
+ "Expected": "000000000000000000000000000000000e8137c15436264b5960c27d0c22be7fc5d56a12f43b3832ad0d7f5abddbaaccefd140e2f7c476b99e6fd9b3a52743600000000000000000000000000000000019ee3caa56f0329a2e2acb8907b3edb21f4eee73e312352796b51282e097f9b10af61805d5c222332888737c7f8e227d0000000000000000000000000000000012cb9c610391940fed7882a5cba08eba4226c36eca8a2ed22fb5e752e0a1a5ec556673e47013258b499268f1de77bdf100000000000000000000000000000000031b769f606fa25b81a982db86a1cd442ed738019e7e64728ecf485cddcc17d9dc271146196178740b9f05f56627b061",
+ "Name": "matter_g2_mul_86",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004d79dab9eef873f3415d66172bab7166ce0c71f322529bdeffa915c1b0d3fcd645c91dd3450ba61593ffecb95edb91e000000000000000000000000000000000d611a207d3222bba199fa083d0459675cb5fa00839fb4c9034ad868fc1e79d653c18651771431d6fb6b6b5ce8cf6f7a000000000000000000000000000000000ce802ecb106a4f0ca4efdcc058dd0e29deb6a5d30a2c15c8eda896bcdd3ac19053c10105328d239b26c5ddbdb3a95fc0000000000000000000000000000000001073e142621ecbeff6f81453660362545751f992ffeec3a83477fed3e6215a709ffe0d17b65d3369f8f3913bf000e844228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c",
+ "Expected": "00000000000000000000000000000000080807a0570b628549629d2eeee39de773badaccefb76e01efaecb0ef0356f535d32c3947f0613bc7d847ef8c8778f02000000000000000000000000000000000e8c091ea30465d204ace72015cbef29645206390fd92ba7c4aa0fecae4ecee53c0b06e1fece99511efd8c7e9cff1a8c000000000000000000000000000000000c881c678c94d80164bb3295acf4341fe6c726ca64a1a015c890450e719b85720f41f80369f99ad3e7e3169ede0113e00000000000000000000000000000000008a2fe01a7100afda40091eb0b2b14cd00b7a4d8bb5cf9d9a3847970a94f2035fec7f292c04c38d7e49890e612830aeb",
+ "Name": "matter_g2_mul_87",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bd84f04b3858b1138b1b429c7216d5d1b1e99c1e0fec26440d59b1ad79788c2d5583122c2ad769fcaa6d10d816a1f1e000000000000000000000000000000000387977ed1ce5da51dca230531bba53d17d3de5d593ec576cabfe6463d5164d7153025dbd4cb3525c4145c4f6b85fc76000000000000000000000000000000000a19c943a90fec6921367a2edc5bc38a5c59839cdb650766a2d2d068242463dd4460bd1d0e7a7fb0e3d2104704b8b3730000000000000000000000000000000011d99d44b200feebe00bd42809e3f67a23cce88a07165416cbfaf4db14420f99e54d62db4280d2c99ca0bc3dc41eddbea417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f1",
+ "Expected": "000000000000000000000000000000000d17f6d9460566d0543df2666d6ade685565e668521a87fabc58148343085415fee92c32907311c9d04713c34bf7690d00000000000000000000000000000000185da28f07b86885031ff5cda913a85b0e4d07673f456ecf2a9f0fd1b21d99e22442f9b705039252d57380b6a42912050000000000000000000000000000000014a4bde5973ef43691b61b3c0f6c2fdb4bcd6ea88e53e2787a7d93ad6e05ee2e69f2799712520f72b3c577ee278008ec000000000000000000000000000000000d92a565b3d8d0fded054a75198b31c521e3223650cdf762fbf7b851f7ac0fc66b8c86c20b905117585704c23b27e7db",
+ "Name": "matter_g2_mul_88",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006a186aa584a466a860849c78e4922889c95a4ac6f39c99029fbb422c43d699a8baa51aa4ef51ff99557babeb3e9506800000000000000000000000000000000065fb15b5a0923bdb52dbefc7e9f1a898e32f17d610bac829235446fc5e1913fffc8176e0fbd33091505761f1d06d8920000000000000000000000000000000008bd358698fd073f660ed608462cfcef1da9a59b10905f1d98c4fe66958e56802814906430c10fc25a4d351d91f91cb0000000000000000000000000000000000a53638b1b6c6eeff468e099446300ca7c7bd899c6494682d14fdabfa9cead0bb37a0325d99e7d0ba6341cfa1d257ba846561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb",
+ "Expected": "0000000000000000000000000000000008b1ebd753364a5a0a6296ab48b348f91668525c0d5f7edc4f2d29844592f34a209f9e77f94ebb38ba76bdb3f96063ec000000000000000000000000000000001062e0ff0a67372207052e2520d8b2823764a5075c94011afd6c60288e187ec77e08db01c95dfa195f2409b58c9dc4e5000000000000000000000000000000000cc2b87b613d97a716586f371c457fa869c2b8d1fa1cf4b9e8c34bae23e0544752b997df4711d0712ec11d3a9d96ac2600000000000000000000000000000000140eae891c87c2026f0b1293df2bd8ae2dcb0ab3f8de74676f37c905334ac1f53fe4b75511691dcf108fca51abcd524c",
+ "Name": "matter_g2_mul_89",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001070b98c6348a67e996626ec2752f45e4c007e9c9668459a777c03fab633c10236a1c5be99f3fd950542d5648ef9e88400000000000000000000000000000000073a564401cb1a3a53334c0a55da261814d27b86ebf40b02a76b20973ba2db92e42c138ca7790261c2d70401c984bf470000000000000000000000000000000004212d8a9e4b01f5c6814a88561c2c6143eea61327b031a2e0e4bd056c12dd7098fdfe4d1511bb441ad42b55b584a7bc0000000000000000000000000000000005c5d23824b0fe05eb962194550681c57c1566b315efa8ebc90b3593d7d86ad18328baab8118c9f47eccc0757588591ccf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf",
+ "Expected": "000000000000000000000000000000000276a138edecfc9378be4e241d64cbb48bfa6fd4fb1788f8bda870d5ec8b2132fc9ec888ef84c43a50b7de0527def36800000000000000000000000000000000153e90d52c747859f88223555bc8bc4e8b6fc846fe7028de728a4dfa085c6e350f9f1d12b9dca4ca8e07377648544400000000000000000000000000000000000cef00e7217da6df0a6d85f40be69f154300c423e86e54e513b2491e65002e308445238082da69aa9e5e83b5f4fc17dd0000000000000000000000000000000008da1da2a0d1da9d2158b9408dd9b0eaf414d237b8219fa7661e40c1a88eac2f9735d0dd6ad67b85aab85952369e8287",
+ "Name": "matter_g2_mul_90",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b1b3053774ad5515a20bd4c556d2b3ba95fe74fd0c955069c7f933dfd718ede90ac295f5a675f1c29dcd9701978353700000000000000000000000000000000145746ce88686021a0635bf6f0aa2f77c48bdb364cf4ffa804a57f95bd69d24eead05fbee24021c1ef57e1c7c7b894b00000000000000000000000000000000010ec4795a0762b86f3b83de1198698af67fd1b1be3ddef48f35cf82bc96d886fbb4c75064f51a9cfc5f61630c95d0ad1000000000000000000000000000000001465e31f58892466b8ae4b76a239d9f8d1ecb1834886344013cd1df0be13591798868d224d38213a6d75b02a1fde0ff2f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5",
+ "Expected": "000000000000000000000000000000001484993096c210c7bebbc4c0bda24b44a70e982b2528215c0e8578ea55f1181472758caf935aa0a3d6820cdad753e2f90000000000000000000000000000000011802324a6e03c3174bbe7261ecf3812c1a97e1be27269214f232274a3bf82775d47c5fdd70fe1c57155068b296d394200000000000000000000000000000000050f43c874c1cfb5fda81059cb7b4808492632fa20369dcfb611e503ded81a49dacff253e31d7e27ee84bab79e3c5d53000000000000000000000000000000000ef945b6f210fb09bf0ad5bbd4b5a6630f43304ddcb396807c967eb5146741f7432bfdcbd7e5f3d29917781efb62e6ff",
+ "Name": "matter_g2_mul_91",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f39e731e6ddb7496448c912ae314e833d28208252c7f8e27bcf7eeaf1da6e2310538b4ef0d55401c6552e91fd70691600000000000000000000000000000000069d3612f924961f827497028737000513548ad8e104acee28f014e730d4752a583cb9a893e6169b71966a1c4a4ad2dc00000000000000000000000000000000090899907edcbd336bd4fdad0dd67c578ced4481a25b864b32aef920842689a2c23265277a6e1d4a1dc1b5047a9f79a000000000000000000000000000000000055ba64e2502baf68e46c759fca30247a080464eda2b32e7cfe539e545d6aac6dafb731c2c45749e50513979cecbeb5440ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e",
+ "Expected": "00000000000000000000000000000000028233bf12e8dbd8510f119be30ea1fc13b755c6ee3ca2a3637a3bf8f73776c9d1fe231b713396ffc579ef9320a05b150000000000000000000000000000000018e7c00b8047d64ca0c5df54486439c5fb3d1414c2f71cf8a3ed591b7c45bf18b37473daeeadcb625eda638885ddb9870000000000000000000000000000000018b89c9b6bf9ece36f1eac08fc35ffc9f7f964a0a9b19d495ae1361fb4bc98aef8770efb47d9961aff694b878d659818000000000000000000000000000000000eb2fda2c29c6761e35ca4c9772bb232ea0d297582af4f50ef76c0b74fefd414b535e356c069f54ef5224225e95be6e7",
+ "Name": "matter_g2_mul_92",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000042f1c8b9fe81cdcabea047d0998a1354ce09d62a14f1d0e9d188e2f35f2e1845c2b090c5e157595b33108c67e6c184c0000000000000000000000000000000018e69d3564d4ccc0306e1e6b227b0f961aa9afcad59d4ee1737f980dc876609c59a4c6a3506f987467beba0764b857000000000000000000000000000000000012ce5883156588cfe0f4838f819f985b09f1eab40a5ea8e30fc5d70d029a01a4537641248f4c21dd203909e0170737c80000000000000000000000000000000002888eb9778a4045feb5899dda258657b9f41345731ba630fbbf186b3be4b58ffc7f48abb65b693b573a73f85440a7a7ae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be5",
+ "Expected": "000000000000000000000000000000001239935827fb2a269ab064a3ae2bff2555f89bb3a71a47ae815ef755fc1363a89d20326855cfdd0e13f6c85f727bbe120000000000000000000000000000000012fbba047478b5f5b07a582200271a0c331d6f76864f9b6c6ef8ae6b0965eda481eddaf72c7a887b21719164c633d39600000000000000000000000000000000017eb4353b413437244983554a639a9253d105395ff9652504df7700d879cd9a32d5f0824b1eaa532bcf2fea34f8f08800000000000000000000000000000000054ea45475c01ea0557fd143b21c7bdcab6d287bf6bf4f88b6fb06e02ac6fc5ba96f323bb1fda3a1c4d8f42d01d267b2",
+ "Name": "matter_g2_mul_93",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000051982b46a819c74105cb36da871fb2415328a1531d155856f6551bd043eca62ddb61f24af429edda830fda31e22cd340000000000000000000000000000000006449e5bcdb5619aac542f6633ee3e06a4fd56a3e1ce4034efc608131ff6ead70ca63e70f494f519d5c577ae7119c8c200000000000000000000000000000000153f4f5dddd5801fbf7f88a735b9170d24d5b63861d50cde9644579dcff277cdb0d5fbfc3b3b819a1172de05afb9135b0000000000000000000000000000000010fdea84983fe6c08cdc4b4ccd462bae2ba791ab5209363b10b3ef342c9a5e92184e9d8be1419e3d88402bc05bad5fa21268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c0",
+ "Expected": "0000000000000000000000000000000015a145e379b7ecf4566a039b753f91e8ad75d9e9c9a20725ce34a900eb9a1bdf66cabee2100208d7792a963d1fb8c02f0000000000000000000000000000000007f0ca14fc4e34bbdf5008d632dd112c7368e037ce019b7c4ec412000ac02302c85ae64f9ab495361fa5b620e46420aa0000000000000000000000000000000017c00a08bba18426dda40e773d79733030b5b3b199a62436ed06b773fd1f10688e8af00e8a223cdf242bd1ebbedbf634000000000000000000000000000000000a17365cd9f7655793682b72e342227048da0cff88f6ace33ddab548ba126017e4b7f7439373a893e3b5803e662814b8",
+ "Name": "matter_g2_mul_94",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009b011f793d9a939d916d058ffe91b58138820a646cc450389b3074ae3715d06ddec1075afecda71c65c7ca085210c740000000000000000000000000000000003d4d20f4b93c1e90a0a06bd534d8b4fd64e4c4aba77ae42cf4c5b2bd95f8b02ec4069ea246ff46404e6c9eac632fbac00000000000000000000000000000000051e88c3adfd4d6a02d3f03812362a6cfba3a6c69b9aeef75b51106cc7f1750293d61e31f0ea29b5d7aa56debb6d2aff00000000000000000000000000000000086d9c4ea6769cdf49ffbbf7351023b4aea640e8c90f9291222fd0b5984bca4d481bf7e10df921406a34804e6a09f99df9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169",
+ "Expected": "000000000000000000000000000000000081b4dc78b74250a82da9d803876add659411cfb467860b2ac6f0f68929d6377deb71d6acc9ea8fc8c1286b8f92056e0000000000000000000000000000000002c5fde71346a255ee9dc896f654eb2e0c66f4cb4c51541d2bbccf2463ecf0085a22b9d2bdc5bef39d80c4477824f116000000000000000000000000000000000ebda0cd8bf6ac7e86a1bdbe44ed1e15f8ffa1fff92afd67fb564306882f35037b61cf0d93f278f15149c04a2e83041f000000000000000000000000000000000fc38aa811f5ec015f10a99bf175f1479d4983c9d2180a5e3da88b4e9b62ef50560ff0a6c2fb7bda4c46c54551f8390e",
+ "Name": "matter_g2_mul_95",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010d48bf523f3909cf90aa58a9517ef5421f1212accd5e8a0f830aeb15a587e215ca9c340bb846b1d0474e43840b2af79000000000000000000000000000000000cc1a3976caf97b9d59f448f6d9f413eef8904f360c0cf912fe942b38d7fcc637a17038973a133608ae769d3e389b18a00000000000000000000000000000000069a6122c6f0ec68834b7617c755a7eb33a80a25acf95859da5ff03316447182f122d20d993b04e79b6fe859b7adf5a8000000000000000000000000000000000058c6f8c297524319bae6722e0a957d1ba0f75ee3a8aaf06148641c67925d15780e419a38ed7e07410e82769da74f2d070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b4",
+ "Expected": "0000000000000000000000000000000007b46fcfb2cd8efe32754306ff2f503d7434168c1c3cbd7c80470cc5a5c8bda10a80bfc0129da349724d2d6431c5ac90000000000000000000000000000000000e1078f4f4ca993d90accbfc036219507bd22d00930ffcfe1227780c00914fcff845698b2541510daf59cc83d8b947e7000000000000000000000000000000000b7c6d9951570e685d3a71b19a38f5485f974f85fe8cd4b4c196d33a18750b278b6d374483d81dc3e15c9b8b9b5dfdd6000000000000000000000000000000001003a239ea4a2f213f0f646bdb62cbe4f98cfaf7298d8b2e0eaa07bf3f939e779caab5ffa0033467c5b297166df657d7",
+ "Name": "matter_g2_mul_96",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000156ca5e80be8c8c03a5506ce9abd22a9d4958c372678c0caf6f1329898507dfcb1f06a9464cf080bc6881fa5b7df1ebe00000000000000000000000000000000088174d486b4086b931010da298a399e15b60a113e08f571e096d3a4e94b57b3a684711318796eeca9319119b201abb30000000000000000000000000000000000b96ff68505c088cc03a1c2dc363b05bc8544728a12b29569bed137780523123eb17e68f4632383c252d81bca0c5ca9000000000000000000000000000000000486fc6e5224c5fad56234c41856e60bee4a6c1046f673bf7d5c1bbb603b141fc91074da5f9d3d41b796a2ebcebd9e74d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e125",
+ "Expected": "0000000000000000000000000000000000ea29b1e059560fec21c3692d4e632a45c88a807c953fa23dbedb271b049d7fc717333b498ed12573a896f872e795dc000000000000000000000000000000000de0d10c47df92010a6635e3403dd6e91a1bf35bfcae82c1008998e86aa2d18a6cfd3f2f1207fde3bb39b723ec4d3ca60000000000000000000000000000000005e2aef9cd37430b15e5e76b2c7870630d255f630c12e865caefe308a39833e00319406746dbb2af3ed32135e91eed49000000000000000000000000000000000c229fad41b0d27ad7b5db33188fa70b97f22e323e429ef65fcf98f5339e908c31df8859b863356e0fc90538c5c49cf2",
+ "Name": "matter_g2_mul_97",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000121fe97c62e068988ebff21d8129d52aa903afdbb62862c7fd99564d9ad72182ab1f3a1100223ae486cd76f6938e123f000000000000000000000000000000000968ddedb04f52140160061828b5f88dfd09aaf37df625ee6f66b9500d6608df31c7edf86296eccf8f9918b051a5e4df000000000000000000000000000000000b7491cb8f6252e3861d7160feb0afdd736d27886863ec0909a7cc711a9b71aace18b17a00a2999dd57ca1a74f148516000000000000000000000000000000000fdb280093ef45b12b694ca3390a865ee18e4c04b231e2c98cc28706d4cefaf4e654582ee03f34ecf1dfa9674489d553041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b",
+ "Expected": "000000000000000000000000000000000444a00cfd258bd46f659b09eef17be9929008d3d1c65e46cdc762eeaa2f0b52abfd636e6094e21983fad8171194c71a00000000000000000000000000000000090833e68614be5bf298e04e44527480cb35128bbdecae15eb95d6931a718f66869ddb68352130b4dd8a921ab3f26d080000000000000000000000000000000000994015b1b55340c3839d48320d178b2ffaa0bbff038f7aa63d4dff41a217582fae9613bc537fdeac8d0670c0cf479a000000000000000000000000000000000fc486e2a1680c10ca28d4c3bb22dbccc9572036512645bf868e7693ae4591569c973f9ea26342a573e23a06c2fb4b70",
+ "Name": "matter_g2_mul_98",
+ "Gas": 55000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010d001a09cf5dc3276482185f26ef3f75d28cd6d2667eb08a7fe06c03b99f3b6c4d82390739b6867a314291cc642a8b2000000000000000000000000000000000587846a460b1f37c2e7f491f9a097b4e86e1943d9cd0999313f65627b3907f09b5d5ac1be376a313a959dd136f7e9b3000000000000000000000000000000000af439695556e86b102926d3b40e3e54cc84464e120de3b4e3c5541a6a5bca44151fb0594009663764c1824518b13f020000000000000000000000000000000003bfd9418c1e57269e222152d321b83ae090f216cb422956dd1fcc464f68526cb4a05cdaefc7bbe6e81d4ffe27d64db47cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf",
+ "Expected": "000000000000000000000000000000001375bd5ee66c330796bd8381a26cefa3f40f8cc8de42d4d59a7adbcd3852e6d632422e6ad9a06a6e497b23b17b1df87500000000000000000000000000000000165d8e7be17ecae9bf51a773da705aea42536d0fa3a2206267da50451f5104ee241811dd0e6710a80c38df77b126c009000000000000000000000000000000001559572407aff34969f83c394d2b095a7ae9f53a8e6c923910f256bb87b6ec076fa6acb85465102fd24d34031f88f7510000000000000000000000000000000015ff9ba89b55ef75f63732dec1e64106d7a912a6657fcc970dd011a03b5364117cca46d6cbafbc0c5049db10fa83fe6d",
+ "Name": "matter_g2_mul_99",
+ "Gas": 55000,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsG2MultiExp.json b/x/evm/core/vm/testdata/precompiles/blsG2MultiExp.json
new file mode 100644
index 00000000..b5b63625
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsG2MultiExp.json
@@ -0,0 +1,723 @@
+[
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000011",
+ "Expected": "000000000000000000000000000000000ef786ebdcda12e142a32f091307f2fedf52f6c36beb278b0007a03ad81bf9fee3710a04928e43e541d02c9be44722e8000000000000000000000000000000000d05ceb0be53d2624a796a7a033aec59d9463c18d672c451ec4f2e679daef882cab7d8dd88789065156a1340ca9d426500000000000000000000000000000000118ed350274bc45e63eaaa4b8ddf119b3bf38418b5b9748597edfc456d9bc3e864ec7283426e840fd29fa84e7d89c934000000000000000000000000000000001594b866a28946b6d444bf0481558812769ea3222f5dfc961ca33e78e0ea62ee8ba63fd1ece9cc3e315abfa96d536944",
+ "Name": "bls_g2multiexp_single",
+ "Gas": 66000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000019d5f05b4f134bb37d89a03e87c8b729e6bdc062f3ae0ddc5265b270e40a6a5691f51ff60b764ea760651caf395101840000000000000000000000000000000015532df6a12b7c160a0831ef8321b18feb6ce7997c0718b205873608085be3afeec5b5d5251a0f85f7f5b7271271e0660000000000000000000000000000000004623ac0df1e019d337dc9488c17ef9e214dc33c63f96a90fea288e836dbd85079cb3cec42ae693e9c16af3c3204d86e0000000000000000000000000000000011ba77f71923c1b6a711a48fa4085c4885290079448a4b597030cc84aa14647136513cec6d11c4453ca74e906bbca1e1000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000176a7158b310c9ff1bfc21b81903de99c90440792ebe6d9637652ee34acf53b43c2f31738bbc96d71dcadbbf0e3190af000000000000000000000000000000000a592641967934a97e012f7d6412c4f6ff0f177a1b466b9b49c9deb7498decc80d0c809448aa9fa6fbbb6f537515703000000000000000000000000000000000031d84356ef619e688a10247f122e1aa0d3def3e35f94043f64c634198421487ca96af5f0160384bba92bd5494506c4d000000000000000000000000000000000db8fefe735779489c957785fa8e45d24e086ef0c2aba2e3adba888f0aeee51385a82898524c443f017ee40be635048c0000000000000000000000000000000000000000000000000000000000000034",
+ "Expected": "00000000000000000000000000000000158d8ef3d5cdc8a1b5ce170f6eeadec450ca05952ea7457a638b8ff8b687c047799eb3dd89c2e3c6ca6c29290b64f5ab000000000000000000000000000000000807d135b6b007a101e97f5875e233b41f12bd2ffd77fe1195418a73a4c061248118ea1049aeea44750cd5ec83bcc1ae000000000000000000000000000000000f04136354f45a85a53fb68527bc8fbc7e8c1a0056878012b548a97bfdabcbd3fb8eb3ff187fbe65e1ce233afd2825050000000000000000000000000000000007b15428114e2ea094ba1e64df4c244f80aa2f75bbbf21a407bc84e80bf2a5ad787d02ae8a90cc1c137f0d898edb1684",
+ "Name": "bls_g2multiexp_multiple",
+ "Gas": 126060,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3000000000000000000000000000000000000000000000000000000000000205900000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e84900000000000000000000000000000000000000000000000000000000000b7fa3000000000000000000000000000000000e7a30979a8853a077454eb63b8dcee75f106221b262886bb8e01b0abb043368da82f60899cc1412e33e4120195fc55700000000000000000000000000000000070227d3f13684fdb7ce31b8065ba3acb35f7bde6fe2ddfefa359f8b35d08a9ab9537b43e24f4ffb720b5a0bda2a82f2000000000000000000000000000000000701377cb7da22789d032737eabcea2b2eee6bb4634c4365864511a43c2caad50422993ccd3e99636eb8a5f189454b18000000000000000000000000000000000782c14e2c4ee61cbe7be6e462a66b2e3509f42d53ff333efc9bfe9a00307cd2f68b007606446d98a75fb808a405d8b90000000000000000000000000000000000000000000000000000000004165ef1000000000000000000000000000000000411a5de6730ffece671a9f21d65028cc0f1102378de124562cb1ff49db6f004fcd14d683024b0548eff3d1468df26880000000000000000000000000000000000fb837804dba8213329db46608b6c121d973363c1234a86dd183baff112709cf97096c5e9a1a770ee9d7dc641a894d60000000000000000000000000000000019b5e8f5d4a72f2b75811ac084a7f814317360bac52f6aab15eed416b4ef9938e0bdc4865cc2c4d0fd947e7c6925fd1400000000000000000000000000000000093567b4228be17ee62d11a254edd041ee4b953bffb8b8c7f925bd6662b4298bac2822b446f5b5de3b893e1be5aa49860000000000000000000000000000000000000000000000000000000173f3bfab0000000000000000000000000000000019e384121b7d70927c49e6d044fd8517c36bc6ed2813a8956dd64f049869e8a77f7e46930240e6984abe26fa6a89658f0000000000000000000000000000000003f4b4e761936d90fd5f55f99087138a07a69755ad4a46e4dd1c2cfe6d11371e1cc033111a0595e3bba98d0f538db4510000000000000000000000000000000017a31a4fccfb5f768a2157517c77a4f8aaf0dee8f260d96e02e1175a8754d09600923beae02a019afc327b65a2fdbbfc00000000000000000000000000000000088bb5832f4a4a452edda646ebaa2853a54205d56329960b44b2450070734724a74daaa401879bad142132316e9b34010000000000000000000000000000000000000000000000000000008437a521c900000000000000000000000000000000049cd1dbb2d2c3581e54c088135fef36505a6823d61b859437bfc79b617030dc8b40e32bad1fa85b9c0f368af6d38d3c000000000000000000000000000000000d0273f6bf31ed37c3b8d68083ec3d8e20b5f2cc170fa24b9b5be35b34ed013f9a921f1cad1644d4bdb14674247234c80000000000000000000000000000000008b7ae4dbf802c17a6648842922c9467e460a71c88d393ee7af356da123a2f3619e80c3bdcc8e2b1da52f8cd9913ccdd0000000000000000000000000000000005ecf93654b7a1885695aaeeb7caf41b0239dc45e1022be55d37111af2aecef87799638bec572de86a7437898efa702000000000000000000000000000000000000000000000000000002effc7b302730000000000000000000000000000000002142a58bae275564a6d63cb6bd6266ca66bef07a6ab8ca37b9d0ba2d4effbccfd89c169649f7d0e8a3eb006846579ad0000000000000000000000000000000012be651a5fa620340d418834526d37a8c932652345400b4cd9d43c8f41c080f41a6d9558118ebeab9d4268bb73e850e10000000000000000000000000000000015f4b235c209d89ce833f8f296e4cfb748e8abce6990ce1a5a914b9416c08e0d3a26db89625915c821a5f152b7fa592e0000000000000000000000000000000006fcacb3ee6650a1044852d61c9c20bedc8ee90aad97de8e24670a9ef57483e678db11dd95428915088d76e30cb01a370000000000000000000000000000000000000000000000000010b4ebfca1dee100000000000000000000000000000000018405e4b67f957b6465ead9f5afc47832d45643dc3aa03af7314c6cf980fa23dd3bb8db3358693ad06011f6a6b1a5ff000000000000000000000000000000000c48e0d4f9404ae0a7f10774c55a9e838bb09d3bae85b5eaa6b16b0f4dc2354368117f3799c37f3f7126d8b54d3f83930000000000000000000000000000000007e61f4ec5bc9e2cc8ca471ce4ed40e729b1790cd2c0d9c1cb50e615ec7f346636e77e1cf632c881c07c5385898607620000000000000000000000000000000011dfaf9281901dd356fc5dfece21898a93d9ad9e4e246dd6e18d3ee46d58ab7e77401a3e8d04057e5638ed74fb95688100000000000000000000000000000000000000000000000005f04fe2cd8a39fb000000000000000000000000000000001796abe0d9e4a703962be528e6a5cb65c60725886f925db0e2a89107ec248bb39fa332bc63bd91d28ae66e0dfce8f754000000000000000000000000000000000fb665f5a7559cb0fa1300048a0e6f1ab5547226e86f8e752dd13c28eda4168492e3d3bf2f8a6b230dd57f79b1afa9910000000000000000000000000000000003422dbbe4a06a4c6c9fdf35e54f74b4ab1528abb7249e99898e6fd7affebc7aef95bf82d328dc01d63c25f6a735c35d0000000000000000000000000000000010aa5504b469427eb3584a286191149f5c3c5a745f338278dd95337cd2336d3c4e7532d98eb189fa543824953e7c1c170000000000000000000000000000000000000000000000021c6c659f10229c390000000000000000000000000000000009303f04d568e289a35102b6df883d5ed620355c0eb5d02236718cdaf99fba6e19ef5cee2996268eb9a53ae1ee09bce3000000000000000000000000000000000190be857d602284393305bfe0a29e29a6982ed3f04ccaabafb7e59cdc7eda85c22bc3e8690355c7a0fb7590ae40f1b00000000000000000000000000000000016efd497a0c5c6b59a1fdf2b590eb67a7da8cbe72f49084e7050783ff12a783cad1859e1a0b0ec8ff784c703617670330000000000000000000000000000000017a957ea4d53f4fc8412cb015ae91b38445cdb3e7078d875c465c941e0d9a852c78d90b31b6b6010efe8bd5117e831630000000000000000000000000000000000000000000000c01a881f8abc4d8843000000000000000000000000000000000173ed58056bec9874464d3f23c3e7d3d429d6c8a167fc7f39368830eca839d0eb8260d64ca823f6c785c71f85893d8400000000000000000000000000000000123372d7d4c91a249df8f3e4f8e669087b252ab5d8cf2529a87e4ed3622e4158cf17dc44b473d5debd273261383e8a0f0000000000000000000000000000000000c500eb55ab86381a1725f339f686c7e38ce9113493736f57e999badc661b5b8494d220ded0711e841228a389abdb820000000000000000000000000000000010a4025d823c4262367c53f50e67cffa046e4a1e7c69ff30373772e49ecb310de3b313d83cc41f40a00205722f233e270000000000000000000000000000000000000000000044496e633650ef8f6fd100000000000000000000000000000000152110e866f1a6e8c5348f6e005dbd93de671b7d0fbfa04d6614bcdd27a3cb2a70f0deacb3608ba95226268481a0be7c000000000000000000000000000000000bf78a97086750eb166986ed8e428ca1d23ae3bbf8b2ee67451d7dd84445311e8bc8ab558b0bc008199f577195fc39b7000000000000000000000000000000000845be51ad0d708657bfb0da8eec64cd7779c50d90b59a3ac6a2045cad0561d654af9a84dd105cea5409d2adf286b561000000000000000000000000000000000a298f69fd652551e12219252baacab101768fc6651309450e49c7d3bb52b7547f218d12de64961aa7f059025b8e0cb500000000000000000000000000000000000000000018461a3d444ec527fcbf4b000000000000000000000000000000000027513925b419f6c581788578379995290ab9478e08ecd1999d5e1a05c58144d2f9f06fb8c7fd1586f3ef6a973a3ed7000000000000000000000000000000001292b2ce751f6f859ec7882e14083eac9841b035f9d5ed938a81579dbce07dec2c0202b7f6b25226831cd9c578e893d00000000000000000000000000000000017f36da49414d7706209d52840250eea6f33970fd7eac448ee122f24c62f6a6e09757aa29761160be0f65ba3ce7a153a00000000000000000000000000000000086d471f958f3ff679805751b183fb6310e871ba72bbdefd59c58e95ea62de0820d5affe601757e318abaa5a0c2715bd000000000000000000000000000000000000000008a0eb53c748001536d7ffa900000000000000000000000000000000090721a089bbbb130c21a529be0ede9271a91a2dde9cb2a8e091a19fd2c0a40c390ac2bda8304085c2d6e38e520eae44000000000000000000000000000000000cc64109c67b342b6dbcf86cb60fca7ad378ed6398d89076ed108685c57a07d26e40ed3d5c4b3560b21e519db5875d49000000000000000000000000000000000b0ddd488f5a6f61f087cdbf011b50209a4460c8aa8c5f48c0b30d9cf6cf24259f4e7badc42e1b7a33352949ae566fc100000000000000000000000000000000038430e8db04d205d81aa1632d23919c06f89260c7ac5850bd8b780f8388e53db3a3ddfe98cc55d1c686e582f85b0c8900000000000000000000000000000000000000031133a6c7d698078a7ec7e113000000000000000000000000000000001800ecc167bb714100f31e7610cd3fd010ca299b394c01b1a89afd11b051e92989f6336db5e6d3212f6b04673526d83900000000000000000000000000000000070401d9bba01c0445e0a682406b099f21d16d9c348cc97156769084055ca328a145c134b8c8b58f019d62882b2965de000000000000000000000000000000000287f071bda99b0318e386b27a492a6823a9664084b12acddeda34cb53f827a362ba97c0e652c37bd9d6023041d8c8d8000000000000000000000000000000000fa708ca7dd917541cd02281e525d3367b5ebf5e9353103e1f83f3b894d03d8be7e4d819c123492788855d1fdb63f2e000000000000000000000000000000000000001171d5c4909480aae3b110d01c1000000000000000000000000000000000ef786ebdcda12e142a32f091307f2fedf52f6c36beb278b0007a03ad81bf9fee3710a04928e43e541d02c9be44722e8000000000000000000000000000000000d05ceb0be53d2624a796a7a033aec59d9463c18d672c451ec4f2e679daef882cab7d8dd88789065156a1340ca9d426500000000000000000000000000000000118ed350274bc45e63eaaa4b8ddf119b3bf38418b5b9748597edfc456d9bc3e864ec7283426e840fd29fa84e7d89c934000000000000000000000000000000001594b866a28946b6d444bf0481558812769ea3222f5dfc961ca33e78e0ea62ee8ba63fd1ece9cc3e315abfa96d53694400000000000000000000000000000000000063376fcdf64c9bcbeeff0f9f9f9b0000000000000000000000000000000004b6570b4a6affe97649b0dd7a0ad0df160b37c332a8a7348dd3994cc6b1eb65623b4a9f0a3f320e7278844e261546530000000000000000000000000000000005f8fb4cf5e5313f403f15c59c79b9cebaec78291f2053c49d6427f40f2db2aa659d3a8fed7c7b07b7a5680c7b95ab5800000000000000000000000000000000045cba5ec3fa9acd1b11e1f28a01ebc028f89f96f814513453c553f58785baca8abd4150f334b405fabb925b71f4f4dd0000000000000000000000000000000013daf00b8f53af776c2e8c08d55d164aa15027611188e294230477dc1c926102088f0451222fd2eff9802db8b884ab9c00000000000000000000000000000000002344b4be368d3b617df4aa8dbdbc190000000000000000000000000000000002b29192945df0a74eed138e431962f1d39978202d247335ffbf29d8a02e982c69e96b58d7d92528baf5c422ed633f1f000000000000000000000000000000000d52c7a82fece99279de7a49439c0ff8463a637cc6003320275d69549442c95184fd75ee5e7122e5575af7432e5159290000000000000000000000000000000006ddbaad6cc16c9e62b0da9ab0196dffe92253fcfb2df9aa2076d3f16b3284997d6558cc4432d2aa1705452c4e951e6e00000000000000000000000000000000175f906a99c9d65c4647807879e5eb781532db184d28a326ef9691f8738af067b6a80147bd69327d219fad7c850a7545000000000000000000000000000000000c896c3f9d64341ba7c5f8a06271dce3000000000000000000000000000000000c86c92c9598dde7e6fc5e05d70a34c7a14cff5f400f33cf6cc26e6bf6d9a0bbc421c00f3360721f51974d76be43bd38000000000000000000000000000000001137d93502ef32471f47890a181d7823b3a86dbfcadcc930ae53952f528d617e742a52e4f243c615cc28163dc31bd80600000000000000000000000000000000088f7f8bcbc6dfcc8005b8308cd4780d574d8530e95e7831e52eb2c9a88b846852e111a8389e3d3a67accf78b08326d200000000000000000000000000000000149e43fc675dd3bde8b89cfeb29456f130bbf674cea0266bd1b2e7de23f9a7294096327b452728411ca58acc949777fa0000000000000000000000000000000474d97a9cf29e85d4a35f6102fe7984b100000000000000000000000000000000186a1da343cacf1815b9c8b6c807f536249dbfdb59d77bf4920ad2198a0d83ada21f7c39de6f06a5599f22571cab288d000000000000000000000000000000000ba1ec44f95121bd622932b84bbb4b3d279f69c494ee44db68e3165c86b627ba5e397ee197313fb5b775972798997332000000000000000000000000000000000783e7493e9fb106fa0d085e7c03eb816468d12c65d9b77643ed07c02583d491f4db5db44e565d50d8ccaa9ad8f7f8e80000000000000000000000000000000010a6a5fd90cd5f4fb6545814f5df065b001074bb3f29f649dd2612815df3a19a320f7754dd3d458e48e7fb1b4953978f00000000000000000000000000000195894e95ca3e59929612e77c1075322aeb00000000000000000000000000000000129c4945fe62538d2806fff056adac24f3bba8e17e42d82122affe6ad2123d68784348a79755f194fde3b3d448924032000000000000000000000000000000000528590e82f409ea8ce953f0c59d15080185dc6e3219b69fcaa3a2c8fc9d0b9e0bc1e75ec6c52638e6eaa4584005b5380000000000000000000000000000000018dc3e893f74729d27dd44f45a5a4f433dcd09a3b485e9d1c2bd0eb5e0e4c9024d928ddc426fdecae931e89885ee4db4000000000000000000000000000000000d6ee02e1fc7e52a8e1ef17e753065882c6fcc14da61da7ffe955fe84a9d2af9ba57562c69db3088652931bf124b0d5300000000000000000000000000009027ceef3ee429d71b58b84919d9a8d5418900000000000000000000000000000000131747485cce9a5c32837a964b8c0689ff70cb4702c6520f2220ab95192d73ae9508c5b998ffb0be40520926846ce3f100000000000000000000000000000000101e147f8bd7682b47b3a6cc0c552c26ce90b9ce0daef21f7f634b3360483afa14a11e6745e7de01a35c65b396a1a12700000000000000000000000000000000090ca61ed16c4c1e80acfef736eea2db0d7425d9110cb53e6c4a2aa3f8a59ee6c60bdce8df5825011066d44bef84d29600000000000000000000000000000000028207394adcbf30250ac21a8f1db6283580bc5e39159930552e5edb25e6215c66b6450296edc80dbc3a2acd125dab1600000000000000000000000000333e268f0b5b1adf76b88981fc305f03ce4bb30000000000000000000000000000000016cfabbe60d1e55723a0ff72cf802f2d1cf13ed131e17729adc88522a657f320a336078a9399c8e61a3bbde3d52fd3640000000000000000000000000000000009aa9a3c2a6d49d286aa593c6ff644f1786fa9ae471bdb3fe70b150a9ed7584eaa886ac057c30005c3642f65ad5581cc0000000000000000000000000000000001d417894c0cce924955a795b188b27951f8438a5485404b921a42fa79dea03c10e29d0390df2f34d7be13f360a7fada00000000000000000000000000000000189b0b3a04e6c613899d51231dbf0cba6a8a8f507ebed99d24fba7ebac6c97a8859ffde88e6d95c1a9d6b4f0a8f3c417000000000000000000000000123717b4d909628d6f3398e134a531c65a54e8a10000000000000000000000000000000016cad7807d761f2c0c6ff11e786a9ed296442de8acc50f72a87139b9f1eb7c168e1c2f0b2a1ad7f9579e1e922d0eb309000000000000000000000000000000000d3577c713fcbc0648ca8fbdda0a0bf83c726a6205ee04d2d34cacff92b58725ca3c9766206e22d0791cb232fa8a9bc3000000000000000000000000000000000f5ea1957be1b9ca8956ba5f6b1c37ea72e2529f80d7a1c61df01afcc2df6f99ced81ac0052bd0e1e83f09d76ad8d33b000000000000000000000000000000000aabced4e2b9e4a473e72bf2b1cc0ce7ab13de533107df2205ed9e2bb50fa0217e6a13abcd12fce1bda1ccf84dac237a00000000000000000000000679956d49265608468757580db6b8b1821c2eb13b",
+ "Expected": "000000000000000000000000000000000728c5e6e69b9103d82358cb6ba3a45a677df1c3eb3cdccf694fd71cee94f1e591b8021b0eef638cd9a1d878937b5b2d000000000000000000000000000000000ba9bcf9ccef956f2af8dc4c3fbf1cc8f3f284b04ae8710af6ef4fb36301254c777d4461858fb38fdeeb72c0d8589af5000000000000000000000000000000000224b80a57d30bce4c752664f3b5b5e3443aefa6d4e95dc334821f754b8b8d8fda4e73d03cbd4070d43b18324a686b500000000000000000000000000000000016909a02214c6c0f6682895aa99cf6cf0a22eab6f0b574437ef9c36e9df32ac3b8c5adb9f6b8827df0ccf51b16f824df",
+ "Name": "bls_g2multiexp_larger",
+ "Gas": 409750,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000039b10ccd664da6f273ea134bb55ee48f09ba585a7e2bb95b5aec610631ac49810d5d616f67ba0147e6d1be476ea220e0000000000000000000000000000000000fbcdff4e48e07d1f73ec42fe7eb026f5c30407cfd2f22bbbfe5b2a09e8a7bb4884178cb6afd1c95f80e646929d30040000000000000000000000000000000001ed3b0e71acb0adbf44643374edbf4405af87cfc0507db7e8978889c6c3afbe9754d1182e98ac3060d64994d31ef576000000000000000000000000000000001681a2bf65b83be5a2ca50430949b6e2a099977482e9405b593f34d2ed877a3f0d1bddc37d0cec4d59d7df74b2b8f2dfb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d93884d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d0000000000000000000000000000000003632695b09dbf86163909d2bb25995b36ad1d137cf252860fd4bb6c95749e19eb0c1383e9d2f93f2791cb0cf6c8ed9d000000000000000000000000000000001688a855609b0bbff4452d146396558ff18777f329fd4f76a96859dabfc6a6f6977c2496280dbe3b1f8923990c1d6407000000000000000000000000000000000c8567fee05d05af279adc67179468a29d7520b067dbb348ee315a99504f70a206538b81a457cce855f4851ad48b7e80000000000000000000000000000000001238dcdfa80ea46e1500026ea5feadb421de4409f4992ffbf5ae59fa67fd82f38452642a50261b849e74b4a33eed70cc973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be1000000000000000000000000000000000149704960cccf9d5ea414c73871e896b1d4cf0a946b0db72f5f2c5df98d2ec4f3adbbc14c78047961bc9620cb6cfb5900000000000000000000000000000000140c5d25e534fb1bfdc19ba4cecaabe619f6e0cd3d60b0f17dafd7bcd27b286d4f4477d00c5e1af22ee1a0c67fbf177c00000000000000000000000000000000029a1727041590b8459890de736df15c00d80ab007c3aee692ddcdf75790c9806d198e9f4502bec2f0a623491c3f877d0000000000000000000000000000000008a94c98baa9409151030d4fae2bd4a64c6f11ea3c99b9661fdaed226b9a7c2a7d609be34afda5d18b8911b6e015bf494c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a000000000000000000000000000000001156d478661337478ab0cbc877a99d9e4d9824a2b3f605d41404d6b557b3ffabbf42635b0bbcb854cf9ed8b8637561a8000000000000000000000000000000001147ed317d5642e699787a7b47e6795c9a8943a34a694007e44f8654ba96390cf19f010dcf695e22c21874022c6ce291000000000000000000000000000000000c6dccdf920fd5e7fae284115511952633744c6ad94120d9cae6acda8a7c23c48bd912cba6c38de5159587e1e6cad519000000000000000000000000000000001944227d462bc2e5dcc6f6db0f83dad411ba8895262836f975b2b91e06fd0e2138862162acc04e9e65050b34ccbd1a4e8964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b890000000000000000000000000000000019c31e3ab8cc9c920aa8f56371f133b6cb8d7b0b74b23c0c7201aca79e5ae69dc01f1f74d2492dcb081895b17d106b4e000000000000000000000000000000001789b0d371bd63077ccde3dbbebf3531368feb775bced187fb31cc6821481664600978e323ff21085b8c08e0f21daf72000000000000000000000000000000000009eacfe8f4a2a9bae6573424d07f42bd6af8a9d55f71476a7e3c7a4b2b898550c1e72ec13afd4eff22421a03af1d31000000000000000000000000000000000410bd4ea74dcfa33f2976aa1b571c67cbb596ab10f76a8aaf4548f1097e55b3373bff02683f806cb84e1e0e877819e2787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c94400000000000000000000000000000000147f09986691f2e57073378e8bfd58804241eed7934f6adfe6d0a6bac4da0b738495778a303e52113e1c80e698476d50000000000000000000000000000000000762348b84c92a8ca6de319cf1f8f11db296a71b90fe13e1e4bcd25903829c00a5d2ad4b1c8d98c37eaad7e042ab023d0000000000000000000000000000000011d1d94530d4a2daf0e902a5c3382cd135938557f94b04bccea5e16ea089c5e020e13524c854a316662bd68784fe31f300000000000000000000000000000000070828522bec75b6a492fd9bca7b54dac6fbbf4f0bc3179d312bb65c647439e3868e4d5b21af5a64c93aeee8a9b7e46eaaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e1000000000000000000000000000000000690a0869204c8dced5ba0ce13554b2703a3f18afb8fa8fa1c457d79c58fdc25471ae85bafad52e506fc1917fc3becff0000000000000000000000000000000010f7dbb16f8571ede1cec79e3f9ea03ae6468d7285984713f19607f5cab902b9a6b7cbcfd900be5c2e407cc093ea0e6700000000000000000000000000000000151caf87968433cb1f85fc1854c57049be22c26497a86bfbd66a2b3af121d894dba8004a17c6ff96a5843c2719fa32d10000000000000000000000000000000011f0270f2b039409f70392879bcc2c67c836c100cf9883d3dc48d7adbcd52037d270539e863a951acd47ecaa1ca4db12dac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c0000000000000000000000000000000017fae043c8fd4c520a90d4a6bd95f5b0484acc279b899e7b1d8f7f7831cc6ba37cd5965c4dc674768f5805842d433af30000000000000000000000000000000008ddd7b41b8fa4d29fb931830f29b46f4015ec202d51cb969d7c832aafc0995c875cd45eff4a083e2d5ecb5ad185b64f0000000000000000000000000000000015d384ab7e52420b83a69827257cb52b00f0199ed2240a142812b46cf67e92b99942ac59fb9f9efd7dd822f5a36c799f00000000000000000000000000000000074b3a16a9cc4be9da0ac8e2e7003d9c1ec89244d2c33441b31af76716cce439f805843a9a44701203231efdca551d5bbb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd108000000000000000000000000000000000e25365988664e8b6ade2e5a40da49c11ff1e084cc0f8dca51f0d0578555d39e3617c8cadb2abc2633b28c5895ab0a9e00000000000000000000000000000000169f5fd768152169c403475dee475576fd2cc3788179453b0039ff3cb1b7a5a0fff8f82d03f56e65cad579218486c3b600000000000000000000000000000000087ccd7f92032febc1f75c7115111ede4acbb2e429cbccf3959524d0b79c449d431ff65485e1aecb442b53fec80ecb4000000000000000000000000000000000135d63f264360003b2eb28f126c6621a40088c6eb15acc4aea89d6068e9d5a47f842aa4b4300f5cda5cc5831edb81596fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f818767200000000000000000000000000000000159da74f15e4c614b418997f81a1b8a3d9eb8dd80d94b5bad664bff271bb0f2d8f3c4ceb947dc6300d5003a2f7d7a829000000000000000000000000000000000cdd4d1d4666f385dd54052cf5c1966328403251bebb29f0d553a9a96b5ade350c8493270e9b5282d8a06f9fa8d7b1d900000000000000000000000000000000189f8d3c94fdaa72cc67a7f93d35f91e22206ff9e97eed9601196c28d45b69c802ae92bcbf582754717b0355e08d37c000000000000000000000000000000000054b0a282610f108fc7f6736b8c22c8778d082bf4b0d0abca5a228198eba6a868910dd5c5c440036968e977955054196b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea000000000000000000000000000000000f29b0d2b6e3466668e1328048e8dbc782c1111ab8cbe718c85d58ded992d97ca8ba20b9d048feb6ed0aa1b4139d02d3000000000000000000000000000000000d1f0dae940b99fbfc6e4a58480cac8c4e6b2fe33ce6f39c7ac1671046ce94d9e16cba2bb62c6749ef73d45bea21501a000000000000000000000000000000001902ccece1c0c763fd06934a76d1f2f056563ae6d8592bafd589cfebd6f057726fd908614ccd6518a21c66ecc2f78b660000000000000000000000000000000017f6b113f8872c3187d20b0c765d73b850b54244a719cf461fb318796c0b8f310b5490959f9d9187f99c8ed3e25e42a93b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c76000000000000000000000000000000000576b8cf1e69efdc277465c344cadf7f8cceffacbeca83821f3ff81717308b97f4ac046f1926e7c2eb42677d7afc257c000000000000000000000000000000000cc1524531e96f3c00e4250dd351aedb5a4c3184aff52ec8c13d470068f5967f3674fe173ee239933e67501a9decc6680000000000000000000000000000000001610cfcaea414c241b44cf6f3cc319dcb51d6b8de29c8a6869ff7c1ebb7b747d881e922b42e8fab96bde7cf23e8e4cd0000000000000000000000000000000017d4444dc8b6893b681cf10dac8169054f9d2f61d3dd5fd785ae7afa49d18ebbde9ce8dde5641adc6b38173173459836dd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c000000000000000000000000000000000ca8f961f86ee6c46fc88fbbf721ba760186f13cd4cce743f19dc60a89fd985cb3feee34dcc4656735a326f515a729e400000000000000000000000000000000174baf466b809b1155d524050f7ee58c7c5cf728c674e0ce549f5551047a4479ca15bdf69b403b03fa74eb1b26bbff6c0000000000000000000000000000000000e8c8b587c171b1b292779abfef57202ed29e7fe94ade9634ec5a2b3b4692a4f3c15468e3f6418b144674be70780d5b000000000000000000000000000000001865e99cf97d88bdf56dae32314eb32295c39a1e755cd7d1478bea8520b9ff21c39b683b92ae15568420c390c42b123b7010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a0000000000000000000000000000000017eccd446f10018219a1bd111b8786cf9febd49f9e7e754e82dd155ead59b819f0f20e42f4635d5044ec5d550d847623000000000000000000000000000000000403969d2b8f914ff2ea3bf902782642e2c6157bd2a343acf60ff9125b48b558d990a74c6d4d6398e7a3cc2a16037346000000000000000000000000000000000bd45f61f142bd78619fb520715320eb5e6ebafa8b078ce796ba62fe1a549d5fb9df57e92d8d2795988eb6ae18cf9d9300000000000000000000000000000000097db1314e064b8e670ec286958f17065bce644cf240ab1b1b220504560d36a0b43fc18453ff3a2bb315e219965f5bd394c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a65905400000000000000000000000000000000018244ab39a716e252cbfb986c7958b371e29ea9190010d1f5e1cfdb6ce4822d4055c37cd411fc9a0c46d728f2c13ecf0000000000000000000000000000000001985d3c667c8d68c9adb92bdc7a8af959c17146544997d97116120a0f55366bd7ad7ffa28d93ee51222ff9222779675000000000000000000000000000000000c70fd4e3c8f2a451f83fb6c046431b38251b7bae44cf8d36df69a03e2d3ce6137498523fcf0bcf29b5d69e8f265e24d00000000000000000000000000000000047b9163a218f7654a72e0d7c651a2cf7fd95e9784a59e0bf119d081de6c0465d374a55fbc1eff9828c9fd29abf4c4bdb3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746",
+ "Expected": "00000000000000000000000000000000083ad744b34f6393bc983222b004657494232c5d9fbc978d76e2377a28a34c4528da5d91cbc0977dc953397a6d21eca20000000000000000000000000000000015aec6526e151cf5b8403353517dfb9a162087a698b71f32b266d3c5c936a83975d5567c25b3a5994042ec1379c8e526000000000000000000000000000000000e3647185d1a20efad19f975729908840dc33909a583600f7915025f906aef9c022fd34e618170b11178aaa824ae36b300000000000000000000000000000000159576d1d53f6cd12c39d651697e11798321f17cd287118d7ebeabf68281bc03109ee103ee8ef2ef93c71dd1dcbaf1e0",
+ "Name": "matter_g2_multiexp_0",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000eb3c91515d4a41209a73564741a8ccf901a624df9db22e195a5d02d24b7bc0a12756b15b8d006cb991a7e088eaef1000000000000000000000000000000000704ce8afc808b0161f6f61b22d990d713ae398779e6e74e9b5771daf006ce0bba3a8088edf75156f0e48b92ee8409b00000000000000000000000000000000018fe81e05aff0620f4bdbe4a715e015650497afab62921eba0ab86b649e5a2fd3d54041868928519f537e36448688a0d00000000000000000000000000000000162bd97161201ea3c26f8dd1204a9c6b61b762bdf573cb5d20b6b255f30208ca7d96aa47b46fb8c6bf0922075f1c1ca807f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf00000000000000000000000000000000135aee0e30fbcad798738c10d4aebcdf50c89ce516325f655fe763dce54ffedf94dd74168611e5ae879b5bf5598d62dc000000000000000000000000000000000c728e672cd8b3bf9341bca929c34118b566cd3a80452d7015bee9d5cdc001b1f5c678d4b2cc4f7cac353e7bf326ca1e0000000000000000000000000000000014809aa22e2051e463fba6d49fbb060d0c7f599a0fc5409d34e71f34817e7beb1251810ae6eee1848c60796fb8647dea00000000000000000000000000000000145a4de777d86025d50e12f9a6615ecb9bdd41489992d1b643dd9aa549acbc63b04b0bdfd14b6e45c70f165e9a8c91bebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da00000000000000000000000000000000009a58b7116dbd6f550f8ca98071813130ecaa9ea86d5275eebc36860690fa048c9ebeb46600b2b63e847bff3e38ed0d00000000000000000000000000000000113ffc0932c041e0e34b2540c485eb74f5029b339cb60bc88a8a749310f33f330dea137e5f340044fd689264af66696d0000000000000000000000000000000002642da3c2c7b6688aba0b19ab29ac72e35caafa044863c364ea8833fca850289de52c0963bc33d7bba40cb5f568718a000000000000000000000000000000000552d35ca054da2f148c119454f6760607b351f2441921a2be17da2cc10902d71571c5554f132e60df79679428fa07e3e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed8330000000000000000000000000000000018fbbcba3d4b1e548ceaec4a48db62a2420ff29a67af332ee7ea3f902f84e6c375fd33abc33d945c5bca25603979f9a400000000000000000000000000000000072ff416994364bdc6535f36c82212afa822cd94fade69f11eb38dbdcd37c7e22af55fe05e6a826dad822073656eaac10000000000000000000000000000000017bba179b847278a4878b6faeaab3b1f4bd7540d22817cd9aff95557497f8b9d286657b6162c0f89f7820becc637dd550000000000000000000000000000000018e2bfed71aa9b11fefca2f0db8bd9b8c69540267de50bec4fc90a6e9741891465c9761d19282e1100b3707eeb598b31d411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f0000000000000000000000000000000019efd37727dfaedf697fcda7a59847dbda8ca7cdc92f34e68691d682e20ae6545ac104d6660fdb8f64a051e69298eae8000000000000000000000000000000001225ace0fdce456dd888c9672503b68ef77b2d11caf1265a767a6ea14911e3ca03fc153f18dfe9d95e0cc68b7b8a3a8d0000000000000000000000000000000008a6b059c1c4da046cc0b1b5d7f33270aceffa607daf6d0d078c06f940604e1a0b4adf01a4091306e3c7eddcf3d95101000000000000000000000000000000000f79bae5260a2f114ffbb9273f3049d3ebb002500a57ee0a7d157d86957f43f87a2e026fb9892dacaadca5ee04fc8e176bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc0000000000000000000000000000000016d2b73eeceee17d3bff3aacac9df9ac1c4248d9ea7d6a503a757f7bb22fa6970bb6f5cb5ec154785f7252e1508b382e00000000000000000000000000000000081edc68bbd8db7b10be06ee23d090bd54f9ca07ef24dfed7df7bb05f8cc26e6889dbd40ea203fd5cca5cb588199f9e40000000000000000000000000000000010d3478508619ea9493b4330e2fb9150024cd32dc1378f824788a884a4a30fbf39c630f465557bf0c6d69b4cbecf89f9000000000000000000000000000000000f20c9b134db5d8b7756800c031bf5962fc560ba95d4bd9157b16179f1a37ae08696a2be455ad8d018aead6adcc69b712a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c520000000000000000000000000000000003dce67181d23af9729e9fb0653d7f79c890fba27de42fada93123e112c4a468fa889921192db8047d86e4db77c60266000000000000000000000000000000000869a1e39d42d9bb0cc0568fdad16abbdac3194af893ebd8dd8f8c2c3c855abefa5fc215412168acadc88e658e83f5570000000000000000000000000000000001ef139a75194f3c4b1378c2b66dd304d179460bac0a289405cd8faa3ff66a7b6e54eb7b8742a68150b1e098630135c40000000000000000000000000000000003892b5a645af916be2c6c7fc0bb08fb5f39341d3c68598940554e1be11e1be75af920db0c8710ed13c78edbf683f17d0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b1000000000000000000000000000000000264dd4b477f5db65edad28c7153ed919a863c5c5661e0125c5429b323e055fd69c33142dfc6ed9c87082e2be4675e1f00000000000000000000000000000000046ea088a2ec94d3a1f1f97949f1ebc49690c453d316cc46534fa253b34b30323b6071d147d64bb94e02fb4db07bb0c400000000000000000000000000000000013692a33bb1348486eec40a9e93a4ea3810c7b4d3188cd07e235a2c898aa87ee0d17682fd24f4d978f9fb028fd26e2900000000000000000000000000000000115f8b64c00cd5cd344a7b5edc0ef0bb85a3e8f0f9dfb28f8ffe12db3e0d222c2d45dcdba0fbdc161c5d558bc71aa0977064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e900000000000000000000000000000000014c83d58d90db4821a0411fab45f83fbc05f7d0d7a67ce75da3ae568978d15f4c1886c6fa6086675c0045efb30d818400000000000000000000000000000000001e68691123451f4c3df6dae62c6a63855ec3597aae33a8a10ee274e902e9aab1460cc9c79726312df0ee0ce90c8d3c00000000000000000000000000000000018a39eb3e3c6c7fb8ee304e55d15e209afe2fe278dda93552a7b9f51fbd778da1502eb6775cbc3f832f8320fa0686240000000000000000000000000000000017c15910fad1ca5749aa82a5a2fa98b0ebb37e92912547fb1741f18c34e0d5fc3a307b928636c25f0320d71cb9d31062686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b000000000000000000000000000000000fa96d9fe01c18732e8d6454df9bb1f482c4b9add837ce9c354c72d49c2d44ec694674aaf0e6d6a095cab7ebb57ccd9a0000000000000000000000000000000001f8ffe3fb7e9e311e0f6949c07c26a0febb181e37b2268bb5e125fc3a100323740d1ebaa5e635dba3770fdc2ce4ee860000000000000000000000000000000012ac42095fdb677720ab3f14bf0afc55c95b43d28d922a5f8cb0bd841306b978751d24546e3a6474976961d0768f29e9000000000000000000000000000000000baf9804d99039c9fe966a696c64bdacc9673b0906b4deab108d34fbbaa3b0905d50892278570564017b96828c7e1ac93176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a60000000000000000000000000000000014ce6d88a7c5c782562aa101550f1af487296adebd9dae8252698ba04fbd58b92e2216de6ffd474d5992f97d9f22800d000000000000000000000000000000000ce92a04f5c8a99ca0e93992448222519fc454bda5d1d8638a7bfde968386e4ba0dcd1da59cd81d4c4dca3e584be0275000000000000000000000000000000000cb570796f5c8f7b8aa02e76cb8e870d3365fe4dce5df07ec286a0a821f922b4003d5b69c0f1588206d9544013e268c400000000000000000000000000000000098056a033d9cdae86aac02de3a444471854b909680719154b44d4f55f30087294e39e57643c692d6da725b859239080d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36000000000000000000000000000000001214aacb0a5e6b7a40369a83c07fa8cf1786ce7cbde2b5a501d9c1292532df7822d4fde10a31fc0cecce3a7cfe3311850000000000000000000000000000000004f9669d8fe4f884ae93b2505710e6e45b19b7aa5df8cdd811f09e547efc27d21024cba05e2dc9d057055f30ec72d9df000000000000000000000000000000000a852b821b31cd27eca19712a636aa05ef2cd82c36ac1c2ca240edc7d0172b42a72c42d3cba583a5b5129ac1c9486e270000000000000000000000000000000007bd8419e791a5cea04993509e91a980d3ae4987a5b322400b6e4a4f2b636891a1c7ba4de96b53426dd556532403d5a39915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc0000000000000000000000000000000005ef88bf38b2f998dec7302cde829076e6cf69df23aa0bf6bbb39fc0d3d8b5eafba74efb928b1de0eeb3d86ec82612300000000000000000000000000000000011f47e9583997b19c36616e4bf78d6ddd6d67937f493986250ff02aef6e6e7ff074559af2f20a5bf1d67158e4a199cdb000000000000000000000000000000000007777c8eb259a836e6459b7bdb642f878d869fdcb31b105d01f280938ef5377f2775874c099dcd394abe70f17d595b000000000000000000000000000000001607379d1cd34e2d0ed765a339b21433e9aa489609b92414c6b5a05d796085269c288d739717def9db3502e0550860165061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b208792000000000000000000000000000000000d6e3068c082b68312141aa68f1540ea1415e93e7f1762b6f06ff408a9995542da1c727a13355c19f8f418a44de1a95d000000000000000000000000000000000dcfcf2ab12b1a0e521ab402aaa4d32ff649a5a97892eb6ad98487c3c73c35601c313b8130ad12e9098d16eed3bcc2e00000000000000000000000000000000013777b1eefa4af03dc44e4e054eb7a3a980a9c55644900b80346be84b970e1754d1f4ab771adc9249e4accf88a23fb400000000000000000000000000000000002f53b231f1209c6f8b52f99a78bc2147c951ac89b341495f4a60a6572985ce2bc823625099ec214bc9ceedb2deea3fff396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c00000000000000000000000000000000161c595d151a765c7dee03c9210414cdffab84b9078b4b98f9df09be5ec299b8f6322c692214f00ede97958f235c352b00000000000000000000000000000000106883e0937cb869e579b513bde8f61020fcf26be38f8b98eae3885cedec2e028970415fc653cf10e64727b7f6232e06000000000000000000000000000000000f351a82b733af31af453904874b7ca6252957a1ab51ec7f7b6fff85bbf3331f870a7e72a81594a9930859237e7a154d0000000000000000000000000000000012fcf20d1750901f2cfed64fd362f010ee64fafe9ddab406cc352b65829b929881a50514d53247d1cca7d6995d0bc9b2f0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa000000000000000000000000000000000047f92d6306bed1cb840f58fd57b5b71a5df7f86dbfa55a36636cb495e08715cd57f2f3e7cd99a1efc28b1d684de1cb0000000000000000000000000000000000f4eb02d687a1a6105b4dbd740e2c7924689d558e6cbfee768dd303cc8dd0fd887f5eec24b54feccf00f473ca3f54ad000000000000000000000000000000000edad68c4d536912816cf6ef039c3dd0535dc52189583270b3b038e2c67b213d943bf384ce69c4a9dc526d7ef309f25a0000000000000000000000000000000006ff4a6b5129ef026d1d5704bf7fc0b474de92b5cf39722f165e73f4e7612d6d3bb40743e4b7b42d0dad5d5d6a2d4881915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c",
+ "Expected": "000000000000000000000000000000000153da66acafe91b6f13cd739ed3342197310e4824e7aef2e3414654c2678b8d09b296c3f928f3cc489893420031ab800000000000000000000000000000000010f501a96b86343a7c8d8c1250577cc9be6ffec81b5175ed07bd14988c5bbf7f2f3e7111df7d941d0cd267ea191d6ac70000000000000000000000000000000015e0d88894f7f83aacb6710f6c03ae60db8844dd3beec160fdb1df746b1f38a5e23def0893a0b39bee47c97af6535fcb000000000000000000000000000000000bcc275115e87f2f88c4afe8bf4faed46e6ad0c0357884356a26120591ba283f06b464c4853217865b1d2301965f2bd4",
+ "Name": "matter_g2_multiexp_1",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017b32e613cb38b41dcdf3c8bb9187d731546977fbffd79fa7f66e3d6aaf9e1af6eca2fcdc260c8f90818d7148ba2f4960000000000000000000000000000000007e4d26606a47c874c20e8480a9f5815e5b577bccd783b775d10309eeb3d2102c7a0abc3324679e44362f09e7a4ada67000000000000000000000000000000000cb6f12ac8b49cfa36b957591293c87b21af0a949c55a28a90ab0fce88fb5cb7645e20ab2edd284f0ad1377dd95ac10e0000000000000000000000000000000014c96b5dcbd3150eeaea5c2bc27750cf88b30a91933a3233a4d1d9b357a80cc20d135e43a344e718dff5c79045c31f86d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd0000000000000000000000000000000001ca1141ba9542c56de8991b313c6ae42fcecb6751b0b81b8cb21ed70d5008f7ffe831766b89880a7fa6dfdb09a2cda3000000000000000000000000000000000e6766b17db165bba564ac63ab88d3f8f5eded07a40b48644e60d3223d30458e7dabe404cab8d6f9fe135712ef0b1a43000000000000000000000000000000000dda3e6c87382fa762510e5cac721fd2b654f002f5b9a3767a8c6d651ccc582e80e3f68d6913cda30f9f51ebcfc7c98600000000000000000000000000000000059a7dac5bb6b504f2bd603d486700fe22c14f25254537b2c9079c2b45d36c7ce56854c5699cc7649b533194f51a9045c00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc4500000000000000000000000000000000090f4b85961ce97cf7f99c342d3627105d790f611e19721a43d8a0febd67ae393d77a02b999108efb56f0397dac22703000000000000000000000000000000001112f23595d1613c47486eadc37f9b1ac3b3c3973b3fe964d3b67c3996fe2eacd9df5c287b0cea8e9475d146fabcf9e70000000000000000000000000000000018f46f7ba3c9af34c1025c2d460f0be966e68944928dbd55cc7fe00e5def598d80b0e3801e48a74963c974ab4727a52100000000000000000000000000000000096845338d5cd2ac44e097607d6a1a05c241eda1941991ae9edbba965d9029032c46da7218b5b2338e6c58898bc4a820f661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b000000000000000000000000000000000aafe45ea7cb8b450a51263eebc28c1ded662972bee512e24fddaf64f43b74b66032523b3b104a4e9f6b62394436c6710000000000000000000000000000000015cb27e1fedfba2d1679f78a388f90b22bbf3e7d090f0ba972fa8e72f6e31c446f628fff929953712ef6e425d16eba5c000000000000000000000000000000000df9931893cae713042bf722db6ce394b6f346587278a154c271d8511e690417eb6dc47efbcebb7c2fb9e77f1de9fde800000000000000000000000000000000106ffa395ef170c99bb5742428ae88fa4fd7a94476985c099e3b700b7403d083281fb71a19640c6bc2321e27bcb33fe2346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca0000000000000000000000000000000010b1f8b1c492a56936da905b8738affba6bd29ae5fffd40ba6b31325181d3b489a81b23dcb69f6e71bd29bfb388e5a8f00000000000000000000000000000000116a115303b4774da59844e457844232d088062d920db67b2a8450a194be7e5340ebd4d106454fd9a03c8f50dbb1e119000000000000000000000000000000000eb521edd61b38006cffc43ab72d395d669dec196846fa4d6d43521da6c2fc3bf0994ce7556a3cffec7751b3bc5703ff00000000000000000000000000000000073cea36eccaa1c78deefb6029903c2b6598301bdefa9759719c3b590fcc5a6a4d3d4d19f552b33f4a3126a6e6a8448639a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc000000000000000000000000000000000e3925fa085db73c1e67b29ae90f8773f83be5ec684402e8e2360ffee8a8368911e584843e42b0d470de78591df6ea6300000000000000000000000000000000075c7efdeeb16609b4a47ea442af4d75238fb7534fd96cb236a7886809d6adc2b62c8ff72bdb041bc51c1a71b68219e300000000000000000000000000000000088b4eb0dd185e51b737d797334590e982b7b0a5f109fc7d0524b2465c2c0457964eba5a6d2d4d99fb628f21f15a776c000000000000000000000000000000000fc79f6b38f3356972669290eeadcd992a22bc1191606b663a1e148aa58db3938f0fc65e536bc5811c50d9c7f03d3e372c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447000000000000000000000000000000000b87c47605fc060a8e3677e84ce9d14b9309360a13c80d040c625fbf0108f829300cc1fca409a0f9c96311cd4a9a21e60000000000000000000000000000000014c4088f1e7935cf6a1d2475b84497ce6a250ee2c0c991fe51a2f2836388a354824b02d9cf215328dfce3f546713e21100000000000000000000000000000000120e59be3ecf35674eac6cdc559599b273f13f28a529770fa156f8e519734c451eefb35023639f32049cd19ea0d945a3000000000000000000000000000000000f97755b62a8cb8f861ea02c77819f0b58181aecf612d92180ba9b475f0b4888b922c57f6a1c619dd5514620a1cfd9e2c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d48280000000000000000000000000000000005860cfb6be6720118623d2d8ba05e686df22744b948421dd3cc1b1691e00d9b5d00d00195b4acf7a7b043f764f3f1c70000000000000000000000000000000012632a3313dd611e8d969bddd556c2d79ff387603462ac78ded3a842981697bdac34ee6f1f4744ed2ff16100874ac24000000000000000000000000000000000112b94c317586e343acadeca611c485c3ea172bc10dd39158c1e678007130062a921b53826d7be6286963ff822f1066c00000000000000000000000000000000040de8c0dadd2a6c2a7ea0fa43e1a5f2f5a6be3fcb0de6875d8cef1ee2daad87125d12f6869c4dd3d931b296f1df2fb3d4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a0000000000000000000000000000000006fcd2c4fe848e9462ba1112baad39031c210952adbdd06293a622ffe2d1c6e4fcc8773ec8913717018b97bcb9a554fd00000000000000000000000000000000130a97442f3273b7b35464545e7351faf71ead9b8996c63889a45945ed82bba29bff5014776c6185219a5234d8475c92000000000000000000000000000000000491d571bac5487b866022a0714be11b38bfb296233845cc434a50be1d35f516b8c6b046fe3d0a8f4f95ac20eddea01b0000000000000000000000000000000017e34b04e6fdf152c848f2432b7bd84b3dba3915f06eb77efb8035750aca9d89e92e1d1bc4871105c440d639e8d8b05541776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb000000000000000000000000000000000f1b8df4e8fdfe32eaf227f5af9f2befc85073468f10b81d32d0e126fe2b0cc8e8adb8afcac73213b6ed95e8e843b97c00000000000000000000000000000000004e3fb435ae0fb2d8bd091f250aefe5922b353a64e16abd75627737f3bc56639f8b40652cae69c73ff1969925b0afdf000000000000000000000000000000001003aed7cfb00efce49d6b1a8eba27df87479a4d37bd7fda6121549483b669a1a761204b0dd28262bf27e5c8e180540f00000000000000000000000000000000114fbca7caf782b3296d0b26b4c362bf50acaecb8bc5726b2c99f904ec3d092d5d40991d0d30c8e79fddaa45f04a75d3fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c4250000000000000000000000000000000017faf481fd4cb0c373d21d7caad40e93d9a86e62d26136892fbcc6f6e48205543aff00c45e82fdd1d3e0e733de91e7000000000000000000000000000000000012e14fcb9ad4d9d15347cf004745ed4bd92097eeeb41c4cbcb728a234616363589d8f5ad4cbb61d31a8aa27627723c7e000000000000000000000000000000001513dad1ff27e053902e779e35d04cab648939317830144ea775c435a4b55e13fa2fef03a1256abf5c187487c25a774f00000000000000000000000000000000139da29de8587c7d0ca9237c37a116387385e9cea453b9e2003a37ede7aa0a3f4c1df55255897f5975b662be33622dbce7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96000000000000000000000000000000000c118b147ee3489f30c6ecc0256a314ab674110588e8b69ca6d265fc270c3e5b767817f861140cca5d7c6be4012d1ffe0000000000000000000000000000000014800790654726959fd876b035bade0da744fb36ee5b304f228663a531345120267c55ac19fd66022752010e5bea7cb30000000000000000000000000000000000193ab7ac2f151750356b6e178557460c9c2672b1736d19a20e3fa28082479ca60021aa68edf2524f1aa826ee70b65a0000000000000000000000000000000015cee9ac55ab45abbc57d0ea6ec9ee49f6c59f6b94f99589dbc08ee877d3a261ad77f5473fedd72ed7206647eeafb6eac26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc000000000000000000000000000000000ef203fab794a0ef29eb2ebf00076134e5932e27c99d6d445695b9df2afe7563602e318caf5d44724a21790ca0ab0d180000000000000000000000000000000013b9b1b1d3e98b61b0f1a0ef3a1a4ceed57b6c01849a4ad66a86332b3d27022cfccadd3567e6709d2de5b23b23dba43f000000000000000000000000000000000c1fbace49684f4be32ef6178ac3a95ea3f50b11494340fb73dc5391d50bcacafb3bf0f2631fea9c4ec47327d644489500000000000000000000000000000000040f82812855aa3e3aaba826d5810c1049cf44e86e44e23cc6da437971b529d2f2676c73e1fb9da52640c981fbd710bebba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca00000000000000000000000000000000060d7a718dd02b147c265f71eb136d1f31781b12a41866b4f86d7374b93dd10058c192cc0fba928373b1526e1a5d7d7f000000000000000000000000000000000cf29275373c0573ef22bf87919faf5444847203c7dc6d2e18986152cc294be04a5b1a4b0536797158113a15276c4fc6000000000000000000000000000000001016d5b9d4d200d7b4b7cc3836b85d6697fe14db350badba9978c7b56983dd1a7e572640ee0372b0a4e2079ff4c1abf2000000000000000000000000000000000f2768d104d895473ddf8c6b3cd0e7c22458d0037eca6365c766879a07c95037ee0de00d32c974d767080935abbe0be1705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a0000000000000000000000000000000017b9ca4349fecaa43ce911c0b256680edb8a0906ef5460fc4d2004579336df1e19560fe960a7a7cd74bb6e8272e08960000000000000000000000000000000000d5b96dae738db59cc67a51c61bec6deaeefaaa51e3259243fa4b142ef59676231229ae386ce699fbe18c4c00bf9d49400000000000000000000000000000000111b79f4b68dad16550a13334d09dc38336a75a5da23a17b5064e2d591aa3dab4c2e982a9f730a7633070504663a24610000000000000000000000000000000018f6d3616a7eaf17c805a88c9710039644d01b61aefebf76717ddcda6f4bb34aa15702de1e92bdb27b27f3409638da90f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa4000000000000000000000000000000000aeb5c087644595d0912879f61959d2731ff55260c682ed2bc5fc55c13964ef7c1f70aeb55876d2264d558c31371ca69000000000000000000000000000000000e173848f4570525b03a2b2c86f4dcdb8b28dd6d18c1354cad31028eb1b8b44432c2346edaace093e3954c7fa6d338a4000000000000000000000000000000001949b0902506d111ef6318edcd7a58ca4d69f5804a028aee73c3786cb2db168c6a73b77194f7a021ae6ae43ac78ade340000000000000000000000000000000017c5e28ba6103d97e2f3d3611c0c78f06406e0da8a49ae29c7d460b52f75136920784cd500aa3593858b877697eb8424807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556",
+ "Expected": "0000000000000000000000000000000013b49054c3957d1e77ba2dc3ef75775bab9f0e9f76b33ff22e244e897b8ab80ee0749c81eceea259e99b5d2a72251e5f0000000000000000000000000000000012e017e4354ef86f73ec51921cbfdd01e3113cff044a049bdd34e36401712420790cf718bd28afa280ad12104c1851ed00000000000000000000000000000000097f28bee5d903e3c6de14e834d5beea5c847c3106742978e586ba7e913f8b631a69c473aa10e19df9795ebfa3ea6a98000000000000000000000000000000001953493daf65b974b549bb98e735da44b543d6fcfd97176fdc7f6f03617d90e6bb952a607fa8e5791df5dc1c9bba2286",
+ "Name": "matter_g2_multiexp_2",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b9900000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c7a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac7000000000000000000000000000000000f20a07526a082e88630a0256d134a8a5e8ada07b1cead39ee838dcbb30904e9016107fcbdf1f8ba182308dbe0b043d20000000000000000000000000000000014fb7732f67abf60c03ac902577532d0acadb5f3db0d6397a42ba693526ad74f2c61a0195bdc9704aaaf12e65aa6d88b000000000000000000000000000000000018cec4fb81c85d304588d11f8b9c51f5a053df11463e5812a1b2e6c7144522ba36bb91adf219892d0007cee470032e000000000000000000000000000000000b8e52d958a12a9037e8be9bc0d5045cade2d6ea05c6e68462b3a30b5d4ea34e5fbad173761e4e216b2e6958c8983b28b473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602000000000000000000000000000000001468cb35a60898ed129f30c261b8431df6a154c250ec16d85a22f8717593b2c21853d123da86d977a7938c5ed74ef23500000000000000000000000000000000011f4e28e31b5f9e6877192a5e632d8c1ed7ca0c42e6e9902ca68f1c2de0f648c6064436012c5c7b14bb8d1078e02f2c000000000000000000000000000000000b25114b2697ca7eb1e6effdd1054893a188fd382d387ec098f846c1137a9b9baad01653b963a0b0bf3cb50c3ce3563d000000000000000000000000000000000c1d241cb03e642c1752b1e1886472477c19a2801ec032dc220c3243952f882094119bb92b621b654b766bc900d2d4f7a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c013000000000000000000000000000000000c80d4474390fa791ea5f2f16b41506d8ae13ee0993c8d31a07712687298ee7978a724999500c42400d2f788a5a36067000000000000000000000000000000000592705cc5a8875750a4e6ceb42aa3bef5593eda9e8212702a2e08ea70277a2a66526bc5237be33c8449301544da35e60000000000000000000000000000000000facabfbd15284c6433f17b0e6035d4fdd84d3ad2dd30a27d52809652ff6e7a684d7724697919100567ad0c3e1a26320000000000000000000000000000000006a0fc4e2af69ce15a356656f5d182a2cf213d76a6047a05a1a3375909d245f5316b91333d2141c0817438f0d87bb52da9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc80000000000000000000000000000000003f629618e1fc3018bb836301ccdc59022f0a25cc9c5de6e4c31fa08feea525c83256235e4ec8364e77e5df478f5f62c000000000000000000000000000000001120d6af221ba6f4351bbee4c2c664a769adb17872646df2c408f70c99ea991ffced4eab50fa98be1bb9426915f125930000000000000000000000000000000015cd16b028ce3d58b10aeb84b783475d894ab3f0cfdf7104ebb4f3417a038107128f07518dce548271061cb8c97e88af0000000000000000000000000000000018379875b68bc26107f9a068e5034f29dc2ae7e8830f8e9ecddc53fe7991206646cda33d37b31a47a977b46be58d7618f228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b00000000000000000000000000000000036570783711b381830e35878fbeb187b84884a9a0e88c38e84124515b470e6ac18157e1499026b27f4f731a961eaf330000000000000000000000000000000008382838c18d56c046a8db495babf8d14c915622d7917ebe10cf7da7ecb65f174cddb9e70d0262ada961b396c5511b410000000000000000000000000000000015f63ce982aa581dad5c71fc79251b7f6336c4e78a4a0f4cb6f87167cabd31cbec987d7af4f11dc6d693a0b0774864130000000000000000000000000000000015c001372fe0530a3f50fb8b30e75ff4b264d673e0448211d082c7a9018f583b4d01790019874596c59c68768cfa3e699431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb51124400000000000000000000000000000000074d78cdd35ea17a3013e2301fe9f80f2d20d270a25fdead37eed7697a52d152612543781763e6035fa5452ab12cce25000000000000000000000000000000000e572236e1c203a1c0f99e6ec978458c1a143a6a650eee27cfbe406bb2858fe5f30222f468d119703c2f442bc644ff3000000000000000000000000000000000125384343fe132e16a9fc15efe1b3a9e47289e0afc4b44d492e33a6216edbc96d66c1ca66944a8296e7695f27f414c5b00000000000000000000000000000000084c2cbf0d7c932c3098ded7c70d4411eed882feb0f79e0f7f1c31f5fccb6d53fb57de179c3ba5754bc5e532c3784df12051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d830000000000000000000000000000000004d46066439c3ac559cce863c58316883651023990180470d2efd06e443a7caf3a514b54f15ce6e850d32779215bcf4a0000000000000000000000000000000019ce904b6c9c3de59f7d5017f60f1978d60c564f94a0f1964c24c876d1139a7ffbeb6d0d4884bbfaf5f2f189af6904a50000000000000000000000000000000015f1989719e69be95f25dda9358fb98aae2819e0deb7e2d291e2c01e85ba26a9da421896c6b6e2ed20f609b533154694000000000000000000000000000000000b287cfcf1dd7c6d735c1358dff15393ddd6c82e7a33c5d8005c4234cdf823c76a4725fd74cad74b3ec51df67f09af0fb96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f85200000000000000000000000000000000006b37e2226957d639fcb0bcd6c20b3c7b8372e7347a14b970e01c67c1859fa97c754ce588d0f835ecc053549d963ab4000000000000000000000000000000000c6a5fae8be3a32e3f70a4202a1ab6d97183964b9f7b9a084c49922cd9e0e952b0bb66c5580f0e0c417e079493bcdb4e0000000000000000000000000000000017b6132f11adc0d5d693ae7f3a0f89f5779708083eba23e03b0c9265e4e60624e1fb6940e8ee49d31618fa6389b1b50b0000000000000000000000000000000000a45c5f6df71359648aecb6434bad1619c39f10e279a02b3cc9725d0256bcd126843fc9ed29cbe02a32cbbe79774a3378176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c000000000000000000000000000000000ffed009c78ba9af8cd33af7b7697ae4dff863bb92365055baedd2299b7f5b5e8abb84ed434f7223c3e309ca53c08aca0000000000000000000000000000000003b2370c837dd6291818efe7c9af62dd51295c418739ecc509d42c92e2c97d12a9fa582946e176e8153fc9a273140b2f0000000000000000000000000000000001e63438e8b4a0462cfdff64a281ab4a7f48d51b51325817139f8ee683484f8695f1defc0c3efcca81d5fbff06cf9c54000000000000000000000000000000000192fc391cdc1ed6ddbd317f2f366f2ce25ba27b8c0f09c733e7bc0c0697544399a3a4f1186d139a8f6399ffa88e89a69c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da000000000000000000000000000000000002e105e0eaa418d58019a849b89accf665a94ffb0bdf308a11b99b521de7af8ddb150c0e3b2e9c54cf5456b6105bc81000000000000000000000000000000000691a3b3986fbe1c0ea22329364454f37f645d6abe9310e883b9191ce512347e074e18e28b88c2adcc76190a549b80b40000000000000000000000000000000003f3a37a763c8d0d99a3fe36923843a22cb0fa18ced48493b2510fc99afe5b7699bbaa6c2ecdad8aaf72969354f121a1000000000000000000000000000000000f4bbae00205f54eb10c83d928d908fbae342b76050e33c51b6e282e02b3c1f132a4728dee4ea95455c25fdfc112f2542ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd450000000000000000000000000000000009a3e98fe4a98582ce9f274965f376cb45e8583775dbadf626cb1327c1f8a25b293b97e7f8f31ff72ba7e8e769ff25ef0000000000000000000000000000000018e4785ccb76c4897087c8a4242ddc744c6a0a53a4a844254153c23d6f16d4ddb945252d13f93101613f4eb0b1e2b8320000000000000000000000000000000011b81d344eac04d3471b1edde5e51f31f97bea3396580839fa094db58cf6bee371bbdc045fb60c3ee5c6cd5d3f6d3c4700000000000000000000000000000000073476bc5b1d52ff4ca89c3afc099417f473543fab6e59cf9de8a19705dc4bf2a210b1e6de4dfbde035c312be0c70c56fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f000000000000000000000000000000000c414b95b298b9c673001173ba7e5ee3e03926f28068481cfa0b469ab556f8fceba9fd0a815180ae0b82c265fd4c6b7e00000000000000000000000000000000054a242c1cc1a9c710bc23305d09c2d613ee8eb3840b37943bfe83f9c1db456ab4436ad319fcdd8684db129d76c95320000000000000000000000000000000001683711c0c7f02e67374f190eed1ce6559479d6d199f43fb5b0ce7df7774a5cb21c86b3b3498855d9b69c5763acd8c4300000000000000000000000000000000062f87085dfec847af518bd71c078f994b090c3b27c6eaad79772ab58afa43993db52fb08649a32629d61c3db12c87318a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d00000000000000000000000000000000083eea9b5b2d5ac5f7ef51ca889a4317322d098a408a741827fb3419eb12a51c07c788c2798cb37635e224e99bbc894c000000000000000000000000000000001312ec00f4b3a4305700b44b3f215779a9a8bfcf5b5d3a7f237a33c5484099ec9bc5c8537fae768e2c0ec62168f383d6000000000000000000000000000000000cf1d5d05d11e1d07074dd34211d0f00eae1df4dc550c55bd2fdafaffa1ad36abd5da30c5d3a5aa2845b1d95a5cb571e0000000000000000000000000000000015223baa9f2ea4b04fdb05b05bf3a94dcabc5e64189aeee39c380de9a34fe6b4253f5795f70bbe51b80e1aec1eab7196d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a0000000000000000000000000000000011a960cf1978aa2ce1731b857fd91d2f59d4b8d7c6871ef6f4f85aeff549a2f397949d11a4793926fe7be37f3a83d11c0000000000000000000000000000000001954f056834d6e3b16043ef1acd0a47a353300257446e9a1db7e58bd0d7c4bc9ceb3db51ae01cfed9de99621e96934c0000000000000000000000000000000002e2fe460e71b65595ed93a0010e5ccd1a2c16fc4e0d345e7226c947f29720d2f3f54282f79cec086d3fb1999b9629b300000000000000000000000000000000060dd8a7ccb613f1521168a8a322aef9f84d9708a893f704f4fc9a19e2493f25620a47e0fff1bc1e212e65e92873b4f2dbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad997000000000000000000000000000000001472caba61c2f1fe4b1d0912b114c25de103ef4351668f22f3a158d7a347539a7b6656044bd490f036ca3e29dbdded370000000000000000000000000000000015f8cdf7786410b409f218164063c99e77d8f72f03882a6c9430ec725ae574547d3ea3cf30c3ad2c9c3febe6c30b1272000000000000000000000000000000000ccbbed85c2809433fbcf22d6490457dab800b21cb4de414c7dd1804a0bdeb7142f8ffbb2de921c2c9eabee6a6351026000000000000000000000000000000000a404f42c48e3ca408d3f92079b99805004da928f128206d8904ecd7fcb14121c7d9a9e7fb69accaff921315ef3d5372807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a",
+ "Expected": "0000000000000000000000000000000000fada9f43b29abe15693d047adc277814cb94694cab3be56b92312ab7666649b8e9d92aad81f8e487be0f74b9ce8c250000000000000000000000000000000007f6891775811a325cd7f548011ad4c705ca0327ea0484d938ce061c913a7ee6978293c3258c4b865d5c2325816c39990000000000000000000000000000000016761f859beb90ea03aa35e954d112da02daa8e76de80297afde9c29cbfe8ef4d42dad535917685a99b2a91b1f952ae50000000000000000000000000000000012a4f24ab88341dfb8a60c19993b8abea96dbd7033d3686c40903728b4fd4da7d07961f2584b51e9e6c05976d555757e",
+ "Name": "matter_g2_multiexp_3",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b52f05365c4df20a7290aee71a7e030615d1a2a971167884d835c24e756a0faf6ed0552341c561446c7fd3d5e887d830000000000000000000000000000000018718ef172c045cbf0bb132059754b62414097eef640a781db6ad521af5a24d78c622d9402033fa939f70aad0510a1ac0000000000000000000000000000000017e969e44b4910304b350b5d442bb6a0b71e1f226cb4603cc8b4dd48614622f3f4e1ddecb1894046649d40f261d94e030000000000000000000000000000000004dacaeb9e05b9d60ce56c17312a092cb988bff426b8a718cdff860186935507a06eddbc4a1a29e4ef88db83fc4b6e77830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d0000000000000000000000000000000019829d5799eed5a081042e4646d46fb6bead6d3b9893a4240867b25ed6af6a3e154514f244466d80e3b9311e060bbd7100000000000000000000000000000000156157a654db2813cb9c1b4da0a3ee192fad076bb2767020fc5fc00e967c1a35a367ffa375703e1181b3705ace9dd28000000000000000000000000000000000093385a6a9dd0ab996df54b23f47f4a49b3f379e11bc8331016ecee6161fcddd22f6d49fbb21f098873f1e17424dedca000000000000000000000000000000000d5b5b0f2ce81e755b4030b33fe3a8bdee38c2c60ed3b4a88bffb9207cb762c0a5c699ff424c000ab080d763abc5438d184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e36160000000000000000000000000000000003af8c25bdbd0dc1cc344d55366f15555709a74e1f0d8d7050cb6b487759db6200401b7868fca3c2ad26e6362a30e6250000000000000000000000000000000013f8b6ffe30f9a133fafe64461d305cc6b2cf5aededf68ba396d4e00df651531c750a3d94dd77bc5c6713b939b18fa19000000000000000000000000000000000dde97855d7728f409d873b83b6879b45ace5b73f317687fbf478e594a959ce21d4d751db646ceb20432e8311e67404f000000000000000000000000000000000fea997323cf29710cf0e3d44ce682e039d6cbda155e43c94dc8cefc5e94000de4b9525123b9615b5f1019a46ef37ad3a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af000000000000000000000000000000000cdf60e3bb018407eab162822468255bcffd54cad9127054bd1c30705a4ebf1afc7f539cca6ba4cd070b44410ec751150000000000000000000000000000000009a2e3e5993b6a7007dedbbd21737a8c0aef3ecd4607953c4a24bb3fed97ccae01ae1cec024443f300b570a66e9ac3bf0000000000000000000000000000000008a21fed19e9ec2a741ade7767b0c9f39b79c3fbe34aadc9eb3043583768d893bf927d26231759290c7dd9c4f158d5a10000000000000000000000000000000018eef4ff88d63149d2632c9db586a4af0606644b16c82fbb0a3b869f1ff924c59acc8efbfde7bc604497ff68939cdd0845111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d145000000000000000000000000000000000f5d47911596c46c0c08cac5f5e7f6d0609874da4ac1bd4e0e59c393273a5fe31a756c7cfff2a01d19e79d209d7c6d3e000000000000000000000000000000001010f864eb6624132d4436d18db7f5b34727060dc426c109886be88031e3c155490cb3fb09e1fbccb7912875477c6d840000000000000000000000000000000005cfbf1c2ae1b80a8c7cfb2cefedd907b0552794f4fda101ca1a723b18de8cbce30eb54287e1847cee3f416cd8b45f2c00000000000000000000000000000000084fa63781f7eba9c7e911ae5866d485bc7e90603541c55d1ffad8b3cf7547fd57fb24b14002560e58410b828513e109c07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a00000000000000000000000000000000124870cfa469136c638e0cbf15802f2699aacb66d7e4c2965c6759dbca4b7e47941ad9ec37a84db1afeeeaa65a7418e4000000000000000000000000000000000d4503049a6a53536bdf41dd832a6ecf3f10554887da7e389cf940394e1d88db94369b7947436546eb6c6e82c48dfb9900000000000000000000000000000000053f9a6e1f05b67cf553073358009a172e2ab8b43572a974da1f3de85a29103b13d7e67b2a359297172d27dba5c61439000000000000000000000000000000000abc29f50ddc1c113c73700b9b9796890cbf48818ba981fdab2db27ef1c58f4c2e4595b99eae397d40990ce2f6c9317c29b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd00000000000000000000000000000000007d2aae9794b7a7de97f7146c0ee8415e09e56fd42535bce6773cadd6f7ac09c4eafe2e926cb7014377e54c703eaa9dd00000000000000000000000000000000172a4a33ccf99eb0473b2c44d30bd53159afae0c7706ad128bccf6258974d5e5761f9be43e618cdbd96027aede7fd5860000000000000000000000000000000012601bce2171c6e4c2968a3efdf1491285f9e4ab37cf973ab5c8e224ad5b40e1b6459ac89090c73deb8fc79fec7fb8e200000000000000000000000000000000112a6443116e6f98ab348e57daa3971b5fa506e40515e1611fbed3e7dd64c5c1e991e0d2539a70eb93e3da0f573d6b2263d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf54258000000000000000000000000000000000030372914b83644fa4db1958831e9335c72ab7a811fb337696221a3290e4c54bc10c2225f8fdc3a9f62632ba2f1594500000000000000000000000000000000114205926609470b6022d24046a1997c048e6d2cf6043397892c967692161c0ceedf409bf5e1199a64eabb1ff8de23640000000000000000000000000000000017cdecbe73779855b7b94920d4bc8ad057ce51c5481a5579650df8a5bbc421030d2ac44568217c4dbb13d7c639760236000000000000000000000000000000000f194fa814bfa7396697bd812d9449d06fc61b580d7a86429fdd1ad376e21ceca139356d7d13964c3c684563675711c67a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e0000000000000000000000000000000015d4ae1521acf897344c3a76261754ff99742585af4a0ee86dc473a88fd408091404df1da9d8bb291db68bc9c07d6b2b0000000000000000000000000000000008ce160213875c661163990f3f7ac219ea295db5e828354864517ea8689ec15d35c6df78ff14cb276e0c97ffd7fbc09a00000000000000000000000000000000038a3ee211e777d6d6b7ca6c7a0d2130f1a071c030eebec412c3a0f14c3584e7c5cf15de254a8f141a8210a90249ee5a0000000000000000000000000000000019f7ec6b2fcd8b3190ab37a6e843340d3f3fc092f5772a042edbd5bdc967b96e8a1dc9e435b8463496aa1301f87d0e5a81b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83000000000000000000000000000000000fa7f8fbfa1d4ef5f001a451c55ed261dee344025e599884b29d086e15665867932120d33bee579d5eb1b7e6c7299f310000000000000000000000000000000001f06356f793350b17b47a623059a068800ca1eab6089c7c146182990063e8e23bbf40d95a42bf6e976224b680b75bfd0000000000000000000000000000000008807f6606d2302450bfd8b38fd4147b851ff59762c1ff48f9442c4d7b77a32c5e023821eb47fca839a27fde60e5f61d000000000000000000000000000000000c5b92f1ca9c20d4b6b11d794a5853824cff20d9267a20a7aaa4bed8bfdc728c4d4d50feb8f0b569757b97f473138db1ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de070000000000000000000000000000000001191410ec6c5ff628bd25d35965f5e9fa7f3c3d8c0a9a1ee7ae37437a97c25e221110d892e2c7a0e9c8e386774eadb80000000000000000000000000000000003be30c25a18cdab139277232d8888f6d13112c9556895af8030f1893114d5845d895df9afe3c6f9ff7ffb1919adea9200000000000000000000000000000000197f6b4e38be0358a3f1722664c61e62587ecf5467f8aadc3a236b47682a75cb76bafb18a5c556b321d5da49cd4bfd4e0000000000000000000000000000000002e4ebf7f22d929b7421a600e67fa2e64a59edd87a2e2eb9dce1f06d3c793f1a812bcdd510e654d44fb4c1de8c64ba9f0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b60000000000000000000000000000000011c6f1dbccde640f63ad7d40089779d01075e26269421b4ce12fa5341f58ee9110f17d08dc1052426f2d00da2dd70b4f000000000000000000000000000000000740b147bcdf06705971c113a5cc12fb37345dd59f2cbb5ff500ce2b347fc5a8199cb3007a871670d5093f28979cfade00000000000000000000000000000000046563ea98b5e85b3c42222d5e0d8481e6aefaf077a1b99f2b4eefb397ec846aa3659aacda569054c9c8b9b69750272b000000000000000000000000000000000812d887943506d68e3525ced9b979354539b7b14003a3169e0084c26326b92be67346920c9a99ef0f9638e8991296feac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c796590000000000000000000000000000000004c8078fe8567013e8d05a546934026cdeee7d485e30d739407db16fefaef53ed7bff0f9adaaf064aff014ac919d91c600000000000000000000000000000000107cc17f485af7f22e07cf14c5cad6368323f720511fc9dda677b360567f769e47a77f61274927ef9b7be48a77357ec40000000000000000000000000000000001487f0880a6cbdac33ca35b9b65e4ead9d8c2e9180c993bdb2052060325aff8c62668c643f0cd9b4bb1f06a3dc74285000000000000000000000000000000000d4b2d062e31fabe8d2a329dbd6417673a519f455739d140246f2b3e43e20f390088c08e545bf0419d796ac71aebb5198586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d000000000000000000000000000000000811e9b0acfc10830c074c5a4d9f4d9382461eb523a61dda0b77f1c43b285fc5c1ef3a1fafd923addc9a6e904505a255000000000000000000000000000000001113102d015dbb509f0b8d0d0ebb4d3711c4f0e1e3d55fb0af247dd24be4fec9d6fe3ad73fbdcfe206891bcebefee4dd000000000000000000000000000000000085aae9e58fb97b96ca3c089acab7bdbd0c3adae141bf61075f5c13145b0d07113f1075dfb959bc7c2d3d3b3a06ab2a000000000000000000000000000000000bb5eac8125807c10270d94e5bcf278241d6fa82f68e41b5529b28aebc88870af55881db526f7bd221a8c4c0b29a1b7d6e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712000000000000000000000000000000001335276775545fbb4c701beb57cb34312108c9f1d46b4aa4b09a16faf0e648b4e80848bf5e75ed8730715f0107afc9820000000000000000000000000000000006ffff8736bab41b4ee5681b741a81fc870e648001027161144254d04c678e4f954e9f191bd8b26201aec681cbf0654b00000000000000000000000000000000026ede90d14fa0885baad21f9631bae058573251cbef5757bb8cfad061f3bdc78834fa5862dea19a2236c014b0f1652e0000000000000000000000000000000009844d0cf7f6f3401145d8d720defa577ca46b49e04e39c4c139ec6811a574e7dd5ce3acd00d1ce9496f10dd15c6d94685cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a720000000000000000000000000000000010192b925fca096682acf138833b12d96bf97c9a2e69e4266eaaae1785b9008f36082e23e2d42341427edce24449935f000000000000000000000000000000000d5b24a94adadbf542aa663114096bc670e1b6c99f3b661f55de121922452534faed7f68d6b431fcf6f3e379d7acf6b6000000000000000000000000000000000acdbcae49206b749d8c0d21017a33e689ebe26804d1fe7c863a2ea4210c3559805dcf73685702bc56e644b4e02614a9000000000000000000000000000000000092309d684fcdf44bfa321d473060dc2d8a8c66c51419894a3fbadbf1b56179c31dff25403b970d543f1dd0e19e56cf5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6",
+ "Expected": "000000000000000000000000000000000b219032a2461a5fd1e43361c46beeae92e30247acadcdd241692abe81691c295ba38a1f0a2a45ae76b1b95d7d0fdc460000000000000000000000000000000016905f64e581aafe928520adc27c24703e7adeb36dfbb416a159cdb9b9a26c9cef0821ccf52f5ea5253b7c9d78769e9d0000000000000000000000000000000015cfff195b2123aa140f963628c41deaf19dfff44d26a38de4547c3d15edef10fe9f65b1802dc374d7ba8fb62117c8880000000000000000000000000000000018dc725cc8d8919a7414b7866fdc54c4467b0f87cf99fc9b36cd65c0ec526e32649f9c57495657a93487f1f2f5769168",
+ "Name": "matter_g2_multiexp_4",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014441b14765eee30e8131a7ef62c3b59370f2f6f0dda20fb2a3654fa09492bf695de1d1a8f250bfde3c7d2ed805ffaeb0000000000000000000000000000000019d813f8be2519e89d42a9fd3fef09d44a996d6a4713a9c224bee10f0ebb196370d6231fad810edf9cb4c875f08357890000000000000000000000000000000001a5abea13e909bbefdb51ddc699614366f271b2f6490ac8efcca7759833f3feae11057ab1b9ea32311e7b6ea6de110c0000000000000000000000000000000003ac2bf3c5486ca176e34ec5212165cbe04fc9e8c375e3e999a31fe014eb824ea3f2d06b9cf8b86ce3a76960cf2eb4d7535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b000000000000000000000000000000000598e111dcfeaaae66d1522be2a21131350577253a3f33bdd74a04b0bfba2940e73b62fefa8f0c34c4aa91b633f6bdfd0000000000000000000000000000000017fefff7d94afbeceb33714e9b5480c3a2f3eabf9d7f6e8507ae54cb65f69b21cd7d04d23f24e3a272c589f572b91864000000000000000000000000000000001652e3f5a99ba8dfbcd1f90de955ef527947642054be603c1b84b24bebb579b78e2a0be426ec21d32783a0e55f0178dc000000000000000000000000000000000a6c9ec91e8bc86ab198416cbc76239f0ac0b903f40310ee1f2066b01b08191538ca913c2736f53f23ef37fea13d52756e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a403500000000000000000000000000000000072e022c168461905f798e87425f2eebb517e473cef98c255d0fe434863ef5811920af65bc946b29d489b5dee1066c56000000000000000000000000000000000e7a9872caa82d191f6014c845e1b3ee4ea1ee89852b546a2c85ddbfa3c1d4ce99002e3d7732ccb8cfbd57d550285ab400000000000000000000000000000000144be65db373f6401d76e0ee64e51076b861e8fca596dd6a7f3b5735c23b0cd13248404fa0969ecaa701663a1032f48a0000000000000000000000000000000014c9e9c5cffc4518889f7742440053678ff1d9fb1a1a103d0c1f762b10655bd5849ce98f4bc5eae80bdd9e767aae4523a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff000000000000000000000000000000000948d0f0c20715f8658e1f2b4f9d32d851e584287225a2f47735a1f4c241b07f8d7c5dd8c13bcdf84e97d49817d4d88a0000000000000000000000000000000013c064548cb756b48600dd535af8eb5b9138f984bac0391df2e90a204fcb6c36017df910031864d802a2ff719856b336000000000000000000000000000000000000b7eeb7c9a01be88e573f196c2a531635baecbc8cff9af385455af3757301436686596ec7fe3618af26953c49f7450000000000000000000000000000000001332f4dbd5461ab9e2c8b3c19c6ff407a071018c92d2c17c1d1d481c24565276c0f55eee8692016c1fd76d70f44627cbd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b000000000000000000000000000000000d3ee70610b5029a28e586f0f3e65bb19a263db3438710fcb8073e1b25f83db50eb5bbb9d75cb20952a225023f747baa000000000000000000000000000000000682f7d5cf9d182b20ee88683f3915e8c9b03074a373e573aa57232de4e997bf155acf680e365aa0988989dfad102b2e00000000000000000000000000000000143962963e230a9154dc328f9583f5be6923a3b10ee7b1d0cd5f5cbff13913d8ff78ca315be7387900a50b94449884c0000000000000000000000000000000000f4f934b42452d41cc20d7b1ec547bcbcbcc10f215364ccf2b864db23a09d06e94c7a87165dcb691f4975323486757ada300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d0000000000000000000000000000000005f0fd4080e26971ab16d33aeae04220ae23781da3179e38190082f1d167514bd73bc8ef976a2f333570e9f56a6c05e6000000000000000000000000000000000e159905d29b52ba61575c3a263093017783e1028b3701ccf060c165ba33a765b5265a9b1681c1759bfe2c9c401275e9000000000000000000000000000000000c5ac0bc29a49a7c37d772954da850e6b5e301e230552be9a94017d770ebe2cf4dcfaf104633623e024aef6db57892900000000000000000000000000000000002228e7f42a9409acab49cca82cacf306f6c6c29fd9f7e2ed12fef2d16383cdb7bb2b39ad598b301072c615232db1fa833e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b3300000000000000000000000000000000180569ce03e4a0155285e733adb18fbca71225507a7adf01cb8e8648891525305e92087f58378f4fd8455d5632ad660e0000000000000000000000000000000011ab84e42f10154e306a568d7cf7bc381000f0add0500cb508f695a3b283ea69d140aa0ad48fce2d2d6fcafe60761078000000000000000000000000000000001136c3016474d6f475609606e8d0269fcdab9fd3188a512681cbc41eedeadfa3b3d9355e5b4503e8b5c3665e49fdf3ab0000000000000000000000000000000003f56cba1b9cb4302099b16b09c2602dfab80d1151685ef78e5054cd454b319adf8b5998053a5b9fddcffa020595e3bfc48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f0000000000000000000000000000000004d79dab9eef873f3415d66172bab7166ce0c71f322529bdeffa915c1b0d3fcd645c91dd3450ba61593ffecb95edb91e000000000000000000000000000000000d611a207d3222bba199fa083d0459675cb5fa00839fb4c9034ad868fc1e79d653c18651771431d6fb6b6b5ce8cf6f7a000000000000000000000000000000000ce802ecb106a4f0ca4efdcc058dd0e29deb6a5d30a2c15c8eda896bcdd3ac19053c10105328d239b26c5ddbdb3a95fc0000000000000000000000000000000001073e142621ecbeff6f81453660362545751f992ffeec3a83477fed3e6215a709ffe0d17b65d3369f8f3913bf000e844228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c000000000000000000000000000000000bd84f04b3858b1138b1b429c7216d5d1b1e99c1e0fec26440d59b1ad79788c2d5583122c2ad769fcaa6d10d816a1f1e000000000000000000000000000000000387977ed1ce5da51dca230531bba53d17d3de5d593ec576cabfe6463d5164d7153025dbd4cb3525c4145c4f6b85fc76000000000000000000000000000000000a19c943a90fec6921367a2edc5bc38a5c59839cdb650766a2d2d068242463dd4460bd1d0e7a7fb0e3d2104704b8b3730000000000000000000000000000000011d99d44b200feebe00bd42809e3f67a23cce88a07165416cbfaf4db14420f99e54d62db4280d2c99ca0bc3dc41eddbea417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f10000000000000000000000000000000006a186aa584a466a860849c78e4922889c95a4ac6f39c99029fbb422c43d699a8baa51aa4ef51ff99557babeb3e9506800000000000000000000000000000000065fb15b5a0923bdb52dbefc7e9f1a898e32f17d610bac829235446fc5e1913fffc8176e0fbd33091505761f1d06d8920000000000000000000000000000000008bd358698fd073f660ed608462cfcef1da9a59b10905f1d98c4fe66958e56802814906430c10fc25a4d351d91f91cb0000000000000000000000000000000000a53638b1b6c6eeff468e099446300ca7c7bd899c6494682d14fdabfa9cead0bb37a0325d99e7d0ba6341cfa1d257ba846561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb000000000000000000000000000000001070b98c6348a67e996626ec2752f45e4c007e9c9668459a777c03fab633c10236a1c5be99f3fd950542d5648ef9e88400000000000000000000000000000000073a564401cb1a3a53334c0a55da261814d27b86ebf40b02a76b20973ba2db92e42c138ca7790261c2d70401c984bf470000000000000000000000000000000004212d8a9e4b01f5c6814a88561c2c6143eea61327b031a2e0e4bd056c12dd7098fdfe4d1511bb441ad42b55b584a7bc0000000000000000000000000000000005c5d23824b0fe05eb962194550681c57c1566b315efa8ebc90b3593d7d86ad18328baab8118c9f47eccc0757588591ccf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf000000000000000000000000000000000b1b3053774ad5515a20bd4c556d2b3ba95fe74fd0c955069c7f933dfd718ede90ac295f5a675f1c29dcd9701978353700000000000000000000000000000000145746ce88686021a0635bf6f0aa2f77c48bdb364cf4ffa804a57f95bd69d24eead05fbee24021c1ef57e1c7c7b894b00000000000000000000000000000000010ec4795a0762b86f3b83de1198698af67fd1b1be3ddef48f35cf82bc96d886fbb4c75064f51a9cfc5f61630c95d0ad1000000000000000000000000000000001465e31f58892466b8ae4b76a239d9f8d1ecb1834886344013cd1df0be13591798868d224d38213a6d75b02a1fde0ff2f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5000000000000000000000000000000000f39e731e6ddb7496448c912ae314e833d28208252c7f8e27bcf7eeaf1da6e2310538b4ef0d55401c6552e91fd70691600000000000000000000000000000000069d3612f924961f827497028737000513548ad8e104acee28f014e730d4752a583cb9a893e6169b71966a1c4a4ad2dc00000000000000000000000000000000090899907edcbd336bd4fdad0dd67c578ced4481a25b864b32aef920842689a2c23265277a6e1d4a1dc1b5047a9f79a000000000000000000000000000000000055ba64e2502baf68e46c759fca30247a080464eda2b32e7cfe539e545d6aac6dafb731c2c45749e50513979cecbeb5440ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e00000000000000000000000000000000042f1c8b9fe81cdcabea047d0998a1354ce09d62a14f1d0e9d188e2f35f2e1845c2b090c5e157595b33108c67e6c184c0000000000000000000000000000000018e69d3564d4ccc0306e1e6b227b0f961aa9afcad59d4ee1737f980dc876609c59a4c6a3506f987467beba0764b857000000000000000000000000000000000012ce5883156588cfe0f4838f819f985b09f1eab40a5ea8e30fc5d70d029a01a4537641248f4c21dd203909e0170737c80000000000000000000000000000000002888eb9778a4045feb5899dda258657b9f41345731ba630fbbf186b3be4b58ffc7f48abb65b693b573a73f85440a7a7ae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be500000000000000000000000000000000051982b46a819c74105cb36da871fb2415328a1531d155856f6551bd043eca62ddb61f24af429edda830fda31e22cd340000000000000000000000000000000006449e5bcdb5619aac542f6633ee3e06a4fd56a3e1ce4034efc608131ff6ead70ca63e70f494f519d5c577ae7119c8c200000000000000000000000000000000153f4f5dddd5801fbf7f88a735b9170d24d5b63861d50cde9644579dcff277cdb0d5fbfc3b3b819a1172de05afb9135b0000000000000000000000000000000010fdea84983fe6c08cdc4b4ccd462bae2ba791ab5209363b10b3ef342c9a5e92184e9d8be1419e3d88402bc05bad5fa21268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c00000000000000000000000000000000009b011f793d9a939d916d058ffe91b58138820a646cc450389b3074ae3715d06ddec1075afecda71c65c7ca085210c740000000000000000000000000000000003d4d20f4b93c1e90a0a06bd534d8b4fd64e4c4aba77ae42cf4c5b2bd95f8b02ec4069ea246ff46404e6c9eac632fbac00000000000000000000000000000000051e88c3adfd4d6a02d3f03812362a6cfba3a6c69b9aeef75b51106cc7f1750293d61e31f0ea29b5d7aa56debb6d2aff00000000000000000000000000000000086d9c4ea6769cdf49ffbbf7351023b4aea640e8c90f9291222fd0b5984bca4d481bf7e10df921406a34804e6a09f99df9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169",
+ "Expected": "0000000000000000000000000000000007638fa4e8823dacb40ece440f8f1e57cc5c3851f94357a5325207db92380dd57a7c8709e4d00b670e8af1b77368285a0000000000000000000000000000000005b66a6e6b13ea0eb367a61ffe7c620d9edf5563cb4cc0cdfa68b99d9691cf9a40efd967c1e880238eec313eaf4c92ad0000000000000000000000000000000004f7156c69ea88a71a0af2922d1caca24055d40df058eef02bbf95d864156f62fb0e17d9fccd193840c36ad8449bb4f7000000000000000000000000000000000b8f46fd695c5d96d939d42c65c3b709d32f134710a67909dc4bb43d752521a8d4f0465d0590f30f06ce42bf5f8cac28",
+ "Name": "matter_g2_multiexp_5",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010d48bf523f3909cf90aa58a9517ef5421f1212accd5e8a0f830aeb15a587e215ca9c340bb846b1d0474e43840b2af79000000000000000000000000000000000cc1a3976caf97b9d59f448f6d9f413eef8904f360c0cf912fe942b38d7fcc637a17038973a133608ae769d3e389b18a00000000000000000000000000000000069a6122c6f0ec68834b7617c755a7eb33a80a25acf95859da5ff03316447182f122d20d993b04e79b6fe859b7adf5a8000000000000000000000000000000000058c6f8c297524319bae6722e0a957d1ba0f75ee3a8aaf06148641c67925d15780e419a38ed7e07410e82769da74f2d070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b400000000000000000000000000000000156ca5e80be8c8c03a5506ce9abd22a9d4958c372678c0caf6f1329898507dfcb1f06a9464cf080bc6881fa5b7df1ebe00000000000000000000000000000000088174d486b4086b931010da298a399e15b60a113e08f571e096d3a4e94b57b3a684711318796eeca9319119b201abb30000000000000000000000000000000000b96ff68505c088cc03a1c2dc363b05bc8544728a12b29569bed137780523123eb17e68f4632383c252d81bca0c5ca9000000000000000000000000000000000486fc6e5224c5fad56234c41856e60bee4a6c1046f673bf7d5c1bbb603b141fc91074da5f9d3d41b796a2ebcebd9e74d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e12500000000000000000000000000000000121fe97c62e068988ebff21d8129d52aa903afdbb62862c7fd99564d9ad72182ab1f3a1100223ae486cd76f6938e123f000000000000000000000000000000000968ddedb04f52140160061828b5f88dfd09aaf37df625ee6f66b9500d6608df31c7edf86296eccf8f9918b051a5e4df000000000000000000000000000000000b7491cb8f6252e3861d7160feb0afdd736d27886863ec0909a7cc711a9b71aace18b17a00a2999dd57ca1a74f148516000000000000000000000000000000000fdb280093ef45b12b694ca3390a865ee18e4c04b231e2c98cc28706d4cefaf4e654582ee03f34ecf1dfa9674489d553041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b0000000000000000000000000000000010d001a09cf5dc3276482185f26ef3f75d28cd6d2667eb08a7fe06c03b99f3b6c4d82390739b6867a314291cc642a8b2000000000000000000000000000000000587846a460b1f37c2e7f491f9a097b4e86e1943d9cd0999313f65627b3907f09b5d5ac1be376a313a959dd136f7e9b3000000000000000000000000000000000af439695556e86b102926d3b40e3e54cc84464e120de3b4e3c5541a6a5bca44151fb0594009663764c1824518b13f020000000000000000000000000000000003bfd9418c1e57269e222152d321b83ae090f216cb422956dd1fcc464f68526cb4a05cdaefc7bbe6e81d4ffe27d64db47cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf00000000000000000000000000000000196f78b64fcc342ba4f4edf34a3080ec950532a5de21a875dd061f09351def5ba3b85745a561e38117a14c20d33a14610000000000000000000000000000000003929c2bc55f323d57dc3529bcf6644e61c941b72b424d69969c1cde7a804d157045bbf6d5b79a3e6686509e11ecdac0000000000000000000000000000000000f6b659818510cde463c52cf00bd99da045c80af4d5cd0e55f9bdd81f34169fe869c519f37a98ff20c56db554469087600000000000000000000000000000000129709e97757724e765f6600c2b1928286efab55ec8d16876a2a3210bf9d31cc5425265d0576a2d5469cbd9a6c8c27c012adc8edb64db5bf0ed6724f3b54140ed6c81ca65ef9d1b38c8bca6a62bfd3c60000000000000000000000000000000009f5f167c9b61a0ef76415fcceff04f3fa57071c2d79f443ef8a7e6049cb1352f650ebd8f358904bb432d42772c29afd000000000000000000000000000000001524a875d73e03c53b92465bafca582479110611bac6a98fc7d76966e9781308a10cb202289c0776cf5c36515733ccf900000000000000000000000000000000002b1acace94a6fe196b217a9aff413fe0bcb55122ce9e344942843e5afba0d5f2cd0bba14c9c8cb9dd1c3e9024918fc0000000000000000000000000000000018e4f85c7663e596182603862adb559635fdf16ba35fbce7278680ea289f871bcf6755d85654b2a37ae77a37e77ba06ed1535bfcd68e8136808edf89967fbbf76b7f58d1a8ac95ebd4944b9e440f20b20000000000000000000000000000000018ee4b4855f866781f38a618c2fe4214c63034620ea5b72361079b0a5c2b2d6fb9ea73fa202db3a2678cf07219cde81100000000000000000000000000000000180870513afef93870ca64e2363fa1aa43a599db97f3b807ada1c25ae331c80b8ead5cd69b6f5a65a083606591de90ff0000000000000000000000000000000010afd546703baa35a9eabaeb45d301bd5be115557bbb4ff2a0e493668ee790e947eeafcaa923f62ca00b8e635994e39b000000000000000000000000000000001089996b218aacde4ccfca4d2f66d79fe161d962baaf2d6696e1a76ea40af4ae7195e8cf9f6417ffd054f20b65ddfb104c576996d90abde581afb58903cde4b9443eeb65e21b0d68c578e04c8f28f3d30000000000000000000000000000000011757ad74a3fb341c8eb6862978ab3fb5e8cfc8fdbda7d82756532a890d61919cce931872ff339843805e00d8c62ec4200000000000000000000000000000000060783a06e93e82cb08e5dc1aa31202ba11676511300e186ae8e45248b7fdec3b7d5b6849f8b79b8f78ad84f36218544000000000000000000000000000000000ecfd8ab18066fe3408fd20f2a4478156e9a19a09b58da76486c9f6a013d861960b6b99bf49cbecfa8c9d01d5615c1bc000000000000000000000000000000000b45709845d35d7b560745375df79fb95df15e85b96cc1b98cc832c74621339c609018d153bff93f2f5493a52b7326073c558cc615b1c61c9a42b8b0ab4668ffcfc9e95bbe958e72e7a5500058e6b0bd0000000000000000000000000000000003f9de90222619216852356052e9819d7c6e8ff91e0c6f1d8cec832770ed9001db4569fbf579ab16964d76ae7d1b89e900000000000000000000000000000000010b7cf8f0d283cc22942ed73c599115763dcfc1ddc98d87979fc3dce2f33ca3531cc2909d94f86736dda2a4e94a4f0c000000000000000000000000000000000b0aa4d947644cbc7df8d1927cdec66a68862e5a806e25554f27cc1a3701f429fc7097497ad0419e21cc403b472c8ea900000000000000000000000000000000146270ecb66e1763437b824f2ae122f72f20eb93fb30474691a0a192ceb932b1dee111fa44954075335ab360d31ee68d61301b4957a468e2817db5914ff102bc96460a2c5c15e78bd42884b1223fa71a000000000000000000000000000000000c977cb8de4b6e2e33d916f74eb4e42f089d22b54b59fac9aab0e4cafc8aa2b0f8c55d7251662b3499ea140e322dbbff00000000000000000000000000000000106944a9c2d2ecd08e109de29095f3460128bb751051a1f079acb58b6a60b0bb5f52e63d47b688f4a382a77c3b039eb5000000000000000000000000000000000d2f8be1c78995d54fbccab61f816b6ec52dd19aee6aeedc0e4bde2898b2d07c2925da0440a38c4c965a823fff10389f00000000000000000000000000000000183b5d15b243cc5d9584842ab1a0a1e01ad87268728d72aa8c0d7ec6e7069063a11fdd1525d2b30b35e4568da7c44c5495cd2686d24a5bdda0bcb118a2c0eb5ccfe411ec452e1beb3adbda7e93ea367c000000000000000000000000000000000f65ad4c21fddadcc49a8f7bc281d2b7901707f51a67122179fe97da46ea5e1bc6e70d68eb4eb6776307510a67e972620000000000000000000000000000000009003dc68cb0cdec4a502436718f066348f1957ae65ecca8d32c5fd776215cb9a098c0ffe56c92d79dd68d251f49f13e00000000000000000000000000000000038ecf0bb98ff2e84b388c58059ba0de0cff3d5881ecf01d668495ce81b76b00323c665ba88309af5552b7950cc8c08f000000000000000000000000000000001924aa0f460659f552458fb469467a2925fcb2420d4fa6249310456853be3d08bd5c37a3f0a9d6e94e434391d20cccedfb81d555d1e2df92cdb487a888fbedad976dce54b5c46a39893edeac21a12d6e00000000000000000000000000000000189c3ee691387fbbcffdb147c880218c3e5c0bf78c44461ac1bd3ecd5d4b85225e46cdb068049607fedfcca14882e289000000000000000000000000000000000260efc08531083db2839d1413c90968e87d79bc1a2c730f0020e40beb92e84b73ef43e80f7c61e1a30c0cee11b3cb370000000000000000000000000000000005c852ca0aae2c575c65ef18b624f50a32c007d299f24a3ec6cacbcef1d6e3bdba9650fd7d639bdc60a3e107ee9c013c000000000000000000000000000000000321c01a9de69d6b89db4ed88dd48261ee28facc5e26511fb2833fa45edfb58051c8c3ce9501e8b4c3cab9c456705889bfeed84bd95fb955d1b1045c059ffd051324dc8966e504164e54f76f02eb1b8600000000000000000000000000000000183d50635b22e4d620130e0d4008e3bfffae5dadd7e34f4496899ca54eb4d9e3e95c54ae1d9664609c58d02ee5eff65500000000000000000000000000000000029e3b4496a379464302b1476a4549db371f5d6721704b1d6bd35e2344d7679f8a61a0c3b12f287fd86fd247f9652cea0000000000000000000000000000000012c6a3793fd23e955708f5aeb4d6efb670d25a38a67813ecc72f899cd5f926ab7ef198bf6d591328383aaf54f756c66b000000000000000000000000000000001914d3e4b6ea96bb91333468fe8f3bb74636e9a4f2ed198e9ff01b49ba02791d5bd63224f6a38538aceb777168bef688e3b308b95f6d496e6d5b910b6aabef8d9f868471653e8254ab4d49d593180d250000000000000000000000000000000007457f2601621a99050d8993244f026b9a62ff7055b325e6f1edd1cf54065785f003cf7c8a4bb1f7bdf14e220e490ada000000000000000000000000000000000928eb76b428dde37546a27f3d77605c293738f448fbdd6d618747b0de04004aa4419cc5601600419c6e1d470c15982e0000000000000000000000000000000008074e9f5473492dd2e536f7b305be4e5c564cfc9218934d03dde6dc5118064ebaa5c26fdd1123a9c31336c37c1234900000000000000000000000000000000002bba1f9b7da6abd2b322c8f11c749b2a284552eab25a77d21b38b028da477a3ffec1901a015e81fe2893576a41e4c0bd4ea92e0e776be341c8444d4040ec121a2847256c5c9bc918adb28618548b0480000000000000000000000000000000003760958eac45397eca1a1d951a80265a728dc3c584f7dae111e7ce04248885321b69b334b00cdb0334a362676c2d32f000000000000000000000000000000001031e4a63129ec40da5fe9dacfe148a67662eaa00e1fd5c30336462371c167348a10e50f4dc18469a1a6b76485f77e12000000000000000000000000000000001412dbf993c557323426b486f18a91d16b4baa2c497b30fb332a710ac901c96d46a577d04ea87afb08258aa6d204a1c9000000000000000000000000000000000da015ca09ac0c3245c090f39852218f46fea62198fba35ebc4a7f14887943c3bd1bbbfbfa300611e45f419b33988e404c07f5188e4c6270a7e9e2f551683c4f9dc943ffc7ec279d15816a7f4910b8d30000000000000000000000000000000015c9121f72e2425cc8aa4c878907628dfe75a903b7f756b9e13728372cba598859d20a92a8297d95e1fbe25fd1cd968300000000000000000000000000000000025a3faebfa53918efa733949f914be08b791794bd4963f0c3fd78df48b14ad214374b08299327575c0731b54eafed76000000000000000000000000000000000771782ecd9980da521618af2f9eb55d91d67b20ba615c7b3cb1a48d483ca405fe99a1cdd17e4dc7aeffce586987d41900000000000000000000000000000000136000da90a76d538f336608ce877be943025b4c8bf15880ea9c1c001c20c954292d362dac9783b7bf66b8d51ddaf0f2a819a0438efd7ec0c1e3eea07ba201af6a832fecec818adbb781ad0c23e81dae",
+ "Expected": "0000000000000000000000000000000014cb24001bd933b1d5866cc3de9f4b8479fe23e4fc26dd210f9d06e7a05449b9f5ac4e2f48fb847599f625824336bf1e00000000000000000000000000000000033fdb2e899427f1cb9757022c5b614f08c64b53583486148b7431311a6f15aea3b968913fd5f3e9b624705351074be600000000000000000000000000000000035420be9c7ae3203d0dec61ecea70e22e62f50368be870e74f9a7349453647a7f61d2a42cec6522164cca0c7081d4de000000000000000000000000000000000fea43388e9f6e31d419c7f9fbb9839b4cec04163a7b401d8f7de73a4560fbfef4e272f1db9c9d5b37693378f139452a",
+ "Name": "matter_g2_multiexp_6",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000039dc2b60389f6c893c44072f4db23e7df4c2f299d6b70b70784d9370d9ff8e5413872c227074d429db999d30dc9499a000000000000000000000000000000001702273db356abe7a3f91a9fe4bf56584f13de4069a91daa6c0b552089bef60da98d32c615aa5610842dd8a507f9477c00000000000000000000000000000000095285e8c508ff12da79e16e0391dadbe9a823c586a049e729596864c3cae117305c05f009f9e8ac032abaec8a63f8de00000000000000000000000000000000078fc70e926decf7aa4c2e4b395e88f367757dc47a4cedcd5e632c456a4c160393837196af474948ce6ad53f830ce8aeb15af019ea2de662bf187930caea19d0aa07a74b49fa7d1819a539e06e4c69ff000000000000000000000000000000000cc3cb5e7b033cff3e5cb01ba29ce8e9f4a93e836ddea7d417f7b07ba8aa71a0efae2e1d7a8ec70bdff12d84d229245200000000000000000000000000000000019ce3c830505324b9bc7cda1fbb328150d71310f06a8424dba861d67a7bc0428beaaf697646d22cae9e00477cc8066f000000000000000000000000000000000f6ff67efefa5636b104a0351c90fd3e89a32b8a9beb0d123d3d6ae42eb5e8bbc19c7a972e27762daf852259c65fce6f0000000000000000000000000000000018d98c43fe5b13b701749f4a5dc25f0e713d241d573639fcc73429226bb131d448283338a909670066045c65789bf9e7064a6af51c1d499c4c28556ad1255af7467bc750bf2db2842d626647bdb3346100000000000000000000000000000000003cf82958d68429503265dcc7d88a3763cca32baefe3c8d32564cf30e8e6b8255d4a9f6a76bce1da473b50287deda74000000000000000000000000000000000bfa9cde6c06b2a2ff8f877ca90b3827d0aa0408c4ccbed23ad461433dad71017d4dd387f49c5febdeafa17d06ba784e000000000000000000000000000000001770fe70513533d91c83449ea52964cd8b449aa81f71e71995db5b19ceddef18e2919439c80e10086e670be669696e4f00000000000000000000000000000000194c20491c9d5ed827cd9d370b9bbec55e4a7b1c34ddd1d80201e7019d9487a747b4fa57b480dbdd09af73aa4f5fa0e9a3daea5a083af43711fcb09282b66882ae5b5b8e1714e9186f33ac0dfe48b7ca000000000000000000000000000000000a79d9e0ff43249ff54526c5e1cd55a9bce93adf272508871326c933d526602dc9dae5b6f129a0f1c38139ed1c39be5c000000000000000000000000000000001458b554e0387c1ddb9dee9f4e9fba9c81c15807f496442f4b7210267912b9439a19f95dc80a1e09a0e5cfe750f43c8800000000000000000000000000000000012c06b19ed4e8d5d1b9fed56bc5bdaa3bf0112db997e33aa14899d53e1bddd6aa91dce7e9d25473b66b8578d398981f0000000000000000000000000000000015369b2228e728894f2fd7c2d8c41ac3550da4f297de445cc0f0ef7134c478f526987643cb5408a0bbb79f5f983c085ebd682acd154f6e16a583ca4968d28471653375ef79df078b17b2cd9634258dc10000000000000000000000000000000016649a8231407074af5ffa93f9db5a2ddce8785be8ee77149602d6afa24ab30b26d2f74bdb5f7464333924a817e242e50000000000000000000000000000000001b990f5ed0b23e113042ff004236646c6eacacd99d1d73fe0c3d9351ce8d622327e827b2c0556802c5657f8f06062a4000000000000000000000000000000000f002a2a5ca90285f9b2fd429721c2daffcae5fe48c571ebacaf475606f96cc8350ce88a850ed75e5aae59d445249bf00000000000000000000000000000000015157fe1a767dabc185a8dc8fea3cb208fd995ecd9acab762638faa987f8367ff7c1a60b657be6e9461acc9df16381e5562223d3fae1d303a01ee4642fb4cc70f21937ba7fe377260fe82262a8455a7700000000000000000000000000000000073884ffbe6deff99cb4b0ae1c0e91e2f4a8c2c7296339b1d7e117d5d47ab055743d643155680740befb379a1dcab666000000000000000000000000000000001995bdc23991dd4cbd973e915a16691fb860490bb54011384c553dd14afc37fe673d13950c1e7eaa29c324fd9304624c0000000000000000000000000000000012197a19a498cd94ecbb3a409337b04e76e1a52715c40203add20eb80f7eac66f3386242d51bea34ea016d778248836f00000000000000000000000000000000101069ff0af2ac4dc7a5bf7bf7b56d82a310d67cebc41a9abf1e1af489e1acef3e726fe9571b4382777573712663e26caf1d0fdab6185e1c3f9f621ddc169ba92584db0b40b6ace7ed563eee0090629f000000000000000000000000000000000849b88e7ff52d8136a120f924b20b45ea9ae654a0fa037b62f3c275f0661091038a4c1d6ce7d50512e628b6b397c9f6000000000000000000000000000000000e50e82e9b368f2e316d41febab6b0f626d6588b7217b4e28eedbdf50a4abc9039be9e66c97790d12cdedc90873993e2000000000000000000000000000000000bc5d2bdf06fda1e1d1f5c5eaa7988dfdd790bf4d952f5d3a532bb59edf619dafcbc29274fd3661a35a3f15933b1849300000000000000000000000000000000162e5ce45499e620d0977fa26a291a8e75943c4b5a2a80be395ac9b89767ea5a06606d6b75ee4c8a286d2ea5a197baa5e910487c91f3839d5961f02a67f3b357206e406ba207dde969498e40d4a26e880000000000000000000000000000000005c11afc970544b96fc1a4cbb27259e19b5fd588d1be1c8f19eb4f111882292a463c951521388cb8cb743e5a4a1b57cb00000000000000000000000000000000013dc433dadc122376b75fedc923386a7ba5a363678fcf9edf165a50e160dadcc151b6f402648193d9ef960f5e401030000000000000000000000000000000001893af155aca343bc29989ec2b5a583d020a7558c7663accf6f3e40d0a8eb98ac548e933eb8e2d5fe3550927acc2ed4900000000000000000000000000000000043a79bcbaf07bffe6c6890d95c7e74d127446bdea51a0ba3adb164ea39684bb3ac552020ca28b86e34692c9b36f4384396d32c2c9ef685120995d2244756bd45591618597306193422f3b5df4b075d2000000000000000000000000000000000e6946ddc8a9d73e5b140af80cc91b31b9a226a945a9574f0629566f7ee7650730c5ed758cc30442770ed1602b84175c000000000000000000000000000000000da0abb9f5bfcad73b3f24903e9ef887c660447332e5457e4a5764f6628c04d6fe903679b8dc8bb3aaacde410812286a000000000000000000000000000000000656016c01d3405dce9f7d40e47976bc8a84abc370e7e42849dd0bd93ef1da0bc88e428efea43dfea37dd834cf246d69000000000000000000000000000000001939b2c92c8299d7ec1dbeb9f291c5e1c9481e10df10e6ba18ae695a780aec5a185ed4c7e82dc2bb5af87a74552c2ea32087e21d775fbc2c20dda715e46c9c4970394e40e991c78ecc13a2a5d0b0f30f0000000000000000000000000000000000942901572722e5005a9ef5f948c8cd6f557be8d114d2810d3cca29933a94de3c7658e7e28675c2a49f138d9c98c524000000000000000000000000000000001908e8b815e95ec07a90861ce53f545f0cd44aacc47df40c24d6cbc61e7b28fb91cfb1cb3c67b6c5b38c34fcb2ca35710000000000000000000000000000000017bad3616d8e510e325d9166790239c8c817c68ba7fb937fd5fb70a4219265edf6625b52ff26f0a34c0bf481c482b2c600000000000000000000000000000000023ff8a50a9c0e9ee829ec81972386ea012df5e8476d8c342df6b98fa1faa1382ae921c2f1018a918868672450355c44f44043002a94560d725da2ac44f30cc5f14f52dff5671c6689efebd803b1df7a0000000000000000000000000000000014675ab3efd44bffae321791e6fb35a24b9c07405d9985c685795df2db183ee9dadf18c76cf4095e1e0695dc2c08c4c4000000000000000000000000000000000835f2cf09647061ced2bdf4211bdaea408148100f864f47ff76c0c63a43e44e8ddd9e01709b6ad129bd574d71a1a63c000000000000000000000000000000001017eaeaa6eba76923ff27e5848e5f3b09e7b2b9d55b2cb7068f39defa8628d1c8cedcbb0e1cb5810febc4ccea712b7100000000000000000000000000000000054c873449c738383e9fc2f0f74a6334904171fdb704f5ac35a483ba19a8f661187d36fb35014af9ecf88225466c86e48624c83d846ad2e53f3f8ff5ffd3fca8723e6cd431e89ca29a4d662e82004b60000000000000000000000000000000000439ae88636244d5e09607960fb033e4217343899d044b21e61335425b94a5067c941e83e5a77f4b0690e1de037325090000000000000000000000000000000003a67653818cece3ff0390d097f1bfbea9ba954a85710f5c24d1de1893f25f2863991fb9f330e60cad725708e70384b4000000000000000000000000000000000243394c3459a3af236189ec6155418c1916b854a20b980ca1044b48e23b725dab7c60a48e89f642423c805c117e64870000000000000000000000000000000004c8c9fd9f278dfe9f5e24e0f5b42699bb9751b56520827afc2fae8393c690a63f10e92f77c4a10b0c161408da9bf505b2b2a8a42887ca6dff5b5364d88962068496bee79cbe74de0e8a06209feb38320000000000000000000000000000000011ba67024503301ec72bfad101a48708e3521c8a23c6bf2994078690041cf7eb75675cf5f20c8e82d11145e31751a2300000000000000000000000000000000008ace953ed2eaef19595cc7c9fb1806d26cbf1e888075e3985b28f8d93b9c0b4c820c8e8b50fd4e0b23923d428da3efa00000000000000000000000000000000054ee6f7247296e0748d0b52148a97b930e69991a242767d80bd6434d42b0865a64d3ce60953fd2631aef873d8b2acf3000000000000000000000000000000000077748b724301a8bc48efd1cd66086e727e9872e4efdaf55ba90ad1bed7e229a9cfb79013333b50efb46090ac0bdab488ecb5976f63a38d7f3d8c8ec441b705563c5e3d899870ab5d2ff84467fffefb0000000000000000000000000000000005008a1d62dad51132ad38a226e8abd7421392414acda61111c728713a2ece284b04d75c2bc58d355bb1d3061415010200000000000000000000000000000000189725b7fc48b8a648237021e9a2334247f1cf18ca50008b813978db01667ba08f00b23b3aa0e015f549ff2d5e5c535f0000000000000000000000000000000010483cf2310f64cf0baf556cb2f2828a1c15922547bec03cdb182a316aa86b5473f03373cf7e59a9a78f73193c1caf520000000000000000000000000000000007f635394301441bdc57dd1f4f97656f4218ebb139c13a17e12839091e2e81327f3353c56880c608de824a07a17b2bdd951f4960d6614b098249eb9420077ea5ad11e38d1694f4df33719d1127338f44000000000000000000000000000000000daf4090a229a1ce946064cda1c4b19c88100c8785c69f2eeec3aed12065787ab0abd797ceed07617d55a9c70ac3020c0000000000000000000000000000000011d77fc28355f61037cae3a8342bdf8d11e963495ba3b5d67055f790b1fd632b23565cad77a3d9968d364e4e2a553c9d000000000000000000000000000000001038d7e8fedea873c864b79d1cf8045485299a2bd4d26c5ab5c8d4a073e2c3fcb38cb230dc6ab7e8e228cabc6ed97da50000000000000000000000000000000009de9209ed14d62625ffbf770e8c528594aeddcaf1aaeedb4f3ca973e7b9f9f1a40370cc74b154f3bc641665d8e4d96b7056c7d93d8453be369831dc0575df6438db488780d518a53d19b8f5d22d506a000000000000000000000000000000000a6b0dc04591cbbb1b82a059e08b488fd66edca0f2d264c352f81cb6ec45e50f0af16917fa4727ee9888f84b6c888c60000000000000000000000000000000001369ae16bb0743f65cdfc8082dbe0d588cf8aa5406a095c3deefc27eb3ed462dda9dd4921cde6a1d878a805cd144515800000000000000000000000000000000124e08d4de6e831229005663df4e4bd5bb7af56dfb13244c50410e6d0aea420ba19208bf1a774207e0e0170ad3a9b4f60000000000000000000000000000000011b2973743034a2c362281b11a1ac1c89f59ace09f0a53afb0c2ceb061726c7aaefe274f6dc04e5d0dea2b687a00609a8aa982de1583c25307e9e2c8cf2469a0b1076c6be2fbf12caa8584f34988221a",
+ "Expected": "00000000000000000000000000000000136ff52e440da609b6b73aa838f2eb9791221291b7b14d902458aa7aa9e37114c573edbe8cef7a98dd07275a8c3fd650000000000000000000000000000000000ba625eb47be09ac8cd1e2ec9015640f416af0e3e0e79d39ccac600ea08bdae7a2bc9144f13168a8cec03ce66b9daadb00000000000000000000000000000000095c51e81b5881b009b28006286c704ce3b002e4ca50ac8ea8e574d1e9665a5b1efdd60568d4a4a656ca6a2d1750a39900000000000000000000000000000000143c0c4b3b720fcd0b044a6f420961e2b7eb5f9f1b0d200de56ca8b02709d819f47f0a6ea7d6b49c4f30520586a45616",
+ "Name": "matter_g2_multiexp_7",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000da4cf56fdbaa9004bf8ffa12d5cfb3f296ba5262dab079c91bdbadd6e41ee5f89912bffd5df1643146bce1f0e021b3d00000000000000000000000000000000150227356e48f29443a0ab4536e7a2f86f9e63840e23bbf1b091a59f52c27978bd6a15b29b105132298de45e51134da50000000000000000000000000000000017f5271c97d84f55f8b7ee0d73267bb69cdc7565c470a4b531f9dcd29596eaedf46e61bd79e71e5ade7d000c1c1d81bc000000000000000000000000000000001322812590e6c22bd90511ed72553c1cdb0ba83487b00e3adcb01a9abb438f365ca23fae9ee4a953544253696ddb0bf1a18ca15f0d931619363f5ee56bd7657b2298f228cae8d185c9d062910193e9c40000000000000000000000000000000007c59f94693320b01b56b36f8d1c39fc9e01bad289577738e648771d8940778276cdbfd59f07926e516fcebb70592de0000000000000000000000000000000000aa71d6dcb0b225526eb92b79891ef920634a007b87986fc0f776f85195ad7ec2d84b9bc684add947df8ff42c33b034d000000000000000000000000000000001362cbd6cca3d5c1ec68928be38aca5de1f224e7cd4f5c3ab1c2cd589bbd7c31022d4adc51720bedf2580d2acfa0f06400000000000000000000000000000000162bf0f38e19ddca9aaa370f988be9b35461d2a0f46143e8663f1fa549d0afa1596f029cf2f800b027b90d1eda6ae8a2b54274927eb29fea0cdc464271c918826d5249b2180a52a5020480d1020c9795000000000000000000000000000000000eb12a92fe65f79c646ba508fa615d09d86e582c3337ae16f66cd3bd74a9caa9dc17defb4b4e67ad62f0665c9ad1b6cf00000000000000000000000000000000058b6ce2582c46c0fc108a37e1d2713ff21ec8b1d8c18da0e69f0dfec7f2f327043e174e16d9d64f9ed4d3818a302bea00000000000000000000000000000000068192bd2ebc0a23092bb98c23f5792e179913c4ff1f23eb27296a77e83729803764b8db3b7ba4fe154ca467475eefb2000000000000000000000000000000000482b16e876aa90da6da35e0d7495a04d5b0a1d084c61821f23e1ad63cb1e66ef5975a3cef9ecdf2e696e9d9b50bf9b65849bffc842c21277be88dfae0040c54b072ff526731947cbec0cfe963f2d0dd000000000000000000000000000000000b712fffce3e63362bcc246da566a14139a3d12807ba83ab3520b0aa3aa20cecd5718e2b7e00f24e6fa705315bc2175800000000000000000000000000000000057a66fb12f27e4a5268e56805fe2b61b5ef019b31fcdd861e2b0beecdffe1a3a69e8d193815f97740324aaa40ce34a8000000000000000000000000000000001080a9e1133f37288dbc3835e45b6611fe84ec4790e23e5ff84a2f72bfa2837f55cae9177e5a3a918adde777b7298a9200000000000000000000000000000000142dcaefd73d7f6342e87fff8c6cd161389b6049fa077f35076eadd2b4aa66f3a1819bf8272cac1c28cc02bb6440dc42aeff769da1b62fde321d46c66f8ee7f2129446d805ab7f7bd586268de8f57c4300000000000000000000000000000000034c0f8249d6aefe4cdbf84d151ea9f84add42ade087048bbbf9de4a412cc805dd9b608fdcfa34fa224066b5f06d18630000000000000000000000000000000009e235ce5eb936bae00d3fecead8859e6d909da3d57bbe0a8aefaa5efdc94969a1cb2e12642c0099bca4e7bbf9833469000000000000000000000000000000000b6fbab498c2706f0efdb4effaf79218cf4b652a5205eabeb84f05a060da8cd18c8154a3d37594485ba50a8228f27f6800000000000000000000000000000000130ab70e17dc73f773df99cbe3f978bcd3fcb92a8226a1450239d209cc6969e2cecdc0bf3cbbe9a9c1de072bffbccaa952c9e56cfe957b924c9c0294e1c1f12474331c662c8e86288c97e6a8b8b5b20200000000000000000000000000000000031a2c10e95b841ecfcbddee4b458385e5650dec9a2d1e50216d9fc261a9829eb5fe894e47f171c8fd2f4d5d89771341000000000000000000000000000000001378471c7f770672ee82b70fc87af5ccacdf8995df9ce48aa9fc2f638105a2fdfa48b615970665ae4869f1e2dc7988e8000000000000000000000000000000001969517c503df5560628555a8780138e4c340d9d49d8fac4a8a11c894d283d49fd06aa81e9f0db8f015d9372762dad75000000000000000000000000000000000f5c2d9b7fc33167a6e9b5a5fb8c5d16ca009282edc05cbc8a048b835b16ba33515c226174d6ce5f9836581611ab403bdecec569d223c724d162250ed1d074ed9f4080aaae3f44b77df05292be48ebd90000000000000000000000000000000000a6a32f2006c4b7804e99011d934ac91b1b3fa6f5d02c574cecd6570bde1e998f135449dfc148aaa8fb8757d0a7299b00000000000000000000000000000000198beb461b59f57b85d858b730fcf853d967a1592e5e5787fd81c6a3d9d9b40c1cd7912cae21a47aaf78df5540604cb4000000000000000000000000000000000955701e84721866683b4eaba82c2df8a89bc906fb0a3cde565d314cd7278b0c56936205cc8ada10b03e69b93c48067b0000000000000000000000000000000004740253653a0d6cb15c76e145dc0b1f811bdc964f7d595b6027bb012b42409deaa8da83e6ddc3f0f7b4b237eb62b537915ac9453b831c41becd3c1f412cdf5379e9cd5c80bc6df92ecfc5005356d2aa000000000000000000000000000000000f88e1e30674934bf1062ac619f1834f35f804a958e82121255f8087ae08f10525e740ee53d7514e0ee7c49e324513c700000000000000000000000000000000019d554645696b7beae881ef62297283c5b68ad3fa9a84a47c29cb53449d33d6ee7a5a3cb83b6acb75cd41ac3f52fec40000000000000000000000000000000004b32776966e52e8a72c88a689d6c56833296d384e2059d8f615ccd3616972074987f839b4689d5610a88addcd836d930000000000000000000000000000000000fd4d21b00d81ec993d2350f1fe360576fa983754a7159c2e81024a00931d84e419e8b5231ba8cf8f05a0ee6ccea7e558fa60bc7cff4edde18301af2348faa69ed4f31d437decb7d4fe51142d179e6000000000000000000000000000000000177830cf34186191fa295b7f279bc819d8a53452e2114dbfe709971584ec7a2da7453aae3e64f4b14c261e22314027c3000000000000000000000000000000000ebf2aac35fe070403a4b7a5c2f102c67300bfd68af7863b45185b37ade1bc53d46772062189f348647e74c77caca4a600000000000000000000000000000000128dc7846b2dc5c453ba5fe4675d0c22f4d7089624ede05b0910c34ae623d4671979fd73455b35b61a57c51fe2895adf0000000000000000000000000000000008e33a3c3735be035b550613c712b220595a83c1953b24b3efd38c5913fc23df823e00ae5a1c2ea8a8eebbb93c5c721dc29be0b271d4e22d39e9e06db9e50845515880f30c5bfac80bca39a2d8d61ea0000000000000000000000000000000000a060a957a8da4384e3436110657110653685bb621c32810b6516c690a00c13e37f70185958beb0ed886aae5cdd611a7000000000000000000000000000000000b5afbc85e274049985eac230b2aede7b2df1485c9539a4a4eb6aea406d0f6515ad8bbece7155fb0dfb2123919fb8af9000000000000000000000000000000000afa722987390440a33d5103445dcef42cc4a3c461daa076d56fd38e0b220016ed2bb8e99b9a8da4af96b7da64ba90950000000000000000000000000000000013ea6b8d327191e53bc71fe43fda305a4a0584cad04048afc0480f179955cb27f2ac8791d847036470ffeb47aae36877dc8c2e971a3a4b9909dcc5cc6a0de50286294ee15f441521e0f1d2c3ad3a76e900000000000000000000000000000000032b490f795ac3242b8c7185c9e19f0440ecee3a65263dd4e4c9a431571deb7339bc6e2d73ec43750f6f027bcfd674c400000000000000000000000000000000076ab4ab3e8ed6ea3b882fde5cacb3bd094567288699e11f368c3f60f4283c5bcee7b4c5debeac541ead983f5936d9f80000000000000000000000000000000012aa2060e421f4f4249e83ca0ae1752dfa2b7ca958821841a18f05071a35fb9c1448619bd96f8a7adb2202d3ffda8eb30000000000000000000000000000000008b24f29ee7571f31ff86574e654a5d849acbe92653ae1a1d2baf4c9ca6e67da4937bfda51a70931a6e60d90162efb4f21c9ae0132a4886820115e71e280d33378a04344f635c769fffe91e89fa7ea47000000000000000000000000000000000c8b41e5c47babd6ea113c0ad9f45a75d1ef6bd313b768ac01e6f581ef6630ada623c1a27d4aadf543af4055de7f6b73000000000000000000000000000000000a0f73af06f8f0115bf17f7c5db0a6bdea77a8e3d8fd0b52b0d4e2c558f1331f655dc272c86d98bf166b532ec8e45285000000000000000000000000000000000499b55964186bcc6986e7744c52babf47e274e47a202abf6f816bc748baf846df2b5ced2a5f61fbb0aa2047bbaf82db000000000000000000000000000000000d6c2a9a3fa5d0524f772cca2c7e72a5f2da1a6a1b9550997e7a6cac5b6b6c37693a01d30bebe4b9c742b63bd31487a1e1067c01d5565d0f387516d9721f7f4e5253d5af8353db4a55500e20a95f3c9600000000000000000000000000000000143220e1cd08ffaa6db4795ed4aa35f3b12cce724fcad005367328972f2364f34096e32f1f1cb7a4287ab636d0030322000000000000000000000000000000000f2de47a37a55edbb75ff0bcc446611d690d7f9efdd09ca1ebb6f1d64a330bed420bcc85aed8b95316fcac3aa7d1f2230000000000000000000000000000000016afb044b8b8c64547e000f80b25576aa329a4319dcd4f1bbe15d12e6f3bbdddbb52140e6297c637311ef0c7a31cafab0000000000000000000000000000000019e6803c07fbaa075093f6a69f9dde05ba3d3f58e67389d7f096e56df49f8270008ed422b64fcdadf7cbbc8334037682a23bf766a1e1c068e6e8e4b60391583ac197ade53caf0f8a43c53d1bae9f13e500000000000000000000000000000000134125416c7908cb4454ce6aadb30df46042ef2a6b4b69b19fafcb9ebafe8b5579046725590266cfd10fa26e1b5ff3dc00000000000000000000000000000000073f4147cce24e13b9eefad7c69b457acf126bf278a58a26a7c7c6b482edea6dca9725d7e5e4138b4ec81bc2505ce2e60000000000000000000000000000000006125caac1061cd6c556f4cfc122df8e949622a46ca707b48ef088ee5623df058bada1bc0cce1399f0be1ee86225f13000000000000000000000000000000000146e398c161e29c90c8a4fc44bfd5b3dba6f9e80ead561fa3d91ca5f416e06318dddcfe5147ab5def858fb025a1562352c505d4fd8287a897e01517ddbd7d7ea9d26ae4f58fbca172e5265e2b62858b6000000000000000000000000000000000944942effc77ad02c5ddb052acf86f3a9dc4127dd032181450295464b49ac1dc0047790acb378221fbeebd4c92886820000000000000000000000000000000018e1d201b38d88665696ee6cef11fb19f7daa7f11c5a5ccc73e6b66ac7b89df8437c9f07132ec8b69e13f63424ad694c000000000000000000000000000000001463117fdcf17f28956a42677b3ff431cc17ccbde067b91ecd6fae51e1e24ba8d594ea368d041656022611ad3ed44a6e0000000000000000000000000000000009715cc5add17395b7ddbcb961269fc5d4739d799fe9554b3c9e9f59c895ca5df8ec75bda05cbef3e6a165f7987e78662908006c06ceb9188651c59d434988cb5b51a5a75772ba71875444c65ddf0f4f00000000000000000000000000000000007c07cf1ac9b8b28e3d2f1f4ce22b8ee46e99914ba20c7362c679559a1618a906c6ea65c475ebbeca4947019cb6fbec0000000000000000000000000000000008b29f72cda71e0bc2246ead57b2f758b741b9232d87be75331275a5cd63afc9aa98b0e42c1b82cc258e93c97e596a81000000000000000000000000000000001512548a4bbd537a4d5baf673fb76ea7e35b2977216e7b29a6375e1f92049d7b7d5fd5d8b4ae6191f5592b738e149a5f000000000000000000000000000000000cc9d646428135296919808c6ac10c142e769bf71bc1490196dfdd4e1fc7b84e58155bfdbe77a9e684622ffd83e97ad3e8e8724c80f3527de5f0b2b98ecdf0b8d0471e63c0763a89da8a21a70dbf8399",
+ "Expected": "000000000000000000000000000000000ae9da7d12d0a03cca3b41ad869f762784cacb988eac7ce904ec9ff47824e058e2e211e2285f9fe2aed0b4385949b4540000000000000000000000000000000005b0c873d20f7be1410d39885ce4f79884eb6ae2b2f27510d6f6874dacf2a66c64e56b7aacac61ec88261624936e695700000000000000000000000000000000076c6076175ad748dd68fee64431e5e4ad013797de4528287e7226c3df90233799ed5c8b36848c1a2e1c02591a013d270000000000000000000000000000000001f7f6972121d38ee2d10c621a38448ed12271f7e0e9e4567fe1b5fcb469c7906196fe92c66c37f8c5abc91160fea8ae",
+ "Name": "matter_g2_multiexp_8",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000139cbf360b10e59c20dd4155af2023d5dfe0681c62351dd541cbed41b6a328aa44b862d1985b132a4d4ca61c95b61ebf0000000000000000000000000000000004af6b5a0f7a02d5c93304be0d31959bb4b1a7a5838dc3f9cf50180c4eaf3d32e68c006263d75f9735c8f0b5f811d3cb000000000000000000000000000000001644937e5ff3b8d2005a2f3b0984917837d44412362a121be481526173a4c61e20d61076aa10b4072b79743c5f7f4c4f0000000000000000000000000000000009bd399b55a59550dd876f35e54a5803058228bd6ab6c9a66e438cae473c63816c96bdf378ad426a236b58b90e737831e14282bc687a00264b4e4678ff238d5205f6b6fcc10040d9b4393e93f76297a8000000000000000000000000000000000f343e5118d7dc3a38e9975a5f40084ee5f2305e45a8aed28ef105f76345d9f5646b4f3924b92978846b4e605b78fdf400000000000000000000000000000000017e61a2ecf9b3403b43f5a10a97cf5088b4f98e5a4513b0912ea7ecef44e6809f10dee60367cf2fe3e903dd68c2a97c00000000000000000000000000000000039f37f414338cab0e12f99b2aa1e3c02cbdee3406d1bd17c359ba899b7cdcff605f894530895aecb469f41628c3da120000000000000000000000000000000001b78bf69f1b7168d735fb4b7b135fe70db79f50e792eedea23f83cee9b48e092536c2ed146c7499cf047c5b4f0a08735307650d6cfc681508fc7b8dcb5291837582eba6588132f46ab8fba674a1f5af000000000000000000000000000000001342346f1b553e29e661c9f6c0a24d8f788db98262d6af86af55d313a37eeabed1183e367ee3d83faa3f284b260e786c000000000000000000000000000000000960c8af3f7e6587cf83baae447491e73cf41e637e1efd730e3acd9793717e57b85530584942e7a030bad3b91a76996300000000000000000000000000000000166daca4ee2cb9516b5178cefef0553115dec8157f6194d24d191cfe6340406071883c89246c0cd5f89bbd5d0f1ee15b00000000000000000000000000000000187f668086b9b6307899d301bdbfec915cf24ac0be10d6897b0677e4f1de6a241f3dfb19225644858be0941530e67d0f7d6a25511ba63f0b7ebd2189cfc4c551083ac92b144e30dd81d27e59dd86e22600000000000000000000000000000000032c3783e701bcb651aef40c91682eda03f9d90f252740612c85a5727f8bcc41a886b328d5ce787031c08ace235ff465000000000000000000000000000000000b0eca06f9fb69ebb46d0af56d3d934b333514d7f31208b4ee2fb92009e6041749028a78246a0adc324034a94503e80d0000000000000000000000000000000019eb24ed35f6c7ae53047814cab14d51ae6cf336d140a17e794d5cf18450b7fac3e6f990e12d340291459197bd353861000000000000000000000000000000001983a596485e657deaedf01614dcd5f4ec515c0050e8068ea02c9833d0b165c0f467107a50da0d8cd43bfcb59db6e710eac8e5cf13de6db37982390c8b6b0474795f479584960748b7ffed881285e2df0000000000000000000000000000000002f1c29ffdf7bf20fb8a13363393d5f1cca5dd9af82888f0102030fdda641abd5532ffaa2669c0c4159a989cef1c5bdb000000000000000000000000000000000bd548079899d49cd368bf5c246aa168fc8c777bb84a7930258502c8424a4b68e1ab20dc9ef39c307e52bcafadb0c8e100000000000000000000000000000000070c18918f037d5fa1aa005e2c80ce6a80b4b24d33ce72a2bd824f9a061af1db236f04d6041314310b31b805b8a674800000000000000000000000000000000014422b173840da655aac6ea4b7a04313d5d0675bcd565258c73039f879176e51ec0c8a9deba9c78c33179a5ba54492012c134652c27da0a0272b0783551ae44db6bf592ff299b48c50c550367d470b5b000000000000000000000000000000000a1be8e39a47dbe0bd19b8108a5bdac582e1d11ef7fe28df1f12da52924e734e1d591e8e33ec20c6d5af5bc8c1161fca000000000000000000000000000000000eaa7a7cec93b8d5eb933103b52a35b3d58214feb8e2de0bba3a0e57e7993a9df0dcf8089142f57f8e0d1d303588ce9d000000000000000000000000000000000089fbfb389ba448eb77722994178ee3cfd15a27be4ed6f4d4ab6ea1a4c10d6ee8424beb17d08190fb18ab8498d4a4fb000000000000000000000000000000000ab02df2eb474735e28c45b915299230ce159816419fe9c99a7da397b7210590705262ee14c2a244f4922c35bcb119338dca9ff432bb483ad726bd20cf96b07ab6f07170a1449f0f1b50ddc6e1a0253800000000000000000000000000000000006508fbef44d36cdc6fb37b6324810ab2a1d94e39abdf09d530df34714168105e23a7d6f7fd9caf31f263b658f16b76000000000000000000000000000000000b5bb1802813f9f8a16991d41275ae6d18532e3dcd2eae091da7256aaddd501855e775b779959fcef2822685725cd43b00000000000000000000000000000000052146ee63ae277911fe491420651a96994a30c7d1b19bab32eded008a125369baed2ec5a963bfd863a83c29bc1afb23000000000000000000000000000000000a180d79335347a8be350a92491760c6bf1fd56604d4d99a1c49bcbe50b2d04b7cdde55b4aea8ddda4bfeb8e79ab6ce4146433a0738ab1b044e059f49a8af8d85546d0e34eaa0edf2b2a6ee466c0def80000000000000000000000000000000015dcdc17a9afbf88b54af22ed2168329bc43ba50d374c0507c790f37f9669d0af167328d50d322a827d45f39724d2b2600000000000000000000000000000000169b83f2567e921a4319fc03b2a7eeefd2aed79914bf608d9e0a54aa71b9cb3e09f1cbfbadaa520c0f77f547fd407ea50000000000000000000000000000000009b7a8ff8388c85a0fe3860f26b09b81b5dc51e00a8961fdba96eb462e1334e9e28a2cdc4be49dd8b96c548c64921718000000000000000000000000000000000243782436fe7cb20a3242a3a21402a43a2c4fcbe77cc7182ee3cc04f4795c269d8a64ddd25e89ba4fc796747b608092de0399ce1ed861c0ebce1d4e811ea0a3d87e21a54ae34e6b5e1284cbb94973680000000000000000000000000000000013ce6856b6df48e4c9e3fc0be0aca5b139e1b874de6ddc148c1c23a846d61e7a531cc889bab99706668a3b69d32b9160000000000000000000000000000000000a459676071c7f3065a6dd7632edd5842db34aeda8fa0e7d7a8ea29f842ebcf2c5fdfa74ee7685caa51481c4f46952240000000000000000000000000000000010c1d9ebf7bed9195cf0bfefad6ba45f1bd19a9a7d340b7c630b9953923efe4907bd75a3da066fe3d49d656f3ed91d2800000000000000000000000000000000039189de73332d5b5a160c296a195cb9d8a736cca23a92948d513da7e4fc46e1ed9c207e86751b3cf1310d8a7284877ec2b034594fa53a0951e2116db1b063345fa42dc8c870e1146f1b00f626dbcfdf00000000000000000000000000000000129821e97c65ad3801c011792f4c099e19919d7d03bf9fcba30b3735586bb7ead7d4f9bd10bc5f0e5cf1dae82d5651ef00000000000000000000000000000000038cfbe45bbdc494988a2dc72dea6a7e36652f5e5a2ecad41b4aeceec05dc4a389e54cd3aab349adbe32e65206eb481b000000000000000000000000000000000bbab53f2be2c471d6e9cbad719a73c00b582d0983e25e1969c0be1faa56b1dfa5b7b55797b3340cf8c7eabc560fac71000000000000000000000000000000000b0db19410e552a2f7889c2204a93c5cfc71c360329e3be3171e88fc7aa1e993a5d089c28b1a8f8fc80d93ba194c63ccc1e6d9c5f8911014f0f540211af5184d96fdfd47c03bf2d7bbbb3bf1a330017b0000000000000000000000000000000019320bb8d29b7b5a7130b87a39e87e271b96656b5a2749f13208520634009c26f9829401d3e21cee5a757782c6bbf9ca0000000000000000000000000000000009b37068d72463e72f3a89b9093c1b09f01770e647b5ff7daa50e0679bb76404cf7729d5575a39f5b9b3b371893967df0000000000000000000000000000000019ff29e41db50c736e12f62d76a28f4ca4f6b0f4f61aee00cc0e9dd4e5a75c0ca965b82698f704c604bb309aa5b457f100000000000000000000000000000000062c352a554dc4bb96b459378c21ec6446e15b868221b2fb745d31dece854bc281bc22827d84ea3b0fecfe5d156712ce6df5a133d3332e1f79f41201f8cb2c8c8d4d1ab0f640c4de6bd6e34884a77aa200000000000000000000000000000000021c52e82b0012537b57fd92fc276e8de842a59355cc15d69a52effcfaa7cc43dbda0c34e1b9af44c2db8e9356b9c71e000000000000000000000000000000000371a6da5dd39092b6108f631a0f4c4401464a109ea1e5d14e262c8a9577e1421d41734d2c3ed73645cc13ef3988e9e90000000000000000000000000000000004054159263ee60f6b1882ad7c376c738c7ed87e6b34dfb4be2fd7aa29ede414c2c6c3ff098c53f22a1c1cd836a6b0600000000000000000000000000000000012d7af6b57c688e1ce90e9f2796b0e525e775fcb6be65f5d2fbe3d1ce1e5d948dcb098c98d495a6e3dd813527b4635258e7219a9d431c597fe9700d43da8b545072f5a27a9f1af99053ac0494087dca1000000000000000000000000000000000e53128fa5392dbae9e40ab1ff0149d5b577d9d30dcb85eb5e4fcdc17c7daf2ff1d6fafd4a1aba88d2e7aeb45a01afc60000000000000000000000000000000012972781f214511e9b78d276767b1b64bfe5b43215c7680c0063b6974f703b209b2929470dbae16f9767a7cba5311fec000000000000000000000000000000000cf6b37c5a60851d03752f68eaeaf37ac67c661f644cf507c5458cb5404d0ce903c92ef66a657b25ce07e5cf5d956929000000000000000000000000000000001835f202705c8b984a4c7a6cd219c718ab27a96671574cf7cb618235d19e9046a15212e0da6233f15f18bbe192df29c38efb8a7a5e48d5f4a011a4aa0dbab22ede62c903414d005d507ea3d77bd47a6c000000000000000000000000000000000d01c6e8e34e646911391b012680f0dd8f4b8d77c10192ac09ce57b6524f0eb8c7f83ff8f26d856e0945d7a909eb790000000000000000000000000000000000070fca42e34dacce0051f9e26c7c0dc328fe652110976df6df77af04202831dd095715af1714b60a99f2177e86a3443d000000000000000000000000000000000063ba43df0155373df59b009a8083b9f62004327b16ad455037487c5b8325e7eaf57a4d05c533e284004be6de79ad1e000000000000000000000000000000000870c2e5a7d26ba54bf0d45ddf0a4c3011152dd12a5e01a80e42bc4dcc784c7ffdb66f9d6d69ac445c1d9aa29586245147f53e2c06664e1daffd7d9b114e12d4190d5d0fa2244d61a13da915c39b8d53000000000000000000000000000000000d84ca02ffb6d3cf6eb27a143ece73d5bf006ff61569f0eab00c5a512c5b46e1fc21e8031d1a578010c9582d75e1faa8000000000000000000000000000000000a41249cf01ecd23d06f6a3bb8573186fe47e5165ec0d447df62bfc236f4c203b4feb8e2a4785648af86646cfb0c4e32000000000000000000000000000000000244fa6caa86fd27e044145557697ea89baf718746711c8dde334a2c5ae3c73d7a0e04fed6289ddfaf26e47a9d26b09e0000000000000000000000000000000017db897060c0a8e3e5d8eca9970407b46dc2c2ca0c004d50a171450852f585268bfa8a379acd01b6d4685e04c0b8c106fb109d9a0a7b62c7c452bdf0a2853c4bf65e5439fdc83aedec8c0bf73a16b55800000000000000000000000000000000071e13963e20eb1dfb671aa4a090973e4a4b7ad3578f8630db8a865847be46c796e6f9e095a9ce558b93d702f8f8572a000000000000000000000000000000000dfc4c89ceaad07e3b4c35d96e8534122ae48421cd4443de478ddf9a8867ffdab279ad745e55c87b731afa7700bbdb110000000000000000000000000000000015dd6b0c26f6821177d0cfebb7f1481a971e7601fb24ea365a0c3127a5b1042eab69446de05b61cb6ac0576752f87aa900000000000000000000000000000000156326c52bc78c82f5cb4aec5de35e3c128c5561dc80da2cb24d68a7e912b1f2dac2078508fdd4ec38769102c082f0f74b0a931b894fbe61115fcf52be51d44afdcb96c94117c75adffcd8729b0a699a",
+ "Expected": "000000000000000000000000000000000b537dc10a6f518122665f7d78326a4728a2889325e5be7da7e25e4752c680fd786cdaadfcc426343a9844efbbce8f2300000000000000000000000000000000085ba3a04aa8cea82b95dd994f5b3bdf0dcf63f13909aca2c2d61e4275a7ea22445c953b927ebc6b0987e98b553469d40000000000000000000000000000000019cec2e9fab640cc88073bd39e46cd571324904b1950fa8f626e2725936d80daacce2487f46ad23fa8af9c6ca0367fdb0000000000000000000000000000000007039a0e11cbb8bd940eaf4a192bb94ff8c6d6c79f775fa67821b5ba411641c09dfe9fac4cf45eb5fae52d2fc4beb6bf",
+ "Name": "matter_g2_multiexp_9",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f73a297cd6444809aa11b0756167e71986ab31b52b57d3c0aac5637129b8702ff21ec649541e79644c27f0017c8ae3f0000000000000000000000000000000016f96d6ba02aab604dd918cc799cee61cda4c0164ed9f07d4932fc4ac3eeb92b1e6b40dd7b18cd8d26056b486e57ed290000000000000000000000000000000012156f3ca3aa1e79014dfd92fbb6c785cf0ee449a8920b89ad04355e0fb7c8ea804bbad082b4edc9abd3b24ab0df2b61000000000000000000000000000000000d51b5f62a6e70816d7671bcfc52f11bdac6221a23287286af78605b99ae8bd0c722e485bd0381b958a85f61e05de68368ce22e379ddb8352d12eb597c179c7089c6388542909876c69ee377b14054e7000000000000000000000000000000000acc52d0fca02c3228cd2e5202c4eda297b8227bf4e64308226bc487e5b64738efa4c07a3738397f90251ea9a1a9da29000000000000000000000000000000000b85b853826a28777a5767d5b1966ce12fa8999ceff5d6deab5c947fd19d19de9c103bb920bad615186d132ec22187320000000000000000000000000000000006b5a83827dc7b3580579ab7976a70ee160b712580919b6f5d4e180165e50f5a1698fa7cc63846eb1f5e6df955c3eefe0000000000000000000000000000000006c2957d8adc55931900145388583e5c2d5f6bd784e022702801c38534d2c92c6df9f95d022aa6d800e1e458eb7f313061529338195b665f1b80c4b95b7c3a26a7229884be1f4be9d49e1274a9ec3f810000000000000000000000000000000014e4c5991f9f2ee262019c1344a0843756157dc85aecb15718217a2fbe23fe0843992dcd3953ebe79acd85517acece0e00000000000000000000000000000000076a18fe710aca2875bc102f21782c9649f107684a4edcb0c4538f1a2890a2ae5b46a182d5470e620375327965b6d37700000000000000000000000000000000142a0fb19b28a034d326121458628356561e50cd3a471ee78bade0733597b8b90f647f5199d4b5b1ee6be4e1870bcd310000000000000000000000000000000018f8b5933848813cc2c1a0f079b095d565e7875ba6693eaa10967d496fb47257c9c674f301349dd8f2d22f8857f9d5ca44d740a72e6c8b5632314408022093618321c8c0a8cf2fcd9ebacbe43505a01c000000000000000000000000000000000db331d2b965dbc053b01a61e671d2ee6b04b072b6494e482f48f12221f23e3b1ccebf48046d92b4be2e4283c77f51380000000000000000000000000000000016704f3e1ce14f49df400592ce29627833ed1dbb91ae5f00779eef94fe9ab313c3e7c8da940085034e1a49158043599d000000000000000000000000000000001956d492f5764c6de0b8e9a716766c762620ebd3265a95b47a8ad2c0614c337692108800e22abbe321d77a6cc17f4b880000000000000000000000000000000017149865739d6aed0f2a4c3c71c2d02f8080d9339025b03f89a37a165fe6e5a4cbd489b5fc90bb2cc432e5baab213c8424872a78e340ccb077259aae65d6c448fe6bfb64daf4e2b6ecce2cc9525e35a700000000000000000000000000000000036804da102cce975f980ed5a69e0464241b5de87238f9892c77fc2b6e5ceb00d7a37a45b5520fce5f094f8b9510f49b00000000000000000000000000000000049da8b6c974f2d680a80d2007333f15702f1517d3dc11395662ca1db945c795bf64167840c4df0fda68a69e127b2d590000000000000000000000000000000000e94cc66f1ffb2112e37cbd5b4feb7d65032c2e57260504a42816aeac85648558f6997ef12028655103a8cb9de1297d000000000000000000000000000000000abf7703ddf6995d5c29124ba9a3f890854fe0622d547a4f24d6a60b036ec9e58f7ec2deca5a71e1fce2210cf810e2f901a1d84826bf78f493417a06a800d58dba688800026638316fcf9ae534436fc00000000000000000000000000000000008d22e456c643ce680f5ea14553a9c249a43d4f92d94135dfec85bc58967ec01135507bd8ac3954b5876c5bebcc1179800000000000000000000000000000000022029d4abec7fc9ab3bfddf2f462660bef7449c4093144d9b7d6f9e84f4f1c947855ca6e09bbb3bee4db096978ae0dd0000000000000000000000000000000014beddf6a3fbcd621e2a592e1c87952ed277163ebf390896f7c668944d6e0a026d3df74b0fc877ed560527a80b981d1e000000000000000000000000000000001414af918645ce0d4d1f670333fedf286b01213408019e327d3cb9321f06fae311b598c2f78bb578e85692e6cb787a52c5a3268a8ab5a12214b266aaa4eb562aa05dd19575a7f3ba2d549a25f1900cb800000000000000000000000000000000129f1e25d96b8c879710a81b727b31d27ce9887c245bf908a3768f3606870ca6bfa70dbf5135819d36582d55f230e94c000000000000000000000000000000000e91eaa33e7cacce4e1d6d0fe905c72221b534a72cd51e1de79a25ef0c06ab454a849a241c023b0f82aa07de28e35869000000000000000000000000000000001379e390f2f0f3636312465469b532d876529d58dda8b024b6b81d242af47b5720af4360d5a3172ad80fd9fd8a14ba2d000000000000000000000000000000000775992d5a8ae0640af845fae03dd0b2197699f413f90f6130d21db0dab042324094b36acda26ed86c65821d2d8a29d9e62a7b00d2be967df04ef56121c95c8736efa95e1faa0196e1f4485da82b3c3c000000000000000000000000000000000f5420156358ddbabf31fcc94678866f899e38747e79dba8ae280704c4b199a03eb423ceed18b5cba7e7ce84583c84a0000000000000000000000000000000001127669ef3ba3785a859aa4e942e8fc3181f2703b0ece6ddbee8830d7ffbfe498794f1ca2e67c3ad39ebd33e838dbc5300000000000000000000000000000000138113386846310db8e21fb8bfe40035cd89e51736b491d5f2d3cf5672e6836c25f62eab80f25ab49d16dbb83796aa5d000000000000000000000000000000001711d74ef4995b473239a574fb8ea6edc6eb7a88793a093df4652da240d069c5bf9249b58e9b1e11f7d6619cdc28a5787a883bf845d1ed04e0664d814cf0b49cf8c3e8b8594ae5d2834c753851ed7803000000000000000000000000000000000d32ccc6598af8156f1c5b35e69e7c7f57f9fe18748510605a2a81b4ee09882bf3fb26abf50206cd57c77924ebeda8010000000000000000000000000000000009043d364e0637c60223f9a5db8c50e983746fdf4c9f7986d27f5f4f3a6df487592ea42078f14efcb3eb1b7e81d058eb000000000000000000000000000000000233495c4961e71cffc2abcde4007c0d587687aea905f3ac5758d0f8d9020197adb6f9d7b86a542b8efffb05dce997130000000000000000000000000000000015b084e773e66ab1459825b6e6dba055a96e4dc1d94ac0b640e906e0a9f12d2124a58537c458e6e1b571311b93acc26c0f474e8f4051c4e91124c14895fe9e2516b315d805b79013caf830524fce8880000000000000000000000000000000000e4b859c679a90c03ea4d4b0b3d38211f685db053aede0f7f359f712e1ae808185758546877502d57200da2c2137f37100000000000000000000000000000000173b24ca19436b51aae22838674c41c752536eada3197de6efc98303eceb3e6e8e47ee6679e61e3cb5c8c734c96c98720000000000000000000000000000000005232b8c97a4860a23999d6ed6d173d300ed50b77c7b3ceb4e8407d9d6877a6004e2f76c553bf458b7cfd8d1e6fd364e0000000000000000000000000000000018a115201e3f4eb308c16656b3ca0635e6284169cee3f28101903ce1cab0659c3d83a449918df6e58e8af2e001036b8d9b3a5790750825ab75ab7422f833c671b95c6c58619189db66a6215ce907381c000000000000000000000000000000000131232788aa3038a6b8a055a896af4f8129e3dd3397dfd90ce86b3e09a775e5b5e19f4387f4c02200a36bc2a1e09d98000000000000000000000000000000000eb8cc0455cbaae97dfd05c1246d3d5ee58c286d263184ae342f5c0ef432355a574bb9fb8ec67634f999b6d1419f2b6900000000000000000000000000000000188b8a85a6b255408f074b3cab66b95e0e1a1b5b8965034246dcc196f2bb84aca3a78907409826370bd65cd4c4d0bcf30000000000000000000000000000000009603984f6d9876e9c235621fa817efe45727fd8c4f76abb7b0796ae721701161b39ff7cab4c57850014e7f1750954ab6607a48ba3fa5c033a1ef90260ada14ee50c95e5167bf801ddbd3acb77c3b3880000000000000000000000000000000009003b42c08b5c7d3ee9f6abb96e08e6f537da25cd0cf7eb85a49067746c03566e133b54153380286ef5725db5b41058000000000000000000000000000000000f09b7b754c255e0e3b8435ade64d6960285759495659dfdb9b117806397baf8d3c87e30bee02c9e1b22fa3efcc58f300000000000000000000000000000000003582c08a8de4bbd20ebfa833517a75682618fba2702b6c71a4785f70dbdede4e86ad8e04aae1f50a6bb75842ab74aea000000000000000000000000000000000ec013f22e64a4d4fb6f964e8319feb1ddbcfb71329186545d9b9d7f97d1f6a56c8aad03d20e9c30966ca932e1f2bc67030db724eadd2f487d31dd4354b5c0321a7983aead21759807bd893217c4d40500000000000000000000000000000000025809fb06c8a31f31ca5b4a5c795bc93355c78d9a2a4c1d707e32ff2a71d94cc1bf7b709cd5d6a183cb05fb6b5f360c00000000000000000000000000000000127bd8c9ee6388905ffe59bb0fec0e42b4aa44be74e5961dc2353e474baabfea86c41c6173db413ee28681a6bfd3ccbc00000000000000000000000000000000181f40dd8581b9adb2981dbcae27c7e906138569ff41a833ed3e6ee4fb0baccf2ccbe5b28ae2ff8e08c4f534116b58c40000000000000000000000000000000005cdd822cb47f35f31e0cbc26f6c957d51c6880369af94fd84daa1f1ca95e41e240b910f031585842fd2dfb170d618aa88e71d0be8fd050f6dbb8b2fb3ae2a9e593bef7a5163255aabeb07282e8793e30000000000000000000000000000000004a06984a3916820368076ab8cad6ffffded2cf1e67ac33f539ea8fc7a79580c1969e55b2a2fe3b31de912d6606c20780000000000000000000000000000000008a1152a581b6fad2a23aa8b0b51cbe523e701193207c896d08b99a672dc047498e565a568b79f8f9188767ba95212be0000000000000000000000000000000003539e82e5b88ef660b6593fdfd9591ec23e7109642f4aea0570f1f8f8e00822d2af277632ba74910459535b35ad47120000000000000000000000000000000015d3441f621c7e6922c489e474f80ebeefbef66cc59e4350b6f803e409034b7f498be2dedc97d902590fc1e296fe983c26989184bb87a586b8752733f9ce9ea06422c6a898f0f402cbcf760a7a21c95c000000000000000000000000000000000f775e13276c2e32dfde955009422557f332fb42dd9ccc3246d2b080e3ec44d910aa734478899698a9b04f6fb1a8f922000000000000000000000000000000000460ee4df6dd0184bcdae6d53cb66967c2213fa878a829c3196664f8d594ca6d60bb2a56f93bda3b0d2e6aac0a1a222d000000000000000000000000000000000fc9bf81d4cc80ba4e4df7307f976c2ec1ea2415df3c263cc970583824cd83703aa994daaa6e5c20450da2ba90a242830000000000000000000000000000000011f08ecbda9a192b232e8330ccbccb16a26bcf4791707f2cf52c2e11a8b3993221666563a772d82f4665804275b03b613d1dd9cc44b30a4623a4d14861688cb678bbb8b2f8ae3ba140f60e64c05514b100000000000000000000000000000000027fe7ca0fdf1cab9a52e304e55350195492abecce4289b0f1c02235412bb012803e7eb59e23c665ea86dd4f74c35c440000000000000000000000000000000011301ecfc78ada92885bcba8af75da6cbcb448e0c49511f3ea306f4ab944f5bc114e72f473cdadee2d0e84021905c5300000000000000000000000000000000010eea529fd3162ad7b49638a70f6f2c26a6844251b2c2f9f8ba54cd334914e84e5a1ba9c7b4e7a8b9cff1a909db78bc8000000000000000000000000000000000b8a6235a7310d52fc8050bcc484e6ecf299099e193f91bea9db31fae71fbd14978984a9e6de10939d0fbba96314b0a55639d80f55e24e05e3d943340e324f6738a593a915a6bddb40f01bf12f73daef",
+ "Expected": "000000000000000000000000000000000de312093622aabdc7523cd72f568060f4236c7287d61c3372bf81d9bfebfda2795c3182d508f0268d8f445f6ea0a5f3000000000000000000000000000000000b027f117583406916a8f139d47227bbea28502ed0df91cf0841345435376c944a587c3b4bd60f8ae0be7c7bad1c8199000000000000000000000000000000000e9a7b96136b26b0044b11288d35969c17146241aa529e581a8fcf000c33fcfff2dfe1e55c0fb63f6032d0b6b0cf81180000000000000000000000000000000002a442e740ee390d87ec657fc218b76adad7f6a766cbe8f34f4824ecd1587deb3706af77a95c1d5f8e79eab1dc482c45",
+ "Name": "matter_g2_multiexp_10",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f54bcf1637d03854cc2b785e52bde25de7e45308048ed8ec0169069c2124871782bd9d26471014d039c9aa022e1a99d00000000000000000000000000000000106698139b096a5a79d43321ea64adb783011f04e5779625c9f77e5c390b46ef0d249387e978e64529bba2db8d7aef2f000000000000000000000000000000001668d5261a4ba37d79c76f44eae9ce2aa3e216c5fbf6cd2e90c6a73cebd8b59600303afce70de3e83a08c20de4609b100000000000000000000000000000000004b1b122cb55e688f8297913b84d466c6f3d99c09f4b039660238c8bcd0b7f6977851a6ea4b1deb01346db06d75180c142fe1e5b3c0245e5cfaa1ee8dd8ccc4ea8878ce2272d152fd8b24032297ac01800000000000000000000000000000000192a28dbc40d5ceee4d33b5c2778cacf8c3ed7d3227e7ea0d6fbaa7cd4a81134b63415f4f1960656b1fed15023ce3a4400000000000000000000000000000000138f296c45594a930b949756d0ae14dc9a720bb2bd9e93c7895268121a086a9d55c10135962a172c02da1eabfcb8caa20000000000000000000000000000000001605ef8182fa13a09a6b7661472296af2b0fdcfd7b051e7cf1d9e6d7c7f4ad9521d7732733399bfd5d09a088f25d215000000000000000000000000000000001928f2e5d47d7273e035114cbdeabaca724409a56056b4e95a4ca3b2222716b3a5368da3ed406d73f43e9571d1e04902253bdc5565b6ebc219a75ab74dc5ffd304c94e67160389f87111899ac07a71b70000000000000000000000000000000009b35f132a903579d82cae6a321c1ec7fb0281c3e82e9af05c3b2830ecb4a941da5b1637c1bf0fe9a39fcc9ceb0d09d8000000000000000000000000000000000eef9c0846064c866ae07b3709091b8bd48bb6b20f995b44fb49e030b5cb6d78b7f8201704b53697190a5e36e9a4541c000000000000000000000000000000000a98a5d0d5640d6399a3580036f0e5cd693a7cfaa26438a00767d5ffc0777b83c516316d9cd4597cf8601544038f4d9a000000000000000000000000000000000e59541068a62f105a0d26a5f79fa5fa8b41b2211f1fe674d84dd853663962d64a7f70e785b51ac3cc07267c73400fe6acbf64f93f6f85805517ddf0358ecfea1fd58a3666b8dd9d3773a28590fb8a13000000000000000000000000000000000157f58b1c7152a7f931bccd9a79073967ec28855a6d74fb8727f59c5e3728fbf07a5032dccb28eb8d8b24229f2dc1880000000000000000000000000000000019f41bbbb853edc1fe3ee82f901e613107dd4ba1d880284ee95a2c4cfb2220ec1408f8bff14defe59775136bc75b4a1f0000000000000000000000000000000015538789157505a0798aa36fdd171e0bb14bdac75339b35805807c18bf9175d877360748f97a8570754af0e28e89df660000000000000000000000000000000010500aaa99216aa979acd66c5b0cea2a6a973f1cd10c412e823c61cb897bce54d783a6c0acee22cf9052166a4bb5adb8d9d3f97893eb4f14f21f68110f612a444815fbf2f76b8399ba6045c8a44270df000000000000000000000000000000000439729e13e6a9b5baafdaac65783ce79a5972791610a333224e61104d15c746d7cf8350e619f0f72cb73635f6795c5f00000000000000000000000000000000092e3c976a4a5424b09e50e6513a9e1f427356ce161e742be31f0e589e9ff862460d41281f0bb2d27b1837a70a5938fc000000000000000000000000000000000e0e51e92ac3cabfd999cd72b67cfc488e150b11b18f9a31b1c2338fd4f2c58937521b5a107752c342e67666b99fc42500000000000000000000000000000000023d8884aa3f556e98e006960293230ac966ad18f3f715e6ab31a6bf0872c04e6f115fb1608cd87ffb369ff31012a11705fb554531f53b8cef8d93566df80878baa96f92bb54aec19445980b1a1f6c34000000000000000000000000000000000be33bc145611afdbadc636e9d7cb7e3a9c92c32f6944a2b7b5f44c248a0754c174e3286ad307fcdb2ea02a3578aa588000000000000000000000000000000000457de1fa8642d302065319b1d32009c64e7d941fb43d1b3cf455248664b1db516379df87aee05a651c132eab8aaccb5000000000000000000000000000000000a711f3bf1bda60ca49271e8a3143330cf924328d3ac6f7a802c15be1d7413e300f398274f338e6bfd0225cd8ba25fff000000000000000000000000000000000a786c5c7b4f1701e292aaad9b2e47bb883409aae0c44ae813ba48f401f4e2146ea0b1d85f2ce862b6ac9ad3015d4b14d79ba2c485f0aa0e35212fd7fecf970258903bd2427c4c8b97c2c425ee1190990000000000000000000000000000000007d03697e195a6b714fc9785b49e54e219694250cf5fe77553434eeced15422de3985f8c736996c1763d4b9248a7a7e00000000000000000000000000000000015841a70a168d2f356a8ad929e2d1433b782351f4833c51b50f3a1af48a85468c2ec02699550d21bd919203df73abeeb00000000000000000000000000000000170902520080c46faae2bf35de396d56921bd0279fc889f0187adbabb9ae52b849269d8097d5b3f331dd5a817f9b2ff40000000000000000000000000000000016846a000f037eaf5953b7c4b477e441ca4fa738895aa24dfb0ef01a4c8fc21a318d40a9424e151380084578ca413b3344c7017258bb979cc9bb8acbd3a3e62eac7aa152db46cd7398ef07edd031e4f60000000000000000000000000000000001a50509bfb12040c0271b231c566d13510e6ba84448e59685f5bfbf5b008fdc64cd5e9456beabd23ac011b071e3a5fc0000000000000000000000000000000014a964c9faf1752170ca40cff1b9b4fa17f8d2b56a4c4bd7ffabb65798771cd624ba61ee43160e70731fb9b07af8ecc2000000000000000000000000000000001822ceaae7bd0a734f57b67e4834cfb00a6b415459d81c7d380a2e5b5c795eb1b6d63ddffb1131cdfdf0d76852c75a70000000000000000000000000000000000c5a1575b30e5470151ba055f577a0ea49cff869614c50194829e53a3e1a95847fa387a0f45d537cabef3a5925e61c432583e821328ae90a7db16b20525228e8d915bc8d46a642cb0a06dfb64168cf1c0000000000000000000000000000000018cab86a0d70fa30b4df3e05a91eef57f6505cbe4bb7284de56d420ef3bf315be9249eedfae92561c643bac2c92301ee00000000000000000000000000000000098ca598ccdffa9bc9d464d51b46ed8a8f22a87ef408cfa45fa7f78ae2dcb9f861d9d6a571f6fa702a71e783ee3395cb000000000000000000000000000000000c073c0a323c3051c302c0558463a5c030539d74b440fdcb16b42ad5ec097e10c16bd9a651d149dd719fb1fb865420a9000000000000000000000000000000000164e622bfb8ecd5eaf691abad9db38ccc64ff0fa1784d26db8c8fbebc929bc6d4dd471321e01233d55fb4a9661780b5506f22d323a740553d6107e651c192c1dc6e0a0161a82351f125f08c77e53fdb000000000000000000000000000000000fa48147388181e8d0033004118848c50c6425f2e5f91945a17abcff4d11928d298c092d60184e75e67c7ddb9eaa8255000000000000000000000000000000000c535bc54df050c1ba8d858a346d3a644e03fe24873b7dc3e23518d44b06fcb3f52b4be6f11d3b66f0180a0a95dddf680000000000000000000000000000000015e279a2893c205dadc8e1cdebd9c85454cd4b5d7537f984c8f9d451f8316620279357e218fef87339f1728fa317fad5000000000000000000000000000000000316e343ba68c8a762f4c8f2a5c20f16abc4a7a8365556c1625df832219670619b6dc70727e9bd9a64ed491dc22cb9d57f1bc0e1ebff8f935330c35573f9fc3b900606da9cca9a36b425977af47c7ca60000000000000000000000000000000011dc72100cdf676e41f21015fa7c57897da8260609467ffd38c17868a4dcd2bd5d4d72e89cd0db2de83618222ea3b5cd0000000000000000000000000000000007e074f73287faf304f618478566b91c8e191b229ab40743081342e676be09c2523681cf7ca6f7a396f8589a4ae18a6d000000000000000000000000000000000ff753a16c16bf0dd1de9fa9316694214aea6f99b81f66b6bffd58837c00d7f5632ed5f8f4cdf32ec59c29241ed5e28b000000000000000000000000000000000851e26675814612bcfa639fe567633e1960578a0c8d2e6568418f633eebc109e6c8af97e77bb28ddd47c6bba8a7ba724429b85fae16200da6eb8f62e95e027c24aa6ee2a145f6ef225139f29aaca29c0000000000000000000000000000000009eb2f172db0fe9ac0332381d929fa200a97047f6e732570d23fe27f5ea3013fdc52fd0b5ee74a4387af44647b75f956000000000000000000000000000000001355f8e1cf45443855f2d62dba0fe45b2bfc4e0d06aa7aec7e4f7f9c4e25b33d9c46a01c224517bac9a1390a9806ed4f00000000000000000000000000000000179d47a62a5c847f47341b1ba58f2c3b073c5282f925f57efed1fc43db04185955075255e4e4f6c209757ddae59101dd000000000000000000000000000000000ef5f74d4b13754ceb3b468879f1a8befb8bbbdbb143eceabf2dc8e68fe6cc8e1ea4f3eca1b23a1175c9f5f5c4c20d3454a852baf21df9f4ec8d711a48e6ffb36be8c09c8c60eaa090876236b2eae37a0000000000000000000000000000000005b70a4d5b91b85971aef26b1521e12904b7ad224f25e31ec6ef59856cc702043a3eb975bf21dc8e4fc55171a3865bbd0000000000000000000000000000000007cf7c3e75a837545b53ca3e175a275dc6fe42fb88678aad45910d150ea9c6c94eba615429540348bb2ba8efacbb20e60000000000000000000000000000000002eacb469f5f8ee6c9f557a6ddcc854e955c5b9203b4ca5dd2e097d3e021479e13629863eb5ff17db46a17d3b0227f58000000000000000000000000000000000905e66f3a051b304b110a8682169fa749ba0de7763d3af7edc3e40f2d22ce7b6aa00cd06d2c82d74f3a9709d955f44e13814a3c6386b19f7b93c2c4e0eb1568e8bd3f0012a1ae1357b127c33808aa0400000000000000000000000000000000060ac9ce51426d360eff0d911d9f97a86494340bc5c5ba31ef146b55ad3633ec57a700f04b0cb9d4e91e13c2cc5e68a8000000000000000000000000000000000df205ed85e27c25ce27270384d7c3e58c4e0a9f214d74cddfbc7904eb3115e7bf204375df7558c3e65f7a81a942c5160000000000000000000000000000000007a220d42ca8906013479442d7204457b3ff37c9ee70d64f9f6858ba788b7fc13b71d33ad527c6fc673ad8940b0f01cc000000000000000000000000000000000ad481ef549de13b174d82fe88fa57b7e31ecd8999bcdb0c7a8735ab619a13b1e684b9473f0c59c734567cc08c76ecd6aba0fb0440b2461ef64af6ec5f15db381714fce1da6e03ca962cfc94bba26d74000000000000000000000000000000000366f604228e2dff2348a462c56e0043037d1b415ffaf155e72c559d185c6b0a0d125585d060f159a8cdad959af631f5000000000000000000000000000000000f69e829a0995914ac122299d4424b4e2e120fa4913939d2f18f9d1496e7255d00ff0829c20521ef47bb0dee06c28dab000000000000000000000000000000000a3efb4a376281a60f5246d8fc10bc23cbb9cb71037f8f57271a9b01f5e0340a562f9acf0e9a95b8c65ab7a5cd95520a0000000000000000000000000000000004a4ec86e2b04bcb35c7840d85cd1dfaa88e17ffb557ac591640ed8e563cac891793b92e349a7903c6c1f88d26a01c88c01749cac36dbbdba5662687fd1ea5391ef9d0bbd24e05bb5904a20fa6a1e11e000000000000000000000000000000000f5bcc27c243ef65dfbfc0de6d431706ab20d6cf6408ca989a2bc1c52b78ab63de6f58b70bfcaf6878a2746f249b6b160000000000000000000000000000000016a4c9e8ad0634e8afa8606a1a7bd1d8cc0815dfc6906b6e6446e0ceddba4a4a2df979d27cd07b8982a12550bc700fce00000000000000000000000000000000051f8d972362caf0a8a39045bb468112f2e73afa392079f8a4dc4c3a3cbb8dc224c21b6633a5ffbad08796ba2f8df44b000000000000000000000000000000001825aeffda04705ded9c702ba30d24b9fe8eb7cb106ee5d4e4ba029dcb57bc42c74e74e92ef8360cf130590b838645429680fbd6e6c7b1b14b000d3d18bf93242c74662ef108d711d85d8d442e415ffd",
+ "Expected": "000000000000000000000000000000000d0ab61b29ddea1aee0ca4e81b5369f37cf45be383f64ba0b1a5a74b790d7264016ee671959444c94b8e6291c5158ea90000000000000000000000000000000000152bf3709c56b3add8e3396d17abcfebbcfeb230529ea8144d6a120a0a6aa83cb284e40ffb9fd9a96f8a2f7244212400000000000000000000000000000000041f516a7cb2a7137746d028b0739c79ffd8f7535f20ba3728ede32504fe058baaf684cc7677967aa46777818b1fb6630000000000000000000000000000000009f1035729c55cf6ee090983a54d8c0574bf96342901f471a2e5380f11f235a075b0e157c38c456b6eeeaa10b87d3afe",
+ "Name": "matter_g2_multiexp_11",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011ada4731ae7df493e405383603a8d79ef77f3fd14fe7b8bd9d2afe068998cb712e84927d5e6ea6e94d7f10270fd193b0000000000000000000000000000000008a14eddf88826dc3be792a0c1f7395efdf91454cec7e26c89f6beda37b194b706dbdde8745129e821b6f4b4ea6118490000000000000000000000000000000011c29513e8a826e6b3eefaa20ad841605d04b813cca282fe02dca0f588b9a579b2195b0b080cb6d12c1a7881008117f8000000000000000000000000000000000689c67d05ca379367fec99439e3806f827218ffaae995bf38dd8e2919fb2e751f426525cc2c6ead3b9aff2e377fc99e1ddff10527bb64de6ee2e3ab4959ebef9e7a6964b7482f9fae396b2b9b0cff9e000000000000000000000000000000000dd683a8e4ad54b1a95826a3000750c6e3cb250ab5d6add63c21b182d736b220d917d4e70044ec7101c3bf8ac620e1dd000000000000000000000000000000000f3e411cc6800b304fda1373ffa60c7718e20bf3e2e5f9784a81b47e398888b366e1f04f48f5aa070a661b5e2148d4fa000000000000000000000000000000000b0f8d0b695e000158ba80881a9256ed9dda5a7f53b550bf3b5c67ab160060fcbf5ce07fe38253ce037abedf4c6f08d1000000000000000000000000000000000bb92d407c457e9ea7b9851770d2743758e162dc9cdff2dd54b8271c046f642729cd2f10576013adac84a46d38623b932943fa2957d267019309f4fe5b6725379d893dcc270ff7f35b3811ad1d8d12b100000000000000000000000000000000023e880685aa69b3480bf2b7f2aed1181e094322da9e79c9263d50a49ba4fca713740bdb55886fc81c81a51045b35139000000000000000000000000000000001707049fb8b7ad278be2949b9eae2e28bde9de1d9eb964eae582541c2d7a8afc4c1489624a0919047a167028b8c77e3c00000000000000000000000000000000062dbb2bfce2f67c32b87ec2fa01ebf7deddfcbeda2fcf0ef094b1be77b7411f657e745350b6d2da16fc83a96f6f20e500000000000000000000000000000000062daeba038c7bc379f56ac371745b91fdfd5b4cbbe50d9619bf1d077f3cde966f81f9b851ebd206f2609a780b6dbd681551a3c2d0391fd8dedade892e8e2171e652d2a9b52f2288451c55f77fac788a000000000000000000000000000000000b553826dd9e2252c9da74c2bf1bf850df3f9c37439859f93df3fbceb7cca4fd949dcaa7fff31c9e06f41e51ae0b30bc00000000000000000000000000000000187810711ea5911a437a62e2ca483983bf2535ff9301a1cfe1b4d41902ef689f8d86f817a2a7c77128e4ce1ef6b037d60000000000000000000000000000000010170cf5f2ce08211cfc41bf54cfaa16584f833f7b97b2f6bc436eecc56ef44463690ea1f5c8c2a8f69d93a25206282b0000000000000000000000000000000001e627a68dbab6b0d05c85e49b966a769461ec38c38fd94992839bd0d46e06410fa7a48d418d65a8285f7852e8af4b318eb2fa94a5c97c28d95008dd1fe60137b34c2e763292d1b86993c02790b8c91f0000000000000000000000000000000011ebe2edc3de58a57aa9ab4d6626d7b93235ed24efc3d75c1ecae376c00beffc5e89ec509d243f693d327f7a4551921f00000000000000000000000000000000088ca2fe0651e4d8f3958454640a58ea1cdd804bfd2700bb1bb8e26ac50f2d7fc8c292f94b0bccef5735c4548025735400000000000000000000000000000000154936de8932279cd39ae803a5d814864953f647a5334bad958222de765250e4bc847e02979689dc9cfe1993486b5750000000000000000000000000000000000c7ce07c9746c6d72dae11e243acbe12dc23423f870f3130b244eef34524d547fe0b2c4b704ecb6b2e6c32f5675ce67ff72ae1def6c988f9242bff0e683b8d2a5c1aecfd6ebb9442131ec5b5b825d0f600000000000000000000000000000000031ea855125d75321a2a86a93e72fb3869dede7531dbcc1cb07ea2a352f3c6cd913275d0d43ccc370f4539f668f205f50000000000000000000000000000000006c4cadb11361f164f5899c6b57c0c6d8af365d902f4575c9d2d14dfd880501ce9ce218544b44bf07f0f04ed68e8f315000000000000000000000000000000000131332638026fd25b1a849c984f9dedd71e64fb52a61968666ba80238673077ac00b9e09817426ceac8c308f475303c000000000000000000000000000000000c7634af796e7aea4d4d83c9972fc822dad951d2473210ad82706ae0aa023ea85c1c467bdda68881094ad2a4f54cb33f331451748146f0564ab0d91b09db87e8a6ba8b14f8329bc041911616195f9fc0000000000000000000000000000000000fcdbf0083065e13deee2020bb6e47cb9e482df3768ce569f1f7c0e1c6083c97d9f08444e67857c2dce40e4a7b8d50cf00000000000000000000000000000000010f246e8ffccc2e752049f638617e122773a6f10220cdcc0603d24f1a94ca7c100f8ee2d9bc7c0a931fa0385eee456f000000000000000000000000000000000f8b68941df75cac3d4b6b3bee43fb357c8f4e56309d8509fdc62620a085d7ee58f52c7dff28525a449cabfd3b7ab3dc00000000000000000000000000000000019f934ef0c7c40786b073d38cb3e4623544cad59cb63440d4a6e76944d491f6b982e3a5e84124996634687d4618418316d298bf591bd927aee24a37c5ba508c3bc121f5150fcd1a70c1f27a79da7d73000000000000000000000000000000000c0208c1f3653fb3a5e2acbbb42f2598b22db1a714d616ee6bb501c3338e80db34d517c7086d43ddc77e0134dc5a4f290000000000000000000000000000000000a528245342e44e36f8e02e7259749e63ecfb38cb0609075e871701f2b3bb0765277b78d28cc3ecb7aa8c9e3b27eaf10000000000000000000000000000000010446583a905864064400f9ef168a122d179d46a058525c9be8a65a5d2ac5e967d51185d4964f81a5571123717210d050000000000000000000000000000000017da91a1d0358271b11a0aa524341ba1ee8c31bed15efc4c9183d60c6e1842ec4383070a09914fda991a63d55efa8f2156be810c3fa86e35bc935fc2b27971c9c41d03c8ab7b6c8869db90b6e0986ef400000000000000000000000000000000176c64efbfc9958b9c8e71b55e9fdf525d4e5a0265ff01ba95bcd5c6093bd063726f8e277d00b138fa4d8c8f80afc4e200000000000000000000000000000000183eaa6c3c605828852ab5e8a9432bcb87411dd18d574cc2491f1a280e7a267ff9ccc80b06c22e95107a72f22ba2fafc0000000000000000000000000000000013319d3a8564ffcd6fc7accdded740127ef205e8299b390d21e96b2609cbb463569c878f36191d43927868b06dcb912b0000000000000000000000000000000000fbde0ad8e89f5458007ef6ba0f01d0aba04217e06745a5571eedaf544443150f59117b56937f533b4974e5d57c41cbaea4445926775a6baffb4dbeb249dfe3b3e0c29f2a579927f540d8f6451553ef000000000000000000000000000000000c044a5116e175ca1d1ae59d400de24e4f47132251b4b3dccdf458623c36b4d3d83abc644a2247ac4d0e3f195d12e7b000000000000000000000000000000000048dff6bf65f158b19b992167ff8adb5c858a154bd68bf0c84e41351bf47a8f870cc735d1be5d9afc62bbcda2fcdb1c20000000000000000000000000000000008c5539746d2610eea22e79b3fe5b33a47fd3bf9991d34c6f9d824a46458480b735c0051d7b4e4909fdb1f2a1a4e4b3a000000000000000000000000000000001936558ac97acd903a29d07c4aea399227ea13fd6dea820813c5519412c157e1a477fcfbab60a787c6b3834eac4522889ee0e58d08779add74b68dd75e82df172b719cb5a772b0bbb34d3401b9f212ea0000000000000000000000000000000017d978d60fc89b0429c1a6424231fe9274cedad5d78d9c4ac5aa2dd5e70e8238a0bb1904bb4b6ee5de5cd1ac514c62a8000000000000000000000000000000000d4ce85a95dbc40f405f4e7ebf9121cdcd22766737c39618ad0fb3e10a6e53be1faceaa96073b2a877ab808483ec9b6f0000000000000000000000000000000016c61599ae4da787fa6db233fc28f5c56f7133d403901800ab5fa19d058fb27ecb34ca2e56ffa7628ed004c9e62092700000000000000000000000000000000001e64e4adfdafbb423b1b9f8973738c690713911f68f658d234e57dc35b9554e0f7ba345dd7920b429a12b9c74775222773d07cb9d20744a2c3ac88082a8d6606acdc892666753793a2b8bb81116cc6d000000000000000000000000000000000908ebe27a1bdf0b9e56325c00ea3814527005793ea97eafec541c01cf2d7c909d2521a5fd475589a31e297cecfd5e7000000000000000000000000000000000017e3c40c60cd369ce5a90f6c4aff14896cf73fe06432e71940bd8086e36c2353d6bf9dd414bcf92889887e2d49fbbf5000000000000000000000000000000000ded856e5b2b139487b3816351584f06582a933af2bd4573a89aab0a41af01ec1cb928a7d8035228302032d399bc7caa000000000000000000000000000000000833b77c5d5c98ad95a144c0f167fd3bd62b03f4ad721561ed1d84c7137dcb19521f781bdd3ddc22afdd52c75146e101f6bb1445e9146b117bd0c95b009fba670a5391874dd314cefc884bdb0a4eba680000000000000000000000000000000005c6f28c5ebd981fff3aacd70eb18f134bffdc8507d1a3aa153e5787b68fba7f4a94c43045d2676aaa992754783ae87800000000000000000000000000000000148ff39e8062bd488accfead42a684f781c4ee579af6204b5b8dabad9022b029139b1f3670fc270710ced9a53253850c000000000000000000000000000000000ff50eca1a92f123e2534b3289f37ffd5d4e05f7678017ac20e35c2deca054dbe376c5529cddb5e58973f5c60914f251000000000000000000000000000000000b58298ba9496fe32891f4c1cff25395ac5a447205cedaadda4dcb929260ee55781916ef5e4e39793fa2831142111226d4158de4e23d793ba77c24a70f0ad07314927fff34361b0d74b25e8922512d7a00000000000000000000000000000000184d156f881f7d10d2f196b7599db85ee826c9c95383978ed68918756f642a2ed1c951503251b0778dcc39598d79fc8a000000000000000000000000000000000952168761380e8fc90a4966e94b8d2b88a784f6e607c99d9af1aa902506f59d6879153339fdb7b8acda178b9bce4ef90000000000000000000000000000000009997621d4e17c76b7798ef2f99d3c0a7519cce278cf718789cd8227b2b1459af7fbbc93078aa0aa361167b1d1c9363600000000000000000000000000000000005369eb3a77d2e26f9907a2d930f39dbb87634346cf10525733aac8ea10eb918d4043d2a05ff8e80b9c69a670e17f15c629ef41d5a2ce49fd81930406f19e760a47074e159ce372dd67e7ea46ad706b0000000000000000000000000000000019bdb390c66f7d28cfaa91bcb34c5c55bf93a9f2345ea396f18ed33ff2221a39cf68c5514fe091f7882e82470efb1fee0000000000000000000000000000000002d0b48d2c0377b0dffca247b7625f9901f86e2161626b4154bc25d6c643a48e9addd260298bedaa80e42caa5b9fc5b10000000000000000000000000000000018a2b0a760652e546eeb42e857ca48f59741eed91822c17692e9c41358b213c82537c9c6898713a13a241cca627a7dc400000000000000000000000000000000079c02f41fca45a56d9d8e305141b4fe8f98d102197e7864065d342e6b07f65b62632e0c12660f37de4d698c0df3d0f3c718651715ab786b4855092ed21be41b499b7824d0bcf68ad31b31ee4cb730d5000000000000000000000000000000000c0448fd4ebe9b5615653336fe0a618fa281b0fd7d72a8f956a5fde84f7d356b6be853bf823436bc0b61a603636db9ef000000000000000000000000000000000dc4f2b4d810c4290e263098576cac393fce137cc901b3be23507cecbda7d86d18022cf8e1a7df4b1298520ae5c9314c000000000000000000000000000000000a39413967b558dd8a6b2bed972687d984fb9abd0662a266680f8c90f1897e2aca1ba37b41d7d3fd47406bc5fa3c5b7f0000000000000000000000000000000000550fcbe5bb75afdd8d5f387798a8e83a8dbb6da4918c24eb2e5d2d8acd3512f6649a4ac9c8d3e6794e6f4f8a87687bc685a2872c4980518fe60c61e2276ef53c007166f7eceb355b4cd533f42c00b7",
+ "Expected": "000000000000000000000000000000001654e242002aafa89c6fdb9e8fe2c197ad2f8aad11868568dd39d68ca35919f94308a80303655bc83fd130de6f9723a900000000000000000000000000000000062b5a064840a5a28b4991ae949f9508586447ad5e8c463593503c0e5857c5233b7ce7ac03e555c2675f2e320e8cee6a0000000000000000000000000000000017d65fbd7caa69629f66be8b201f53baee5ef2957a3c04fe384ae82959105342b52483eba6bcc1442763c677f515f6cf0000000000000000000000000000000002ef8f8ed1114cc9d299e59003c61d62edf8971d65b1b621779bd7b270c4123eb629f56dfa2e2723501588a0caf1847c",
+ "Name": "matter_g2_multiexp_12",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001392409b92282bccbdaa0268e1173e60911754eb3cdc28a52e93f4d82ec99026f314dfdc59b39a4f988100f9c30cbd1e0000000000000000000000000000000016b3c555d5c196551ba715c6c334a668bcae80f5a17f038038d35dce34843f79968a90e2102f0faa22a93d3240b58d490000000000000000000000000000000002daf83727fdf45dcc1a15adf47de3f8a1724cf4d34116f52106a9e6b22dc24a288e89b940cc57e5a6bb87ee70f680a5000000000000000000000000000000000446009fa3555e4a056a820efa7da52117c15eb105af57985d8e9b33b0b22fde6aef9bad30480c2b8c1246519795f61fc067ecd54e9ef59996493f846ecca63bbd7ec28da586f0b8d41bfdc6d97a35cb00000000000000000000000000000000000372ead514d53007690843484c966361661816e0d3949b868176d7a9bea42064f49113a74f2572a6dca7afa0642fa5000000000000000000000000000000001199d3ea66fad87074e62a0b77d3fb962db17dd948f30c38f5beb0e44e1cd11d9172b878128e9a64a08394f13cd786f60000000000000000000000000000000018b7db157bb326ee2f72d4df2b1e0ddf0a90401ccfca1d4ffd6379c62acf5d6e4176a23ded2f81653038d56d848b4fbb000000000000000000000000000000000a932cc9740812c8bde33b68d94220690e0f55618b7e51d3e3fc29d0cb9a8d42b8f8e1efbba5984c3c1007c9a80fae408b5112baca5e0f2bfb885c5041189612918d203a117d886bcb3b27df7e64d17d0000000000000000000000000000000015798d10386f6d24caed3859875be5fb1a43ac753f725f28da6b3583bd9c0e404d36265c2305d7d194e2ad84bfd2bafe000000000000000000000000000000000ef2ea5f3b6e03e3c9693d6db60019f2efa4ea586bdb7623f03bd035c603e8996ef2ea7cf745aa31f60679ca04f93875000000000000000000000000000000001792a66785a3087a80c4b8652c1e4db8f602cf75c1a6955f480a977f92ea262965dad84061f6045177c831dc4a3bf8400000000000000000000000000000000006ea3862318974d6347639ec0d70afe748f4edf32b9e437fd98f38eaf72168a153cac180c2d67bac8a358e3a4d57a2b32db7ad39ec8129e9e9206bd46cec6a8ad3362ade1beaa97befe148f6c67a9c2b00000000000000000000000000000000000974da7500df70d888d5876e7c61bfffcdf830b49bdd40edf65a2ff476e9add35eaf9451a2166e9781805192ffd7ac000000000000000000000000000000000cb2e7152b5b40758b18caea356dd8e095f400282881207c4b79d10d741756e526be261b98b726d5cefb668dcf73a0a00000000000000000000000000000000014aeebb995d464f4d77bbb72f15d9078936b5ab68eb8022bdd97d050576dbe46e6010eb72250c8ccf2a59138efb38f9d000000000000000000000000000000000cf7162768e8eb50e21d3c0a076c7bac4920c70f334336037fb40e57e0efa91eb025356ac3f0988a6b127408a02eb53fe2400a11d9a67041824b97a96f0ea9da8848e7990373655d76e8bd4eb84df5dc000000000000000000000000000000000b1d6214796b4775c2b50e634a549ed104e6ebc0e032967b17eece6cf88c93aac23059f263faf3c3f38463270320135c0000000000000000000000000000000013ffa3894a36226664ff53ba9256d39c6312303f5cbda6847b4f68c56134b7d731e74bd711014fe374f909a081a7d02a000000000000000000000000000000000ae4590cdcb1367392635d0f8dc6b9557abd16290fd1abca6da354646d8585a7c9432978dc616e5fc38cd71d55f139c200000000000000000000000000000000124a7b5574ef52359b4beabcc56d3286db8c8fe4ca4718f75da28d89a8a95efb878c18b48360dbcb6fb50a9f18f0d559aa2d17c409ade92566ddb3913806723d41067540a36a9c283bdacb273c5b258a00000000000000000000000000000000148ab0e847ecac963f0156da025dbc52e765cd8827fd55ba2969da6775649529226ab13ab8537ad0b89e8f1ebc8648ea000000000000000000000000000000001395b1adb6a56b91c3621a4ac5886a7b13ec00f1c74d5317eb74a766eae655e09e269ec48cdf740abc38f4d6fe52dd0f000000000000000000000000000000000f70f77f07ef2909033665bc05cfeea7df6ed55f2f0b1b87d9f247b6c07c7e22f516840efe68005c3953a2702573a9b400000000000000000000000000000000166a334a711416cab180cc498308487b281711f2d1b832c410ebb4c591af54b154fc8c8d7ac9a49a241f7a3840acbc75e5e3d21862b64e09a0893ece646de60cd66aa483662125ffabc46cc52f1cdefa0000000000000000000000000000000008c19bcbdc2ef26a30dd88f3e35dc7fbb3c81c0224cbcd6b12c90883f3973bd7089636f997e5f213fbdcb79514c551c600000000000000000000000000000000058620cba8ed5b738167e809cf71392aadfe8f384a4cf397d10f674cfa914e9e02bb1518e42f16806214fec52d880f6100000000000000000000000000000000048ac1120d26e4173bb33a58c0ce86329cdbe9df6a6f268c8d5ee4f1d6110f9d81cd50c46256198a2462d50be3e781270000000000000000000000000000000010af13ba791d554720f5075d46d03b55c0c1dccd679cef5a7d439ae868d3ff2780cc3ab151feb72b8b92905a205e630449510ab1b7850badf58cacad67fe47135f6524f0d160f3013e8ff1c881e469e40000000000000000000000000000000005c30a126c94b87c54270d0f23a486c3b36a8b491bbd805ae0d5f2bea818a87ff5aaed2d5e6317b786ab5a23f1cb48da000000000000000000000000000000000eb2d4663eca7f8433f10e84984781a57fffcb8f9535518721521ddfc7a4958778915ea3c57bef399a453b8ebc10befb00000000000000000000000000000000161947f57d97a858e5b3e918dbb22dbf28629e51e81335a9bf105d0fd660ef80087c8d69d8db9841cc69fbb5e7f81487000000000000000000000000000000000c52b6a559928fe4ad984a0569c081f3f71eed3d5b0d3c14d1a23afa45594e0fbd94143348390bee178720fc603145ab713aa69664a8c721cefa7d6dd3fe9f92432b4d350621d5297805fcabb21ff8c600000000000000000000000000000000071aa47d392e1a7787b37c52acedbb4632d5549fc11b79919bab7d22f1bbf1c3a239df622b8824b07f6e35e627283b8500000000000000000000000000000000198e72e05388021919dfc1b2a58ca72bf7655cc6c9b62abe3b45cc782ccfd4a2334780e451b8a6b7c311887036813fe4000000000000000000000000000000000e20cbedbafd96c42612e146debae48c7fab4846b20ad0848c4c42c6aa0603e72f94dfc938ed9e3a9886d221ccbdef70000000000000000000000000000000000c861d1878e63e313e672bebdadd3fdbb691cff5fecbc24da895febce2eef0a3c774a8a9d751498e4fc8e2b71daeb40dc040d8bf0a787346560fa3b100b2dd9adb3f7ee716b8103abdd9609363345ae40000000000000000000000000000000005f7cd2205fa2e17fb9896efe3fbe110e1fa59db1ae5f8d6b5f4510abb4da867933d4fe3caaadc4457dcbb35f1b9c62b00000000000000000000000000000000126f2ef6022a7211fa865c1dbdd5b84d96cddff424b06647acc462408f2d31f34ce898d76e1e124db7c39e08dab0bff6000000000000000000000000000000000987f916ad6f718695f3c40703c59ca93eba38931b45d7c33c64c9f75556f075b744dfff8a5f21489b3db6c3846ba09e0000000000000000000000000000000013011b8c72f3853738e22957f742b05ec428ab0da28901800f787b7c3678449acd0359fee93c40c69623aa4acfc0a81017b811aeac4fb7d91abc655f8a4392176f9060346073c957ef903e25d10935a00000000000000000000000000000000014b88c0586fa18333ab11a79acab8e12c6257f82a4ed16d929768a60a3a5d780a22101c32ea9b0099aa2816f18a0351a000000000000000000000000000000000de0fde69efd2cea7ae08d6d2443883002e0b4e11da253222429f6ecc67ba8d282eee84d7f46e0ad00b039a2c2ad226f000000000000000000000000000000000aedfa0a5a8b7577dcc1094469233f8b07e6fc32af26841894d498d70c6a9a046ad636086def948d21e39833c5b6c5a70000000000000000000000000000000010ec6aa0efba4995582585bb67f997f60741648156324696312d17656baf6aeb3e2db0d1a272912fab2fe81d139e971cbd1f096026159218836a46b9801a4f0c43189324d20220aca777b826eaf2575200000000000000000000000000000000004a847c06abc8ae7ce6e6ff0ab856889dd3e9697a75e3cd4d2af9e06d4c2fc48c0562289348ff52f4d9855ad03d83aa00000000000000000000000000000000075673bc79bafa9a64de6bb0e9dd9fa29cdc9c82e90a7348593eec673cbbf22b1eca436ecf767d45852ed888a3f23949000000000000000000000000000000000f3f8543d1e667404b4564dddba4d7c11d13881fcd8ad774c8eab8fc599f55147c353cd6e163cd7b9d5da55ebc13c2e800000000000000000000000000000000069edec7e7d26962d88a89dfad213daa36046bb2851e5d67adbaa227220f29f83ea67cd3747e6724f148dac28308604cf221dedfc21098ff9a9507e493d0fdb1efa6029fcdab23a016515078c76f7627000000000000000000000000000000000c945e83822896974116663d3e2769f3df5a70d55b8392c1f6966e330951f3cc5688742d4588648a6988b928b9fe00100000000000000000000000000000000003e94b7ff7c71d633ce69bb44d0ba1bfc7c27a5ee618e703aef81a45ad61771a2fa8e3dadddf7c8038f1f65ad7513801000000000000000000000000000000001727d768c1b51066d2af87a9da3e24ea2a75b0f75b8ece70727f9f54ab77d841e7ae01c9c0760f4186d02a28d6f8ddfb0000000000000000000000000000000000a273f9395cd49b646e90fd2526d5c93fd46c7366b715546529c9edf5cb3d274c9947c21a03add3e7b20612636a6745ba5b30d1397bf28100f108b84e05107ddd6cae2e82f1973ce187e8c3a7d02f3e000000000000000000000000000000000c996c16a16879bd3194ac366bbd11b5863123ce6fdabeafe56407600e5d49c92ba68ac1256e1515dc9256de14ac26de0000000000000000000000000000000018c584d8a4f14900b2fee70b50b700199ec2372b731dd1380f42ec7fd3d01f0c9a007554059b85946c1c4f4e2fc504ad00000000000000000000000000000000073d6c7d671762e5398e4c9d57f6b68c3d97dfe0d01783f124256fac236f03b774db58b79cb4d5558e1ebf18bb9e19680000000000000000000000000000000008eb2b95e17fdda916b08ff2819cecd2eb031f41c8299b308339b7d9836382ced75e8eb1514a70356882d3a43227a9bc19aadc83d1db9140af303c0492d2b9bb9e2b53ddb62cd2132bdf8ef62aaed683000000000000000000000000000000001029fc28cd502caf3ea3619f6fd04bf457e6a452b5cad680ec2d4f8222a5ac2daa92b880bda76016973494e605ab28c60000000000000000000000000000000002c672c7571b5d8e99de6e47e0a2eb71c6d9bd12baf2b083e6f88598b32c4644d1486aef582c5936e622058bb141db1700000000000000000000000000000000033cda383a77d5b3adbb0809e834993c56717f81f8c66ad2d97f2b298d5a46f7b29a74d35da09271b7053a05af096393000000000000000000000000000000000132da041c6e3e1d68bbd2223f8531eabde8e180b36b2cd0ed4fca248f255cf3eeccdc5f61e1c581ce54edcfb2b73e0787eb6fc40b00246910626ab66bfbac96ea09242d1d70496466e4d681942050700000000000000000000000000000000009721f22bc49f68d703a4dfccc3bae791caaf0d73892bafa6e9da465ddaf0fb1a069ffdd55306acff2407da64c1c5a0200000000000000000000000000000000056c0a4804a19aeaf1b4fe52064e43de8e5d41a8d77de054e2cfdff078eaf468d123d7317818d1bad1bf3469c0070b680000000000000000000000000000000007f1f318aed043d9ad7bdd53eb6a8c3167240fca75925b04795210700463c93a66ed64851195df1bafbbe4227d7db5ff0000000000000000000000000000000007b8945e258311e7672e842b91b540fec9ef4a79296956a5cba3749c0ad95ed83d7b0b48384ffb3188459e997b86695d3bb5926f36808c0024ea7388998b4cc8c6c48d32917f6456b39d514143c6eded",
+ "Expected": "00000000000000000000000000000000086a1ab4c19c27f70aa422e8292752c50b365d6fe3eba21e8f2ed51f283df0446020834ad27c18b5c7285d1156049bef0000000000000000000000000000000007288f40fde69bd350ce1f4d0f68e645f42de319cc032250b76fe4fa305341e244e5b2366751d5311105e3ccd30e701c0000000000000000000000000000000011d0c487c4eceaeac009b694931f8eafaf8eecd6028f14a4de33d2940bbb747025eecd509564721b50b7186910f81949000000000000000000000000000000000366f0c901fb859b4bae006fbcc9ec7e456eedc7366c899f68090fbd457c37b03ab99ae982872c7888b65c1a056c134c",
+ "Name": "matter_g2_multiexp_13",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000072f3f03bb09ca30239dd8302b05e0d9dc4e43ea33e865864a82578c35eafcf6868bf0cd9431b92b76f00990b780ffa400000000000000000000000000000000170b76cfb7944ea5ea055aeedaface3e8f0fa4d0ff657fb9d5311f3af6e736da84a5e2bef5188e20f76fb42591267fd9000000000000000000000000000000000d85300009165a8da9cb8e590f7f8d372e4264df150b1551185c80e49dbedaaf872ef69c5763fc3713d0c087c89f21050000000000000000000000000000000003ba59b682174ee61630df95c8e2b1c48ffc8f7f8508c21f3bbe8f7bb3266521fcc06c8f90fe5126d872707872db6d59f44b0204792359895b448bfe6ffaedc14d54a6d72be7a49718c0a933807a399d0000000000000000000000000000000004e8f16480c2f080a13b9f2b66e6480132d76c4ef76e8bac995a8e33280073ed5610865260e154b32f75f527d89620b3000000000000000000000000000000000f9ca48d732a8055d22fbebf3d2bc1e1c9c815c184f594ad2337731709317ea6a205478ba05ee9271d35a19dcad4db5b00000000000000000000000000000000078013b9290284e7ad528a1bb9a2a64b3ef43964c7226ddff8ca16ab17b4a2e8a2a7d921ba924a718587954f586a954800000000000000000000000000000000004aa76bb1122116cc0c04d65265d8652f08b411632a732a9e66d7932801b77c4ad398d582e446968f7f4966e9167894de25977e7426cd5652559626ff8b195ab7ec679de987a6a22a6a0e366759dea000000000000000000000000000000000145de5d101498bfc7c57830eea2931663ca1165ec85b77654c866b04ba6a28bfe710c1aac9876a68cc6ca119708eaf0500000000000000000000000000000000096f9df9d5723e8379f2d09c76a3fd059be47d2c2ed8905d333b2464f72153c5f50b6345980626358839ac691c26c967000000000000000000000000000000001788ffa765c19758da6eb6c38e793190c64d4a7b116576f6827fc090b0f65304988f6a95cf4397f82b7691fc43960ee8000000000000000000000000000000000746e040d7aafdb06a31ba3d7b590dd28f0678badc261a93dc7bd9a605047ec67ba86b2b6dd72637a449872674d6b5982e7ae497b44f531fe203a599622954804c06d5348dc17eb1537e750006584b21000000000000000000000000000000000d8f3cfe1cbd2629f3899313cff16ca3d8f964ec1cc0508341936a7b3b49240db1116b2c3de28f9bc45cdfacdb5fd98c000000000000000000000000000000000fa642ed31293e44211b34bb28bd5b389ae6d0510cdab46c89756f31795506fccbdacafdff21b0127e80557e5ba9afdd000000000000000000000000000000000715a8951cb358b0d8cc63377799a9a61ecc85dac795d726fe60e429d492c9ca843be2a2633c17f830f199335e5d7741000000000000000000000000000000000b88a23fdac7d35fc135b45d7565854bf010a75f072b32c57ca4d0979c111aadd84c71df6792dbdc8e975ecd46a15df2e073adfb5ab96730c53015a4ab6210a35a37b2331ff5123e00798c33e040a913000000000000000000000000000000001171be5820b5a19c045abea399f2b8ab9905d2aa367c6c8c0f84eac132d26150b759a9c029414f1c8f7e4880214446c200000000000000000000000000000000147f0877321f2709183f0b617a7c5ce898db508a3ced4148cc9f7af011fe8040e90885ce817aa956d9f5d19dd968f6220000000000000000000000000000000000acb005c11481b214a17e3cca02c2af266e4c8cd928e3c4e221d866e9f296a2e913bf34c4e051c7503a5e4e7cd7449900000000000000000000000000000000125f45d0af1c010cdf8438bff0f406007853e566fa646df40a581f65496197755eeebaf4f0f77e1e936f399dc4c6c020e6e752d40d411f1ee6e67f48109c9a059226b446601047a2189ab815a3fe13c40000000000000000000000000000000019cce3f872af5cc515ac4cd7825a5318ead5b464d50349909a70b415a8950206974ee0d4203f208d8e6d14690158f5720000000000000000000000000000000002e08e8accede11afe3e2d085f35c08d7d414c26a9caa992d5a090a43c9b0c0cc1471f3693f9d342a973da65189c888b0000000000000000000000000000000008a984ad2ca60c492cff2e95d541d71e33b269b10d3df107c0513dad5af511c51806068da6cc7226df1cf5e5a2fbe707000000000000000000000000000000000fcd3ad75bb0a5c046cf83be3d973bb3685bc717d7b8262fb8205935db6e632472496907f7c965fc6b52042ce69999f9e657fda33cf4ed1aa89dbc19d58fbe3043acb5795dfb8c0cb97620f16f8f24350000000000000000000000000000000014ccaf7594d8ff6157f9439ba63480d3d07f44e62a86caaea510d0ec456cd8c6c4b42cf9e38713213eb4942ed45df2ca0000000000000000000000000000000015c2061c532cda006addd2fd6ebbae458197d55fb336f75ca7decc05dc6d421a65495b71ed11874aaf24a0ec13a7c65000000000000000000000000000000000101f953aed7f23b5b6208032f05b818e0147079b7764aa3134dd9e4a316bbef0309ac378ca3cff3bdeab9ca56cb78e60000000000000000000000000000000000c76a2bc721a4d3ead95af79ec24be9b7624bc80d7debc07e388e52ec621082b9a69f48d157b168af4aa73629697f784c73458e18d6f832f362dec7c49140e6523ead045131a1b719b0c836c1ef13a79000000000000000000000000000000000761832bb5b530b80c668234ab5996bdc225c0c696ea07dcc61c330320404827ada9d58d658e230fcb39a96b339b830e0000000000000000000000000000000001198b85418421d96ebfbf436193b411a3a89c206d006291bd23254ed5fe12ccdad15725a34d962005c0ae60e202bb86000000000000000000000000000000000c1d7ab83b1d2ad57a407e248492773a357c06b83c16c6ce1490e84bc4a3cbae395f160181d2bcca3edc34b764754ab0000000000000000000000000000000000f1e9f0cf96d7671763739b6c37fd442f0e816c49d9c8e001d322397e9d6741dbf8769ef9eb83d08ab024294e279a02838cb0a2b191f538b30187dc730a8c665bbfce8186883500baaa6c3242a0d147400000000000000000000000000000000063049bc3282934e29f3bb3dee432bdad6193a5d2247270e88887cac565f4b986e1b3b2af5387cfca64f0d50bc0ee1640000000000000000000000000000000019f0f05fc7f8bf2f0b8ed375690b53b6dafd0a07c49fa55d36e040798334700a3aafc4995bb90de9c4dc0e077ee18b58000000000000000000000000000000000fbe702d148609dc8feb3ac11c5eac8e32a2f7221aa135cc33a585e9f4c97afa1658d8962fd96e26e0c4c1d5108229ef00000000000000000000000000000000061fe418d3b440e84728091a4996119b515118900f54a6f2da2ad5592f48ebc17bba50b59ecf435de3cb892a123ae9d18a27de64d41d13ab67c1f7b1a7390ab4dbba7d219dfeb31255f9401d5b3c62f80000000000000000000000000000000011e8ecf1e341f0146c59a79a8428bb01d2399d3f87d90d057f63e6cb9837432154d17975f70df175a016735caf85120a0000000000000000000000000000000002a5bd53e4f4c5b9682e1af1f7e09dd305e7342d1688f62885b5e59f173a9fc731cec481559ad693030004a5fbd90a9d000000000000000000000000000000000f9601f95e12bf05c35deb204558d44a60fd630c05f4060b7bd9ff943946e8eab507422afe00a3e7706b8ed013f712c20000000000000000000000000000000003bf6fecc0c7414a69c2b48e2c16e88d988ea8ae9d8b59017ecb89394732a20e4321cb5e4fb071aec7d2736220a4553780030798960729d63db70b8bc3c0030e80d9b8ae766e3330128557e6c34442f6000000000000000000000000000000000549f6464b657eac28f838c6a8bcfcb7a189d6b3b9712e19c1a23503ac209da5f2ad4df83acd505b0231f00eb88515c70000000000000000000000000000000001bf4a46dfdd70542e9d8cd6d6215174cba28f9adbff31c02482ca38205cb4afa2f7fd65ecf57b39e4ee5cee320e33800000000000000000000000000000000012d04a693d565f96566b7c313c47d272fef0ecc828493b0841d58f6bf690a77cb72824a656442e288460ecca7cf05504000000000000000000000000000000000b33eefd5df8b098e6505cbe655a483ab5c6e417a4ed55420beab95e8614c8538dca9296a7848d6aa0495a173df6d0b80d32b6969af54dd345f42320ea96def3c6f4dfd4e22a82686b7a3c57a0df5250000000000000000000000000000000000fdd9702ed88aa857254c3ba50b484bfc324e583659c57055e4b09eb1662af2f70b547a1eec139193a0d3c75b565d3b200000000000000000000000000000000193df0fbc5f24065008b5e98c4c4bf9f1e743a6ee60c3700ae4a9108639e540384eaf1f9d7a60b8b6a5d79e1f34949f50000000000000000000000000000000001022f8a254d17e448cadfad35b7a54dd2fb319c8f9ba219874bd8280a5077301ff4332d731a75646cd93bbf31331154000000000000000000000000000000000ca1eb350844ddd0a65a4ad56e1a96821de2c6633a4a45be976577c223e367853e2b1ecf2cc40b8595ba5591ae8e40f3969848f1b8b36bd28967b762168edb451322e2f0c4b99b7f9112c9a66093fb3f0000000000000000000000000000000001f9cda056a0f8803be581634562e975223b5311f4752b189cb6bd6df1ca5e3824bbd2889b9b93da59e4f08d482734240000000000000000000000000000000009f43c25de25c5d76ee1a03691aa434de6a063bb3a1133b045797a279346fc938dd2636abf0c4bbcb528c9c28d3105c40000000000000000000000000000000012afc29245da8bcd3c0d96c4ee61617cd9ecf42a47c2ee822003af26aeb4e4de8e432ffb6b2d8241090b814401a8676100000000000000000000000000000000053edfd98742dc70d510f1836fcffa6a3ba9ffd4904c7f5559b48e49dd21071401362d0b39bc0d786b7ee2e84a76af0d957ee08a513c5e22bbec04722575a9b4f3a1343db0ae5beef4e66fbbe1ac90440000000000000000000000000000000001dc3f016ea1a74ae50c21c1955ca1eb4a911026a1e72b316c7bbdc708caef63f0c1efecbecce8901d65bbfcaae429da0000000000000000000000000000000016ce9301888808323c9baf6402d7073fb85ebcd389334cc69d7947e345748ee44b2d6aab3ef818beb21b54a19ae4f5b5000000000000000000000000000000000c49817753eb6459cdb4bc737d3710b5f044bc544c8d92c8ef138ec9d83889664267e1a5691f4bc3fa235ecca2a973a500000000000000000000000000000000074a8450e35f1da18e6de05960e21b7059ece8972c36f000bba9e24488730a44ce3ce200c437e06703addb3b442a790a8e0cf0f590f77d13819001916d2c58a654d0b9d3c47c842f2d649cb2570dc0d5000000000000000000000000000000000bc1f2e9af093ae8235c93af098e692e697ea0ab4c8f53019a6e950f7072b56d5eef6b3237710f1dd1cd1970668d06d0000000000000000000000000000000000d9a63f7a13ff9755c6a3832e3c4c852919514523092367fab7886cac317e564d57fb4042ef40e696edce868e697c45700000000000000000000000000000000129a30657466460db13575dca367105c27d631eead330319b084adfac591f5b3b94988925d778e6d4645d1d2816baad00000000000000000000000000000000005ad64d6e761a9a301589547929f4952ccbfead278cbf6658255a075966340f185d5f356679fb02ff2197468ed7de19a71a8c2a479dec43d644ec4113142e666bcefd6d729d4faccbc147effa836ddab00000000000000000000000000000000077d1e5b35c224e2cdc849c02e800c0b80d1c19f3d74d9eec34c40f56bbdb9e2b5d2ef274991dca843755f91a50826fd0000000000000000000000000000000014f3b653e0df0c608b75dee3496a7af04a828e6fc5604f16ed49c39686ec757e96adb0a667853006a8331c3d63ae4ec2000000000000000000000000000000000aae011375b337940f2a53d9091d3581e8197e79251b19c7fba01de987721a9d6fa694b7978f0abf877f46ec26147c98000000000000000000000000000000000aaffbd468a2eb86a3cff59e2e9b7ab88286d2bdd19c2e789b1a68810f0cdc76171a2661ab54e81b17643ff0275eafd72d2d59a7f138327a20263d6338d2a92fa5a2f741daefe9aa81d06f20a6fe3641",
+ "Expected": "0000000000000000000000000000000010a2434fd3150f6b9b491d3a51226bdd457504077ef2ed5a11ceaa8284900d1b84039a34d5239a863809369bf20a704c0000000000000000000000000000000007934f34fd50a98225fe6578d3f34ae5e5ef5e104bb9cb398b2ca4f09048ec39cf52e7fdbac48d45212e9e4c1dcc6e120000000000000000000000000000000013ee70f1b52cb8b07ad957a7565b3e3c56306392cf7b5aa29047b23e5b41fb3239ac3611bcb16ba7c7ffc4213e3d9cc800000000000000000000000000000000035840f8ecf56359dc3239945720ad08702b4ea8d0fa9bea3bfb234431df4618e960a1eea87da72ba4d9443f14bb87a3",
+ "Name": "matter_g2_multiexp_14",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d04bb9b75bc8078ccfa85e27d32e137ff5f05f9241b19ea835bba2fffc9255a4a3028c0caf9c32d3d27666e1394fe820000000000000000000000000000000013f59c3d8aaee34230cd7715a32e4a45487b9b16ce68d178f95461229a4d0fbe7d31edc7208a7338eed08e65847f8f29000000000000000000000000000000000d63ca2bafaa54e93ea54846b26f88b4c6749953f9cd00c670914cca279b794c1fb5e2664fce44b8c04f01c68698a8b9000000000000000000000000000000000b5188b4b7ef78d3662baa01b1813b4a0b0f855e11397584a460d56f594f11ff2e5d708a23a8e64d0ab337c7076872527740a826d524fdb7969776bede5ada468a0115229152907cb2b050760c18c8e20000000000000000000000000000000019bae57568c879cd743f7def43b6b994f29782c6a0c74734f35b97042a916da00daaea34f321481e6cc4749e23297c1c000000000000000000000000000000001853fd11d4688b027146a07edea647502e80750de4e5e2d105faad3f71ccc90badcc750f76f1b02db3bc0a1a635b2bbb000000000000000000000000000000000b1e45b90e6a7032179236f13f01ab664c32ee5728414ac0d6b9d79510e8c5bd0f5b62e6c59c1a3c88998bf45636cbab000000000000000000000000000000000ed16c2f88b5b8d29d7e01633e2876322caeb740251b034e5e898919f836ae73f0296c62253a0329ee8f71fdb5cac3a1d226f56bf3935ea95d976fde5790ba0584e5bbc78b37279aed8e50389899b9e9000000000000000000000000000000001455764f99e5eb0e0371e89f88bfee1c43224b9b5202746bd151f72336285556acc5ff36bd8ff87378249e82214cc5e500000000000000000000000000000000007fcee74e5335d96714e4d1a7c6f5c211b1a460efa283e0d0578c6c1f56dbd252198eebf0625362973c40d95fd890d3000000000000000000000000000000000ede26cf87e604507230ad996788e85799cc07245cf7191a6c3cecf0bfd5747b3a277cfbe41252808df6da19f005de9a000000000000000000000000000000001855991a4dd78dfc6088e6a43a64b56c8d86a0278b899bc8a1979a40a287979dee567217b006ca71374156a96b79c176c133e1989ac82e4d1c9852a6c7156a34b05784a58231d59e3cc875ac5834d5c8000000000000000000000000000000000cd032a7dfed029af020bfa249e6adccaaf5bcd2ccf33736281c4fce9c6e2b2e87fa828cc20301269d8e0579ffb866a1000000000000000000000000000000000765c4d6c4062cfbf7e24f9772dcd812f7e707f2b0ccf9043faf10018326834934df121924abb74d736b0da47554794a000000000000000000000000000000001540fa51e4580ff73e58def90a6f19557dec3c8306e2317ba0c25ece3eb4f8c39beb57741b3c4b9b8554fd2597743ce6000000000000000000000000000000000d875c822d0ce50dd638254cd4aad5dea1443813689a940d72cfa5db9309b171299ca3d69b137dfd37f0b7538a0852750fdae1b53f6442c4378774a981c90d282d5f8793feb2334470c873491e41740f0000000000000000000000000000000011c230689175cc672c25f3c56ef4eaf2bc5766ce424f6c596b40ab24fdbfa56a955205419c149058dffa4d86a48ad35d00000000000000000000000000000000078d493ce3a8038134541ae5f2a82b5e0590218a499dfd78c7a9c06b92307003fb62d6414d6c04b22f2877c3de0b65ca0000000000000000000000000000000001d53c22a622c5d91df934783f8c0cb7e370043ecaf99a0554987e6c5120a0e5f4ede023a9ad988d30d945a2132ba5770000000000000000000000000000000015b1f36a00fee95e13443c9f6e67935a840cedc7c3fb7833ece8e180991909922f59d4f4ecbbf23f16bf5ee7f0b5851b70f1de7cc5e6a2cf7dd4b6e60ada67ca47e7b9417bb5f599048fb0c9b2abf33d0000000000000000000000000000000014adff1607236910597a951ae169a7f56d6a3b4e0f44ac63a247716bbbf61feff7865d075f79e4108cda6c0731fdcfef000000000000000000000000000000000d740b13885c268da876898b77914bf4a002beef5bd2a3edefbf366e45ebcdf593ec6d9ab21e983fcae9a0832986182d0000000000000000000000000000000002a0827e812e983898351d9f03f660317d41669b0fa378e5c7667b73df299ddc4a32a529ca887a53245d7e1f946623b3000000000000000000000000000000000bf09a2de1a8ccf24a8a65dda72adcb96535ea7235de87f05d27341738b0b4ab16afbc5b37c97e255118dea9bf180ec2ca82cffdf59b742a736ae9a6d36f7840c46c20c126ec054f47ad52a22948d7210000000000000000000000000000000015fbbf7e8c26e2f41be32daee2c81390b9bc4413aabb053e3a88bc6117377bc16011e81ed167370b72f84f0e77c2b8680000000000000000000000000000000013d48a27d06ff00048b19879493a5f8ca52b7154be2fcb468b9de9edd1395750434b0e95ae6dd941e84fd6d8918455bc0000000000000000000000000000000012fd2bc91286dd46d68d87a3f8793db997ee684dec6b2de1c4202e5e7eb0e4a8a21222e3dcf80e1ae4a3a92474107d330000000000000000000000000000000004d8b71978c9025dabb3d1b1b3c7f4f13f166514b8b356fd064842269a36c6f1c07f150c03510af7d0913103afda4a68fad69492cab4ec7eb89ed37f1e7fe898ff49ffac4ef2aeb75d9c6b544109a08f0000000000000000000000000000000007d679ac21bd4634b415ef8e0e3670a8a1d673f6a4f7f3786b92d55458af980b035e4dab165a3b773ff3469fdd9d5135000000000000000000000000000000000fdb82db6e1096e73322050f828ba41b3012496a4fc4cb481f11fee338243aae20b205ee06887e28f6ba6dad00445f9d0000000000000000000000000000000017e6894b48f60b3d9b4184d58ab9554851e285a1d445b4d97cb1a7ed5a984ade8b0f62ab11ca75fdb280cc0e526108ca000000000000000000000000000000000c03b61690cdd9a4c6c83d03749db72c8946c21a944fb292866cf3a2dd1bf3dcd95743227709740ce8124319d0a540555af71c9baaf54967683f8553f72abf789da465041ee5a92c9ce1ad562c91c4d7000000000000000000000000000000000289f850c4834153f36bfc4855f89e9437a172c35a856117f8b841e5ad4ef973d3aa33fa73d8dbba4b9b2101708006bd000000000000000000000000000000000700025f22c0460613c05f8941f8a79a4319325c37c2b8f099cd910df5c0c27121a9de0e40adc7ba0fda61ea637b47d600000000000000000000000000000000069e17e00d4d726e8eaca8235c88967a7c093c70e5a46b1863ad097acbe233554048838a0a486a72cbed7001c83a27db00000000000000000000000000000000016ce4afb84c1a9e0216f23bcd2dda0bbada6a4acca78e1e0d765a5290f6f4929f6d0eeaf1306fed3c9766ca7c7268acc7effc9a7fe773a420ca430c58bb94e7baf26b9a97b618a15e7a18b31e5914f10000000000000000000000000000000018ca46a89dadcd3b54f60fdf9a7b97c95b9e0668ed9329bbe4121e588a1ba773c9d086dc35b699d65487f428c00ad8c30000000000000000000000000000000003ada6835a93310d0ada01bd7fd6778bd07e718d1ce05aee2b4990bf32322fa94ca898a531ec6e3b8cd7ae3bdc77e0b70000000000000000000000000000000004a8abd2b9f7449213e63ecdb435e5e13fe2aaa31a2c38673a6adb5e96f4dd383dacab391787f6c17579c78a1cefa5450000000000000000000000000000000002a8768d98ccda80149a767e9b5a3b0bbbc0ab4b5f696522c8f1c664f1d27f2f0a6690531672ba2070355c0e77095dc02d5a3d0370f4a58c21016d208609f1d3e7cdf43abdb85199bfc67dd12f589b8a00000000000000000000000000000000048fb58924bd5952d3bd7b1cd57a1dae6c1034df3a420c1151737f88760e4b0e78fa3f891a0dc32fcb50f89e67b0f08300000000000000000000000000000000073e9723c80eae7685db774d3e2bced53a52f24504fc3aff98e2becf8d59c6e83373ed024ec1ca50101d2d613abd286e0000000000000000000000000000000003b64c8e9a1341bc6a444a871843b3add7dbf04bd1810e1d6da7d31c7c2b7a264c362ac9a366dc8d93bcd9392c6056f000000000000000000000000000000000064462d424e54f50e9849a2bba1b0caae966a8618fda0f8965b1a841dd2173872a44a18ace1e2aecc8e3546a9558d7013549b86ed3fb880269be22b9cb8be6f24385bb5e24bba81bce9fd5b72ce2ab71000000000000000000000000000000000c40c8da9281a8b43478c28b2fe59a3cbad0a818e2077d40cfe44624dc2e46f72d4489cccf63eb8460d02f895e78edf5000000000000000000000000000000000735d768f6ac999a47c88bc2f3375f01052259dc69011480e468d8963ea8eda74726c4ef32c8feba52878eaf5c0147730000000000000000000000000000000010adb3ad214b17b963586a10701934727edf05fcbdc94d98255632647d73536decd0c91363840e1b55f29f7d32f650410000000000000000000000000000000019349045e6fd25960c03336888679cb53409027f35a1f211b40d24ebf724866c085a978ffa3a91d989da1a7902bca018c8f6dd56906fa13144dc87c31b53186b0683cad220ab2de89d2fb515bb269cbc000000000000000000000000000000000a5d2dcc05e218b0633e0a965b6d69a3c6c1c7837e1fff7ff75cc9ee93a112f8e34cbc95bd9dd8fe6ed22f2e9221aa110000000000000000000000000000000017d2e5d2c0578b1ec26b57c3305b209c979bba6925756892f031a7462ec44e8a4a2527e6aa2fc13bae91dcacb8c7a30f000000000000000000000000000000000d437edb45ace50700db548db68b9e8376b3039fa00cb98dd00cd197c14d0f92c8a3945127c43b10b34bef7894fa43410000000000000000000000000000000010d5a2e442a2eb35aa85fdaecf094c1e1f307dc9bcc540693d7206cc4e0d050ab900f17fbdd0754b59bd2aae705c60149ec934eddc44729d05f193ac927fbcb022288ffb2bc7d4f46d1bfcc7efacef940000000000000000000000000000000016c36464b426c3066aead1aaaf65ca637e93279e8ccc9d838b9b3ff1aa7b896f36de506efc2b0864763cb6ecca4926f30000000000000000000000000000000006d88d5764fc854ed7d7cf1c0e210496ce347bd887da2a149a09679469e98c453d85115afdd2fc4987b64a88c4a6f0a200000000000000000000000000000000053edcc0ca4c205423ee6a7031939379e552bd2d2657f8f25370c9f0ea0a947e77f18b5f218f98d12d720667844f3795000000000000000000000000000000001292909190854cee4499faa602af99dc49d1354a71278b439e983bd89e6c504fa5fcaaafb6ea26dbeba9850bcdfc1f69bd211ec887635ca841c4608fd00bdc0f5fd0f6365dcdfd7d6f4c36f4b25b5b1b000000000000000000000000000000000997e79a7549ada9ee0233b3bf9289df3ff797595f4b5eb2e7dda6977ca981c1c4a2b91b924812b95418f1b1d9d0cb830000000000000000000000000000000000256b830e80f238e8494387429d727a91cf5d323ea87f7dc143058c05e11858796adcdc677429d1db4dc2415cf23808000000000000000000000000000000000cab529c6b86beacc57c874f07108d1df7d98fbd59fce44c48afe9eb2dff823f4869b620bbafc121b4ead2cf244974de0000000000000000000000000000000002774906c1a0acd87de224a9450617db37f8f36a0a192f5daa2774eff0b73aa79b4804342999df761f8572974c697c6010bce61d4e35770e7737636c0f9a664eefa948662d3d22d1f1708fa48d3043de0000000000000000000000000000000012abd02540073017011e186586023adfca36fae454350b2015a796b7991eece65b63964fcdf581b4b51dbd7ddd506ec3000000000000000000000000000000000ccd3f2d9280908d4b30e924e4a862810a92e1a880cb56e842a94a2a5120956e8713f548ca279d66d06ab23e4976e54e0000000000000000000000000000000000c052ed00fde2cab515694d8c004de910e62d07c462345ffcfbd3904a0171b970bc58d99c5833059315283004f3390e00000000000000000000000000000000008fc4860366074ec0c7aed2c6ffae7c93ae0a81067edd8911b4c53393ebc0f23243823aa7aa2b2e987cb510f6e0a55a65c86930c1d142985bf85ce70bbad170947e850e5c6ac7803fc45980dd37a57d",
+ "Expected": "0000000000000000000000000000000006ced307065868b6d082bd205bfbaea3b0a8cfdccf831bf154563b5a942154622b0d7689819b337479480d19aedd85e4000000000000000000000000000000000c0f04fbb26cf85c2c22763f3e78fe255d8d1f45ea47232ab58f5b785ad9f2458b0b28f3cdc25c4dfcb47d59957ae10700000000000000000000000000000000120e38740eebbc3eeea9beea483e70d6a9c30a5abd61b86e5f94bf65ffb40fb92c8d246edbeca425ace175f79c9c8afd000000000000000000000000000000000d5a503a26e50f9be34c2e64e4a80402ca6e17f09db1b334a9c1f6318f3e7e63b3847a7ca38ae6aa7c96ff94bf5de842",
+ "Name": "matter_g2_multiexp_15",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000036480931a5a585ea54b6dbb01759eb1d86804e3f03326188c71f859613722e662c453096431171a49eecf8653f14d470000000000000000000000000000000015fcd6a30b9d59a90d8595ca1758eed7d6810d2916638dc2cb637aa09b16b5ba4920df7d21fc0b923453a6c7d32f056b0000000000000000000000000000000019aa4d8e98808c2fc1273d383e836876b087ad5a7d01743bded01314bc62ced94052d75d312a18839c1b33faa9e2e5160000000000000000000000000000000015747ce0f1171c0d0ff1fee9dbb2e5673b9db0b0c3618cc8bda474f378db58ea42184f907593f3d6fc2fa215cabb7b2308e559e394a9c1ff07a45bb3e022f9c212eea4ee5b77db1c5b93ce72c0512b79000000000000000000000000000000000222640c1d64948daac3ff93e86ecc96bcf9c93559266529a37ef1372a81952431673d69f1220e07b8aa0a4f3164c83b000000000000000000000000000000000db593156078821cd0ce0270e8a444d0d204dce0583774496620bd4752839f3451e505aeb3db568048739c7e71d279b40000000000000000000000000000000019932ad2c7e857c2dd51f7846534050b9243e388260cd47a91444fa050a9154eca88ab4d29a37def16d4a11d35683f2f0000000000000000000000000000000004d15ec653a72256ac6b616e9870b0acc7d46286893c0eec523dc27bbcf5fe596204cbf83ce71c2690af67b3616794225e55826db8d12169a31ca27beec80554954f522b56f7994c62bdb527c2438d5d00000000000000000000000000000000180622bfa9a1c452f343ed21a3e9c6fdf76589cebfb9a3f0a53782a3e7c9d066294e10699c386b5d0525003289f0ec580000000000000000000000000000000006615ff63c856302dba6d4e25d1070fe873e0c4950ee5ba8bbbd4b94ceeb181f1ee450acfd22f21010b88f0b88375777000000000000000000000000000000000cfd3940b5eeefa92d775792affa34371d13f3098ede3007e06510344ac8483debadd5a2baebafb5ddcb45a9449768b200000000000000000000000000000000145be0107a1e3acecc89a116668f9887579ed7a72abed3f4236930edd3f18974465c99ada86c4980c88768824216170f1362e8e39ec661cb3c5af64e0001cc94701194344a7404f1ecf7df0d5633eff9000000000000000000000000000000000820e74e6d0333b6b36590ebae78960d019065f1681ce68a2a01a2522496c840c668575a57f9fd0f50b87f928a41b0de000000000000000000000000000000000dee60d90e96019cf2bb552d016419e92dd358ff97039a61838b0a89ccbbd537f2b435cd11f7b6e75a4ec6675964e7fd0000000000000000000000000000000002ca767de9fbf8af7c73d41a07e1c0e38e3fc971472e11928b65393a27354b2d732012dc57f498f94c0b933565a7493200000000000000000000000000000000134fe97b24e153f0e9a27d3fe7b89999c6a19e353325e0746ead013198b8e00ca6472fcbd2a112aecb9ddf671aaedd9174d3d66cde7c4c8a4499708a0c6f7c4da458eb970b6ca87e23601c702365b6de00000000000000000000000000000000031a9c29323196ef31030ba73827d228e56fd5209eeef0803a189e0c0e5b186ca1f342483eeac99e1e1b12cf490856460000000000000000000000000000000010deea45a01370602bf57a1f81413e8d3b337d7a1a33f9525e4ff7003454d1da2cfb1a9b42c4a654320f91fe7d04b6200000000000000000000000000000000002bafb7b7452a173a3971c2ba1768061a043307d2c32767056f18c1bf8b066176937876a87055e54675876bc1b2d2fc3000000000000000000000000000000000b5c77dba3b4136a7efaa8c2e28f39e88afbf26a7313b52ad6e390da4d948209d96e39aa08eb52200dfb890d7e88b46a389e0d43f2006449fe2de506dcdba4cd0e6077e2228f7d8b6ec9d8a4129c494f0000000000000000000000000000000018bd1ea5ee8e39c43d442e9c6fd22706e582cd80051f18334c4db2ea91ab019f54bc0074c8f0e52e50367197a797e7520000000000000000000000000000000005c0bcd1b047fdbdff25b138248bf4da4c013beff7dd3030c348d6b2b8724a147cbc44d570db5c4b273c94d0b99bc2290000000000000000000000000000000018e033935c20be5940863f7e9e39fcbdc29ba031e58c10beea90cc48e9da9988fdbf108bcbd87948058f386928f81fa800000000000000000000000000000000107d179204db7b288315e8aed7b92ebfe53b7ad2366d5d7944b3df68d9d9faad023e477213f85214047645bc05fd4cde5f8dc332cb31e43bc2e551356cb8d1533c6e567d34622667e7e4e3ddef352f03000000000000000000000000000000000a7b364fbd3bac7e2f2e7ee501db2d248bd73a76c2a12a3e51718b56ca9a8ded14b83b8cf0b5bd46f0c26896a65fdb15000000000000000000000000000000000eafea7128fe20ddf740a6396bf18ff5f2652a0317ea9b6e934927c3ee95b59c7dcd51f7c895b3989d40ae5f78ca508f000000000000000000000000000000000bdce57be904236a8df532c2c0072165b5cbd4103e9061fcfc0a45a67e4b25d11b9f816f63fc0eac4d6d3e10d2764c4a0000000000000000000000000000000012419f94ddbd8275054f8f89fdc27a74afca2eef314393236fca65705354e5cc0a470818999c96b5087997813823e9be0dc7052044251fd360538fa6d5dec9fcee53faf2f07de5d8df212d04f968a0b60000000000000000000000000000000011e4010d0cd7855a92cd5d4954ad735363c0c2ab00053db5e078f34e772969d8c492892329cb95ea8893b4b7ff7aaa5e0000000000000000000000000000000013badc54d90a19b84d76b30fef8e3ad2cb268204fdaa50ae951b63e48aec9cc6d585751dd48e4a8d4659b835f38f8da8000000000000000000000000000000000460728f686b9b15cc19ef135af71312e174860284c3f0e7a84cf85a5c934e2bb6cadee8e482d88afe788a796605f79d0000000000000000000000000000000019a50c06ba307d83452a30fbd862270652cf5c7a09b150fcea858a8102ce3b1e9ec13b6abfb323d63d2c4edf209c7cafc579dd4f361fed9084d9c66a3ec4c6af5293710ba5299df3abc4cbaf5802b5360000000000000000000000000000000009faa74f66ec0384f0458893c0026f73688c764e8df9ce056a88a2ed0b84ed8f88d1b683443a3269a3db838f8aeb808a000000000000000000000000000000000949c4be2708c1aac86aff39290ab6a8e0f332e7a098bbd64227a175473d9dfe136e07548b282f69a94a15e2c32dada10000000000000000000000000000000014f2c7c7da781e2f50803e3a948381c3c439b127949f79824df1e5722c206efccd6c0ec5dd75ef63d8b1fa301c83356900000000000000000000000000000000176753460d241f38aff41bafdad51688ab0dc9a5fb3643977c7b9d282ad4532fcca1e725715227780ec28bf1c32bbc1d69f0f3c3f516ae34fbecf45f4636c22acffbee765952b332c0f3d8cadb9c93f10000000000000000000000000000000011982264c8c078518cd0adb05034761224e9063654904e06fb5e5a6eeb1f45e4ff3da661f1232693b79336215dcc0cc40000000000000000000000000000000010c96c872160d2de03a16e85f2828d0cf2dd16a3389effacce46b5b5eecfea1042a77de653da5a1c0380a84c435723fd000000000000000000000000000000000a4ad2d9956bd407c555b26c192c6bf59bf89e40d9c6f9c90780bba313a39db71a73e7633397d47a3f58f61c81edee77000000000000000000000000000000000a7f912530d27a7bf74e01d8e48890cc66f72d14950554991ed1edfc504062ff6bd3cb6941bb398df9fde3cefd33fc0676618f1954730111e572937cf0c9f7b3298a11d18cd890cb419f732c766bc6210000000000000000000000000000000015bc12aa9ecf417fa5bace8d9e5dc4a418555eeddde1da8b624bf7d6e1873ec4a257d5f6dfc058a8d9b02528e699abb70000000000000000000000000000000015b41567f8c780f83342449f27094bc20a839602ae482de14b92e40017e7acac8857db48a2d27f1f1a625883b6e5255e000000000000000000000000000000000cbe79ac0718555fd8fdc38b68eec8be83b32499d2654be44888e45a2d610b0e81ae12fd56550524ad85b5a632db32ce00000000000000000000000000000000069f46b5baf4357d8010869685b3828c0dbf6e2338598c9b42dfecf0b22d803f95fca716115f74c77778d414cbcbd881fbb9f2400ed1dec7ea63d2b26bb3e9c2acf70117e3026626f6f88a07876177880000000000000000000000000000000017ada4038189c544902167be958e43ee133730e5cd329e572dae2d853b694f5ff8032bd9ab41cddd11c51e8284970f810000000000000000000000000000000013eef75e6d28deec945ddff33128c199fa52565288d63677c824b8d56a6c29eb98d34c5834e84865be35d40c1c59a40c000000000000000000000000000000000e2fb4f9c7ba6bdac1d4ff5055be609abef7fecd7923a753a704da537c0ff41951552420bd78d14cf972dc84fa3f5dd9000000000000000000000000000000000805376b814b8a59435310d49a43081dd7ea36dc7dcb40d38068ae9085b3ea9a3b2249234234cacc76724d8ef84a2eaca0170d7b7604b8951a95d49b6697e2d0cd2a41c3671d8f96e936cca911dd516d0000000000000000000000000000000002288860f2d671c84c5239313b7f6b82e31c3976e6d310e15d3bfe1c566e2ab5d86ae6ed0df02530f9f7893ba419f1870000000000000000000000000000000017365bc096e260f8dd7b189fabe10eb66923783b41fff70a149251576b3b465c13230dd0af13cde562751dacd8298335000000000000000000000000000000000fa8eb9c818df27181b45a74b333ab481dc7212e417c4e12634816f9e177064f9e1101deff26156d26bc6574db9617080000000000000000000000000000000009379598bf02222e1ec37a721b9ea31a3adc33524c6a41bc58da06caa3da3bd730659f0a80f793a0fcb9c07b43ca929c2c2afc06f19e627e9ec0edf1083823d30ac569346040965e1c92e0c15011c90b00000000000000000000000000000000136870e08ff5fabf36410629ce5c23470eafbe73a7dceb633df5c1492e39445b86ce15c22bf4c421cfd0adc6518e78c30000000000000000000000000000000010aefa3cdf1225da09b796430d096807a83eb2fd5a58db3a4bfc5e500dcfcd472fea3077f0c059620f4ff708f37c95a90000000000000000000000000000000019ee2c62ff860338af623c535979ed31c42c0d0b2f82cd56c153e80e6d92bec9ce39bc8e8f285d1efd1c1e969521dbb50000000000000000000000000000000008ed69eb0a16c8a35d507bc3a50bfc97e18143fef611263715aacf5400cb1aa285b6d2ebf2ec219d2fec477360875a03141d0ff346e46a20c2498a74f910e9bb2d5d8530afc7ba47c3525861c9e8c5920000000000000000000000000000000014abc4eec64f2611197d0c1322c3248eadb725049379e64682f2b3d7f83f7bcea11358d88f52711b3020924b6ddd84790000000000000000000000000000000009fd78c5d1d2043d83be30a88f046f5b633c6dbb11bab25fa3037bd250b6b9d9394327aae25d1939f777fea9f3df46960000000000000000000000000000000010f413640aaa16a95afba98660f9e1b03a8f3e0a7a3d7f2b971f71b5e3d09016ac2b410f97d20471f48621d5a363e9e6000000000000000000000000000000000154b5df93298a5a14a6157819e38db33ae7f2d11dfd13f7f2a92b2fd9b053fbd25f10a8c45db3026f6f583bd56eee0f1d688a1aca2a837e0a353039294a9988a7111ac134a6a8a68e4f881e7486025c000000000000000000000000000000000f1893df99adeff5e4042c4c5e8557e53f7c34efcb2a7953d5347f81d2f4a75ca0273a3845f54e795ac1c1f8ae7240dc0000000000000000000000000000000004856b05d58898be6aba07fcffe487dd895144c7ac8fa8bb1a37c61e73bcd062ff541d510e24c5bf005c8351d3ddf61c00000000000000000000000000000000178b22c2c698dbc4929b119474a741ef44d6275fff5ba058d9debe9475e71398e464aa14a6712c5deeb5010d1c7758ba0000000000000000000000000000000005ad09389c35c45f349e6dcaf1cdb3b63648b3df427ea0c2a371f45634635f9253957ba6987df4aca6cba4cd472308a31b59c33ff02791031e7a9424c781ff17a209d132af06f5b825df363fbd902cd4",
+ "Expected": "000000000000000000000000000000001090d83d501373cf07c75effb1c85852019b39eb0d77226823aa3c1054d4e408e82fbf0f4420a30144c611fbb856748c00000000000000000000000000000000120a1e3795f6d5c4ed5b886256c611bdd209677f8324b7091cdd7cab11788b1c0f780e8b4c38b84d7c2ea528123d4783000000000000000000000000000000000d250df34d906ed421eec2a78c2ff4ed4eedb717358d7ca879d58ff5b4d2d72521082dba6ac5d10859125e32c2c8b490000000000000000000000000000000000476adaed9d80cb1545be505496222dba1f0ea85d38d5bece0663461e0e9d47abbefe95303c926db008d08b8aa162e27",
+ "Name": "matter_g2_multiexp_16",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e1a9066289392b0b0b8f0986366c2975463c9cbe7a74f2eafcb3b8b6d4ee3226ea5886aaae374341bc76b53b165e22a000000000000000000000000000000001557cd01b61b5f2361f6b558a87c67f2778e11c21734b7ed25f72a88cc62cbed396d583de4c2190ae6bbfd096c33bf73000000000000000000000000000000000eab68305118d7e7076043719ac1e13ecda4497df2cf392d6aae4b7753f114d30aae3e8535742947636901feac4b620a0000000000000000000000000000000002cfe5014446556b82d60adf874cef25e58eabd035deb4717c93bf0361f37a4a67aab70b95627326bd97f111efeed57f58fef5bc887b7caf72f2a533fe1455ae523841bd49b4adf16cfe87edc6f573eb000000000000000000000000000000000c8fa30f6055357f6b697f2115203428b8005ad03286d2b3c805bf3d4dbb461c30e6ee8b0973ef41f884b91e857c53500000000000000000000000000000000005e1c785feb4c4fb7e960233d431d51a4fe471f10321251d018a950374d2a686d52ee8cdd855a29e770bdc1bc565f471000000000000000000000000000000001158d31faab483832d39f5431a5d8aeb952d6a63b82ec019f235b5b2e5580df8cd91b46cd53d4a90b9db354b38c5a1710000000000000000000000000000000004a389b09be6fb7ffd14d7f3359b17991e93d92a1c0b9a89faceaf71f5ce77a1875aaeb7a0ec3b2dfb363c47dfc9875273b243b83d44158a66eb6d31e7c4ae1f4b3ddbba81b2cf9a654ca7c4ea2147ad0000000000000000000000000000000010587118c5f90b545ee707466ea2c5f378e6795c260235cdf9876aed8bd753aac592ee05e23882ee77f4a13bff97f5940000000000000000000000000000000000a0344aed244b90c4fb9ac337edb01429e09f951062b06025a5212300f5471a95f28e09bbc715417a6d98423b518c3a00000000000000000000000000000000128457cf374e5b8864b8241f476da093f48553d609a5f30c0f0f235ecf7127231237b6c8802f2904a8304c7c237842620000000000000000000000000000000004d55ff04eb09b33ebfe90f2a0966a1b59cc224215c0359a4ff0c09e60f9fe7ad8342868184d8cfcaa1d8c28328864241ea87af09f6e62111c48993c408efd3db9ebe218ac68f61a461ad9ec1306873d0000000000000000000000000000000019e6992c3da47715bf379a668a15668508e7ad27bac647490be8e82759b9b79c996735aa1bfdc3cef217750e4ed36fce000000000000000000000000000000000828f782c5bd4f2de3570a4930db2c020f75f93adc98aa0e48449d29c7a3b0d5c349963d956bab7f985ba6ffe59c90ec00000000000000000000000000000000062c7a730d286e895c57b75907713ebf1d20650b5e621f270f1d22a2ca480d022346def4102a62eebe867210e4b6122e000000000000000000000000000000000d6c29462ad449ee6cd122e3dc00d56dd5caf17a2510e5305aecfe85626cf73adb401ec2192eb693158650893fa67412a691b9635e38a46e2469811405ef6325ae7ef88a67c1d1c5b05806da329f27e000000000000000000000000000000000098de9ab41c289a05ba5a774eafe27d91aa8272fe9f81fadefba9a0cc0e31de20f808ff454a8647c44f5aa632742af9e000000000000000000000000000000000c96019bd5cdd62df1642656f0832ac8ff6aab86f671e18c1c7023dc16b8ff54a8e3e446b19682a23b73ccb90da2fdf0000000000000000000000000000000000178e3b4366b2517d4c19fb40551be6979d46319d7040682241b046f10ab88d269dfc097ae02952d46e69cb1cf159da50000000000000000000000000000000008341bfe1e2fb999f0c3f4e79523c720edd332401f9dfdb8dddba8d1342c2c1fb20ae2fd9dda92c7bde5a0c95ad971f80d9a35f474325d0f065442805cab3beae4a186b252ebae54a567dec6695588f1000000000000000000000000000000001004d60af8c21f7c62fcba1c5c41b94fc77f64b89abcd23a218f0da8f47d2ae6879ddcde52f3e6feeae2dc7b2720577d000000000000000000000000000000000b8e8a7da87aa62ca852e2984b0f12b85052fdd03883f01f4496df0835d1cafa48818b5ff1e3cb0e9ecd66054540a0d40000000000000000000000000000000009c16854580ad8191e3e80a0afa8da759a8b2bfa7e0d556418b5c96d97e88a12fb75a91cd68c2f4336c3ed7ac99199fe00000000000000000000000000000000195ce9c562c460c7e715908991ea8b017b81561b45133427f63cdfbe8f65202bdc8e8958ab0977b3a244cfa32fb35f37c20e998acda67d406a238f16bc2b3066a6d69d2436577b8900a180e6a71b0a01000000000000000000000000000000000107292f77666064b7d80d73ea8f3b623170ef79ccc7c228b8366675a422a0cb8491586a2e4ab1a067c31396cd670a8900000000000000000000000000000000126f8136dd61d61b2a9c0f4af3ed44a3cec3ccdedc74821f341d200601a7bf0a17079c824de6cfe28467e843d0c74d2a000000000000000000000000000000000bcec8afcc7ee56b36d6d08b51f61454c8fb15ec5baee1117ed55af8fc85f68674250334f79b0fce632e75623dd173210000000000000000000000000000000016624d64660b63b70ed197f6a675911b02b0bc6f880348faa6ce4727af74127c509ce8535d8dc8db5ae2d71aa497e0756fb773cde356e2edac3afd2bf703b59161162dc1e915873ecf606dfc0e6efec5000000000000000000000000000000000f57747c20e1b3923c7e1d8bd7d877736cccc0e0829837a086d62d48cb54f323d90b57ca3339fe4b256df529bff11363000000000000000000000000000000001940327a1b319dc4212e7a553d3f49904660722c89636f6a38604d96771fa0fc71f57674b7aa710db4275822c2b89903000000000000000000000000000000001956b81bcf961d16e50c053ca07ae67cb8597138f34a9dad4d82e0e8d23a7e08b751682d588f229311bc63f9598ef448000000000000000000000000000000000208981064443e8c72987945e399b45b74e529a0bb75e99b7d6744728e5c182a6b0a10e449147bcb0b0cbe70edcdd845bffc1a58dd06752a2a77abab835d089599b4781ae51ab998ff3c5b68329068bf0000000000000000000000000000000018c35ca3a63053fec853e8fda5920b560f1be28431f2f4b08789c7a202336c8905a5ffffbf69ae4427f267b1e13288d60000000000000000000000000000000019de96be76bd93886cc486c2671b5b0d731b568638b1b830a52dd4c481b9a1fbe2b3cef14b46e25f1188ddb3c158da6e000000000000000000000000000000001813ab16a11c79eb3d3d47ae7d9a7c05401ee91eb1183266d23077ec4c0c8f3ac7188eece06876025dc3fe271d65d4ba0000000000000000000000000000000004d2a416dc874e956fd6d29a3fb96195019f4136561b4c127541ac171b5a6b229746af6d6e535a8017e64ce06709e52e57f35cfd74f62fa39f919400f4d692855a4b4e9f91920e4306ebb2e772a484f4000000000000000000000000000000000623b7a8a1c24dcc603f01589e6679c74c4ed3452894e536a4cea69e99047092acc877dd0bb395b0cb693cb1702a64a00000000000000000000000000000000013de9dc75e42f12e905d729a52f25bb1a4125f5edb435734649281bdfd41083716d0797b0a80d842c2503d09cc61162a0000000000000000000000000000000006453c06f56dbaabd4530160bcd5312b8a148dbe19fdf9f1e44b7b047a73ee9ef9d981116d00269942ef73537885eb7a00000000000000000000000000000000075376135ff3acaecc0eeea32f8dc15add57e8f0297d053ffaa0fb0a8fc4418c5b142f96b6b9ce9eee2f949c960aed682d1f3709700634653374fba5a94d69163ef616a72a63d462afd9f01c9ddba84000000000000000000000000000000000120d088fc12210c1f5f6cc3d1091563f9a37d4d0e0d2c305b479f4d7e893c4d5c8170eb164e34e4843a21c9eb193d11d00000000000000000000000000000000159de80db3b1f0ffc5fa8c93e1bd54cf8ae19cbc9018a5dfed86179cdbc976c1c312212080ab221806bbe142d496e7a7000000000000000000000000000000001103abb75a78220218cde4bc4c59ddb5fb647ff808754dda200bdf586ee9c47a09e03762bb726b085928ddcc998af3ee000000000000000000000000000000000bff4bea17eae0f2ff3e7f99bfa91e6ae8aea28f6f3fb6080eb644861defdefc26befbb7874f612edac0cecf70dfb275614ed9a08dfd406df00719d5eeacfb0a96413b608974fd0aa1d4c6176b968dc00000000000000000000000000000000012dde607a2d4452c6c060054c8adb6307743edea3ccb6ac34c275717f177f0e454d9e33d4391208198cae39d7eb6f6c00000000000000000000000000000000014cb4d8bc98060ee68a8ddbc44b83db5cb6d09f09b0d608357629251c35e44383e97058d0d68fe2df3bc47424a5dda03000000000000000000000000000000000c14fbb6c844fbf896fbd3cb3464a83aa4c6e9a7f0450ad96a07527df6f1eeeaf587f60a990bd6abe7aeaf5eb46f362d0000000000000000000000000000000001d9468774318ea711b79f16303ce86288cee312af296f1c9f607ef5f97c7d1cb48a7218775c8aef00c227ccb586286e7c1dd2e5e5f630fb1d07e8934dd3ab029917e7775e401c0bcf7e1fd83aef728400000000000000000000000000000000181e7f8d0ec7a4a7858bc96b61484c24dbb9dfeb3746fd3a231a8e442369e3e83516ee6043b1c06e7e2043dc86f6c75e00000000000000000000000000000000184c1d667c0ece59f18fd2eeafc66f1ed530b7d5f4560a6c886429caa13255c63dea01c3e357e3408af58a39420a8b28000000000000000000000000000000000a8475ea694cf607246a1c50064cf90cbe50ad5cf8006934a1fdf1621ba38d20e70860a2b5aecc05acc60943224cadb60000000000000000000000000000000008afa03c2df8e83fb64523c57d0daa7cfbb7af6a4bf2960ebc64515a61a659b2c37ee661050cd538fa00cb34746a371b64e9d16cb61f2bcdef30cf544d97e078fccb999b96a1da0eeaa0bf232f01995f0000000000000000000000000000000008b33a297c8f86f1e9d7166f9e905283c8e1581e582b879caf48585d0bca3608fe46d8d9f6e7c90855aee9d92283d7a40000000000000000000000000000000016962410d6b4b6f91437617e84bfaaba49de0369b8748d2e2dacb63b421e0d7de4514e7fd3e0dcbcfba8baa4915610d0000000000000000000000000000000000efdab72953b870d0e113efa7c183d99aefc100ce59791aabc72423aff70a5b74c577c06ca94bfd6a7722199b4bc22660000000000000000000000000000000013b18e31700987dfa4344384f9b41e72afe92c39bc961333cad3e7d0a5efd3842a5e849cff5655c4673f720fd0127dca35bca9082d66c06761f702dd439faa4957caa70ce0343268787f41a2f4bc0cbf0000000000000000000000000000000008b86f70c8d8b03b0e9a8975776d7fb0d08f95eded0a0124551d363c2df57124e0e89bd45ddd1cc75c258a4ae2f87916000000000000000000000000000000001120eef9eaff7c308b629deafb060d2c12b20b57562007fa810a2191d99fabe9c7d3c364caec1724665ef556de66b57e0000000000000000000000000000000007698bbef6dcea67a2c643342ab2a0f830c329fb6244d4a98512daa8a3c9d808cd2acc0cebbe3da920053ad73eb7cdc7000000000000000000000000000000001155b6beb28fd88d252c6b407bb9f55d22103257287ce77353bea580c90173b5c3d49080b319ea28817d67c52bead96f7980eac6c8db86ef83748d10b210835e53baf8cc9f607915df272b6e28ac6b2800000000000000000000000000000000142b28509d72f9e3be9ee916827fc1a8dfc4ef7ae2b72eebad5db605fdb2dfa4492b50cc3e472df1b52baa6e2b0eff5500000000000000000000000000000000134d6821088ce4a8b42383d5a43a32bb0cdc96c85f304a2601292670633d5e231b9dc479d199829a9ba9f39c162318d5000000000000000000000000000000000636da344fcb0fe50ff3e22f8591418f64cfc722b2860b4a5047f973f42e4cefb93c2f8eb8a14b4d150758ecbf3cf712000000000000000000000000000000000e6fd06d5dca702cc9f199f7583add86c82f7b530d4dfb9faec36dbb669cf7c1cd1260c7e4f3026824eeb5b979e9fdaea256ebae4b204b3888d7bd244bbff26431ab5890098870f13800bb3be3e842ca",
+ "Expected": "000000000000000000000000000000001684f447f8929ec0187811f66e985f0014eba46eaa87de2d4ac2347d10c0550e4044ec7792d9f315c50081dc2097ebdb000000000000000000000000000000000ee0c46efe930bc98f39dee8cc6a792744e84de4fadec035d25ee8ba82e1c53264d0885a1fb05b2b8dc9c6a1846c28320000000000000000000000000000000003a5ef98843099235a2ad9522c9cfce1908bef77b45794e7df9eb38a4854460031829e947a118e8160365fbec3725b85000000000000000000000000000000000dd205e195abef6a4cfa7da66f022a418235e1a1b2fefa6bd3ddf8a3851d8ca8c27652bf87ac644cd189ae55e3cc7808",
+ "Name": "matter_g2_multiexp_17",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000064698182f90c20ed6f6da7248cea32a291f901876a900d344ce4dc1b07822b480519cb8d891b5ee4f33b4efd90742cb000000000000000000000000000000000e7e9d2e79ec4b07015baf69a283f6a4abc8d7c1699f3356fdad6ea9b1c70e41e73bc14e500634d73749f9900eeb65f5000000000000000000000000000000000002ddbf40619ea5123c100e2d6553213e37883fb34f0f0f2124795dd971892d5c9051cd4aa78b9d20f196301ca9bb4d0000000000000000000000000000000017a07b32fbffdbf7a80f0437eac1ec5fff5a68f3b053482f034064992158b604bc34489dfd41a24ffba806ccb871fff15805f2e8013007c4f6d8abf441728eda8d742ea2f1df545f85d092f50ca8275c0000000000000000000000000000000018b4de9c04fde8b708408efb3aa7f24b5f7bcec14e7d06fd5a5b36bab528e5adc0bbb1e378a5ff6fcbc95aea530ffc6a0000000000000000000000000000000010da98267770a47e5ed14ffb3dbcf537dd14ae5eb79522c772a7a2833be214690db0b4e86621de1842d88018fc0f348400000000000000000000000000000000135548e2eec9ae7c3d23618d8286db13a5a628fee04fb6ec9da980f3a46838899cf965c1cc6f562e71d5b5c7428cabc8000000000000000000000000000000001669fcee7804df9b7bef32e2ffeaf285e8501842efe87c9e827fce872dffbf92255d3c3a2fb5c382ab7aec0bba1ae0e5502d777b25f3112ba2264022e2f28dfb6e5d5239ba097e9d815928be44b6a62a0000000000000000000000000000000010ed20c069bb300a27571adabd239e70b767af90b91c4d0e93d88278a6da47b7c12fcfaf62ac0a7b9966968cc9f3770b0000000000000000000000000000000017273eddc25cf41f2d7734a3866711e83d4f2823ee6a036942799f837d5ceff10dd6022ea25e3c1e28c7b14ed8f4e7c5000000000000000000000000000000000f201f314f66f6b2c6e1365c0fac7b187d31bc45b5edaef5243b5488e26581dee24de4a5fe493bee44165cc31d8d72ef0000000000000000000000000000000009dfbdd86633edfacad6b78d292141a1e653a1bfd8c48a96b2f6bf8271ed6033c0511628caf2ef258eb64cc8b63d8e5be7d64b471cca34ab0c91f61ff26719c7186dfcdef13895d37ead407873736a740000000000000000000000000000000005c4a4a5ffcb4a39c8809821ff275360ff937070cb97a791cc9ec45f429256a6d2d6127248b6ab0b6c71c30c4fe84ff20000000000000000000000000000000019fa60f481c5be953c9c7dc86903a89af0ca2b4205be3a00d793d6de7103852e147ebc7d983c6d6e8cd99e681241ad440000000000000000000000000000000015b3b2eeb0f81ff8a2624e2ff2396bc69feffeef62b1b6a1e73ca4b9e60506c2950fdd23a37cf56387b8794449d3237f0000000000000000000000000000000017021a69ceba3446dad9fcfd8cbe5b89b61372f57d43a8d2e2c8f4534bef6b91408409dfda9438f24526f7e6bf1f4240e5723630020fdb48e44adda735943c91ad7d1e12f3c32d823833eacfcc8b02ba0000000000000000000000000000000007c8f07f22a3412fb4638cb704751959cda4e42e4612edaf5b1f22c8f9ea314508353445114bab6c07ccbb4b0d0bfa6b00000000000000000000000000000000062d087155c8722d0102c8e5084f95f5f58ed626d48197297d21d2108ee05f70f16d595ef73e8e1207a3c0b013fe16710000000000000000000000000000000003b6652934f3acd4c91c6c521c2476bcd2594a939ff2e7ebcbb0f451fcf0a656a518dbd4f36f165f9b2f58054e9f778f000000000000000000000000000000000bbf21158227e0ad5461de9ad8bd580f9e65327dd4e23f1ad55618f6b0aec45aa6076fa88557953ad15d385a074bc7d96e9e37bd811b76133c12268d325ebbd6656e7ed718cd777458867dc98b1b3bc50000000000000000000000000000000019e336d4d342f110eeeba9773b8e351f26bb56361c77fbf12fd9fc218fd075ae38b95f4a8a5ef830fc2cd92558b1711e000000000000000000000000000000000a112725046ca3b6cc43207e6b36f38d96ff98dfe3444d67ee3f4b0208f3b8543768dc9989f936637d7819e7dc5740fd000000000000000000000000000000000527682076572d8cca15e47a2faf62b129baad29afed22d32ea47983a8d0b138653c1353bfc6fbf9fdbec2efe36700f90000000000000000000000000000000007e3c5aff373b5154ae66f978fcd66d09cbebc7e0c96b4a4cf23c4fa5f2fa655410c7f1ce597a3f5f155017720f7c50f7d46516db284a3938e672ad3c6bd40313d77c5d643ffcc59e3f55ad983cdc0ed000000000000000000000000000000001865c265ed4606ed16056c0b28f953119751d7272bb33b9865eed312ba23b32d01733ad5446cea5873c2bbe37fdfce7e0000000000000000000000000000000007018aca1e7ac211921cab1cc6bb18874d2f39f00d916b8f3d46a088a378f3c9b49ab8a296d0aa21608f11b144a0c687000000000000000000000000000000000210561c0bbe5a9f4b2237e5bdf88bcd73326d395277deb2a883526978df90792993e6ee520c9d5ec0a6f7ef5c6b3542000000000000000000000000000000000cdd344124b7b5da556f64ac5d651a6f9b74427fd712007310d720f3236724e2284aab812d739a87f3a1bfe8737dcee7586cf63c5e52b44aaa79cdda6dd6fa92c6fce11d867b2ff5a04c9e44e0b3930000000000000000000000000000000000024494aab30849df790185a4f939954b724c387c9a366fbe833b628577654174f705d05e7d7dbcd29b8873aecd55df0b000000000000000000000000000000000863054fe3e4838d2caec7103e3d0453e86a17fff0dfdb84dd819f31756032e9e97b7be89b636e5e0b642718f6da217b0000000000000000000000000000000015c8bb4fcb6d9cf941b722136d8d76d847fd6d5c643f4c0049c9746e76e49726fd463ce7899f4df66d04e5d48e523e6a000000000000000000000000000000000f101bea4e1bf610d2782ede91da95eb2b0be9ce60485465b9e94cbb9530b416c4394862f0ba7ee8067bb48e94c07c53efaac96bc5f686d6b952e7082236622b737fda0dd3900bec71654bdebc8ba2e40000000000000000000000000000000002dd11f4dacf3d9c46579182df1c1c45a364a8dc1eb7aa7d54d0141306f1c23bed85235783a22b8e6dc4adc35f9193ab0000000000000000000000000000000010d1c642fce533039e98712bdfcda86eaa62d2d69b861ec4fd835488732fcea414cfb6f3f8414152f9d5398c73a74fd2000000000000000000000000000000000c6759b75b1e3fe86c00fa124d09c5b7438ad61fd1bb71695743ed7793f39b7a0fc99b055201ac1e3aa07ccec61b24a80000000000000000000000000000000017580c9341789484fb31386eccc9c344539a09f1c4421dd124b1a0ce61f2d0528942f7fe8df67c6b2bbf782996def47b39d6045573dafd09ab2a0d8ab6e97b0ade43bd79d820749ecf19cf7d99792ca8000000000000000000000000000000000d9c48a111c8c74bce8cd78d127999531e46a411b2f0be3507226766bc8abd088638a237674ac62e0fb7dd4a86d09b79000000000000000000000000000000000073675bb81e2bfe6adb5cd929e0b7280f5d60b3dee7f797d65ffbefc2c2944a9c7207648bb096f13292ff4440c3f03f00000000000000000000000000000000024d2e0d5ba1a804520c72331fa23a2a326d461177fa527473240dda130f4ef893870e893e1dbf7c5dbb0178dcd29b3b0000000000000000000000000000000002a4c9487485ec33f8fb347d246ab0d41b883bec30d2a5e88cccafa676569f25ffd8341cdf6c09f68afae442a574f3334c4a2ff4ce4b633ec8fe0bfea42ccc329b7d3fbce96c26989b3c7a391c9e806a000000000000000000000000000000000c1965a745e42853b4d54739b2dc507d68d80b330360a4020e4412ba5422daaae313fb9597c98575c66ccf351e62a527000000000000000000000000000000000844439e6f08a411e61d37b5b2b07921049432e1833e839b00d6cc11227dfc8770ad9ca06037043668fe7ce3bf3ce84200000000000000000000000000000000152ad6fabde2e0310c978404a5244209a9363cab1f3ac9f71339cdad6d40c84f8e5a8a196283b581d0209ce90e1e3c6c0000000000000000000000000000000010eb6af62c7dba122b0e24e8326dc906370bcb4ba791c47630f05f657a228c20e010c065b93537ec84fa14a756b199789af09ef1f27cb83189e4e13f3801c08d3a2adc8b5f88717954ee84499defc0c40000000000000000000000000000000001febb2cf2d664e4a277cbf08fc1fbacd05db415a12329f7be551ed56d67f0b5dcc917d1b02951657bff3a26bd8c178d000000000000000000000000000000000018af160555292b2f7ce27112c1d60038b564f5427d62604387de97dcf48e4473107f91936b5e8008065a1537f7ca340000000000000000000000000000000016bbad2a7f5451098294a7cab2fe10d206741a99b128dde5eade581d02ca849bab3662fc3400fbe055dd93a418aecf0b000000000000000000000000000000000b1e9586cc1b357da6e58621ce09288e62a79517144f6c6b867359251baad6d40217578d49c1501f23206b125282bdf4c72c1dc1efefb775a1bda754ff17389a6b6b6bb25e22697847d24a117eb8974b000000000000000000000000000000000b88892250c848e7bc7bb7e42cfe1048a1f61dc546929211846f49501ad8c7c8817f5b5b99ed092d5a2236d59d9c8eaf0000000000000000000000000000000011680c6549f6b7d9d187a6409d40cc26554df654083f1e8a47dde826149d68da756adfb1b65bbd219f79a10d8454e881000000000000000000000000000000000f9596121dad98bf7acb3fd65fe7e0bdc8924e2390341c11d9cc9cbb0517f988ff79a5e1d60bd89449b5f042f0d0b0c30000000000000000000000000000000008982832ef53bafc23ea817be378532b95b5872217093e7c7c2f4512d03a9c9a6dbb7950563a520781c7ae213fc82897b4a0c7c2e611a24c722975ae882dcb4b45e6f6b41cfc87e8c766beefd5b10bfd000000000000000000000000000000000ea5bc2f8bc2b4088d1fed7090ba389577b11a3ee0775cb3f0657ab5b07a6709d3a18fa5fc33554dea235c60baae4bb100000000000000000000000000000000196b6259b06a4c91a0bb0adecea134c8609cf983c2c87158a69c9de3b6768510fc56543a84d1266dda78d90c3b0516ac000000000000000000000000000000000d0222d8ef278cd0d85dc8765fa7c4256394a5ef61f91301af6c7422b4cb17889224c75ccecd2df3ddc9bac98b493863000000000000000000000000000000000548809ce26cd498816ef1222d062b1ebb7313a07e99e3aad1431f984e9b8ecfd43357ea57da7e0c6c011c5d5400f7ba986d48aa5b00fc16c36dcad061d10937b55ec4deee63cc2841b7ebab84f910d2000000000000000000000000000000000b95455351fbce6f73de0345a195f91bf96abee361908cea6c4dcde72048a13a9a23991a75b9c988ba0afd9491d15696000000000000000000000000000000000305f29b05fed06ffab484cb065d4852eb323fda8c9b7c0a78843bd7143effa95cbe5e50c1a0c3a9675bb5381709b6550000000000000000000000000000000016ebcb25f1b8e8d7a8f7131455ed2be084bdcce40034e7ef24a47fc29e447f912c20c7c9910e025aab975cd2c8cf1a96000000000000000000000000000000000d84a5de7a5fd8592f6cc2bc7c3d93c06e26185787856c922d95eeee345ddfb7cbbb60b6d992c5ea4dfb33101f2ef1dc979d4df836daac0960fbbb8919d2f90c3457cc987153def711d6e8a12fb14363000000000000000000000000000000001377d654f80e933c4598aba1f637d1e37d66a96680c3a89a762f412e187817ec08f0ae897b08206a73f1a423b742261900000000000000000000000000000000014b71954b9bc22ac22cb2d7d7f373c3238c923205b223cce6c219175df2bb6d7258ae46d6cdb019311bd386275499fb000000000000000000000000000000000a08ef83b67bc972a67b9174d0e5b1536af882d505d03464c9a97f68061aa319d612de9db84e1e7b12fc3015fc2973b20000000000000000000000000000000005f716d0ffc30005e4a744092704a9e29f58fb06bf7d8d6fdbb95a4c0eeb5c39452cf662721ea3e0bcc67f25931a109425ae495ba75cdd0bfe200ee24d813e1aa93c100ce861c9ed7fa5537e11778990",
+ "Expected": "000000000000000000000000000000000c53f0ca8901f4751be4a478088b30dce70b9ecc382455049df9ce108eb0a8d2696bb325fe9ebfd7d967ab5b9b2c2bd800000000000000000000000000000000033460babd2984a5d8b7002409349972f518364e92648927e223d7a3b648e952482c06cc713bdc29ab83f2646e9398510000000000000000000000000000000007cb9dfe603dc070151cc477ec5bb5a2a949062e8442399597c5eff8f1decff538cd0aef1384256dec73746e63a6c66c0000000000000000000000000000000016b56ee9b21c533b9c464178d14ba5c92a90e6a54c3ed319f487c2082b1ce1d0ff81131a5fb3dd7d13e0fc1d9ad9e4a1",
+ "Name": "matter_g2_multiexp_18",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000104e0b91821c59290be48b97936458af89078b176b5585ca9a79070c7050309b01df4b0bcd84f137f58304d90599212f0000000000000000000000000000000013b00ece925fd17a8effc43e21d982553ab2764b13defaae5e5419cb9a23ca7436cfc44088c2aded63785e4f07b6e186000000000000000000000000000000000267cdd42febf0706675b60af8c0953582ced84dd5ae870815654cffa46eb14b747fb8fbb3b014e59c929da49c6908050000000000000000000000000000000011c5384d7c3e0f4fd66ba4b4c2ab60f6f78f9930e1fed233263dad25294814d9e2aaba6388ee9f924e2a323693b6e43bbb2a329761a3d6a2e4d9d63d7bbf7fc6fd321ec0344cc4d7d1b6565c475ee9670000000000000000000000000000000018158ad70994584e6f2443b8b96c1e4772a00fa0bf74865c76000eae470eb02cff627579126cc465046d4e088782557b000000000000000000000000000000000d72979d455733756a0849baa8afd79e18960f3f6dc9676c33d1663961617831f3266015cb998fff28b78300c87c2a73000000000000000000000000000000000056192c20cbcbde6099256a8f40c78a32d3fd212fe9c511951c7523a3559f60662e070f5b5e5f87b1686be0bf6cc890000000000000000000000000000000000c7b7e8ab7486012d95af5b2474ce15db612bfe1508852b8d99f4402d0e4f075ba056c19df3caa3a93bb4db89443096143cbc3dd7ec63ac63618a9e5da1f9c3fb952c6fc6972dfec6caf1a415a0aa79e00000000000000000000000000000000005a2741902dab47e8d38992180a9670faf56d1849dbeaa75b2b4ded93ee5494184c8658232e9131a8b08ac9b5460bd400000000000000000000000000000000189077d5130b3a4d7d4c3074633fb12739f95b8b6ccb082dfa61d845a389e6ca7aff835fa0f194dc349e1584b3141507000000000000000000000000000000000f226324f242cbc5f616c4a897f82bc5503ab1963ca38f30070c7c9916ef6bef5caa7e2e26b3f9fe68a1d59f19a9831d000000000000000000000000000000000a999bdfa10e4838ca69694272b0187f7d0198d6db0fd85eae688424fb09baa165c623dc6da567fe034d7cf9f9a0087e733a3a84eddaf3af8c5009646a899f6ae8cf233f535e360e29e2952088ebd7b6000000000000000000000000000000000fe85d976befdae8fd0ad33a4404415304afad1c5698b91bdc15abb4f268807c906410a6ca827320f5271c8fd4c8d6fe000000000000000000000000000000000cbff7963daa20c1d20717bcd47b872b3ecd5f38de1a467ef50936f13d6aebd978116a736cb6c5d676c6a9525bb0b7fc000000000000000000000000000000000c3d20ba17a21bbfe873d88e9221571f1bae7f02f35b8e677c9c42907673d765150c737f0011fdbaf4faa883b0dbf0280000000000000000000000000000000013482c68a5e1084faf12e8aec92cd9f0692b173556ac8ac3c7519beb4bd75f847f41ab9432421c631b14c885c001dce25112b5912aa3cba657d8de3dc8138fec92b391d5f988b82e19f16fe52fafea71000000000000000000000000000000000f9091a0df2c989e12a844c447287b704803d1532a3ecbcc890e6f6a885a54b969c53323c105b3d14d12f2cf766b8ac8000000000000000000000000000000000e54f3a9def8b3a9f972726e606195849584b7197ab70a28cf5644cde15e70bb6e3044042b649825adaf5e37c2d5e614000000000000000000000000000000000cae412d8a3ee3c5af38d7a65bdf2440d9cc2d6348dce0791f4a7e71ac483d7487b6c789be0a401777de3f57ec65de820000000000000000000000000000000014df09fd2ff406707004f6afa366d06bcf8bf18f5fc4b444b07c98b3f358247c6056a6337f5b53c35db45904797fb4455683e0b33b5463bc71283f0625269b2b33ead69c1eb7b23a996c31c514d06937000000000000000000000000000000000a8aa422e1d58fccc84615f9ca4a4743cf5efe3a1066c9819f05042100bb8784fcceffc8b3a739f549b42f34d62629e7000000000000000000000000000000000c737cf78b10e82fc0cc9823891f1a5f1e9229d61e8f369c589512d01e5180246db46e4f09e811464c6e1ad930226d390000000000000000000000000000000016017354434899e2285da6ff4b27fbaab633d962197d2ff4fa5f688c4a85e1817434cbef13a6b018df4e359d7b9ab7cf0000000000000000000000000000000001433c364428ac69ce4f5678aadfed4e6d076241519310686de01572da5cf78af4a98b3502519beb0dcf04b748d08cac5bcc597c5ed7f79173942a0250e618c93cd0917b37b5f354d63a2c02a576080c0000000000000000000000000000000001f8b803f3f76aee9825a9a960cd2f9e8aa931568b32be6169036683b4e6d8c4abba6bb73b137c7c6d6b6ea92f2023ab000000000000000000000000000000000fe9edeab60bb55990ad2c85c8fc9341e81de54324652c08c615a745813f08153bab3849dbeffcf4073f087f7c0cf0f6000000000000000000000000000000001955289b1210fa31542bd89f95188d60751b32e8d54f1d4d280975850e57db7b151b872bd431c528c22fb89c9b8784af00000000000000000000000000000000079c8a56c72adb9fc9baa503db394635abb10264dd43c60f2c82d041d43240321ac1028688d92c4696395d8840d52f15f2613a8e50fbc6683ecdd7c7fd38b4caa8e5dc9778909fc8680a58b16ebf40da0000000000000000000000000000000000b0fd79e62c6129fa115d821b8f2a58a4564f5ccbb14088f59d5e6a17a64e803f32bf8e5a415aac4d6491612d95ee8f00000000000000000000000000000000008d837b6c70468e1e10f6b979b7c0694d65942aac48b5baa829c191579186314ea35fe440e6d843fded02b95f9816890000000000000000000000000000000015a05bbc4607b113b37dc0b4b8add23736e0f1bb1e48aabc15500fa6941b17153918d256b6442687a432dd9ca9a198c70000000000000000000000000000000003546953d97306266bdd359d4daa939e05c0466691de59d2dbe3584e2ebfd9a9e1516cdc9cb643c5d31731835dfb07c657a747bc919991ef9b7b10388bf3f301fd910f807ccd31e322be46580a71b7c60000000000000000000000000000000009a4366299290c3c6651b22865fb22cc972a05ca5981f5682574851e41096d531e375e981c4e1b1cbfebbc70a41bb6ad00000000000000000000000000000000001e6fe2097fca2afb8385a3100dbd5ee1b7ae972e06ef9f5e34eb9fbdc65455e1c822299e06a9dd5a3f71a0c1efd44a0000000000000000000000000000000005ad2ffa8861848c46722a7924ece68580fe44e03157c982b7133361e974b59dab7b75358fe498fcde9f68b5b99f23e0000000000000000000000000000000000adac33e0b7e6740c980a4f297917fc4fc13f53a71909f2eecd0067656c6f82c3b371cc638509151bf937f8257aa415d86ba09829f4bbb383e2e131d554c42edf1065022975655c07df2b3445a3e6cbb000000000000000000000000000000001462d509503d2c33829c3fb5380199b79b970c2ae7f944e54a6d0f0deab3571976916cfc311ea6ce6128c467665fbbd10000000000000000000000000000000017f6fe356cb0dd5bddd489c26669f0f365260bb48a5f862e9bfb778a7ff5392938b905759718d050f7d93f107236cc75000000000000000000000000000000000d9b3ca93c5133cabf3d3daa565bc6b51e63b7e37f68f3bcc43b9b3ee7db15f8bb33052eb7e332ae3e9ffafb17cb77d60000000000000000000000000000000017d6b898d9799385990c9dcc3f72ed93333486b98349ef106a230a71d768b75cf56cd946f5952075bc41f26dca9c83c003fd5e91f590fbe171aa3f006617b20ad645626c970c2351e048b2ac3773213600000000000000000000000000000000158e5e008796c10f6050826c29523864d06e68977cdc95d281a8606924aeed0b475ab152bec5bfca8e0ec53691b307f50000000000000000000000000000000006fe8e75328c067546eaba93f4be2b15513bae4a3458112c3ffa457d15c23636816fb469f071889380f31870d713e949000000000000000000000000000000000b9b21cd58f8742ed094e9b770182f6f3f855204d869e53c02d0c242a133e957c53c9fabc827d6379b39541170be313000000000000000000000000000000000014eaae1f0789f0b1e8ad3b452b4ed3ff87bed49ffedd13c8c35c35668c33537b63050c06a5bf3d88d516cddac13b4c935ee16785c004dd2a01920c52d3244e2160fec2d17a519974d4331527cc627910000000000000000000000000000000019f976b3584ffc188424614fd287eb79f060c55e9b3dd2f3eb99760a7cb5b70e2b62a0895b05e7cce2e390853fed61b3000000000000000000000000000000001117181241fead3865eba4804ec2c14f571aef5351d5bce29399113d007cd4e9c262af1c77daf9183346153e562864b2000000000000000000000000000000000f823f71035a4870be2ef20bc94e97d74d18c0a1be9895fb27c54df1f663df6f9e6e45ea5fe4502143a84c05e517b02b00000000000000000000000000000000141250f392fabd4566e0cd3a472a4b2971a432a3a5e1d9c924866c7a9516322bfa691e9dccdd5ef14c561bca6dd70ba204a6d6e29336015d99e107cd312e300bd54f815c785f6008c47c99fa008452700000000000000000000000000000000014d6827b9bc782863491bc7c544263f58dc04c18e08a87ca2fbb5799c4aa70bc039416a85dbba67dd83bcc27b70748670000000000000000000000000000000016c2816e93ea9d4bd6e42a9720cb89d637d88e00074da3300c6409be98a03403e9ac15f83167cdeb13800ad174ac47f10000000000000000000000000000000002aebc0116a62f93a6e86c7fce86745618e08f4aa9cebca7b520e9176bcdf1521cb2bf7eca7f7af9487fdc82dce76bb50000000000000000000000000000000010684e3254207c4ccdd49e4775198df981afcf7d9f89b894e204c5dd84ef42b89fe3e2f6b9278470e6cde4d3f4abb3b003f9cd3873dc6243748e16e4806f8eaa339edcfdbf4408a8e41a3df80c9816210000000000000000000000000000000010ab1d5494509060c9784b4744a0572a9466d6c374524a6d338ea12ac5ad89519217c462c3487e398325439311bea86400000000000000000000000000000000197568cb53ce03f00aeb04278f355da862be757366dad14ca6d30b3a537df9855a1196010773768a91cb4bb664a34f0f0000000000000000000000000000000001fee249315794d30eaf929f44b99e07927194c6015ff34a4530698d7d68239240c9cc48530d52ea06218a826a655cce000000000000000000000000000000000645b5d701bf3422228576467120935f014c754dd68bb3555b50aff5ca04001a26298982c97a64469aeac3432784efca34135a2e7853c74725bdaee1ceadead7b4c7d729650df6544bd525c05c94234200000000000000000000000000000000113e17730f8dd7258157085c30cd9d1950a26c848b55e3a8a55865eb567edecfb09f32ba27fb3e2096ea00c30f31ced8000000000000000000000000000000000076db9ccf8df9530b64cd43ef7b496d1f432885062406028901bbfc5882fd12533f84eb12aa2ce8b7adf9dd980db0870000000000000000000000000000000015e487de49f1e494ce9907cf0ed31fb0a159c5290538ad969b2c8a504986dc9cccf7c74a61f622154e928aa2dd689c0800000000000000000000000000000000195e887083a98fe3f50a9ff4b342e004398cdfee55c4b02a4db0f65a77d3c0b142a45201674726c96d5f79f8604d61860033fdcb731830951dc3c4b33f06310eca51762cb7279039b3d7d9ace93c5f2a000000000000000000000000000000000d80c7e50973205585b20a068c64957cf4572eea40e32ffa8b759c38c6ad6f4468421f2fd6a6f5da1b0d008f625b3e6600000000000000000000000000000000009242dc1de055aea82b3b917f88b6232c550c3aff41241a7e54caab4c234d29b5d8138968846f7c754d73ab3b4e7913000000000000000000000000000000001188c31a9d8359d737576f4ce7a7900314aca0eb3b51baeccfdc9245bffec49143a11b3331f9126b01de0c307aa4e44400000000000000000000000000000000104ef4835124fa6b30dd551653aca25db5a544af6782cd0b1e7d26178253e0e33cda77428fc1dbcfe6114a758cab5c814c8112ebfe12bf44e84796e8b0cd03a93d2164d6edf1f06a5c520330a177da87",
+ "Expected": "000000000000000000000000000000000e79d18633c18ac818786bba87d09c9bb1571e179d8769f8fb82e2e2b7a6a8695c1f4f06deebcb84524e8facdcb49d0500000000000000000000000000000000149d0231fb030a1bec170decd307c10e72cf1cca55c8a1b67aa94ce61e4c7d2ddfd0b8e71598e1abb054355dbcac1528000000000000000000000000000000000090f5be784dbafb0a8aab1516c773720341de6176017e0fb43a275d60de54c1189144956d4876d989232b362b90851c0000000000000000000000000000000019dba28eaa6706361f285b3abebef68f764204c74ee93ea011db01c19591ddc6f98799fb3026c3c223effe4489a7c676",
+ "Name": "matter_g2_multiexp_19",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018a6a982acce5693e632901f3136eded40071e8c7caa7887f302c32621c5bcf9478991ca519978b52f8f69415c0d070b0000000000000000000000000000000013420ab920c8ecad5b2f9aaf9b0074c2386b0b08c81923558770d4c4a6b206a865af8322e9755706cd5e595bf0ffe564000000000000000000000000000000000c0e5bf5465d564e3ce86d6b742ca687448e6952439b1ff44b86ee6461464e07f8039e8ae7a301c6caee7eb99e38fab10000000000000000000000000000000015eb8751b750af62f57971e88b436658758bd5712f98861fa07328d2b11e8725fb55a2a00252e0be06b0c73aac0f7b8cdbb32a4fd8b9dc58a382a7e436e23f49a134915372553eee8c605436221acc80000000000000000000000000000000001328927910ab502e573188271108706152f562b1d5f6ec074f8f9ec5eaecc6cd5e8284a060b65d26463d22c8290ea4ca0000000000000000000000000000000005a1fcc348122350981dd5090c865a2aeb851ba8b6e0443c32f48b157ba673ae5652a70390888b3458afe6fe975321700000000000000000000000000000000019edc749a9799c8d3df75d4024791943a8fa02ba0cac90b6819f0bc42687b044457bc7cc6073506e8fc19af37f224624000000000000000000000000000000000fff20fb2b554b63758963c1583b996ad450cfbd5ca9952e38f38a8994809096086ed86311f7d73a0a5898ac261ce09e57df9664d3e17d9d46a886efde4e37e38859893113558843bc019699eeed8ec00000000000000000000000000000000002a7005dd32bddf1031f27c2ab999604c048a37c39734db48a30baa86c61ef626cf82084651ae9ba8a265333060a408d000000000000000000000000000000000421bf913a25108b8f520b2becc6f8064029dc046d0d5effbef31f0af59eee71cfce83fec8dda7983d50c6d5cbc8329a0000000000000000000000000000000016c75708f1dbfbeae3b06e5e9a7fb676c27100b99deece14d979b32a9c3cde6e9e96c8560a00aafbe6e7decc84e7e2780000000000000000000000000000000000ce23c27b5128bcffa424fd1d181d21b06b77bd6549ca5eba9a28cf18bb9a979270f6a5807c640dde57a0cd4f3af8cbe2b433b7a95c26e598002cc00b7904816d59baaba79bae7c6a7c26dcc48a487e000000000000000000000000000000000690c7ab321c0c93b5ae4ed77843ff4030e4ffb504c685d28573e98836e8e56dc19d662ae9f496a346bf2a8be5396741000000000000000000000000000000000fbbe3861a8d202b10801cdd606b50db0ad6ec7b923b90ae81ff5443676c3399e249e9efeb47b72d2b0a54cb0594686500000000000000000000000000000000148a27016968f0258e5eafe0a8182c22091873a5a58b27aa2160674584e06d5b2f46fc57a00617af18d0688df75294cb000000000000000000000000000000000148449d00b3d1b5b43b08a0c6e909a2d9c66920b60224a2c6a2521f0bad35b99e3bff8be0effb2f7f34438662d7a4882897583b53567bcfdbc63ae3e864a9cda24bb732694a6b27415c5212c7f45a9400000000000000000000000000000000026b55509b81befaf6baa682a3e92a0ab423fdaa84d2897613fd31acd9e1590f81581ba0ba87d68af76b01c36093e183000000000000000000000000000000000c675e190570bc5173b8f508d5bd2768c83e7f56a08cddbc636792dd75386939942827617c4aff8628a74b74195adea20000000000000000000000000000000014f59f38ae9e77f3a76478ecd47f32200567bad11f191d303cf15d7801ae7b5a3286095fc8726acc9818914b27a776bb000000000000000000000000000000000da89fe9493b2d9d46596d80162f5831d4fd8cbb83b46e84e95d5d684eb927022ee62ebc3519442007fdc543701f97bd2f7ff17e54d759eb9c51e16cf6f12d645bf2d091427416b4edbe1dd21947b4d900000000000000000000000000000000170e52a240a7ccf2d57ae92ea8dabe62ca4b458a5da42319ae89cad22ebf13541b0daccafa1b1d3cfcffe81b500c4cf400000000000000000000000000000000174879425f3bfd40fb74a88e3dc578e45b0e0eaad94da009e4076dc42d234d78248ec3a035666dd6de235f87e1a47bcb0000000000000000000000000000000005aee47acc3260d11fe0ca16050a29f92763b3cf8ac78da52b3b2b3e26d8ce7b6ccc187fcd81695aa456e9b94a84269b0000000000000000000000000000000005eb297abf35b51d57474b4989dd8f793005bf8e82e49859c41b786ae39217b2321299829198bda4aaa261a2723d43d6ce0a097efee666c22d1dd0ae8c8e11283aae781e1deadceb3ebbcbc5e5280a61000000000000000000000000000000000e49e94cfa35d8ade2b76865cc8be04737d00b48b195078c8085cbe782232a544cdb548373bd8ad0282674ba5c96fe0700000000000000000000000000000000047d59661f095c41bcc27da5f260f13a3fce334bba216b45df548894bdebc691fe779ccd63d99a9872973ab165a90c01000000000000000000000000000000000772e9a9c22bc7352fdf74915bc464de99ecd96420ef1af6e8bd5a05d73fff89c78e28eb340d4967e906f28afe1320490000000000000000000000000000000018bccff27bf9d7cb2159b9f2d1faabbf8591b53ca8e67e661d9f44f6dba6296e3e46ac32c50128bb5fb076cb8f214e277b2baa349884b54b542e3993210ef002f70c6467c7d512801f0003da789c00580000000000000000000000000000000002d947e728a3b376de520bf78e56452930de42544241180906719a24d72df65f8250402ccaf14d69935b1ecbb0b4d34c000000000000000000000000000000000d5614ec77a9f31915dddb3e4bb533db001702891a45f0bbac49e73d9c19a235a00442b52d452d77018f883706a616f1000000000000000000000000000000000dfc6a73a8e36b7b2d0614b1c6f7bf1ae284ed740c768f08416c0c09a601fadf3e4d7b17a93601b1803d19a04ccd570b0000000000000000000000000000000010d6a8e4eca2e818d6dff13faf0fae44a7fb90be436a9ef3aab05515a35cebfbd53e9af866cde1745f0e2c3b045486dd2b94d087c3ea101649ed57ff308dd3ae0d25a1ad8884763cea1b0b7c56a3834e000000000000000000000000000000000d6c5a6fe9b4d4580f8e1d89f0510bf5dd04e113d6ae5db04af2553bc0eb3a32fb881300f638fb33f7c4bfaa10b063660000000000000000000000000000000013e001b08191707ad98e21b3e0830286c6f3bf587b971dd4ce39e55f06db427676626a5c31c4a67a996a5725ec8f402c0000000000000000000000000000000012f86ed85113ed1abe9dd3826423911e63df0dfb51ad3d1e0e0318ae95991a6a11150176cec77f9c83268a322cb7e934000000000000000000000000000000000dda719cd2cf1aa769f94c21af20ab076b8f024e0a4903e38ddaca21b6bcd6f00baf7e1ed23259f135eb8bcf9c3f97c44f8c35b920a35b71dcf8d15a8a826e5a7c2a2c4f1ac2c2e3a6d100363e7f541800000000000000000000000000000000195ccfb9038bf9e637b88c83c552ffbd562357792513b15f703bffbd373ebaed715a6772fa7e6e5678c2e6422811dae1000000000000000000000000000000000c5a110f31d71b12cc42974003ba39d99dfd91769c2e93393449083a9b84d31473e3a7dff7ca40164e6e7215b03f44ef0000000000000000000000000000000006233b2dcfed96559b565928a494f2a50c2c375b3d7c60ee6b286c538f4fd5ca6f8b2a61654fd04d679bb3e05b9bcb03000000000000000000000000000000000d42233b7b5ad809c735c89c455ba1e8fbd623e1602bc729c01d362368666e4f90e7b076e32468041f3f5665c6fddb0d0ae6101fac82c10267770e74a0ee16b5be6eae2d455d742303a3c624d52aa726000000000000000000000000000000000f6d53de4f8b20de19b2fcbe8a6b8b8ec4bb801bce7363f89b133532ca7ce4925312e23c618a0182d158037c0d0bf07e0000000000000000000000000000000006ce094e24eb14b9bb1b4a1838d8b6da5f53b5c5799ab8dc8934b488cbabf698b99abeb016259a4e1b0f626d27f2c950000000000000000000000000000000000874aec7c8ac360e3980a6e2cbf3f7468f1df7a8d9158f8bdbb0f387d19f3b05326a081129576251ec41a926f670e58f000000000000000000000000000000001711c9b2ed7e2f789b29073f180e46d0c373d6e75c587ece67b8aaca1e9d9b43a96d04dfdcd42f943eca48e240b72ba8002fb31d0372e7730499b26d617b53ea04821c6eae922326d755a0df31b559ae000000000000000000000000000000000e8ddf88269aebf190bf9bd7a8276de92ff6039e479e42a490fe4ef00f646b049eb8ec4b8e073caa000bfcd86ee8724a000000000000000000000000000000000a9623655c0121ea0575de714e53c9e304fa3309f00828ba0e786112781a38bd458cd67864ab17929448171b5937c1d900000000000000000000000000000000198fccc4a333322599697e904e9096240b9c54f89ee6db97475beead62ebf730da1a179409133698ef13abe1310689270000000000000000000000000000000017b059ac08a3fcebde5888bec4d7cc2c70b147b3b1483fd001330637ff1c036faebf292801204bf2ba49350795708dedaa846e68337f4e9c99dde506a3af792732342e3b836376d4816557fc1fc9b916000000000000000000000000000000000a36274f33b4dc09e03a5ad648af0913e5ee95af83df8b4f2a158456aedf0a0528f9b4832b11162dd67e4d22b26e9f940000000000000000000000000000000008ce96d8bc0aaf2dea732dea188870d398b1f3c266b9bf019e1046cca05002416c910e02e998a1604a17c333c65c99a0000000000000000000000000000000000c1a0e4a80bb0331a94ed14570053f941a0438794e6f19d976cc62b3806a565697720ea03c2531004f13453991bd99bf00000000000000000000000000000000184bdae93abbe4d931a6a51ec85bc330d6181da2d34f2cc530e56b6803515ba87f5719fd6fce6a1a8bf1ee5a968bbfbedf9035283f1afc294ee68b2668870aa45e483d208483d9e967b11990cb55d8600000000000000000000000000000000016c3782daa55312a7cfa02c3be73ed75f4b726df5592351fffae19121b5cba73f427d35d5a2df7c63e2a5c68bf57f3800000000000000000000000000000000018b608343616eff759d512c97257f2103cb0909afb4c24a1cc9d8204274b7c9ed51bc762a6280e223a6116a9b23d1f1e000000000000000000000000000000000c687c11a879ec285180cbae3d2e4219df4614e238d4cbdff148ce5a8d21647c489ade3bf6f738052f149fdbc76c8bf6000000000000000000000000000000000936b34fea3a2633b9aa32244329891e332745876d05f95e4efdef859b23ceab4869db562555e5c8edce87a6fd075ae54005df80aa522e889e7720a9f2e44e6e7e19c3160ea282ec87a4b446d7b1c45f0000000000000000000000000000000000d4636a5e13bb59878319af6bb7c98e5d247c2c9cc970b9cec98027de2d4a8ad12d50906fe302c3d055c499a3742ee30000000000000000000000000000000002b0214bb1ee887a7ff10d458fe35208573456f685ee2fb93bb470762c9e27595cb00f2eae7574c8467e417c63c2a960000000000000000000000000000000001710d130f91861230562cd7ab87984ef45916af8e1168fb17b9765183d9d3f9b2c81c649687842de495a757471e28067000000000000000000000000000000000dd15fe505b1364f134ee77e5e3c1a497a20849b6ec7e201813677a1569a9f5a9edbe3df4c36bdcf9ada139b20e048ec893c9daec43032946a9e892dce960e07d29b304000378145148b9a24afd151570000000000000000000000000000000009a48d7c55d24ba49f890791d0f6a8a5ae08a19177575dc0d734fa37b52c3adc45b31b5e485a5d4a5533470c3549f5f900000000000000000000000000000000090f680c6fc1f0588add04ee03bf821868b1ce588e3ebe384dae657ba7885ef74da0bdc98d9d9594a9b979d5b50b93df000000000000000000000000000000000314f6aae1e99dbe3ea9ef85db7e1693a30869f48e05cdb073bf8e14865a671e75abb875d1b41f13d4eb74fc802299c70000000000000000000000000000000013c698b76dd68d1b9ab41672c2b07cb9a63168497d1144b51509b602c5acd71ca6cd049616d949214d95ab7a906a8f8bf685e6bb7713f8fe202c05dfd18003eff261456026a5185ee9e68aa821fe7c5b",
+ "Expected": "000000000000000000000000000000001747f6d3154e0717435fa023754f115ce2a2b3241b62525cb2833473d84a8ccf4c95e3ea030f2b8b0ccc61124095ac86000000000000000000000000000000001827ed7d84a61c21268857036e91c732b304f609f285cdc4736c951fd8954b10267a8505f25d8be666792358632058b400000000000000000000000000000000121ac61f59051e6e89a7c1e2fb4df4b3a5b7773f46495a99e55348454e1d9d42254e5e11b841a1654ff9c80b157389c70000000000000000000000000000000001bc60cd06879980bc6ef2ca109d31f12cac28ebe4d2a934076d720b12f430e1bc4d4260f40045cc7a862726521a69dc",
+ "Name": "matter_g2_multiexp_20",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000012a6984f0f8967c5ae6b13569a62095b5fe61ec607daff1845961bdd827c00fd56ef864802673dd21d90560fef6cbea00000000000000000000000000000000085ececa080d0f4c996d46c80a1fbad2ac9cff8b3e324aabb67182d79f941927050f025b633fd5119f30bb29b8e4b6f2000000000000000000000000000000000987518a5edfd5ae2616fc60000e117a4f1dd1db68195c3fb68d8cc639e4200945b2864d41ad86fb3e11c504fc1f9766000000000000000000000000000000000310939c7e11b93e5773cfd36fa70020c85396e525840742f994110e20019769abcd339db6881291639c193b987b68ae94b3c88e51af5822177b85978526036a426c9ca1077d594618ebb8fac4cdfc89000000000000000000000000000000000ec6922dfc74009c3750ce2540558c7c1e05cb45a5d651b96427c615d8fc563219215a0ee431c0a4827e40b26c4f8d3900000000000000000000000000000000040a4189d002a0e1ec600e71303575e82414e6400f06b9abf57151a28835d454f56421a6dc4049902bfb94dc0e9967ee000000000000000000000000000000000dfefc7c163c34cc004e9d97d812b2717d4736d0d1c722b6bf1a29676a32c8b46878d05a2d137cb7fff5fed8c0f02474000000000000000000000000000000000e3f0c9cbc778693c8ba88af8306d45477493ed6be1bdd9c81c65341239eb510fc948142cc30b73f570819b38f13e20f6e456b39f4efe6581657f5c701c696fde8acb59e856943f15cdd639c1fa68ed70000000000000000000000000000000013705ca4ecca16559713df65b376c7c5825b4f63d001ebbfce9cd1b592af5f2ddb38ac7c5ce3c5f7af4f39f909887e8b00000000000000000000000000000000179efff38ea1044e91ccad467cd2b49438079ccb4d0fc692e79e0bc374abe064fb9979c4a1f4b92c15cd1b042b501d5f000000000000000000000000000000000b6fda2dbf6339af225515681184843f1a9bcd72f7b1389f186f8d0e048ac16e20967c28e087cf09d7bcac597a85398d000000000000000000000000000000001946fca8c816e1e11187aabc40dd2436533d537ce4639eb2d08630ed2ce402c1806b6c2b3e04a960408fd4d2049849bae5d306f46a31c14de7b2940104d0a4424ebaff805a81f1c4a910566057c81604000000000000000000000000000000001802064095d029d3897725eeb93ed6e3b090390769026120aab6977d0de264a262aa312c5777ba322c9eac29e5396fc6000000000000000000000000000000001410f17820941e6a67b1b4993496cdcf0d4fa2d4fda3d43ee985f2606b1408aa9c9ce412c80c90a0c876cb5ecb76878c000000000000000000000000000000001514e9b2c65ca86713447f2d5bb8395fe8552e059829afc68bc43ba9267ef41ec6d69d06e7407a731bcca77ed5d9716f00000000000000000000000000000000025b5bb18cad46179fab15b2ccef17858f9259a90ea4548852b8c6fca69f0ecdf0b175669bacff1625a7143e762514194ff6d13bb0967945ff3b6fbbc104296805e4fedc3c25bb55b75cc997834de6b700000000000000000000000000000000146eaf5da57b6ac788f8caeb4b2ebf7c8999e03dd839977046ca834fffa7e57cd949e3fd44999a007b5dcf3c8621ba2f000000000000000000000000000000000d859632d3424ffe4227ae14856e05c4e750545cf276c97aa9ec03ebde334144eea670dc68e92b61fc775e477a2154040000000000000000000000000000000010b44279c0c80886e52fde5e71726422da2f9457ff86b21426d80356fad95d5ff3a7491002364d9de5ca99c2500f344d000000000000000000000000000000000851b769a691f0ebb53ee3693833881fed8dc6d9e5f1dfeaf4ab1aa7ad54e2fcac246b70d81110451ed78044a98d1547de4fb2dea292b76d8130e6aa8aff5edf0097de935b252d42a777d4d9b8615ef100000000000000000000000000000000131c9a76109929fc977a0a6eda0a7c71cfc744f5f3654e2221ce84c70787598e24c5d8049f92a7c4d78fdb869cbdd1ed00000000000000000000000000000000049872d2c7d472e090d2975daa64fd96f33e7f934e739633b1d7fcd5e771673ed8820752a0d5c8b0c6933318293a4f27000000000000000000000000000000000dd68fbb592a3957ef893180dd758f75978042add36c91b7bf87c4493b0baa875e1854fbc09e6856688cc241b76ab5a20000000000000000000000000000000006143699816cad8ab7583a72b6064fadb6caeb51c8625ddbf7b2911426cf438534da1bdd13e22cd545495c486c9733f7bac5c50a3a8a37111114c22839c88ce4072940c06f0d8b6d53fed155d0399ed70000000000000000000000000000000006c14301984607d569ad1bd774135e7c9e328be1fe54c3b543276bd06bc0bfff11f299a5eb43b5218c3605011d0ea6d80000000000000000000000000000000012f0a848022f95f4884380a5b8e3637a41e3c399a8d2765aada85dcf4b7c2b559122f792850430681a58ca153be2768a0000000000000000000000000000000016b4cb233e1bd59b7b362c64620eaaa5029c173a05e2278774ad6ed746c70a2f6e76c237182f5d9d790966ae69da5d44000000000000000000000000000000000c277d54a7a72c8528188f6cf29d934cc66471607e5e30d493cd11be6b203bdf734aaf37b686cd7101e8599b69446991c3f37387bad1af3a896a7e66a80dfce2df1709fa252b6fbe4334d02bdced432900000000000000000000000000000000169a3928266375dd5793b7504727f939ef0ed52d69e569b1b75a0e094698b37bc70472578beaeebfd0c3df4bce6177810000000000000000000000000000000008936d470dbb86db1567bb2fe7c09971c6d12b07208d9b1b403c20fbdc05ef8984dd576457fc6989470e40ebfe4ceed30000000000000000000000000000000009cdec9d80f2bf3ebfa9a3316e4250741d0d089245df2fd3c9bba4bac1c2dadfe212682166a0962f78c4bf25b618da900000000000000000000000000000000016521411286cabf3fa2c8f72ca62ca311738fbe63717fd12916a4c9e6af9b05d1f5d65cf60e84d9fc5f7b7645fe9bad570fbf5da3959a49fab7e97b3df3f2a38d16d714dd798a1f04ec2cbf84fce76910000000000000000000000000000000006a827f6149a320a74d9d8c1ae8861c1cb963b3eff899710eda642dae6ed4dbc247a22131758d9f843c62710ce083208000000000000000000000000000000000c83a9fd96bcfd4adcfc6d5a47e84108bd763366e91bf06a7431c6c3a107cbe5647da99ee6c1e57c376d366b21a923df000000000000000000000000000000001604d5c0364afb5503b0e1d52226988d7f7f043ce95e7c0a09d7f96e24a58f089156f0e6d19022138170c1b4b7dd33560000000000000000000000000000000019a11c86f78ce462f46e0462052cc3d342596b329fb62a282a59bbd64c345bd266922b1540e40aac147681754643c2e3e538bcefab5d8d0be5fc143e632e86fc065af3f2f621f293b914980abfd6a0c70000000000000000000000000000000015635de295c16841bf44c73639f047f735175e8906301746837838d124bf0d2a1ebaee142393ce9a0d58107c7cb036e90000000000000000000000000000000004fbbd4252fb901d0737d1bf4da62010c06d690a9584c7631ef5d36f1d8c37486a83f2a1e2db21f05c993fd117c662e8000000000000000000000000000000000f4cfcec1545a08e0e0298753ebcef5f61bfdb7c1b9af71cb4c2f783e4fa3948945d357e8302d99aca96df0cb0fc01a3000000000000000000000000000000000f543dad6d4b797f6fe0b00215a5f70f6340ac6bf7cb0bdfc5bc7698dbf0647e4098413dd19ca7af01685edaaa190c6e30b921d8cd2ca46aa6f3e0dc6ff08d77972fb0a248bd39e90a1e9f32be9e892a000000000000000000000000000000000ed552e94021d0912a0e7563462570cb572b189569eb847bd12ebf976d22343b9ad04d400ae98fa184b10ff36720f12700000000000000000000000000000000178727c3e6ff33be9894ef26347b104023ea0bcf79c1a33afc26ac0ee9879344964fada757118829214cfcdbbc0c5a30000000000000000000000000000000000b0a6a575afe5b0c1e287815612fdd3838ab39e8ee7795855837588614715f6687910c42217ad52c1b8721a9e1c908dd0000000000000000000000000000000018cdbf244c78cae1993400ae164b42c09dab4d8e3707a69e25ffa8d0b96b8270c022c0375f933f16f45c9274132a0a633a5ccd9436b15d4d04a8ee9894c116190062c4e7cfabb047b585f3aa1eeb460500000000000000000000000000000000070636611f903f55cc9499481bc3415a6de62d5e6bf8bfa82a8ce665f85bcf01690118441961ff46ff701e361db208500000000000000000000000000000000013d22dff8f6f86f659ad17ef91d90a70c180538f03e10de20c445d22e637015d51a311a3daaed90712d04c9a3d992d12000000000000000000000000000000000db3535057db95fc262f8adfd7f08f3237fde5f0e2aab589d4ddcd9c23aadc437e13644dd3b3534dcb17936a7c610cf200000000000000000000000000000000044c177d4484c07fb04d1dd477b188a2c157973cf26075001d14d2b07ebb9dbf8e495dc23b32a2419621e1c129b08c5ac7a5bf2cfedd7048be7ac7d2ff19d4f8bf0a94295ebdc5e792393e0e4bc27d56000000000000000000000000000000000e10fd069f2f5fddaa0112e70ae89d1ecf034defb24e2923731a7c0068780177c186fde92a3c254a1cbdd255111a4b7c0000000000000000000000000000000018363e01e86e2e922ba435651ad892bf9288be14b54dda821c397ae6167f9478c8132e92b1c2cb0c4037a4e020f08291000000000000000000000000000000000301b5ad2d5c35ebdcc7e7cd1ebf0405cf204d6f5e30ae6f46d20534eb6d7013682c5ae1bba76d2811124ebded0d2a590000000000000000000000000000000015fb3a8afad778031d04e094cbde5f02dcc89ad7b7d452c6c8f41be336a4c8b26e75cfc685b8776cbe5a487f09c304083563651d5f5729a0ffca6b383d884823aa3b0215fa057bffd8142199a16e4ffe000000000000000000000000000000000a7880b00f6a3e959ff1bd207fa503eff6e7279e701e37b40735e2bc8bf49e355e92edcaf23aa3654bb26fbfb07b5fb100000000000000000000000000000000113d9b792f4e3dcd958664a8778dc4b177c430d8db9da7805595e40293ef2c0a40f7a843bfa70ec134ed89a453f9da50000000000000000000000000000000000d7f92148dca4a9c96c47a0eb284f1834cf3d141be7c0d9a7a060af6e28e45620d8255e465e9a0d8f78b2ffe17d6b04e0000000000000000000000000000000004e7917a8f3070c656d324c9a816236842fbd6147d326652667e7bca0666d214233ed136dd9464c4ac619d46c28e2393833323c3a668541ceba18375531c3781dd98525b49dafce4c4b3188c90f3f4b500000000000000000000000000000000160cb05390b54151f6b154b396bb400a91fa83d77fabdf31fba349d1bf3b5dfb6476ad4d714af2a2963e41b077bffcb90000000000000000000000000000000012885f7ec8e780cbaa90a465b5706cf07d45bda7755ae3477c79adbd7956b926e0ef5303fc13f0b97349ff8b754dab500000000000000000000000000000000009ad7509e9e7f5018ae3d1280e881ec12129cbf825cb6606459211ed7b358a97cbe430e94dd9f5e4f6b74fb7287f862e0000000000000000000000000000000014d5d2ac2dbc3d5a061f4e52dbfa68e1eb1d3c818ba26686a3171e310c63cfeb188030b83407070019dc5c42dd079413d422e21fbffa7d55270eca9c96bbefa29dd915aca266071673e970daa0ca9c050000000000000000000000000000000008ee93fc610712411634079be0bd96c3969b48955fe5478b7a31c3ba7639c18291034167eb62e6b15c16b0dd5145edf500000000000000000000000000000000158cb1731b71905d7b958c5407f090a2c8a9319017719da143a3f4f3fb3982abb83b8dfe14facb014321b4f5edb5e41d000000000000000000000000000000000a9f98f775f06055ac1f137cbc1f95f4afa0d1c4935f536ba2e0569d874d9d76b7b86f71afcea07e2e785c7a6ee1c84400000000000000000000000000000000072f8988dd1ab0fa8037d3620068b34848c65e20dfc90612d123b6f9dbcf9d9d699d5ea73739d31ad54c22116365ab983ba7ea9ffda87131452b24a9efcdc91d1262d0d7550e5a6b787eace3577159b0",
+ "Expected": "00000000000000000000000000000000161203d8db1381722644f87b04f47e4be2ea2bb105ea0e67678bc8d29f8a8a3247f8c05e057af8f98032faa93d896aaa000000000000000000000000000000000d3af4842627a095a2dca99b52d802b2ef8c8f3d09873ffe39d224333fceae84bf74780956904df6c1dcf5ba31be218d0000000000000000000000000000000001c79fae014e55e5d0239645d618593bfd5aef665b3e636dac5d191a8b88949d207cf0ae9822ce8e1997de302b386b8800000000000000000000000000000000136314cc68b372b06e7771d82b7ce7bfd0e9fd306787e07629f831c7aee853bed80172121949a940bc59c4a0b76f0819",
+ "Name": "matter_g2_multiexp_21",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000099434adf799099f2e6e2fda4c905e1543893462133ba216aace25836db37b3dd5bd80af1a8c31c7fee56b5ecf9a0acb0000000000000000000000000000000008a6890e5bcacc13e116e3fe2d772ff49839803e4f81d6b088ecb7835b1ed44f2bfa04de1d46dd352346cdee71774e37000000000000000000000000000000000e94fe40225e863b7bdfab4cdc0c1c8d1399554ebbfa3f2c95ddeda74b3dff03d5cc78e295accdc9f02f3f89b4953de3000000000000000000000000000000000b23f2912fdc7a5fd1de69c1f479228f8ffc9f97c40845808cf17a6fd8131ea60285640d32bcd64c9be71d419aae82fb16aa2cadacb129598aa459bb2e6b7fb26d1bcb7a49617b6ef8e57018c3db1f510000000000000000000000000000000004c6f5aaac90132b2d0c6a4e70354ed2e724df7c3e6298eb9ae4ea92e3c7981944c89140c52e893ef2edb2773ab36bcc00000000000000000000000000000000021e813378be9ec30395b917ded5a0424fc7eab0abfdcd2328f725bbd6a1dace0a5aadebe40e10470df0c09b3f4b68440000000000000000000000000000000014e3fee16a833f8c543860ca438d763f764f488463601741a2331fa90efce9f6d54ee0fb7978460a1ab838039d398918000000000000000000000000000000000dec8bb882fe6028a4155e6e2bf48ffd314b5519dc4560f8f7410209214c4a8e37b2b36facc53f4db11ee63ff11f9f228c02014d5392d30863a12102d1c9315839b5611dccfdb489207f9186625138500000000000000000000000000000000002d107029bea087a2d53b6b371aae06c695fa85631450f4ad92c8948b09ed568b28948f80f1455cd22e2ad44697290b00000000000000000000000000000000002fab10cdd8bf17a633c8b3ee8ed2ce783f64bf978c384fb7dbd7e4f0da50b65eb9530365d982bcc17ab91a29eabc065000000000000000000000000000000001369237fb3241ac291a868e6f4610a5103d93aa915e954f18bcf348ece1560a12451723b96ad5fe162a6107dabe1c986000000000000000000000000000000000cb70b7064a2f94efc86060431ba4dea38bc64822efa73c76f3a4500ad23c452c8f2e72713b066a45bfa49559d14a719d960ff678e1b46ada4f866adf354ba8c1514df10ebe7d88d2c8de117ef5ea2490000000000000000000000000000000005ebb9c8202cba234851cf5e060a4114c6fee0632f37e0c52aeb852637f362ce64403347d336c32617cc59f23cc7c93e000000000000000000000000000000001126827b6a0a8adb698854c0089276861e3cccfee420512f0966df78ea0d9c55e85a0536f14ad40e649b8fe4384c836c000000000000000000000000000000000998549680649b294d506c529ade746aeb087f75d62a246b7abfb69397ed67f0f2ccb4811219b35aa894b2f87e3fcddb000000000000000000000000000000001027b604f877ade32df8de6162251acf2751a9bd770c21f22dc819a4f5515bb276a246ad667fe7881965f0b083d1f76304753af76295f72295645243ffc87ffc2110c9d8dfd20b464760ad965d7a97940000000000000000000000000000000005d1484bad44069b16d1ef4e9ca1db70ec6cd82eca645c2fbd4029ab4ca33d79780ebc144d8774d82518c1fefaab38530000000000000000000000000000000019abc7063361ed64a5750b70bd59283e6a61d55d49d8c2ea2f1be8ea425f040d3865c399a66c253bf38355360f06cdd40000000000000000000000000000000010a97b13b3b579ab5f7fd9801d9e4fc40f3b2b2acb9f21bfcdc6b6a3168720fd0abc2f77ccad01be6a6e268fddf3759c0000000000000000000000000000000004126b5454050d761047e5da23c0b2f9370996589c04f255a1ce8ef37a3a7c8078788a0125e4aa86aafce8df33f322d3d1b8760cc40d093912fb073c5012f910ae90f0a979cfe6d81c603adbb98289030000000000000000000000000000000017aa7a3f1ebbdec6abe12abea12ef50a3daabbf96a5f2ebfb517885f0b7aba1e927c682b15521529cb9e1f87c59be99e0000000000000000000000000000000016e23f7effbb9dd34ec1f6974115e7f0d23cc4553d86e6d61a0c98f47d09510e06b3f987c5bcf4bc30e20ae9684da74e000000000000000000000000000000000f3905dd4f99cfcfa6152db53106b4d1f6e24518a822da9388d8ca1dd654a4b8315697328571691f105d1abe9aad3dae0000000000000000000000000000000006bfd10d33df9326a55b35aa6d2bc3e831d4c3b5959aaa35613156e5e19343b74e34ed2670c43ba1a45cd3d91f055c9aab79d640b042664b23667d6c60ef9a5d59de72aee57a78d75752b350ce56d8da0000000000000000000000000000000016ca071d741363e7c3297355e49cfbdcf03d419813ed7b329cb2b2a26fc6a46cc52149ca3e9ca3ccd7284cfed97b985d0000000000000000000000000000000018da360fdee88e806ea1a61c01e86687f8e5359730c36c876ad2acb0297bbc1ae13d790d1edaafdaed65db9dac02a74d0000000000000000000000000000000005a46e4572f667b46aee36b8d377c249de25e797b31b822474aa647ee68cc7d40b083fd0a1d938e2b8d85508004c73f40000000000000000000000000000000011701bf88d4287c98996ea561c1ab2f29a5da9138338c7c7539a5fc8355efab6f58e240df4b0e0cb7f01df74bc8010501d1a2965e995bd4380d4ec52fe8e65e7fd99b1ca9f4f0c656adf7051c4b9a99a000000000000000000000000000000000576e79e507d250eb4040197064b8898b0142b3a2551875935f91f22705bfec6da156c7858fbf77028d4a00957553bea0000000000000000000000000000000015d39a325181d6d1a809b1236f4a1ba66a9bfa6c448470425aa5c8ef9fd00b5481c51e8752088dad62e928b3180408df000000000000000000000000000000000aafabc2f68a4933c7d734660e422ba154e37dd90114272e948f79db4ca51d5ca75d504cf74f2dd0479871d69a08386f000000000000000000000000000000000b017c731f63bbaa8fd0b0d9c17140060429f515d2e85a938d10f6529deeae4818c29b9a628802d0ffbbff720339b7bf2cfbf2abd851d2c1f55c56d4f8b11b196c020c2584cb03764580d410d66784d400000000000000000000000000000000028c4dacba5f33ba66368c19491f4baa6aea4f309afafcc8f464f2886b1d05b6397142d02f0295fd50825819621673a1000000000000000000000000000000000849e1b630e8db8ef039f280f8d401957f807ca90479745b68c3db1b5ce3a02fe2c099ddf9c387d7ed76ba75d6a9be9700000000000000000000000000000000013b43fabc3d4df82058db215a69776ed5dfd4c773d7a013dba3b4ef5cf65e25f79d7f76a06ca99132d6fd1fdadb59d400000000000000000000000000000000072cde8eb3d3e1a7f7e4a9eedb8e56f5e103db6de6ccf833f818f02a0706b2043d4ba0d5473bbb6472e8aeb28364e1d8214edaf16742762baa58a3d22d5bb2305cb03a1326adc68adcd268428f82a1e00000000000000000000000000000000007a33b95f42cb1d1ddeff3a199ccfd9a5d47c9fcb89dc09b5b3f59dde2b47d24ff29931920b76ecf6deacd70e83576970000000000000000000000000000000014c0a63e0152f06cfc32e6034b7829f9d9d09aca0a6ef821dc61ae8d99b77d76c1b2fafb2a14938a82ec72c4041ebd9f000000000000000000000000000000001433135cd913b05b3f58b2e9c1a3bbb951d2cf6c92fddb21bd5e1d9c44e464d5fe98f0791044d56e50b81a83ef6cb271000000000000000000000000000000000be12ce3bc47bf69a13762343b5e39c2a2f285896e5d1b73c55203cae2f32cccbb4f7b8230b2026a0c8b2f63db5e5bedc1f38916d6bdd5d379967dcd058ebce5887ef2bccd5fb7c2bcd758e374a195e2000000000000000000000000000000001494984d478784b2ab3ba27464109f99172033fcd5780a48fbd5a2144354157f6fca2d70b15b0081dfd306ab4239cecc00000000000000000000000000000000078aebc22025af53c6542abe56cf72ce5eb11d3f19212a0f7442d0a0df907c8aabe0ec01d1245ca237a691e685011bb8000000000000000000000000000000000415a1804a46f4595014ef29b12d99b89600aab1d98352437ab8342abf479bb2215bc687532e75f140918b3d030ad4520000000000000000000000000000000015e7b0dae7e3e80eee3c7a9ed4c739288ac2192f7d80b2c8cf9934cea5719081803b207623c771051d7694e705744dbf1cb8c8303157f23987f8a2d206f3add697b9d0a303393008429e93cd35711f74000000000000000000000000000000001470f82372e197a21aaf46cb2bd3c0b77c3428bf2ba073311e75eb65471a8164753ff1d989560f1ce477952bb6555200000000000000000000000000000000001645b5e5b4bcb5f6d34ac841e3a80f09a86a5edcb7f2a7e7bf549b022c0073e01be82e4c9e5c8e8de76ba367595639af000000000000000000000000000000000b43f6572553154e2530fb448d5bf20c3a182cc190149d3b1d75b60e45baa048f44884500fd02c434f9f7eac01dbe4170000000000000000000000000000000014adef5a52d76a267f87d9a8b5e9f570e7775ca4f6a55a5afbf80baea311b1866fa0689271799a654eddcfe36a6bb64c61ca9ab9c3df673b7ff8be098cdadd8354c17becdf82e7e99ce264174653007a000000000000000000000000000000000345a2ffa21eb06fa1d76fd81b1239147688093c6a44a40cae37f2af26add812884bed3e8b4643675b1a45320c64f7a8000000000000000000000000000000000c58eeb5ffdf886d6319ead9e6e190300ceb91d58abfb79c0a322de3987eee73ab82092eea8e1249e83ab67e33b303e1000000000000000000000000000000000763a3fba513b6731fb501aab39a4697f3e4de89125c6884f9782bfb73e6e062f17d34555a04a8e2959ee4e1a2ee284100000000000000000000000000000000024180dde2d23cd88cd29c8142d32435d0db57b8ce8e309701fdb963533c1cdc2595e3bfc01d8c0d08d594e096afb34a681a0861df30946911d789a5da1f5b89c38fa1a8c0407b608122a18be05955da00000000000000000000000000000000022d2e7502c4d9587df7ecdbafcbb813b1812d76655cb7f9f57418d5ac83d4f60b84a0ab5b53a5eee3c3954aa9fc70cb00000000000000000000000000000000083212aa1316561a079cb8d027bc8f89161fc828d050c8837a24fca6f7f94b6dbf10d6032fed895a427f07827deaf3cb00000000000000000000000000000000021552b99dc02a051ea3af1b1bbd0a7ef64088c3aef4a58b18a29ca05e1f442f8ea2c8fdb3642ee94c5df501ff6898f40000000000000000000000000000000001015a7987d329cd1eb5f991c270643a05b8e1bc35467130e9f53c5d96fc3c8336a00c060dfa2d3165358b51b6a521e56f0798b448ea0d10c84e2a8896f153b1ac3b84c5fed6a4ba6c932260bf01d34e000000000000000000000000000000000c19c3b9d7c7f520968d8531966cccbe6f0c3fa0938480ca3591b7489febdabd56a70ae55cc309e04d7acb3de6f41a3d0000000000000000000000000000000002ddc64023f0de2730d3affb695927eaba50ecb91cdf1f369a511a8cc8dae8913ada2d8f27a65e75deb9b8b648e4e2e00000000000000000000000000000000000311ef260debf2310fc31fb8ecc802200e11400909eba24b14d9500ff47c1c36ec540eb970c9262dac947b0c2053d6200000000000000000000000000000000199c19645375dea7602b74301adcfd9af259e1c7c20f377fd10d56b719f7a6e0e57d780c976124e0675c2a54aae3e0f5a8b7de8f34053facf1338b54cfbe38dad73121a0429663f484277af9a230abe600000000000000000000000000000000123fce6b793de0ce2d31f2c7c4218fb20f9db68946a7d57914174ea773d6e6fe1fbb1de141c742e0a8154fa1d81a91f70000000000000000000000000000000019f75536e004a61c6d7f466bfa06ad0c9375a1028eb7746406e7c71e551dba249b5c6284f635fe26989aeea69075b3fa0000000000000000000000000000000013088eab16ec77c7ce7e84236337e395690169a4ed7e44e23d233d36d5d25e6afde794cca2bee88fe749851a71aabe24000000000000000000000000000000000e627130da43a6ede3bd6f2fcdf008c8f5c7b7b1fa56cd3b367d3096317948bda115d732346e73b731d1921a1da6aaa18823cdb73dd076ad95679a9d7b11145c12a81b825477f799300d1fd761417c2b",
+ "Expected": "000000000000000000000000000000000e3b85a3d6628e097a3d962f3c9aa37e3c5be43faf2a12cd9830ab33c4a904eda23027735bba563d38ae5ae8b302864b000000000000000000000000000000000c92be62cb091056d981ab8872292017cc22ae4eeb0cee03a60cb5d57d37b264fbed2d752ae9dfd76c0bdde1f1dd10500000000000000000000000000000000019e172b23249a17924b890cda6a65287039d0c32b2c0833409816cb21ceb73ac95928234ccf566287400a2ed7d9de771000000000000000000000000000000001276e206235392fdf65e4ea6210d22eb7afd7783caa0777ff0af719cc1822579d5b82fb4c30f07dffe7d68c649b9e2fd",
+ "Name": "matter_g2_multiexp_22",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000a3d974770eda8c742e5d380482d36fabe18901b0217485141c3841003aeac4459ee28b280550e4643d0f50862bf2e2000000000000000000000000000000000369c2bf3beae4e8761f6c06d9bf5261bbedb177e609c81c9bd81ed0a17573b6e10e7f0512e06109cacc3d483918ed9400000000000000000000000000000000030253d0a050986f49c77ee20ea8e3e07de3ba72c39ffda877bcfe569eeb29598588f5a7cedd9e2e34491a059ac4e707000000000000000000000000000000000ce201f07353bf82ec894ec66c7012d17f3c7968b28b45e88f091510e1646380f902c1c5b036084f9497e9a91476dc2c9f2e54f21b7f2116c30d6e444ca82fe800435cbbd72a98a6d22bac92039c54070000000000000000000000000000000018f493dadbcd93df2c614af310e5aec4fac9e502843b8ca8c3de739315d9e9a380f826e2470c96bffa8789133f458d0a000000000000000000000000000000001768f8c3da107b9ac30a12b99f2f3a0f21483c0be334377733cee6024d85af91b03c7ea1c548b42e7a7869141816917a00000000000000000000000000000000076cfc99c16c270d2f6e34aff84832f9ee6493ab757b6361cc921823fe9c30f1c9b1664b650548dba767616bec0fd5d80000000000000000000000000000000006c5f580c9556ed31847b1a3527ac0b5b5f15b9c9197d3cff061c1cf72dc5c96cb5fe98535a4dca8c4e20c8c02158466c8cecea241dd6a924c9b9cc3d390fbf40ab897208ce9d3e4a148b2c30c25e7eb0000000000000000000000000000000010e2d7eb4e874a9c72a98e4c36701a9fa11051b683ac8ab9ac20d14929d72ff7b92a9048a11bde92dc2696467fcb48e6000000000000000000000000000000000eb29e621e9d0af8f661eb1ba90b307eb542dd84a486568f85e19055bf7b8f0a76d34acf276897a01349eff2c36e4b43000000000000000000000000000000000b5f890f22658b207dea2d721d90a8f5991ea2c5ca06b8d1b293f60959ed424dbd7052e010e594a5ee0feda1e93bcef4000000000000000000000000000000000082cdd4d8452078e8b853f196dd76505ece5e98df3e6a8bbb21f422755af23c5ab261accea48d8e4193d6c884773cf6e428fab2c596f23bc3c9e9855b74295f52caf73cb7371c93c65370583f7fef4c00000000000000000000000000000000077501a457d5f0946d25a4c5eede1b7fd80d90d502bca47d8cc40ab2f9a6d827d7323e7d4035f3d32b02401141f0a89d000000000000000000000000000000000985410246c1db01b42728ea46758906883586cba5618b66c21a3cf58cb98e7c6e0dfbabc5505d1d11ca9d047fb6d25f000000000000000000000000000000001775f4008f688882d02355b6eaa1ab108f239890f71238b36c76228cf2f575cd15f15293a62a72f6ad0ff17d7e8ae79f0000000000000000000000000000000004b6967a5ee180d8b92e95c5ef26baa56d8509e1acc710237083d19269c1c5a1f2d1680e85f0bf040747be1d301300b0f7d3d755410f77a0e4b2fad0f184fa9312b559785fb04c6020432465799ebe22000000000000000000000000000000000fee170589e8a3d3fdd93b536347af5002e59e8ef2ac8327a7e9f382560ee9bc36b3f636a3f99fba8be7b5ea3dfbcfc600000000000000000000000000000000032380cb6c043e3f9ef7169da12df1c6529d776b049c7061df660df841840933e514eb7ea3152ddac38daa2c52d66191000000000000000000000000000000000620ebccfd931eb70ec688110975ea24b7ee0f9937841aa1b7bf4f45af88b732b76a26299f0fe48259fdf08abefb4314000000000000000000000000000000000dee6bb8c198363fa4107996331aac07216b82208242c73736be31e14e4e04d97a56a1c22479dd94997acb0d32abd3b0557b05efdd02ac9d8e1453c82a321d798f3106bd18764140faede610ae01fa80000000000000000000000000000000000eb60e98d6cb4e4b3e58271d47261d05be892eebb9a37f6831ff19d0bf2fc235e655f0eb9b01494868bc082c58ed82d40000000000000000000000000000000007254a64a0d94340bcc2b0142faab2d73e8189dbaf52ad0c3a9206e802193168b8eb03cb18b0e4f1cc95b98b943910db0000000000000000000000000000000001e0051fafaf454072051d2aa9512ba2367778aa1617cecf6a7f989d69c7627c9070c349d363f56711f172d43f5730cf000000000000000000000000000000000f4141c8a45448fecce09908ddb42f7b5f6b5bb53b9e1ede0417bee327644af5c98470e8b5364642fc7435f84be1ab443313884abc4d430c06ae843d263f2efc1bba35f6cc270de05551e1f86096bb7500000000000000000000000000000000049c28e0bc677ccf54f4cb46e953a057ffad624752332fb9ee5295438fd5bd61abd2199a0bb729bb7678cf3077e32ec10000000000000000000000000000000007138a996356ca3f5d63bb5a36dfe901254459ed515e18ec8d91fa747a691b40a19878d9a6f1dc74e4f18374a399d38f000000000000000000000000000000000a621b36a3cf04e6a5cb699fe4ff7fb8b3361207186848e81972fdaecf667ceb35f413bd68772f7c1f77c1d3f43a3d610000000000000000000000000000000010becda5a06f3f077218d4387158e4a1ca5e0ef24d4ed304723ed5dd96da7cc9325f7e4ae16d9d6c348577697aa6017b8faea236e782a8fbe27ab15f051ed007a61e25247f1f259b9300974f521f30c800000000000000000000000000000000163ee307e0d0c3b61ade05a022ce2bf315d820ee8ece60f93d63a150e02be843a2eb2240a4882c29be2c7403932c348e0000000000000000000000000000000001fc8e9ca23e8dc8457df8f255db3b434f52cddaf05819dba7df1c5bfed438f756c8b57442197af18bf83fe9ee2b765200000000000000000000000000000000109cbe5279ccb592bd0b33b1a482df53459c48cd0913549739b784ba7ad32872377c2e3924c4d45064b0cc4764220513000000000000000000000000000000000d789795d556a37a375d83120a022f57e26da6e6f9aa3e40e1f32ed04b50fafc4d40d0b9b20a26e4d230dd789e20823013994f5645c6ce83741e48ae472674921bb2d9b8abb7d04ddbbb85a3f2f7f090000000000000000000000000000000000960654bd6e6a6b2f7d87c3c4d6e3fe6c684a50b62f7acf82a67075139a614c056a41cd49769960e229cf07468fc2dcb000000000000000000000000000000001727f2dbcc8d889127060de0079207eed1e094259b59a20fa42ab2783bfd176da00e61a65709dcd60402398fadf30710000000000000000000000000000000000c17805a01e64c320601e0ef521b6573e9c2eb354157cf0412e5c2b13f826759310907c4b77164f5899958cd30f78c030000000000000000000000000000000010fb286ce797c0429ad3385c709259b55cc962ae02c814e537e5261e897b7ee1b7c660273ec908110f997b166c14f5c181eda24db328588e8c670ab70431ddeebb0749b431bc1bfbd992c91f35d59b180000000000000000000000000000000015d96a0f988f4951206aeda63af85910db49ab817c83e218ec74cbbf5f34f81279d8a3f2fd1f3000f73b8c5550af3fd600000000000000000000000000000000186d2eca1cac226227d8981324859126864b84e8dac563b4d92357591c2416c93989cfd9e1ab6ad257dfeb168d829a09000000000000000000000000000000000a8a7247a3b09583cd2d4949721160573f1f88221e6eae833128914555a594f21a3fb2bfe3b1f01f3dee90f7772dc97d00000000000000000000000000000000132361ac1950756549c957c174cab9ef586eb2057a4eb22f49252cae032975f56eb0cb7ea70810afaf5716afde5b88015bf25b5070829e3d5a66ad24ba9930f3ad64767c51e432b51bdbe2fab470688d000000000000000000000000000000001328e22bb83331adb09dbed0a8c58040a3564fcae0ec85794f26c077de69cc0a7555f011e028879cb3aafac4dbecab33000000000000000000000000000000000a93db348adb3886802bab1e993f5d7275360a5b0466845055d5274e44716f3e1d03a6e1796ed4de4c157dc8a2d92c39000000000000000000000000000000000dc0879a8e9556b7d9b6d5dffce5e648f835f10acad3afca7a73b0fdd5d5babaa74a1ca80aa4f6880d9b015501e218a20000000000000000000000000000000003f7ae8207de4a179ae48cffc8c6e926455e46ef9e109c08be3ae7401bd36e0876642ae9ac4fd75a74c67ffb7790e265a9535c082e11b366cda0000d8ed0f92ee30fd2c4364c163a718518321c5e85d2000000000000000000000000000000001078f43093602a2dacf9b5dd7ec41d47bff02e0dd27a996b58c73febca06e3d977c2fbd73f63508243696ab5d8b97b980000000000000000000000000000000001841869086e850ad97b3122fa51c437113d2bca14deaef5715c354d3845f6829f6aebe668844352d5af3509c0d8da7800000000000000000000000000000000047c42e83194143b9e977fa1babf80d455fc86cf6cb491ef8306a1c32bbf8c868e11bb3308dd5f65fc2942b3e49ff5c50000000000000000000000000000000000872ce87ecd22b39b14c9036e971a562d51c5122bb10939cdfd1945dd1445ac9f5de06b70931aa5c86cd0fda51b89952c4cb49adce0292e259e92b229bf7965864a945de86eda3ce0bc9f1a6dc8b7b200000000000000000000000000000000157820de2a134081eb47b1800ec72630348583d77d512b4c6a8c8e581810471a2f57a8eb6b0af87a91960424009ff124000000000000000000000000000000000378cf11b0a2848b06412aa754ddbee5660730001db073724caf902d4b4894959f035a8838e28554b0efc2388f2b4f27000000000000000000000000000000001301d15f290dd11c3f8e53407195e02dbf8f13e4fe25fe38e84740753b5a0032f8dd07df3ce46ba424f6772b3aa66f4f000000000000000000000000000000000d166040d457187232f8f38f2beb1e0e0864105595764022c282867346166e46eb789786a7ec7c00b0446207e9ac1ec05e927f57aa85b2df54b4bddaa041d43766c8929c8b9146d723806ee0cf042275000000000000000000000000000000000793797c5bce4b1cc3bcd751c5ae1d293477af96a0e7c6bd392ab4410f806a53088cafeed51754ee7e60e61dc200ccb00000000000000000000000000000000019d595730af1f3039e37494b86a638a528d8bd24c429e3f8bc97076c7463e7f2618e23bd3f300bc7e7a4674f14f8295d0000000000000000000000000000000008e245c7590888fd8dd58f93332b81f48b6e3acd3cfcf5f3b28df654eae1172f52ef5a121707aa9cb111b0b402d1bfa6000000000000000000000000000000000a7c6403659e1a0c2dc7cc2e9b57a452bf553e96388676f4bf4a6e26b3ca2d3cb82006850d8340dacd65aaa0d20e6fba606ee8a5fdd9890b8017f6c432a45517d65328f13f3a2bb42d7115c02929db7a00000000000000000000000000000000054c37e8acadcec8a795619647d4cf1081a0592de02bef916f847936a1736e74cc3b7ee018717495def8b4ef1d098fc9000000000000000000000000000000000291d89d152b414fb5e7139d6d0bdc7b5b9de1fc44b49f895ae08718b631f7652bb4a895fa11149b9a9db30c344108ed00000000000000000000000000000000107b30992ced35e4ba874e436bed5d88aadf0a0c944ca3eb8319539017bdd652feb7483ab6c705aa17e845723b2cb46a000000000000000000000000000000000895dd8e04114fde4a4cf19925004a72f617f2ff146dd650a2cdbeb12977dd2b34ea7d655dee16ad9560b144b81212f5c1a77ccb4b32a762d60b37827ad6c3448c33af6af861c131adb5920ba3c2b85100000000000000000000000000000000005cea2e036a8ce057e4dbe2d9d786eb759c2a75934580480f78d2e228c3150a0a1d8c95ac5013aae3ab6e35f524d37b0000000000000000000000000000000000e18c18884209f9e4fb17431248a5f8d29c616a58af16e949f4317c2e117b80d531a39800dc70f6b161b98ba040a8af0000000000000000000000000000000007c42ce885d1bae906128589b72f2e6c18e4eeacb78c853e923e6eb785c073b6490b2f6b3dff2276916d96770ad5019800000000000000000000000000000000132d809c37c341eb0304ec933a6b11bf9ac0d2a13ead818ab6ee03ccc94160b405066381dcdb13b6ee3f5dca48ee10ef47cde609c38eabf457cdbd1e0c5366bf523dd5801d66a0282bc187d80417f455",
+ "Expected": "0000000000000000000000000000000009406918e2dd6f06f4782ed110e29516a911f47133ad8adc58f5780de916a8973ad60e05ba931d66de7545a92f388c20000000000000000000000000000000000041cbd52cad2a5f4c8353c7153b5711ec23fa8bfa2f34f5e1a16d8a14cfd47c237766880debb992a05ba9ed0353beea0000000000000000000000000000000017d4211c827379b310956371129011a92d62d11f0ee5b0cbad9eea2d3f2a95d364717713fd0c544747338725adf27248000000000000000000000000000000000a61903fb81064614c9c6894c7f3954aace7611cedf6bab8e751f0c203bcab827d296016947c071d7b6ccc742e28ee9f",
+ "Name": "matter_g2_multiexp_23",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007f90813f8c3eabcef04dc1bc9bbafe1dafe220e2db24e4b714aab2b164d7ec9df3e6a3f903e8b7b96df2ad8297381d2000000000000000000000000000000000e34371e51c4c952a0f38c4aaa5fc2324971ade310af2f36ed511fc5fd7a602a551ef77775fcd0f1fccc718710239561000000000000000000000000000000000787edf7a6ed6b50afcd7c0d3876d8919273428bc49833e3503f650e48e788b15cd82eab2672f612025d796bb62d72bb0000000000000000000000000000000006b49e631ace4f72c959919df5d64c537537ccaa3d1890ea9a1d70f9eacbaaa2ec361edf2d4880c9810976c6073028bc3c79fe6374bf8f91bf7851ff935a124b54fdb5db498d2d37939fcd43bb93d29a000000000000000000000000000000000cb63d7eef2d6614d1f629756b3a619a221033207d1621e4ce4791db4248500649b91ff07cd2f1f06eae3a9be5b6af080000000000000000000000000000000019aafbe56da1569959019033e8cc785c9b98bba6b069603969e7ff1150f023706b461913ea7949306a44c3b7d199e86e0000000000000000000000000000000005cdc3a7004f7a7f79ffbf4c4ba7c5dc30ecc62f270a5c231406fa63d82fc64f45e94779cac851ff8443040fd3b2ea6200000000000000000000000000000000040f30dc98e8668194c9278b189e0c0f7b76a4c686ce26a4a96b93190938f07c5b813670e206eb6b5da29624a1b6314ba59fcd2baa47621ebd90c5cd12b89f2a533ae86d537fbb61a14b1a80982c9257000000000000000000000000000000000a5a1bc231f803ae272e497f812ebb663c2ce8b43a366717fc6349264823ca93e29e30762c1a366d8680f81838907f59000000000000000000000000000000000a88fd59ee380449d632d7e1b926210d984d5298fa807570a63a63828cfa55c6e2f01b7745848281795dae36e562181b00000000000000000000000000000000025ad34537909e07beaaff09f22e91e76d93c668d1b45cf6845ab8ba0129e417b758e85a7100a31a9037e307f454bd370000000000000000000000000000000013590106126231b1c616a5dd7aa7ed6946aacdacec963b507907950d6ea11cf1f5b59f819a43eeebaf51a1faa7daa8e719ef9fdfc5f0c4ac41255eb172d485317c124211498a8b9a74c0bfda15b986c5000000000000000000000000000000000938d43b9747c926c3e2dfaca2d6f1e6d61d5a621ae08c66a5baf33d9241771509689f9ea7d75af607d76b66faa8fbc2000000000000000000000000000000001889a48a74966b9748f4a6128dc3d75a69499db1ba1bc9aa3a9428f0efa898b5f78a9e2dae942d3794ab3d1157a1d305000000000000000000000000000000001129c9bf343f476541980b85229c5c25289ca62173e29b75de431b572c8f01f64ec1aa4625dff9e7df535194c7f4e6e7000000000000000000000000000000000fe95c71f703dcc71cf409b332f66fd69c330758d41832236a510ec4bd9a28c4732434d4c3f97445e6301e3070153dbbb8ba028831f429d027319a92fc0f30def8b97a43da456ddc79443d9f8df72cc10000000000000000000000000000000007649efeb3e0bee49b9adb13f8e5d7db1c06d7fde08a3f3082194153bf4b3615aff1450e47fae88ac93f55a389a319da0000000000000000000000000000000008334731582fb1b6125d7ee1da0124fe88f0c70a0a3f6188636976c31ba6a72beed927fe598386f328e4ae534729a57c0000000000000000000000000000000010b57d80fce5cdc90bc93b3bc7a1affadd19fb00aeec2ca9a6287bf4e40fb74616986a44f2f7d945f58501a965f37f3000000000000000000000000000000000180dcae46ee41bccd422b3cc2b34cad26f6816dd08ba51b2f12835e7439ae2d46933de28ac04bbcad68a188e7e90ee8dedf8a6d86471f58c69c1a5e7518c69c34165e72ce84fbe0b7f69d9c2717e5d4d000000000000000000000000000000000b419b675ccee2509daf66e5da4031b08792e1181140b30489ae21f7925305d8cdd8a104580ae5938586d6b8e74f750f0000000000000000000000000000000012e070ab7118991a20b27f1a87fba1f5815665d76269f0d3d460a6b701e57ffdb4fed2c53fa63a3121c74f67e770f31100000000000000000000000000000000124218ca85f235eac3471e0acdabf73f79afdd4bbc159c1e34c641b97f03735e4c3430264f2d94f640486488dd1067380000000000000000000000000000000011c24f4fa1862779f22a628edf9d3cebe0f7593964b642f889201ae85e8fa01e00e48355053f5a7c6d920dcf6a7ee1d60dbaac3f5e25ca3d1d50ebb31258ec4450feca1e02c84672ef15c49b4de2cebd000000000000000000000000000000000266bf0d9d5a4fc713dc0fcc6ea6edae0b326e22cd97bc49c48a7ba398fc87d7a0c7141ba24d80df454de66c2b5a55fb000000000000000000000000000000000aa8f95c7cd61733b0a260149d6608a73d6c1f989afa8cb2aa4098e1fb5a66b4ad5a5c1c4d901aa79812385fd507f02e000000000000000000000000000000000a6b4929df13e1fe7f0a0cf699a7fbfaa97d7527cc3ea1f728ba59def2e75fcf3490199bd42e93b7d47985a307add07c000000000000000000000000000000001719321981d2085ba31c9fb131d6b79c7df5d10d6ad0b5015454329697860121e781093fdde1f19e897dd6f2c272f87a109ccbb8fcd4d4651b84f4708799d84ad0a717aedaf5a76d2970a7b93bd23d37000000000000000000000000000000000431002c9926aa7d2b06412f544a868a7d48fb5f077dfd098febeeafc28b876c434daec809e5cbf50ff2395ae7e456560000000000000000000000000000000005a15f713b6eafb09495cfb1c89e9421515a07a99ca0f208883f11c430ffe6f2592dbc41bcee5db36385a26f67cd26bb0000000000000000000000000000000008dd30fdd7767486844967c5da0803b52282178287b8ef28e14f07b487132fea3a82d86d414b4d0a25b3dc538be11b500000000000000000000000000000000002dcee67e2d17b3106dcb9f4117456a037ae1996e8f7a09b179baab1ee8345c6d01eae554d3f40da86bd79a04702fbf76326fded2b8a3fbf7637bc25bd201d20e3d4d724806cfa678ee039a39c24e86a000000000000000000000000000000001629fcc374e99fa8303a715fb5077f266b13367bbc0098b5463d3298c0892f83127d6b7f751446575b88858bc742586c000000000000000000000000000000001100783c10618752d25c235e1e76dc64db94adce05651fb8df0a5ee7c299d35b1319f7009b857892ddf9e90c91f7d23b0000000000000000000000000000000000ab6996e4935131becd5df288dacfad1e69b41e200ca7dc841ecc180a81b9d2ca14fc8a76a4e7bd6f924bb9f473de62000000000000000000000000000000000ae9b22f8dff29e5e0a2ec5b5641f53fb5e1ca03130b49d0c26696ca4b439a9d998d9a364ac9cc5ec52df699318cffeae005efa8ee75dec8a013029292976e107a507ec09e3c34fb4baf2979fb759f1d0000000000000000000000000000000019c557ae1c12ff8a7c00b7c9e4bc3d65c92753549c193311a38a84bccfc090052a2219461a9691affe2d67ea4357cdeb000000000000000000000000000000000cd35c5dd126bd4b90dd671f29953c5a49a14b6b3fe946991416edf235c3eb3d574613d27b05cd879518fa7dda3ed39a000000000000000000000000000000000224392063b0825fd332bbede23588c1912e7670a013a99da5507f650dc4284431698a5b4e8c180269af8bb30e4fc8450000000000000000000000000000000002ab8d3250d4bb8ceecc8ca2003f91420d0ef8a7dbc2361e5e7fbfcb59471a4c525856bf796a2c2608d219d215cf83fe3917f8baf17f71222166cb9b6c4beb2e57d0d054cba3f7fd3a28cd3dc4b409490000000000000000000000000000000000911417908c2bfe4f63a388f699b31b47df1ea0ec289ee3f96ffd0c71f3deade00d1841aa56b4bebc2adcd3068adf920000000000000000000000000000000005467c7e58e82089fa285c28ea22c759c7806d86fbdcdcc8e09e847d6330922a61bc331ae3b5acce777b7809ca98213f0000000000000000000000000000000010f376fb47933b1f701dd81cebaebb2d8d8f5510a26fb3e9e156ac5ecf2b943c5fa2812d52da542e6c335abad8ecce3c000000000000000000000000000000000dcbf467432acfa4eb9ba11a7cdf02f9110f44ac371128ff8f1f98fc70e4554f057a4608180bfa54d99fd2da010594f6f0f73e1b62561f5b0fbc409e6534ad9e37d1c0724b35cdd3f94bf6489e500fbf00000000000000000000000000000000179aaa7119f6fb986714c03b6db16f25eca7172d24cbdd318bebb633bf08920f9e2a8136c94e3ec7c19e57ab51531b3f0000000000000000000000000000000005937c484213ab5b2ca8ed1c5c90e8d2a2f1bac044b88c04b301ff2fdbe67dc4ea42779d919ad510cabfa2ccd178cd9f00000000000000000000000000000000183cc23fd64514ead63f55d375a07af7cf2a56aca64a887dcc542f8a396468a6abc776170a5d4b4bbcd4dbac285e7ffe000000000000000000000000000000000ce12228dec2f84219904d9ac7923f122a99803a9b34749ca68ba385c178811685c19a492aca2e1123ee82a8a9cb90fc3ea24fb6447f2493c78a267daa158eabb70c1b60af8175d0d4594c99122cb4420000000000000000000000000000000009612bf9130e17110f8b15aa6f3317071daf3433bf6d008c383bd5c2fdc7ca03f25ff4cdb483de3c84c0ef9e579f38c6000000000000000000000000000000000c40172540a7e20eeedfe02c37aabac07165cbf04830f20fa76fe8b05c826e7762c9f7567a0fb972212bf736e627948a000000000000000000000000000000000f49e5b1929ad3ed5c07670c471710baa24e8478a50f72a5b7bbc23a66cff91d30a3d68961fbc2e6e8003d08196f325c0000000000000000000000000000000004ba098f915ba9e934384682648ed8d4e1cbaae60d596655fcd9c05f4b049ba0d278730dba5ce3fd4892531a3153bb955ed307c01d9e29a0571de07c62d5fcfc80749f02b8dbaaee9f69dc9263e99188000000000000000000000000000000000449b15ecec6d6fe5cd32437b54218f62527157aa6344c635fcec8f8305c8b6e44c93105984e0832536237606f07792e0000000000000000000000000000000011e40e8aaf75f5ff8e4040f725ac27693d7b24805a2539ff54b3a6e90c048875ea9609fb8fb3d8de63ca1118876c172400000000000000000000000000000000006ef2a24445f728b53cbf01e5b076acfa7761a84d8261cf1a1b99cc32f330f32fa5ded83d5cd51cc284207adb2451ee000000000000000000000000000000000977966380e772670447b15ad9917035273eb71a21c37607a761aaec808909fcfed50679769aee1573d73cd241de6624877f31ddcb55d961bf9bc09903bd927451390922d647d589302855141cf5cef500000000000000000000000000000000074e475c0ff1a51a24be3c964c45c41f767f890dec82712d92a965be504fee43fcc6c0684b2b17c5b294a3eb7ceff1cb000000000000000000000000000000000597b7dd287f3fb27e35a9e4e1718b6b1a4addf9e95e93aeaa25aa34023669368b794a08fdb178d9bcda2738534d1962000000000000000000000000000000000a492d648393bfa317165ccb552e045fefce5b3444d5ff770f43a08a68efefe7fce1216114ed1495cd00f832538198180000000000000000000000000000000003d85cea8063828ff025ba599bdf1efe0412ed5ce06ad5faa841c6400e4eeb6aea1470d48f4e66fc768d7e7bfebedb37145c1442ab82241f56c27dec2cd4dbfa9fc3cf1ab72bc521ab32a82346f8f6070000000000000000000000000000000008ecc3dd40da2a7a348b4817d9c84242f2f07c5d0ef810dc08311e9d4090d6d96d68b6c725ee6c24de076c71754bc4b50000000000000000000000000000000018fb3a1dc4e0dd9227fba310236a6db7953f0b716fa995b928a2a8de38edb97eca09fe2ab385037dfdcda2ee577e677900000000000000000000000000000000062fce7fe7810273a80760d9f4b3be9e7c821f38ed3e075210d3aac6aa7a763e3cda56465f88b34540b408ac850742080000000000000000000000000000000006fa94466cc47990a80ae6a310ea765590a0e646b5988925f03cc7e30f04fc0a8044b403212290b2fc46c77e84a9028dde4d1470f6cbce027465b4dc2a3deaca14e34218910aa76cb45d47139b31df88",
+ "Expected": "000000000000000000000000000000000f41bad0a932e28096e51482c646dbdf294aa7b91e0ec258670e7674864765c76989a936fb440bfbf4268a49f450d3230000000000000000000000000000000018282b76521db98f589b1c14e603b6f5d27af357553bca761189a38a944a11c66480f7ddd89d17e4aeddc8d78a2b3a0d00000000000000000000000000000000007efc4a90dd97f1312047ac78a3163dc014c42a44c7054daeefd5b72cd0488832cb6396e02ccff09e4171d790954fcd000000000000000000000000000000000e790fe8323fffc96705a42ca071532d5359641ff7cf8714789c9c578717a054c811cdb581df8b6a43729c6c3e3255ab",
+ "Name": "matter_g2_multiexp_24",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001304e0ce6a4baa6e0545fdb314523fc91f73eee157249b94f284ba7390b12b23b1c849c45a563ac82b62a2c48aec24e1000000000000000000000000000000000a2d0e9e222db70d49d1e85f587d35bdf5e8328aad14343d296f95b152a79c83a4858cafc350a5df1ad0194c49bb929400000000000000000000000000000000199efb09b34d0699eb4bc1c57fef9cc5d98453bf522c504fe7897e22bd0596a3a6c310eb351e15e3f6609b074b240f7d0000000000000000000000000000000016b69f12ce30ad1a65150094e29d4cd82fbce5dc343517ba9e5d89245ec083c44af9a3dad2169f713d3b01fdf70d20642576b42e0728db912a78eec2b7b4c96575e341e86a7592a07a660c11e0044839000000000000000000000000000000000b3ce4ac12861052c602e71906a7c9f3e2186bd2b6eaaf222d8e80b48baee537065ce78372ed936e6728b9642ba1fdb9000000000000000000000000000000000e8186561d23515bc58c77769c93db76dc9c62bb715b283cbfb71462451120a6ded736cd8a292a6799fbad7617d9aa84000000000000000000000000000000000368a6dbc7daaab0a786257c813b1a25c97468732c27cc759fb921cbc3c9a37a46d7dd0298771c447d36ef0a10579ff5000000000000000000000000000000001348d5e34cbe54e3a6b357c4e651acb82d2dc40ef9ed8bb89f0cdf0882ec6a737998f4e4dd61e296d101cbaabccdc3e779f9205ef0e3a85199c60ad9267349fdc7b6fba4cb765ab21750eb3dcfc48d8b0000000000000000000000000000000004ebb53c462239a78bf13f29856ddc4d78645c457a656f3cccec9d3c032ec19c26488f39e0f5bf0d38424f9e3a9bcc870000000000000000000000000000000002fe1949365831f7c38b1cd6cf2e22345c4ce40cd73def77889c214d1077d70e39578e8be4fe5998f59d47cca7917280000000000000000000000000000000001152f2df1512013a42ac056b75802bc35c1883efb345cefda8276c594b061a0b0f4a49d8bafa6fe251658ee76b2493cc00000000000000000000000000000000094f90cb386f7933b2ffcdba5e46e09cbd7d537c12bc223e76d3a88ce9063a7b3574d3306365d65dd4c6505f1dceea53300679b7be7c71224247e8034f5d30a63f8707d92d843a703f0fa93160f6571500000000000000000000000000000000169d9469c53e55768c9312680ee82ee581727e28cdb1d6fcdca25d0c03f3da2ad6572039f12c90b09cdb843bc506e07200000000000000000000000000000000174528257f6d3542f754ecbe97eeeea7d196ee4dd01852f6cbad87fbeb4dd7d3799588f17aad129a15549bb787468772000000000000000000000000000000000c9ab635bdaca1c488538c0830453ec6ab3b2b62447c03ff6ffd2712bf62e02a63c76c79d41644ea412e733128685c45000000000000000000000000000000000172ef0fda359bab149c8c04f583f4ace4d1b148426e993996d278f79ed2c6d3933d6cc5fb62ec4869aadc773d3084ca0454b01910548432a0f706818a98151e38ff9e854f1faa95ad41a7239b5cc4910000000000000000000000000000000017060fa73b58957d12b3996d67b7baa8b7f0943ad52e80e5c4f8830d33dc74c0a39e08594b647945b402299ca861f7b10000000000000000000000000000000001efdc7f783f9977392e2797a3e0bed222d5b661d056aa0c7e04a493bb9b18048bf72aded134941ece78d63df0a0868d0000000000000000000000000000000011355198320af05f2121939e6489f31e9e13b3cbb2cb30c9e675854cb8ec038f80aa2f4b6f995774b36f5f1b6a84298f00000000000000000000000000000000172e18c490d0cd5ba2449362c0ab296212dbe69ac25515d0f91941d300051320f067f946dcaf999554f55f1f616adc0f3685617371b27ba8898ce7f30776d817ff09ef68a9d6721d4a923ed244ae82060000000000000000000000000000000005854f4dba62d1dbbf3ae16f70792f1bb39f111309b454a6400d2916e619d4f70764ecfda7eae5c28cf1d178ad53fe6d000000000000000000000000000000000ed0bad1f5d69a0e621d137746a9ecc764931ab89f24ca827e0340ddc03571ed697f63e79cc58b946e8462099ce4b1d70000000000000000000000000000000011de76edd1cc2f9ba06b98593a24a7a011f2701b451ea3ccd04361ddb678e06d91a676e3f11b62c68cfc05242cb8a859000000000000000000000000000000000599726b5f5b93d414f9310383ed9414e4675d644f83ebaa63dceb2bddc7dcfcbc17c7aaaccd0ee32b0875952554b4e660cb5aa2a0cd1e8c3fdc06a3a1f6f9b6d52a8cc2e98c85b8e258f72d03efc25400000000000000000000000000000000031110347cbea2756b5fdd549d6c0b8f4036f5718d41dcd6c854a91c9df29bd464774be479d0efcb8a3f82cc7441a6c8000000000000000000000000000000000e24a52dccfdda3689c87395e45dbd46156676d9eb2cc09dab22ef7ff0acf5ea243ff117c82b147994d65aee8605b2fb000000000000000000000000000000000e0cd6ea0bffc591c13c48bca0782fecf8e128b0b842aecb06f803a223d32cc350db869b7a77f8e31b05f36bddd587ea00000000000000000000000000000000042ff4ab4596d610638ad23eea904a82701cdf61f9e2dc5832a70e11e717711a2d0e72f32f74706d385a9567426b4713addb1fe778c84242953db87d2307b40eeb776f17767c3a4311b5d2ffd738f151000000000000000000000000000000001517efd853800946aa37868b525e58fb488bb69755ccec806afca2d21bd3a30ba46c39cdf694ad0ca92841760437c3c1000000000000000000000000000000000e5591c339e88544660380d6362f4119c5596f910d4ceb96ccd4c4d9672efc50805b6fedffa0a48d126aae69b241d3640000000000000000000000000000000010ea5babb0de734641f63eed2eba6124377b5c55e429987917c0bd109d7904766a10b0d2dd123413816d0fbabe25050b0000000000000000000000000000000000efc89ee2ffa56193129062ca55a3350bf50e8fc7d586fae3636a70e3577987fb0f8674d383def4b41225e490d3d81528416b4b4e965a5f024723fbad6ef2f65a1381e70201e26ccb40188dc3d0fae8000000000000000000000000000000000dae4277d62e3f3dfffb80818a5ba5c371a48d73b92d69a168ebab897ae8be206fdf776e9f955136d7f7f7b2903040270000000000000000000000000000000010ca635ee2e49cd6c951d75ffddd11557432726d26564239c611b139329a28812afe21f094c0585675f4f233233743050000000000000000000000000000000012378b2ec31119e508fd9ae0ccc4c2603b6820283284a278fe16864e5a18cf7992d850c1d6ebd1253103c219bd95ca4c0000000000000000000000000000000018cac4f0660240045214034cfd8a7e40bf0aa12f97a23c4e27db0e05bb25f4d755276a91a4e882a0be63437a522943ab78077a51f88236dba6d16d7fd681c631510106b0eb7448df456eb9ce758e74cb0000000000000000000000000000000002fd5571c818322d207d58fe0a898a045a26c95c2490765dc9ac663a0de78ef5fbd05b20ea96dc5388d5b2ccf13a5e320000000000000000000000000000000006ff29ccb768da45061ba4e01c90459ededa5e79513917401e7e37151095ccd4656aeb9cb7c083cf27b69377295934cc000000000000000000000000000000000414d34eac47430495be735eb5c4b1a68372abeb43658f27613a9c8b78f17d9074174a8deeeebb1f9cda5d6198bdf89d0000000000000000000000000000000010b11bf63b8c39c1370e8fdbfdcd149fea88eaf1c0a94a51bdd061e4c41abc626a448030bf9ba880032e9f1642caabae871716e790e1a0120fd26d169b8ffe3fcc0d03683dcdba7d2f953f05444076ce00000000000000000000000000000000023eaa08a44eebae674434b013ae9992c75690a3d0de53e4b05d1c0dff249feb24a12432bcb5defe25ee4e44a56b27eb000000000000000000000000000000000f146ac27e685cca04afe8fc58fe853825f5b0009e8831eb0d0121decec23b25bf8521da2fab1508a3ad8254865fbee70000000000000000000000000000000004af1a525d3c33e0b1629cbdb90c56a88d70a28037c87db81c59bcbc811c8f0b98aa9dd574436c9f600c0e8e2d194c0400000000000000000000000000000000170efb5e0e69e46a21ec3b972265bc04b9d5ee926254f61c0e18fed013922e00f1897cf69889576bb5d54810486e7f2776ed0a27553db6ac6d3959ff4c9bc5807fb7d4f0a56095ed2bbe31dbfa41827700000000000000000000000000000000111c832a96329d6db203fc8b6bb5b7db01521529c91c74d9cd71dc78d067b36cb7eabf1af80129a7a3f44b719235927400000000000000000000000000000000097339c17816795238629d4ca6c243a14e9e227e9bfc30370dbb9e1475f6d03020dc35559675121792436bacdf9eac4a000000000000000000000000000000000805870a1efd1fc34c9b576b77418ee8c0d36aa9caf9994a051e1d55b49275f34cdb55edc74ffc267c5776c8d0e113ed0000000000000000000000000000000001513afdfc2f000e3b725fcd0428fe72ab2413ff2aa91b44458a5249c9a160ee27bca01d2fc2e230f4a80454769961af95ce72b30d989889c8779c4056e441bbcd93629efc2877d36d27f670711e21c4000000000000000000000000000000000485b3b1f812b4a28ac87d16f86d8d634e85d49d6dc460646e1224de662e906002c44a1a269c3bc011fd22afeb2d58df0000000000000000000000000000000013ba0752444a794cd00c99eceae51e61c382d0abb26e5e0e595d59321447400e8a8f7d97390bd217fb50bc22cef34b2300000000000000000000000000000000184515a36024d0bf71d9fa4cc5165363ff94ee9f8579bca653ebc0620a9d3146fba70a2f4a9f6bd3777101de0d32e327000000000000000000000000000000000e041422088c0343f7704e726d65ccc4216c4a1bde3668108983643663cf0249e992f9acde2dd8ff478dd26cd8d9434d06d220f64de05bdd6e1140c1e409fdc13f43bd31cd94e633be38ecf22ebd77db0000000000000000000000000000000005bbb0c55fdbc59992c83fc0ff03f677e58b6de6f8649141d88963ebfead9383d692015a7b765b727eacb6de250351ad00000000000000000000000000000000183057eca610b8e07fffb60d21bf2eb87981e6e881bba04ceff420ca38228fce2f94d40a993e2aef09e209f3990dd14a000000000000000000000000000000001231bc55242bea6b589cedd1d82621fb71c606ca9306b268379dbf83ddb1420dea228ffc05cd8b67c38206f3f006ef18000000000000000000000000000000000f2c943e7a8b0ee00fc4e4ba912b94f68f504d2783babb90a3781b666b31bd161af2f97a77813eab9ebba76040b04155257da8ac7d23c5ed965d8bfc76a642a36ea6ec4c45baf6882021372e8643f09800000000000000000000000000000000054bd97b9cc979006f734ec433e215a4e8afe468e69173384bc895e10ead3749d991ff8ff203abff30bf5cc0d2fc8c6c00000000000000000000000000000000066b73a98d5f5ae140a5784c5594892c849aa7f2db3b5798643f755743d401ca745d810fad5f4a33e5b3cf0fd7d96f7b00000000000000000000000000000000007caea93ff5cc6ffc033717220a215ac4ed7283945ae77e62320a0bde13f2153dc8dd401297cd124b4c67a4f3839dfc00000000000000000000000000000000094568035ffff439e3d3201466f3a1d43414e3f6455627c5479c8b7c55130ccaa5007ace7ef6a2b3e2e5a4c9543dad9163d017ba8c7ed138b1bc70141abc5cdc3afbccd8b1db5a6b5f775efa62b8dbc30000000000000000000000000000000015eeef8bcbfac04112931e186f6fd48b7a8ea891ab364ce8266c5fd15f072f08fb3655e324795df182a5ed1c917a5db000000000000000000000000000000000028916fcb3b30a7f95321a0998e544f9f4f578be7a9f866cf72d6b8baccd93f8935f105ed26aceebb3f9c96073a8be180000000000000000000000000000000012b11f356a7e32f3d9281a8999363aca0ae5c1a058724cefb51583e5f217257d47ca76d21e54ab62260796b95f9d3ad0000000000000000000000000000000000d83c75c36cc8dea4aab47823edd26b4492da39b93a15fa454aed4175f28a025ad2c576ef2d76a66e666bedae95cef1a7a16e23e37ecffd514d47199cff249415a6d366fdfaa82450f0744520258955c",
+ "Expected": "00000000000000000000000000000000059443f363ef0c65973d36469ac651eec6e52485a07a6d28112f4d0711802d182b7e6fc56d4f1aae51fe1c549247d885000000000000000000000000000000000d22118a6f1cd06ee14c63f0e005076bfb061bb85ed184b5444c08ed9dc35f77217b6daafeac89a973f2c73f00e0d3c800000000000000000000000000000000180430caa9917cbb40e3ada2de8d685b4daa99639669a643b8f5cf9a4a55d6162e9fd7f5d4989a1a6588feb0273669b90000000000000000000000000000000015d01fba1192f0f1acf8fb32fe790f0448c6563cf8ef5505d9378fa2fdd38bd99ba938077f71bb8eaa91a99e787e840b",
+ "Name": "matter_g2_multiexp_25",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012d948b5268524659e29cd407dbbe8f529e608193ab9452f936b2f6fc0b81d3a63a0e929329e2d89b5475dc2d73ebd8a000000000000000000000000000000001219e20a081837f4d4e33bdffda08a946bb9cd876e42e2f561ebfd18ec439e0104b43de61f47b8b7a0c346c33e632be60000000000000000000000000000000000a135c72c45f254cc1c260af803e14cd0f89c2ac3029629a86b05acd3440465aafa4cf84e69551ae772bb55802a90ef00000000000000000000000000000000052750c3a99974f9044531dee9129110b99572cf283b61e6606f1137a87de7344bf01d2ac2f8a1db8d815b6d9e7511fa26a9bd0a71fd58edf81459152782733536e960d27e35f9f84d00da256bdc118c00000000000000000000000000000000136b2f21aba94bbc8e5235951b1b186fd4ad221e6ecbea5c7279cc8ee8b01edecedddf48cca47624ee9b155a4c167f140000000000000000000000000000000019852d2bc9c8abc92503f3e7eec9fb20df108c23643ba8a2fe16c2cf085bb4ac079d3f065a1241067daaf401b662288b00000000000000000000000000000000018bf1a4e74ac9507b97a990f3a41cbae3f32e263e9937a8a62679bee93296ee5cd25110833eb5d136425bae0e9dcb8100000000000000000000000000000000096ae4bfaaf4f18d3e987d9f287fdd3dc9b497cc84867e757da52bd5f58688403e1c9cb432a2eb87e239879d52990ab5f1e168ab93674bd7f2bf73318a48ef17ef4464fbefd39f77c17ebfdb24d679b60000000000000000000000000000000016ebc2ee18515354b7af5d924c895ffd5556ad088560f89c59a4ceec229279d4075f732b884a6ef2bb2eddc11d27572500000000000000000000000000000000110282084ab6f3e76eeb9e5e8c56749992913c2404b003df9c2d01d72751f879538d23f612c8faabbccff45185f4c6a40000000000000000000000000000000017476677ebf052d13f60ac0ec5e572c398f1a478d60ce92a3de88a74a28688d786d30b1ea8008409e45697db0adc628c000000000000000000000000000000000a5e4239d938bfc7c05f3b3a850ebd5f7784eee7aca48c861eb4bdb1ce6321fc9c6bba997e143aba13a42f69ea14937397fb0d947d71a1b032070a12588b85065c19affd0db53e466f194f04f58dba2e000000000000000000000000000000000b6e16f2a6cb821abc43c447da207cc3013f2f750c844f42f0fdf47160a38501bf502073bbeb565122bb3de61b3a5ab800000000000000000000000000000000040f5f3aab5d416e9a084fa298814f894ba599315fe10af20f836e624680582413b4a54623cda8ae2663ee094e4db775000000000000000000000000000000000d32ac715a094813c7b46ce2e932365bfd62ec5e584e047b0c56ed6eca3c58268ae01be31b833be7ba5c2588ebb9859d000000000000000000000000000000000850b9044f129e51658a02cfa49d40a2b09239823cba4d8fe423fa1b4815750811daf745e7e02b317a7318aad0734ddc640f850bad2f22049f2f8aaf3ee57564fb38a847e428e252f003eaac465f7d670000000000000000000000000000000010c703e31f2d488812a387596c797d8d414e406bd82f238cea50a459d842502e11220ad82fce5dd36635792ff5770bc50000000000000000000000000000000010c11caa640708850e1dddd48bae22961a45029971d823b53030979b7d8ef2eaf2ed055436105697c5b0b31b1a9d0a7a0000000000000000000000000000000006b98568b2b7f0aada97310f7e14084a14bffe580ec65bc8fe5d19c6213c45dc1b8e1da5c6c1b8555729f6c781575278000000000000000000000000000000000f2c506f3e41c28a748656d1dfd87e812b3ba21815637e497a30eca4fc5de18257846f12b67919dd2d739477cf5ed0ae8bf91051da5bce0a51bcba6f4e1b3c9063743646f4e75e3e5a8cbc84e8112af400000000000000000000000000000000102b6d561172adc9316b3ec11f05e66e7affb1bdc70a364faffa57aa5938c2ac08863be8fe79ce3f627558fcb2ab1230000000000000000000000000000000000c5e72c271a1ee186d443a96d53f0ba0ce226c76aff2a7c3215c2110f96cb3301bd586f509edc45cd20e662756897b78000000000000000000000000000000000d546fbf485bb283a04fa05aa962ae8d77ec4d26f749d83b208f77247778e32a9a2f1483bd84488806e27b13eabf41d30000000000000000000000000000000005a42c6ce8d43d122bbf984e9777f5d1c15057f27e70fef44b97c2c6e7e2e303fcbad643027b7ff3167916f21a723ea98da771e0e827a52a2f7e79e0e5d93ebae04c1ed78cab87d4353f24ffc52099b3000000000000000000000000000000001788323aafb95f8761f87f771fa05a8e49be71e397849daef5877a7f486af13fa651be7a93bdd9465df7be4ff65825fd0000000000000000000000000000000014b7a56f3f7c12e39be76b3872c1ee648f62f9cb6a1842d869e00a5dc2ac8cb4ecd96ec2483d5eade5b0f9113133bb050000000000000000000000000000000009a30623632b757ae8d03ced0c1fdd1877718f8d84f34ebb42426284f73bb7e8abc31a5e5ded57a02d08adaa90abfb2600000000000000000000000000000000020b47acafefce7f617081e22b2bfc566acec6d2cad5063a79cf33e02cc8931bb698b72184a11fab73e0bb0aaec76c61d6cff707bff10fd53ffeff8e9400966d8ffba6d4ad6a8e7e456df10f8f5ebed2000000000000000000000000000000000d1190466f0e8f03d2cac4a5e63a13d7c6d0cac9f2065295e2de818773199d731f8cb7b2be5f6ef0a246401b345a2d560000000000000000000000000000000007d9c5d187494df79c25b6292527b0d6d8c50b6467bf76a1a1316556e48159a3b5dbdbd9fb0bb901d857f61f423d15db0000000000000000000000000000000013e4401fe76e3f1ef73bd244189cdc81fcc152f71449c11aab24c4fa1d123c5aa8c68a2d10fe88c1c6631778dc0bcd420000000000000000000000000000000004ccffb4296883b8690b2f3fe17e4e9ab24390084ac917ed28fa1e04b9758373abd348290d24c915dfcaf0649ddf5a87e00831cce307cb44e8dbd5edf24f1535b837277160d2cf6daa4e862e57fe73b10000000000000000000000000000000000f4baa5e531ae462b95362292d5366daa89f2fb2707c58568c094c58578e84a8d253fe1de26b917b84635c0aac3a63300000000000000000000000000000000109057e5c5451eb9f85b95aa5ed2615d2faccd0539b1e4481923e04cbdbd2ea9290969022cfa508d3fd050549c74940d0000000000000000000000000000000001c3e147ad9c31927207f2344fedd541316f4010e3de194f924c4a1450a221285b76ff1894f8b1670731007f44965100000000000000000000000000000000000909cdf5c56dc177daa1f3fd7cc31d79a4f6dfcd462c07812cdf629426b75bdaa297b9d7e67aefdbb58175a21e29edada8168d56385722f339a5b27fc25a88034d348e3d533ff4dc99d28536c1c09a770000000000000000000000000000000009b4c6bd1c460d2e93febfe523c1d54d6bf6af50838e7a10b732c1be8748a0752a517e7103d0ffa4507b086626fbfa8a0000000000000000000000000000000015bf2c13891dfa8dba35b5da1235563d4ee1dac33e89006f5c9fcf06f2fef7b31ca845bcaa8ac608046e8b01c8a61fd2000000000000000000000000000000001898dfd6a0618df821474b90542f261c1febbf2e566978b0fafca44f6dadc57202f88366b19d2c955e4291ac21beab520000000000000000000000000000000019287e1ac6b3eaf412e58511b40d87558e7cbf90dc8af2f5d33825b40fd2f2425d0be3a05d0a49076f4114350dcc601eb929ae82ded73a4876c041d2e52fa811882fb8e22690a27cb4ad3ca05169bbf0000000000000000000000000000000000c0993401c024d32cecc0d86d4cc52c200e59acb34fee2ae052837f467905e736a1118260ee12a963ca2df6e1a6c9d0a000000000000000000000000000000000103f78f0e7c9a5628a66efa91f150a87e67623ded2560aef278a8caab017fdcf181981952b450c67e3b4d3f362822a80000000000000000000000000000000000df01ff335f23652f1c34480d23c62d705572321c0e7fe92556e033dd3cf5b78a3d554585403a7f3c71744c20d17579000000000000000000000000000000000a0e2c9e2e34e5cb36e96b29231f702abb127a011c7ea3e21d59e5c55f745a02039a68d59ce8e29afac0752d1939106936999c516d4acdfbcd488d39e3073db9db6cdd0c0fd1d29d58294ace6d2d199f000000000000000000000000000000000eabff0e6ed9dc358881796441c48e722ea171f26011ab898c5a06758f61a629ae21d5a2595a22dc9855fd2e516b30fe0000000000000000000000000000000002732155a7a2791078dedfedfd3381281554c389bf9b5baa47593153a2acfd22a08557d7a1d49be298e416051b9137dd00000000000000000000000000000000116faa2e2a261e6a3e4de6ad80d75ee05aebae47872e2eed9cd91aafb94a706de673a05f1b86c0b0131cf148a90b2b7900000000000000000000000000000000009a04c09c2a4fce22d237bbe930392dfbbe5c82d480abefbb3be876015e2f5889a0922df6d00d4e94be0e9fb8d2f4a1fd0bc405e3970dc2bbd7dfe0c54b7c64543fc241000adeef4f7aa2f1dd2506770000000000000000000000000000000002a6402848507062e5c5d63b1207a1a41d3b941d21792391f2feff95035f1b4625541770fa5e0f87585cfca670976533000000000000000000000000000000000904095ce640605c957715e378ed733ddf1f94d3beb63543a50c8922ab9f8092755fcc65e2a1ed9232c8cddcb5816371000000000000000000000000000000000ec62b911b08d3e8618880c3784685b2c6cbb07a4aa4e348ab72e4f918152622ddd7748bfcd79f35675cb956d11fcd650000000000000000000000000000000013f651e9104d48a081cef2ae0648816b2b4b5f644a791514e94a8e3dd3001099c27d1f9860337ced1b177b4ad7cd5866c36afa3c8581df069292d53b8ce3e35ca136a0b3f95a894958105fde9c77e39d0000000000000000000000000000000016334abef2a21b9c1926b2086075471bc2d2d2f66b963a41623af91fd2fd50f254c008fa3bad6b53658c2486edcc94aa000000000000000000000000000000001063002a5d17aab2bbb5da49e8bde63a1f3c4dcbc8800f9487f47c6d707109c86d3cf7f9171643418b195e50d7483af4000000000000000000000000000000001213004f31fdd0b0df5d8e3677c4f48624691e2534c02881c6cc6875b9abaee56ed5739c2acd66cb1b10553ba066ef1a000000000000000000000000000000000fb7659081cfcf8beaed9c1daf9e92702977c37a54376597d897082a25f9882f1ae14e7724c0aeb9e002dee708c6b4eb0f0a2bd678c5858be2a49ca54de8716fdeec84e1935b8f44545c740417efa7e400000000000000000000000000000000078f06bdfcbc7c0cc491fdc8069314c8a395983f9a2e5c2d1bec360f36e365da377885f897d8d711e33270e3ef9dc4d80000000000000000000000000000000007d43394d5175e020b3a5d768b60ec763d60cb1bb37c0343930fa82e92fb1becde0a178c4565df320824bdadd54ecabb0000000000000000000000000000000012f9fc96355721c35a6f5439065d89cfca5345622b3f38041b41c036b9bc6bcc980498ddc7bcf807e1b97831c099505300000000000000000000000000000000105307b482467b881a59eda1434e31dffdea531603fd3c460aa8d4f58d32668228bfa585bbba2dae7346141af59190e2c8e420db340ef2c1b5c6a71645e303eee95cd93228770b639287b14b6a5c59ba000000000000000000000000000000001576521fb3be8c3178549969e54bb17b0a3546ac4aacb470e935359e36bea4f43dacc06c151a527f441ab9616e07f7b90000000000000000000000000000000018dff940a21768ee9b9450fee7259663bb29af645bda2acb4d43f4e9d631e0127073f2db04293266e6fd6fd3d005e3f0000000000000000000000000000000000ca6a977016c1ebf52827a5ad52e5efcf7517ccc3ff40df8141f6335fb6c77c3fb8f6b0dcdba2596ded7c3838577e28000000000000000000000000000000000150cc33b55586fac30d316cad6580cee0a070900fe7d540167560b79f4cf9690a5e02cfce9946cf67a95dedc9a7d9aa35398541eb5a03271e2ab5ec2aeb2da80e634f63a050c25de98ad13e9d63d09bc",
+ "Expected": "000000000000000000000000000000000adf84ea7681c442731be8db9508a050d4689c42af8f7472491655356a86fd9a0afd91435bdbaee98db3b1d8f26203fe00000000000000000000000000000000090a7dadc0a14df481e44e2005c9ddc6e026ce2afaba7badd18492bd3a338dffc349b4a339f56221eb795314252d53640000000000000000000000000000000007390fbc06077cd167f53a16f347eaf50ce8c9d111afeabf3a672687441b80e66a66ba3fdb28e2ca8282f3ae3dc81be80000000000000000000000000000000001998f98e85285a428a2860c22a00d0b317854da4190dcb4dcd182ac249e13c51f5d5df5db6a0fd61d01232cbcacd5a1",
+ "Name": "matter_g2_multiexp_26",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c868a2cce65692f83eedbfeef6f9823ae9382fa5ed23395ff2444807e72403d4f6ac861ecd3a51db841889fe22a033700000000000000000000000000000000111c9aa53da85a63ce1870b963415f0d5f812e061aa6bff57425038d1b65fff57a78bdb963bf2450001525a93011a28e0000000000000000000000000000000011770810c16367d075c695981dfa69b072b82b034f8ac371f26bb157f9f9d667aa555a5c6baca69d08f421cd569faec2000000000000000000000000000000000df6146b29bc8226dccfc95a325d791b30cba8ff2495434d75622b170a634ec7995c5b4c689c73582ca861dd21d8e1e49f99387baca30b9cf63ad10c445daa142fcae1ab3c0a366a068bb5efc9abb3a9000000000000000000000000000000000fb30aac6502ecdd3544f1879bf1b3f4c19fb897de6c3a7cbf08f36244aa8e9dea8aaf781f7509d3ece16ca144a601e40000000000000000000000000000000012304be931a1d7440d67740f50b1a281468b412e8b6c54c62b993ec609012c7056fc7e62405c7530e8f5136cacb5926f00000000000000000000000000000000182320f5d9211c08f3ba5d40ccca45cb0060a6d362b4422084617b9d8212e94a9b878294ac176b8f0e959bc124a753310000000000000000000000000000000010be6678910072ed9f932ab01a2d72f7374a2cc82bbd86a6006a495272aa89fd655e6719ab8b3a0643d002021f7b7ebb4283a1773995bbc97a6df107082fed4ba40e2d30c5472a25a7643ca9e78b8b8b000000000000000000000000000000000f1ffed9514ee81e9b3fef4162c8f4980fe0429e57bbc224a9c9976cef7d26ab61ea7b0cd42eda30da97e3f8f5ab5f0600000000000000000000000000000000035b9b349b531d85361a4618a172b510dbc924df671b3fa707b474d0d8b17d30dc8ed208d66be91dcb7632d2f05ce31d00000000000000000000000000000000010030dcf6695d44ad3236032e47f7aa25b9f55869f5207e7ac8641db8c01f5b59627dd3442a1834b8b1fc595e47cdcb000000000000000000000000000000000f91ad5c923572a75d32962567e7b1b0eb84a91d485c968b5aebf8b3a772c2f94e47bc1d5b333fe43574308a78e768ac7f4202d670fc3b48eaa92e925f48821d2ae057d90c5f184edcce9ea900ab51a6000000000000000000000000000000000ae11c60537bbcfa46a08cbc219122ed66fd0d42f90e68243c32010eb99942554c349c021f0e3635bb50f7ca3d106a3f0000000000000000000000000000000019a61254aaa5b51b4d354f444706ebb0bc3edb87ec2d83e830ffe0282bcaa3278e947d053d6678549a098129bace43da000000000000000000000000000000001100f48a07456f01e16bcc833ae0a2835c964e9b0aa850574dfd8b4a7f06d03059e9b4df8931740ce0621ec7eb31218400000000000000000000000000000000003072392a824c386859735e2d203c9d52c19796ccf8538bda3b1436b2f6815bc86d05287f29fd0bb0569a81a57f0c22a76cd8d292a7053c449cb98f13cf768c6e37da9d702af28c16dceacfaf9cdef5000000000000000000000000000000000392760f98883f9cf6c0f0a324b9a645cbae12b780896f6a3eee918c44a815daed156248d6afb25901521b323f6baa240000000000000000000000000000000006375c6629f30b7a36785269d691772afe1b95d6e1bfaaba9459c31086c2697e4ce77d148fe2ea166cc330373583f4730000000000000000000000000000000000aa8e338df7eac5a7b070a69d3ed1553a0c52fcd894c2bc8d1b8cf6ed38983c6c392a9a045ffe8ff40b39d18e7c87c9000000000000000000000000000000000cbc73b589cba1bd47161282642fe6f51f2b3edcdcad6020bdaef369d3f2c11ea9cafb9a7fdccfb89bbbe13560d42d1d97b7bf8acdfbb148814afee1df79aea17261dad6f78772111a6dcb021d8c79d0000000000000000000000000000000000e71692cc2342d1e93e0ce72be69013023d012dd2294249dfd69e1d610e2236ee2cdef22446f1996bd3309825989930700000000000000000000000000000000013a1bbd3237dcbe44e05234f7e41982f4fd951d3741a3e90345418af1c922d35edf776a27bfbeaf7a15658db67164bc000000000000000000000000000000001197a2ee5c2541e19b5368c97abf51fde3dd0b922c3d701d7d84552c9f47b38ca09a8aef8240abfdcb03292ade1ff04c0000000000000000000000000000000010ca3c22ff8a47b1c683a58086ed9d831a5c25b6ce5a1971989974b4760cc9e83a1bc8d819825989751405b242eba379efdbd5953bc33bfba09fe7b3ee22c46c3a86f557e4b5f272853e67fd95a0f9b0000000000000000000000000000000001306f8047ba1a3417e7993bba0dfee9077eabfc275af91d0b882a53199874e0777d8dfd29767186d922d49087fff38b20000000000000000000000000000000005371b760380a6d287e129b329e735413447969eb9048def44f5c5987a64323d2a5c81484c40b20206832b86a4af9c4d000000000000000000000000000000001552eeae620c42d0bc4593d7c8e2c8fb4d6dbfcdde68d57158a7dfe837a1870a73b45a97b02abdea174a475a7061331400000000000000000000000000000000033a6dec61540a5cd5773b76847dc5016b309c5a027639598f51ae5b1067b3f7a02f5ea11b0e1be77a3ac236cba15c929a331bb218b99fd38451483a10e8add23c9641b975af3897670884efef90d4520000000000000000000000000000000012ad5ff49459fd3a7940a69e2a78919876e9b3a4f0c142499e7b5dbcadb5c2b5d79c5dea972f0f0acdfd10ac53bcdd92000000000000000000000000000000000ec1be9cb379bf1e24bd5429a4a91857bc3ad45095d15bc5537c2ba39407e9f2edc5fbf711ef4287a73ea466d4f53c3800000000000000000000000000000000173605df66aaf51810793db1cf2021de6a7645ae84a5d439ee035b917d037d9f9ff072b5dfe8b9ac69feab60fe2d70bb000000000000000000000000000000000d0bd336825381ae1e18ca37bf6160ae32b653ec9f9dad159006e92c24b661f22b5629ba323e9e06ccc5887a962ec23fe9301dc826bfe2988cf93c29ca9f01421b75ba63c5ed2cee1599122012ada36e000000000000000000000000000000000f5e593c6588add92cac2c9467247fc6d900f20b4d3216c258f88f3334eecaccbf3eacda227e2da46cf520e5102a9cdd000000000000000000000000000000000458177ad6c190222e53e054546413c13216286d414e3509b7dc794dc0704afd26bae93ff630c6157d05d46d805a04470000000000000000000000000000000015df8a7720d389e6112707e37694afac2f97282676a89964deabefddbb3a0f1cbc885d4c875b945b8303c1ed2c0f46b8000000000000000000000000000000000e3c7f1af7cf5923dccfc1d25bd86088706a3a44f5fa7f97171228e8f2a2b18e9631b2a63bd5a75ee0bb83fcc91a45c30a1cb530e8b828542fa4114de6aa936bd2be5ef3a9b7a0e20e475022381d62d40000000000000000000000000000000017823fc8a56e6e5cb9924037ad6ad1b43237894a877572dfe3d3cdc1120fe83e01de112b55f7f334dcb5c6247c210613000000000000000000000000000000000daa01f90cd14d82d4fc40b60b463089fc6c0e567fa46bae69184d0e3cc5acdb1d759e3291e2781fe0b65c734ddde28700000000000000000000000000000000164e742b123c19e52e2d7a6727689181f323990a3f3238072f7cfd7fc0f55b7be4274c0df194d85060a81f3744d3978b0000000000000000000000000000000007c03a1678b6e91c1bfc66ce8fd419cea13c7cda3213856ad21823b06db94538153a15d43a9d4270edf77b9a5ed490e6cf2f0c33bd044e8c4468b4b7e137ae294c178e7b6c9f19878331fb93220db2cb000000000000000000000000000000001865bc91e645e2e24c3efa3afab8b0e278dcf16b29831f75b3eef0b342479e997b9c5f8ccf67c789c830609b3cc425400000000000000000000000000000000018dda7857f919a6a49f6bb465c27342c8fab6afe6350c43b98e91a3105276f3ac27268454e9a9c6dafeb2218ddc7d3cc000000000000000000000000000000000b098258ff8b185a5c59b46150954d52db5a5f68bc7975234491406131e4f1286ce79156dd1290aafe688f936ad34e31000000000000000000000000000000000b294e9ce904fb9e243d0790147b6070b10ff611a06e3f639aacb744154d02016ac08f6769732d4f6944ce9257680d49e5f460dacc592bb947ff6f1c15b8464824aa5c957a645a763138ac1581ac5768000000000000000000000000000000000e541a22a7a36adc06e445f42497596e1017a1d99de85bb945a195cb3cf0c14d39eb7a2aa994cf234eed77f6307cf6410000000000000000000000000000000002de753e41a16565e5ab1b61debdad54950e9930e04badc6e356f10711d7688befc6827040356c0f0a8ce4f8d7121b3a000000000000000000000000000000000f2202e34ca164f1a6c0afbe179b714b303d87ef14534fe3f4230180f709dc63af17f04487264b3dee6b24ec4d0a423f00000000000000000000000000000000004044d9e3b3a77d6a309780c870a65e05e1ac531c5420f6ed0056f5e728e2b83a968ca90d579db50c2dd395f7e40beaf26a9736f728e16d7b8ce0cc59e2ccc848c181459fff4321982c08e9cac5794600000000000000000000000000000000166d7692fd30dcd06b9f01ba2101870ed347840509b3242f7cecf91fbed91abc24b08b08cc39c508e6499a2f8bc3637700000000000000000000000000000000076ce6dcbc77812b4d5b44a50edba5a082cc36dc24a5cc348283a4ce1518198b56134c9807ef850edc9e36e9a282b9ff000000000000000000000000000000001261d9412245abd7ba3fc1597f34179e54766c49306725d42588545e14f4e450ee1c7af913ad7225275c57680c23aa6300000000000000000000000000000000096602b4eee053998555ce522c060d5e04c7961eeaab0145d38c9b13362624f54fcc8d0b77f2bbaf8c312a3279f06e4eccf0a9be4775d65bbfc894f8ca66fa6f69d4249ea7f6b076fe193f2805e64f940000000000000000000000000000000012be34c18145aac51a1494f4052edbeff14c2812ff494cb78198cd7d9db9e951aea80490c55c4ed926f6a96a2c337c880000000000000000000000000000000000536e46a63ec5ac0f2f4eaaad6df98322c6a981cf2fc8ef253269cef20a76ba1ad089c24cba4ad4680dc4192d66595d0000000000000000000000000000000005363b9acb66ee95713b63dad076529805c0dd8921c738e205e7b1d0410a3ecca0870aeb2e64cf45270d49b473371ddd0000000000000000000000000000000016749b2b09d889b883b6fdaf518345d4cf097a728b833e92c4d21b5c41c8d5cfc0758e895b60ad101a74bbb6be6ca0c5fc6bfb37cbfb10a1ffdfcb91d9a52883cb9a606f4ffa8849a6e07386dc9bb34000000000000000000000000000000000067a684b55fdeea39a29252b355700a4810f083909cf2c07a80b362ac1b4d58f5900c68d266f7ad81ea278c0931bc1ec0000000000000000000000000000000001b1f78d194d77cfb4a2116ce9e29438dbf38c52733b0295198159d7cadb2584d86a75c24aedeb36234a0becf9d38a870000000000000000000000000000000011fced2244cd959872a25c0c7bb4af6151d99e1aac079c606db4987b9ba111261d4a16e7d82362b865324824445a946f0000000000000000000000000000000002659e7016ad615ed80ea1ae020903431b470bc0341f8e0918de9b8d2e933dd9f2d9123e9e9d20bfb05d49f71c3c454cd94959e16f6d780628694075ba5aa1a476d89d8fffcf4b4ab7e6343c011fee920000000000000000000000000000000008f3c5de8c94a98dc5ad7846c53980384f997d1657f7349ad9b51376d41f4b21861d212fb6428bcf2347d8774f44156d00000000000000000000000000000000110b245b1e788da41dcbf60a3ac4987c1925696dfca85d450107f654fa1230adb9436d60c9e742dfb4e453ec4944c56c0000000000000000000000000000000011043b975e01df36a36307ba9234a18b97aadb9da509513b13e4f3c80432b0cc5e69a3bbb3cbab8df41bbcc92cdbf60200000000000000000000000000000000120aebda10c52a67d23842e2bd9a897cf38c58fcd11e4e8c5614db5e409a7c03111feebfe2f1212ae753497dc59d6ae9122f3a5e940ee7e5038421619daffb8a6f433605f37e78d863f814b51b2ec4e2",
+ "Expected": "00000000000000000000000000000000021067690e6e001e3d0d01449a7257348c4ef68e66dd47b9014d7687d44749be1f33e6be95df6a204169ab7103dc2d3c00000000000000000000000000000000062efa0c36462ab0734128dab5da8635705bd1e1b540817c5805ed9417f176723eea92425db539e8763b1c79b9923e9700000000000000000000000000000000176c9af1970f026bcfa87e6f85a20ed498c28c6982e21bc050cdc29c0f0af832ed4424082e4862d985b78519cfa75b820000000000000000000000000000000018718b0d0fbdf4783cd0b01524ab153b891fbf08cad60241a3f3163d2c3496c36afdc6de62ab3c9a037f88ee408ce5f6",
+ "Name": "matter_g2_multiexp_27",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018adf92d8da050c76118a3a3b2ee43955ae8b14ddc8ed64f5672f40de475f7e0ba6ff60c4b6ca3e863d7914e6de2cc330000000000000000000000000000000013d1e19011a1ea90389480d14fa608985d895e05edd9c28fb34646f70fd7bdb7857fa785b1e3c8a2997da6c3b5337ccf0000000000000000000000000000000015764827d9838c2b011660230ef9805af388fd997cc229c939bc5f4213d517dd837328c45b0b8ee1d6508cb70629b7bb000000000000000000000000000000000d58fa30a2d095ee8d946e50a027ac4cfdd557b3fd9c82dbf1536ddc0f42491a176ecbdb026306e6ebf1bb182a4e8199b3908c739d505a1d6fa85a6dfb7a155202710b45861f1a8a7ac7bb3274a180cb000000000000000000000000000000000cacfc8d0bc6f9db737c8a316043a6b52fd5946937467afc09ddd14e509a89f2445065ac8a8c56454d529d67793edb0400000000000000000000000000000000148b1b941f159d93170fed949d5f53bdd2603d78a49443ac0e2353130ff914376e018c3db3d12b807d105f2d50eded8c000000000000000000000000000000001382a3e98cfd072807214479900a8602bd666cac7f19be0443ba1354bfc05666f40384e9ccac314b5d0a2bec1c90ef0c000000000000000000000000000000000c12c2222f67a5adba78f2c0be5be95ed743e835857f4204cf47b67fa2eac45cd5985fd82c7a3904944e7b84737374b17e0e27a8a416eb38c989a66b84f037a5a24ef3358e20cd553f037a0a2461d31000000000000000000000000000000000197ff997d6c5efa3d7de8e16f26082bf13a2401d6df5f5c33c6614c36105f347e40216c907bdad9c1df6ebbd44f41c3f000000000000000000000000000000000f27a0bf92329730d776a83583177993b2b354a212a9c004f9f8892a750c477b8d1e68c13127f03b1629bc8392d06f5b0000000000000000000000000000000011b239cc6914a321385d907527b85713a0d842f5be80752f4c5758586dc1de944b6e4578bbe324f16838115e9c866bca0000000000000000000000000000000000cf93c5b48cd9de51ccaa45124217cabf466d07d6fdf4a7bb810443339ec4af5b74931bd07eb9fd31c284c05f3f539e0a3cbab01c34856b892aacdabe63d0a0c241ebc137a88c83ad22cf38997b211b00000000000000000000000000000000137b12f731ec925dc51e20a9c90323d14e1497e16b3a4b5651135054ef0e58e9b18167da15220b9a4f7d81e9a7648fc20000000000000000000000000000000000b2d3ac534e1e5b2c9ff4092c2d8dc5efd99121de7df953e5426eb33934ef07e41b196eca50f5a04a936881a05f2b2a0000000000000000000000000000000004feae2377d950717695606844a4873ed7b5f6703d7a63dc8b960b99b68efbba710c2db0f1371acbee314875b97ca054000000000000000000000000000000000f49ce3061e7254dc1bc8af3636a05e098cb96d81fb31e25da97c6266adf3c41a74d46ff32f4fbdb4cb7e4a3f69e827bb386bebe0e49b7f07b0ac61b15306c2515a1ad6fd76a1825dd29a60e845c0e4a00000000000000000000000000000000064ae3fd67250f2c6332e1e149ec09946147e12e0d871403e559b49aab68190a1454b3ae924727b6dcf6e1ab327c9d7c000000000000000000000000000000001131f91c7a0e1854bba3958b36083c27904cfbdb8b8cb3fe68cf578bd1cb6f7c6eff91d98e4b99086926c5d4272cc1f200000000000000000000000000000000071c6a92a8d460ff72d172c204c8a69d6b6752b8c1f731ec63f7f394c0c3a2a1bc15e865172f693f523c11cd4ab1f88e000000000000000000000000000000001193876df7f4a1cc9b337a41c9faebac2f209b9070bd75294c2a88d3091a1e55b51fad482fd2aee8f90458eeb7e981fb8902a82d33993a10c56b2fa3333cabf1c5d47a9c78354d58f70ce4807cf2062800000000000000000000000000000000025c20ed5572dd1c9a098f241d2965d8739878ddc57c017632afcf6e54964894adbd6d30f62f316c9c3ec7a08268afc70000000000000000000000000000000013bc3e930f4fd5766db8f04e1ebfaab2b67f620119c39d687c68619b3564f3e8b74666c9f8bed6c1f080a9e23e9c0f22000000000000000000000000000000000973a3cf19312f90843f1f013b05484064032557807ca67b2ded4a27fdac12d6cd0e1416c8998cc8635ce10046adfbb900000000000000000000000000000000108903617c78fc608eaf007aa13861c970557f2693b24e8a278920897be9694570ae6e6c7749c3eab84d5fa3af5164b1426a4e2317fee033a226a91a52a5830f9ac2cf5f329feb6bdb382438b8a39f2a0000000000000000000000000000000005695975c140fa14998e5916268bde2135cda80a45414fa85193fd6e13c6b5a6486898f590d76175d8ec2629c923e33600000000000000000000000000000000033f58b1cf67e51e9ad817b31919530cfdb5db5ca4a537d9b006b63399da49b2a5077bf5c3b3b4fb10b2478f466542540000000000000000000000000000000015c532e40ec04d9143e308895b2e7e3d3daee093a5840e1e76ab528fcfa5be57d9796ffd58ad5ab7df6f88aaf34706f2000000000000000000000000000000000b55747d1e8b66e2b2fea67229f2b7b17d58ef547ca841bea8db5b53fafaa18390f11b8170c41a5dd29331917fa2e348de0390c05fb0dc9b4a3f76b51cf952a11b909ce13f9abc9fed6a349b8efa98ad00000000000000000000000000000000001ee5ebf73bb40a5c0822350853bb5aeead3262380dc274faba6b04e58e7fb9d5a4ace109ffa5011e73e3d89ee6fd77000000000000000000000000000000001427659e5ab1f8b47edddd27c613b578890d4c66c835c0cf8e8daf19d0ae842f0bba5bc83ed7248adcd75cea5d222a270000000000000000000000000000000001d4560185690ac05e56c2d629d599bceee3ed2919c29e3d1ac54e80ae99b5eb2f93bab865e8c1eef7206f96b2bf4eb20000000000000000000000000000000016ecd3589e3703e5b0ef53790130d5074d2bc0fd5839d9c6ff905746a77e393f73edf53b98b99d9c87a1fee1086aa8657431db9e576643f93505b5b25836218759e736c0d650a5221a652338b0073eb600000000000000000000000000000000163850016261f34de2b831a0a8dd3f224adaa3cc279cdb40e0ae976bbf736dec26c55a6c79cb1c623870b62ea216274b000000000000000000000000000000000a79af5c054cd08608d4be1705058ef7b4ec38a8727560d960f0325d0ef915c049a89e76956d0296bcb6c96333c3470c000000000000000000000000000000000ca89379e558c7308edd25bf06dc05db857204e9351299ab66bf050c8f051341a6c15a02864c679f07373038de3fe87c000000000000000000000000000000001929f42ee5d9dbfd1f6656f61e6243ebf0eb491762b7f3608db3f3e9abf565ab1524f770cd2ade334885d7479342c92c6745a32591e359efa41e9ea93a016d2eedf1da112cddbf31818e8d687b36af2e00000000000000000000000000000000193b6cf7300e47ecd21a05a71b13a8de45418d3f67931789ce6111b8633b9f44063ca13ba8c8a598ee0725caaa3f277a0000000000000000000000000000000016884d982e2ec0fa7e59fb34ae8708d0bf4abfc260837ef4432e8e04474e504b85450db8af8e6809413c90268801fb3b000000000000000000000000000000000fb48a8331f278845979beb8cd21060355566af215ba44029455a03d0c016daf0f6b7c5773d1a99e893e76b4411a53c70000000000000000000000000000000007056e30143058eaea89a3065e1de768d49860b170d4c364a28d38475f90711fba62c1787adda90dd2d347da72680f4eed37a5f4bfca6b77ff9e4f7e03bfed52ecf02a8f84ed3da6da2787a4ee81ad9b000000000000000000000000000000000501fa9af88e28d4f0c0590a2624239bf1724ac7174b0f1d5fd7527cff1de9971d6aaf28ba4005e88e181daffee6b20f0000000000000000000000000000000007af5e30b5aa9ad206645ace12cb2b36cc1c6068e604184ca8bfaac5a4ca327f7c43a74d43417918da7df84e3bffd282000000000000000000000000000000000bfc0538d52f277d54749ed0b69697b4c60ef0c5483d21dda76533e15efedc9e2b2ef07618457d64bae8ef922c0b41f600000000000000000000000000000000048935cd352e999bffa613e3be0a9f9a063d5b5eb46cb5056e41ba214e87f871f216ff41ee297aaaf2994a7b6433f58d81633dd6e729bc17ddc596cb1f17dc6f0e50c052a0b8c5a4c83900d918a9eb560000000000000000000000000000000016ab1e8b6f41891e0b65f14397c0887b27ff27e7463333e0938a7a1a181dec603056afbefdb23b41bbfb2c05807289b8000000000000000000000000000000000980d0ea9ad5c87bbe1aefb708061f85faae1e1e3b01c55bd577631e5bea2b5ffaf5e2478f5a8df89447fb8a73559729000000000000000000000000000000000784d0c5fa243bf0125cb2c83a4040715197e99d507d71a3bd9ca396074cfda652c1ad0dd95c3cfae369e68d3431ee7c000000000000000000000000000000000e533bb33e6d269dfdeedf7d17c3e0c19f694d151e8eef801c326cbcbc463a42558f58cbc330bdff0d8d91e2974eb4cfc6b019d29219b57404baa955f66cf1b2ee6571ad5b80d471ff6db569e32a1a5000000000000000000000000000000000050f005b00f371a7308b5d7d7f67f7c00bf15acc518942607f32686feab5eb503391f964eb7ca711aa6c7b4e494d7eba000000000000000000000000000000000e2ee5092170ea3da0b1397023b2386c65ec8b090484353f2e5d64694aaeb8d5410ae22c92662fcfa21566d70173ef36000000000000000000000000000000001549723160fc7b8f5ef9a84bd1803f18b76698aa7a663d9c107c9ff6c6d02894edc80fd00d436f3a942c05593c5464ad000000000000000000000000000000001032f49e3527cc1f1355c65edb21220c6afc88919ff67ba99c65645cd3b8ca6662dd0146f6a90d92558b3f54815a361d6a76411ce02b4dfc84ddf62ed26508a2dfa5edb5a98a6a20dd69e8b8e7ad2f5900000000000000000000000000000000170b317e49f1304570a3a3e6bef78fcf8537a451ebcfef5afe3eac4aa1aa87dbf95d0f870fd3372d37efc9e663621cf7000000000000000000000000000000000269ae0677d71b2537078e96d2593482e4d41b6d1d2cbec755f307735faaf79c01fa27f1103cdfae1a9bdcb665f592c9000000000000000000000000000000000b115d5a9fb9fd9361d0573a8d68c5193f02edc1cf3fecf004c6603f118f28ff394220f6a9e1051a5d9d4b417290b7f800000000000000000000000000000000107b45614b18c2513f8c42a0032cf0f3f300157b39d2969ef7b126f17a9b5e8e9ecc5a61a2ed4db92134b0797f6a0ea35906098e4ad7e4eb2e996075c7cd660fbc399bc942f9080404b9d0758c4ae14c0000000000000000000000000000000003de39b056f8f0248b138437db1536b7bfee29af00c37fcd14c25c88f0f051eaa07c763d94c8ce497696311736c0b7140000000000000000000000000000000002b52981e828f8dc1cd371e6821d001e1f96d57a865a3c0a255298c43d52741b18fc60903d1a5ef6227061dcb243096c0000000000000000000000000000000016b5335f0f9516f52f2ed45fe723ded427206ba96af0879958f1f22795485b2867e953de3d9b3a9eed2c37f26838e1540000000000000000000000000000000004c860058c7ea2e6e4eb2a65c1dfc20b3070f89ff58ab99bb51a4eb9e7f0642f7b32d1d9f27c668a36a9e053a8d585f394ef8c281a9be3766fe784ae017d93f608dc2cb97cbb7dd3e3814b5ade845d370000000000000000000000000000000019cbbc125ca1b89330c21ef5b42fe0dc1e795271ce4a9ecabff04eec9029f756f180520f0e7b84be2e9fa4af395536ab000000000000000000000000000000001630cf0c4f3282689a3e01b5c8f9be3803f60238bbe9fecbb0d9e8e49f4ec9f6123c44840acb8cf55f8f6bd15579e6830000000000000000000000000000000012afb848bc0ade8f0c25c6c342bb651a7481be065a48944bbedbc14c095af8a4a048fd1e776126e2128f904afbcb17ff000000000000000000000000000000000dbc984f9ff907ce5553bb11a458deaaee0efea49d6816ed7abf1dee7b70cb18cc669d4808e75678bb898359c7ebedbe6feced33019b3b66d335f2118cd22b2952cdf9757fb3a0cff55b7c4f245fb438",
+ "Expected": "000000000000000000000000000000000be6dee62b8c85e36a216d16c5477a7c58f03b992277af83d9b53b3b2169414b72bcb4a97e3667482e888738ff17c94900000000000000000000000000000000067337c69c37ef6f0ae59fddb84c46a2afe7fe047ddb57b3b80437609f1a21fa5a73420fa5b44704ca1cac6c7a99d9320000000000000000000000000000000017fe6f37d2410159e533374ff3812714dcd07610d75a53a5d502cf2f51e750c48858db1e109f6aaf724292c1402382f1000000000000000000000000000000000b8ecfe1f5f5d95777b0fe5d94fe81b82656e6e5a62b7591788baccd251d93e4bbc6857cc87cfe6b4ed470c33631ae22",
+ "Name": "matter_g2_multiexp_28",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000126d4a9ae3550e31185aac9011e3f086517cf79a279326c264f51bee6615dbcc730d78055489b5602e91b08f96d23882000000000000000000000000000000000aeff5fc04fd06c26af8b048fb2d0d493525ba5c2bde30664e7371812d529ec7dbd584c056b05fe02179b7eefbbc45fe0000000000000000000000000000000017c6538d2801947cbb646d4ec8b70b1e24453f7a984db7ba73e3a5dcf595bdbad9703f2d846ab02491e5e3a5bcee0762000000000000000000000000000000000badf551dbedcefbe7c303a5c8a52151b5460caa22004028893af4d8a3fac30cb1da1e986f9124acd5db7a634657dbd0cb5e7df372d346fd13faa90b0d6961372ce2f32ec379e5e50e7ed8a13942cd9d000000000000000000000000000000000bed71c7d878e7ecccd8233e3e604e564cba0b1ce75f726f846f3a6e2f3b4f5b12a28b8638be647f5c33226edc2bc7fe000000000000000000000000000000001914c20aabaf1f6f82063223053809622ad82a3a54668bd600db1aafba22aeee5c8a07584e263c91cb0fc5fb809da63d00000000000000000000000000000000056d9cd8f79a90d16b36bde77e546f8b3064ba7dd0fde78d6bc538bd6ce12a4f32860205d5d396bab3d70deaaaccf9450000000000000000000000000000000012f7e420708b66132157a80753678de292998cb6c4f00244d3c47a6077b3401132b73c7f52369aa2a6a90892f7be4ed913a5fa1674c20c97d08608d200f3f7611010e6a25a790853ed4ba0c5aacf111b000000000000000000000000000000000339aa1471eddee8cc0a4e4db5a29c3e4e92cfbabe023995a79624614aca522cd459dfacc0cab346b1cedac347e1df100000000000000000000000000000000016cc4ee8cb72fe09e65616fbe9bea1a0077114ca841ae335f1f9eb5a0b129a4bdc77cc6dae8727d74fe21f0d870a43f2000000000000000000000000000000000098a21da6e983228ebbed0ec3704c9d2521e935506c0567e3bbf9b9c379ce6d33c3d0dd8f5e013b431f740964db634b000000000000000000000000000000000a7a38abe8e282544ec6c8740dce8559fd264393d0a5c9af9813b2430bdb92b3150eacb6732b9cc278d0d0e622b263ecace10870acf190b373c19ce615e20e5cb96d3c6be3ec155f2b29825f8476b7740000000000000000000000000000000019ed305bfe8d8bfcc20794832b3c117715b6a658c0bfeb629e5989f265cbb456e857e53d168932589e4ed2806db7c4b4000000000000000000000000000000000e2ffda25fc316a38f556b35a7a3acb1a2bfbc1f9469a1b6427ed1f216e113a379932b0547f5370be1017a1fa0266cfa000000000000000000000000000000000ebc493c9a79b8ba58f48b90b9d287c74f505dcb484eabda79ada987d63a4df04d671d4c4ae4b32f8ad5db6a1b80f37f0000000000000000000000000000000019fc715d26c0c7a0c291ad8319e2e8f2920c63b4d4ed3f0e2f376aeddd4f7bd9269175ac8d0f421b001e2e48634f3f238d9e38d9383f09cf0f8a8077f1d1dba091ff0abdf7e77c3b65c2df48d6c6f536000000000000000000000000000000001285ff533da833a3daae7d815b1b86feb6f20b7592af8b0eb76240f390ea48b69a75547b040e7282b71779f450d3510c000000000000000000000000000000000813d38fa21c1f3c87b9c97ac03e6aeb8fa23e0340a0dff4e3892c774595648743d0b8980a7bd21648ce9b16a245ac3400000000000000000000000000000000020a69dbfb736c64e4cbc800aa415729b24ec05e901f2c7ba38e49a21c3851dc03bd4f7ec829d4326fe6c13867069a07000000000000000000000000000000000d518f3944053c8f74c0aea1d054d89106312880de4479b3dfb45b00945ff8bb58b12f9a489fa9fcd87194a71475d0a1abeffecf9b404c6bb2e2d0c78fbb8609a38e3d3187587c3848e8f9781b7e9f440000000000000000000000000000000018c82052cd483eee7aaa421c2b998ab0b4b32326dadba03c1d923726697d3940b40d5109ba34de09439e833ebc19daca000000000000000000000000000000000e4feddc3eeb3fd1eff8316d5b0cba554714713e8a605a55909889970ea2c8c58bb6c568024709def73b29a5a76563c100000000000000000000000000000000098da4cd0281a16e2e3e542ebb92269c8208a3d373394b0af92dc8a2676f9f0b6e85fda9161e32558e0569cfc7b1f3df000000000000000000000000000000000b7b54b51821fc037f02167d2e640f8dbfd1472407278b4bdf47b958da39f28c64569c3199846c293bf60e86aa45f205adfe53846c0038203d8b8df0cb636aec7d4ed7f78b0b0c1734be448bace08f340000000000000000000000000000000003058abd4e3d49c86ffac9c95b1f07b66a22c42654dc4a2e3b07b87c22024a8bb0ee084a558ac22cc9fa286861fd77ff000000000000000000000000000000000fc9a89ee26c323df22add487a6bb278ca3f4c9a91eba4e067d5abc9dd3afededb4f98263e10083cc7ea224f28d3bbe100000000000000000000000000000000058eb015f1e14da860215d59165e12feb8d1317f652eeb76b3f08b38ed943c94e632dbf8145233dc93755e44e027553e0000000000000000000000000000000010897d5c2b481f9937d830b333e7649931e801a6bbffb7d9a3ee28ab1e27889691a9f0b9616a8437c3cda942bf07282206e9d4e41b628be51690b86aa8938db066c052f3adff774d35eee1e332312d3f0000000000000000000000000000000013b88963296d8c8197cafe160846ee11365b7a991b35cf5613dc57714aa48307f4dd9c6ff9704b29905c18a41a48010e0000000000000000000000000000000016a97fff65fca5ff282a818deb8100104308b8d9dfacddcae32fc2b6082331b44fa70580018930fe1ab9d9c1b13a59a20000000000000000000000000000000019cd2038acd84c2db1f0fa1b7eccc5f7ae3da803cb72c4a1e8390d49e0adff1d88a85696d9daaebce9c6b8a2f861fb36000000000000000000000000000000001271338587f06847770c72dfb3d9a657d05f8c7a012bec77a7d40a98cb1637ae99281c82668486119608b01feb25e6dab3d349b1546a8c235d60c41408c969a0fd42425f8b5ddc1fa5102d2821bde2c600000000000000000000000000000000173ed7c70f4683102cc6a276d192a8f3b189197d5ea5dc813c7d0162a1649e906f76a1c9a1cb1ace6e4d937934b72338000000000000000000000000000000000936d260b789b1a2a9d04388caab364049395be61d320aef66ce50f052eb462faaa2017731518675bb0e4a2f050e4f7900000000000000000000000000000000070bd1254cf4b209ecb40afe248f2e53c390636625460439952ca2977be021d93fbec264c31ced2a810e8a5e54d750230000000000000000000000000000000016ddc3312f8ed359792bd213d086a0ff1540e3e5a2dedf6c450fb96a9b6d1edff9bde31fbc04de382cf44694a631178229b83950e79750e9827ed92856e4d1e1b5f0b47c6bbf3611a1fef8f2fc47659c000000000000000000000000000000000aa4bc6e1a3e6c3c45a29db74b27af27b61856e2cf385ce0e5094ad53db4d31c4af45b5b234c66a21bf15018c13ece8000000000000000000000000000000000188affc993bf6c99103029c1e406bb1a693e4f1dc650907809ba3de1471d41095dc1866578962c72538ca85d09fcd22d000000000000000000000000000000000e487a7151916694b980e62b64ba49ffc54aaccfa0b0fbc5c14fa4a50d1bfda55698df5cd8570c07030f145c49a4ba9000000000000000000000000000000000084a05dced107d29a0fd4cf817ab67017ca33018d5c7302167d08c64c45c5c455fb5c907f21c39b8a86d037a126df4e76b5ac07fb4a184dfed685b93d2265cebd02a3296a3b0416cc6a115242079752e000000000000000000000000000000000ea7060a07dacd84287007a05b494bf19a03e5a759b0ba67624c54cac3562c0ca3fa6e444206614d00d6d6684b86bcb5000000000000000000000000000000000eb2f332f4481276f931d2192c1a9f6d7585e85f248a8ac95aed398cb61bda05230bf8b9c041c6f78be3b34668a9c1a0000000000000000000000000000000000faa038219f844e379d8cce55cb8f0fe2b55548a0a0e1e37e25ba4f432e6b1a6451b8f081c171490bf055f81cbfe5f8600000000000000000000000000000000037c70d4e8befff257c4bc98a4726a961f3e2e68e7e02f9f2c94aa8f5fc67a1da44d41394dfe376a6c04240e4cd5825f3a7a25ad9f02bf51fd73550ccde12374d9b151f2f6fe535bfaa43efc391f789700000000000000000000000000000000100a24d21c0ddb20d76b6d9fe642da5ac1de28afd642ab5c08574206b8b64d1fd822d295476bbdf2ca7e9267138034dd0000000000000000000000000000000000aa7e4f2f77acfe8b4c8f3fabd56b17415ee9bb182bca1db15c399479ec60382f980067b9d4c4ef7556d621259ae9110000000000000000000000000000000012f7a7f91a988fa661c661013736f0ec92b40f571ac15a47067bb847b09ba128d1dcaf8049b941a51cacece5db4e1eb40000000000000000000000000000000007528b0ea66b6ab8d5d318f5e4d1c0e9a4f504057dbb0397b614a1adb160032127f2ac35a1a98da70f023cd343a35ffd47944c8c814f143f746175ba0b2d75e2ae73730a265d869763f0e986c088bfcd0000000000000000000000000000000015d72b8d4e71cc092c2875de80f3d12e003804d980a4b1dd13cff34e9336397c4533b6ae3a03beb2f09312a605947a270000000000000000000000000000000005976027a98f7b0caf4cc7d0d71440d3e4fffb1ff65fbf32dc890b275b646f2a32600a6215d6b2f999eaec8e58cb6d5c00000000000000000000000000000000111583b7734be53a7d4d090486070cd3d9622156c52871ec79c83ca024880684eada56a36b58cfc3490e65de41e10579000000000000000000000000000000000fb670b553c2ed4c81962b149efd4b0c77edf6ee70eba88300cf264dda98190e550540fb9fb95748599bca3abadd752030f33b187df3516866f259ff959d57fa9c53323d5c851fdabb96e5ea470518ac0000000000000000000000000000000003900e7cc0a8e891dc4dfc45f08d97e73ccbe2021a560a92c493aacd9c0614ad100294b5d7ebd634ffe4e5ea301a26170000000000000000000000000000000011ccc136127189728a7036e85d233fd150d5483963c48074f9d8ff83a0791c950da380e717f2bd0bff8fc115e9e886290000000000000000000000000000000007d3e76bd1f22679d228b4ee50a60cf1bd1fdaa171372cfa34bf4136a091abf7e5ef3c6b3446fd41d5de68b563fc7ff3000000000000000000000000000000001107f636d9187155357bea75c943dafcfba2394a9300054026b46d6f9db31eacc06d1f64c2b139af297dc4783026d98f4da8401050f30459e026a207ca631f0684a10813c64ee86dbdf06b7b29cd9786000000000000000000000000000000000e3a4101f6af3cf0d5d5aa5a0ebc26852dc69f91c06e96c5f1c7f8e4528c3dd92cb6f629620136ec356f0657fd9ebc6a0000000000000000000000000000000008d34dc3e1fa8bc22258e23b504d442a11938370325c101f1cfa52f313724e0894be722646195fd078c1a49720cde8c900000000000000000000000000000000163730996c79787e7ab89030de2c26e26188187762fa128ba4378a398ebd906dc56d99cf228591f394396248665c196600000000000000000000000000000000008f0a8b3d003b6727834228798950fb7a3cb6b931bced4540693445a007b474f7459ede17f87158e932e4c9c094ab904d940555d48649f30026f70450b2caf2b8f7148b28bfd4349458ae89c323512e000000000000000000000000000000000cc2d30f7d3869abfc34719f40b0ddaf00f52bcee7ec09a16de51785d55531fa7fe3ca1544d7103b9caf7105d60d9e930000000000000000000000000000000002ebd8af0bd3f82dc9dca585feaa83071534b2bc2b3d2aadbe0d01d759ade77ecec3b3f7b72f82087365a14dc205add80000000000000000000000000000000011aa3734a4b9168d3c46944cd726bcb203b94b25a97437a6aaace9c84da708bb073ee10585f28bc41e0601567863c193000000000000000000000000000000000ceb4ae5a8b506d31e77e2a43f3af8ba9459b887a927ca5287edbc2ba7c7cbba85a6e4d35c099b7ec7bf7eb2814cc38ae140e30424d2cccc91be1fd3a62d9ee49c9d64fa062d9350b3fa567ec21bb06b",
+ "Expected": "00000000000000000000000000000000192eb406b52075513584ae3c6093fb534270d716c79961d0a3c4bbc44096a2e8d28228363e2c8da54857945f1b983569000000000000000000000000000000000ee0d95748b13b531821ddd71a15fc529a2ce2c99a66f14e28f97478c3c2d524cb7c4cd7e71a1027030765554b8f50f7000000000000000000000000000000000610ab3e064532ce261aa2ba4f78721ac4f78661cc13fa09ccc279267e6f703f1bda17265a5eccb0061ce24d31e000ec000000000000000000000000000000001966a334b16e64e4dbd66119af97bd2b8d6afec0eb1b8207f437c00ab134ff369b3b3c1bf51b871a7fe8ad1ce93dca4e",
+ "Name": "matter_g2_multiexp_29",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004c22bd94b82ed3b106532a58a0253daf51f579b9d746c624bbc6b58603942eb139c1b576241ca8fab5bf1c457112bd80000000000000000000000000000000010c6f7551d758d1128add57b110227296e060074e4cb934132368f079a794770ff406fc7717867df0f461f5c9fe56960000000000000000000000000000000000048f88afaf6eee5039b76c0c5b4b49671f6fd04f38bdee1b1c8f347a9dd4e6aef387b742c8f9a8aa387ab4d01fe4267000000000000000000000000000000000e7be987d0411dd7138e47ac00f9f07c4737d93aac501edd16362ea5a633c9071a6bf542d4db540d75edecdedc3a8f0ca57b2c351a7946a20cbae1fd789ecc5f77376b09e911749831e9b5680185b15300000000000000000000000000000000056a29b523b0cf85ab04b0a496e078dba5529cb9699e567ca42f9ee3e3f07b61ae29b0ce17cad23131375f624a366157000000000000000000000000000000000acb91d1f057c7aec1f7561614a95f8db2252cc879bbc2595a5f607d8b0ecd6e6e3ec19849eacfca62d870b049ce84910000000000000000000000000000000010d9459e07178af8e125c2f66de699cfafb5f87a63454e24d0ed88b6c804a9ff204f146ecf4d6db62234ace0a944acb20000000000000000000000000000000007256a68e23b43a3b6475b3cf209ec108bac13631ca448cc860672c65c1760a8299fe941ed5bcbbbcf63a683e86806ae8fbff9f8ac4ad10718d46a857ba28f182263bf2d13c8b6a00902af737dea56160000000000000000000000000000000003e33b840426a6bbe15b23fceba829bda9a5ab89d37e60133874f61bf1b10e05d460bb5d228cb178cfae2a5f41035d32000000000000000000000000000000000a9c5460c6443364d9f9440d101d92a0037343789ca0aab6dffcc2bf81e1aed312299a21556d16e55b1398334d9061f00000000000000000000000000000000015db251708253f7de13a5eeae5aa76fec415ecee1ffd88d882580da5da8d9f96c6ff90d920b329096a103dd71e7cfa580000000000000000000000000000000014c3a004cb6ab8465e05d965dc720b37084d98de424b160062f225dd0b67a8e62ae11a3c7bacaa129a568f3a243357ebb061de16f4f609c6947733b58c6444fa9549721fd9a2459652e8e4b8c69b5d61000000000000000000000000000000000c8fecac8bee21d916cc47b96a66b7a522ef4fea76fcc86ec490ff44b46fc01ac0446e3885e36ae7ab62a409ccffcca60000000000000000000000000000000011676ccef54bb27ab7db0b5ec025a9d1f29217030f3686e71564fa011d9fb598f44a8bed3da8fa7fcd10d01e3f66d86500000000000000000000000000000000093aecb91956215980854c6f19120777983a160e16026560c8076bdc4372f53065f9fee0f5830ea192aa5637590a745100000000000000000000000000000000035d773ef15d8d99b600a6a575eefd661aacb49d6540639223a454594570d0f00ba37340b63a2c8a0d4e53ee7dc2dd91355ed5b57b28451ad98fbacd5ae87551b7304e4ef5cf7b7dc443a66432406f9a0000000000000000000000000000000007b2891e9cea2a464742c7f962deb1566c9d4f9e4e7cbee1912a72c5b064211c39801bf42bd888bc239e6b4ba71d700300000000000000000000000000000000169cf5e706dff2945145d5ac14bd5fc8f7e7c3e5f7ce733c865e1882d236926c71853efbea26e13efe4eb0d0e7ed5db6000000000000000000000000000000000de9ee19c4bc2fac36debd4c91317e54f57e761866b134ba9a0e84a8d268b11674110ee8f91aa8a6b80eabee2e5e75ae0000000000000000000000000000000016d91408a670e4ee43ab8e21cc341596709113950d22bdf5073cd90f520667699e94f64f76290f1bebfecfd80a9e051430b6eeb01874ff4b0fb07dc9f23d8e45455c1480eba7fb3033942214e85a7720000000000000000000000000000000001982744a15e8163a6f2ee681bf27a68996682216037d67d91993fbbe040e16ea21a9cb600fc6a40e7289185393544c3f000000000000000000000000000000001131d7dd5a5b96ac1f4c4aa210afe7af8d371cc16d32289aad38c93afcc1d3be53716f82e9d14ce6b1c833f7f5871ad00000000000000000000000000000000009adedaf19fb8823ec55b803c9509ad98217730bfc6424c8b69a071e99d026492e7c8c4a06509491a3bbe5893988c357000000000000000000000000000000000cc60733a783c7df76541daddef2245e6d2b694b94649b13c21aaffdce124c1cec3fd8ed5a5d4d4eff3115ac933e5df989a697a0e8d2cf512edd2a3c3df354eb30a3eaf697779dd9270234b367c2b5ff000000000000000000000000000000000b366a80247a8e3797f1c711aebd60c99ec7caffda34514a3716154e900f2387c46f87f81af036a383e3f9234bd1b50e0000000000000000000000000000000004608b7cea13d08724a2cac691e61255ea7472537f7ff59894d511af7fd99ad72f0a7406271576300a7d1d56aea17bdb00000000000000000000000000000000141abedc914d3d1ed587162acbfddde60f7dbc1ee5e07fdb5f3515b87d1a29024c9e19f24e4c0e3979bd938aa4e798270000000000000000000000000000000010e72c6c0510495dd2c4ecaf13c1c6404654e1be369d1ca485c76d8c2304d60d69b90c2e171f18bf55668232e747825820b72463d54ac1d8f1b3f56f0f98861768b05d5174cf1883dd8eb0410420d56200000000000000000000000000000000081d5a229481fd297363e8e217bf1f94a00f54eb6e8a3f95f4de30081bb2b9edd82d53cf287e37b459afabcb73fea1d1000000000000000000000000000000000ab55f52ff7dc578ae8267fe3fa09bdb8174dc30bb835cab9851dbee7a1aeba82e83e07d5e79aafb34643d9fc9a0d1c100000000000000000000000000000000195245c7a762776bc1e81d7111e3b814088f1e0e7d686c3ee3e500cd0a7ad4015851563a1b8b592e491e00078187c66e000000000000000000000000000000001850c1e8edb0d6dab973a9975833cffee8b5243654bc4ebe64972e423799283707f9ad343bfa86548cd2acbe04ede5da3de7997113708f9d092836c2b0b59abf710d8401baea6de73ee0689436f035fe00000000000000000000000000000000000007e9191fa9057cd7df8fb83d497ad774735c242bce9bd34cfd21d3f8f2a8e37d1f38b592a61ac8a8d22a4287fc5b0000000000000000000000000000000010e36db1460fa65ea229402f558397c6fc57e9c8a4b0b9e85d9ba938196bfeffc951587353cb7c7d84479f60c087e3660000000000000000000000000000000004d86938bebb850fea82acd336c3900b241757dd937f831dd909ce548325955f103dd57611c0b75bf71412a6ac3d6ed30000000000000000000000000000000013990c82583007b693c1d6271c1e5820d7274c4a729da21a76eccbf7abab1f2bdd6c5d26e78d51476ecf154e4fecd1b87fc3d0560432dbb721f8a0610f0db31dfdfea8cd5ebe8da3fe3b8ac5358dd4400000000000000000000000000000000009104610d5887fb7cf6a866584cae30cfeb00e1241083b017ccb82ddc9d72fdc0d2b1d227c22ff6d8497495f44828efc0000000000000000000000000000000002235f959b071f21fd63282fdbb46b1dec27cc193f3e9988def691c73dddd789b6a1adb977a68e2661fb41d62280f229000000000000000000000000000000000ccd46984208f183f0b70c9152c01fdb8ac078ad1d85f41e3a24819da321d9dd9321a8d70103282abe6d8b981447f202000000000000000000000000000000001711057042a54ca76b0c3e7f36f2fd49e339b76cbd2e053d93ec2838848d359865fdbbeb9e75e408b4b316d60ce2741ef0b271f02031a126f8632e30d8b17cc5b57de7b8b873e0971ff392d4246a40f400000000000000000000000000000000001481684941fea0f66c78faa40aeb4b5254bf78c44df7e37b191c095ff12fc94248acf01d2aac5637e9536e73a82c9f0000000000000000000000000000000016b72eff2830f49b24b1e1317c95143cda8bc11b9dc4a91ff22a24e0bc1a244c7215ab1040fcfbc292ab236ac73cbd3d0000000000000000000000000000000013535421771fdad616171f7348cdf32bea7486bf4d836b8b95c69b71ea9915c099e256287aa119af53cf6320ad86664f0000000000000000000000000000000019ba0f36dc556fcf09f0a4a6cee53de485d03d846af7afb792d16220551fb5a42a4261f936b008babc096e6f8f68b63af8b5c136aa5e2d670edcfb5bee9ff6095d85a332ad55763fe1e5e8babd145c070000000000000000000000000000000014b2da0add872d6e61253d6022559f668bf192b4aafe0acfbbf341ada55b404d42b2b31182c1ad50c73673494ea5b7d40000000000000000000000000000000018b76b74e9e6cda8466a354ff66baeb935b5645cf9eca81f4b7342f7914c9bf35c57be402458c09781e66a89cba6e67e0000000000000000000000000000000019bc8c1f32ce934b7ccae6d8ca39a263939585d8f94414c3880fc7bb5a0a27d728708e7ebc42c5a935f769adcfc083f6000000000000000000000000000000001636b62bbbe34bec06253887b78ad5b3ccda1bc5d8baafe450f2d1a8e07334ca79a40c5c4a50b58aaed96408749e6f68285193e7c10646a4601787edfad3d76e19d5b013a0a954873d92bd5293d325820000000000000000000000000000000013c0fd7a8441b6eb2dabfe8c152aa480015f81139c46440741f3da1c50d18c17526c47e8b8c2fbcfaefabbad5f8a0b000000000000000000000000000000000009da839802e7c6759a87eeae5a05146e1d226dd828d4ef6d908b4a0431008f352539f3abcd3e4c532a3d8204e350a8510000000000000000000000000000000014709634973e4554d2379e439d099e9be8bc7ef031b6ea36a7a85d2ff5090b0e0de7cc1c6b6a004465edcf868ef5fd5b00000000000000000000000000000000146779393d82bde1eaa6205e69907a0536c782fa7fc6e11e5e62ad5468f4422b3688f2ff4da2af396741ca5e0f97de3835bb2175fff61894ccbb69d90375df627e925f1ac430a349e75580dd39546e44000000000000000000000000000000000ddb7d0380370830803a7eda2e9b694af71381990f182b5d1223992abb5afe9531bbef8b9dba239f411fc422210fdc930000000000000000000000000000000018b685009d012d72193043d09f8968f9a41ce2fed598a20536fe54cb26db1733214add38f73148e754e632f6d78f524d000000000000000000000000000000000b967a7b4ed1bcd9f3da16584b08e0c28d967cebe7a07069abfb3bbce94d26b6d95d8a807879b24fb1f5ea00091d6dc300000000000000000000000000000000039349785fdb7d38707d8136e9a8f650c4491c50d7425388b75fe30da56147992c3d662f22131ba7173b2550e613477fa25856e5fb9547c48d41783bf2cd13493a1fd71e56b9c7e62af84a1f6cdae1c8000000000000000000000000000000000455d7799cc1c2af1e219b23e8683113fec126bad1dd7a441c5d113b064b552ccb1e7314dfed1b11f42a18acace706e50000000000000000000000000000000014d2400aa3e2270714b656bd755c4bba55866d6e313f619e10f94de6d82b5343ae9a9483dc10c1a72a5a21e619a20a8b000000000000000000000000000000000a6caa6cf8609d23b7873c908e5321d064a9c107b5492d296d04f92c308ee705229dfecb1f908bca0024ca56bc125126000000000000000000000000000000000b31c384423c84316f65e03ba9e01a8f626236f76e4df4b8ce2fa053c1c1e6a9b8f0afbc253db8c9c5e2ce9f9dcf05c71155c0b9c4185025310e8020eb52abb6f2f1780da15e4ba81f3c9a88ed1b4a6400000000000000000000000000000000097938bb53db8d0aeca3f2bc180039a5dc5269748e9cf065cd88e59b30733d527e54cdfa224e9690581e8c7f0881241b0000000000000000000000000000000002d52d97d4dd415fb18348f4de78c65e2933fc45d5e5e1d8f0f0ca1cd52885704ab12609b91d6d2d1ce13eecc7fa0c2d0000000000000000000000000000000018b926a37a8e0ad836846d06c03a9b84db795fdfe5f15d1fd3e0f8fef1b2825b29ee3a503ffb2f75765cca49c2b3d4cd00000000000000000000000000000000073bac093e958a3a09543e060c81b35b6598521a8685629f77200cdc73b372588e66c247097e7c03492c0943bfac4d6bc5610b2707ce84ce67e82d5c0e5f5cd2c90925aefc1e39468ca86475012df045",
+ "Expected": "000000000000000000000000000000000f79110c74f0e983f3d3618869af1d9b96dadba61f1d596294ef8a9412f946fa26cf63483528a57299dae48f85ada81e000000000000000000000000000000000e1a9cea3af1debcf7d6ef6f7b8566b5bb52d5548d4caf85925109228d7c9b50d65a1b24f089631e75a694f8e8dcaf040000000000000000000000000000000010efc1081f079e841eaa5a65cd7c945d4f37acc92c4ace9ae6c69a9a95d8cf569d604376b1c7e63558d022da90d269fd0000000000000000000000000000000010b7f55ffac8d57c89b664c36c20b2988a493de32f5a956c91b16ff67cb806298a59adcde12ead42d598b6ca3e1b94da",
+ "Name": "matter_g2_multiexp_30",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017b139e5dddd53433362c49403838b3e2ecdd850a8df12d4dfacc0bb98f79d40966d62dfd0da1e721e7c0f298457d590000000000000000000000000000000000fa35e9c2e37bee1020ed99516174408ba2cf443fed115fe3a964ed86b5e5369e40291dbfbab477e339003ac85eb7405000000000000000000000000000000000e8fb87794860237066ed1b7ae7c2a783c48c52c2267f3e7295d1f17598b96232954e1eb6d6e80e716628f1db8afe48600000000000000000000000000000000083521e3a6d6e3f99570b747498520db5c89092b0077519c8421f9f41772c7a6e177c9cdca52f89a26c6036cadfafa8b32fac970e52778cc90396a5ba92ab98e26499eb1ff17d4bc4c1f78b64887d3f1000000000000000000000000000000000b1415e1dc2d4c1f5619b40e616d258867493d8624857e41d007f82ba8dc53f7ebb36d06f8348b94eedb794899e97df80000000000000000000000000000000001c01656fa47d62b4372361b80ea61501cfda47da5534e3e2aaa27b1e3c4de0bee0aa322e60c476fd4345340e5c00e130000000000000000000000000000000010caa407d9d265721d55f01dcfca52bde851ebd918e8fc4c752a41875940709c64599f36fae5e3ac7f211e1f67890d1c000000000000000000000000000000000b54a86474dd5f410290e4b4ac738fbba5e88c6debec17e38a52090b17ef371dc8feb0573e76c4b61d7688547a89f6a36583bac9672a77f2fe62bea4364aacf62d5e10eb3a757fa0595a81f76543e8630000000000000000000000000000000001649c78147fefa91100738e50034424244d22d8e1bb6a2bf471e4c9b29694a5c9476f4b129912bb09fece53aa87deeb00000000000000000000000000000000117a3e040c1f54b96c2435891a45fb9dd95774b5a55cfb306c22517e4ea72172332d893047f7eaa665fcc58dd21781f400000000000000000000000000000000105e8d80d46e6bab2bb9ce0525cbfc82e8b3320ee4a8b9c0086e21cf2b5895cb35abffedd1b5a9eef21f62a0a1dc48e8000000000000000000000000000000001437ee33abadc8ef6bfeca16c3edcf05480c3dd97db06e396e10d5180472f50074f43f9a031a04dcd11d803462fefadc5a8e1d77c9e42a187054c938a8a5b4bafa834021b727036ed3941b1c1deb9d030000000000000000000000000000000003b51b10efb54dbc2973e001f0bb634e36f689264484eb128de2882d6600a43ad548bc7d1def4541f0ed88a1fb37f3270000000000000000000000000000000009dd80dbfe6663ab04656856f192002593df9ef7f792dfa81f6a51c658c4c9ce5586a5edaffefd507f51ccb7e8c8101500000000000000000000000000000000144160d5ca6b2ad626e6a3424ff5139adadd3319940afa9bff7dc409ac1fc3775d5413ef4612b27fd22c02c1fe57bb86000000000000000000000000000000000e375ff490a626dd1d933a5c751c88cbd61803986fa8dc089ccbdeaa0a922758afbcdc30d29268fe0a34b7b79d0f76c139c02150e4e89b25563985c7802c0c43d00c721d521b54e767c1f509f584bf2b000000000000000000000000000000000997ade20fe9c0d3eb79e61a66a5c272d02af668b0f3c8201a1ea071737f3d2ee3b0764f859480e95be75ab8845b407f0000000000000000000000000000000003215194b6a363d31ece09b18700479e6093fa3472a23ef0133e3dce60a3d56b6fa984b900162c4ad56a6899aacf35c3000000000000000000000000000000001647647bbc399f40124c43510469cf613732d0919e22b478b2603d7553927584cd4b3a407e3ec6387c4a93e9e5373178000000000000000000000000000000000bacc8afdd70e927e21521b3f62264ad4f22adbc872439ff851d3d169a1c79a0d02bca2aabaa0b9941ab1c71d092fac12196ec0e9d2f572856217521fcc5e2869f16d5ec5fe76f7d350698f55ff0c565000000000000000000000000000000000b0c5981bf6ef5b85bbc504fb0196ba442fe87302346688165aa7df8cf2642548760e11daf5b3fe2e37b43379afbfd4a000000000000000000000000000000001086828b9560aaee5e28bcb50db8153c40e632b18c61ed4105bb7f472b6a69ddd8a2836f6605102931ee66b2f07e441f000000000000000000000000000000000f4d7aa3d1a281af6f8afb3d886774f4e4a64490232f63dbe16e3b8c4f626e9d07f7c668d09cadab3c92d6fe852427af000000000000000000000000000000000d92ea3318779b532cd81c9be44b1abb179a8411319a6f8fbd7e3f158bc970917d3e0b25f3f3f6c8e0764011f9bab0398df5017c9c35604f061a7095d976d08bb3570ef8fb518cb606cd39a3060157ab0000000000000000000000000000000000dbd83910f304d0fb2b6d8619c3a308c719f6454a357d9ced03b2882a50692c06cda7f4331f54eb293ed5aa079121fb00000000000000000000000000000000019c33ec829367dfd2610ccef9842ffaa5e4f35809657c22134fb09b024e07949d8370ba8ba1e9149060e9bd3babc19c000000000000000000000000000000000ac468b42925d2daacb8574d40064d393caa643f08767d20e72ac0fad1447a64d8743523312f3a91a118d3e51e1f52d7000000000000000000000000000000000202d1971fef2938cfd10bef5900b91cc4811939f66f1f5578a8ae0eacb2538d2a51c1e025449e1637b5173ab7fa3b6f7b82e7e565f8a521d1a9d0ecafc029f76b70042e1ec36c20e3789b49c7e50ef00000000000000000000000000000000008b6709123b9bd501360fa463dd08076c59177dc0e8035c49fa2f541eef3831e4c584c5a9410c68999dddda6c86fd9d5000000000000000000000000000000000fb94eb34355c636dca909cfa71f52471217b9bc241cd3e98907d4a5c7eb67d5bc9cdb0c73c1369d7950a014fe6069fc0000000000000000000000000000000002e2ee515a5dc96a664bb1f862f21a8d3b7f903fb87f6dac41c3541f3d83633f351ba8dc4661607d24b912dd1ab097da0000000000000000000000000000000008bee545e00e3fc283185a85511e09fd0253e191f52d5c0b440b10228041800c013db3c9322a835e4927c0ae0b21bc1e8260c1b7a249ba215f0dc127a41876f858b20f4422140bb7695c8f98e4c474d00000000000000000000000000000000006ba635e74538748c29aa7c5690a0530f2b1970554598a432d4ea6d2713a4d26786b6e80f67b2f39e218b19323654ea200000000000000000000000000000000133ca9e5e0d4a8200d3522d8e87dec3c72edc1cf16b7305af4abd466aa7a0e30159388d34c36ea030450ef45b7940ec20000000000000000000000000000000004724239afc773688ea92296bae8845f20793c05807a18d6f35f03bef295da06f8ac9dff438b720dbea7ea93f3ea9c4500000000000000000000000000000000149c12922fd69e1960274a8b91384e929fb354936c020911495e6e3c49faf16899ec0c6e87713ee2f0149bf808ac8abfcd68d2b074d038ee0d9887168dc16805ed55df26329a4c0e062c2124a6e5066700000000000000000000000000000000148a4fe6ca67b6c785d5d8a784d5e68fcd2bd08294ca37f296b6426433b805507b554eb9f0fadfa9d293e8cdb8547d4c0000000000000000000000000000000003700600c2b7bfea54801ac95ff7a2c069bace31ceadab2947a0641462089fb43f0b9697acc005a23007a923ffe97360000000000000000000000000000000001705a769ce3c9a7a91283e4068c602d85808980d6fb457345a5f9b2499ff8fb3ec8383049b9b7cae96bd2ac6106a07fd00000000000000000000000000000000052b1f4e8a48a5eb2b2580614c656393819b4f0ffea874be899e4964c7e32d54757f2d48ca7b50e47e8bf6d6ab8ee7572a40c2e796148ed1c539b0584b90cb386844fdcde5d3766cbfb1d1b58626fcd10000000000000000000000000000000012ff8ba50d587765e68f95d276e364c8c40c00b55abc929f9ec240985269eb096dd3cef5826cf6269ecf54bc67773510000000000000000000000000000000000959492d74cb34c8c9ca4a21ddee97df99c8a6e627db3ef72200f39e0402d56f0a9709596189c80aa3aa50793e0f1a68000000000000000000000000000000000f7e5dbe884597054d6dc5e80bf4d0d333025bddebc1fdb1d61482cf15bcb4c8a95ea29cdd0925b5b816cc0bb307387200000000000000000000000000000000194e940c041d71f43ffaa51fbb31eb63c23559069b42dbf8777f35eddf14edbc3f7762c7b354174a584507ad714948234a1e176fb26983e549aefff9aeb220f50e071222073422dc2c44abd85528ee2800000000000000000000000000000000101a8e54d1fc2357df60b0ef8872b729295218f29ff63f7a7b6a70b3ecdbfc6809eaa8dc1f62a664b9987e8e86154c6c0000000000000000000000000000000015b5ddd012b42e1a600d738e05b551d91e7fcf3cb36018ceda9b689b92022224990c11a6fa0b421d5610b7e59b7463c30000000000000000000000000000000016130be17fceab55387d43179cd943c85ce1ff1881c07c937b2cc0645ec9ebaf0e10718ec7fe0d720f49bed2b8caf15b0000000000000000000000000000000017d73650680856bc11619e6acc139e137f0a06476f5f8979b5ba7fb8123d85916915da60d1f2e8c84197eef518b350c2a62e07bb97ca3805ba2d30f39f44e70a7b2917889c26b84bac8f9739bdf764090000000000000000000000000000000007d26bf37a97d532ec93a3eac00d9d39b064ecd172ebd5e18228b1601eb7a2c272aff9d88d63781b4a587c2c8582eec4000000000000000000000000000000000108000e850bfbfb02d7acef97592e15ca721334eb51197511b0eb2bd3bb647fc8f07713487b0a0bedbafb106992de4b000000000000000000000000000000001868c0b2ba732731f7536851f8005e8bae7b16545b39190251eb2bf93dedbf0803a42ec24cebd151998b690c38c0346c0000000000000000000000000000000016faafe909a1f926333b12f5463231a71058aec31d73893687d3169c4c3588436f6178447eed307b642490199c507d63a14278fe7a08174660c08323de272b2110047a1d1d8bd0e3c7d76dde030e00a6000000000000000000000000000000000331338cbaeb8e304fbb9257bb80aff5d3e043d07dbc476dec2795347e4c25248caad06ad14f56183d2b6276c49ff98700000000000000000000000000000000167e9578304a1162de73914b02791468e14faa2e0f161aa57818b8a169b5933dfcab787ec0f4b23737011163dcaa02750000000000000000000000000000000010aadfd5cc781e73c31f2fb64e7981b2e28614aa18dc7b2d96d2bb4ed8c2ee9089d6ebe0cf85479b272cb049e934739900000000000000000000000000000000128d7ea54f338064cd2f041f42a1a1e77d8b9be4ee55f568786a36f87f965d8142207e518798061eb3e32fe3b0f1541d1f516ab5b36a59e6300a54d17363ffebba35fa0c64cadb21e541af5078545b400000000000000000000000000000000004539f22654b3182d4fda5ab8d4bce6f1268d4e402b6c29a4cdff3b5abe0618d33db55ccd1ff12b27b2cb0196ac53e0600000000000000000000000000000000177e80ab6aa8512cc9e4d65b06b2bd76e33bef9038cdc1ab97fbb9d896ae2ad884ea16407490653dbe972b14e9c30c0b000000000000000000000000000000000c280a4431e41df6515979a694ce292f220278178f7f36e23c8a4cb2b8a7ebc520901ebe34c72a26b2c8a60aa1a155100000000000000000000000000000000006a0b80538a6c8093f3655905af1c59c235567d22192758c28dad1b715045189a412e4c1edc26e1d8ac95a584277709b3bcdb23f9568e409271b5f907fd64b0cd81939a52a6db38fd8d95de76213f7b5000000000000000000000000000000000eb091007672a212dc4937b314576963d7561657cf1103820ce9bc34e4d46c24f4891a4a4ada648f8cdd2c30f670b86200000000000000000000000000000000166389a37e6e3c02317d68d54f29cc98d1d1df5853940555161d71df791cd92c483eaad87dc0e765b12408d6ac344f31000000000000000000000000000000000affd0d5734cbc27b192c0c0e464db48d3d76799d2c6a493b172127ef2df6ea18a33898828effeeaceb7a203e35ca41800000000000000000000000000000000155708b9756752c9b44048c91d71970fd2cf2a4cae6b0baec00629c81387c8261150e78f856093d81e816be6403f1ee91b716b02b3e94600867e019be166f4532d264e0aa65d723dc0e117aded59245d",
+ "Expected": "0000000000000000000000000000000007ceeb14945414d96088a7900c1120ff182b2a93b09943c2fd1dc2b0b223f684b0d4c0b1b5803502582f2daf16d81d2d0000000000000000000000000000000008df450fb25534fdc456a8f41cc143a84729ccb082aaa2243c8f37e34a6670f5195750f8547444c49f7a898aa8567d980000000000000000000000000000000008c12d360078d5645b0e095c90d4fd37eb20f0ebbc6fa93fa5beda7e7c78eecc06e0d839268e2c303422ab1769402e0b0000000000000000000000000000000002bd594a21153d7c458b9f804050d05caf2d90bbf9d18def79eb8148b7f89e3a3ac21f84b87fd13c39df5b91cf73460d",
+ "Name": "matter_g2_multiexp_31",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003e06e2dcfbd695e9bda0baee1276ceab637fd1fbe2d2d6458c923c35b00edc7edf4f9e797aea59ff8cfceada0615a02000000000000000000000000000000000a04a2ed5e42fac7f064b43d64151a6c517ecf22dbc7563a3e9f35f555a9992fe45cf6a728ba94607df7c96f7e0a334b00000000000000000000000000000000090fac97f9f524168bc930d26ea1627ceaf187398d6bfc5a019c8467d75cd31a41c7eb9fda35fc85bd92b4cfca92dbff000000000000000000000000000000000f37b91dc935c28668c27d38328a511148c1739b65f2816dc53e42a8f059c9b2be7417a6f97c9a2597b1a0f06b7afc65bcfdf0495e49dbb8a8f9a0dc517351f39a6d823dcd42715f329dc78400bd74fc00000000000000000000000000000000090b834a587521729426d5b134c6058bf7999f4d4bcc0812e8d8b3ebb050961321b5e93356e87171a6f12160749394ee000000000000000000000000000000000cd5148c7eeac4aaea4288b38a02b5a901a6e2805e2b1695ed98ed86cfa0d259d87b65bf3cc9d00b8548100a60a371d200000000000000000000000000000000026db1079b85411dea0b9fca383956af50b938a465f35347605c01f3b72b297630ee2fb5252da20ee0d8ba5071974ed70000000000000000000000000000000012ae26c193e02d7ae4a7a01181551085dec9fbcac811c45d5cef19abf736ca2514e1259811970af5913891abe22a75ecf095238bcee61ec1317c0f98ad4f8f9b39c5940cf37a8a3a676787d9dda99438000000000000000000000000000000000ed5d8a609aa4f3c65a89b8dbc9334bd3cec6c7763bff298acd6c260e4d3bec0088e15c5d82618571d13b74a2031eff1000000000000000000000000000000000c28f92f018e6f822912b6eccfab37432ab0ab9acab751f848401791bd2f16e32ac6d97948bd8a0bed2ddc1917f0db3b0000000000000000000000000000000014083be2539d914883172cdc70950512dfe7be8893b1ecf085d837c2e9ba7f03656c5a0e15373e04d300869620eb66d00000000000000000000000000000000002561b77cc2658c54d29f8d1988dd7448f59c80c02ee9256404d8ef5536ee50104cbc11b6ee1ab9ccbf0ca55e53c52aae45a6d64cac817cd479a501c77b6720c6777c6026dbee471b490fee9f242a6700000000000000000000000000000000000fff05aea33a9d1e8f7b227c80ae87c9e7589ba2804904b7d8386b24b0e5324e718f29531251969a972870a30c310630000000000000000000000000000000016ecb8f27a369df13e122c981e7ae37882b36d5492fccbc86d606aa1198f3e4ee7bb7ad0555e11949e6c1783d8f4cda100000000000000000000000000000000187f425b675cb12719a01ee3b78ea73d88f70805f72d6cabef6372ccb9d99008bdd7da54f155454c4c59f041deec86f800000000000000000000000000000000151c272d5cb67b3f801e103ee901deb4b3d3bef76ee4e1b2ce1b5e663ed292845ba012c732d38f9209f82e77f1f73cf354868215022673de608cb43a3cb74ef2073ffff34c54fbb43f19b22a02bcc2ad000000000000000000000000000000001791bd59815309f2aeb7b07df8afd89a288eb6f19c7e613f394353ac5398267e1388c97b17d83104446e57f94581a79c00000000000000000000000000000000154cc72ada5a9c99dea06ebec143a14271cf332b57c631725ab30e2d308d6b688ca08a79efb6fce632cb1216ac3d077e0000000000000000000000000000000012b4c6fe8c17274ef57539563a736c2f83c4cb473e9d075a976e18e193255057340f45de373c7d6e3fe5e08ad0dd97d20000000000000000000000000000000005aef16e11bd4e7787bd5ab4427276ecdf9c6c134b9fdb2ec39e87ae4a5b3b674b5ceee29bcdf804ebd7e83960d8d7ef7068c3ba82e52fce0223a9f28c1d42681c7863c94797d1786c1adbc3e6d10dbb0000000000000000000000000000000008e57f905fa202c7640500746b590791cf9d0f160a77e5eaa5a30280e513e8e801c4b6b04cc3f80d9403388571d180ba000000000000000000000000000000000da3c128ae234bc27824062832ac10aa9cd4978f37855a8b4cde3822f5b485fddb9a475a9805e795519d7f138a8199cf0000000000000000000000000000000000ec11b7e07710161fc557a56e04337f71aaa1a0f070cd84525965e53a1fe445c91ac07c618ec349997890ae893c165d000000000000000000000000000000000406b0eafbb8782d11f5dae2f6214282252af9ae9ebc5c17a81d4ddded40f05d0b534d14019bcb6cf4e49c4c182b90f00042b8005283c7b91ef4b3ff7e20a91349c8c3d1301c9b54b901e8348a7d186e000000000000000000000000000000000b1d456e66671dfa72ef3a56523eb939146226111fdbbeb697983928aebd5f50b0518db841a3d48912a7a780785c1f180000000000000000000000000000000007a15b2253496b78d270dd55b80bff90583a95283a89d40f6df71fadce56d103f0d365fe79256fa4f93b2d2bf4c06a2e0000000000000000000000000000000010829223166d38fd2c3041dd5643c9784da366a2ea8cbb3abdffb5fe43e975318c86de0ac9ec77c0126ee75bd209f7300000000000000000000000000000000004b124018e83e1e5e77bad42eb831798d450f8ff4a79c9b14f67f080047c491fbba45db79b2cf6015188f9fa6329e8be0a3eb64ce8fe140d94956b0685f91a5462dba1a90093e803dc617559a66d20da0000000000000000000000000000000011119be42b90c7857079a51695dd5be08e59374b0d1c7e12d0ffe870202e1f0c62bff84c9691679a82e610e788b7b5e1000000000000000000000000000000000c7a64524c5dd1bf10d16da7f15b39d05c9ee1620d4dcae79c60316a1f522b238e7934d1be897a441d0c8e621b67d44c0000000000000000000000000000000013045613a090d05d07310865d977c8e0bb1caa713b2249d6676e7cfd6f4e3ba8e667deabf9fdf7fd527685f7d251b178000000000000000000000000000000000dfee7f8259701b5726b6439a7ce77b92245499906502c7dfb384e29cafea61f3b1f21fcd7888231569ebf29d3035a61ec88ed0eac8d0f2f618530e91cdb9ea36b8d56c1001a6792a09e11ff65fc02aa0000000000000000000000000000000006d77669207bb2d064824cb56fc786c631936d30db630be3c08e18d7e95b1c26e2d4e7b2eddc2f946fba6e99acb2198a00000000000000000000000000000000168bd8f291f8bcdf8b5e9fa915f7f24856a62803bbbeb9bc38384149008d4e3129338035061631f1fbaceeccfaeef4a700000000000000000000000000000000146bf2dedc262557dec2b4545c94a37434e20e4900b1693e8fa9bda9a94dbd07e0a3bee5f3bedfa42148791f4951db7500000000000000000000000000000000138467700fd5088c76af2f77fea4b746f98701fc0578571997b0ac2fc343354ddc8b2dc57d5298dd4daf767573d8bd3d5f03e53ff983fe4886a3dfc03a353fb77927d7a0d1998a1c55ca7421a4bdac6f000000000000000000000000000000001536da0df7c91687339fc93608eb404c5f46adf4b9122b99b1e5cee0012e27ddf30934d8f669bd39091f8673aa3b3c490000000000000000000000000000000002deaa8f9349e7c551e39751b1454a00f8f7896d63110e8e42607e8023ae3070c4abc9885ed54ee37a82f6e5c68451e900000000000000000000000000000000079a62eb17f7b07d4117956d3dab5d16a7f90e98948d5c3caa124fcf755c73f060a90d002cf880f5246a87342717b4dd0000000000000000000000000000000001246f0f3ec2af7c0250ae14cc67b5a1d42309f06c6f47b89178ff7534c47e8413a26a43f27454c0f946c66634563d41cc1b04dc356bd348211ccc4c50d12cb382660a4f9526539c2a0c52b021ed216500000000000000000000000000000000046e4a08785de985c66c7417f9262d363b9acee07e250999a4a7124f101ec4d82e3e4b2b0d9736471329fd61d0cff13b0000000000000000000000000000000017bf1e20ac181780ced62a18c78b378fc0dad157cf30d6026680560b681f5755183bd30b4e454764c08edb93297590b5000000000000000000000000000000000a57cbe93254bb0796eafc0a57330e38bfca37f8b94c4d21ba656e5616239e1e18ba6d632c0129d30291736fe37a4ac90000000000000000000000000000000007f31df7dbe9abe15f4024d8f6bed93c92ff5bfbd7835e08e870eb1bc4a6f62b3809b922c6d5a7350e2e5a978c80a67397b584ee05c27d45390aba36772ed49d571837567e95f1fd3ba3fc1ba5916727000000000000000000000000000000001577abdf6e915c9c3b3fa50a4601709cd629397f2f91784528e4cdbb140065fc2a6ee3830983dcfd49a928e78cf530aa000000000000000000000000000000000d6f98df9e41009837cbb05bc3e3340d38e56a448fe396bd48acf03f061e7489d1402b36a84b3c56eb859437e9c406f1000000000000000000000000000000001912afae5361c3d8c6141755deeef26d1fadf6b0036b9d05b2e0c4d50f42328741f0423ac772fc66dbc922bd4a837ac40000000000000000000000000000000000616661f049b5c784ba05334b2931509e1e033bd203fe17f04cfe12e80e73eb7075beac9d379fc1c457bea1b6adf365752542cd551cafc5d50852526ba0a23d274317e1e4a6e75c0d19319e5853b8b6000000000000000000000000000000000f98fed7e4d67a513c746d2fb188597a605165d5d299072aad6d621e077845f93804d575a5796bfa726f529dbd90e014000000000000000000000000000000000adb2d0b6c02e4e8fcab11c7c8819e87f73aab673ff9dbc5c50fee751bc7a6a8d386c8f9fa830b5545f94a73ce6e1f1f000000000000000000000000000000000f08e05ac40655cf59ee3ea9f10fc900315c6f06ffd3b80853560559f580ecdd65aba5ba660c729e0bb9576eee3703710000000000000000000000000000000009da46469f4b8fcd8d2b016e96f6e6582fb01c75407c36c7f87b4a1cd8f08ad06e962a0ec2138ed6fabaa1cb0115f97e2f76a0fa585828f79553fbf3baac6a2776b782de66dedd6b734f9342e734ee3000000000000000000000000000000000047b45ad2ad4f7b5b72194f98b98b2150b5d73a9df2aeb2377beed9a1275a882fa2d849037ddb56af632489f892a48a7000000000000000000000000000000000e1b0d9b52c0c5324067857ba4701f5f20eec165be418871fc0f0adbc3a0bbdce5a33277a33b79013109b81e006c621400000000000000000000000000000000179c471e01e340d8e6fc0f737ec09f0180bd2dd2a86d0817f753d1e9a9f8cb18178e9de68c596dc6a824e6c3c151d8b80000000000000000000000000000000019405c1e571a9b200ff2949aa74647dae59d92a8669d4876ba23f1b4a12a1f9412412503c68acbd619cae3ff056bd346f638e6a70917c89811851109296a7225f9c7c5b3d7fe6d6ba6c7d1ee77db4458000000000000000000000000000000000ca8566b9bd088c471fd33fb7b1bf760ee12cc8b0cfa9ad92b45012cafef5c0772d9bd3bd9b266d6c3e3890c8f00057300000000000000000000000000000000055789839e786ecee7fb7d10f3876359fcc1bd6f2c5cf25c8337aff7fdeec9b43ffbe932cc4936bb708571a59e4339990000000000000000000000000000000013cf827bd57d8179d105f34c147665a072714ccbc114aa4e878d04ce66ca78bdabdc4867b3968c75dead147257197c6a0000000000000000000000000000000014a8dc5ac1858442ca627eaa194e1ba64091b5f9ace551338d770c92fb49ee12449dc200c8c35d70f9e0652b4d9b90da1c4ac944341dc68fee586d221db2a8167e833f18f012afa7c3844def6dfb26bc000000000000000000000000000000001124ea2b97a6d73c81387a51e814b9bdc951a773db2a32d50691be60f1d397cd4aadd9b06e4f49c32b12254e9f824fe80000000000000000000000000000000014cb365e9780feeeff3548f34a56548302ae0dc73402c40317fc819969ee9c4ea2a181381b94f82dd97a236671b456a000000000000000000000000000000000064b769c4b785d45472038aeeebd3ba9b28b3132d72023640ab2d7512cc6e31296c5330be5653ad6902e4e15e57e2c3e0000000000000000000000000000000014c7bfb1f142d69c17f73e23011aee0063a97a99d982d25ff72791a65c7a68941a80fc216cea8a49f3df2d0748b1f95db0eedaee9347b10ab7b346fbc16c10cc9db486f561f88b756c269ebbba23a7f4",
+ "Expected": "000000000000000000000000000000000fb1227806c750e0eec0b865daaaf51afb74a88589d1c035c60dc1913f05c8ab18de24903ea876fda27b97a5eaa2fd7c0000000000000000000000000000000019903e1341f0285658164f9273b5c958060bf836264502b9dc298f75d4104d7a43b8d5dc0bb934a506ce1273ba839d830000000000000000000000000000000006e791347b54057195189e8b9f10fd42d170f37d455c0af5e92cc6a12e2c23990253be6855f4be6c84a708852c19a6f90000000000000000000000000000000005b72c361dca430fb2414b9d5a326cef8b77cfe5310153d6994dc1f8b9e74e8fbb43079e21956f428ed8aa48d6897e32",
+ "Name": "matter_g2_multiexp_32",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000052acff88605f33a0cf1201e8101c95ca0befd443c087265821a7d954917a026d41ab24d29bdfd972bb52ff4ad6de14c000000000000000000000000000000000e134b2aac3f6270e43afd994302426796b1e362031638fe0263c0ec212b828a30d8321af34ef7bf260652150cf2293b000000000000000000000000000000000d6628f675008099e9a75e1294803e86417ab22670d36316798680289ae61a26821693f2f9efc8468721a1097c3bceb20000000000000000000000000000000006d66ffad1a2e0f39488fd3f6e0214c9407528c8bfb8d1ebe6d75596a3e3cc844d00fdf46ce7ff6cd6d67732874a24a484adc8cfd2e42abc2f0e0d7e9c4b378f73731905760bfeeef01c94f8d5c3cacd000000000000000000000000000000001160bf0f7f2915cfc64e12a5a91b7e2aac78d4c2ce362e7677dd0e9c0172b37fd1b52222a13c65819b87593ee32a9ba6000000000000000000000000000000000c8be2cbbd302b31b1ab6dcbeb57b4ad428447bca9159fdfd007f5375218d121673a010f2c7fdf83fb45883458fb068e000000000000000000000000000000000363d3d492e6e6901756bac13b5c32d55aabbedde878115aa41b57d27b49a0f017a61fc90b13a20e009989374b82f5dd0000000000000000000000000000000009302fc26e6d750ff9441d7471903cc296b320128de71f86c4eacc80ce0725e8eea6acd2af056abde2f61e0a349f9bb5bbd5d4a15998d733326ce23cced86ec5d5b410c29ee98a4de19f2662c3933dd1000000000000000000000000000000000b12aca17efc103cad500b3d773e43cb24df6be651963c0f30bca489f1dd7911ffc7204fcaa4511e161c6f75da4a5ff600000000000000000000000000000000179a36e9292d3f78a5fecbec1175f001bd4ac0ff3610f596aacdba29a12ea4844885a7c465e66d3883c7fc99d4a7e06a0000000000000000000000000000000016bfd0758b31f54f90eb8562bb693c45a92a297a3d302279c9e3cb8263efc0f31579a3af8e8f5a091d9a6a36776f445d00000000000000000000000000000000020f6c66fa554a5cb610ab05d194e7583e6798a113b8fff336c986f7358bb9fa6a7aab0b04be9b5c44a6fcfdd21999e83717aadf16301a9c8741d65c86ad7f849101e30b7b1a344643b100a8582a6ad10000000000000000000000000000000004bf40c1d2d3574ad7fe128ee376364591b6f647f939b0b556ac3fdb5a92873f17c007e926b8a39a97c814728f355bfa000000000000000000000000000000000b8669e10e0a538a421b717287455620b82574b96ed09f64db444ec73a67a3227503e1b4fd6869314214071399eeae0b0000000000000000000000000000000006ddea4adb703d7205b6d2af436b41b4bde3a8c5dbed9dd161c9b3b466ebf06beced64fca25c3bbb97f232315daa5565000000000000000000000000000000000d97248a25ddf0ebd0200c6abbcac9ecd9775cfc5ec8da91634e77488bb592e5ff277a9607fe721990f403dd73f746e622788b3597da7b9b106203dd0ea97527aa8f5149754bbb0c10bb6eca8a46d94000000000000000000000000000000000135bc4f28663a6d7d995f6b876ffb8e6ef1d2d0f232388aa5f390c57e8c48cb84d370ebc4bc267eae4466a019c9ed56e0000000000000000000000000000000008b6a9d13dd9d7014df6acb59f80b335a751fa2ba4dce63467aed18f68358f5cb743718112b3cb2d0b5add34bb6989000000000000000000000000000000000013a5389dba4da195f34fbe798b254403f0bc5632ed98bd6017ef24fff33640ae493c1bb7a77a0d3c97649230e455eb51000000000000000000000000000000000a69803a4cc237ddfebc51df2d90fa1ad03359f9635ac1646bc942546575d1558f5f2c3010f6e2207849ee697be41d093c21276fc1371060c226424eb9886de6897b15b075fc5a51aab4710e9dddd384000000000000000000000000000000001939c2431f8ac4ab19d2735f122c0424af2ef18c0028e155611237e86648bf1d74fcba3008f5c6aa30feb5d4a14a3f3f00000000000000000000000000000000174473eedb54aafc522973244ec2feb3f7e95e50a1e996d1100c8da4fa59428c280f76e9e7364906662c4d2802235aa5000000000000000000000000000000001021d15f8ae2f62dfd3862944bf3be88d86d8113f4be22544ae5e925d450044279c5bfa1bfca44cd5934b42a27096b510000000000000000000000000000000015e0f20efae92e1fe8dea2222ce808a7de9e9e861c333db139f8ac11d7c4fa9ae6e49f51095f6e16bc738dc6d094b4cfccbce4e92cf377f67244995badc72db0b80fe37c9b7d443595156fa41abea17a0000000000000000000000000000000012d70691721f5787ea2e2a652f9c65edaf763637f95c285a62d32dded18579b7257493e01eda19631d00ecdd4e27a9ff0000000000000000000000000000000014da9ef6076e646e7d5b52d1803d3a6d897664851c6de2a9b330e48695737e05f0369224c3eb357bf557625bb94e6ea2000000000000000000000000000000001554f68124a91be5b9f325394db23ed5db8f6c46eb46cb50e57947bae00819b151afbf4ab4949290ad41625499f42dc00000000000000000000000000000000009fc0d459e28cd1239d227e1d2f7d530b9d14ce5638cd308569300a791c997a51dd5a98aad703239a23cfe7cef7f47f6ff79345f31c107841ae388f6cf116d10bc696aec4933de56bb9affe7e20c649f000000000000000000000000000000000452580d6a37a07038ce3564a12c1c7391fdb002cf27a6df7e194b38f3c12a3026f2a8acfe5e634cf89140da256d0a420000000000000000000000000000000004b73c9a4f9d41b8b84e53de538e4b15198f50247e75c274c14f136d7d91dce4a62c5346bf11a105f035e29ccac3dbb70000000000000000000000000000000008a8a3b2705a82b551f8913853f682253e7f1f68c8e42f349337f4f1eaa5103f59430af0c4a124b6a739bf88298c5f6f0000000000000000000000000000000012f4220609899e8610809bb3a4da46e0688c285ba2e8750b4bf44a849cf15fbf5c016e8e8f9372239bb562e7f38916e921cf773387d5351aeab99971eaa3b207fa6a318ad60f1c3e16b7f68251f9c910000000000000000000000000000000001884558e709635c046bd6ea8872bda936ba4d5ebcf7a0208cd0a4ee08b69f36dd2e136ce655ddfd89a5b1cf8e48f5ef7000000000000000000000000000000001357e2dd9fb603e5190d7b7ee105668bca2ed23ec6a248aa71aa430c2b2755747b8dfa3b147eb51ea644bf0354a61ba000000000000000000000000000000000009b0b0a76c6980e62e4893157b85f59345e1ac81e1aad1e48acec44c4803e2a9080f0d193fb799e0277ae6f1058839e0000000000000000000000000000000014c984ae4ef5d9d319fc89895f34a7db02747f57b206b0b30e8c9757d4b47419e6c0c8378fdec5aba364936a3b1922ca2d69cfed6bb2d33fedcbd215dd4e9632a3cf86a4b2716406305f6a85e6090a050000000000000000000000000000000003e1bbb872db172a1fa615155f81aa75ee9760f8602e4135ef9f1640b7f9d54bda911a220d211dc4bb767bc2b5e6e23e0000000000000000000000000000000008464f23cf693b1d4545b6ce4aecdc8fd182cfb288c5ddb1f78ca578e9b16342c8178d886cbb6b8086c0fd1318c4ae09000000000000000000000000000000000af574c4d0fd86087e23daf6d9ce98765e1e445ef9152dbd68152fa4833ada0be440de4abfe7c07dbd4ee67f1a4aec9a000000000000000000000000000000000a8227b982f9286b03c4d49766687622206213d88cde007360df9b4ca5916c44ce44dbe6443577998b4b0d527d22593379cabae288f8a9a8cd54523c20825b8fb07886bbf0ba0c5c807956f268af4fa10000000000000000000000000000000012e31070a501a7df7be43dc23e23dafa32ebfbc10ffb4c53f5d36bab2af69db5a05ad64b9ed116560e40b71f9217189b0000000000000000000000000000000011cbcd38ec3c6a6d49df6a8d6e1029a0412b42bd3fe8b42ed625adeb5a2f631e97bfad302de82ae34f715962b5ba0289000000000000000000000000000000001019b1b619fde9fb885d3c5f03a4373358107af7509754ce1ab2deb67df536d05e07ca7d60d927c15b549502750054f90000000000000000000000000000000018f1768b7140484105cf3ad2daa7c565e18eaba834db3f6bdfc9ee37445f2d6f7dc2b4c986b7efd5373224d2c92aa5a81973977d8e8c592f9063c5a14a658990f9c3405643089eb58324cd3f05b5b5e4000000000000000000000000000000001847b14146cfa2e1700f368f414b6a66ccaa02ca2a90b40a8e2be2ee4eb66af77ba563d7507de63362fb18426b6149610000000000000000000000000000000005c028d2b344ccb6400b53134bd179028b8774000ace89369bc655bb9dcd1643aaeec830407ee941df5432ba27987e8f000000000000000000000000000000000c4a680e2157dbdb53ae761209d505b4cf6b18fef5aff1c5009ab41295e0ce2ca23bd7a4f983fb9d085e1d0dbc75ffe40000000000000000000000000000000013c0cc77a5d771f1df99d1530e65ba782604c1ecf67d08572609de9f18405b9b817c2643226cdc7c9ad35beebf87dab0a610bfd375a7b8d0b034c17c8fa27d4366b06c681131fa7daaeeeb08e25c2ca60000000000000000000000000000000009f32f2f83c21875963818872d243cc8c70b75234f53490eccffbf060cb3b9c53545c1c32025b271514f500b20b00ec10000000000000000000000000000000002491b571087a9e89dbdd039ccd2c37d5d8d25587495b2d7b0066e9dcca02d44b2c134b0128a9a1527396729f069df83000000000000000000000000000000000264e9c47f72b639597de8f26a42ca7d77324f8c0db705986fc3b40dfb46f47764b69c70037a68d76a5de49a278779a100000000000000000000000000000000090614b3bb302ed9fb78b8756524fb78d54a4390b27136087181342571f994b1a93faee28256d765a8ff4f448cc357c199ffe1dc2d7526338462860501d75380a5ed9d53e675125342afb6652a97437b0000000000000000000000000000000012c716ddf17fca0d974e8d6003d99aa90f06b201fd141c74d8fdf1167030d14dc732917d3c6f736c68fbde9df50c098a0000000000000000000000000000000000261ef2b47de8e1576aecc6e19ececf80ddc1f4e28b2ff27953a65199f65a6211db7326632cfe04d543895c727ef8b600000000000000000000000000000000044fd6b9b4a1bacb8b7d4c53c106b025ae78f17c3baebbccca4e18cfbdbcbf8b3ef88ed5bd9bb36d9aea9e24f4117e760000000000000000000000000000000007721612515fd075811ee804314acec9d389900c7ef883e866f71fba00c49d5c4dcc7a2b8e2366f5a93f4577926ed171fdd97465982b58e69993711a6a64134bc4e76b88ba1948af91ba3339e9b9d3e900000000000000000000000000000000122581659ab1712afc23c23c2986394de8e155bcf722e944ec05e7e42e05acc366d9a7abf2136b5dc68a8dcfd4a640bf000000000000000000000000000000000188842cf4ef54cf77c145acb685d3187cd9c842ba6705bfed846ace83dc4400c45120fc1d6a633ea879840d3d0c902f0000000000000000000000000000000005c8966862ed4458a753155ffe2c64655779860149641ee5511a46ec576798fdb5cd9521528df77bfebcdaae2f94b865000000000000000000000000000000000cc10d888d2b7a97666de99ac14a501b7e2171f074d30d947efd67d85226c312a7977cf923ddbc88c533f08a99f2045f786a2a3974c84752b32f29707805c71992d5d473f4b7bc1f0757d126607a1c07000000000000000000000000000000000e5af1420546c1a5a0e0c2bd9241bb7c7a26dd52f4f358fc868bea457a60bd4f6bc5b60b27069fb4f6760813a91ada740000000000000000000000000000000017426a65d239b1d9505bef2b476799c394fcc7bfdca36a1ee5a600351334dadc238b64cf8a667a25d4880a31b73c53a9000000000000000000000000000000000f151587944aad17429b51b1c16193c1e1c93cb412538d1475473666c997e012ce618eb841c4e9e064a08ab83d7fa60e0000000000000000000000000000000015c2e049c532db585807319c23ec077a51f288fcffb2cb6528d3697221e8542e3fc85d18b079ea1b217fae30858a36f285d33a7fbe6ac6eb42eb932dfbbca2f771ffad5e80fde686e5df9d34e9f83ad6",
+ "Expected": "000000000000000000000000000000000c9be91da9bd8774f18efa3ae9248e4b03d11c49b377c372613b7e745882b2b23c49d518672e58eabd4d9b510a25d8fa0000000000000000000000000000000019687b9eaf5d68b0e795cd57055a74e44efb3e997cb038b7f1cbf08ca70e80a1655cdb04402c542a92ae4e435c22d0b90000000000000000000000000000000010aa1514402ce348d1d61b8d38b53017cd3977a84dc14445db64799cfe822b56a0adbfc5332093ce7ea1f0f438bf15590000000000000000000000000000000019ade30ba0faffcaede95aa272be042aef090f89d9ca25cb825846c4bf9e4c1dc575f8968c88ada51fac71f26fb01517",
+ "Name": "matter_g2_multiexp_33",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a1346771f8ba25fc44323d5290068e46b3f756de6d97aa934d511979a1486bc32173575639a7e54aea8eeb60f32a8c3000000000000000000000000000000001958ae7fce87db47a65a03402313b99f659ae02e8b62db3525d48dc9075aacc5e5abb50156e704701f3ceb18747e0431000000000000000000000000000000000f98778311e28b4081aa76a3f9546b94c29d86fe8e66b905265d74ee21928dc3ac463049f70d355d8caee5b59d65e07300000000000000000000000000000000185cc233ce72770ae26406476c1779858523e7c940d69adf2750695cb12440440686b6b918f4adb3b14aee9aceb6422119582dfd9cb80d44c17c5f62360e62f6736d186194f0f8483e34d8d18d832d37000000000000000000000000000000000ae2f565a44c8e07f2a136368798a44926cffd3c3a6d4c2fbf91763c20d2bd959271343b80eccec4d59a84394c7a3ce70000000000000000000000000000000009481a5fb276c938801133adf10dde3e7da2087d0bcecd3c9435b7de544271eb3b07a69efe7e168869e727868f24b0d90000000000000000000000000000000011774e0197866b1c8b3428d353d2c9f6326a77ab30d5595e2402a0486f03ca6ebb1e8dd335a60a772dfdd9a3dbdd3eeb0000000000000000000000000000000011ed2480d79f73a67a2adaa6da3ae4f1e1c28feaf0e4cb9aafac658901960129e40f6415ec80a31d72004899326f714bac0bd9b8746fd02aa70d8b8a2b5d3be46baecf9449d8cd3d620cf9efb3c615d1000000000000000000000000000000000a73b0d8c31af2deed481faec54095875639233bb09f31b1c7c745cb54778d1c8bd0a230e963ddd2ec8d178d31fc14740000000000000000000000000000000015a889b16be93d0b6dced01f5e2278ffde1cef0576d0b04b49996cc5252854f879e04b1ffeb90e222f4b9d5fa350767c000000000000000000000000000000000b53dc4d72e90330ffad17012bc7dd2e497cf8aa6ec73bf25c10427e23fd28137631249eabe9d0308c956dc7a9e92047000000000000000000000000000000000930cdc5d04ed2d1eb62937d9f72fdd733c07a5a0e392fd5216100216b1a2e3cde7053bf766f046cc470d92bebaf6290069d889881d5bb87dd65a9a02a7fe239bdb55ee54a6310bc987e7c5772404d7d00000000000000000000000000000000131c4e590400b69b3657f7c67272b1e3491983997993ee87c94043001d78e605965abf3c1a8c8c39cc08d5a5ef05520000000000000000000000000000000000124f71c136dbb032504da910958e8a7949f1dc5c061f21d50e439e01e67919891633b3bb84fa8a54c69b632f78560ca70000000000000000000000000000000014a4b1a05f1060853f4294e669a20b91f939793a6eada6dbc84fda8ab11509b256d8b785b252a3795f1d2b99a51df05d000000000000000000000000000000000be2489f1f91d7adff356236859679c46b6bf8c1b375e8bc8bd1e97830b5ac223ffbbda60ecda168bacc2c0b90ed25d3be658348e299bbf2438a0c013f86eeeb69a013b8004a4996189472f3372b326c00000000000000000000000000000000111ebb796e8770d5a69e724a8d3ca62ef1f13778baf4ba12bf462211d35e325ff8e455c85237a73a3046e531f2e2255e0000000000000000000000000000000004308b76b06067e0a07bda143341220809b481b40b78edb2e24e83aa0f003d209198825b5fa9bfd92597e27a4054d3ee000000000000000000000000000000000de74485713f5c95653e98b96aeefb79b59911a610c2a848a807653c19d50394fdb52178947c779134d24b6d396ca36800000000000000000000000000000000069f47a71ad765591f6335b962e7c2d87b556801e1e6c25b449edc83432612fefd405c952397a704e9aa5a924769ad4e9b9d0ec92ae7df3f52a95747659f8fa3ca2cd01e8d7ef6de384111246886bafb000000000000000000000000000000000a3f89408ee43c0ba6a7c9c479327ebab426d430e3ff212c65da6364b16195619d27eee83d701a2ec50bd4b7acfaa06300000000000000000000000000000000092715831af983f740ca2c673e7c9c47727d64165c59fce19dc3fbbdd0b6a7be66288ea1f033ebb5ae2b38b3762edaee00000000000000000000000000000000071ca6fa9e546d4bce965b2bd0f0fb97e6833f05cedcf66d43ec88aba411dc4d6db9f1591de22f493f49a1dab1a2701e0000000000000000000000000000000018f89932ec032fc28775d34d588169a1435bf4ad7e2ee11c9d6934dae31324ddb96b3ef88f95d1bb2e52c3c8d9c01516d2ffdf1237b4e03c219806f2dea745c94bf08924e1b9f11deeedf0db19da6f3f0000000000000000000000000000000011b5cc382164fc21c9a72cd85acf61c2a78d00a16a2dff938f0b36bfb3bb7075845a1616001ab53271a9a257a38312cc00000000000000000000000000000000139ba2f27e545d45027a0b11253532e28fa691170e08608472ce3b3f9a3e9398c5ee76953b1a1d01a5e79f194c32d1f5000000000000000000000000000000000d875f44829555cec695f3f4a28078b0a6f168bb0985793d003443b75a141936f3c7c633518890e0f7238416d46573cf000000000000000000000000000000000675420ed817ecd24bc5172d3e7df60ac4281b24ba91e8b5ca8bd6a8321f5c7312a6ba043fbcdc467c8a5c957590a692cca0751c9534cee7f14d11b7c8ccbb2c537a799df59f850bb125c6362d72e9c400000000000000000000000000000000107bde844286cd3958cc7a1314127322251699b51d8af8e6b57495497f21a84e05612b1569b54fc5639a75e9f9deef750000000000000000000000000000000002355b1a60e24e4879448437d2c1b12e58f02d7eba88583e96e9634f7e2c8c6886132ef0488918f665ae3f7b6977c7c4000000000000000000000000000000000fed531e437b70bc4a19ad63c61ccaab49afc50fad1f156b1c8ecba0e1b703f8aea61882c6327d4d8fdd072df9c4e73500000000000000000000000000000000182177409579ad53786539514753c696c8757b8c4d9b8360392f24b591e43ec20e84c0abe468061a9e5e879c5c81314217f890a1120daca4a1bc1bc0fa7529f0a87b5fd6ec385f12b270bc0f1a5281b40000000000000000000000000000000001fb25395089228772d6000025cb0356eb510c964bf7d0c12d47a6608fc18cc448e44880eb5ba8475cbe6418fc9d8fee000000000000000000000000000000000f3b9de9980e5afaebc59c56e02fd75fdad13013842ac035f8d5569a46cc67f0cee461a939aa5a3d8fec2966294207930000000000000000000000000000000009a223ac0edb164845eb8397e0cae4363fb2c8c996c3c5d722cb50be56cc3789c732763cfd4b61470886dc991be39f57000000000000000000000000000000001909f17b229eb351dfe8317a8273d846edf14ad5ee0ebe8cc2b595ebfed19b73983035e19ebaee3d05b1dea35968586961ca18257d9d989ec13d4f158b18ec17d59344f4558b6dae6c0aa0c2f37affb500000000000000000000000000000000081fa9eb8ca7d9db52380e4c408e6d5d668471bafbafd62ba9023fa08f6d300a45295b583677824c29ddc3254439cadc000000000000000000000000000000000e2e613043b1566674f791dca9d860a49a75dfa24dce3fe18f544a9b24ec5266a64e77386b672c93fc4d079eb8e76a01000000000000000000000000000000000f471b86ac5783d720e7d73e8871474c8665e8a109aba27c1172ca24217eefb0f66c53232df1672dc0af6ddf9640e10d0000000000000000000000000000000010667cb22a6a818fa7c729e40a7e70e1f31b0ecd568b54a4d352d5c9df8cf1072ebf2ef1e612efd96bddcbeedd8566430fc004ed8a135ad97cdd1bc4d0c3ccd15e65031ad7e3cc13ef2c260958bc43be000000000000000000000000000000000a0ed87b01f27f26380c6285e82bf2f12ef3016c7e7f3a13041d465825664573db47be6cf099cea615e21f6a5d759b6a0000000000000000000000000000000007afb2a1bd50fa0fd3174d70f1c8d5c229627a496bc9bb89d4f52d47b1862e14d704dddd80045e58d00336e898a996eb000000000000000000000000000000001698f30f824ee5cb71b3f2451953c371987433d2eda570f2a13262ff9e5e529e316b06ef6aadffc152803b076f22db9f0000000000000000000000000000000009eb1d5f3da7cfe9b40a70e1b3c3dae36436e8d068a79dcaa283905614676645c99a5a165630ad46b70bd6be8b1f21a8d8cfaa1037e2c81c6973b221dc7badf25ebe3fb4b42bbdef1124265df2c7ccc40000000000000000000000000000000005c4390b8f37cc3fb9f248470b505a5d9502d44e4a4459d1f56452cd9aec89d114f1402fa45935930fa00888a4860a9900000000000000000000000000000000163b0ca84b5cca4f124bfb5a13a4a3efa677a84dc89b6a61e69d0aad34fade528614e549a7b2326d1f6016bd0d35465a000000000000000000000000000000000bf450dc8af483a9f993a29cb47d5362c9f5ef38afc2fba8040e14514eb834fec6520a413fce5868aa9a2c7c3ff6617a000000000000000000000000000000001063619f384102949fa1f8353f0aaa5031234d736c54103df6ef6fcd0df02a19c3aef471f0413a1e19febed6395459a0c25ecc5d37659ebb0c9e21ea2f8fddc518e3d8faa99627b21faf105445f69d7d000000000000000000000000000000000e35db3017963d3a9d62b7e7fbfa13ce4f5fb46a90c1285ddc0fa481d9379b95a77e8cdd4aab5c33059bfcdcd82473fb0000000000000000000000000000000004fa27c663c8d21f041d15cb199d31cfcb96a56cd673b730dd111bf03cd954cc33799456674ed4d58e8e0dfa826a6b26000000000000000000000000000000000e0df4e7f943db5b5c27bafc7e1ce099b2caa64642bcd6336ef926352682fbe81a1945b266cba7eab52b16f4aa63eb8500000000000000000000000000000000020167756b8c68f535c4691b1249ca1ccf0a539f7274623ada824d0ba789ef44ebb20ec1ba51d46c0a42da78653d287e26cbb32382902d9b1963779070d749cbc4df1e7605f840819f2c04aaf89c732f00000000000000000000000000000000178037c6b5fd1c6c396d8aaadb712863557feb744d2cb9165ae5c36376d2c066f7b1648e083f81c2c96da6562e0b3c20000000000000000000000000000000000b805b4e1cd5d45d8b6ed9d4f604ac0b40f336b8123f7281df43a6e803f8688bd8087fc4d5fbae695d06efb0fa35e18400000000000000000000000000000000000a947562dde45f613ee1d15614940a2edfc770d733a60374f8e9188675d4cf973a5c1081c11fe5a1d93bbe85e6f47800000000000000000000000000000000059473d80c82c6ca06b4aa71d072f4751b3b053b53ffcfb4a84906ddfc36ec5918668a62f07054af1b241bdd4485edba699aa549077a80ff8732b5fc9df148a90f405bccc14bf7305266836566b7a98b0000000000000000000000000000000008b9d0916a9f5689b8fdac84bec3a49d0224dbadca6329ecc156da633e1332bcc6735ca3ecb228c22032dcb7b2f372d3000000000000000000000000000000000cac0c264add10bdc1217384a7379f65b93cf822418f7e4e2b48eeac45f068a61f805cedfb1665dda06e04cb726d245c000000000000000000000000000000001578e98a40a64da59154b1c3d757d8f1f8cdc500482c7b7d65b9997576f745442fbac654c19331977bd210df440372970000000000000000000000000000000015ef69f82e85c81d28893d94927068f14c6516eb7d09898d5d055cbb7a9b55c6d7f686f067ab164160e6d6a8f91ea19d40e2de1a2901f1380a383a741d79fbb0a041da5d7bfb92edab74cd483edf95230000000000000000000000000000000000a6a27b498285085139b8dd0c37b700997134337e696c84b5e0cf70ea3991cfb40ca3a3098a3b3a2fa31e91aac78eb2000000000000000000000000000000000bbd7ebf4301c5eabd4f448b89f1b227415cede3247a1c8dc56a02247efaa99dc78cf370f644ffc06cd2158fa25197dc0000000000000000000000000000000004535a402540474d53c084d4fb6d9e12dba6716ee13286ed758aedc1ef911b55c572640180a54cbc084ff57ceae8a4b4000000000000000000000000000000000759de2a9e0f3c04b4f629a682dbcadb2140e5b935845cb55bd267e230e08c6e8cc5426057473aa03ea2196203bbf6dc062b323592118868d547e83b731d15ba2c7bdb1ee4fdf73600c2584f1db0b45d",
+ "Expected": "00000000000000000000000000000000134c29cc5c33c10f04b6c09b5db71b10304028d06ad6acd4f4b39b16823288085a84a0380a1549f04b3dc692cb8216d3000000000000000000000000000000000a0a9379d63527ab9b5f9c00be4acd54e5fd683a0a2f37c85ba570171c705eaadfb0f4e4be1a8836c9de86dff46138300000000000000000000000000000000006ce78f135dda5af34a0e069d7ef13fd589cec5a6128512bdae7f45f28b09c6e4b3cf638628c9f4783097cc00082aeea00000000000000000000000000000000141e710ce7a979dd1772150d0cb2d5b269d5cda50d1bf7bd0cd827b24f9cd8c1e2775f495cfec0428519627b7fede464",
+ "Name": "matter_g2_multiexp_34",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018aba8353cc470b287a163fdb9b8b4cc46071543ee8261f928a7b856287946637d9b36b728a54e1df5f185a47f1556060000000000000000000000000000000001129541b2e3b2e1a553995b603dc3eee44a5ea440e687739ee9e1339dd79bd96c67231ac753d483e0ca96b27054997b000000000000000000000000000000000e1cdf3591aadeb56dbd80890ff7d5639a64847cec771a19c769df7da732a6d3179d3a89ce0052bd7c982af0304408120000000000000000000000000000000000f5f5f0ebfd2b632e15381ccbabfa88eb774f2c61801381ca73e6970965ecd54f5f3a9af7c152186af8fb75ffb5bc25764ab6f4c43630d5e79e8c474d76d8973a7b7bd1c7f1a985333cf1a6be5ccff2000000000000000000000000000000000e527e40c311edc5dcdbb4d0b70497eaee14533aa8ec57dc7cbd7d839fe6c6ae62b1fd0be2346a038de687d5cf5394d60000000000000000000000000000000005f9fc63027dbee5e0d55cd6c57daf5df7af0d138393a2dcdc71ef9aeeb204ea347f7d574e71f2ffdd37d8f05dc7979f000000000000000000000000000000000f8788034c9f1c9c2018a52326c046cdba8997199732152963819b663c6e58e9d6a0065289e2e25a97ce5627505900f20000000000000000000000000000000002a747bb3bcccdc6ea0af1bf1d0ce55de3f41b93060361b30c76063346b606322a76ed7eb260219c83aea0806ac7d8583280f1b1e78d2339f64b5b2f2bd77aa24623b79fe2c9debab4212f4ff564983b0000000000000000000000000000000002148c043e065132e978e89f018a5b728d278c95c9cd1a6f276bd13f0cb708422a62fa22f7b377adf33055fcb09a6a8100000000000000000000000000000000024c4c721a0574e53118bdcc3fd41f73176bc8264d2ff39673210525166bb3513016b5c9af67a47a7032b74a62effcef000000000000000000000000000000000797dfa8cad94896916b7d55fbbb3eb0eeb74f70231205388d0dda69dd8abb436c22addd22c1e3689093739af957b65200000000000000000000000000000000010dd2ea2d45528de8bf1b5c5dc3267fe8951e48ff5987e67ec52d58635521cf1905f1688894e3e23a659764880b2301d4d27ff9d03ab9120ac2adfeb36b070015f0e90782255ddc9111704c5fb11177000000000000000000000000000000000eecc0a4edd3cc3f70d3e0e43ba56b04cfb3f1ac23c657048a94318e622217572b0f929c73f545d6f5f5613920c0580200000000000000000000000000000000137a098ea8d3aed32c197a2d244a2e18753045b55cfe16874f79c728c664b7f23b10476f20dfffb2f80417c26dff4f860000000000000000000000000000000004a7789b02d7d95a2ce0c7bac39d5b057509200393450a47fd9d087a353f866921aa11185550537b98f3073650d9a1370000000000000000000000000000000006ed63730bae06403baf705da0e30c6c00739799eea4a312d06b8d7dc35cb43a4f1e941a69e55ddd7ab8ce42d8629fdcc66d5291311c7cdd1f33e5365ec0689608b3569427a8f6a9cd0b94b671472e66000000000000000000000000000000000ee7ddbf43f17f722dae84d34d26add8c1d732918b8c75c6b295f2f584075cea0c655911410b32c06868c1acf36aeaaf0000000000000000000000000000000018775682555d9f5a576cf9462170910bcdd083671ae2e4c8c6fa99a702548f1ce9afe90e681b00d194322b1a2a3be7ef000000000000000000000000000000000f3935bbbf58b91fe8176f3e25ad3fdeffdd6b369ae70b704d4e54d4fe32fe5987e73aa5aa975e958497340274577cf3000000000000000000000000000000000c088bc439d638d86aba6bb1e6e9f7540ac2da3b96080aed455edd1fbabfc141e26f125cc3a9cf72070a24f298dcc3ef4b718a5129659250640e333f4567043ca749063e63d87efd86a9995adfd3b8450000000000000000000000000000000018d8a47d1a13b9b8fb5a1625f9616ba120d5c677bcc996f694b7e15d251fc4bc938b0a7cb5b70f22b8e9f5b416c513210000000000000000000000000000000003d0646458bbee7ccab27f858b8ab0af0cf583da12a40ca5a954d7eaf97c897d379129a63d8131036f29c30c6e644149000000000000000000000000000000000d5466b50975c5a2dad96e4e24339eafc8c85c2497a6f19e12d96603596498654cabea6995a92c91b8319ce06f18d56d00000000000000000000000000000000191a96d62139f8219b9e4369a783400d045d72ab2dd83fd229e08a4ca73de59a11a5add86c739cb3bab4adc5e9f79685708891f45d7bee38fe382820260061e212c6cb9a8572b4d1854f3ab09409b05a00000000000000000000000000000000032eb1f7846b563e98fca0cd44ede4909b6e16a893f5ef01eaccbd7d8aa11710606bbbd0ee6480f7cdbdc9ffe66c3a9c000000000000000000000000000000000c31bb6fb537cfcbffe815d86ebfae1f5053ceb756818ede8a58cd84cb34d0eacc70ab9095f9db1691e4fb4bb816d570000000000000000000000000000000000a8fa1dc2f28277a4bf8fd9665d4b5c3baf1352d89890d4af94a3657cdac7fd72558da1e65cbc5bfac142f0e817be74f0000000000000000000000000000000005ff65c22ff0abfb33518791823c5f2202ea5f7258c0a507ab84460335ffc2cc8d7c7f670752a7647d6a6487ca0c9adb85ac0f94f300b004c7f20aafcfd9129d6c2590749504a3f08c4cc708fa30100300000000000000000000000000000000190379b7629f74bfb88096dc9ffcdecebae0d653410f032a35a811a09022679c9be19f3790af95c3205a396819e068e1000000000000000000000000000000000b6f114fc277ae8f0b5374dd349985bf955dff7fcb0095e0e1e137fb539814be78c924074bbab54f29dfb42f3e7df24a0000000000000000000000000000000002d86b0507c147142d03d3461bfea4c3af7e57a6edbb372387de24a27cfe27c44ee4b9571325a1b3f5e83eef450f2fc6000000000000000000000000000000000ac3b226d5e13c36c3a8ef0c8896d9af55bcc0cb67ac1cee57a5c6519617ec77af9af60ed44e0a8284a2d59816ebf848fdbb634bc0f99c5795f3c4d6a0efcda7f71427f1eaa1c5411caa6cb05ee3147800000000000000000000000000000000079cd4511e953e4d1b3f4f3bbbc66a62772018e809779fa39aaeeffac737cda9a6116293848f967577f03017f33231d2000000000000000000000000000000000ce3cf48be423a2fc0188b94f2a22579872e9ba140798e560ad107f63ab2b8c601831f89d06a4bb8e7a758cf836ddfb3000000000000000000000000000000000a6a90f735f215a79216fc4e7daffbf74775f38824952af72ac38c38a77a277483e34bc95031679494d76f109c0aecc4000000000000000000000000000000000d55fbce780d885cf817cd2126e7acf115ae9c72843af23c376f3a5d4307d1eefaa0f4691e7c09b5da1707aeaa5b675af5e4695c01849259fb969183de385ef30c2403e081067c2d9b6b5522c73fcf200000000000000000000000000000000008924efbdb46b9324bfb79b922ba8b7d83f5e5e4b3b736105e5339805838171801bcf17208f3dfe5c7475d4e45b6ad970000000000000000000000000000000007bc0096fd23f0c93f0dde8a3974ea3105574e031202f6316d5940c85164c6d6bb5b86078a0c68dc822c0fd1b3dc8cc10000000000000000000000000000000017276b3208b347388a5657b10e3c8e4a187b376e42352f76ee3ee88873217b6b8185022c93097cc116abdecf3cc64467000000000000000000000000000000001915ff932acbdeb52f07b664bcc47c3a5b096c6cec32da4d7044326dfe84358e49539fe50782538a901b99428446b0f50ea6fd588db5efc5fb2248634cca683d39d610886b59eb3077fa9612c368d7690000000000000000000000000000000009e295d229b543a17db1cc85c846111b7097bd169d19b410de78f8da9684e664922eae77c64b0db430aeb422016cfe7d000000000000000000000000000000000e29aab30a1da56b8590e9df67171cc1b9c847696b51147cc57ed6c3b55819cfa0992c67e15e4ca6de2573c9e16231c10000000000000000000000000000000007cc9990c6722645e320dd16a4be8adaab41f958f769ba0d22e235549a7457778cb9b14aa6ea5caa9e0bd43f8d04cacc000000000000000000000000000000000b2dab5cf37ae8e76b71dd8748c86e8823142792445fa0b140de31957d35bb7267e3d94e0dc92f4342d9f8560c5d9d86dc2060a3421c5a8336c80983c9a160345901a496c3a74fc5248fca081d09953900000000000000000000000000000000128e2aa795f8479da3ea2a4efd12aa90a6fb019d4da89fd372e6848ff7ee17da689d766c9e49c88c962eb4f682c56fff0000000000000000000000000000000000fd68bb80d6b2200297aacae1174275f864669e962d85c9105032d7a352fea548e9fa0629a6749c789fa0827a40190700000000000000000000000000000000175bc3918dcc972fb728f1d8cc30ce9887efc6e0b254d8d22af87f95cd4182129d494c43d11b028c4b9849f5520a4fc00000000000000000000000000000000007c5363f507a01c0b6935fee0413345bceaf1336cdd20f69060bdba2e411521a61a549e6159b2e006ffa16e3bd77e998e27e4afc3e6d59d0f5871b35eb83b46cf15da6c326e88dd8edf84031f58e23f90000000000000000000000000000000000efcd782b89fee74ebc037160c6653ccc104260b5f8989545b40d51ead6ad6ce6252e1232281c813e3c883af86e68ca000000000000000000000000000000000b68ed21f76ce131c089dc454dc48ef948cc7c6d5fd87d647db954c9eeab2f7f76ccc51a1cff8612e89bceed16ca03ba000000000000000000000000000000000cd776670d5171610046fa294fecefb42f9bb4d71baed4af65a09018b09ad9341789abc23c9feb85adf96b4203b0c0a0000000000000000000000000000000000ec4ca0091a28b73c9adbe7120f2bf1a84a62ebba1e86b1948389b1a1966c1de4c632a5e245ba634b53cb932f5847f6ecc7efff04f143e2d038de153861da5e04016a7eb17fbe6365de13069d088b1a100000000000000000000000000000000022f319bb5167c2b945a69a438f712df8975a0e262438ea687e2b0d824e2d1d14bff1065f50fd6ae92494f6f3aa9472b00000000000000000000000000000000198ce9e4ddb6b423788dbea82d75513f43cb43ecf1b27c8788f041248f01808644f60fd823e5862cd7afb4f7e8b6b6a100000000000000000000000000000000119dc1be1bbb7e678319db73055ccb88ef7efcf6119f8a9c43c69247ff264879a627f653a10a950e0dbe69155ebca4f1000000000000000000000000000000000692a0ef5a75d42524e3fd52ae073b0f2ddf6378f18a5dcef05af4868a899b93c7f1d2691883e5c85f97052ef1f4177d09a2c3dbb4ee4f485dc60dfbd94a358a7c62204c021f2d7b140187ee9ffdc4ce00000000000000000000000000000000102c92272571b73a7df754728d7293fd8050d9dd2b8605c3f7722e6de541b7fc6a81b01c1cf15e5241ee4ee1f81ab39d000000000000000000000000000000000af1cd6f23bbd3e9ef75eed6d6d99a7cdd24574881b3609e45c4adbf82e08259d14701fcc5b6338ecf52166aecca003700000000000000000000000000000000026a1a4c3eb54de2ba4509dc806db9efc7e26247d501cb59c525b8dd15d03b91abafa9ba5816c22e1f8ca159cda34bd500000000000000000000000000000000170b510ec227fe8534a2cbb0f405756491c4f6832df552bd23980ab0946725371b3c24fa8b93a38bdcd47e1026e1d2a0d9b15c065497392e4b477a556ad620d44e671137cfd570d53590b7528f8ff680000000000000000000000000000000001423d1707e49d2215f639df75ee0e13bc724efc7d099259179260ba0f17157c4efc4276844bfdc46c61ac2185f64beca0000000000000000000000000000000019ad06d215d3c819311938f89609ea7cc63fadaa11bcc86cf5f26370a966eaed1aca312c18176674b5aaca3ed8ca876e0000000000000000000000000000000013bf3f13e87f3ce29f0524094e2ab8e39679566add32e779256006dc92ce09f60d5bb9cf0452b90ece71a5f6981d77f300000000000000000000000000000000112e4901efca14686c30a883ecdafdc389303f4cf46345e229885c76d900b0aa084a957076009ce22ee36d4e285d410c9e2a72eff2ec29a65b417767e7090b73c2fb530de6c8f4e4ba30543946423b12",
+ "Expected": "0000000000000000000000000000000016d1fce53fc4cf40acb0347c0983dda46383e4828c16985459ac89a2ce8d3c2a26cd9acfaa2ec899cc63b4c6bc351f560000000000000000000000000000000019c9626363b511a79f297dc79c5a3b7a2e5127fe49a2fac5bc43a4376f170404f044f9f84b82cd09a306012fc81e3bdb00000000000000000000000000000000062e324f3d7c5bd39808b762a5b009cb30bec14a9591477959339bf2de9ef27eb42a0eddb95aa5fdca9bb9d89b278cc20000000000000000000000000000000000f05225a4d3bf910b0ac0103594a90684ffc0c09e2c21744032e30470d5727be3c27621dc2377e9845ad78be67b856a",
+ "Name": "matter_g2_multiexp_35",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c64577b78ff306186dc44131cf8bd946a68e65502c4af9613154a7e3ffea4fe4e59cac4a500894b470a74e66db1834e000000000000000000000000000000000b4311c295bd30174f17b9ab3544f1496b9655302a4b6026a113b1aca31b555ce7b2d812bf8fafb6b075f67cdc59b77f0000000000000000000000000000000012d7dc3db10ae6b4e3e99c655aadb71124a0bdcfa6e30ec13c7c977d39f83aba4979a1f45881813a3a68e149a40120a90000000000000000000000000000000001b958c47cfecd619c05a2c54315585d15fe377beff889602ecba6ea3b29d51f6480f09a0a8490e4c754045f0bfdc3eb7b9aa7e0bfaf135ff24720773ccd1e0a46fab6d678d91a14de137061e145fb9d00000000000000000000000000000000010db66653f2ca73e55d85254f62e8b558584d546913e4b8f530968088d90cd5c4bc164fdb77325fe0bb2fb1a5683896000000000000000000000000000000000a1af9bf84f0b351c8e8c082a79c7ccae768bd2ed40eede38666aab1901a6eab0cff258f440c8c8eb4854a824b9aab4b000000000000000000000000000000000444fa654afb57f1b01d10be08a330f23667af58e3a40c630a2e01c1809125b3ff8f76e8a39418688a023293ff1a45e90000000000000000000000000000000002ebb117ea107a3598b888dcbd5918dd0ca307b21d65843c6c28b3efab89d0e276e5d92283bbb345b674d4a300595425c6733c9bb7bd195622b96c4181e8c8837d1912fbadf77d6029f7fc44d793b48000000000000000000000000000000000105818a11efaeab4801d4fa7558b09bd56294be7f58e3e54fab1f4f7c243ceaf08c99a14c3128ccfd866b6f93caf989800000000000000000000000000000000091ca092e5f83a04e872e621e71d54dd6886d088718f60ed5b62d3e4c165d3ff2cea1e50fcb94fff251df0f5ee453cfc000000000000000000000000000000000b42051a1ef52f87536b9bca459fa7070ca17bf825950b13b3bbe9db183ef722f62af6c05c174c65d59b722e1d2f5b0e0000000000000000000000000000000002fdb4a5480418e43aea28e5041af6ad55a6c226e1eea1a0449a99b5a937375285feecabea95c2652da5113dc17d8ef4410bb66334c677397d04f59eade9630463065cd7da3c9d50580c7d66bbaf487d000000000000000000000000000000000d8f93b589678d4e93bdf8da7834bc8edab648ead731b7f5f0cc299488f07262877ee9bb1174ccc106204dcd3f1f416800000000000000000000000000000000160f740ffca48d3a10c43e591cf46c129507f10e65d76a031fded2930d6c2dca4c79d7813f63e4ff71aee09d672173680000000000000000000000000000000013c768a4889315faa3976c8e43b4d466ea594bd94773f270a198f2571ba9662d10435d1e541a492055c333eece9bb29a0000000000000000000000000000000003dcbcc9e6a0cd5741d77da88fbbc269202e8f944a5df5dc4f9145758654934d5e1eedd596325080382458961ed3d21ed97a16fc5b2c70829b15f73615286eba334de1f520b5f0f6a83d2578399cc0b3000000000000000000000000000000001344fb37c1d7dcab01a4bf6fa50c6bb7606f7db22b85a3888ffcc2e9f229f196881cd7c82160730727e49b9e6fea04320000000000000000000000000000000010c7b15a6355d3152eaada7a606031f28809f278a1d0e04d264b563185ac7d9e351295191a6a90ffc9c6dd33995265db0000000000000000000000000000000014438086226a061a1bd557dac24d9333e14cdfa3a7bb00ded4a450e8889a3028b174bf38ae1347e6aad19ebc1cf5ff7800000000000000000000000000000000105165703c4592cc4f1f489d78426a56434dc77327c13221b582dc25306f4c5bfe596f3e47abcb741ab553fa14cad374bdbac08202bbe5df1229e99c76c1727f7789e0f8c2002f0a2c195bdfc00acb36000000000000000000000000000000000ad8b55a198a5e788bb54c32112761ccba9863cba16d95ec9e30181376e7eccaa2741660f2c5f708300be058e566ae27000000000000000000000000000000000b9bbca7db413964d2ec113cdee2d7a7bcdb712d285655f6b2897dcac61456ba4d08e25e8c28627231824829bd7d13800000000000000000000000000000000001ae49c10675256651e3e038a2150d85993fa6f2a97b9bc02c693ed97ad52af34015176258b3b2546b81010a4381d85c000000000000000000000000000000000c8f9668a0a497420acff5207a07cf780e0b2ba78083eb0ed8eef76beea996210541bae2e64d825000f307d54cbe3b2b43da827b812ec6ac23b00208cbad0f2e8b3a32434aa61dde029683c34c1ab1900000000000000000000000000000000012990a66c132a31d60d182f729b52d9b57d9d1eb1988b6f0b4d9fa2847f26983078ef9bbfd0e888e14bf7d1f92d09e54000000000000000000000000000000000585215ffc2673a197bf9cc6c6424547886abc6ef5c6edfeab2ef0c42034a4a458fc7155c35c84a8e9e9d89fbd4aa25c00000000000000000000000000000000118fb4fe0d3498dd2b55e62272e95a1203f9fd22314921d3e044f1b162376aaa7e8154a4e2184b66451aba98729330c0000000000000000000000000000000000364b9032ab9cd9f599979c8a93acbdb831707f1f84fdc92844b58bc7e4d72472ca5b09c51b1b04271ed9f0e391552463c7a8f7bf434ce5e63ac9365448da8663745f66689b4b04968f9b8b1b6805893000000000000000000000000000000000ddf9e4e302169e195f4f88fed06e0c93fd1b542abbfeea5da5d47c662ad9a16b8f4aed7874354fb9008d073920e1e7e000000000000000000000000000000000043fd1a4b781f25e8747ecb3eec45ce90760e0d5dd701e8193a7e726684ccb8ff21f0219ba15e9e777d339a3d87a1ee000000000000000000000000000000001117d2ca429048056084e4847c7169b4c8ddaefe1d48079949f9f14e4d74f0e0b38a95d0f17389f61da7b2a6d8cabd1c0000000000000000000000000000000007adfc7d87b1c533b4439f6b30d38c694b65b3b321f3eec13cd7d923f1d5f117005be6c3ea901a9479d79fc553e34e6c51f2e2bcfa6ebf84d3ad83c57257b9032e5d62a8663ed5d77afce00f33382bc600000000000000000000000000000000115a81aebee0329b174c01458f8714b13ea3fb2dbfb051b27b29b940652f27e01a84e522626d12be80da7e1039e2baf6000000000000000000000000000000000d9e37d2e5e7160db30acf5593d1c282541a0d4ac0482f0759fef8704b9ec3ab1e3ed248e37c6be285e890ef1a520d0b000000000000000000000000000000000c198a22c2f590df2902c8dc2bb1ee427b33e9687767666140f9d3b51d73fef18a259d43d86fb3559b1ab0abacf547a70000000000000000000000000000000017e705af54ab76145a79e747167a4fec6ec3a16f3ceef86b1ddd1be144e616ea7d686bbccbd1c5c258e4546405be023d6d8b15ec8908bfe008414757c0c7f79b3079f9db86d91ac3ec8f38ae2c94d48b0000000000000000000000000000000007c4c31287ae0b3bb90475f84abdda36610f887aae311d8e97bf97bbdbdfb11d38c7de331cc9dd022926678e5180c0770000000000000000000000000000000017f4afe28adc4b24d16b9cd97aacd171c2104b13b079c643d664a7c924151a401c352832c4967c0e5cecec5f1d1dae290000000000000000000000000000000005a8aa8a3a91461e0ba256e44af56875f8d07e24628e738ffc057249d8380417884f40c84e76dc6ce5816ffc05c0d686000000000000000000000000000000000f84bb7385a6936b519e881a708541570a31a9d7897ab8b348a350adb0d30522567fb917c9b6db661b6f53f98b5e68aaf4723e85076d48389c3fb5a5df16b6bc6f7a69ca701632b1159677bd8a6f7bb1000000000000000000000000000000000a8726ea352582ed52ab4e440102963891f059cf5a3f4901615733ad560a99930efd8692f3c30256d58e5cfc4f0803bf0000000000000000000000000000000016a623dfeae872639d99e3b8209748642f20af796325630596b6ab6146783bd4f2247c7ae38d53ba9a3fc0cdd6f29087000000000000000000000000000000000e40709656e569e4fe90eb85d8761c6ce44a4272793ccb7635ce75d67d97464e8dcd8c32bd4ac9a36fcce706006915b20000000000000000000000000000000019e64802756896206a9600f2d888f3d307ebf958492b1b5153c06a11231e2d7d2f1786368447f380093a29117cc25da9a632938a6df169fb64daa55d2f874ef7629d5be41dfa0d50827c082333f0fca00000000000000000000000000000000019c7409cda6084edc6e559da9b361c96cf207f1e2cd63cabc9b86c5bcb07a59b43e9c6ae3e90a61c872f168ab89cb2c9000000000000000000000000000000001101bb63a452b766a085fb788937f6b751417dd8d905ee50ab5bf96cdbb9d7b68c1735460a71eaf9e9bf662734f495c20000000000000000000000000000000014a103871fe523cd01053a992eb9884ce83c6023bd6a8c2cd9ca60b8780118c88502c6980904f2d2bf9ccc9fb597d535000000000000000000000000000000001929f25d52ee6b9a44333237c732a63ce2abc80c5510bd67faad1d7adac96eac5449823f3a52ed18bb90b93d9640d0d1283a4da7f71bde54d4b7e28b2b23e2eb05d8b025e77e15810625d71faca6d6e50000000000000000000000000000000015b0a46692f57ccd2b7f53040dd75f30af0196aa3c5499049eb172b4d927f96a59c42a129117d6162a1bb31d2e8734a4000000000000000000000000000000001366dde2d9070a2c057744fffe78effdc328b122e356a6aadb10c3fd2e8badc0ff70bc6d18293b3c52428e2ba78766600000000000000000000000000000000016fd48b067b949ed75bae3e4db29b5785bf672bd01032a925d653f8a605998e1eff6c77ec39dcfccd417f1e0a9defa820000000000000000000000000000000004cf22bd706dbb1cf8b97187ed97636380871402b3ba9de58f174bf50a7a0b528749762c3f55f5f835a276e43b46e669d402b71c1fc5c3f3a4ed9edc73457a27ea427f83a784796e01b7a1451b3305b0000000000000000000000000000000000ff424ae9372af46de34210bb0bd670eb173bd49076df5caca4bc4293e742121267a20506f931a4ae77cc36fcbc8df4d0000000000000000000000000000000015a6815b47966fb84aad5de62e6d4280f9135e129f33fd01e667f4d6e1bf7204317fa7741f3cff3682e251437927131c000000000000000000000000000000000639dca43483b79ba8043130e508e91fe3f43bc362fd1dbb135a2eb8f3b94d5cc4af70f1101c790545a0eaf2408706e1000000000000000000000000000000000045f0a04a642bb6e4db34fbffc8adb19a24648554f36ca371fb1a851384a4516a57f1850f7d6be59ff67029ec4002de310bc47acb3aba7eaa490ec104ed9b2985f65c7347f69fdc67b76f6f43846a99000000000000000000000000000000000e796fd500cb1a25b834baf7335641f34ccf04ccf60f82367f0e5c8c7fce8e3030e7b916752bac8e3adc01cbf4b319ac00000000000000000000000000000000142e8bbac9cae69ba3dca48aec045e0c4d7028f73c254433f921b7240761c661cf8e774a21da249f7758234cf7607fbe00000000000000000000000000000000045a3d80767d116e89bab0e9de812ffe7ffdbc41b61f5f17ad16be5bdc9968e34f46b937c5f94f8197e21b358f44b5240000000000000000000000000000000006978b93018bfdbaef0d40f1278e831a1fc50b44fff39b7c93820a284d90b699981b1f422f751a33094ae7b5cedbbb2691b88ce9888e5dcfef70d6f960a456dbabc792571f2a98746b7d833e7fab98500000000000000000000000000000000003c3561f5d255cf1f83cb5f4df8e3b8d5655d965826d56867ae66da631f8e7d489f733f5824c36652ab00586d9c593be0000000000000000000000000000000010b3adb0017e2cea1b71680ca33aee368429880759660dce2d3cdf57b6cd7339bd8853e5efafb9a5aec3f7e22da676c2000000000000000000000000000000000cdf976e4c65edb79ff15178f6ec5bf0a77a30d97b799e433f216a2fe3eedb10bc6ecbee2974167128773cff43f1922c000000000000000000000000000000001599b60ee70d927849764880830b2e7355daf95eefef39ef61569a2b83b2bcced4dfb28047a1e5350cc87ef3cd5cf1d93e82cc1261ac3864266379b4d518e25c05bc492a8946b38b8a64acf47aeec4b8",
+ "Expected": "00000000000000000000000000000000123af49ac2981e14a490a4a6792f21343497b562266a47487cf6c650769c810852e357445bc68f3460e7822e8cd1e3f000000000000000000000000000000000143e79853e4bf6d031e1116dac2c6eca4991b8a1f822fac1d352d2cf1b88df239d82df886f0b24b3e7f305286cc1257e000000000000000000000000000000000b621056a9de2d83c946b1e2c7a07f9beb8e053202407323e412c0d8f60123cfd5818067f57034fe1b1b5a3d1bb285a50000000000000000000000000000000001642fdff2c52d58d38201cf44c31e00df47ea1439e9896b5ac5e9372482f4ffcc698be46c2d375d57a72fc677a9fc8f",
+ "Name": "matter_g2_multiexp_36",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011f78204afa05c3717d3908dc7e4356ef96c426ef380b6abba3a5616d9ee01addeec3369967ed42e030c4b8ff9939c4e00000000000000000000000000000000175a19c86e7eff0f4e809a5105503ed223fe327ee4617f7f51257426fe408373899f39014821292a75e4cc4eb9f7f31e00000000000000000000000000000000052130dd3cd17840385db424802d869d7eac781365be25ba401b7b0e4025353c8dbf59e5997b5aac74c252192061299d000000000000000000000000000000000457f4fc7ac5d7d4fa07e8ed125df4c4e950e6ea926be9c04b6df3c3699a10e99af7ea8546b8ac70c3003468a75c821ca2a1148f1ba719b2da92c418fd137efe21a44dd4cce013ab36e57d97dfed92990000000000000000000000000000000005182a3af2b52102e09214d048a1a29d1e10b7ace6afbc4e6b1ebf16790be372dfb6d65cb8fe08c3dbbed8c5435a59a3000000000000000000000000000000000f2a1261463c09a88edac443ec3cea8aaa19659e8b7ec2e8a403dcffb1e50ebb3d07217a9ab057d8d097c075609c13900000000000000000000000000000000007d6525fea8fbb685fcf89bd772d48c406aff7377429fb199f27c3c3337f11f8e24c4d81c9026b469600d11e8cce51be0000000000000000000000000000000004b6d6102debaec16c34fecfeb444e7ba573b13b83ec375f14d2c541a0d1fa528ed6599a0eff4f8ca527c5baa579f762fec5d6167d7777169348cf81ad3eab5153f8f2f18fb5935c5ee5e3a759f9b5af000000000000000000000000000000000ba1f2b2c3f1c57afa0ab647d32af5d036ef18069a4abc9795dd9927ea274a718b67373230e337cb9374ef73b5e2303900000000000000000000000000000000016458ff2f5d600af9d2983f535c965a2a8aee48c0d95095bee642bb7bbab8bc87e3e7c3b52a787c53f0d1e00cb4ff32000000000000000000000000000000000d11324e812cd4fa65d20cf58f88a9bc9407657834d7a92f80bfd32c7085ffa2f9f78d7e18c1405a03de939bd0dbb06b00000000000000000000000000000000144a0f4d50bcb16942d22a12d28bf34d2b4c51512a3f11c130f1566aacbdb63ec3984df5569f41ef621f50d138883d0dda609e1c8fa42a993ff355a70d44dfeebc71a801daa36acd437daec5d7b645d10000000000000000000000000000000000d7b138fe445d7b7e130134db653022ebb389075ffb62ff9faa544cd0fdb9e78e313d0b1cb19bd812421d38d1e9996d00000000000000000000000000000000084411aa2719b729a1e299fe8a710f767009060f1b2becf2aaa92efdeea8c91239aa5d2504c6e7ad2e3f39d89ef00c1e00000000000000000000000000000000017e86dc0146c9bbfa5ea1e48f49918167dda13b31ba73311fd5cfdc12845b95b9e90972a9a4d36203be8c5920f8de5600000000000000000000000000000000150e4b6fa9cd9a609241d1de8a637c6ab25207bccf8e5eff4a97ed633b67826135172880b118037649407a3e1b1a0661bc5f7f5d096247ababa51852724ce9ddcc6acc7ab6180beaa1cda97dba94b4ea000000000000000000000000000000000ad7430b7778248d63a06e26119e5600ae97071fe8827b24440587e8bf6887b646f342741af69d20e243c9b45d7dcf24000000000000000000000000000000001230cba1a5a66197875240fe00c59b796ba1db5ea5653cc76bf43d6adce0db3a109168593beb39bb45688c1d124b9eb300000000000000000000000000000000144652474c58413cadf9b31715152052b7618e7093e931367a7ed0340e66d84c0471b6ec178e1730cf10e749e01815780000000000000000000000000000000009abdd0210f25d12146f2911a60035867f59cc341b35c73bbdf8f7a5a90d0bb6566c6ba0e868a3d62d3557436190f3f63222b41a59f9551e91572ae00582e1e41989ff5f8e2cd1ee1a78f55c2b28ecb40000000000000000000000000000000018ced3cd0c169693368fcf9c3dfc49fe248f0b9b5511e9407b8634d8ed7b54ae2dc4ac6ffde8b3dea70ca86ddc89449c0000000000000000000000000000000002f6b227e699dccf7ab1e0b1cba4cf9f05c4dcaf9fee6cd94bbb79f42bc9598fa23eb2c653a7654db73feb511b24829f0000000000000000000000000000000019785959766eb8b00ac2600d87240f2876e049725680f4504f59db6642ff8f82d4e1b856929643906c3be7807a2443180000000000000000000000000000000018285acdf25a475b37ee4da872debba4297fc8731eede6b22be3b0dff12117634de44b84a18042852ef419c3ae18a46b7431e5c1fe5f8d38c759bc48e8207695a3cdf07d4c1fd02f1009088539085da10000000000000000000000000000000019c7950b01e15669cc1f96fd94957535f32132ff6a5ae788f6f660024c332593942bd3e9603f862756edd4f3ab17b20b000000000000000000000000000000000bf3a6bbe10ad91d687a135f4863ba0332e9b04271d437a6a4770056e6b1ca34319dc895f9186482bbbc815aead03392000000000000000000000000000000000a3ef4d4f7a15da04a91ff079cc40040993a90e9ea21f53e31f7dede52dd513a97ece780374c5f3aa8c8b2e525ee31d10000000000000000000000000000000017749fc7761b06432632ac686d93484f08407504e58b04b3890cc2101f15d21f46ec0dc1e9028c8ef8df10f9ae929887d474e755f6ce9045baaed65c80f5a686547089e8cdf4ad2b7c2ce7c255cb5c730000000000000000000000000000000005a36af876edfdf26175c185c3ef005530e02474232ea659f5cf251c5de5721f1b44a25714967d283525632789331d2900000000000000000000000000000000130a6f5edf94736477143b1efc316f131b36d9658c484821be08e7f5b9c93f60cf34042858664db0ff0240addad8782f0000000000000000000000000000000004fedf49e6d49c074dcca96c01607da2105d8053861b4c677a69cff0f82e66a2a63f32f3d9fac8e6c844a1f77055bf31000000000000000000000000000000001528541de3a9d4a216c0e60c31d2b7c7cb91b839fc31307cc70f18e9b87b92bf5b9a9dc4eaacdec6e6bf7791e547d8a2976c8775b0eaa1e4aa384d222efc476305c7ea2d625cf5c67ea4368d7a9fccd10000000000000000000000000000000013faf7b2b8514f77021d8927a3b63bb7c57785e581f40ca82882341c13a9daf062a26b668844e58291366ea6ae2f179f0000000000000000000000000000000009060f9e1047f15f175fe95cb0914f4941bcaf071f24e856eae6f36263c812689a9217da277613c10c8e254a0933c80800000000000000000000000000000000154619e4ae3901789ed3ecdfc76069d8026a3e2cf142a144e8b58482233380690e378de6b81af0ed9b6536da1cc2a30b00000000000000000000000000000000040c1bce922503699e1fd5ac67725f11d7f9bb6903ff9204412f65355be69d73cd7330a3f7bfcacaa9b078ba6b9a9f839db274233c46caaa9c99690fd00fcbfa4eaaad7c41f8ae84313448c787165f6500000000000000000000000000000000103d91916d537379d6d8717b17ac5b7e9fedd98c24890b51c027cc086458259767d989b3ff9d6adad72bf977e4d378f400000000000000000000000000000000159c01ee371622378339518217dfc0570178aecc938b4a008dee1a6661ffa605c0f1472c107558ea791e0959d7dc1c70000000000000000000000000000000000ea3e10cbc3a55ef2dc7bde7a2e80666557e9e8fd9ce77e2e92c2c70777afe43c23072e263e1def56cae4b6d3772db96000000000000000000000000000000000cf1db638331c47f9080c04117ddab4ba79950563810d50e04af819f14ae0981f6e1e94a635fc90226c8d7beef0844354ac9f9ed46ae5aca33af9ba1c0fa5a2138d4ca02b962fd1d02b4636114ce19970000000000000000000000000000000000095c82c58182ae9a1ba14421c2966d687f7225ccd192b24097f997b471d13b46a048202712cb2d8b1be0ff40755dcc0000000000000000000000000000000017410aca05935a06942f673d1937a593423cbbd226f6707c5922306d28a60396baa08a941122dd4c583331c9481a734f0000000000000000000000000000000002c1d3a1262ce8aae42a6ed10d8020c31a468127e1a59d57d2d409ca9d14143d9fd21353b260edd8b387840580698846000000000000000000000000000000001512e29256b6b9f5a7ba4f79dde2c915b162e4881856258ac2050f02868842381518da4ed824243692b131710d7201f8ab300ee55e90ac046dbd772da788dacddf72c559d9378b39507987a9774301b0000000000000000000000000000000000ff83bf1d50fe35bb3d1bcb07b02d78a1b44d2e0c6bf82c600feec3897fae8b93c0ef05006c1322af0a732392dad86e8000000000000000000000000000000000d70c4957cb3615027cb950e4224d41849b9ff1b435ce936384fe17c4d7bc2883fdbba5123ca0c0c010651500557e1be0000000000000000000000000000000008b16fe9af45fa913aa7e5d01b5b58f946004eaaeeeb493759a5bc2b192d2dd71af24ecc5c6838b5e267ec2dfcf5c17d00000000000000000000000000000000038ca027c985af3cf60cda13e770fbe4919d3a5b413763c8ad155cb4903312822366eb986f2ec9e0804594ad4894e468275b22db781d5e8fd07f36788bc1219c4b4a13554c28d92a381adae111b265730000000000000000000000000000000003a313d6d41f1ebd6b98b2061a2d85943e52d89e4b8680611d41ea182385e154da24248faa1563e6ad79172f91a8763f00000000000000000000000000000000038d9388fe9169710e1a205ecfd03f674b47ba2275794469dbd5f193a55e00765c8eed026363b41afda417bdd8910ea60000000000000000000000000000000007a75f53d9b8e5eef19ef6f5fe8ce5d5308a1a7d02e0bf46f91a1e0cb22555752d82d8471c123269050fd8f35a272f600000000000000000000000000000000011f313127a036403652fb2f83c5122fd12c362ecba2251bd6c357a964dd758eb2a2c3053dc668b9a4bc071898d45cd46ec69b95dccdbf193d9ee4c51615c0b7be5ac6bed3f2559f0cb2755c634839ce7000000000000000000000000000000000a43335eb6ff3bf2daeeb1eaf44c2782eeb517e82e55203a247b7a396e26fdf85f93695753c52c68819b58c95f361820000000000000000000000000000000000c240b7896b3dd0c318dc9ffcaa001d20bff288def3ce42752d660fd705e1544e292a5a0aa3a9a80ae91cb47cb938989000000000000000000000000000000000e5195bcc4ee8b149a769322165b6a3157ee7d04546643390adc812b6296675dbd31168b268df869a6722a7c8f51c79d00000000000000000000000000000000004af7dc8a5c552f00d55b996d193a9571173ea829eba8fadfa7becc2f4149ee7c6c4d2c8c7b1970df33cc56e450657331e2bf1816a84c190eaa850ecfe1a9376123e0d0732d90ac3537668f8f18b9f70000000000000000000000000000000007860c3403607d4e13f738357e18bbcc4df10fad4aa25776f84d3c2758624a83aee0996146ba17a812384e1d67a7c54f0000000000000000000000000000000002169148d86b1f7a0ef75d9bd19b6d7cd66da4293fcf33fed9241544dc2564d980161a6bd959f3b43569312bff7a23cb0000000000000000000000000000000001897c121cbf5e82424cc50078ca7143a0c670f1217a9180cd2a4700e06aa895cf84c0af94b7c04bfce047a7d1f8443100000000000000000000000000000000040c1a0c4257f90bd83fece3c9372842a148132d2dffa956729e741ce996d229aacb04387d51a72630329230020b2235f4087feda4bd8205d96cd0bf6eee44c27a6669d7ae8e16c731849cfbb2324e1e00000000000000000000000000000000058c001ee1343c6cde55bbdc4c538f5d14b0e8c199fb822f080ad96ee764bd1908f92260ce60cd521919f223301ba1220000000000000000000000000000000000f8943c35e7fb8b58963719f1b9820153e0831cf81dd208176af7527781ceabcf6ed2e2276cbf374e0525952bace0c80000000000000000000000000000000003b43ea8c32a13c014b05326f7b4ad5b5fc1bb2367866a69373ba91402f4b45409c6d034898e8b0ec3b93c2878d59b72000000000000000000000000000000000101c371ab4d57ed2cf17dcb731117b1986bffc586529fc1edc630de1c6f4fdff1e10b0895907bb81d2ccd3eaa96c04a67b81583fcdc9afe5f35974dc9b6310ee8e1c92031a49c08b05555fc0d33517f",
+ "Expected": "0000000000000000000000000000000007152d538d0f750901466c1ea34a16e7b0e1296a2a3740568812587affa5c0c76ca2055804e24f3415a403f06a717c0e00000000000000000000000000000000119c0c282d22a01524d87eb850789c4816e7dafdb2782b57c32409b1016615beeee2067443835466283543773cc8b427000000000000000000000000000000000d68137c3df081a519747c044950c3231ef82295eea5b7040843668195d4549c8ece4a91447e0ec89530bc51277535fb0000000000000000000000000000000000d81a4fa2d32ada3e08a7bd4471d45a6afd2cfad5bbfa3d378b1df2e0749f9b05b465be61cc9d1a0f4abd56dce03dbc",
+ "Name": "matter_g2_multiexp_37",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004b153d6554c9879359052717457179d8318f8127eb73edc1d6ac2efb1ea9643c4357cc813d1df49730b77f995d6d449000000000000000000000000000000001533a450737b4bf8edada15446cf21ebf82aa7bec7943025dccc4784e1070fbce430699cf3a37a36a3ece692ce87639c0000000000000000000000000000000017b8afc300bd70a3221120f6fbc37a8e6158c48b476f00992c6f41808036765071bd0a76f7c641443b97ba523153947e0000000000000000000000000000000012f686b4759a3d5db2325508f148bfd6217e027fe261d3ed7b8fd0526036044dfb563e1c4399ec266e140ca372120e289f3c65c2c25c6c37aa45b1104745cb8ec511a165ffdb7e304f5478aa3add4d7e00000000000000000000000000000000061c8288b7bf2856c075a176d1086fc49f0359ca3e7c1aaf5f151e6462916a4e1b69b6decb18823759b620f7593079c0000000000000000000000000000000000877af18cfa0d029e7c9a5833b346c7fdec06e54d9641d3953d3cae0e8912bac7c990f8864c2adb6e576442c634865b6000000000000000000000000000000000331490f42993de3ce7cdd53afb4b310f25881710a23f601ed95961bad4e9cbf57d3077803908a91b65fc32d1a84130c0000000000000000000000000000000005aec079da804fc572bb8eb867acb93a24ffb6611eba920d2ce799c4c80cd8e73b3cefe989885167ab685365529b4f2a8fd50c46bade91a13d6dc5a06ee62e5e89e0ae7ee885e5516ca6c2dacc36f6f3000000000000000000000000000000000ecc7abf4f6f9692cf3a118cd01abaab4754c90d1a59468d402bd699992800c2994f47b2094878604bf7825f125133e4000000000000000000000000000000000662396427cc596458e880bb8a43dbe046deb85601e3c64556990de36e8637e8ea3b142a8195762910a83609ca311c3a00000000000000000000000000000000198b9c52be68d073910f5b26bdeada9e9b308e4541561a8ffb21fd8e69ec9d93b01ec966fba65be27ee53d4857a43e120000000000000000000000000000000005201975985cac810248e333ca714cbcac0ede46bb915d8c857837c80c805898d0f9ca0940819878a26d269faa02cb86128db1a106328916ca5d63c0b5722642febed26f00a89430d52ec3eae25a019b0000000000000000000000000000000004e61ad4818ea3c98ed3c0d247798a1a6ca6bcb35a1cb60bda9394272ec092c385661ab93a42af439f1b55ee8b9c0cd4000000000000000000000000000000000ee0b71ebf39e4009bdb310fe3b555cdc860abd47a67bf481ab36b5ed0c00bdca8082abfb75691d45e10c2f2d777be19000000000000000000000000000000000e9582e3b5bd580f3ca7ca1f58e39379918f2d04b82b418a91e133117a9703f7df4aad30d48a47e29aeaccf5b8e33559000000000000000000000000000000000113b4c068fd040cd3300a2d1ef658955b014e571e7c77594edd31968037c1fff241da88e7a88669a569462564e28cd7d45665afb6a864893e389511a0f7b2df74c9e45a86fb69f6bd79854e3a88c206000000000000000000000000000000000d8b0bf633072f19db61ea263a1dbeddb326738396caf1196e31e2cbe99a68e8c70f8db13cfdfa4fc4494e54c1ef28210000000000000000000000000000000009ceaf2a0c63604afb8a903195933fd1ada0e5314255be3d74a95679c7a7845785e22d2c0c206f3afd62110ac9810c2e0000000000000000000000000000000003a135b405f46ae3f5cbdd63f4964cdc5014c9f3405c2062ba17423dcd22b8f2011638d520ce0ec7bb0cb5b03e8ec01700000000000000000000000000000000066eafafe1cea67aa6de267c767f49d4a3fd44c28d45a920fe9b3cebdeded883d8960f5e9fa4cc179246918942b1428d28f5fd09c2c1819adf8e6d0e0f4e4681babff46757edeff3839e9691888c13220000000000000000000000000000000017e37a2f1c892fdc58ac3f72cc5a5e2b7c0c87333afb06de89f7a84b1267695bcd452925fb2f15f8b7b20aaa85a6b5650000000000000000000000000000000015b2919343962337a41b54076d6735a093190e1965faa33eee800f5eaa43c35f349aaf93f19977b6fcd19360b27edd6d00000000000000000000000000000000161afb1494482f953007038557c847e2cbf84c57c5f5b806e3b0178e71e3238305f733943bea7ad6f2bc290778638e6a000000000000000000000000000000000c27a2170fa584863697292e626e2539aa15f3c8eee65cbf1f1b7ced6297248d059fdaeb9c955437a51cb016d1ee97c3e6e61390ef88f20591570ec1fe71c3ed769ee8e234c7cc7303a4cdc065717736000000000000000000000000000000000313a30edffaf864d0f1c6bdafd7d1e563cef434d45e71489e9f9e4cc6700e44991a99220f53f0cf5e7de5f6e4098bf20000000000000000000000000000000010429081ebd2ed6fa07de6ab0b7bd559a26a43df99fca0a2252411b4554dc69821ccf3df1b05114da84a616ccee0a9c800000000000000000000000000000000131a31442f80da4621f7691664e9f8b467988fa039bd086a2d64f9810878b557614c27745b2e821016f648ec36ee797d000000000000000000000000000000001160cef9f5e4d022baeacdf10b3bf9d7ed5e50627a99e29df1be3667cb872b2af333f803bf426314369b490c2eca642aa83c5af2f9d10c06552ea7d1749cbfa7574b238433c1c0e4788efd0cafeffa57000000000000000000000000000000000b20ec53bc643bdfda1e3947b3773d748cce1992e2ae27c6b7460d90d48e08eb9240879a5a7d3dc3189f486706438dbe000000000000000000000000000000001024bae4a7f71d3d2fb8246e82d95664c4ee8bca4a380c293ea084f749911f984aa4c6f266ecfff69c4f57e20c0660ca000000000000000000000000000000000b58472d81a9f16d2fe7af87170ca0c8c51dada62a4b2a713cae053a0066fd268283a785ccf269e05d8873cd686d2f4a0000000000000000000000000000000016b68177bce92fedfbd90cdb752bc332f46fde6673911c016fb9cff4912d79d3267bf629c33097cf8979f2b913c0936d4bcc88d85a5a8a29dfad37ba97ab3a5defde4ec356146db8d10f33bfb36ddd37000000000000000000000000000000001030d5791bd2a27469d242c62403883ca167303d907839e608acd827b4118b752840a4eca0acbe5df0b447d6651e517800000000000000000000000000000000106d65f922581237f779ba3e66608729dfddb2c487bc927f34e5e39707f2c8a82e8c96af68e3257c7a9876a05a1b01d800000000000000000000000000000000115bec40b8fa914305b1d5a85b65f0811517d36839494ba69c929fc2422f7e8b85d78df4e1687ab0087287eff29c65430000000000000000000000000000000018d78a75ec057cfcf179fa2ffa7dba79cabf6525dabd69ab95b23dc8f293aa077e46e562caf447dd0913ac9dd60ec76b29d5d818e62c9791c320e01a3164e142d9804e9caa7f96b4c3b76baff38ee2e600000000000000000000000000000000023f7736d6de94b08d9e9efb6f32f8c17cafb1e1b9b1f3db6e58df72a451c3225d11f4304eb0d702b07a7966f95a11fb0000000000000000000000000000000007b3204f258c873a6fcb48d0b36c98ed5f99b424cf4f92a028174e0e93db2af549648ea95fa8c7bbb42b2a10eeceaf8500000000000000000000000000000000165d6e769b7df91374dfb44e18d43e03ae12ee10d8a618a20f67332cf96492ff514eb7de06ea53096e823770c686c32700000000000000000000000000000000012e69ca1e106411165c06ca15988362de583c4a05425e2f4aba4c14cef6d8d04c52c87b4fb26b1557801f55b02ee8ba971c8aad41e401ab6c49dccba28ef26acf4961978e94e633b72c581ac03621e4000000000000000000000000000000000e8e6bf1c8837c31446959242285e9b85978a5349e1f0b3447e380a7bcd6bce758bc6192cb880f9c09d6ad4a0ee36eea00000000000000000000000000000000199b361ad0b435d7a66b46a43d06e5898376a6c260b68c965f7b186fc75d2f321bf883646e7551eaba03181907d3aad1000000000000000000000000000000000a76e3f399f31cddc4dd4bc22187a68fba31fe2371291ab515d22730d320ae4240911c755750f687c7d26aed09da4210000000000000000000000000000000000cbc8dbc004b9253ba91b2238c92bbf7883360c7ce39f6e15592a8668654950a3fc5a94cfa97f5ddc60add40c32a3630659ff910eea5280dc5c24c542516053637a5dbea576a94a22acefc902e56568e0000000000000000000000000000000005448b623604262a9cf1a9a292c36738960e132bcf0ec8e61a510008c2ae0b51b31da25f2bcf0d7c0d4ce15b1d7179fc000000000000000000000000000000000b61df56ef891bac07a873571f68fe43f79438a31038cf8ff97393ba44cc47408e5a6d64e9ebddf0195bf914f141e668000000000000000000000000000000000d196ced22ddf11132bbebf6c85bb3006a194cebca975d74992ecfcbac546f0f25a39ed5d6100768c1f1a791f3604d12000000000000000000000000000000000f727cb947849d2d7b046218f084283e5513e8582229085f9f98fca522879543429cb8ab435aa3dbf01b68ed258d82c112ff32d44eb442a711250875d86a401d0dccc95e5ee39bec71738fd812d487c6000000000000000000000000000000001044bcb16b3384a1f350cbd62bae568c96932a364c16b34d91ab9b1035ddee93a02920ab4dbde2c6f254031909dc3a450000000000000000000000000000000004a29aae48210289e5f588aede0756ddf60724b8ac54de5d9159ea834d5da98b7a9d09a6f37bcaeaabc559dbdde58b6800000000000000000000000000000000112ca953b5ba652c715fd20e3b85c5bdfeaa7d577aa49aa4656d142c9c2afa3d8aee151338f59a199f3c0c3f6a430d6a0000000000000000000000000000000001ebc7a17da7809f9e744cf7f13fc437de34d3472f022493f58bb979e2282368f989ca0982098a7c377498f1d8d32583666b820fae2459b98f9bff20275a3c96ddcaf98a78f3f5fa4a2c0a26cea79352000000000000000000000000000000000e7c3d6bef4b1723479ab6724cf7858c221993357b194e5055db96b8168f8d78f72aaa4a2046be17ae9a7eb00695ec510000000000000000000000000000000015e85e85cec08133b86738e1f7a738de455930ffd5073997a1f1692c28044ac00b634b90eb24938cab56e286ca0dfaa400000000000000000000000000000000164646a4767ed69f9280f96be9a7f988d17c187162554239797436a0bf4c4ffa7e4f8387c3d2406a7528c021f56081df00000000000000000000000000000000197b1080bf3ac3ef7bd6123a55f20f1002f366d4efea9e14ed92fd2ef147e2b5d9251a302a85172235438bb2d35943a740a9181633a146d7f307ca7606cd45b8e721c46b955a6989d421baafd8e40139000000000000000000000000000000000db7cfdfd58a6ce9dbbcd5d65cbf22b5e1a81acc70f1c85651ba962d61fbd7ad83e5524fb9aa019c6bd75dade96f7d4e0000000000000000000000000000000011e269a390fd15ab1d52d38de78ec97eb6202604fab02c4598ecebc7635ac91ee564e751275a485fb43b933678f11fd8000000000000000000000000000000000b8597a00d2401664405dd1fc7d69786353c86cd4699af981fe869f266f9087b00df22a46ac34883173bead870798f650000000000000000000000000000000009117a49b3f2a8a850a0179b558319bdd19a5f1f4a45af0ccad0890e63b222d028536e9bb612093cb3f1068d262af90d662ac80797c633d8b9c8907acc2960ebdcb5bdad82d9fceb4411d5173b7411fd0000000000000000000000000000000002e1311abb9df5e4d76959276b6f725f13728844f8c7dfe5e25469cb95c6937a822282b3baa38817e24a6219601132bb0000000000000000000000000000000012820e6ddc50e19a8f98c15013ecc38901a4ef8ec2b79b85c7f7913da24404afa1c79045f1318cdf271028126f9420a5000000000000000000000000000000001794e653c5673e51a3ace631c1a1265dba07fb74235506b2149d42b90eb16afc26ec0ddc54d03f7ba2dd6a2503971fee00000000000000000000000000000000112479bdabb9dd057b325563c666910c01ef66adf47aa32f5a41bc9cb8234750985c266fcc329ea3704e2b8d9b15bfeb59401af15d9b83e2ad68cc8e2ad1508391516ba0b26fcc5ec6eda8b318a374b6",
+ "Expected": "00000000000000000000000000000000168c90045dcccef35cfe8eb642924ec2629db886366fd9ebc082019690d103627865f0dc39ffdd2167111f68d8d03c89000000000000000000000000000000000b6f0928a32672983664ad15252b3f145afaa04f11d5f43a6169a2fbdc0b0a04902a183b25e38987c45579ac6d11011f00000000000000000000000000000000195c4d796989630f85df4594eb8353d44bcee76d82b73ff7a57069466337b49b875b3c1418d22d79716ffded7e704a6c00000000000000000000000000000000032db644ff8ca6a3b1ac7bc51ff783ce0cdb7bee8b2c21dcfd3adb56a3e210390756211f22feb3dd4f706e13e5cc163a",
+ "Name": "matter_g2_multiexp_38",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c675cb5e90e45300619be91c752a5831ec47b4143c28330422cb57139882e776c1c5f000d6032cd87c16ab3b1c08ee0000000000000000000000000000000000aeb4e78724d46a55e5f101564bc05e0a1be1d80a781ce8a19607322e82c7ee59db9f53ec34c70bef0766a5b965f54b1000000000000000000000000000000000933e8d7c2420cc553afb1c88b5f64c7a39f78272b34b5611972dd5ced3f639ae2ed2aaba470abe829be6ca6d666ddaf000000000000000000000000000000000ac0a9b46323ccabf4b2024e3a5b4717cd8de9ed7de8a78e33a38037f802651a4b43380a746890d93289d547d94b61bb9c351c585d1920b8cfb89a5bcd72fe041b17f7bd091ba505b287778b0be4e87c000000000000000000000000000000000196597114fbaefb8108c185a85d0fff0f6bffecf056902b22d61cc70b49a747bb35638f5b663830a8d2ee15df9fd5a1000000000000000000000000000000000616ed44a5fe69da994e2ada03a1e09065964223333229f5f30ba7a452830848f599ee21810a95e3659cca495897bb710000000000000000000000000000000012d0631e524ee9d3c776c79137499f8c9fb752ca93e92497d89973033d60971da23f672f140c1a753b4d00d08a00babc00000000000000000000000000000000111159e95d131c8cbe8df75853fe9b3f24013daa083e57c5b716e77f6fd3872dcfe0156382c9d2778fe886621be19973ec42da11e95cebbeed0ebaecd31be24801fdec8b81f4046fea52f553c4e7910b000000000000000000000000000000000a7d253487591fbed97381b3a430404b87aac04073e5931ee0bfd9ea6e0d38a41090c6dc7f6a591336fc58a97a3bea8d000000000000000000000000000000000647c67f1816ae6fec39033c3169eb1ea89e5e20e755cfdea33572d6397e7e87635c7439eda4912361a32de313893206000000000000000000000000000000000e0cbd54634d070aa3c7a503df1171a5cc435d050def17395707bdf7a61cfd539348ee5a4c29c7845cbf0e5df0531f530000000000000000000000000000000007d006601dc1e092a616eb470be35b5d32742dc6a2a4d71cda8865f071dbba9d8a3a8cb10b486253b1633e4590e716dddfdd8996780460757702e34ad98f5f64a8c1e0bc8851d6c97f02749b8f77cd03000000000000000000000000000000000c502a19770a892b2fa1ba59900a36c0ed054a8bfa0c4e32bf471b90d0da9edca6c06b133c8f12e233b104262a81dbe00000000000000000000000000000000011801f159086d07833a691182595a42645513d316c084b2841445c4a63c6bbb402664a9a9a100e8d6436337ecbf398bb000000000000000000000000000000000f2b9bfd8ef6286bc41e9f47ffdd3efe437aad553c9da02b3c22ca04b5578d634c0543a07bea966bedf345562218c2190000000000000000000000000000000010be5ffe0cc9f580c74e027aad09c213189fa4b7aa92160ce813b8d398b2e2803294e1a730cf5c891cf1546c6bc91414f256ff23b38b3b986a62074c5a3e05e86ead9431fcdeb67512f6d502fcefe3c300000000000000000000000000000000132cd5220c125759a18c31313592eda774247f97b5134111b01ef28dad5c3ba4d3f13d1af9076d663f7e217258a6fdaf000000000000000000000000000000000f06a5b03daaf8f92f9a302f06413044ca0dcf2be81d9cf016120312fbd41b273650fbb542d419595fd2815a809c4b960000000000000000000000000000000001b11acf12cf46e40554a1d6a833566cec1b2750f3f72ef77496477831d5933f477d59463ba19c03dfbbbd02fcbb680b000000000000000000000000000000000b2aaf91827ba923c8a1c2fa1d6fb92384c9f48f8f77273056b94245114d1f3cf66fdcab330673ceb2e9dad6c1aed0d4c01b3c8bb0acb17198bde9adce3b0f7ed4cd8615f837aee928524b0984c99d0e00000000000000000000000000000000051858339be99d1271152bb390e9a2ec0c0760b7686804ba072c46db3cfc4472404a9f87d868a28f2aef16c9e989d6e90000000000000000000000000000000019a33f21d0bb8303f540bf26816f145360bd1e9a8229dbbe7981f1cb5b099e814f2691fadbeeed8e4c4b772bbd27e60600000000000000000000000000000000073eeb49aa7e601732dc0888ae6b0f5e8dde3d97b818155221f5ab8c599eda75b25c86f15ceecafdfb9ee4abe3419e10000000000000000000000000000000001507073b97d494de26e70f18bd1723d931cd2a88903ab6da2aac3b80fea78ce75caaa9b99375780d759fc4a1683950bd458f882b63c99ada33d8215111a6df21c8f7424eb2fe9f429256201d099413c10000000000000000000000000000000013b5422deb0e80bec71309d03fdba007eed33c3ce0fc6d4f9a0d063136b3b85a6fce90ee59956a9b91e1caa519f813e8000000000000000000000000000000000829a11eb50f3bb1a47b72cfeec9d1f63e02b9f7b2592174c481ea7b72a121645ecb36b3d1964b082bc6c7efb4483a180000000000000000000000000000000003d3aab53814f55fa97285af2dc6d32cfcf5a08032d2c15ac83ea036603e08a53e0d2b8d93a25dd969937c113e78064a000000000000000000000000000000000c938a68688138149cda64f168ac1466c401196eaaa44a464d9e345c422948767ad1e25d1ce4cc5996ac5d5dab61516b804d7a35e5731b111a6904e0998d90ce86cf612914152fe3d2fca0201a41166a0000000000000000000000000000000001ab96f0b60213855fe221fdbe2fb22da6bd6cad8bab8ecb747c9528d3511976236ffefb34afc462abfde13a99503cb900000000000000000000000000000000182fb121778cb002be3f90e2d6837a406edbb609bfae8fe59837aea6f5f6131a10791f92188958b57059b7b9a9d3a24500000000000000000000000000000000159cac269098d223ee6d145a4489f05875b6a546767c023dbea62b3cfba9f8518c9f4d2594d00ceac325f3d8ef551369000000000000000000000000000000000c0d2e4e7aaedec7e53bfebe8f7fe5115720e58768469b6673cee3473b08fb8cd1ebd0514689ef65d78d008889e3ed296f1629a801db6bb4066588ed79f75223120728c3a57f7129d88f7f877149223300000000000000000000000000000000079c40bd7fd2ce0f48806dd2e88850ba988e5adb0cc5120977da8110b07da264318fa034c0c213590a2616f0ebe40f21000000000000000000000000000000000905f41389be39361fbfe7641394d30870a079f230dacef89149fdcf81a4d1e0e10b9fa1c0c3ecadced9aaa19fa9dcc800000000000000000000000000000000192f50e08e497f902403df40a504a1b4b82f1957572a9ab7ef97f5ab93c6fb876d8b08f318244cba95ad5200fc2a6e34000000000000000000000000000000000be7ef45a14871dbb344a69c4036af4f994a22ef14540377d1144a92978a23c2d678cca47cbc18e8c036714112d11f7cfe80ddbcaeb784e24975b9a42801c89bdfb842cbde5fbc0c3d70c0632cfcdab80000000000000000000000000000000018d7410f0105ff03cc4ddd87a6e0b65ede4abd4609db5ae53720851c90255757e63c6482de4651eb1d3669b1e1a2f8d9000000000000000000000000000000000d4223be106693a672da890b64d2653135119983639f7052eb32051c34113022080ce2355a93a2f64a75d8e0578b2f95000000000000000000000000000000000764780391249d0c987270bd181a44f6260ef82eb00c06585db7ef09e8b069e46c4e0e659a081ab0fda491534b71b0ba000000000000000000000000000000000a8546031e6466ae43643462b7617703a63841d6d4cb0c09ce63b2fbe2c2ba7cc35367191d0313717b1daa665bcb54551aeff13de7bcc4bc2ac1b37e28ce466805757dda29c9c743eaea9da33f47f4fd000000000000000000000000000000001922491dee4e0f29a1dc090c9b48fe8e6d70c3441e532021985932005b22cedaeea7d9ce1796808d756b740ec63f8ca80000000000000000000000000000000005b34dae0e630be6a59ccae17b44eab4e7f10be2ee700bea15f9771a724f0979798617e129540901a8aa023630a446f800000000000000000000000000000000095bdf612289258b31cc79188566ceeef6fd66858b4dc060864d378cbbb69f951e9c6bfb3d1384014507ff29f9446f410000000000000000000000000000000019f06f11a833c06c1c9227255e3a1d74172e73b06675c547844065dbb909ad66bbc150ba396fa1ba22b7183c0fe80e96c4984739882bd2f882e12660815b96d2af7812d7ae87f5be034b88e9e04fa2890000000000000000000000000000000003de8082f828ec51e23c864a16147546ff60b5fa71897ff4c120556af5c6616bde96b6e53fa673cd1f8af503070bfacd00000000000000000000000000000000093013f75b6a19b5433b3b5ff044384ddfa258420c80fe81e0424e3102cbf9e550a946e56ba9746423ef745e33da51e7000000000000000000000000000000001227cfc3e9a8d6a71738c514c05766ed4f1f4605198f5a3ad8309c0a49499e4ecd34ba1ba7677d6d90203e54d7611807000000000000000000000000000000000a635221d514e58170ef299eb7f5b679050ee24c589cc7e348b2905a3cd1b7bcf2010cfe168f5aa60f4bfe15e59b4436e7f33141d383a1a927b7645656ff7a5795901a997e27003c5672ae4fbab4aecf0000000000000000000000000000000012ff0494d308d3e7321ad4c4000e9dcd19552d5e4bce8504760f066e2fb2509279b01f1568e3c3f6216bd5328cbf72db000000000000000000000000000000000038c6e8f0fab30b5c8e4323c1fd29527845c29e1a26c70b8e5284f7ca55fb55ad4ad5389b5280927b98907132f26b76000000000000000000000000000000000aef946b9b9e9fcabb36507c1cf441df2f5ccd71ef9281dafa5e25bf07d69556e4143ab402dfb38aa756bb6ee009a6890000000000000000000000000000000015f69bc7b0a6f2cb64fd0897b421e339fcc8637efced8bf33f5aed809a38b49a2e6376d18b1bff0ef70df1b7187ad048fba4674313a9727aa4b733832a0e06666d3e38184836edf786317de9dd055cbf0000000000000000000000000000000009e8450887137cf45b04184b3c6fedac6676cad416a7646e9980dc99a6d6b62164dbdfae7cc20edaacb84432627e6e550000000000000000000000000000000002acbd87ddca9dc775da01ae026f1c60f1cb5974ce40caef80cb0d2eb7839777c1f61eae0472c7568ec9d0ebb2ec7dd20000000000000000000000000000000017c295c458a9dd995d848e3ba585f8dcdec4185a953e4b8e3ca760eb3e815e39a8ff60416e1e6f974cf7e7b086ee4baf0000000000000000000000000000000003cd8725e1cadfbd80585bf5a19e086abd631d6787403edb4bbc785d1a81f6108f451ff642f4df17dfcf94dd6107352bdc0c4d0e34d8a16b3bfb51ffc9b3c353817e8e357c608b5075c173204963606e000000000000000000000000000000000b3cc99db523b3647937b694fc23281a74010079351b2c7d1ae4cc9167917f06c06e627c4ec44af6b09f2886ddf309b800000000000000000000000000000000001e2681dd123994627adc92e6ddd3ffb006521d8bb03040fe1989e4f709e4797d143cd0bb749de33c8109933c709e970000000000000000000000000000000017df13f532bc9894be932e72c609c0386d32390dee95dda45821bedbc1067043d46007b39b6ade871bd36d39a17dd04d00000000000000000000000000000000162db4d1e956fa5b5f9ef244dbc0c6d27718eca7dcc512d1d7b97bbfd2bd00cce7941d1b9a170da6341891773a729e9ae4e31f5b6629463311b9d3c8333c33c5b2e79761ffff9863acd9d636e1a9586a000000000000000000000000000000000f0e4b606ba0a175bf57d4478aa286640ce4b5507f9f9e354fd96c45443333f6889a93012d663d78956bbfa7c645bb9d000000000000000000000000000000000d85dc4d733f0498fcb10e1e814eb61245203d6c1a46181e5a388fda2680640a1271a68d645f8fb179c0dc3107fb788500000000000000000000000000000000185b02140f6314cb62bd7977042ffaaec41ba8788d356047488004d609ae680c2f0cdc94e59a3cf90b6651298b6a81d000000000000000000000000000000000038ce717d08d367a9f882f2241ae4cc0e8a31418498bf68d05805db2e162d053a10dcff85403dc473598089a78dec27e03f256e58f60307ac1888a1b0b14b56c7435213e271eecc79b4a6f88d102be4c",
+ "Expected": "0000000000000000000000000000000004cb919a72e67c31b3409c28dca1d57833a5066c240d2889f5bbdd5540ab2a49484c2462b25da197ec8d93dc8f26ea83000000000000000000000000000000000e1ac1dfcfe22ed7ac52c701a7221b542ce72bf59d62cc49f95f8ba64c05060671098d40c83947dd1952494833a19b55000000000000000000000000000000001331f6ed8ea5ec9b9e1a14997c2c9bc9af2ca305b313e2bc5c5bd35308b7b451a362f8ad61d636dbf77d1b2388702d8f00000000000000000000000000000000186b85e656e45cb5ac9a2a2009353e45749b53dcdcdad4f378431a0e4a317652301f834617e14dfac9836c3c11512aca",
+ "Name": "matter_g2_multiexp_39",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e6292b4d3031fcdeabe62921f0c562606b1ec6139b9c43938971d7851da4945cf69f39652425396ed1b2e70e65b9f55000000000000000000000000000000000e94bc63f3b8944ea6bd7bab811c013fd61303aa7713619faab85a271308bb220e2a94b26f5c7e4136a3d2761dffea610000000000000000000000000000000012313ef65ba41f8e0a57e9b810c13d23241e8430c6ab967a1a9bf5bd6308e89c135e00e789a5610694d146840fbd877300000000000000000000000000000000165ce83af7edc9e701eb57b332597305fedf4b939f3a13a95a0bb3d119c2a9204a4991388f7fb344ec8f15d32cab0eb5eb850f01feb55bb99e4accee0aea8fe6ed0bd29b2ca942ffe09456733aff10ea0000000000000000000000000000000005a88477765bbc8290b7eb137e6de78e62bbd929ca511cf0aa701f926440f21d33bcc6ac8f2ca5de57ee8116c685ba38000000000000000000000000000000000738074a9365c707190f882780b27dbe96179224103392b86c628b601e33b092a03e24a89bb6d1d1024862a9df6fce8d00000000000000000000000000000000188c713945046771bf852155ba412b4222173b6dec8320ffd1c59e9b36943c2c18b0dd3bd551b7b1367dde3e8031201a0000000000000000000000000000000017222294bacd664ec37e9b214407e5325eebe9753b430589de2eea13360783be52a479e2b0e9c5dc4907dd5f06a7fa822b373fd7e5806d227ca1f49ab0a7f8be2b5950906c8974de9f2cb4e13ed20a9a000000000000000000000000000000000c97299d7e18f41e538b91b75e962c3ce4e068202271b40469c58cfc477d7820e90a0e91d647e8ef5fc0cb822daefd29000000000000000000000000000000000bd1e11a3646c499a240bad708f97a49acaeb653aa5bafdcaba41c1c9d32d32c516c94a3db8816e0a43d1b1eceac7243000000000000000000000000000000001223ecf82c4622653ce84460c39afe8a967cbd87a2d75cbee1609161837c15b522480c4731c9e6de9c5c392ef1db18e10000000000000000000000000000000016c5e98d3d17c723548427868e3e6d7ef4bca339e41acef19e0710459bd4732de4a556b22cbb49b823c4ee656fa354f1babde7f3fdf9fba868b5eac61337be0d73517ac3f06c39b4eaceeb27ab6311db000000000000000000000000000000001125735092842142cb5387f1ef8fb69a3535e1f0ccce59661183d3104ec1ef79dd87a7fb36159bc67bd73ad403b46c1500000000000000000000000000000000162caf579539574199d56f4e756f1532c66278a55b4f67f4f4090368260f46023543a8a18d49e8c5783cb65f93d750480000000000000000000000000000000003accbc87996a220a625e36d5cdf05d8c16fb353068ad819f94ba8223cdf6436f8d822719153bdba620a07c5dd955fe5000000000000000000000000000000000b53c8a4b62466c998327e0c5ad65818ea383650bf0977d98a8a94fa9653fba276f7781af9f5a4e99052ee3ae65c283d5ba1635cf82b25b2d7e466717f5716c33f5f3e826bdedf19dbc1d95ff0c8052e000000000000000000000000000000001264608a59c0ee9a26568cdcea8801cc8cf6616773bcb0971234b2d987563270c7b2291fa035c8f2069ac99e16c68fc0000000000000000000000000000000000e839d8d982d6663ca4552527f4fcab6ad5e0a444e7b5921055c774871601d342a151133ae15bc76c023b7ea643182ba0000000000000000000000000000000012ffd0696b7e29b305412fb840c596b66b77ac2eed936fdbe0562541e4de6b3166a9991dbdfa0f79b78b4b86f11291de000000000000000000000000000000001777ece357f82d7303aa816237a0dbd3a1398574f4061dd2fbf6b32af38a65abf5ec9bc53bb8ede932db9cfa0842d53a1a0a832e5bbdf897553c1aed35fab43aa3f4510c1782115e14e5d56229de2dff0000000000000000000000000000000002b41743325db9550c3a84af80bc20c54b8b0b685d7f84d05d14dcabed2f450b91675aa8c5c650eb81151bcfbf1603b4000000000000000000000000000000000f3d3e69d475fe1d4259f18f193cd84a90b91589a6502588106f0a577d1c1dc4b2feeec20a4fc30b3e403d6ca9e03894000000000000000000000000000000000c10e2bd1335363fe958eb50981b99bfbadfd1c414830857b5257bc8fa6e26b50989d9adb5b3a2fa610b3151f8754309000000000000000000000000000000000008c825371319f4ebd684f76b567c4e9a389dce96068c101568dc8cafcc10896e3c20202b591a344d9a1c1be02310be9b75e0582e9ad7aa4a02ed5ffa22e55570c9f20e6a24e2186e8a2a2f838fa45300000000000000000000000000000000101d3f92fe64af93468229608007f50e3406719572acf265fb8b2a7051525a9cb67cf2e46fc8e098cf081e73f3b20c770000000000000000000000000000000017b1422f8208c2521e3896820b22a65bb2a9b47d7fdcd2ce57196123c1ce43c1db6d00f236d7582795d00ef33ad6d585000000000000000000000000000000000e261500a9c64f5ae107d6ccb57fa9151f5321ef4e80f0e271515f1eaaa5e3714c59bf97b39acca41b15d90c0505ba9a000000000000000000000000000000000c08c955b6df18444ce3726711d29c2088721fa0aa6e317c52a05f73ec7171ef8bd61047174c74afa1dea804c68a28e33b7252f8f3cc6341d490c5c4464bb36e012f1b05057f405aa907ebb2c983f646000000000000000000000000000000000985cdfb3934e0484805a1965984028d6c459654a3eea6ef66e867dfc737e1bbcd92e31020d5a4ddb7f8091cae2371f8000000000000000000000000000000001998c5682209153a261bf981e16bf1f7a6f8e5e566c1b0f975253ea62439e5b36c5e5060751f21941edf0d348bafd18a000000000000000000000000000000000c8822c1d6412bc45fea05faef33c65d5a6dd13aacf1279b9cfda2a2ee34df3146d45e3434ce8e5f242e9cf7d3ac27180000000000000000000000000000000019191b51d6664a3047aeb5590df2939b2cbb115ded70fafc2de4c2e8c2a955a957375314081a8838bf89d5a140b7b915f10427f6e461e7b63b781e116a4d5136ddc79ff86b71fa754f00c797c035412b00000000000000000000000000000000156fcfffbf01ff3c8a97e7bd99e59327d38c6f7f1083d068ae158d1901808b3c9ac96f95c2bcbdf5f74b36dd8ce58d7d0000000000000000000000000000000014c64256d1cce124c01fa727482caf8ccf007e4ae00e5277d984f31a11ce584e7633565c61d47bc8accdf7c28bb266b200000000000000000000000000000000052dc9f7fce4859c852d3d9e1e77bb7887ffd35d4d550726632acab3d4303ecf8b3ec7f4114dbd590ac20d748570899f0000000000000000000000000000000017abd1e5dad7ee06116a8131c05c9b48defaa92efc636ee34a2970d701c02b6be0345a58cd8749e582ebd105c02f10a06440c89f8b10ce15806938b7ad65ece194d2fa3cc8d7d5591bc1d52d010896af0000000000000000000000000000000018ce0fb077dfefd57f7943d432e12dc9bf92dfaa30f8341397ff8906b1abdf0c02b599edf85ba1e5bb6287aadc72d7a50000000000000000000000000000000019e5e9e3b0632ec10a26b7c1ec40248a9a8b230806c38aa24e47489a8aee5abb5450f6e5679e3f13c6ec7a79560689050000000000000000000000000000000006e257a74f45142817ea8044f403e98c99db8355d626c59e1d11c6859eb0dd1dc8af389f07562259c1f85411be6cbfe2000000000000000000000000000000000f463e345b004b1364894c6e8ab5d35bfbdf6b7544a576ed6b5c5398ca2074f67e2d80af1ff5b721fc126d3afadff1ef43f1bb26469b778edd10127e634fed4d749e25b41d8eba86eff2c068c33e714f00000000000000000000000000000000174231581338fc8c461c981d4949d18f5b753d27184ffb41568f11e178a271bfc69f8c73f2daed0fdbe5bdc7fdf8ef56000000000000000000000000000000001532474399d6a73501801e5f3fbfc6f13bdaff7a3ea7634568fe82745752ee15af23b16809be18788d295e044e29c05a000000000000000000000000000000000912eaef94ab1f3b3257b26c5e8bbe3f99eaceb8c7ae8da577ef98e24f3308abe6e6005ff674a2af01b4242f8ff87108000000000000000000000000000000001925cd635d0ce770f4925a3117721e96c316dd96708b096901ee04ce02e7b357428e4364cd488eeedf76352a26cc1d10a40251ec7a7e9f7cc29948b122010d9745752df3f4a9c67427a8b58122ad4e7e0000000000000000000000000000000005c4a7f26ef0416f34750badcbbb3bce075606435ee7f69b3589e21e37491f0b4a7a98c825ec222848f5e29618828258000000000000000000000000000000000381c5f6511c9f06ea1a76ca84adab4a26a3cde13e0825b3d81899d6ad3191628894d0f57787f854aeb9e4c57fd15d32000000000000000000000000000000000bd706a5b5ef0d4ee1b679a0af90c217ddf9242b7c39523c39657962952dc14e5e07d02154e05693bad08bfb24a2b19a0000000000000000000000000000000009f28a84aa5bd39eeb09f13fc8770fa7e2e053b6f5d7e6021da77f48b9c3807ad917ac671de88b28dd343c2847c5e8eee03e5eb477506c397bc1a5204b30872085a36b65b7a8df3e0e187f3022736329000000000000000000000000000000000a8ff1b15ddcc3684b4d4ecfb53473497feb8a04660350ab84e5719fdb0618d61acbb555174b0900b32341154eb7bec9000000000000000000000000000000001464d21df798c0242ac6aaaf3c579eb66eb8cd53eb1e5ab2727298ca61ea8ca4c7cf815bf5c9f94c2b76bf659a4e2da50000000000000000000000000000000003a25752a4360c84e9353b7f1ce74d5106cbd637ec5ecb03dd0752660fe5c7622fe2d0475a4db98f785307c6961f14b000000000000000000000000000000000163601a86f02900d214ff8fbd041934189503438c557138b6ebaca8ce3c109af50ac28074223fc81d6476a3a99559ac565cb04110bbfcdf00616c2826e253f61cf955756e94dffcbb6001f59ae4a93c100000000000000000000000000000000189597e6d618a20ecf9a87cc70b3e0eee69ffa4dba75056ebae93cfc3c2ebb368532b17d9f6c06f09e44d9f101397b2d00000000000000000000000000000000086ba610e490588e9385c8b6944c2bad1eb03058e927fb2f9740dbefb779bdf669a51af88b45985e8345b8cb168c13ec000000000000000000000000000000000db8b9cdd4a9bcfc9f7de144da0b33981e4dd53744cd260c4bf045d643a4ef5f25aa19edab7be0c7f8f5ab74a4b7f1820000000000000000000000000000000010198384a646807b16e2ed9186aed99ca3197b05964dd0348086f446d3ebb847907624f4e02f71a1e866d17a125e07e93ce1bb7cf7d7a55f0624bf5c4c35327b178923d88be748a9b079720c27b500e6000000000000000000000000000000000a293f07dc3f0da0da4bee671951175a4480a719d44cad3d627878ad2f17596f0dfbd6f43acc7a1f9857c5d1f453e5d5000000000000000000000000000000000be6382cc7a00d590f2aada3b4b75f01f8538caad2ade90227ec71e5661ae353e68789807a13f28b23b17dc0dafc19b70000000000000000000000000000000015a9ad5a6f1a511ffe1891ce260ce442996fe4d8515ca593e3e869cab9b18af57956b1daa43aec98a0281143b0c319fb000000000000000000000000000000001807a4ddb73a9aee58b54bab2b878bea8429cdc91384c8fa533a8c9d15c966350e892bdfce16d37a4048a763cbf25d71e2b4c64b363efef0c5525b0337bf407879755f060af451075f4345dea7e681a30000000000000000000000000000000015aa6b865796f88ffe770bf25612ad27942213131c566a446dc149fcc70a018230f1cc8b20461ba2c55300fd27930bb0000000000000000000000000000000000c39c4f229b23c0f65ed720d655121eab50f695864959a2aa49771b848730494d14597eb85ba35743f64eda897f95917000000000000000000000000000000000ad44cafa754f06e45dfab801998c40e5a9f56e4add5c8add1d7ed9e05d12459f2efe3f3367cbcd161f524c714f7782b000000000000000000000000000000001437b1f1a1399ce2a860f7c6517b14a2db264b2602c1c57b8eb04e165205842b483497e98e6b6f8a62e25ab8b0e722f04c85e47ebe2c26e0aa25661d3353b5d88c632182aaecb35303d8d47f01308a0d",
+ "Expected": "00000000000000000000000000000000077b81fa5997de07738e1b34d8e17ef4a9bde516577a4290253cc759ceaae745e10a457204b9ed0069942e0b487d106e0000000000000000000000000000000015e79be67a752a46dd0605e9d07d738c5732b2b605457ce056deaa1f7093b0bdc91b4c81c4c5462a51bc713a7fbb86c3000000000000000000000000000000000cfd2e6043263bda2b97798e1a7dcb24c63aa7197f2749f92524329e97f93dcb56429d82c1d63c067d7ceb38e6c65b5a00000000000000000000000000000000026f352d2f93e6407c59d58742dbd91ced464a3746dc1ad9059e6bb9c146dc1e74235bd54b1d90bb3399865cd3102f3a",
+ "Name": "matter_g2_multiexp_40",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001387fb972f997ed0cb97a5ccdaa759dcc3c2c7f4f15e5cc4fe74685e42cba75e778772d795847b45f274d32cd4960de600000000000000000000000000000000150b1ad31a3d434c1cbef877fde2e105d4a047dc34e3889d21544c2143e7b41b8e0024443a774bd1e09438293860a43f00000000000000000000000000000000065033cee91f5c4d429a074be3d2a8b001892455a11dc708ea73c0082bedb1cb8e8b567a6ea68a1296ad2b80e4b5b08f0000000000000000000000000000000001991ff6fb57e8cbf9d228f1a99697f785261ebce9d3c1f592389fc860b8d7a069896dd48debb8cbe0c43175cd2ecfff5bc589e7d89994400c511789cbcaea19b077e0b02d625e549bc6f2673ce40128000000000000000000000000000000000a0fa2d39d868737b9a0526296335256ab4894cc58ffd80bc6334e80d1314bdf017c8226b41ea135f6adefd07650ca1c0000000000000000000000000000000004334f7985211061dedc794ee8931ded12acd39d7e6a6ef44a749118d19ce8204d07935fe62fb2a8ea4f68f99d7c5f5d0000000000000000000000000000000018850a3fc8c851a06781511faaded1ce0752e7ef66da82c2464eccdf78c32fae306da3cfedaf76dad371cfbe012f2bee000000000000000000000000000000001296ca0b0e368429b122537b096fac77d6367988956a7f6cf70c7193b7033ce42fa0cccb8b84b9c78b16a68fd5f4c14c2c3d2a0cba111642a6354c117d494be805cad5b5c486bc47906a2d37a9cd9f850000000000000000000000000000000019deb7de7fa5254fdf5ef34fa616651ec70548187fb0bfae9f512e0bfe1f662783f06a9a99e434ced84229deddab9d240000000000000000000000000000000009c199ef916e6f6fe0677ab07beeff221a5687fa8da3ed3ad99a950b7f27159f857d1b561006bfffab551d240b764fb300000000000000000000000000000000148a211fb58b38072cf7c417c70d3ef92e9cbe22b31b2b626198add01dbe1ccfec32d333abf42140b9316312ac48aaa2000000000000000000000000000000000b551b57045365d842133e46814d5d0084248904960f8d2fb28e9623660bcee658582928703f86261cd70e95cd20cf3a530ff74626657262fb49460b2c6981155871f2eb5562581a74f968233c3cbe3d00000000000000000000000000000000185959a297a8f434cb9529a1f7bf9009fc1af3d09efb0a9dce1b9e7d30699da64e4b1d32cdb05b068621db092c1eb59c00000000000000000000000000000000106ef21e9031d108364e93ae4b5d21b0d6d78c2e86e0f8a7af27ed3d38dba0192954e8c716665333e5dcf21387d3f2b1000000000000000000000000000000000185d21efd7d613c409b6ddaa66eed70c235440974b2a9154f3711e3969061461f8824b4547c65e9db09ce875512ca2b0000000000000000000000000000000001aa46b22451afb12962bec5c6309feeb4acefdf3c98c1ea14275409b7111aacf7c92a8e024d01d4dcbfb1c91fc445a1d182ac912b005e90ab81d4f2a906da8309a69576a8afaa160fad2540ec049913000000000000000000000000000000000557370d81bc3da4c50980106b8e65ca2edc757a475194cef201c9edc0f50363cbebcf2750acab0b67e1020daf5660e7000000000000000000000000000000000462f1c1379be9bfed97a1a83a00428de63eadb6360393ba162af3762a99d7eae8549d0cee218e469e4997ada7b35cc00000000000000000000000000000000008aa5ead309fc703f6de980dd43c294530cc2b38b94d5281e9cd9b0d09f82f747a7107b700f1437f3abe36c01bcfed1b0000000000000000000000000000000014110a19d574f26e11e2163a981c3388c04854c5693e9033a474f1020d5f980666d84c60370950734c46663e194bf0ec42a002a460b51429e25f85ec4abaa580ac1a14315b1627bd52349b7b81a641d60000000000000000000000000000000015beff8cb3c79098bc73dc1ea4b240a4e0d094b3dbbd51592df6adc9c9847beb436ec83df6c55666e296fa843298446a000000000000000000000000000000000943aca2a6e57e9897ec764ee2911d9ff0a59d9e903c70a8494340cef2143895e79d3e6c03af2d6461ca199dfbd0ca0d000000000000000000000000000000000b812ba87c4989af07af44f3dfa87de119fea28ad598cb8e52247cf41bb8bd384c0d8913fc82e4cc2878065e797cc581000000000000000000000000000000000410ed148d1e354653f9d9d17c50026957fb03fec64964f2bee5eeea966b430e77f7b3538d9f4700a673fa07d0daac6b7a650dd3765032ac139d1b54ec7a5457c9e3caefa6af45d198433e5949d149ad000000000000000000000000000000000de0a9bbd63c59767938b555c7f9284d0885ca23019818c213a7d4f1594b028965da871cc5818240d155c05c69e4e25400000000000000000000000000000000079dee5649cc67700e9338799a9810d352a5c68098d0676e42e00bac31f37513944dcf47408288cb7f1cba121506a10500000000000000000000000000000000101a650e84352aaf3817b400da0aff40907aae3d2fcf16739f8ee8d5bfc62c2a0dd518201701932728a41134ea3f6278000000000000000000000000000000000f1f9dcc0b55d0ed327f667cebc052c4b6116fde5e3076dd6e447c3214d4c8847885be9547f95f341c42e7c7fa7e2c71bbedc44d54349cff199befba9531dd4120a51e2b830a3e356e68cff31bbe365b00000000000000000000000000000000148f706b4c93e739324e5db40d42025535cd33a32bb3f211add618c0e2022068384a5612da67150746896a2813a664e80000000000000000000000000000000007204ebcef495ca8232078fbf1539a4b46e89506a09dc008da457dee2792acafb6baac4f6cef2de15cbeb48bfd12bfd6000000000000000000000000000000000bf8900e48a4a56b653b1e02c3b9a7d81c2045dbf6297f1ac2acd69d1bf9e06480ea917e3a616243c3a30235abbc426f0000000000000000000000000000000005ebe0ddf4cd1aee76d0b3d03eab754664c8b36fb20ab1060900909e0e0a4abdb45bf74a0b1d40fece9bf73360f580bcbef3956ac71bfe97029b8e3f85923c2fdf9cf1ea6582b68d5a4eabc6b044c80d0000000000000000000000000000000007824d1c48bb2cc0f406e356f6e52b66392f6203f49dca7ce03ae6302ce3e8055d071cd812f97481acc654b318d6cae2000000000000000000000000000000000ae89f9eb1abe452efb7ca48f8f939d835f9a79e05211ed9f4abee06b93e34b17d920ddbca3d8bf18b96c3705c1a064500000000000000000000000000000000119ac787a7f3e9b7ee34070aac1a769430eaa8cc838f1752b573ac7f3c02a9f490de9600c856a55448598b149f5392e300000000000000000000000000000000193a3655a80e6e0b1278730600fd4f645d54947d193484131176b890ac197702333ea847317568230ad8af1280864096392f5b4291fbb18a93248e830b08fadbaad6434040c02b45cade73b77f22c2bc0000000000000000000000000000000012f66629836f0f57bdfd9bdeb2c9b7d6d5dc55c586e15d76aaa04aef06722bc8ca156fd1295b3063d738a85b3e8746d900000000000000000000000000000000097825c5db7289b1b9e640d19ecaaa81ee59e5b9884713f6d312604d8ac367634a264c316d73a9cf63358c8fb15f8c5700000000000000000000000000000000181133d027b97d8e2bef308a93b7ea2a35824dc7d01a3ed2f404fbe12ba3b3e51d94ec86cadf3da7dc9ecbaa23b411cc000000000000000000000000000000000a28a609d0bb015e375e74c087ce426dd3c20fbd8b374d3817c626faa81469cfd11a2a4e418a44f4d7ca621d0564bc4920a96f963375d7a294b584f2da699a6a00eb5781f46830987346cf4fe922a2f6000000000000000000000000000000000feca6f7e3cb286090fa3df9c5ebd10c06192fe14af58d46b827acf48fbd462f3f76d9d20670803946028437410ea52800000000000000000000000000000000183dc7085483bd05c27691c25588e33296fb610bddaac253af5b2262db38091650c1c3185d71a69d1a63770f95f381d7000000000000000000000000000000000189f9b9ea528bc2377ca3354fccf440fee059f5732dfdac320fb58541e74e444dbdcdc008c7b47681c05502f0b302f5000000000000000000000000000000000906162085e0e299a07e41b9d62668d4810b97d4be317bf376da537de7adb06de011f5f40af834593761b774771a80e4115cb4646c8996239f4fdda8c27a335361f0a19550d6eb0225c008408c47258800000000000000000000000000000000030cc52d7901d0360d10f344cecc8325412788cc30a912d5de3fa9bdab18db44efea235c5d34bab526f3b8ecee2cbb8d000000000000000000000000000000000cda35f561c19ebd85a445ce8bb1618b446c7013c07606ce58e0b5627a5c9e7cb200e2b8ee12a0564730279e75b469b500000000000000000000000000000000055ad0655a96f6dab5a432e7d2fef57a6a11113070444089df23b4b911e0994b90aaaaa2c62d06756f4704fa218f7c350000000000000000000000000000000011d22438d7c162d34802a664c254abaae07659902e1f1bfc2bdffa6c17eb11bff5276474cc3cec9507e28685f1c21bb0c8a8d98c93c392aefb64ce0c7ea455ba14c48bfbad0e3dc38d43abbc3276caab0000000000000000000000000000000001d04065373ce5d1ce47e00476f07708bb028040edb9ae7e8e00e2c6c460e1ab8b730ff510a25a3c8114c1753b7bf1ca00000000000000000000000000000000001c87217f150694a84a4e5aba8d188ebf7224e76b078dcaba4a91de6b4ab317966ce1a9267a5a27ce556c3386b086620000000000000000000000000000000003c8422590826e0999e7ae3ecba84edaed20fd7f1eba02b9daf1c46c2aec74d5fe63319047d37f5115f243ae0ddd4ffb00000000000000000000000000000000136ae093c3bd55ddaffc2494f3ba8176947cdf2f1ae408e7e786b23b6a65ba8c4131c83cd890386ba531b8637b3b042c8221622734dc6ccf6c7b84b387a3dfecafe187dab70ba373b4416ce3c505bef2000000000000000000000000000000000d09b92a559b8efe5224184fb4f43779d0b8c8f23587f4f74e2fc6fb1f94e8d2e0d591eb0702cf51a9eb402e79b46a0a0000000000000000000000000000000014ec2e4702f1ee1074cd1ad29791cf4903357e62570d16ac80c5e8ff73b255ee03a5ba070091cb2f984b2139de06a97d000000000000000000000000000000000d22fceaa48193756ce7331952a2d9a8057b67bede729e07cf8422bfc79f9ed2aeb99a9227af256deee9f8a6f227faba0000000000000000000000000000000015d9322c3a5a7ca404259c4cc7cb93dc3d46dd8dd9475756d2ce6fea527642f9230c7e94a804ecb0b4adec7963fa9cdcd3d1f427a25f5df025fa71244cb92dda9391d65b04756c41de0f67ea072c375d000000000000000000000000000000000e16fee11affc6714c7fc8fc5e7cce44d8afe645861dd2f0b8e58aa93d4f0de9b7e73020a1537bfbb0e2c8327c4aae03000000000000000000000000000000000b7745a4aaa8ab4593daa61e375d55f9043fbc7385ff229889fca514562168a4e769c5eeef4d564b41cff28b4efdb7bf0000000000000000000000000000000017f6c5b1fb00746b50ee4c7c743ae57fae2742617e5565241d012a0ef6067d9ce59be749a99886ce9836b648525d2e92000000000000000000000000000000000a3be81720e80f6aa0570c89613c78efe95d87ccb374e7f77065800590bc71d23ae097516ae1e97b498cd233221cf717b55c943fd9b11f2fb8a89f6c08a6eabe9434062354d845f1ac740e6043443f8b0000000000000000000000000000000008080a7d91caaf2470f9632575b43990a9523219d75994f1944979ed5b650be1e3c93eceeafb0875f66a40651f4c6dfc0000000000000000000000000000000007a19c4a6340e39230a33b12fe63e47bb0d1378420ec9e439f216699e512e4d70571a1670eaa6b60a5c899ac63360a250000000000000000000000000000000016898d22b2c123003480e3a01965a72de94cdfa39b20898c49e451dcf6a4727a1ebd629172aa1a1aa6897916cea192b4000000000000000000000000000000001217a373c78de9d3005690023b9e56bbed3073f13ca2408a27a3480578d8013fb9d3ee5cda95c3cdd091a5cc68d928da7b0c1d54e51b8572256aeb72bb032a5011a3e8ec5ad7e8b6e0397b9f6fc64c9f",
+ "Expected": "0000000000000000000000000000000005829c932c80baa420602bf841ad9bb24fa25c61f33f5d88693207b81271c94eef54bb524aa830fdad8caf8c082bd4990000000000000000000000000000000000b8d184316c2471ec6875641ea83de4f9b7227041922415b38b07a0704d01f2585ec2701bb4ae0bf6a0c0522efc0c630000000000000000000000000000000001dd81e075620914254b38ca5a7287eb56f2f31f6f8fe02fa51488d45c7f4609bcf49972d0ae5ded76eed5a4c096939d0000000000000000000000000000000008067feba36999b58342ac54e48b0fe28245f8ac2498b60093082822d19854df5c3168dcd55ccb6b2cb397b77e712333",
+ "Name": "matter_g2_multiexp_41",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016ed84856b9f41be9bc6c025a9b79e2968e2ee6bbc27608093256c541096e2c9eda1159e6dcdaefe783aa59d52f28ee90000000000000000000000000000000014aabafdfe8c7369f93d5472a9c6c4d426e4b02c943488be993d04ed24aef5477f6d455f82b4af78381b8bd16f42b56f000000000000000000000000000000000af34789c6c923103633e5b1b9fb447b671ab05265c16488ca7224e49db21973487a5d3de4de40b9d8a97ac9b1966619000000000000000000000000000000001123a6601c5351a586f27f8264d4227f5e1df868a03e0c3df5c148cb523cdd178f96fbe52464fdab210564dfc22b29536f082a5ffb8baa38ffd684a4a70114343a1e723bfcbfeb57d0a85ad5e592d7410000000000000000000000000000000011b82d78cd9b53b8e7e5c14a7371f34f08546896bd59d1e7d8be15d21742180aacdd01b0d08da2cb24873ce75e166bd500000000000000000000000000000000161ae0d724085a6e801edf73443cca87995c2d6b37e962db5719f4c480cb830e379fa778fd2f29e75173e1c31daccaee000000000000000000000000000000000a2c2b89d00b7d19f2b0530889905c30cecbd4ed0b56ca82208d666e7576c32a6e90cf867ad87f19e4fd367a10c449a2000000000000000000000000000000000b65c0226743b573dad7ff25bf1885e3dec686cfd5da2862ab300fde4fc8fa9b587d0f2d11ebe1f6a6770bcaf2588f8f5160286a6d23c30595809dab6ee6523d7d235114d1b295087e024b4f6ffc80e50000000000000000000000000000000012d4f299998aa897db9e3194244fdd1dfb95225e3271383b5cc296bbc51c4e1af52e849d8244f82421cd198158918d8900000000000000000000000000000000110638a2f7cdb7104de8fffe29be32610063bc656e13168921501e1614f282bdc9fccff4eb3c479a42b240a2c8014864000000000000000000000000000000000b0adbcbaedbedd376efd20a417bcce562b87b7449cac1e90d44eb05930e6f558b35ef755457305da012a231b5675bc2000000000000000000000000000000000db6fa926c7e02f633730569732fd9239bbacf2042599e79a4bee76619872901c6f4ec4d4fbf3f84143a0d17b167130ebbca29b94b6583d46753473143d13a7aadb0b18d6d35d7423b8a004991fa1ce500000000000000000000000000000000166578f3087772545c0f47fe0b3efe32874d26463e4f262be65a3bb6b0fad7d0f779808f69362f3fe63c72f24ed03d70000000000000000000000000000000000a8e61e8193228fa1825cf14e94f68a5eecece9afb48b44871c5ad62510ee1fc4e9c60d5f2529b8685e6aa13ec91979b0000000000000000000000000000000008d25d81bc4bc92508c8cade33c305c11d71a06bd46f184b05dc406f0939f0e0967b02f15b4f7f6984c9fba0644ca8e800000000000000000000000000000000113660a7d2152346500a1578641aad4dac2919ce63d01d8ffa6dad72f524c888fc2e9d2876859859e47d8e884f170f86607c80069dab2a16e39370de32df20534aca46565cf573159a93c64f1f0c4a1a00000000000000000000000000000000160529ff217934c85cbaa8b347151539e252dbb502c015e8e45c128df2b8a737866737d5cf0eca6f76e4a16790cd02a200000000000000000000000000000000127f7b0e4f9351836db9c204386a199293955471dbcd7b4ee9186f0434b46dcacd1edc02fb46b4c377c4e62cec10cd6700000000000000000000000000000000094abac17b11600d7447f7ad0f21d98c14e439c4a4a6572b00c90e14d9fc54e85045d0576f74b054d384179afc0a70c80000000000000000000000000000000017165c32410a498add8e1dd55ae43f94be234ba3859fc6b4816d7436746add313f42b1fb49e0cb6c4b7341f0acd09db841c1f256e866d218b3ec20c132446945177d518573ae3f0e739ebcc8821bfbc700000000000000000000000000000000060e503ee1c5d3eae4bc0eb30fd86303a5c48c10cc7b4736d17b8774c78a8c97ee05b40d366b2cc9bc7781b1e4a192f200000000000000000000000000000000034e7012414edfc6a8f7b2c6049236b6fb77eb94b05d55b218851fc1e553514e6ad388fac08a24c33bea63ddabdfd8720000000000000000000000000000000004c832477a90683d417a00a698b69c643d6dbf82f5afbb83eb3946f8098d80de6f2d457c0a06d0051315f06e93b5e13b00000000000000000000000000000000048c3339996948974f2bac14d8a6b8430897644ec8e9cff9eb369557003aa2827a4f3fc3444c4df73663ebc9325ff317c72a47e2267010c532d676ee3c3ebfb2be2b7569f6f7a22f76733d7773ed383c00000000000000000000000000000000082466944ee7c62788b6fa77816094ea623d03c7aa2af249cfbfbf78eed26a76cff8c23c2295aac7ee1ef8dc84630003000000000000000000000000000000000a8f88adecc3f50d8eb329492f2c031e722f36627cb3b21415781156ef44954c5b8529ceed5978a37ae1248909d38b5d000000000000000000000000000000000e08f628aa014152b50a85bb6eb947d53c596d82c0d03594ed3b64c486b8630c880adf43fb1575b02e4eb8174a04034c000000000000000000000000000000000776844f28958d3e12a5c163dbd039e50df44b1c6215429381790175a609a339621475a5b9a06c3276c9177d2dd2b576c52f48e84a68d99124e678dabaf376c956dbe9603974283a9efc7c27e830e9590000000000000000000000000000000004477f153c0510d8e50bfdc2db69182c05d5ae9b94bb1880de239733e380e03d50001378432312b24b5bf0952c38396c0000000000000000000000000000000016663990dbe529a5658f2b3044bbd390ad430adaeffbd5306f758d86bd5422391bfa1d21e88c63300faad55e6a2d1d3200000000000000000000000000000000188f701658558033ce2c41101a611f74ad6d3cd075c195476bd2cd59a1a9dcfe937020737250fe418b4de435f8b3a0380000000000000000000000000000000013f8d3625309767841603329f56686a99e196d697802cfcf31f8b48f9c76f77a321276a0158a22b94e91d6907f6ff451e4fe662495bffd8ace4c1ddb39e612b361bf90a0f1bdf6c7fde2bcf63df1bbd2000000000000000000000000000000000f184d22f3c0431b031ee0ee7ae9598ffb511a2a56f5c9f15c9a4b0c53af2a10d22a311805786e303e234239326dd74b000000000000000000000000000000001062725b8c576e79e314f6a56ef9c41f05a65d7d0d57d8414e2ae9cb1a520b16ede7e418d3a9413c9c1660dd7508d5860000000000000000000000000000000012ef02fbe96f9a191804b6c4a0b65b6024e3e2b1f8cff986f5a950cde9a32ad50d4f7a72804b2d18b93250a63a7ae97800000000000000000000000000000000000b3b0333d61fc46653a7172f5a813d13ff5a48056f9689c78c4b18b8aa3afaeb7cec305d98dd600786351338a2185a651e67e96f64b80f4978fdc1cac90be538774e34c2f619f8b8e60cd2aa20f2690000000000000000000000000000000010c91e1dda48dc528f618f01abbe01db1a7b6dcb0d47b83c7b7db3331f7156f7b2d0f081458241467b0078935a7b4a4c0000000000000000000000000000000006f87f782979d2adc02e65b56a4906e50430cb4e0913636e9aa0364535c9d7ecd3b9433358e00caa8e90e84b7705bdfe0000000000000000000000000000000004635089c7706cfdb5a22ef643d1a9a5021847646ef01ea559d1b655299b65cd76a73b04149adbac612e7aa756cf30060000000000000000000000000000000002d83d82bc9fd66c558e00547a8c25633899584c9b855195c00eb3c8742d22c601982f244a03f8e0c5c21caee24405481a6ecd3db89a7f07344b5728efffd35a11f7380c740669f746fdf565905a1ca0000000000000000000000000000000000848f10eeba8ef9c7fd0e679767f6b6a2392922092916da8f13573661f84ec97c65717e55c65526cedd59dc1e096f0840000000000000000000000000000000013781974518487de12661bedfca5fe72205c51cab461b5757ff14f319d081e7845cf8e099892ea85470039713e8e48cd0000000000000000000000000000000004cc1a27d1aa88484fed40ceef72e6bd201e5ee276b5ec27624286dee112ece767b37c6f1f7846d71cc0f4042f04dc170000000000000000000000000000000004f7335d6a1463976d9fd86e2baa45d08ec65059b14449ebe4aae99971c5666cdc6e40cf0510ae99dbce97ae8b4598067db5ef4c1c174c2e5ffe5555f54f4e845c463bb5105381fb39eddc01103b1bf70000000000000000000000000000000003c1b1e0848bbe37e62f1ebacef1a574400d5048f1e09d935af2052da29140dc4074175e4d6ceb7c2c071331b2f3d1d3000000000000000000000000000000000e1c84d6b20553ddc5ab09049ec488ea2839c5818e31455a7b231cd0455e2945aefcbdc6c1979821a80bb4f77d46e91e00000000000000000000000000000000199ebb31e8800395a9c2e103c9340444c97004186929b52de33cb8d9396e7ab8d5af3fe6035d4463701ea41e341f577300000000000000000000000000000000081b3882bfdf83e67d2dc42b211069a4e93c0f173263f9f20579128391e7f2de70335df949b9c0e9b834b6e574f2f8cc14018f14c50d40d3324952ec22ed247c13c4cf10eacd32c3671757bd12b041e60000000000000000000000000000000018aa45c6b3898a5fa618f87f9a08a7234c1b94fbe38e2297a1f9c7a2e9de0ed83023deebd56560b1928c012c14dd7a860000000000000000000000000000000009ab80da6c519aee8aa1fa68c35bd0fac78b55f88d861e8fcd445f629054325d63cc4241f61e5596dad0d54c94511e4c00000000000000000000000000000000105f8253f37f5538a2c25587fd33ea61fdc744a7cdf4ff23a55e2c66a39040d4de5eeacb7e11c0d2a483d59e7c3186aa000000000000000000000000000000000f6b10cd6522a1e34c87c702f58a07858cb753d67da9625155bd433020775351a9ec4ff879f91a43f63be1c969afe675ed4a28dc3acaf2220ba56d026b292a7d017bcbe358dedc57556cf638517bbb14000000000000000000000000000000001618dd5de43a6bcde91a6a03fcd88fe59d1c8c51d3d85cd44a1920dabd2608a0b17a987b76eb8f5b20c7f1dc0abb383e00000000000000000000000000000000198034b7ab8fb8ff267a52a9423da95bc587eef8684f18639df5db44e50bae7fdea5c5e5ef37ff14937f86cc948a34e500000000000000000000000000000000106d1f017da463176bdf55e3ada78ce70da4486be42dd0095e3a8a0f6e59ed503324565b717b45ee38d90dd3ad13c10600000000000000000000000000000000112d425765fa2fc28486b95e49db63346188fc5a6bd0b7dffa4430dc82703eb44d98d726edfa4a275aa5db5028d01ef530fb17a38b7d0888eb02394eed26406bce9e92779251bdbcb432153a550c0850000000000000000000000000000000001326581ac1a1a960db1ff2e8b89b1debaae46d1e2d0aa6ffc6c7398f207abb699ac59186ae7222b5cae3abe64cb61c93000000000000000000000000000000000218753594c63ebe5fe503aab4dbe1e944b24138948542c7c43d92ccfeba5854b7bf1bbcf8078d85fb0b8701b8b092fa000000000000000000000000000000000c3ce8c17f75e78a8c9980e9fe125290d377a32ac46411876ef011e169e86e1458ac5e71cb4a446f6c640cceb8d5617300000000000000000000000000000000176966eac1e20586ad2a03b4a1598b4db1d7c66be70b1b22833e4afe0e0b3783572f791ddcd4eb70a88f4acc28b6fc7a980b5873a5d0f78c3b8582581349498fa997fe3c6b1abe0edaed594253359d8700000000000000000000000000000000099ac8430fa411e74082cf3282f9a456d3826a7df4f91ecf621e645a1abc057e1bcfaf9ee73f149bc447cf4230f2f6c90000000000000000000000000000000004e93d7fedc9e2d7423c9e111b4674a2bd83de28dcbbcc54ce4b324c96318a11603fc9ea385f1c02364ab1f6b5458481000000000000000000000000000000000bbb29d70fba5b12fadb02a24bfe3f6a5362c71fe5f964dcd0e01442781d0462a873501029192858027d612a8572e9d30000000000000000000000000000000010daa9960005562ca2d18eaf4b4bf081f194fa824cc77515c81b2c836627f21b732448f367e2cc1830ad0fa4ceb928e1619f5719c320320a3c45dcd6207575e0d8527c458c56d3decf1d12ead8a985a1",
+ "Expected": "0000000000000000000000000000000002a61fead6801f41f2f27603cf34cfb4b917f2f85cba1f9c684995227653c9dde559e1e8497234fba9b2e4c119cbd9ec000000000000000000000000000000000085f73b8e835a10bcb9312931eb08d916d2b93a1da843fa2f4530cdb26e93b5dc95a555dbe8e50ca465b162661ce1d3000000000000000000000000000000001442fff9019b5476c217ff725ad95c92c17b42471ed7bcc121e8a0506755ec279d4e56d770a322d56f56bc6a6b0a41160000000000000000000000000000000017e7710c4639d51c4a79c5a2791101b52742df202b1827192872f168bd21020bd068160a587fc501782c1301c231a0d3",
+ "Name": "matter_g2_multiexp_42",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001213b5d5704c454845824994769c8b300676e75bafdeb95202001161aede276ab7967ea7362d38e97ca1484cf9c342fd0000000000000000000000000000000008c7c1fa04bebe5a1fb8678370563db63e7a10b30747c2ddeb4aabd4fc0ec93220d578b8110c6bfe8a3a6ea2820f0db8000000000000000000000000000000000c4061a295120a00de52300ee625ac46566464e6702489467316e8c182ca2168052c50b5962ff47285866c17d213fc8400000000000000000000000000000000086c153169a9ed1aba10a6cbebff4911b37907d6398c441ad47da17988d512d822ee36f5217355b93c9d6dd8dcbc8e0b119d33d32affaadbf6c2b6243bb7b344a971270b488cf887334fcb15de2818cc0000000000000000000000000000000017929edde8f9940826ed739bc9f59099ce76e85950698ab0140784647023f96afa064aa4a49b9728f496515a0a807e5900000000000000000000000000000000198d98f430384c1e7fa9e2403d9c3d2f81873fb7b204378cec95b97e674e10a1a43af97db0488209904469989ce80a0a000000000000000000000000000000000afc9b5138999bcef35613e38bff4f81cf532e00346f5205405470b2424622826c746ddf0369c7bdf77467dcea5cff290000000000000000000000000000000019ccc05724b3e9966bf918f01312c80e8422b697be89365b6ca00eb31b0bd08fae942e90a75bf9da1b3d264e416060f1f1d832b355d7e0ac3653431528ad0a8f6819daaa19292a00c910ff0ff39f46d5000000000000000000000000000000001568e52c2760d895874527d1ac8597730578176bdcfc67aaf69ccda253f6616230811dac59bc27cc1e57b94b5743cb3f000000000000000000000000000000000a4ddeb8b56f105ed5f47a538052f3d38a23c0ceaa2dea241554e6508f82f47d32415ffeeafe5ae5664c936b78e07648000000000000000000000000000000000b3b335a390aa0090bfd6467d6cd02eea1ced347cdce3c9ed85dd46e38e9f2ae9642392c2875a27618ba8f2c555d5b190000000000000000000000000000000012baa4b29d116eec749353b7658af70d4d216189133db707e56068c8483af43ba86583862e6b39df13b88058536861b9e6dcfa50f6129544835b5a4568954264ea68d9e2e5d4370ee31026997a3fbfe90000000000000000000000000000000001888b83ca28c244a6178377b4ee6844dc916e28c3f56312ecc0e29d08e6254dcda39a36ccdc317d1908303db3c028dd000000000000000000000000000000000f4b73d9316fee42d60f8de402a7d07765508b84d8f2c1be1f3f9e802ed7b0c6c5fece3db95d5287225026e73de98ea4000000000000000000000000000000000f1b48122191e1bc421881de831293a80566b9a7f2c9836f7718afb69592d59d2a714cfddf88945b94fac7a50b743eee000000000000000000000000000000000f1c6b052dbd03795433d7ad122473f109484d50245021c8727d252145e7db7dadc015265d1547f9c748409d74f5aa33f7822767391d3b2331e8e1b81c659c6e0262f7355063decedabac9797a84f0f400000000000000000000000000000000011e8613c3a771a177b4b85f0c6f97a53fd7900cc23566aecbf115058d2863189c21be36dd5dd736f6d0ffbe88182b400000000000000000000000000000000017b2c4e8d8aad0a12fd7130789188bb63a08f2b243c8f7700599dd33d7e176f70f2b1818e56540ab3fa507878d96a46e000000000000000000000000000000000e2b5ad5ed3578dfdffa414a4a2142846b1232cd2de468725283e3f92b536d8ede74bacc236993f6f68a16fc6a7828d3000000000000000000000000000000000fdbf06ae4cfedc462f5913bba9bba2b5c86ecd0e298bf27a21317fe74af6ab15014c62cbfb617356548cf808599caf4b1ba1cd6a4a6c433624dec63547119c0d492e3f38afb04e5153d82e400631aef000000000000000000000000000000000b48aebc6525620b99cd83979658a35afa233d17849bd0dcabffcf3b550f875a386b6c0b4ddacf18a23843629072c0150000000000000000000000000000000010432e5abf862d3be10ac5677b9f296ccdcedf1480e45de631b6bfec42f20edf62034f7205f659f11fe5a6aa9d882c7a00000000000000000000000000000000011702a3590e7aedd6948bb94bcc874e0b8d77a18126ed4ba3753dc98953ff941495486c14c6d801c71fca3564ded9910000000000000000000000000000000009faa427c0a7da26c92b451c61f5b5e8804fe032a4cfa014397e430882cbfcff81bb22f9c15a8747ef455773c1ef65b0a41e184bcaa0721caa4114d6393ae2251fed84aef57c7927a170145308bb136700000000000000000000000000000000061a1ee841251bad461f89c52196bebb1cb4463298e88abd62cccd21bbd325ddb33d1306ffedb2734be76c18d80c8dfe000000000000000000000000000000000d05a5ce6372ce34b0bf4b19d8e05aab74abc1cedcc35a2d1d4db38813d1e5c1375d63ca0e8bbf29c510a4319d2aec27000000000000000000000000000000000dfc57aa8de28745b8d28db3769ab5ea26b5115d3e59e51ff19af8ba37efacdccf763ce682cfdc77685705781c3924870000000000000000000000000000000018c17d87411c4f8e0ca51b3eb4c3765d3846e0d1b75574f8e511b2f3e8c5ff53bf7618959ce18dfd9e4c6285e88f094f63cb451d8eb3565274793925a1869ca5a25fb19639449c71a761809f785568de000000000000000000000000000000000a0642094b89dc9c6c7c11c1e57ed542982bd246112884969d424a3e091ec4fd73dd40a5ac116f6c68216fd1e733cdc7000000000000000000000000000000000788c7a63eecd1cbc26ee6b14b09d0a3b7a17a848fc0551d50cb7497bc98287da2d9b898260eb678a8a0f446eef5c6670000000000000000000000000000000017a1298f90022ddff3fbbcca180e3f4da8760218dba595a067287a2473a6e10b93dcd54154cb64b6c078b083b42cd09000000000000000000000000000000000116e999b808dcaea0566c0fbef1807e160612dce91756b2cbcf4883b04a90320a0759bba21b41e6f4d8449b52e52f9a96a2f94d55f784ebfc6b6260327372217d6a5b9637ea5f9afc1a65f99c221c29f00000000000000000000000000000000064c95bc9c0e2be48849a349f16713791c37310f71b5d0613cf0706febeea3a56a0f0f1ac6b504524eba801e8b759f2900000000000000000000000000000000007088d2f41fc7e1147b92a2ee7062b9bec194d3a47eb9985ac1ceeef57e1a006571e7247a13dc95afcf9905be57e2a7000000000000000000000000000000000e6a0770f4315acd9e410fe58395ab8b20a08240a6948b762dfbbad3414bfca0ced4ec9da982bc9b8798b60dde78a96c000000000000000000000000000000000a70b53a6d71c83971167afe329ffacdd417bd7b228766851c3b43701a439f253a8659312db7e83a398142fe19332b527d889a3362f551b88e63463b7f0cc334fab3fdd302b630e419e362ec1eaaeec000000000000000000000000000000000002486eaf9b743d3aa6a1f3e1174c5f213bbf3e3cc0558d63ce40e3c03e1c2f6e8508248bb649aae1bc92f3eb8118a2000000000000000000000000000000000042b03959b40eb0641d39117f7af50dc7ff048697a57b80723aaca164e2dbc647ffe78fea0a6a4c07671f7db6d5b2dfa000000000000000000000000000000000e141eab29f52b9bd0ee44861f154ec1bd30abd715935a7958a19007e789a41cdb0f4b9cf7b3fac0b0d4d77637b510d00000000000000000000000000000000002cc2eaf89cb7a04d425d878a30b5e2e9858ae0b2a2ab28fb28a6db0c7283ad861bb6a92067e969e5721b43466e857db8bdd400ad873cd6ec546bff698171942d536b94e69dfef4bbf316a471d4b45cd000000000000000000000000000000000e0f7595e4c136b4d8bbd1eeb021df7dd2bcf1d9f98e4fa293f7edab635e019af87c138275fefacd806213177af40eca0000000000000000000000000000000005dc209d6c86f1871637998c10490a70371f9e00a68d1363dfaeb62046473dfb4bbd3b18b943439f75c45a1ee7f264a90000000000000000000000000000000003d215567d1e8f504a72658d48fa51374ac77234552c17db4033af780133d8516bb0769678ecb50b8b9eb950c2dd73e80000000000000000000000000000000004d780849b731012e1e5732d5f6d32c659a95c3e1c8f5ef4841fe82afc6f0aa309b1e02dc2554a4a4ee781be2be2149f63b496a64cfd15410192aee9912f869deea5a08eebd6b160667e12fdf23c44510000000000000000000000000000000007ecfb753be501d9f9b7ae7ceaabaa4fcb7b690ee04fa1a711a15dcf67e4422adef64a0f8118f93e67f24a2d1a2bcb36000000000000000000000000000000000a459e403d85972f7132641c05bb842416a7135009ff46b617bf0918e65cbbf33f76b98c10d901936e589bdf5de31ea4000000000000000000000000000000000bc6ec31a3ff92b4fae07cb73ad7bfa8423044048337b0ab9add09bf10fdf190a5f7996d157483d29fb29a681ed585520000000000000000000000000000000004c622e2bc606fefc8bd83c4a32f7353123205a6d3716b581c2c71360e5200ab069f60c256dfcb04b466c53cd61fc94470de38cb4627f53509eadb0918e562c6fa68a4cbdfa9f7578a8aaa8182f5315000000000000000000000000000000000125688e44f593c5f585765f30e9fee5e4f15247cf33ac78ed1744453385f49ac61128e23b1569ea33d74b207a5e72e930000000000000000000000000000000009d77360ea37298fe971569230159967012c4991255fb5337ca6d58cecc3cd44a024a9a044ac98a894cc97dea161844e00000000000000000000000000000000056b2dd9569f0698c732367cfb217af90a3d6dc15e2555ce0aa845616e4067a7fefb304f6525b539555a0a685f0ec5f20000000000000000000000000000000009acb138abacac351e03f7589d4bf29cbd331e93bf538578ca9466b759ea070931c786d35f74fad42261e2df431fd00316732c583e8049a5de38642cebab774d90d5f87601e3599ffc9af692ba532e620000000000000000000000000000000013515b0022ea946a8e679b9c0eac6cd67dbc4efc820f0b3d8984f12b7d154c0632a8d7207747284d49c498c79b6bb5c60000000000000000000000000000000004d6765ec6aa8744225c1e652ccddccc91fff7fa8182931c8648b3d8bd33b2177a9af03b2906da02bf117bea59aed3040000000000000000000000000000000006f1d858c4b223552f0aee466cff35d14b3ac6da35b8f482417e8f597514b065be315aec6662ea5c7784d3a9e2184090000000000000000000000000000000000345eaf0d72b9c11fe72261a2fddea318a8dab92a67ccb9438c11e61fd298a333cc42084d4ca127e09792e346cfe0f004a037e7562adfbad6b1ac48b8e4b6f277a788ea2f4416ed2900ed2791f09bc2400000000000000000000000000000000029ad10ed6d6d5bb591771cbd597a3a0b841c2347c89027126bfd1efee2ac403933beb99d08721232ab9b7354fcf9aa800000000000000000000000000000000198400d4e026c2463a07ba5a3974c869ed8ceb1f029bfc7f41b23dd7076cf4a83b17c27ad6506c852cd2cf7c4987f93100000000000000000000000000000000152bbf74cefb77fae8e825443e4ce09b4e223242187f563a236695294d0a5f540f0b29d6f93a54cf0a77900e936e61e000000000000000000000000000000000079f4759eaf044a80417345a1b4029f8d4cfc7e00fc625e815cb7daba2243a97d21e42b42ec968dc8647158fbe467088fa878f6a2e18b88d6badc5b42775e92c17974f3a18817b7769d44ceecac46b89000000000000000000000000000000000cf3148d0c30774104a097562cc83456d5d18643d5f7ad58aedd9327bf8e9450feee50ee893442b1cde87acb02b62045000000000000000000000000000000000011d4037dcc15d0c50337d71816a2b77428b8ddd530bc3b3c8550606229f88286ae94ba03578cbb5bbaf118916dddc90000000000000000000000000000000016160c8ec4e2fb780748aac279bc248b2e2f1092262f86d368d2f06a78ebcd27e929930c8f2be124e9d92dff5c6c6f42000000000000000000000000000000001980375281735390f48ddac9d00d4c6ee7312ed0797333a26a1684e09c9575e57bcecfc4a31b8d9597a8ecc703835e22c4f1a7d2b66e6202c957a649384cb277dbba769afd60708b457613f0f3372515",
+ "Expected": "0000000000000000000000000000000019ff32d2901b7732df1a924eb3c099a9d36bf36cb32ab322f46a72d99d81c7942d0f2193a4aeb55cf079a2cc1707c7aa000000000000000000000000000000000193561d0433e1031fc51829504ca70e92e19bead2e0bad655aaffb6b41f5f75d18f04a162db7714f3f23da891ea91af000000000000000000000000000000000d010c36acbfb38d9dc2df6e6e21bd75deba5708fb1012eab23d06d78b1244d4daae38aa4f803d12441d91adfbaece7a000000000000000000000000000000001459ebfe65c3b2c9b2684042bd71201869db1a0248c740a54fbdafcf18fcdbcc7b677af43abe803362b462369237690c",
+ "Name": "matter_g2_multiexp_43",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005b9860b565fc64146020647d1902e2a2d2fb2002b54bf5e21b6601124edf14d6e8836f938843fbd8c02ed8530953dac00000000000000000000000000000000104938181f16f16318d223febec3be3877bc57067fc23729d1f5552099125558cb21ee0eddc32ae0b0cc3555219eedba000000000000000000000000000000000211f809b624c4992a43e78a978ea32accf9e61fccef6bcd05155e52adbf4853340dfacebec9fa87e5417c045da25f9a0000000000000000000000000000000019bfe94a18da9ab4ea744389c17870ac96218d02178bf2ad502f166a3a1da8c14e3fc52038021503cd24042cde8f306d0241da9d8505208b4d3ba2521a42f28df7d06fc212e9e84931cbd30ae3ba2e150000000000000000000000000000000004fbb396eac2a1de9953febed9fb6e158a3b5a366f783d2105b562e8143031d7a1ef039e3fdcdb675b3d3aa4f4dcbe4f00000000000000000000000000000000155e23b5b70f1ce34fc229ad5c8bdfde7fb5dc0eca19596c658c1f8c38716a0a7b5ff59ff19a7a67e12760fa90eeafcd0000000000000000000000000000000002cc82cf87e7ac05be236104c1e668b5573674d9bd741f2d91d05c8a11af1f72aaa1dc20c73953fea38e6e069d2a43de000000000000000000000000000000000a7d1dcab00db0e7c0a239511d630526fb120defcd9453fbb57ee328f974a98721274144e48d22558edf25595b8ff4cc6fecab1334668102e47f1e7139059c1d715a1851a026a1580f93c2daa3f08a270000000000000000000000000000000010c9293b3c58d646a95c620a0e0a7a0a55cf43b4abaa0de1d5570fabca8d97c91afd67bd45aa234273715457da5a2894000000000000000000000000000000001454f8682f3736847cdb3f784a098f7c9e488629efc3820d49b36a2e928bbf736dcb3e1b30187c2c0090fff290dbf97f000000000000000000000000000000000a0fe3c635a81f20258db4f1031589afc8c7fd07f2fe1e5cfc8f3c40d08a958a3dbec537c51be2de99b849e006870b6c000000000000000000000000000000000728876e3fdc42273e8d71953de61dd5c03e7c31ab6ec56fc03cdf55c8f0aa4b4e5c8ed88c23c28568be0d864df026af4e2023c64a3b51cc3d82e262f83260ed4a5e9e3238b85077852fd501b52aceed000000000000000000000000000000000c9ba542189ec1828c397ace9639cf2ebbd1613356d8fb26d3c40dd00af1f43f5bbb25032561aeebba7b874bf39cb0d500000000000000000000000000000000175aa6e94a9e42cf809f48f51c48d60e74d61388dd217b55f3f63612c4565357581e5c39751a65afc3b7488caf5151720000000000000000000000000000000014c880d35d1d31793145803182584a8da003b0ee3c29c978b64bbfe4e1da82910a4539587ba350d393e1bf3169c5e4c70000000000000000000000000000000002a063b3fcd77180de632deca1ba89ec4ceeefefe9883ed9e7e06301a268bdf377c3a6e30859e5a39419e449dd27ebf5dc0a88f0aeb2b082dea6b50d591018330c2276830ed554840c10772403561ed700000000000000000000000000000000069edfb8a83760e09726f6d1c117d4bb3e499084b65e1e830ab30daf1625c37f851ac122f9f5c795912b5b6f7907ffe1000000000000000000000000000000000eb6e9b55869f65ecdf3ac46d0ee596d07c573f88724bcd802b4429392b9a56730a217a03286deb5103f70aba7a9bc46000000000000000000000000000000000e2803e1a646bd70c51806b676591b328cb20359aadc8e79d59e7c31e1ce2f1473b0b19f7a34f23aae09678b11b37432000000000000000000000000000000000b3c9fb5a39a6c40343259e12ff4fe5058f25619d145922e1d80c3f5d105a7495dd9a4da329a2e78afc31a87b2c5d5e2f68c9e76d9d8914f14007c968a31089041e67312c6a3e5d30e65efa55894ba740000000000000000000000000000000019da372143e30307a71c7b96ae0703301ed723814a35e270ef6a6b0c57144f494df1d3fa0ac369f59f3daf534070c9120000000000000000000000000000000006521d89d810c7542108de26bbc888482a3bcec8cb9b542db42d5d4af30d6c339a5b4e959da4f98dd6ef8075554f4017000000000000000000000000000000001387d9c684a0fbf615e7023c0f3ff47f4d2c5a9f748f0261656a09b23066c745420df0eb180c9716d6d0743aae7689a10000000000000000000000000000000014271b9d0b21cc69072333a6c03493321b9d9028149d24964a3773bcbe5045875c457aee11ab0682c2bdd44f098f363d80eb90c6cc25b3a48d93b94b698eff513da37210ba79d22d76a270aa97fd51070000000000000000000000000000000001dd881f3d2063adcc5638b4b3813a30e75fd308de3c9f42e5382fdbf097d5796ee9e03cb44752515b2459f131f58bb90000000000000000000000000000000010f491f4594dab938115343edb47b0087d1cd1bc12ef908e150ecbdb3a54d8dd51ab24a0e10c585f235ed99fbd3172270000000000000000000000000000000019d1665d452ce7fb6bb6da9782a55dcf12a1d9abdfd50435b8f2a1bc5b323c004fad35ff7e9aedfd414a9b68fb1eb1860000000000000000000000000000000013828087beeeb85e43e8540fbdf97af189878f5ddc1eb35c95aa06a26923330f3b8a2b43f835186865d6f5f6afdb2b9b067bfd893b12c79e13659ee9b5f22de71d806a85410c9a23dc43363915a606b100000000000000000000000000000000014964f3576b97c00a8c5f4372e2501944a1e4374a3c30e11376ea62e09d52d40d428887833bc2f06279b859c00c98a60000000000000000000000000000000019ed533a3bf469ce5b3e4e9035af177efe9e4f8b0a0e5dc9721dde49a7fc66fa31c8b1c8d5bcda1bf75a532bd2be356d00000000000000000000000000000000064ec4ed48d63ab62373adb7898bc904d246bf2b3790c3cd850524e50ec38e7fb4a364344a6a1dbd26f2ad2d0fccaa1600000000000000000000000000000000134aa3c6b72d39bedd8f9c619d206a295cbc05c611147d38aa7304e995089ce34ab1fa13c2d6c6807a88797dea20214b34abb11f7ed6d73fb81ce2777acd6bbe8839112c527ef4ad88b094cabdb4742a000000000000000000000000000000000a2a4c8b457d0d2554a2d439fd3b74b18843386aaa00d1b89a1c2d8ff7192cdd1d3a888994376bb7ddda4d16bfcaae3200000000000000000000000000000000155a7dc763caf6f0fe1ba9537c0f75d3e455c2d1c749dbb4aa7242b40a9740fe9e8e88af6017e8f743a9e4c5dc6ebc23000000000000000000000000000000000a693da3aee178e2f0489af77f671c734423032f30c0b7b48debd3b71e65dab7db12ab1e0e72d3ef686d6c1922aebbf700000000000000000000000000000000109c3476016884386d6206c94073c628375a02c8fcd3041e06b8b413508188a1d26ec5ddf84a77d059e9a039dc5470d08d6693acb1eb73f6ed1bb4f74f1062f720a7f2c0ecf2b5a944ff89feb2688e19000000000000000000000000000000000a07f457f5dee69e9ee746dd67f982914a2182b5cb2609d273d4122d57a32c195270c956361d78eb65449cf5e13907ba0000000000000000000000000000000011f149ce84c2a11ff818be3ff0f86c1b38a9555e169a8cf791c79828207b7aa89c84e8012a0c5d8cce4e89d758b90e22000000000000000000000000000000000d636e5b027e41809d7ec8bbbfd4bf641a56599a63a7678569404ec8d45c3b88c1d2969e6101528d4edf1ee9d8e793320000000000000000000000000000000011878eefa5ee49be83ea1f7a9cdcd4997ccc59a9669778b3f006429e1a22d3b2a051924f371a228856523e3a09bab59b29ca1b157e6a2b5b88d7467e851282491ed30382ba217b82ea5cc9ca0c6986930000000000000000000000000000000019e9a1950f663b258474b24c334bd256d3aedcd26dc971a745857bf1fe007da0aa00777db5c3e5d21294e99862bf8ea1000000000000000000000000000000000329a12fa0add36f259e401442bbe6e5f9139e4a46d5d091a2110d2561b5629211a1c1996f20d19327d1782340e7ce4200000000000000000000000000000000032782c94c6e45a88425438324f3a24ebf37f0be213424b1be52c878985633950a022f57f8d64af1470486aa3744f3f7000000000000000000000000000000000631556d52fdcee3529023cf20d46ea09ab3c642a7f4eca2878e4af88801d21b80b829c9aec9e73317252639c148676c40bb53575662fa0b726469da01c39df389efde3936d2eee18d7035704130ad6d0000000000000000000000000000000009eb122c61ec44afb56b64929040058a804311e0e97d3fa513a162748091304233480bbc883f6fb66080b563b308a24a0000000000000000000000000000000007d1d810fb8788b9f0cd04235771d7adbbdf8c6e67e8538b2c6f0f278755cc5e57ad720515ca558412ae1fe2cd40b74d000000000000000000000000000000000955496bdcbca8716245a130fe6eef44d13280b2d56f15bfc772f8ca66a52ca0a742e6bc273c28cfc858a3269f59beab0000000000000000000000000000000000b27aaa0d94633912c96f00ecc021773e5cf5e164e20c7a7222a58b0465e7baec4e67fb56ffe564c7a2904f36c265e61574a30a575138c44881c1c126be214c6b68335d7338875b8a398196f27510d70000000000000000000000000000000012e0572f5c84f6082dd05705a3fae738920ffff840c21e444f0ed002df16394afdc21c249b6f1837389c48719539f4c5000000000000000000000000000000000c26bb3ab52e3bddc219dc223daf472247547544e3a9ccc31123b82000b17ef325148935621edd36ced4e702ade1ee3e000000000000000000000000000000000c13a8f02dc3f209e9abf3d316fa843be9c4dd98ce1ca2edecf757bf2bb498750f6d96c28abd45d9c6cf5b8b6334b63600000000000000000000000000000000157a50d9034024dfc7b0f0db4ea0f45323d76c81bc844844ff9bdd0c13f2059066ec3060210aaba61bc074afd7ccaa286dd51553c4119255b31cb0aaad7391694f7dd29420420b513699747bee819a99000000000000000000000000000000001054edb092a7053eebc542f690e03139f2e25a0098c665741e8711c8a6b9582af47e467f74fff9aeea098b7732be72d400000000000000000000000000000000084f919e219de15e7f9ee122383c772415741e5b86be6ee7d2193a4f6be5c9cc9b2fe5e8beba26cd768bf2ea1b6ebffb0000000000000000000000000000000001822b4e8fae5bddbb36f5c226216471862af238be770d33c4fc1ec2777350db2f42e33a7ba468c317a128e8446ceff300000000000000000000000000000000130f704596ddb28ec6e335d9527707a75c97298407ff3fe17d3cba0cde4c21bfcfd1ae46272018c1db768c036f215182d88f049ab3ee2b01af449abce08ca14ea3b065f06a8665ae3510b4c04f42308200000000000000000000000000000000194dde06f8c54de9ab0ad72ba0de2241fef32fba30fd6f5e83fb7750bc120d51c461d75e495cee0d1e85f0f39aa9d3620000000000000000000000000000000010646496be02c658c82dc68eab86a4f784cf64494bd8441f884e8ff384cbb6ff3a4bf5126bbacaa556aafd652397a8a800000000000000000000000000000000109807bd4b6613acb3eb7d386e84166219e52e841c41185a269cc7cfc5f34e9ef5cd1fea29877749e0cef93a3b44eb1600000000000000000000000000000000020a388c668c9339e7aab15d03108317dea97720dd27a94cd3bb59b372b268d1a7d7d7409780bc4912c3f95acd42a57619d6e227185c538b122858ad5ae594720fa7f743f5805552152a213ebea64aeb00000000000000000000000000000000161506c4a2d57c852fe8c3dce63ec6673f05f99c1e032c8e591239616ef4469c4240482ce5985fdfd4a80f54dfa7024f000000000000000000000000000000000486c5b106393e544852c143c5ac4a882c79870363858b2c910ef4041d8803876cc55ef59cd6a41869bf5247f0db2c0a0000000000000000000000000000000000fe765ebf3c4edd3035c7bedd4aec918426898339d7aa004fd74bbf0e3236deeb7d2bbba56c31fd447816e301100a66000000000000000000000000000000001917c9cf16032e22cdd3f87f098a532a33c9fec560a88f9d4232f96cbe0fe945fbae6bcfdd2095cafe6e0b21071d6ec53f53123f01c4d0d4c18dd72ea87ebb5fcb559df255773fa0165f1432c229deb6",
+ "Expected": "0000000000000000000000000000000015a88bcfa39f444cd66d0d7e15c4040561154c59b832c5ca895f8f8077659487581681cc8f13be136a35b4a573551ad00000000000000000000000000000000009fb6b87eba1edb3d1d23e566977eac68e8f1a28386fdca9d484c7e341c1b210390787418e2f2dff7a228e1cf10962d6000000000000000000000000000000000978de870dcd8d094072897707313b9f1a18d525e60a7cba2b2a395ffcc9d0f97f84e0784df36247d6c98824aaf3ec82000000000000000000000000000000000fbc6832c324d40f104bf82c8cda941212105131c26f630af1d3f7040ef43c6eb4486766b75a81433e46966f79953647",
+ "Name": "matter_g2_multiexp_44",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007517a941bec38d0e84d21508d8bdd6778a853d9fb4c5e953bcfe3c8fba3732ca0b7f6cb5c363f33d7718b1b1a68f8e800000000000000000000000000000000150c0d975481422ddec2a58a55b3d917b6b7c0510e75442c81ee856e267d7efa09641c6b79fb9e699c6b473cccde7f4d0000000000000000000000000000000009d37bf938ac30fae1cb3ffaa971ff3746ee4090d4bf8b11dff7710b3f2e4cc686813890e03643fd56fc99e847ae5e940000000000000000000000000000000010fabc4048e0fadad73d0481e290c81884f4578cfb66e0a83324739652ccf273b62204f126696a2fc6469ede39e00a9fcdf2bbbad52a3f5c0b3959d46a8c42f6f5250a93c3dcc636712a4a2baed289c900000000000000000000000000000000089b167ce7fa997ca0ad3f8bbbb358824cb41f525bf60352d5df99402af62cc6d768113d2c1ebc7fe8190c5f732fbfff0000000000000000000000000000000013dcd35865e27bf98f1f6508b32c7e9a989d528df0626228087bda0d8b456af3ea2f4be6732edf1bd8cfd0ab9576197a000000000000000000000000000000000333b0612d7068986d21e1cb67a1c7af423e98cb14aace2ce02f84d32a38f97bcdac465f2b22e5fafa6aaf0d40380e4a0000000000000000000000000000000010de7ba4f50b6654fdecc4fc6c41289bec50cff1be18be9d5c9d1f906ae843189bb43f144aad4d2a2cdebbc2697c974918adf5d8fbdf81f8e4bf2f622e2d481fb2dea06a1aaa289ce4f6e783eb9a98dd000000000000000000000000000000000fdddfceb29fd79c31b138ae8e41507f324abd5e3750da14f4f86176126a06380d53dd5f7efd00e7f94bc1370ac9816a000000000000000000000000000000000d8371c602e393a4be250583c299d069270a344953f7f07a5fe27f8617cbd3ebc91f423dc176b272339bb3bd8a9a348200000000000000000000000000000000193a260a417c9c46da0aaf139e3bbfbaa9f248943048396d95716b3be0b8a148a3f0ebcf7d6f9a318b16d2d850ec2f5c000000000000000000000000000000000be4d0f2bf6d746b930034eea8a19d73377617645c29153b6ae6d3ca6fb35a704b6a0bb658282cf93555c998f6fd054a650e995b73b63d068fd54f596cd9669fc3061f0c1da77ae7d0f5bec012f9ba69000000000000000000000000000000000731c0a5d076d6addb15c1e5d3143d41371f4835d77756418bee452d2f03b1e603230c59f87905fb67d5eccce65a45d20000000000000000000000000000000013bd198c023009190c65686468523eccb57c5fe7b159a1c5ba30c662a275fb24d69338ec9c023ee6a10a8ec9dc7968210000000000000000000000000000000018fb369923ee655839c7d996e264133c49f102978f18261faf2f8eef376eb0bdcb5af375ada2bc783e50df16737f78dc0000000000000000000000000000000009ab8e16e1d0b406adbb37e950bc3820ec13c882ec4483528ebac836726ba202bcf796e84abb3c16dbf6d1131b3854cc3350d4f13e25052b1162dad3ace76e5cda71680fdc89460d8fa88c0d157df426000000000000000000000000000000001401029d7cf8e7d2690a27c01b32008e273b5a33842dcf52d84f77dfa4b2a1fb290f56eb4ccddbb420b27e06a7a3a3b4000000000000000000000000000000000c464c6fdba702f2fbf4232b34d615e66dbb5bdf80233f695e9103272111a06a79f8972d1034176859d0e29400f5a9c10000000000000000000000000000000006cc97a29f4e694f0cdbb099278fa94140b40147f4f911de96a762f2bd28233598a892899a6329cc3cb854b56076787a000000000000000000000000000000000625811cad7c740758388f330c4a56ef30429ea4cdb9a00e2cd1b7f310184a2e6ba36ebdca57c87cebd5232f52c34d92283f0256766690c88df6cf7c968b9a96121d26d19672ce9adc84b699476a32db000000000000000000000000000000000d0a16b5d48eb062c71b91d74a0d25eca0d4bd7082de25199f33a9d3d598d137fbee2ac36e8f877c157be7438ebabd74000000000000000000000000000000000bf93533bf677050d9a77a5dbdbf7cf084b5d934d55318256712ec361693738d48ef27536476fdc93dd8e81f13d67a8e000000000000000000000000000000000696fbd8841e60300602aa5528391aa8b196d8c186d6124c842a0124a8d8dcbba637502f330c980b2f5a900be8e04d020000000000000000000000000000000017b0c51e699d2252f35619520af71775f9dd8c57c2ef146adeb72640bec2ca02a59680153e5c9f66bd513bd8559b9d66145cdeae7fd3f7455dfd2ea9a064c135f0a0a36990ea34929e292e4cdfa0f472000000000000000000000000000000000eee94b5148ccbb3642e582cf0a517b72e6ea019676a13b1484982de7f4be0346b7ed22979ba7303f6367294a3eb2716000000000000000000000000000000001502bb3964f6b3e862279e15fb105073e876c4e48c55c42f3737dc9efed82b10fe8e39438ccd39c933f5ac3c6768497e0000000000000000000000000000000016cd8c4b3be55474aef7081cb969b75ef5e7cca9bd0f9627928fe9931c6f869a9a49d0ae2cfb8346116eb3ced25d4a8e0000000000000000000000000000000012456eceaf32cbb6514e6211136475a750889caea18ff4f9d5ed7b378e6d1d265721a646715aee6b9f2098e954a88289d9cdaa979ab08b454dcb961e3cc4bb18f706bed93a72a9c1e105cd69c0b691af0000000000000000000000000000000007b5633f4a7dfe62f11065d44581f5060210f8e572d960eb85ffd0a903d8b989ce10449fc90b7e5646784a9f6df28699000000000000000000000000000000001710f252cb35d88f6bd151ed596f2d6455f050c5e25add394dbaf60fc036016ae07a5a8ed494b95875c02df3c523186a000000000000000000000000000000000bee19779dc6430ebee993f82a054fbd42e5b7265090017e5b2d2f1469bc96a5a188adf471d576a416f6a841081043df00000000000000000000000000000000038f9fb4159e4e6f596a17ddf45a00a9e4aede63b062af5eda045efacd3977e8dfd61c307834c08bb4c284638696e92ef262f9f7a26353193939bfbbdc50ee35614a3c099776f08b21e0c4c97521eb8e00000000000000000000000000000000197687895f22c4a639bcf2f494dd9e5a034610b0297528235f1d806cf032f5a86c5248a83ed6b12f0de27f5c6e6f49420000000000000000000000000000000011ccd5dd6d6ce553ade9b31503a9e6a6119ae329178706f051581e3cf0ee9d6fb527b340bab8c79fad1cd451c7edb4330000000000000000000000000000000011e9f051aacd69c8bfd2f0ecb566e6d38eabc43f276ba7a1b8e8ab093917dd1c672c61d6dac4651026823b9938d3601f000000000000000000000000000000001362c3b2e6fd9b3618df26ed28f96530c1915f0a4ecb647658d1ae4ccf4c000f3bd1797696c9ac5c5000dbe58dba8de44f0d2915e82c9a69f9e9af64a2c5cacf61ead492bf69912a35ad6a316f9914a8000000000000000000000000000000001819d13cf4522a9362bbeb0bbbb0a498c3f34da1c9e3b2c54d08f7c8acd9ee756983fe80405579effb79d673407390ef000000000000000000000000000000000f870e5978f4a6e3b655fb2a05541ac0673e7b10136adaf28be4dfc9022d4cc8a60e17d125dfe53fbe10c644ff37e02a0000000000000000000000000000000010207ef774cddd10db2bca0a051ceb12900c407ee265dea4615553c193d7475b5ba3198b7e0160740e4fd015dca33e1d0000000000000000000000000000000017937be546e06fd2eab4c969a029534c02fb770646d43edeb5e6c8bc0c2b5f35576c375bf860fd1087ce099d4377d24e25ed3f13198b69604c08b414562f67a67aa8dd4a7bd3c066874182d21ed9004d000000000000000000000000000000000db02fcda340fb27a3fd7da468c5cbed9c8dce8471843a8ddadae43dbec9957a0479aa52855d7a6dca99e7922432365c00000000000000000000000000000000163503d24f9af34058cb5afd8e9d5aaf29e141c8521eaac282f138466e834f0daa9ce14e0590b501680d5b47f866aa8c000000000000000000000000000000000fc9175e6d20afd9d194907f2eb311bf8134aeb96da72f6423610612f2ed20a074c113fe8bb632d9ad74b2f6e7e2417d000000000000000000000000000000000b4621f5e4465629648b62b7f2b77afe6470f9706f9bee5b3ccfa66c596842cbae26badc689f7f623360cb7fc1d416b84ae188cc115e9d492be64abefa4bd4c93b61dd42a7d213e1100b8108611a61630000000000000000000000000000000003c77c7efdab9a9e71283b034ef581a31faee417febfa99be3c18e8ab724c140be684ce719bc5a9ac5d3855ddbf3651a0000000000000000000000000000000011889b02b4a1150fc2b7191a95c5ee767f3c9b82a3a53591018242fa8685ee3b3542526dfdc00695a6cf046033b8eb760000000000000000000000000000000016d7463159c4e3cb635f24bfb944bc518369e894218bc49d7b7f0ea99240259f7ee2b4c26c6083dbc4559ffcfbd392bd0000000000000000000000000000000010a85df6294fd6406ca651f15494153e9802f0068bfa149e87fe4b1cc3071ba74940a21dfd55a8a77e7e2a193468a3d2eede725a693277356ce71ffd7814a77fcc30eeb3a2b8863fb91ca03da1cbe37a0000000000000000000000000000000016beec57d3049c382fc039ac96b890412c5e8075afcab599fb877f8639747a587e82241d9a8059a0bb45ad49959777d0000000000000000000000000000000000a70fba1b061dcf587f133035a3aaafcdace3b1e771d71887ae914919e5f52a99d9933307ec15b5f0a1623b9592824500000000000000000000000000000000005064161136c04f9f50e42a5cee5dce3fa0ce1dc0655b3785a852cb9741927f6c9b357ac1010d7212533d1593c83dba70000000000000000000000000000000000d50b992bc0eee37a15cfd32eda2c591fc4c4203ef84232d1a1e7a9888005bc00755d76b9d0345bb01ffa7525f2aa1e9d0618f898594b23ee3754fe390d6bdfa7d47fe749d6819e306935c1eab6b0460000000000000000000000000000000007617e60d8f67344ce6d2fb65cfd5b423a1fd091626da837dc8a51d6ffdeda9712864e8f30e45ae8df917e0e4625e59a00000000000000000000000000000000077c4aad14f870ba24703397ff0b33af2e50b026f3e0f13f3ec1aebc9ea3af98cc65ab56cce4045538ae6e5f410196f10000000000000000000000000000000004a31d0eff18afa87f9a53098cfd5d21e913c7519cb171f83d0b73abbf3e893a3ccd5aebb9f2bbdd3b0eb0326d37fd1b000000000000000000000000000000000393052e6dff65e01e79254af757f12eb1931e0b386f8cf0fa0782269f962ebc5d9bde46f5a4ad3806e88330aca59ff01e1c9420cfa91026286d7f986b538c13e8c97893995485308c69f053927f962200000000000000000000000000000000033aa108d252e9107f29cc7da79585d4525ff2a35d31479a099c7c011a9c4414d7bc5f8498f8a204134b2d14c5fcde5100000000000000000000000000000000121214465992bdefb970d420face6db75d531e67314a021d2877643ddf738fbe57625d286bde7f40efc1d329a2e85b6e0000000000000000000000000000000017e14f6cdd916b1fc949be8ba3ef9ae6cc16d64da4dd498b5458ea0c14eb7aab8f970f030aab26397110331da11a232d000000000000000000000000000000000c56ccda2a5cca61025253407e72967c767f0e7f2aa0b97d4e4a09420dcb882ff35039ae504a9c62b3f9e7bb0c2e7bbbe5095ed9a9181aee392888e3194ebf9c4a6d87b503f4668bb6cc0d290880a44f0000000000000000000000000000000010fb3396b0674b9285cc5d5a4e7a41ac002f2b43332c20a56f428d1e19e1d1bb6f886d3bf03f7b0fc509e52d75965e15000000000000000000000000000000001196b7c253c50da10815bdfd7930a69608187fc3ac5fbcfeb35b95754d3017a094afcdaea867c2f08346717dfce7bce8000000000000000000000000000000001021f178c53b7d7d2041a6419203d12ee162f27999dd8f79baa15c37a7401e7a6df6aa4192a310cc1a23bdb0b427d63c000000000000000000000000000000000953c75910165f11112583476574f3987495d33e5b1a5c650a2b30692592a442d9de36da49255b0c01a7bacaecc9b81adcece8ee33d3bf3188574e94a889794077035ee92473b7266d92a3c018771b4c",
+ "Expected": "0000000000000000000000000000000014da1d424c936453600a4acbd3666c6188493d4da8b34d6bc508aab07e59e3680a9e3488e69d42a724c9486d70ed4fd000000000000000000000000000000000048c637348fb9a4c631a82ded1fa08d693cfa2cdd6cdffb8bffee63d1bb2ee8676512a1a8d375e7ab942b6d6bdda45c80000000000000000000000000000000000443264e7dfca91f17251c33cf72c56b045902b4db2eb10d1fd856f79b4130afa6f29f3283af7d3b8b2a9d8dd63718a000000000000000000000000000000000fb386f875190ac7a49d4742edb387f72c1ae0366ca5c71d5b7e385c11442941ce0fb9fe2014fc624fe93ab86ebc7aff",
+ "Name": "matter_g2_multiexp_45",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016a539a21320574fc25ffbc0ff10c821d6ad20674413eaeda6f4a31f9a028e21cbb3b224c225a2e3bc3dc221cec084cf00000000000000000000000000000000104e44989e2fba9ddce8e309f5d3fa3129f679d6456ed11137149b50adf8b22c1a148d47154450853e6797aba2b006850000000000000000000000000000000008b33b8cfc992efdf7d733803a6d08a4102e27fc4960ebe6ebdb7949c4ff5af76e55002d93a4f7204eff5f2dc4e37ef10000000000000000000000000000000017c35411c571c302c746a9b79cae892e988d50b4660564660de960ee09b3937b6f5b61fe37d09f1c02528f554210744aaddc845ad867f1e2664ef0e78bced8ff6904c5836e7c63ea3a9c858fd7b710b60000000000000000000000000000000009cd32594094d4744f59690cf8d7fd260b5ffb2a22945d938c035151861507ecaac9ea553e7b44fc4b3beb03b33783540000000000000000000000000000000006f4de33731b9b13b9cb395798769e54a0679d272c2d5175455e10c790debabae4ee02b6df08975efe806da9c4a208b20000000000000000000000000000000011859798a8383b7f994a1535bc0a96a114b90644d19921f0eec774ed58dbaa899dd3736cd1f4a4ff9bfacbc7370091d7000000000000000000000000000000000376c25b0f70427d4974c4fd1539d40996b6847fbb67822fa01cfd541cd3a3f8a9f3fe9f7ddcc3ce920a6ecb27dafca0c78cfc6a30cea34d3d3505f4f897631f67ba77913734f6c2895d871fd6d5581c0000000000000000000000000000000003a178f91a135d59dbd65eacebab293a3817d30e734c247f56a08812aa540a5c80e3f9908d86ad787bab27fbddd21517000000000000000000000000000000000672b3544dd2b91a626f37dbb389aff073777164e3e20dc572b18a2e5223bd323094e41bdbe2dec9bada227efb37dd22000000000000000000000000000000000f40f2d279c66f22bf0fedd129e02c96d8906f9f1ec19f5a5c1cbd5beb10942a066dd391b69920a0a697138f627a1b180000000000000000000000000000000016ef3caad858d323b752e5c437ee2043c8f691ca0f1862e80857f7cc478a689df97bde5b1d1350892c1adb03c5d2373ba1e40df9e1f7c84633cb3dc2223296887de7281ea66c5e1f2d5816334f7b280a000000000000000000000000000000001276e133fc5e708a3265646ef0a0122048ef95d7fb46f78b8dca57dabae0164ca986bdc74e581604ff31165f9f28dca50000000000000000000000000000000008a77611be0502d2ea7fbcf73774fbaec68eba36038e2f34f79caf07f2e4b7444efc49a4e85f88af585fd28a041f26c800000000000000000000000000000000181ab176e391190b1cae2e9b4105ca14cc82d15890b0ec127d8cdb46f30b704a089ac69e76f5b50575ed66176950e1120000000000000000000000000000000004031ce77fe9ee319b8db8f220ef4480c81568b3f6e4043c8710b559d25ad69dd38dda48b2e11d5aead18db0d1cc09b98810b9ce0020904dc1903338089c30e616ed0be03741572ce46946883874f4ea000000000000000000000000000000000f26e6d71e206c88dc81b8b8a5c05ee84a9f185e7b7f155253aa39104b5de5be7bb6cb6662df4f8e63b37fd1682721f20000000000000000000000000000000010058d13637c8da2e91c8cda7dc2cf1734a2f14b12b798e5c563ef9ef3624255a6e1c7550c37b547c35c55dc736a17ce0000000000000000000000000000000019ed470bd514f8bda8fdcd9c64f7626efdde0102907bd31551b1d1972aa14e1d361e1d58b17948909a669fa4d99cf3200000000000000000000000000000000013277afe1891807e269c22c9aa1598c12081809d888e0eb2513ca3f81308700893f74f176858ceed9c7955dcc0d8fc6893e7702da2ff9f3f14586a9ae80c8713743d61b915a7c379c1faa1b151406a9a00000000000000000000000000000000083664daa965c4173d6028e047794703a16e52ae459d3db0534d13c72d749d603edd668b9ce500677715e45216367c63000000000000000000000000000000000f4e87a65f4720cbfde7868eaadb34ec1916925ffd84e5407defbda0c39e1c7afcbc90855b275d528e7b63fd3707bd4a0000000000000000000000000000000004c9f689abe0d2dd3d927bad4b39ab44f6704014ef9a1dcd1966777129e1c72515b43c1b92ee60e9611245454683588b000000000000000000000000000000000ecc57b08b45037e62498135643cf077f01d216b5106551daab391446ce7bb37d40f41378c830081bb6a326f0105c2c4eca54e365faa35d2c9be259b53a1157b180a373813382f47c9154af18a2d83270000000000000000000000000000000012b84341bbad1eaf7fc8ebe56f67598821017365b6f3b4cc1f2355f868e8d55f9c0bed2943ada202a7d85cc884d8e6a20000000000000000000000000000000017693721988f73d77f7a41db108e428b0ba781ea88eab463693ec352cc13d394101b9a2792e0f30c77bebaa395a4776700000000000000000000000000000000093245e2919523cd57a0abd2e8a9c5cbe774bee957f26d3cb502b9c8c06483b850b031461dc2cb033d399651724f4fe4000000000000000000000000000000001530f7dbf6a0fbdc8b4f7a4d298b7824c15035428cb8df834907e25c64b8985186bb13f397b7b99ea7014ae65c428b12abe2079ecb3618de3accdf291d9479bec32bca1f9fe87b00b64a12d735f5b9a5000000000000000000000000000000000f323f01f2a63bc6eb1b565594ded14043c4ea5d1f0fbf20f39299052617c334e6126afd4273738aeb153c3561348b8a000000000000000000000000000000001525d1e1fa65f1b674feef74f6c81c82c3eeb709e597aedabbfc2b3262271b31d93818613ecdeb49c5d3a6a64f17a5d90000000000000000000000000000000010458c15bf46947a237dd1c61882b1561121f64890681bae5db6fbd24ef6c34b7fcb826eeee1fa328d9ef4d859faf238000000000000000000000000000000000e1f29275fe1805d02e069082d5e9a7acf69be17013e6c4c351277408d49383fe06f00137e777ba4aa49c29c25c6c0ddc541a44756ebda14aea95f1a1d05e7366dc0285305116b907fc89e777ce45f79000000000000000000000000000000000efb7373e11694b966d0182a9b01d1e52ec1e89cb18275921294e2d36333460b1e49fd420f1ab781b000d1491ccb0b11000000000000000000000000000000000cafcdc2c58fb3fad713ce1a38deadba8636c384243f9971e3930b961efaf303cac4eef1e8e4662636ff91eff1bf52a80000000000000000000000000000000007ea7441e1b2b0f1e42bd511c060b646c2d00bb3e6507beb5d17ab93ff68515b02f82c2dd43ce035ff660ddb0c104a77000000000000000000000000000000000bd04b88caf9dbd0ef5f89d12e72aa47d64212332b0ed871b7eb96b16295cf4810f6f20cc85fd4d1ce72119f80697c1b37d521d31de52681f1d9bbf64a12f9bc8fe0ac61aaef14d7e8d048ff09e6578b000000000000000000000000000000000c3d2d978e23a690e8422fd54f36fbee1f642611b6c3b2c2413844066159bdcd3703d1a392b030446af04b654f8f73b7000000000000000000000000000000000ae652fcdbd8e467ee9b447e61fcb811f8b6aa48840476c92daec3285785a06a81c1705fc2896c0843ab48eb92555b9300000000000000000000000000000000007088e6441cb85aeffcb4a9a0c81ebfc54a61f35c542be3870c2bb94d7081353322d4745747b0dfc3e5db07f9e48c560000000000000000000000000000000006c11f3e0941ea3bde0dd3a562dbbdad433f0b1e99ba34879e86f7951ddfb29b9e04ca62d54d7552a74e8cf1c3da3e704904a876d4ac1341e88fc4808508c89c19dd74aa8fb1dd7673cbc2d28e7d920e000000000000000000000000000000000c665f4417d0163820ac96c83cc2f09b1b3c000023d827e2690aad7357ff59e278832b992703f5f0016051ce0a4510cb0000000000000000000000000000000012f4b6688300b253fe868b3790f6d2f4fc16d81a49ff7a2edf821de16dc992d79482d66e443e0abb5da43df69f8d648d0000000000000000000000000000000009e033750a118d998b136cd671d0e760e3a617f1d6a994db8f6dfc391619f408720cc57fe550785306184b0c824705620000000000000000000000000000000018cbacd471e528535e22f714a841f110fb0484826e30f97842d65072b2790dadf0bd7b28df96bec531fbed1f3f93486b68911b04d8155f90c7c5c0cb519ee6ff14c0ae27ece0374f30fa148235e8cb49000000000000000000000000000000000c42b6fd52cc52034b04078a6565af2b43948695851393596e05f37f297dfaaea931a33f5b4c25980c093f8a742c0020000000000000000000000000000000000fdc7aa20e63743dd6ab32c82d2d6992b29779ec06eebd452c17d844159e90a7f3221f3e0e6b5805dc0f42dc3836d90f0000000000000000000000000000000003a2342a1bd528d701c2a6c72708a16df632f4e4b6cdb3ccc224b58b57af30b44556cc968ba3c0396a5e3f11568a73710000000000000000000000000000000019ccf76462668905c5687b7612a0bdfd4aac70f291d8b772e84fd5d4bcb591556317426471242fb5f44fd695c7d49279481e894ecd52a252cc76547513e2cf0a5cc6b20c3dc9c64c7f34f29a488258ef000000000000000000000000000000000c8fd4a171c5fbf584f567a1c10b20628e7e0d5d796eac4a9dd2376f8d488da25b9219c7c70709999b5553f8bba915ae0000000000000000000000000000000005d791c907984f2aaebf903a0ace52147745295f0c5e85964999a8fc74b64c8871dce358f26ed1b4af6c6f7f18e8f4c500000000000000000000000000000000110a453bbba72ac171876e0f6b4acd5b178816301e02586a143c2bcbfffcdbf593655408b9aaa4141b2a210599f452ed000000000000000000000000000000001025d5065f9801fcc1c1ebebdf67923b967ce985b5ca27ab5db8af7057fda23561a46b84fac5e793dd9af692c4d56cde72780ab3c48c8a102469799ba2f70d2fd9d324cf558a8c8b49e2ecdb71ae1c9b00000000000000000000000000000000023e5ea1909032676cdb79111a33da7ed788d2affbf4029b932eed843268f355dc92905db283d6617fbb530da3d704dd000000000000000000000000000000000b46f07de520aa17d597586cb0a6894a356757941ff9bdc2976f620e1bf1eec1dd9801d6baa2d7efbb3cc7073412ce8e0000000000000000000000000000000010022940611f418de9f9210b1be919d7506aca468fe5853675fe159d3e58685bcff6cbc2c1cb9e7d45a7bf305fca0eaf000000000000000000000000000000001888b5b0dd1648d9a27345f570a1278238957de1bd30c195d554750ea4b119e98b3989b912c4fad531de416c1533467f84ae1de8aaf498bd2d91bd828bc64e56482b225322b86529da703f47289c65670000000000000000000000000000000011dcc334a5037719256e514b2c3b0f36396d8cedcd77f33545842c686fa0f35558c397562a7e245f8cc412c776a2b3930000000000000000000000000000000006efd32c6afc56a07c813fe19e71f0248666c87e1df7e79b7afbd70178929e5660e85cea35d1c6f42b4c627a94ae0d150000000000000000000000000000000005a5fc2010798c793c1b407a577da0bf0e04b0478f19b7d0cfeff8e4e4fe2d581461831db165cfd17146c49a732c41460000000000000000000000000000000011dfe3b62eb87b039113152af74ae74137cba1762d4ae62d3cb0746272d1c42d3cb4a8fccd845a519fd0650a23a897a13256548db55ee9de70ebf6fa347d81bc50494b937ab1c3079977234a34cbfcfd00000000000000000000000000000000110e73e44734b7ab63f021727b75e735702f1acfa6669e0dc27111794ebee371734764bb165132af3a7e02f3605456480000000000000000000000000000000005fbcac7c7334cd0e6468feedebe077b80390833eaa4c28af80d29e75d692a10cf13058526fa5e5ab0fb635335ac8f220000000000000000000000000000000013f537ecc28685aba2cd60d0e3e787bc8104a3373177cb93107b63d39919c583ad3ad7a42e322249d7605ef035fe1af40000000000000000000000000000000014791f94aff42bfca13ab328a3e47b06f7da52e13436ad477cf55e53b54108d3aa531f0a5d73ae5ed7108d5cca1ecf7a575ae146524544307ee51e58a654d7324983a87e1b37d46cea1a4ec34114b44b",
+ "Expected": "000000000000000000000000000000000bab02defb32b7938372d656feaebfb5431de1484361542c02519d20c6a500f0b0b112c331fe6f4eac3ec7f6ae4167e50000000000000000000000000000000000796b38c67df1361115bbf3a4afad2651664ef55b1ed02d3172f024f90a003fc3631753d7142aafffc64c6f6f57bf7800000000000000000000000000000000080d91637a93a9025e8691a400254af37cfde67eff7d3037d428596a808a01d9bda8025b7246fb00785cd1068b2752d400000000000000000000000000000000182a97624249f0c6d24672f04e2c93eff63fbe76cc11ace0f7193facd0655cc1e1ccb2d89d9547bc352a395efeb95afb",
+ "Name": "matter_g2_multiexp_46",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000115b14c4eb9cc78eafedd2072be4555a3db9e61b5fe0139bf3e40a92cc37b4936c68576fee5692a80e4a9aef05a9b7a80000000000000000000000000000000019c828ea555a3c8d28cf0981e98609361b5bafa8b62e860d121c0f6d0f0dcef544784e8a5fa6a9f1d1a68b30e8e8a6f8000000000000000000000000000000000a2ef5146d2658609fd4eb98fcb5d42f6c6aac4fe53597128bbba3ba3539042ee5824f381c41dc76e2c6e4dbe0665657000000000000000000000000000000001807a12ae5f289ecde8ca0a913647d44209b13fae9dd6aa8fb4365a3beeb81652ec17cf92f6784c9ca5a077824ff6dc31129275f3ab3125db33d43b36c7de0ad60a6e9cb4457aa03275caea9635f0b0700000000000000000000000000000000186bfd109ea2369818ae2f466953eddfa763960caeee9d6f1ecbf6a3f854163342c26b56d3844bfedd8f227070f75546000000000000000000000000000000001877077daa2ea074b2868e86faf14efc6ed35a64161a77aec54624d9cb916c45de81b40acc3797c6e3338fcd7a42bb0d00000000000000000000000000000000054be1650d9bb6cae6a1ed08879668e4aa4cd139c8b07ce21d40fb1cf37f11de730ff13814a02d2d6d6df5eec4afe8470000000000000000000000000000000001612b5b7c613cb66d4134aa867d985682f6a544147e7865732887d4fbb191a9f5bdc27bfbefd397f38cb101a2d68b192dbcfd8680258eee451db60f3f42f02f388f87440d00badb0a725964042515c90000000000000000000000000000000015e2b23aa42f1e6a07b0a31dd4acc27e35ce1fb3333c3f330f2d88f112375cf24e6dd5afc4d245531e4e84f1f82230ea00000000000000000000000000000000193649f3b7efb346e0c1f7bc05b0910311270cd44b5803fa16e06655d6239f609363344bb7c16c2105e20709fb5ff0400000000000000000000000000000000002a6ee30841f471dd2ef13888ba03c9cb93c85cfd0f1d0a3927205e3f57fe291bba7eccbd2352f25cc4047097fbb63860000000000000000000000000000000005482d4a47d6e381f755c4756a761f0310d0d981523afcf288e47a1a643d6be62ac6410521e0f25828f469af6150f41e5a6f194abeb6b7c1c561aa820bba658f0277870e2a32f972f9d18ca361929b01000000000000000000000000000000000178ca460993d503e496633fe5230d895bfcdd0696d817a23ae94e529bb145a0861e4448d3bd48c55907be762192a8c4000000000000000000000000000000000015d2db77105a8ed6eadc05d3d1f26a54b3d1b812a58ab49a889f5b7fcf5ec08c2eea6ad09484fda29cc007037a1f6c000000000000000000000000000000000fd5628d61cd0835fe49fcbd2f17058f23d0ffaca4474923a2c0706d9333d9881125efa2fda56234a82158da3eddb5b70000000000000000000000000000000010ce4a0bcada5f92cc8898dbf5c108c0897322eb6a467662be569d9ed0f6e2c808e214b83969ebb86c84d38f67d20754579450b7aa155a3ab61e47e337ddbcd17b197de2dbb76008cfaa09d3fc806be4000000000000000000000000000000000fc4ed0ca43d5cb172deef02704579187a480cc977737070b8ed2dce48d3f3141619f37e985c220a2840ac01dc5667f900000000000000000000000000000000047a15e96760affa4e537a45aefaaab1e0e18052f63514a9f6544136c87b7cb4a5c8dfc0d9544518adc7932ce9cff5f1000000000000000000000000000000000c9be55c06f81e87de58a5c1df8d16174cf4115f81091937d98dad6c4780a9b8dae1081f8961fadc4f994ef62927664700000000000000000000000000000000165f9b1a8f23831a91be8077b18563c7648e54caf30895983cc26580241ca7c86b9b30408a9b27776286ed9f07bd8ecd4be94f96ec4a3d4e028644c63b2577a9ef849b403acc55e42432c3063a918d160000000000000000000000000000000006edc0d62ec31b14e87b2ccff3a21a7c8d38c3ba0ec48bbb8df27fb1acf58e1a87c4458dc2b770172460adfb9a9bd50b000000000000000000000000000000000ae80063df8d41d45fc43f3aa0881364ab5fcb9ac526ee22d3870f2edb0aa379e9d81780b0ab08a4cf308d819338deee000000000000000000000000000000000e0898453feebb51d9a1cd2bda36a307ff2eebf44dc8f4c694831218c42b51f723ffe521b356ad4e5f0dbbca9af9ab47000000000000000000000000000000000fd186dbc046dd02217cec3c7894972f71e5f00e00a40fb1521659a33e079b7a1f60b026d9055a50ae18aae5757ab8490983e6618e9e4208cfbaf647592e42b2d30de9e74e4943fb2bb49109a66302aa0000000000000000000000000000000012134b433877e0a7858e6c3b95b2a1dcfb0548b290b68c209642dadf550db1c636598ac43d101b13c2d8d5ed9602a73800000000000000000000000000000000102b5de123c449a078f6f06935c9537efc791ed8e5475ffc2d9e1d098c814abe56d4b7fc6501c315edf7e64a431c5183000000000000000000000000000000000bce703ba78f45a1c59c69429d3dda18243ba2413c5eab46d469f504da975c434eda451c85357738d6c7054755d5cec1000000000000000000000000000000000387724937bfd817a65c0e0411678cdc78df26ebd4a814d92b023710558701163349b56b80e6bb68a4401f2662a0525506615e300a924ab962e0b7fd0b044cae9516d96de603ee80695718c27d7fba0c0000000000000000000000000000000005abed9305bb79a0ef1cc70e7fc2eae35a8580cd3d1ffad73d3bdae541ad546b8f74b4ca76f8f374e31dbdaf1bd14be9000000000000000000000000000000000199b29da8d161ab3061a18debc8b7400415caf029ced47131e27d81a0f7f79b6ae5e570f34a4c74fb85fea1411bd6ea000000000000000000000000000000000b8a7c42f5289d20b1a55a42d53d49510d3871b6efbe560bb4d87029b85b930f787c3a42e225006ad62c68d5f96c2f8a000000000000000000000000000000000e74aad2b29a210cc316181863e71a1dce8866a088a072ad5972af57b813a2e968a5b16b294273acd6e81e9a5be2961dd77d3e9e64e00b9356cceb62209ad48fc89e69e2214aad2edeba1812272736390000000000000000000000000000000001587e32753adc85c98cf1322115772b0e282ef4e6a75944fc86091e81aad076508e3d727f4df0e30924fff6b67c312e000000000000000000000000000000000ae96d3a1b79985e56f80df8ac4d9792229ca580b156dbbe71a9db470447fa4dfa19fc8a8a2e2f0fae28a24b7d6153d100000000000000000000000000000000114101ad0d29ddfd2fc436d2a270711c444c8c257785f4b4c549e9c795f6dd9834d3744995d2188c0c968752a7f68892000000000000000000000000000000000d30d9cc1e2273af745dd47a596a2202ca4fb655f9f9beeb0a87631e2461f29206163fd921761fde69654cb02e23505c41f75c89ec973f65b11786e186f4d42ee2e85c40f29745d9f428af08a39d5681000000000000000000000000000000001611787ba658b64467b4a28e55ea24a3b230836af6c2a7072231045ee4ee38e02302a62688d6f988f76cb5e50eba40080000000000000000000000000000000008badcd59d6d30f26ca674753ae9257a853dbcf49a5641999634a9a35a97096b6096b7b058360bec2f9476a51eb0d781000000000000000000000000000000000d30154440d8bb5fa6538953a96ba404658817be8047fa7a3a86493f02399543220758e649948b804f2daf84fb86f7580000000000000000000000000000000014fbdd62f761fa675e4cbcb61083a910bcfbd1f8e37f1fb1915f60929b047c970b87be0730ddc20f9716ed8c9bea7f19c70cfb76a04d1a9e0d937292e5553ef371e20d5d3dd33611edc0da178e2e4a1600000000000000000000000000000000143d1f811644e3a51c735b708cb2f8a2a90311f9971c90b9ec8e45bdd6488638b6851dbc882205263887b4dd5dfb4e120000000000000000000000000000000015692a6b06e3bd3100e149c6be3cbf1566fb24531eb29036fc48f85d5da83316a38af4e714a17552024c1ca4a5e39d9d00000000000000000000000000000000172b9c88ed9a1fc2d5a7f147d034fa243d420b129343ff92b79bc4d836e380e5a7e388069e9af9026485e9d3f41a7aa300000000000000000000000000000000012e8453dc64f72653c4e9b3f6f43fdd01b896c642d21604f992dc5591f2cadf71de4099e1075a4ca4b7539f84dd5a908db878b7f5fe817599add432ecf262f19d80ac834bb0a0f983728f6e2c189c880000000000000000000000000000000003e9b6d23809781f50c0033e53d245dfebbba9e0c4d9f676ae61b80fb6e774509f62fad854fd9ea841d9905d48d943a30000000000000000000000000000000016a1ba62bc684bb1848b0ccba59597b19973b56fd9b1d9d06352de44aa79c6bf65409dafb54f859d4a7c32e188bbe19d000000000000000000000000000000000e782741a4b16c5838a8f6e542135221ab3c6ad180c85c08742992ddf0239388e273735eae76c656e61614da386ce2640000000000000000000000000000000001cf6752e88990c221af94e18744790c30aa6a158b10a1f6a56c2ee3c3f0fdb2fa7213f16764ac9e9f4f65e99e715ca170751fe88ad289c91dfcd3c3c61ce1e33f4146f03fc0dc77cde9b32b51c75fc0000000000000000000000000000000000810b0175d781256053c3c9188cee4f55620a6624bfbd2f4d2e70ee68a105bc7b60bafdb76794a048e9f25da976390d4000000000000000000000000000000000716095f8fd72d9350ca62ca3ec34d2228cb563d4e89b19b152787d42fbb750435aa6233d0a97196a9324319837be14f00000000000000000000000000000000178e939d87c37d4a2f49e1e5596945879f2f0f64419e3dfe2afa06bd58098e1ba57a9b60c32cd6527481ab3b325ca827000000000000000000000000000000000aed480a1da482e40ae610a9522f0a18399b0130202f9ca79e3573987f5f7ae30724feddb52fdd05817a96f7937aaf7984bf139cc0b6ac94697b7dc278063a74e478d47528da3f84f55fb0adfd851d09000000000000000000000000000000000133adb236d9eec3544fc91852278abe37a1da0f32a84477c0d93927d64af613b7452a5f64ddec7447779f42873cb157000000000000000000000000000000000f6bd940b51b7ec5a0d92ac77a55c296215e970e9a499793864dd69c3a8d583403e95c08b719b5d8eb0c37a8476d3b960000000000000000000000000000000007d4444062ae06e65b45c6105af53c487f6b275ecdb36f87ec7b71d5861a1bdd6d735e9a1fc5dfb476ab8c13a98b570a000000000000000000000000000000000e043cdc87c67157b5ea3e5ab1b243aef479b23861f8cd823bced140ee03dd1f8bc6cebb4bde4683ac3340823f4d55b8d19d9496e7ebca44354d5c6e1f6b8211eb06ca23a6444c307f92f5bc6dcc2dbe0000000000000000000000000000000018c35112c27caa6bfe9cf8ae55f51755ed349ee7e7141c99069dea07c21a6d8634778a91f4dc3d17da04966a9eaccab5000000000000000000000000000000001800c8a9b146dba27050ce63e78895bee2016255c59acc34fd5e6cb926c16a8fcd2e8a579fa02559b3c571cb08011bea0000000000000000000000000000000014afab23fd4ea54b1ef576a12a2a62d42b493612ef466483ee8c4e62908486c038598e72dbd9256166960db73259def8000000000000000000000000000000000899a99ae8b10da4bbffb6590d79aa33bb2adb2444a11627f05622c732b70f90cbd2779362349aede5b591e84b53a8a06940e3509e1fb090fa787fdf633a74380cd5de722678826224641e46a6e920df000000000000000000000000000000000567d6458d1a3e012c63adc8b9dcf32254c98c0b7021ec6a8d579dad47d501715d2e42a0837def225515d663e663c4f000000000000000000000000000000000178daae121366ce025c1dc2d3e72068fd40ba9d54b2b3724f7a2071a59d4f17d4766a82364540bc31a46398c66d0e7da00000000000000000000000000000000147b2851311913ea53662082acfba785d21915cf00cd154b1b495246e109ac37c3fb6c63aabc4fe71a0d37c81a40148d0000000000000000000000000000000000122b7b1a81888aee37fdd6c23d31c38e79f28945cd1798cee3f4d674e923fc68311eda8ce45a561abf9c5f0bfeb4297b27d21c1d6e06d9fba7b61fb87d364a7a6252c70b8ace2d3679ed87ce0fcf7e",
+ "Expected": "000000000000000000000000000000000f5b941cda417cce69a30c1ba4a82cca71cb4b953d06d8e545c1b792ae22738dc006627da02b4344bb8be93a5a0dcf07000000000000000000000000000000000eebf4ac30fe0ffb905f81577466889666f801d4d6efe0fb8a663fbf1cbe76b2167243edfc6cde3f49d97d3040a9507400000000000000000000000000000000007ae6a99b86dc7ea95801776589472547ffc7a623009a592403a9710ca365510d85bbf20fa4519ca0e0ca208bf86a670000000000000000000000000000000004b5abf778c72bcc5b887855c582c042a4cfff489b0548785e4c1b735b19159be8a3f4cecf34c769a34cdefa722ba783",
+ "Name": "matter_g2_multiexp_47",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017b47384e6302b140118d0a9247aeae2091607ebb413ffa232223bb42d16753b2ae48e5ad0265e33616b25f0c4234be600000000000000000000000000000000167be566292b835a42ac7c099d80e8a0b5d4ff91d842d4ff6026876aa1570ef9641e9c0cbd44d8578f6a758717bad6f10000000000000000000000000000000014f692d195979abd9c55ac132d0def925d4e158fe946fa7b0a010c475d60171a0951d4b68ae3c463bf1136600a1ddaed000000000000000000000000000000000ddba1f4236c5200aa52f8cb7e15fac1f20cc66dc65ed180745a3eb8308f2c851ed6c1e27e1507d3f902ce672d6f8d24facfcdf87c6ca0506b070abff83ce7812181c31729cc534497aa8dabe243351300000000000000000000000000000000023d08e255b244cffe911e43b9b48408f9fb3562edc2c27f405bb657731c885a58392ebbde9fc80cccee2404cc8547ec00000000000000000000000000000000088ef289adaf206afd2b72c93049fca2cf9292bf6471133c64ac4f42015b97bb9a23f6c34653e0218fd0abdefa56bcc60000000000000000000000000000000015cb78c1440f74b17125c547fe7a37611f01b83b91a351664c696e0f647bd2db3ffead880b96a327780026d74c9abca30000000000000000000000000000000004d1a63607b9a5c9ec31168d85fbbee77cea0ae93e98c8c1dde14d0baa72f91042b2b7ca489958344916ce79bcf286456546fa692d9cd61895526282193c90148099e2afa54f7903a5431f932bd5fa06000000000000000000000000000000000ea6cb7ff6a7f4ec38ba11e9945eb406dbb8517585fef6cdd64edc970efba244b071fa162f7c8e184acbf71c5d1e12160000000000000000000000000000000001ab80c0dced33cac8a6a085efce71dcd7021f6255684bb631cf5c1716021bece57b900b819e6eb6f5b755b74c677b6c0000000000000000000000000000000005465fdd51352cbcd8b804cd509526c3b6232976b8278cec3b7db7da14b77f78898c6240c30943d1418462cb7a5abf8f0000000000000000000000000000000006b6caa6a0d5f2d671b10217c0ce5b3962b0c3edb4f2918497c316ebbdbe1a15c803d7fc3413907346f0e7d03920005aa9c1460c1cbb2a552e3452d5c5535868ee9c2952ec3fdb52dd826c16ae3d00bc00000000000000000000000000000000170db23154805a04013052a388e14b5da00e65b35b8ce2dd967213a74735dcbfd28782cef1ffe9d384be3ecadd101e9300000000000000000000000000000000082dea309092976408a379f1dbed9d8cf91f768e2921e49ece458859c80a1d9efd4d5e588470bd669c777d16f9d2e7de000000000000000000000000000000000adba8ef34e197689228e6c4e13be75b3d4732872c99b865ce7733b7a42034d6d4d7520ef7ab712f60f1ff87bc4d9d8d0000000000000000000000000000000005df0788ec39430fcd0625f8e030d917d8e7c251ee6e3b0e79fc6fa5f6fac2ad736c818bd833e58ec61cfdff52c9c6ee2c36204b6a005a64819b06804eb94c311d78977b557e7acfa82e147b4d6ec62f0000000000000000000000000000000000922d8b5db6e415aa3acbd0d6065db1b492c92313260019ef1bda0fa091c4bf091de95846af1edb34516b1abf7d278e0000000000000000000000000000000019af4ecc4f278315ed90d67cf4d22ed6fc9af5c0d0ca654f6a74a3c4bc98588bf5347b4536f36ca8b4750c18464f9b7b00000000000000000000000000000000021eaceb11638bda8b4293991983f11cc60c1daa2287f4b4a6066374bac82d117ac3ea4ec73afc4372d254bfc433b8c3000000000000000000000000000000001037fe26a10305cc5dc11a65edc705be5a0082656cad53e63038ee57a79e16075df54331233229a129483c34d6dd92ec9160c5a553479a10996704c3eda8e57be88eaaf5d1efc8371e7e10d7d106e4810000000000000000000000000000000011e63dc251a5a1e2ec83741682d90588b6b185365b33dba45458b1f56324a4900b04d61af155a0edb0bdc2971b7aaa210000000000000000000000000000000002dc1bd5448a2ebb9a02509af8777616ba9657bd3be65519233f0187df77c49fc931bbd3ec0ad5856b2ec0dfde476a870000000000000000000000000000000019f0cf8baf100451313711bbb0a0fa318c14224933897e74fb727b585cc8620b7d741c9ca2f0d3cbe14a8749aa48ef3e0000000000000000000000000000000018448fa9e05f87d4991ae1c248413edc9a8c3ee789c9c005e691bfc9003191ff469e26db9e42e5758fac79309a62942c5e5a50e5dbabb7a56897935683f80a5b16dbef3c23461e241fbdfceea38e3ee200000000000000000000000000000000109b71c19cd36ef3078bbae25ce6d0e8f7b58e129407fe68ab09aa747bfb3e90c04ab804fa6b7a223c172146fdb14683000000000000000000000000000000000d297750ba112da88beb84b8bbf74ed134b59fc9496da3045aa6dbcd97c68425fd68b75508de113733602a5565f4c8a600000000000000000000000000000000149b8ba6e05b66d07b353f46ace4e583bb61ed18fdbcea0e941b8d9805d3168040186d1c961add494f98e4e7fe68824d0000000000000000000000000000000013a6877bd46557d23b9aaf371ee5a101227d7938c64503b04b39cc6cb4e8ddedcf5cb6865439c9f8b1bfebb807ce52e24a95b293daa2761cc456b9667517f499c4d9eb9eb1d82237e7a7819b5d44f7a200000000000000000000000000000000073f440c2704fae6c86aca3cee34591ec03c362c2c5153a5e82c7bcdece2af0c58a3484b448c8bf4da851800ead959df00000000000000000000000000000000075a2c26372b482a2420bd3c9952fdbf9e5fea906dc8a4deb9691f8745372805bacd68a4838a3fefc381a2ce946ed1780000000000000000000000000000000017575b016435782cd09901afd2ea6773b11f5a983bdd19d14668d75362f95d055b76e5bf6966b1bd7bfdfbe9a939e4b60000000000000000000000000000000001569d74258298fac89d0d91a9945780f4c08d7af7b942d06255ae590db6e8509c908c16bd2c2bb634279debb72f489b5e22ef32d111261dfcb5a2e8d23c8d920f013bd9602bbef45e6d4e0909abdef20000000000000000000000000000000017180e36b925e2ce23c46813d96b919ca181481efb5d1666c4a4e9c8031abdd9521eb8228c4e3f16de0b33da4c73588e00000000000000000000000000000000138965bff7c573546d80ef7efb3d45e87ed20f59adb0cd7ae148d09a97da7feaf1b0ef2455ca19381762768a7d82f486000000000000000000000000000000000360bd29c3f07c5b560e2ac226112a628839da9db18b052991eb2d9c54541c1b5ade9b3c2d7f446ad50050531228120f0000000000000000000000000000000007105978bcf13bbe2bf5c8f7d165998c3ad99b6a2794c90f5b61fb7bf2472d307df8fc9f4afe7ae1e40e7f0eee8ef9466e687c0ac8fab70de2416642afa1553bb38183d2914050602874491057f78786000000000000000000000000000000000f4434c5180ad10cd45dca62b8da790cdb912c255c0f33950f7039e3885b38fa9e9297c7b0a875380545839d8c4d4ada000000000000000000000000000000000d0dd1429e512884ac209f788b5832d31649a78a8966d3348a93f841be23c8e4e42d6ff0d6c27e8f43daf495c9582935000000000000000000000000000000001307377f55dfed30ac1a406671af1895218a01d063b025d25bdbc53f5f9d535e4cd8053c09b2cebb25d3a08365ab8ccb0000000000000000000000000000000004f5c06f505ed15aa7661249b7edd71855bbf47237e049aa951e1ea3ff88f98591518bac975ac628e417892f8e9e5523428f1a27ea15135f044643dc36a3f9c2b4446a3136bb11f696b0a430a7454b3f00000000000000000000000000000000083336fa0b79691b4875ed27b2bbd2d2586992940356f6ae5ddd2021c5ddd87f07f0a5c1e8d8a2654b99182cc2233e84000000000000000000000000000000001880f3824f7cef95ae5743de2e17191848d8d30f0469f455461c6559ebc75a7afbc86dfa3ee17f5470f74018ec335edd0000000000000000000000000000000007c2b26353e86223e5dbd4ed6d59f1170b9cc9dc600fdfbc6c73b96f2c667a82128b1ae5af0542b11a7d1efae87c75610000000000000000000000000000000002427b7eeb497a20cf15c10513cadc9ea612f3ae94e2ae833d281734e7b5d1d50e240659ac01da7864a95b4cdcf88744ae21ad8a6c9d75b51133e81ec34d66ca70a52529c5c3a2307b0e8d6f1c5e7d97000000000000000000000000000000000e72845430ebfb84f8e3cd3dd418f6dc528bf521aca4f9dbd798ed903ef0ea3cf21dd1409aa3759351be32b21d8e8cbd000000000000000000000000000000001457ad87f0957006192dff7d99815c35adb3635815e5d157542b9f52f1e9f8c0143a21a3be4dc1aea3a895689f4a316f0000000000000000000000000000000007e8544b1037ece2e5a9ea387e0f43b72e895e9c2ca4d205f12bf6df0b35ae62a4d62756221d6fff65b928b7358f48b00000000000000000000000000000000012c5c3167f6ef118c4044c0aafc85a337d305437d694a7bd6fb406dabb7364d9e90d74a8b327aba971421a5b3dd5d06988a23b118179ee2c34ad030993a2d2d70375311b95254c44254a32508abcb612000000000000000000000000000000001995d7cb79da7b6c5a0c8ccc5ba075d8d6d8ed3cfca85e8ecdd2b589986fa58c4cd4f045983e9184d79173678d618f310000000000000000000000000000000000f9f7f6bcff0f6fd621f3f8fcfebac132b3f0d52a34af33bb9830bd714d2982f3cc6674ad6ca668131a5062e5589df90000000000000000000000000000000017699b298a46829020e0299ab89ab6411af0a602dffb0e149053ff40ccaec71a908da02c8e611723cd06c16a8e5c0f2d000000000000000000000000000000000523b287383c1e47a6f31d397359941fe0bb8167aa11604ff8569969eb5ccddf4c4f432d2b6fe6f39204020e850d4f2b30eac099ededf0087275d1af828bbf79ef7fb0e77179a068f2ebfe4c749a98c90000000000000000000000000000000004760120239593cae5bdec813735ccc99a88129c707686cf43efbd48fb08d8da3086879a6042bf118879fcccce0736bc00000000000000000000000000000000105b8191431f701b365c66680cb4eb267681ee4da17ba55d47cf26d21ba1c0c3eeeabcafcc79dd87b6457bcc91e9fec600000000000000000000000000000000126ab502f66e732aabe02fdb2f7a665a9a43f6b4ff21c22fa976e7e434b08b606e9cf0f02459fd85f5a80a332fb3a62e000000000000000000000000000000000b2ef01adea6c00250f2f14c98ec6d6083c45019f3d166419e3a137667324f80c34b6b72e991daf72e2eaf9985d0f9287e8dcbf708682225fe3f71b7a687da23de5ed188e40585be0553358012132577000000000000000000000000000000000ff22a0db4f1b1679bde5853a7c2932501f191f4a9f25eed968a796219cef028e26070851a9036a05a04abd73bd6bd4e00000000000000000000000000000000097e9310749f52a4b645190069f4d52315f0eb2ff9cbbcd31f1781a68b2664bbbf27166e6e74fc2be2e5b1eb3f3d77a00000000000000000000000000000000015ca218d7d128095bd4f4b4f7bcf7666e92b905e551dd22745bc743ad0783b6ac44b841f87d3deac44617a7c9a341c55000000000000000000000000000000000a1cb723a4c378e5db2775f4dde9a6887ee3313401a64130a78b90d65dda3a5d9c8bcbc1a0d78c310c869a7fc4889954532cd42a9b698a2c2d22b1a620a7ec60daa9d1eb8ac36894603be7bb9b5e37be0000000000000000000000000000000018b30cc461a4e1fbefe209a709a21ae201bc6094b2d15f0d6dee5a55dd84ef56b62ab1b6bd513b27c84c638291f4205a0000000000000000000000000000000008a6f2082d6d510b280a270c09044ad31fb18b851ad2b38859138c9c2e4870fba6b607f682a798bf21a13bff116014d200000000000000000000000000000000150ef352d494a97d0a7ffe44903aba1611c8d81fa2788c0f42a6db48a71101e12f07318da5ceb1f0af3aa10cd4c26341000000000000000000000000000000000ffdf3b133cc926684e4624531569bfa09b1658e29ad9c3efbd5e9d18353ffbbfbf23a2ad80ccee88f8fa597416d47173ccd5e19892765e549a63238e664c732af781fddea558a117cb927bc4a1aceb5",
+ "Expected": "00000000000000000000000000000000134f45e5409998e657923ca76ce92b7d2acc932308e0694bb22f121f8324d16bfce86f96c67111c8080289eada4b4fb40000000000000000000000000000000008d9063b7845ffc8400c0b7585e819043884f92e28f7e3ffa47a39e808cdbb034ef4230b6e19bebf083e939b6b686b0b000000000000000000000000000000000e95f8fcd6b5bcc9e00a580a99627d92fa7486ff5ea587df5dded24d1b0bb76d339f6765a5a2058a8e227f633ce36e91000000000000000000000000000000000393041eb33f2c63df3f40d8ea1e1a9eaa9eb0a46151294845e542054d503ef69b40b0b676b0e4f3e08f4d26c36a5d4b",
+ "Name": "matter_g2_multiexp_48",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000042a220276f12fb4e81c40ecef3a0d86634b4d1c0acfdc463df4e7501289f0be385e03808d44be053e6ac98f403a8a930000000000000000000000000000000004e3dc92e155aeebdfccaaa1d24f49efc8b02e4d9ba8500a5b953a96e0fdd58519bbf1c279750eb8b98616e6bb9a3f6d00000000000000000000000000000000086bc212a83b09c7361540349767896058d5567d4342c607ae9c07fe5f123d9aaac95ded6cdff0825edb5acbce3e2b6d00000000000000000000000000000000062598cd6d5680a155b6349cd51d636c1350746d17fe0fff5195f164ba2fa51cf52f8662f43d555f7be6bb8bcacca39448da17551b2369b723bf932173a9167663f8389d2461b763d6a061df78d7ff1c00000000000000000000000000000000193e2c749e5bbe87dd5c306d822740969cd69ad6e156c323d217c08b18bb3f97c85aad63aed1e3a455ffa1b6d2a670340000000000000000000000000000000012a3dce63a88ae32a746e3812833569959021e1dd9518621793308f8f11d04829b2c3d0e0ec39fc48dfb8285b6852746000000000000000000000000000000001235488d01c380e91872fc57cbf618c3531a6bbf6cba9dddb9f07168cd459c9e866e44e9e5336369cffd8cc3a36cddc00000000000000000000000000000000010d85f85d6242b63f8421e92f1c37f64d33fed67e0cd3dc4b2b2cb4a7fc7637f9e049fc959720eae6d1f452159d48b78def52379c8b9e7c24d971c3456b85b51a63ab03761ec66c8dfac1018833e05940000000000000000000000000000000010889825c752d0ae8445a1d0f3510135b9672c30a781788698f637c2f535e35788d76492edce8ea091223d016b5cc141000000000000000000000000000000000577175035c86c022e634ccc9a5beb96a36aa068cdc36e5a4fc2028d5dd099c5296d30a916d3b720f2e051e7d72e4d490000000000000000000000000000000017b46e49ba08a0abb9394479d693d8097a140094d0ef1d1ba7761fb601a686b0b2b4d49abc2e393a99c5cb760299992b000000000000000000000000000000000820f8e52c1b09986a70bff04909b044f671c3933de43a6bdfcbe3712310274ed880d7adc4947490c7de095ea651e578b2225be6985b9c8fa59a2890da56427612a4334937761e24a33d37f0f951a794000000000000000000000000000000001776b92f683069fdc006904fef8e91f716d9f6bc46306b042228088545f0e11a41b40b60722d4f0483250391febc0ed90000000000000000000000000000000010d5052ef2504115e9d9d4ca81c7080c0868cbed605dc7673f7f94f5959c793c96aa5334175e58499102ff76f974ced80000000000000000000000000000000011d1e719bb69d842df4fc23e8dc4393067d00f6fa8ee42d89b462a546414b91f68dda5378fa093b3ffa764b5fc63b1aa00000000000000000000000000000000099d0784a200e5d2d38773912cf1a49e813c871ede8c50da03abff58ec1943d2adefe66bd2feed1c57f5a80253e091d0a64ce8ad619276bc7a00cb49faf6cc84b917ae6b37654363f5719a727a220291000000000000000000000000000000000d7287adbe0bc3cbb35ab8bfe69064faa83e3e64d73a0c64d960949e10070081a99c35d1dacea5a3b9bf312745acd6e600000000000000000000000000000000034f1995eb8631e080378b22a51ace902ebc9da4589c89ab557b6aaf685fcc74ec1fcf95f6b9a31b7a45cfc5a1610c640000000000000000000000000000000009f56712a46c0fbc199c12d5eb7abd60e660e2c6d437007c34954c6234a0496ad0adf68cf759f8ea30980c9a78175e1a00000000000000000000000000000000073fae1cb78c776188190a4d7223f7cdce9a36488193dc06898919ef4d5136099c3185d352028760c753e9eebb52ac240b891d638d7e76e0dcb230b1f9a7c3b35b35193c43a6c86f345f5a5bc9c708f500000000000000000000000000000000019944fc459fb601bddf10a3a7eb55f34713d396c3208a10089b8f21f4bf0a5e87e95ccf73e0bd90474d3e043f37a72300000000000000000000000000000000158445bd2b6d396a390a0bd5e26256587f980eae84d7a592b2b4d788c452d312b854427185a770084e1b4c7898962e50000000000000000000000000000000000ba44a1b912645354da7d8d9c694b1d5a9ff2d642fad31975171deef3adb0f8d92b2d3a8bef6ecbe0b8e90470b3938d00000000000000000000000000000000012a040a72ab035684bfdf57bf473ff59cd1ee01ec949dcc6066e5c8afad775ed55123859cdd74c7016a092bade7f991b571175eb91888222085fc2dfe0f4401ed6a1fc5df86c0c6b8e44fba6454305bf000000000000000000000000000000000317ca8fdec8c7c56fa3812157f9ca8e9bbf91013dfc7052c0795a04a1b4649b2147d9cb1a61f2c114a705e5133729920000000000000000000000000000000012b893d50fe5ea2eb528d1a04bc8596b10d4714a0dc38bdd5f0a275c07c846970106c3f7b5686685f5c809e93c57e2ff0000000000000000000000000000000014f018a0d13c4c494f4a6b7e836f0f2f46c4b7975d91adb93616a0555910f53574add03b905000f8492465c9b5488c1300000000000000000000000000000000146eb4ef1103b525dfb5c31bcb98e550245732fa252a814824258093a2397d1489df8ca0228d4f5df0a00d473d1566c454c9e7f7ca14c66b8431e25e6eddb4f20507d03bf124eb607957ca2f43a0c17b0000000000000000000000000000000010e9962dc19aae8e92abf32fb9c8eac44d77f587159af4e3b3a080748322715a958d953d3c057999839a47dcc840076a000000000000000000000000000000000ccafa9761e654ba54a46afff51384f1c6331264082e23f94fffd6c31a1b1b568a391eac79417657f40ce2fc9a154a670000000000000000000000000000000007276b111c94130b2608827156021815faf2be29ae42c454f3e2f95de98d2f5b98cea3eb18335a8fa00e5464f8089cf300000000000000000000000000000000053550896e867e237086098f4493caa2520e8c97a05e14d0ab7012d37b7fbbd42a90accbf0fe2ac99e78ccf0be5c9c58000579e1ad83015c8f02a9db5c38d0220368a80b309ee45bb952cac824817b6b0000000000000000000000000000000016b5bca8537059362147911da9e69ad3ecd3b4a7c43ee7d6d809f46c74c16bc7d69bfb5d7c727b4d5d8a356a0458b59e0000000000000000000000000000000010f3a7eefeb3033a733af7d20c3c5caff4c409305de8d71e08cb9cefbdfacda41bb975c92c5e5f2952c3c1e2bc6ca8cc00000000000000000000000000000000148f5b2bd65b71184ba6974678f709c5f9e3f1a020e3d4bedfa5f5f66478adac47f06ca2626c4a759b5eae09756cfe49000000000000000000000000000000001301306d1259059b5567154ef6e4779fedf98c29ea967ce34b78147c5730f202e1c12d5b5094219bf85fa62834329b45909a45c8b78350e3ca21697e9f56d5fc8fc2a01817b78a7f5daeda487768ed1e000000000000000000000000000000001741f739459f5d462fc9ab55c68101a5a3f2741c05b4c3eec6959b2aa5e12493a19d1b33a9aa89337add642458089eb6000000000000000000000000000000000300d8b7988522706c0690da52d0a67ae41344e43cfa05d22feb91eb8635bdb970810e993e0ebf8fd63ab8fe3e048d660000000000000000000000000000000007c003cfba125692b88feba85e7288bf61bb25e04b1462f7a39b4198737010224ce4b73a320c81b1f70119af34d381d1000000000000000000000000000000000a4870c9de67517f4353de23af21fcfadcfce55365ced33a61a19e5de52f98721b17c6eb382970e7c4acd81b80a7bd2f6d4e2277da617f0ad530b6209df6264e1288122b1b4d92da04fe334be17bd8320000000000000000000000000000000002eef52fc72d5aa0456c13808ba548cb765e11cd0bfd0599544793f57c8a27ee90880e6577af1b76b3fe32c4e71f4104000000000000000000000000000000000ea99a4f6772f8114cfb3ae9dc20f11a34880a86088511e5b7fe521d50470148b43f866eb5bf4f67c523266bb55117050000000000000000000000000000000004bd802b889e6d18df7dbd65f39a908cf5889e14be51b5ebd423ccb63e4e5b35e429eb0d4f384b811b47975143ea2ef60000000000000000000000000000000018dded357c546d709beffff2da0c08e8059c720023234c7b53d0ae85750b3e166cde7faf340697b546b8dd7c13b1ce7bdcba6bed6b8c42240c01df5fa0ea81dd96168c6d98ee9d5d4653edfa5172eb28000000000000000000000000000000001405ef521bcc60c55f8551fb2e2aa7b10117b2f96c03e8535e5bff48ae197b7e5fe69a40eecd25a67f430ca02edcc9d2000000000000000000000000000000000477d85a7dfffcc5a2a1048205362ec42b268e5fbd27ee7c8d4ca77b5c9db84dba482bc4b164f92db2c15cc518b3d32800000000000000000000000000000000060988548ede00aad3682fe827d1e993ed1cf118bec7cbe6f69bc160f030bf87c299d40047a4fb5ee27dc2814649a4580000000000000000000000000000000006b9e0579f82fcb8bc149e40b1199f5897ea48ae5eb58abd2002c923efd0f5275d24a579bd904e49b7447c4a03e3fbe423d168e01657e5c2da89a27e513bcbc6620b8c6082bd39880619bfe2b3a7317d0000000000000000000000000000000003cde2bfc5a865cac624d9018c37c1b5746b5394597d79c171b25f84d5fdbc76bb90ba5cf9db14b3b8e62ff91cfd79520000000000000000000000000000000017596885262075e45db62ca68ee5b99d12223bd476e36ed4ddbf5cd56a0c6e9db5d79e7f95b96b1bc323d7c9fc5447d800000000000000000000000000000000018333858871dd41cddb7ad2f179f1f341b2ef20bfc7a1d3cb235e3a1a181e0da7251911886f0788e0f868e16520c5a200000000000000000000000000000000098ce44092980cb14e89faa7efc2906051c9a51cf7b2757dbffa49fafa3a9ba145f809f1212c27aa620bf062e839f83c2a76fafc5e8e33852bbeb7ab8229305be84f5474427e0c6d2ed35c7bfe99faa1000000000000000000000000000000001180d554fd523a51e0decb92e0134c6064a17dd3aa7b11d590b9b6022f76763b1e20562da21e836e65374efafd78b77e000000000000000000000000000000000488686f793dde899a3f4936f07f9eda7918450966ca85b4715d6fee978d9d091bae1b5d2d04943365c076a849b3359c0000000000000000000000000000000014661fb2d305ec9e63d63e9951d0f081aeba99972b094c922d2797a1100759cfe150812821411205f563e22f01ef29c50000000000000000000000000000000013dd681200608466853cd3bfd20f146a6383151931079654962684d6c6fc3bd6900bb049483c1ca6d2819da456f67e3be3c7e4e95167faed1391e269785918a207490c6d186bf2537c02e52e414d564e0000000000000000000000000000000016c8c7a2a1a76ec05770f2d6c8df35003104c034c76323fedd49663daa759caf2f4fefbe8d44b3abf1dadfec2a06cb45000000000000000000000000000000000837305004aba2e322ae29e8f0109f1c756a44b21c72733019e63ff9886a639464090770d12d35553f0002ad028332370000000000000000000000000000000005c8f82ca2d4f6785e2d76ca3a3d1ac67aedf78e9ac833c52cfda6289e6f5d7a83befbeaf753abce12376889caec312f0000000000000000000000000000000013595cdc9181ca70845c613663367ff774f073774688dc58edfd0c58de5ae12df5acd04a673b645371940d7f7e1601045d335e3d96a9b25be7f3916e92fffd75abeef5b91a1ec577ced52a96f6a9b10c0000000000000000000000000000000010f1b8b39ea8ffcb6a96bacd1c00b413c93d3f8da64dcf9257a7cf0264831be23ca63ab8d3d1cea21ed8d83ecaa3a0c70000000000000000000000000000000017a9030fbee573cb71330007900723f85e9e82530283f713f72e68c1d9a5ff9552d0da469a4f38b66e30df1514f922a40000000000000000000000000000000018b9020986a49213d4f3b4b052cf2fb65f82b9bc2051f20b399f2784b984ccfa2752ca576d352c7d65ab218bb8d5df870000000000000000000000000000000015a375a3711f5e9f85ad7266b2d307cac09ace9ea36e149dde5e0d5acdbac3f62e1cecba8be51d88f2143c3070eddaf0fa563a70780837ffcf9a84456f0b4f6eda0d60cce6a8538ba10960eaf17362fc",
+ "Expected": "000000000000000000000000000000000b668f602b9f56182b74be413d36b03d2266d7165386a7f1f0d25d336d06d2bc5659e80e54dc71f153883292df1cd8940000000000000000000000000000000013151d305bba39734538fe9a2717392bcd134ef1f8c1879740c8cce981a2d70c94b23f1a71a0596e7ead55a55eb186c80000000000000000000000000000000000e5e7c268f93d8a9d3ce45db2a95be906483aefa3831ed2ab2aa357eca0ca231927c0e5031daa200784cba33b96e51d0000000000000000000000000000000011d57d9a9123123f9fb56e990626346e5c76bbd1a4b3349c3f7bc44f05a899f9c4dddd67ce5a788f85b4fb172385faef",
+ "Name": "matter_g2_multiexp_49",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006a7946b50749147573991c91f13cdef4e9558be37736e3d990c5750d31ba9711721b88eec529ea4b1dec1c935fafa9a00000000000000000000000000000000078d8a565b7f58b915c220882a73b6aaf100f2d54cce2524cc3a80d9b526c3058903668d17427a617ea045c3322ec502000000000000000000000000000000000733c6562cdcb28d740c64f50ee9d204af4ecc8de2c1719fb73c20f2580fcf01e1e494faf4386764e03920a4162049fb000000000000000000000000000000000421365fa828affe963d145d318065933d4d865f2a3d24469ab0db66dd09a574945f8a8b622d079a7ce1c6fb6c795a8f6e2ee781da12b984e7a08730a60f50c41cdd7c7c8b3f1f30f721923ddc34fb79000000000000000000000000000000000a4fdc68bda287bd819ebb0a296212ddd19cc76b042e134f1637c894ad64bcd8431392c9791f2eaaf94f6c8d189846760000000000000000000000000000000009d974fcb46fe81d81d62b24b805ab5108c9450e162454c3260ecd0d5356b7c263be5f78f6214cc7254e461166910d23000000000000000000000000000000001081fe3579cb4d8a7e7d43ca8cdda28e1f9ea8df83c6069f4162a2a0e68e0d5876b283193649018e754c5c8fef101f53000000000000000000000000000000000ca4faaddc4d14a6648e3515a8b9028190c17f771c7de086fe4624a3008d7e6e374c967f303d9511b9da1a95409e3cb3d51e0b65be993ddd2892ab8f47eab78352b177be4b3fb68f47c65f5c59fa866000000000000000000000000000000000117318e376f2c130e5bca89b3d700fe76e9603adb22a5ef353bb3b5a8f641c85deb4640fbaccf94e025a59fbf2a41370000000000000000000000000000000000433428497ed89a43ba07d816df224809a827194ca899924c3844650a3800952cda8db82f2f8e513994ed9893fac747400000000000000000000000000000000064889f1cb7d6ab216fcceef7c4abf89be14ef93be2d39bbba2b74d06999dec5ae1941b507709d093b28e030700cf866000000000000000000000000000000000957fcb8658497802e78b8250373f77acc4ec47fa2c87e78adbb2daef70240da640a7945895940f76bbb80bd36b4ba24fed4dd284df98923bfc3c41496d6e64a10815a8c474275e0cdbc9ed26e92b0ae0000000000000000000000000000000013f9771c105462fb6b975b0b2fd20d0accdd2d95d879c8019b08db394cd785ed9f151d0eb1adeaa63bbc2686d1172b0f0000000000000000000000000000000002062a5f2db0a01114a1c6e8c739f80f598f4e905952101a244853078298eb443be6839b59d4f0c7745b739cc89ad8220000000000000000000000000000000015b5485439f1b94fbb3a8f5ac6197f0dc0577863f39c44b34d4c5437b6a82a704dec17529654b3037a9ee1ebf14c8d8300000000000000000000000000000000154d750e2a660205812d428cfe79aef4e1059f4e231024a665889d112af37e6e17e04cd7c926b6240bf2f616a1f572dd7c36ec97c1eafc8a20a772fb7887d75568047ea32458b9ce74ad9ca058129949000000000000000000000000000000000231223930956bd2d36a89a0a0a47aa46b4763919455ad3a3581439d25a82c176569698fd5ca2b9429793ebb16c98e50000000000000000000000000000000000b5dd675af51c18d2dc76e3103da4409f6e8c1cc719a622d4a33aaae3f23e529c78b63c55b67fa999bdcc7095a4ece300000000000000000000000000000000010c971be55cd02e4c97031d3b25acfbf722e47e5179beb26eafaa72d4bd5f47cf280a99e0c3c4cdac05bf1572d01fcfc0000000000000000000000000000000002c1370919e6445994df1e25ff4a79c8cd8805f12e5d8c781e58f04dff68a97424b35d162d875ca2b3f805b4cd6d1fa641b2c0354d2f7d92b05043f193b718d78b457ae76e19069c8e1c2b77d7999d6500000000000000000000000000000000169938b4d3c859f97a0627bd1a83fde725eafb7ab77b22cae06d2a776569236d834702081e78d61386999c938c0259b900000000000000000000000000000000091e922f00828488e324f9fea652ce1edff83d9f479e843ed4bffee27805a5025e7a150719b354b5e61f381ebd24d4ea000000000000000000000000000000000334ba8044d7d47795b59eb089502808a7ab8f18e3d5e1cc49acdb5020b3973fd21d6d82557afd748dad88e45a7623730000000000000000000000000000000002299bf949ef249b5057c103ecd149444635b4f636a2fd0d073484404c1ff4ef71820260ea6529bee6f5b07f2ba94de35615370a76bb0a5f64d61b97bdb045b9669f6a0b7644b101d21a50483d8b04dc00000000000000000000000000000000076ab7838db87727fd653a3b561a2a5594518f296284bc24a7d215b1fbc0a6492d425078fd98f92a414dfcb3c92cc1d000000000000000000000000000000000022b71fb467dbd6d9b130763350bd06f52d20ff2cbd46cdea5e8b1525fd73bfd08f5ff171f9fa28050e9a3b296d3e9e00000000000000000000000000000000007e917cef0195fc589317d4a71c14022867dbc0db26c653052e2e382d0dbebe67a0f582bc0a27dd1dfb4703c545d0da30000000000000000000000000000000005b1d8651b86a403ad993c5cea4b6b82a0f8a9f8a59d4b94f10e68e9538a559efdde2007736aa9d04f585851a89af88fbcc38cfd3c6bdd32ed1d583f2bd14e175d61448c627f195559b751aab1ecf7cb000000000000000000000000000000000653c5f5b2d97239821d173036929dc716e78d835a80af55868dcc3e218bcebdc2a052d31f6a573572d13f3bbb14f241000000000000000000000000000000000cdbdc3cf52239a6d4bdadc273b00924de8730c03ea82bd20ec1f04375daa4497fff3a1726269a736706355e72be83870000000000000000000000000000000008e0285b177fcd768d3519062177fa1314c4370f872eaf10f3e0dc94e716dc6a67894d887f40104552336cbb5ed614f20000000000000000000000000000000000638db8269ea4c2fecd5b45955609ef6a1c2c6faf6ee5a8d777e0b38f16d1acab2da7fe7b6f6ebb315ccb345835a21d94c41471a2e4edf0f688c2f032036d41ef5f8a966871dd099dcdbced8b37e1c40000000000000000000000000000000005b4f74cd099eafa6ae59e7105873d4a46e8e5985faf2d26ca564125dca93b1c48187ed7afa02cde8b52df878e1aa618000000000000000000000000000000000cda7f9eeadda16ef757ee8a98be147d374d3a1d40790d20a1ae42c9ed38e4fe22be76ec4f807cf93fff5c6efdb50d1c00000000000000000000000000000000121219b0b0d236a89a857c02249cc04c22299d041d95296dd235b3639416337f5be4a2ebe92a50d192fb748d5d4dca0300000000000000000000000000000000112545a4677ca7d60645cb8bd98689c4aa85a68bb62dc68c0affca5a17ecf0a08fb9b91589d08712b5af4aadf31caad2dd297b192f1c907914ef949fd27a5ea5659aab659b83239c4433f7a4e24529f2000000000000000000000000000000001342460712b73ca0ef07d953c32d280a3441e108abdc2d133265160608986481df3563c5dca20f209ce078b13b49707e0000000000000000000000000000000003580a5b4a7f6d6e066ad9073f7105f6cc1ff35ef5e79a0aba7f48ff2b732c7aec72cc9c5f9233fc9c267d8aa37ac17c000000000000000000000000000000000bb7f32db8a4e341cd9f8dd3b5677dc650cef675f0923bf2e5c8b84c33d447daacbf68631c2388eac5698495e1ad5a3a0000000000000000000000000000000015bf9cd1aa585eda2910128f2b452569abc1c94bc8bd308ee92b6c7315a56fc92d6cba03334bc36c137c14eb1f198b07d30fdb174a3f5c06b78cbaee5b6e7a4c90551083d78c5164de6bb45ee5de23c100000000000000000000000000000000091bca266255d692cdfd10929802d79b474706d160033495decd11cb0758136ec3ae7fd4bb99081e44dd7f25224e009c0000000000000000000000000000000001fbba1ba796416ac22c92f3741e3b268d89fbf0307edf0f25c7c12b5cd230c41582ba69465686ffead9f8363dc0c297000000000000000000000000000000001139590315fc4d81e3e747a53e63ad856635050367ffc143c1422e324d5fe9e4fb90631ff8bba764a87b8077b571aa0a000000000000000000000000000000000dcbba28afd445a57db762d08338a26980b4efbd11668e4050d18234ce35a909d6b563a5d3e8e72892514431fabf0147aafc42f7fe6854866cb954367fa65c8072bd1b60173a2d45077421d6e25f2bb3000000000000000000000000000000001322b1f1388a9dd2853829bda1a5120250ed08f07c84fa398e59fa2577454f38f0a76a1e8db897bf15b4b50ff52a847c0000000000000000000000000000000017020d7de1dd424de53992c168d924c42f26231d184ea3cd9cfe64ad9c82ad067540b2d9ab18b0fd28477ac792a80c4a0000000000000000000000000000000000fabc0769b95e6feedc2165bd6d324b7d16247b79eebc1f09d849792255136538e628bd6ad9b86af7bcdfdd991fc31000000000000000000000000000000000144f39f792bf5585f4b49dcd3fcdbb61cc7ef471e08af4c15cfebb855f0ac8d5fd057c9486e53e8e1ee4f66bd5e943ad106da5f98d5e7cd9f4a1c8d6e50ea2236c2abdf1e08a0eca54555a59bcadbc6a000000000000000000000000000000000c27ac29db98fe3038fe5f537d5ca6faa240602abe11c6f530d9b18d763d6dda3fb25f9538d316e6527c114405ae54f00000000000000000000000000000000017ecc872183413d8065a99a2d1a73b70150e2c1fca2c13a731a39b52aebc6db79772e91f115a63f7b23e5fa231df697a0000000000000000000000000000000016b9715ce820b619274202b52d7e7bee9a17aaeb06c2ecab8bc77c670bd4c714789e4478178d94d2aad57e7bb0b7a4040000000000000000000000000000000002d0723a3386248d8597d2b63289300de6a16011a38985170a1652ff81ea70a78459b3ef252cc5ed26ff1ef1ecaf6a42c971deeba2f757970bcd4f5548a2767bd6c43e63f4c5fc4b157ef060a1f45aae000000000000000000000000000000000eb1ddb7306d8d2858fb57dac71f67473b813f37f02d73b17f375be86028176cc1dd84347f183cb7d427b861be34c3d70000000000000000000000000000000009a8811ec77eb21f2b33a591f2fe6d7b74b40c5045ceeee275912aeec664838f332bb49bedcd958ede0af0d0232e76ed00000000000000000000000000000000156e28ee3c40c6f18c6059e06ac8f7b39fa23e5962f640ef3afce13c169346a4c8e5c2bcdac8fa15921a4740cc5a0f2300000000000000000000000000000000084371522a6ebb1925c8fad3f20277c34e657aa71abf8ed7d323a10c14cbbb1a9e0e54bace32eb845e6709c1c58afc34a5262a021977dd79ab96606eb24a7c5ed650300dd68bc79f4b8378f58c6eed49000000000000000000000000000000000be2ef9ef38a5dcb42ad31b1415c8eceae625850db4306a26a0598d4a567936d75b701c81793fa7b42d158df2dcb0d5d000000000000000000000000000000000851b82b59fc15b89e33fb618c56d11a07116ea35850583a07066ed97b8a864f3766c0cf921d007a6cb43931ad4fcf8e000000000000000000000000000000000ea8bdfa3c5f000d7cb1b5cd69537e4104daa15ffcec06f40a91b972d8011e5fccfa911c55a07383cce6760c145c39e4000000000000000000000000000000000652a4165602978004ef702103ef18e8fe7decab1522a76486c742d29103e3bdf6dda2d3cd64ff1b5d5a76f4823bd363083b3720c20044fa41712039b6e9e776197391ef393c0935a0e9990fbc1b7a4600000000000000000000000000000000015ce5b43e1fd950b77e2baccae8c99b82f38bce09989fdc5d402420e7931a38b7fdac5a254b0cb9bd8fbb488d02493b00000000000000000000000000000000018c5b3ff46a04ed114bbf56399738e5d594ef8dd1d5e2e8dc23a0097893be3da4fa4662686a6dac04418fd2d344e36c000000000000000000000000000000000efa3e970a5cd0c7bdef6a2df3be9be18cce63c10c331a18d628bbeef30488ef73d866f3c8804acb3bd375542e99eae6000000000000000000000000000000000e966d9e2f2d47df5d661a89fafb6d4518fa1544ab7a56716df511cbcca99098f944a981c9da569cf95debb455842006d6f846581848f5dbb9e8d220b881d0327c4f3f5d4b79fb2c4dcbdb9bcf44b02d",
+ "Expected": "000000000000000000000000000000000ef06b515addb951b24e5d61f6e6eededf5f93f9f17455e1b563f187f73394457b3b7c1b90ed454218f8782d2bc848be00000000000000000000000000000000167398608a87490fd17506166bf54636aa4dd6d3e8c4d42995bcb0262268eaf2a6d828b295434f45e3e53703aa67cdcf000000000000000000000000000000001602ec6519e4987a052f97eb222f505e241d99602c08ea9c41bc95796675ebf6a819aa0bf87319f29dfe47f45f3c8c7a0000000000000000000000000000000002ad4291ece7ea0fcc9f4440e88eef693b8dd53060ec847bd27d74cf71218eb6210a71895ff1f1f4537a901090f14de5",
+ "Name": "matter_g2_multiexp_50",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000129cc9cf82aa30671e969148f058a0b8d275bcbb1c8da66e52998d9555dfaa075e2fcf39fc18f305940fbc972cc5c0c0000000000000000000000000000000001252482c1419ad72229a00d90f1c09d464e896f47db91e9680efe36822e99e1ca7a2b5ba8b17b5929fdbeff8993bb18e000000000000000000000000000000001287d5054bf5db038ec2f7b7a3b79848fcc8ca42f9e19d5e21d36d2256f97e0edc2608d19c17d3714024e1e9e86ae264000000000000000000000000000000000f6262669e30a5db67550cdce8a4611b9501d02cd4e950aeedd1c87c4f0f63c74f35c802dafcf91c988a154dd690103c67c44f7c8513472b51f96d526422bac628aad4c40c521cd7cf9e86eaf92838fd0000000000000000000000000000000019cccd010df3e668b1c3ec053e76c46e45d01a4fe02eb074e296df2a48e0e4eb647b06c40cf64a0048a8fcc2b0cfa6100000000000000000000000000000000018e07bc50657f3bbf736c38518933e91af29e3bafd776243296cca3a1d975116e8b428b050045a61069adb23baa22d3800000000000000000000000000000000154f51badda1b828346986264b01fb1be4c7e9b570ab63a5eb15cabe9412a2f9bbc6d5111c638ff5118a4f6d08ed055200000000000000000000000000000000064d4e607a8994c0bb65770a14a14ed1b68c766ac2aed45a44c0f7c7cd4c3ecdfa077206812cf9b24e35021060a3668d2d6f95d4b6216e4226f78e4fa5011c9becf98fe45a17dfd740fdd0ef36d8ba94000000000000000000000000000000000b9bae5f720d9bd3271a71d751e4c35c39ad30fa8a67846107ff769c455e42465b2a39dfa32861634d5e323878f56f4f000000000000000000000000000000000a1077046cf5c7a66452cec2193ee21c1ace50dfd79f707c9297737f13806dc05e9e1cc5d1fb4c87b250ebea5a4ca6c40000000000000000000000000000000013e1fbe1a9b5f2ccff51120590ac0cb00cab502726b43a6fc12459e27bad4aa41537d6f3cc94a81a170998768f6a0fc6000000000000000000000000000000000a02c551ecec1c7a415256caaec1b5485a42f9ca8d897cf26546ace1f2bc8c2d10a353b8b84495b8dab5e3c60881185a58c25d36216b811ee42d0ba629ab7a0f9ce7edd7234620c28e37bb3df3f042e700000000000000000000000000000000021b9ab3ad614816d7006efe688e1ae8cd99b0c4437d4363e557642a7cfda2000db6503b32db36b6d1ffe40d967c5efd000000000000000000000000000000000b7fb0ddd9eb2be9cdffaf8f8c593a9296c4c7deeb1c714c11863d71dab1e6fd309b75c41e25de3cb6089726b43427f0000000000000000000000000000000001277065ea9d208777d0fb7a6726e11c8330f0b3ed3c6716acd559aab19b2fdafceca8126c9facc43b9d80534c07035a20000000000000000000000000000000015e8c12065d601dd5ede75bcfceb7300bf6f9fbcdf68d2f093b7654d80d3e565135d64137dc401d691a45fe052f58a6850a5c6bb6b87fbe5ebfb0d182d425ee173973c6f2085c556b0fe60219b9f3c32000000000000000000000000000000000484c4f9652427d0649c33e93d666dcb15bc56669c00980c53357ecee874bcdbaa016236df65a4339dfbd44e4eb0823c0000000000000000000000000000000013836a7275c29c989891c94e756cee9d6c54a8f634fa570655ee44b7c1e34137edc33323dc0d1f3a0218039fd6f7013d0000000000000000000000000000000002e88c7d5fd87e97a0de1be95021821942a8004115fb4fdd9ad26b7e0fd171f9c7e6f962eb179bdb95ef960cf9396372000000000000000000000000000000001636e351a0ed1a260ffe0d1355e6da288792fc97a7310b040cb9fcd5c550d85d90572154d58a9847dd5a8a06456bb2e43b4bdeaf6643ed159f4a3e23c33ac486b33e1edbc5a097a47a6c2c753e5299d20000000000000000000000000000000007579785c14fa012cb5d6c116d34dcc15dfc908a29e90de3bbfb8c9b44e0b4258644440d7c78d751a007c10f98053bd10000000000000000000000000000000009f023538822ceba0883a0e3454121dafe8e5e61d4754b54e6417c989efa998334641d458591b3076b615937de065cfd00000000000000000000000000000000130fe7f2d5e0ffefa67ad3378690c53a6e68de5504f3691de0df3a24c309619bd3a345bc2bec4dcfb4b77255cbfe09980000000000000000000000000000000015bf85ed997eef4d97a81f1d75825bb4409cf86b8c8e5f4368cf1e4c803f9e1e23a2a96f7b0a08e5cff55a78761ebce21d18596bc392dd0b71e1216bbb20a0e5e2559a46789c36a146cb78c5aa8e3921000000000000000000000000000000000a95597e4402bbd17c20dda088f0134d42f14443bd519b3511b28fd8d395a0e50758386498388ea6ad0e7634587336c1000000000000000000000000000000000079f348d3de505875c5192f795cd77e2f7385ed447b06f2dbee18e85c832386b201cb3eeb21aac3f258d2c4b0434d48000000000000000000000000000000001895b1891a08ea42eb1f68698abc20394ffd66bf0c32979668950bfec5cfc8425314eec2ac17ba25f29133a8becc9f5e00000000000000000000000000000000146160336d881b24c6258a3a86c08d346900680324632b6d5d4582ee0865a7e5f2d01677e5e49c5a4179f8382e49d1566fb3669c0789ba6a5b00f14c14fe2edd15d37a742c9e36cae9ac010e632d75a40000000000000000000000000000000013cadc6c394efb2f93e00f3976dde34efe75adff34bfb6f5e1a150b79bb5baf6bf29fa149581fda48faa68653cb61e300000000000000000000000000000000005fd25362d87f9581a202b186d2786d2859faa9966a1ceae747dd7a48749abd424eb9813e44caada0e456ee8bd12e99c0000000000000000000000000000000018e6b279e2b545acf1da29dc0504caa5982522546f83d4d3389e1fd6cb5328d4a167926a00ccaca402b3a3cdc67d757400000000000000000000000000000000089a9992a36b476fee21abd50977dfee01d7c91b24b3e26d7c15b2301352069dad920f0ea93a3e477a48029eef35605f06c2988dd6b8e9aa116eea4e1f63dacf100019844d37d163c047567e8e1188620000000000000000000000000000000005200b78dba7e423bc23e87c5937b464e97405f6461d05bd9d1d0fbf8f3c8e64a39081f9e43b4ec416198dc44db897e7000000000000000000000000000000000bdba1ed07c4a570359863a1098a73830818b3fa5b222316a3e0692a4ec65e59ca6b4bf5f72f8c1384e73e807d272d6e00000000000000000000000000000000073fa3eef473707b6aff37fb6f829f0fdb7ae808e85ebba4d4924a185c3656eb2856896307b671080347cebc32e958bf00000000000000000000000000000000076b56330f07cfc0ab34e98e2fa0ce4702b296a00f6ffee07c3ab523fadc048a047ccea7a9003c090951e4ef698d14e5fbf8322f706b1972f73fe4e22a3dad29c4ede09163561b2810cfc3eb2ffbc7ab0000000000000000000000000000000007252747c8275f87b21bbac4071c1826d166d14e6205095e5299315d6b6a85aed995f9ba59a2163ce2c51a8e60eaaeeb000000000000000000000000000000000460a000fe29cca24dec469ba5fb729edf3e443bb032d488cc99102a614a5251915267db003dbf395132d815ba78f262000000000000000000000000000000000161c01cb4d0942faf2303c108604babbd4cabf5d3d30c13d7db9428a445c7f72d96a7405e22e4e451058a94e20068720000000000000000000000000000000010ccf8a8ec4e6515b20e07057fb8cbecc5defb87480f3e32a1bcd0cfe239e00daf6a390c4815ef6b85be1f07a4c4bfbc4a46618381ba6b991b2edfdeafa67aef1cfea066fbffdba24db25385963326bf000000000000000000000000000000000e6cf781162502d2a758d0f96946bab887591b7c9ec9f67a1b0b962e74ee514e84c14bf67ae3c0a9ea2a3e472b7ef59c0000000000000000000000000000000001542b4e97f1e8a64ffd51ca43137b0660f897f6b3d5c6fee598fc4dd03932c3658ea55e1e9e73376e51df278ddd3a3f0000000000000000000000000000000016dae882ba240343e752eac68122424320d1acb1fbc4bd26c3983dd91325f25e1b1f06213e0e06c142997a13fbeca597000000000000000000000000000000001138b71c95d4de320f02e68dae9bb0de3e5b317cb596532c5cc18ca588cc8566c21551d7d55d685591126b9d9e466455cd05fce871e4ff11e7a4e834061c65a0aab7bfa8a0128d460a493337c6e63ebf000000000000000000000000000000000904f6a09f3a5f5baac902c702b059835737c06f62c2ffe9101bac32f854e4d72f74031f5410a5941612b1aaacbb50920000000000000000000000000000000012f39e7022150b2be12cdd621ae23525581405021b21cb9e55972724a22b1aeb2e15b135ceade132d3310e050e607f65000000000000000000000000000000000a92b1daaf23524904d74c3f149fcd2c98e3a4c257113533e7cc59c4656b785aacbf0ba6b9df0dc17cf7c25f1ca698c5000000000000000000000000000000000a20a5d7c0aeb16ff498f46bf05e512784d120b9c3c8b2877411852d7da3abde9e83a6d00213bf69ed88bcbb051a486daba9e37ae0dbb733af820743d8e307fc02a3ce9b40032b16d0e9466903de9caa00000000000000000000000000000000153918807d7da07ec7014154f00a558ebe0d5fb48fba4c16488d61a826a1eec28e3828d6744300c04207e8ff1cb61211000000000000000000000000000000000a755480457896c5a3fde35658e73fae821151c43fb92e9ffedcb05fabad37cb68aa24e029fc33a2518398d723c4859100000000000000000000000000000000148798bdc5b14b90aefc38946db93be1754f15d78762f38971b1e64a53fda92b96b0a70ca2548baec882887ae7f636910000000000000000000000000000000012299fc413dbaa77cf8867e331bc0602c4fb32fe44a150217de9e6391374a9ed83781034e5775c4933e13cdfffd25a9e6ef151662cba4952416eaadebfe5e0fa0ca1d31380e1540c2d5e0181af9e317c000000000000000000000000000000000fdfcbcce1603198fa344487d2d4838b3ff23fc0a73a76222707d9f8623f0b87dfc816be8717b0b12667bee460ef40f70000000000000000000000000000000015036dff68139419db619912e2d19b7d2a2d637fbb8bffcd941aefe2eb4d24c1f7dc32f4f53d4cfce67785e7c328d6c4000000000000000000000000000000000fd575be9bf54128a9a1cbd366339c993ced315a840d60f8b77e035352bf705c01a9def713e8cae3001dc1062cc0723b0000000000000000000000000000000004015ed456125cf0f46fe0093b81ff9315d955d470ad756a9303f548819f339e137305c58e6f4d8db3c8bbfab90718d4f0a3851bd52ca52919dfd21efa6efc56f6dd5060ad969360b1a731e8f38f0f5d0000000000000000000000000000000016d31e68cfdc5823970c8c2ebc53c3d4517792c44e90c10f920a819e72e4a6966c59a691b905c8b0b612065c56d86ca40000000000000000000000000000000005096d516e416fdc0df552c2688c74f1c067a3e5e7fd782479bfa468096e6ee3e601bc23d2e38ae7500325765483250600000000000000000000000000000000092c994e9dae287bb6450607a4263bcf6267f0f66ba3e63436292af7f6bc8e4ba794a12792b6af49ef59b5fe50ff6d3400000000000000000000000000000000175a645988f33612e969e1d91b2c30e47ec655ad655d89cd8dac151c3bd194cd5a8c28b498b1cc2f2966b7fc37cfc8c532b41960417047a2258b6e9e228f3cc1130b296cafbb75f58731a81fcfe8c83a0000000000000000000000000000000008d09ee15c80facf7e32b15418fefbf7e80400acf37f2a1bc6ced88b1591bcb8f86b45b544646c5fafa71b5b103b927400000000000000000000000000000000060865ba68ed8fb3d0a05779c278352b22d4244edb7add23d985a2836d2772dbffc3c82c3134916e9b0900c9db6ead8f000000000000000000000000000000000dce53bf8aca1ed44bee47096dd988689c1e32e1e65a5f8dbabab7c4edba866132ee2c036aba5648d0dafa9a26405fe30000000000000000000000000000000003319995785be720860bbf48692d1507185d898187993865648ded74d3aaca45df939c6dd986db42a51bd13579a55b8f71a6f7f091a6a21dbfffcec2eecaa22d05252b60bf91b56811a833dde3fcfde6",
+ "Expected": "0000000000000000000000000000000010643af30c3cdefc30144c5d7cab17c9c54adccb3294ae79fe5c69376011c159be1e43940640bf5d9012ccdbc997e2090000000000000000000000000000000002a22b08904ea9ca99103a01caad745dc2afb7b6d23e666770e81a97031de921f9d4d1c04fa941c433b8cd9cafced3a10000000000000000000000000000000010808e5518eb6cd61eec8820b9f279dba2423b1a3677e21fe3a0ca2ad49fbab2995de1c5adc9ac867de79e3b40ffddf30000000000000000000000000000000003ce1270644d71e0055345c7463d72dc119495bfa04a818dd398d944ca46deb0aee8c7936557754fa18225522fb79564",
+ "Name": "matter_g2_multiexp_51",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000059234bb6d1b66985b79e6a2c6cd158d37fc50ccd6e50ad2fe3b6a02ae2ad35b8b2be92139265957ea698441e780532100000000000000000000000000000000066adc7083a7f3dd75a8e431a36632dfcecc2527f261e961335bbe8fc8329d992880736bb41fffe41484f68c38fda61a0000000000000000000000000000000006aa0794c27d3f60debbee292c28b430c159cb2874b9467312cb857a8777058580f8a2d3b9bf4b8b732edb185cca6ac10000000000000000000000000000000000d81f222ed6acdf29437adf26d2b785535cd6d61b329df98be04114c3ae68bc6854e275792fd48de3eedf6ba7f3849a2e56b63fc6ba87cf021c2f92baec248756ddae0a4f070df840db281283a4c9b20000000000000000000000000000000013dab8066757b8bcce2c9965e600c31b792463623cd5561f7f6d55c5a52c22efcbe48b8684fc2dca87e2945765bf565600000000000000000000000000000000198a0594b5e606b18201fe2706bddffe7bee6c583147513333230715d18295714055b984cd3ff8d1127f9420863e3a67000000000000000000000000000000000ef77ae1e991daea1fe8338cf236ba959b22df4b24f00c6c01483b6956c609b805ab89712f80892bc0160fa3775907890000000000000000000000000000000004d30f5a866a100dfe469d4d0c47872245c4cdcfb18d3ffa0de422691044b52d2b9335682dcbf67aafa9275712ae3f5512a50af55f47fdaf176d4885e4910c54428c8ef433ea0cb1d009ea77783559470000000000000000000000000000000008010bd5fb5e222618bf4f919c203dadf9a7b7597bf90e16772020614481a0963a8e8b1bd244661bd33e0d147be7663c0000000000000000000000000000000007e21f548efb869a28d6fe39b999ab7fedae9cd6cfa531fe608476ef30c8703951839476811838608dac1aaf9cd87eed0000000000000000000000000000000006cc674c464f80cacb2156fc1eb680938cb38cc166a99f72daa50f9d2c40f10ff07e447d7bd5e59b6b22f0dc407dd8df0000000000000000000000000000000010b160c58ea82bc3904302b1b4fe83d1883efe3c8f52c4e05a3d8681e604eabb1b7f533e61c51e9a172987383506e7b189a012158b3c18e19471fca6d5aba5fd004a337d49ddef5db177da187c8cf1c8000000000000000000000000000000000d4f8372d1138489913654a7567735be1eacf8c7fd497c2216bf77a94f483bd4a7daa2c8232581d6815af9898a7569b80000000000000000000000000000000013676a1f72cc2ed80fa24f70fe1c52aad9ac13ad6cad1f519649fda6ea3787d86ea164d9ac86de96436e9db4fb4aa44f0000000000000000000000000000000003f7644f7ddc9276ac36aea5c36451f3d5d6e4c508932b16d5677977108f04deace5e8cf0b3b3dee88c328b6030f3567000000000000000000000000000000001953cf03effb7de9e62937572850e9fdeecb74fb4aa655de1abdc6e065920e6d2e51ff28880f33341443b5e6652eff4827dd109f6df1d9851dae28bcb9e552c6b1e1b2dfb331aa955d3d0b6c4862253d000000000000000000000000000000000c76a5bcbd2a61172fdd53b351d143bd30d460e398c9d4b7094a604ab2c0d46d6112bd8a5483c9935f0bf6d84df04b9500000000000000000000000000000000116b15825b780c49fb24617dca620e939e2528e10c49f34971736c82cd35fd3965088595deb86eaca3d3239c6c78a84f000000000000000000000000000000000a0cdaa541dd96fefd46b303b88f1dd4d24257b910a596817f1d946873cfd60ae58a88aa687ba573832331e8fc158db50000000000000000000000000000000016259f7285de159a2c6d6d8687ed348ab97e8cf329ea5de49b6d708b6da5b806bd012ca3641c50f479d85921e20fbaefca96785c1ab66cc5c8e434f59cc1ddf76bd78b6fe660f7cf74cfb79d7f2c7f84000000000000000000000000000000000797e815a98d362e1d7e2ac1fdcb477ccdec8ecdf340d7bded36856ce30e92b661669b38ecbcfb0896b2fd75df9b734a0000000000000000000000000000000017916c559db6b4b28b798c2027e2c70ba1b940212df8a1649b9f6087120660d698bea81258e2007edd4aa7d0d535bccb00000000000000000000000000000000167170a76db0783a8c3228f8246502b15d342b019fb44a46b514f4ba2de3ac66e435941adc3d91874371561870ba87150000000000000000000000000000000010097a585eb9264ea96904d8534820be185d8d9e4b1616439a926c0ff8ceb6f2bc082e5712454690c9c05b8018a996235aabd1fba36142bd768339e091b15b7f5b4ea609b57947a7187c498bd9833c2900000000000000000000000000000000025eff57e1f37903056835d1b4133ce064c86947f35859817b2cccf1a5c3923ccca766b3e0affd20a4a6df62a45c31000000000000000000000000000000000011158fce4ade070629162b2b6cf1924696f1f7776f3d623cfa3d54c66fc17fa0299c6650b709a1472262fc0abe8d9557000000000000000000000000000000001828a65fb90dcebe25413566deacf0677a3993b39d68854b264fe7807097fbd3106ac618545d3a6a42e197c65f0d2a7100000000000000000000000000000000045eb8164b6ec874467286dc3626fad3c01be61f6a8a88e5f88797978463db648a9b8a1e1a2589364ef2879cb5f75423fbe608fefa5472c7d1611abfa402d2eddb1e54542f45d4012db8ac6d1e5016100000000000000000000000000000000011847bdf2f67b40aac3426716391da488a8f0462b68bd35a8c1c762591e2f426f48f979a646a094bce16bc99cef7fcfc00000000000000000000000000000000092d61e408120b1549fc8d2174572eb7ed3f679327cb89754f326fa72fbff79e98cf5ad9c94c14dd86135e9aacc98b98000000000000000000000000000000001440e2f4ee2ba254a780a31b02babca093a38e5a1ac09ff388080b6c60918ae5b26e1c0888ea0976527ba103b257d02d0000000000000000000000000000000019797e49808b756128866fae0d6aa7e755a1d6f07f7e6a877bee150fe9adf0cfe612350c5a0e31d68cbeed226fa56f2a28d57066cce439d8d0385f647ed5e9b29e8fd0528c1ed8455f37dcd81f4b62240000000000000000000000000000000016d723a64ee06a7a631509c6e64b1c8bbe199952da532dd92194147bce9942cb4a76f2358e6c7d263916fa36e2c0c09d0000000000000000000000000000000003d04ce655cad1d63748f6eaa9912d6474a34820986835f60c812aee9980d3ebc18d6fd856a6de9546be024b2e95126a000000000000000000000000000000000ea840bd7f76f8e944f95146cdc9692d97e6a2d7d16d4a7f054f81888472da4d60ae5faccb72d3a05781b399536ccb1e00000000000000000000000000000000155a1c43c39e9dfc6d96e01c981662900fadf1a46aa1c2fdb70bb34e94dcbe86c4f255e259c771ea8ede50b388ceb2f61208d8d328014a6b2c8b2b9edc70589cdd63d38f4e70abb41cff1b7693bf9a290000000000000000000000000000000008f189d97f7d82aad87fb71d090a5c99d94079c0b74beb3dc860d440c0f46727fc49104d671bdcbe5b9551552e18afc60000000000000000000000000000000010c4edfb64b8932a617c316820cd27d3f6ffa89b471949362762af8e10d25265b84ca2aafd3b14f33c39a4b533da60d60000000000000000000000000000000017ef3bb919b087fb6745bbf115e2929394fbc9c89f65e7d591f15da93ab785aa6828ebb6ced99d3506810647d28ed814000000000000000000000000000000001591d8213ab349017cc93f1fbe6aca6765dd33ac1f468621e2c79e30aa73bd7606a0e5ba1d97ff03e0029dbc8ab1c5f4d3a2044ed4f938c17684413625bdd281f685abea2e375bece77c03d697c82cc20000000000000000000000000000000019b3a2df3a9571b066eb451e34d8a38c0d90b6e365862bcd92ae76195956c21c59441f0cd03cc69abdf4ba069759b87f00000000000000000000000000000000082537ef7f4bba5f32db4443abc8eabceef643b0878ef83860d75ba508369a3b459cad96f1cfd872df99548f656b0f9b000000000000000000000000000000000b2fda5ba0c405c9481edd598181ed8a59a8a18462508af8c5d66988a7a58a5c9635d93b5e0ee310bd35e0091fcd4986000000000000000000000000000000000af7e15e0052576f82e36e7e2b614dd835a290e05f2ed9dad7f508b4c04e8d437e7e937a7f4c88b5e66b06e0beffc4df7fd81e27a577b5e79929614c069d6d52146a6183822d25cf1ef84d8afcc1f6b40000000000000000000000000000000017a1d5add5601010d138263b4793149a02e8f4f7cfaafb69fde7b843a51cf5f0634e26b6e5e3315420d44b0fd205230d0000000000000000000000000000000013ea863ebe1b1cfcf4164d78dbe8fc809d2b82ef3e5a2589ca1357e48dddf2696e910a90301ed910fae77a1e462a5b1000000000000000000000000000000000012b40d9f25dc5a61454ddf1fa9c38e87eee60e55938b411bff9cf2161ebd7d3fc930131a198e7e97dc90cc245164e7000000000000000000000000000000000054f19ed8e2682caeda10c252f11706e7f3b65c81e7ae0a617469babc5f3268fe5c0ce2e85d44fb6731e8ac132b97c3ac5d47ce35d4ede84a83c9860322f582ec00c872b4b035d5d340981fc29884f13000000000000000000000000000000000ef0378945ae4683666099be36de3e60b5bae9c3137b702e5e4e35afd5c1e81d033c3d6b1debf5bf36bdfc4e3af37759000000000000000000000000000000000c37074af84ff596ff2c7ff963d96968464d6c8d88b69af64ae883457d02ee9ec80720661f39019230a6531a0f2952bb000000000000000000000000000000000454e8aaa2830f07d86eac7aca1d7589fb06aed646146a1b90f4959b5caed73131ab231313b50c15213f89566ed87a3600000000000000000000000000000000143516cd7a1b8da41226cb828887a0b3314cf4f87c207d1d84e9c49f0f7e548ab99e635bd126d49fd2e4dcea98f3adf784ae256d47de2d49b1e755cb0e972f3b614f3e7ba779c65ce175ca3811021a7f0000000000000000000000000000000019384e15a8754c6d85bd298ed550a26b51b714745bf2980b4920d6e73f59e657d85d3e86baa9bcf7e971233daff99d02000000000000000000000000000000000229d233d605a1a9f060605ae366a263594d8fa2b7797358ffe4c62431b9718d155d24d80bf5af1c806f447b92fcfbab000000000000000000000000000000000bbfb66cc0c7bcf251141c540f712fe9a359d1ed36d228379a1f3791991cccb7dfe1a10d40667ca062cccd55c9e6b08d00000000000000000000000000000000150a4d7a003cb81423604c13d0c5175183ab5f459b96842939f5c4cfbb9196db4667bb4382d2d5c92b70800adf384569a09d0136d4dbb3abfabcac55db48b1ce302067f413283fc1a21744f1c16ef7b50000000000000000000000000000000016352fb8e2751f126fd0f889f2a62a85b95c50d6bda7704112e4487dc94417218b0daa1dd6b998662af2582c44b011c90000000000000000000000000000000016bf4c60eeaca103c90643fe0969c2c261e9697ddbc02279f0d5afb5c905a984ab2396db93555cc2dd5682a1525446d00000000000000000000000000000000014be742feb1215cbdcde21e974c74e23c7bbc2cbfaaace28cf1d4f2b5a77dde2f3910aea74bc200277e6fe0475208057000000000000000000000000000000000bf98dd3e3a8b13e487d8b1a35615b0c6b0f514f9b8da7d6402586f113974c8dc9561db797a96f4f8040c1765518d175650a6fba1a5eace6b455ee780ff266c324f49801832640856a80098f0eed0b7b000000000000000000000000000000000362935e552dd01b5fc5a15a76faae937d7ad086b0a67e9cd3558287274106623deb85b6410bb4e64c424d44335f3b1e00000000000000000000000000000000096f23a54cf57aa3306df0a0a4f45aecb9b09bfe83878d551a59c53e18efc5a9f177cb7fdaec1648f66cdfaebb15c61d00000000000000000000000000000000135271fbe0cc0987e82f3430eefa8e3cdcc1be4a441393bb3fac0b8e8f78dc47ba2b833d9dca4277bd60befdf33275cf000000000000000000000000000000000dc1b7512fa5f9d4ea3f4229d947f43d7dc46b7770aadbd7351b6d48d525d0144183f2c84293c63c68d5262851401ae0282cb1f8f6d6dd81e7c49176503a76837a96d7f2b084d29d11dd9c6548cf0a57",
+ "Expected": "0000000000000000000000000000000001c11610b63eeaf9e00552a230bfee290ea49bf9c93cfea1b6f684c9b5a07f341b718a0070534e0da9e6ab1239d800830000000000000000000000000000000017e8107113714ebb1743c34d83be3acde096bfb6cf140e943ecd0831ecfcd097f58d25a45005db61551a01d9da46de10000000000000000000000000000000000c2eff6c7c25885c514aadecb8f0465a0fb4385eadffa082e8d4f497b10df2395be5e7760a87bc26772dd78701146b730000000000000000000000000000000011ad4e20f5c1518c72f75d67a897f30100dbb83365ef7729c3501c6f266d6002edcab8c8bc1f449c30ec3624cda13809",
+ "Name": "matter_g2_multiexp_52",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010a26eda028649789d9e01232884e4e5a6b8e0b17169b9d64393e2568b09ac4d3e61a5996108655c24e76abe9e3fb7380000000000000000000000000000000015e4e36bcad524f8aac7f909fbb884e879caa735f80fe9890d7874be919ee727beb2a074984c047dac1d02b8712afa3a0000000000000000000000000000000012458946f1e853a7a45861a92d4ce707e5aebbf69edfe69190c0bb130141a10869e2a73e06785b568248d5b1f647e63e0000000000000000000000000000000004d8061f25edb5a510a2db9e1df850518156138c78ace50f4c9ce47734a0b14352f5283083a232602a070c3ce94c7bd93d7f8fbaa4225f3008649eebf42315785ccda2b9ce922170e606876881825cb90000000000000000000000000000000000baa40ea518227b007b9714ae6eb5a4e92883dc75e6328caa780bb2ffee7573dcd7e9ac47821ac449187569986bd2980000000000000000000000000000000009d43d61f070ae308c5c285915600dd9c17b7de63cfeee6fe33c9ba857b3c72e057bcb4d4ac2b492797e7d785997c18800000000000000000000000000000000185215a7fefb96b3ff9229cc3239c3ce5202a97e275ea9b1541d7bc0a2931d7e3b01942febb45c6e96e66e3605744afa00000000000000000000000000000000103ae58b8066dd62c46c14c593c768fda91b90e4840b5560c974ce69b86bd6d2c13f689b72cf9619e57c9dc8e3d3fb15e71e6cb3d4e19f4a70a4465df6eec6326f558ee1cb99aa540ad2a73c363a133900000000000000000000000000000000075585f862c0e0e031efe12f31e159f2a8b89825ce80fdf65906474f0155f397fdc666292f6a7384cab790f071335c49000000000000000000000000000000000eba3d37a5cae738ab99ed9475c2c7fbb88ff54edb8490017162dbb16c8225102158a266fd4ba7570ee6d5ff6cf3f5d400000000000000000000000000000000135a0b0a38c036919f8389eb7bdc505a375fd75d513eecf0cac134645d60fb6030a437ac6a0fbbd167b7a77a927b3b0e000000000000000000000000000000001688fabd4ad751598ca036ec5ef6d7b314980dce7d8652163e89fad01b233af64defbcf352743ec478af42587f58177dbdb2b3c3b8e91540dc2724537526fd8c0d4b85d2cc20323d71fa5a4f61b3f12a00000000000000000000000000000000062a74a9ba0e2e8d95fca478be8d18fc716243b1faf7365a55387fd7188021f53bbe780e973e7d16c9db236faff176cc000000000000000000000000000000000f949be3fcf9b38995624570fcc9e7df9964d038eca189336ec39d9e0bd05148ff7df0b48436a2cf6e249e52248ee8a40000000000000000000000000000000007472e7c366419a0cab844522c46356acdf6a12cffae941fae3d3b78e7a83f0446c945bdf7b247abccaeeaafec49026c0000000000000000000000000000000006a564e6860b97feff368fc9a349282112e591a7a6987fd10a2d4de8ae4384ce229b9db9a93445f727eeec55a6fe5a9def0c8574167a3bd3b794f057ed01865ea69c38023dbddb0afdc55dd9523ebab7000000000000000000000000000000000c073d2885eb125d3e7db48127178bea2c5bb0f09eec7081f15bc6fe6cba156914fe1b1fea6cf14a21a328d831523ec300000000000000000000000000000000010d93564b2facde13d29dac198c5f5fa314a0398f30c6fb7fc9575bc83d4e97edcc1c1d34f78728729442777718f54600000000000000000000000000000000136a4ffaacf0b4a607c677ed343c1ad41a1eca49c7c48fe73ab2f74084a07cff18f07f54a7f8ea1bfb7fa3667863bdc8000000000000000000000000000000000fb0c007a907ecdff7bfe2242097caf0c5001124d112689a74544fe4fd85be9771632e7267a1cc7e9f66d7e4bb4c954c3ccc75501428d3be8bb469ed0f2df7dec10e1d205e11a907cc30c4a76eee3cc000000000000000000000000000000000032bb9f20fdb19f578fac3008396f5dd0a70860f77f8ae7771fc6253569d47b72751cd56bd373dbc5eadf55b99578861000000000000000000000000000000000c4a4bfb5ca6f9c1bd69d7377c6da405afc3128338dfddd9aea19aec5e1e0f547e3febd28445af5e27469c87c4ac15280000000000000000000000000000000003b551547af253d07625028db4b9a8da2a857bc925620c5d561bbcd3e063eb460d9407cd4d4813800551e5d0d23a2ea40000000000000000000000000000000006d5c69a251e9a042c66bd4ee92d4f3cd4e79704b1b215c15b319e09cae0d798eb201be24f407340dbcefcf2cb87da5ae5e403f555fbc800f1342275f18a73dbb679bd31873ee87617090912a52d6a55000000000000000000000000000000000a5802e388f7605bbacd0bb65ba96689e223379214fd7a92de9a313f55d66cc71ffc9ab3f9979b75edf55647ad3b6c94000000000000000000000000000000000f86f968b5c20a81f18074803e1ec55ebd73bc87451c48d5bb61604ebae46538dcc9d21cce062abc07b4b9e89c85bf60000000000000000000000000000000000f9fceddfa8fb5bd76fb7c8986372c32ab9fae3c26e9fedae892bb55178fa2f3432e6eab5043496dcebef46b20bf5824000000000000000000000000000000000dcf7a118881aea4e6a0e4e305910d4e4a5f3d0a8800f52659ac26f122bd63c8aa2c5583f1121275adc9af1800a007fc97ea57a38598204c15bf65e7270a175460510848540ca4004286f3ca09eb59260000000000000000000000000000000003ee0ba2b1de438abe66769124b97a951ce18aedc8d9ed005628aeebd90efd316e7a3c60cb5a103d6f72e7a40ed8f44000000000000000000000000000000000119597c99a7a16d8d35937ea15539089741363153ef898d6bb177d9a9b6c5bb4b79728155eacc5d82571f398ac6c32a200000000000000000000000000000000116184ac845a28c4f96641ec19a07e1f8326bd45e2106148f40277ae6fcf200d64e326915cf5c927222def8deccd4ff8000000000000000000000000000000000f890258e70b973c0d69492b2e7d10ccb3997798503c0943af4255c13b3856ca4007b18cb9d638d5d9cca71c368cdfccc54dd8cbe68d5151e4428d35ec2d5b5cc7f5e455207c0788a695c2d7fff6735200000000000000000000000000000000171035755bd519af04efdd477d407267c5a8108bd32dd6d3f1b9555f15f37ce7598c096fb5301873809f0c000457a4a2000000000000000000000000000000000bd35595246a8337a426c50c02299f297036f710b0979c7f981c6909e835c0d9556cf64e2676baf952a787e10d604f210000000000000000000000000000000006600ff240aaa026941290f49ae8968e72293ae7c2af0df1b4ebb9373199b95fc91feedd2782ce819440286aeb2388c50000000000000000000000000000000015b2bbffac097c27944143cfb22e38ff8e50e79f2336e64c8496b0b25892834efb18a765e26f1408df1d64f4b9b78fb947ee5651c127d7c8ef65ec68fcd97d1dc228bffb5bf1278aed3eef8115a5ae72000000000000000000000000000000001064bd04edf96a3c76d2ace669ff72ee5edd87d32592213cb5a6a4a482154c1723bc19c7c530d164c31626dbf758d43f00000000000000000000000000000000176ac06390e3629bdfa282bf825c0bca9bc4e0b8fd90fcf2d4ee456d5bcb3ac2882d8406d2fd59faf10c8327b1962124000000000000000000000000000000000b58fbe4e14ee0af03d9aac4131abfaaba43c7cd92d530802516cb67343b382a6d2af9399d93b43d6e05f7ec827d5ae20000000000000000000000000000000000bfd241e3180cd5ce9de831b24ca50db23685bea7e008be0c6ead11abee338618728968c25a8e5a916cef8aa516667214ab6a1d0d3f87e7c9df0c14b6fd2f9d0cd755d5fce5f40bdc8174790901549b00000000000000000000000000000000183ccf0ddeb8573923694decc02b8f02162037156a8f6523ed178c13113d094521c3d9257febcfbd8f15acfe3d5d5c27000000000000000000000000000000000cf716097aabb07979ee435cf57ae36a3034283eeec0771bea24c9a1a15ea106201af8606d3fc28ad8ffbea2cf274458000000000000000000000000000000000b962565763c4cc155b2d9ea104e754e5fb4745303240688fee7e2256fbda82dfb515a51096be5ba0b111637b1a25438000000000000000000000000000000000df04aea745b9df2df0e34153269958d3640c1596fdff3fba696801c96371420a3619c5ace9210af7e0de4f408b09a7729b12cff5a72f27e15032844fae50e3cabbe31a69568bc4b5cfa884f62e7e204000000000000000000000000000000000e6be3275371e533a676f8d075bb2ab8b0216642ecde13425bce4ffa8ac51cb1b4c5c789d82387f5355c27f18da556400000000000000000000000000000000009fa3a3df5195203f967322cee54a15d1e0096922b6b881bb3bce54587fdb82931c0b87de7a9dd1a21b4389a34d161ba0000000000000000000000000000000014dd5455deaa5ea4f9b5a6241c2e8b2230fabff9e1ac08b359f029f4c7838201cb88a92a5b696ed47819e4866512fff300000000000000000000000000000000181085d630d1e24ebf79bfafa134c08c0e75626dd400ce500392adf4462028bc714ca07b28b8b8f15c9cf2934a299c3092c1b10d980826351c3d193a0f54a7dd78a3995efb02fe5b4525fca8791b1c4f0000000000000000000000000000000013b60e3be9d7d43eb42f7cc2c0a7efc81c175b696e82b034c87d1238db2798d9ad6534b86992653d86755b4f00cf989d0000000000000000000000000000000009dbb325624e698c76b9d697e4f7f03e502ae1cd43b49a0957fc067858e20e8c7ede3577f336eeccee58cad53eb727560000000000000000000000000000000007f2f50be2c6fbc500ea347cd14ca195af08b835814ca515d14dd2f6078eb6def2b9475c2ce370780acf394065032d0400000000000000000000000000000000109803d612b9e27be5725f162d061b9428f363493c17eb39c097032039387d96d0939a06466470ab62ff507ff762fba78f715f35fc967837facb515ebff3df502223c29e7089fe6d2e9120bd3ecfcd120000000000000000000000000000000008a9fcb462412c1065dc7c3623ba5a980e6f86cc813b5d8eca6b1b8a302ee4176cebc233411f2c9ff171332c66a0d46e00000000000000000000000000000000058d2e7ee02bbd4896b5bcaac0f2b09c16d1664209710945c1f7f1a53e24496d7eace99488debb32afe10d7fea442cb800000000000000000000000000000000084d7600bcb68d5e375457078672fa07ba2c87c8ec5f9eb7b61a0232988b197aff052e7125b33c6657729ce8a1c668e2000000000000000000000000000000000a07c42468c7c65fcc984bbfc2f05bf452daf17d57e669ee5992ce67517e1c93b5f7f4c9434d40f3b9bbdb3446ddb982a9e49fcb12c0b1e9bcdbda52e9852ee0e98fa0d43f7476b3d65ef5370c9460a3000000000000000000000000000000000ec380d15e0efd71958978b1f9298ced4cc3322e472d03830ebbaf2a4601c8371e6bc1cad047b0e1e429ecf6fc628208000000000000000000000000000000000b278fcc53b7527545ae1340c24158ff662683919717c220e7d2838a853fcc84ce3915f105a932872ca7f64b7cf096ba000000000000000000000000000000001520798dcd146c0b39ee727e8276fd998de0157a68587c2fde56cd82a9779b6ffbf745ec151210d1e9143856f24f01d600000000000000000000000000000000175d53b992d750b34f9daa39aec918a0ebb2f539db8057eff1409492c90f79a00f14a4c53445c028bef5d6372c9f80c680b0d6316c5d62d41fb0399256c5c46ebe2a12eaad835d2c7177bb7325e21d3b000000000000000000000000000000000fb3863bc7b468f1a0ab0e4701ea392bd820ec5cc2d7d86b58949002f24c972f51f0f82400fadebef13b750884b35f9e0000000000000000000000000000000008fca1b30d4e01991811679f261d11723086753e816239c8c7ebb60ce9ac0ea207011a69cdc29e3336e8f589b71bdfde0000000000000000000000000000000010696ff9d78b48743abdc6c1f4b44b4c960aa516623a24da515206d95e65286e453a8f275d98aaa09fefea29e71b5643000000000000000000000000000000000fb4b5eb18b6f6f8ee7dc734e8bdb625a403dcac6d0cae363e5a7f3a834c8eed5f01fbc4dc752e228c41f3f9d992bbe01b96434f34fa3e00ee0cfe548a2d2ca29a848cf1c52f940685caa9a227e32a61",
+ "Expected": "00000000000000000000000000000000165baa8b143e3734169986e68a848739ca05330786012de260148cfd0810ffd5659210855f19ca92566ea0d6c48086ec000000000000000000000000000000001225672112e0476418288f381165292a9aabd009b0d9e44d9f8f00469b2c56698f5f985ab6292c9dbcf73bcf610080a20000000000000000000000000000000005418cba24a43fc7edaf2fe77422a0b2e8b38a45415e13654c6176c8f7cf6bb2b80401534154cd3b23e977af589eda9e00000000000000000000000000000000067126ad59105621cb0931ab8f386570b54977563ffd69c2231c56e7961f6df2c5d7b114e0b1ea176cbfc1d657127286",
+ "Name": "matter_g2_multiexp_53",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000139cfd67c3365c5b4422063d7901108c9f33e233bf6413ba2e5b2ad62d188cb50dbd3dac0f298aef7c1d621249d4b0c50000000000000000000000000000000012fcc0d5d09cb3d86895f76ac3d3e9fa9b2495110b0276e7a039d7d2fc2e48fee646fe331c1d8e6f019898ddb43dd09b00000000000000000000000000000000159356eb3ed0d4f146dc929aa6c77057be5ffbb064432d3fc35d346f19f6c1f8552c7079e27f3188bcf29941375e62c9000000000000000000000000000000000fbd4e9a57aaaec40ef9bce8b76b529bd2261d373f05fd69af58d1f23c089497473e44e937b2617a92942af1a99d031f10e0acc22c43080ab9cea11a60866feedd57664bbe6c3f0366beff177f66318500000000000000000000000000000000022ce2d2bee57f7567e9b52ae8e913c79e3b2dad381802ccad317b525be0b503bdfa92722eb0c21fdaa31fce2421ae300000000000000000000000000000000001177074350288dff9dd85dbee758fee1400cebc173793198a96c0be3bb810d352720e94b9bdcc6f5a8951b3a86b2a0e000000000000000000000000000000000179e21de58ff76427f5ed7c8ca3058d0e5e81e436280aecc75a3d989d1cf11d41734de22bda74cf0dff175ac789532b0000000000000000000000000000000016abe94a49f071fcd5e24b5f3a837fe3fe7c7dc53416f59d0469d71f144f71ade4569bac3aaa202a8479c794bd251645cab0c230c354cbf1a3c13c23a36ae5f2d5d084d7aaeb427c580cb6b9bfd9df600000000000000000000000000000000018dee638031a3c9b1198cd4a4f267cdd66849e2b80e3d670897d9e058bbe772936d827eaa4e78283d42ecd25eb4b22e200000000000000000000000000000000009c04ef31cfda7c086a31341434a1698c1132fb5916d359a523b98d05d57bb38a1e2e2bb779d4762f9d4ec24fbf2564000000000000000000000000000000000a788450652e0bfae66889c66b0dab8d1972a626facb690f8e4ebfefc7e1a7b2b58f6eed02c1f10a74b140a49b6c5de50000000000000000000000000000000009e48b52f2b0548dab1c0d260144ad2e66a22e0f1781f94071b5a3a08311d11dcad6963b4339fa63bd82b4ff0dabe685290608899cce4b3d25f57519cc881eb748e9ee7e27f7b21d69f5d8ab3650c3e8000000000000000000000000000000001319607058637d4b796020cca79d62af5862b1c186f32d99c0ff53a830888f297ac4389582f9fd010534d824522e6fe3000000000000000000000000000000000608ca0b4806f17b59a805a3f9f75e7a33ac0791e05050d4eb19f2d4c845fa4e4c738c3309e24a4524b6bfe716949ab5000000000000000000000000000000000a6a6201ec077e113995acb81d4d07d0c4a085d367ed740d26c4a0c04ddf28697c1cf5e648b25148888617ba77ced5e50000000000000000000000000000000003eaff54800dfc8eb3ce647ec4ae8c1aab6a87d4853a1ea061a5e6367d8ebc94243837d4752a1933f7eee0ec1ffe68c8b71debbd9f3be5d6e65e837bd78605d5653fe63025c320cf49c035ae66d8ff5700000000000000000000000000000000122822c91bfc4f761b65f4066a94c0eb1f53133a1355c019f04003e84edc5095523b2ce87ff24bb42425ce979743ce31000000000000000000000000000000001928bc315800ae9936e5b763bf29b19a9aeb71268cb47706494598e0ea057f9dbdda6733d9ea165acade87bd89b3ec12000000000000000000000000000000000a87c1ee17bcd7d348ed1a5022bbc7438bfad06172584dd8e3b51db4b3b09645290382ba991df37db0ce562c950c0e6600000000000000000000000000000000127c80da591c3ff8d300bbdbe27e0aa21b5edc1c1fd8a5da27f58a4dec3971b3c4f9631bde244a7072d9c19f1c0a46be250f62ee2c2972e751b36d95a578efd2fa5e0a2c1e29475a3cee48a28080cb0b0000000000000000000000000000000004bcd0a0321c3c7e6161cd53254353905c27d965f57c9783c3fa7cd5c55a5820116415ce45491d5d1ccef6017ea4608c0000000000000000000000000000000013a30e19c43a1f466c0c3ebb5cf1b57c44434892b18a7fde18a2a29b09a5b4d13d26cef871d689d9855a73a43d22119a00000000000000000000000000000000066d6b3c9a949049413300ec0398d605277911d7be327b1d816cf25543d1b2d7c31d912f426021e612b56ca288b462450000000000000000000000000000000008549f4dfdf018073cc4e32ac930397659ae7a59ef42ca4f864b26e4635c2b7669186a107e9e91c35f04674d2be46051ad08c3d2c36085212542427c1760c72f22838be5286402ef87403f816f4fec950000000000000000000000000000000015900fb486bd2c066cea98e51d30424681fc3347a1cfaeeab65989d1adba104a362837bee51b8b953ebb520feb49aa6c00000000000000000000000000000000198ccab1f94fa910f755936e357a92d358e00cf406894b46adcfc301918c4fd7cf7200a1ea515343d577d920680c83640000000000000000000000000000000018d9380a8568adb92f8f9f67c315f2a837d542b32aa82d9bbf5db6dfea27260738bd0a03683a9988c6c3370563e7bb8f000000000000000000000000000000000528ad42f23c4e21a687f2303f495e962b0a90713d6ef3abbdce38ed166ffea9c132e50c5b002b2ddbbd4933e9a1aedf6ffa16b6fc4cc9509a2b8d8434fa0f4f38b4cb4eb1bf7f545f9f43b9190cad890000000000000000000000000000000017eb2587aef34b03943a170d91d99aa16ceb2a36df3068663382ff4c135083c998743f9145a2fd5dd4ce3bb8b64cf3fe000000000000000000000000000000001256fb29c7482e5469d64183e3e848e5bf32f9c495cc495c3f8cd8e46f71c3f9880f875cfe429677615a6803f849952500000000000000000000000000000000146e2f329f86ddf5b0b17c37aa2905122f457c2c812782bdc15e132468af48c49b715e3080da504d59414ceb367596f100000000000000000000000000000000022a8e385972592430e76bd952a700df8d35b32deaf06c60173d0048d6ea22dad95cc62300bc1a60c6452c41b32b504a1271d29abc5f972809461a1afa5eb186dff5e28f20311a1d8416f8d54fc4b2d90000000000000000000000000000000009c80b3191783d235814fc86653bf2f9a32cb7938111408087b6ab5bafc480583e7a2a32c6bee0ee4aa867ad5dbbf77a000000000000000000000000000000000a09af60eed6c47a6c2615cbfe62025530b35727b42fd812032671ca1eece6694aaae259b05906faf7fbb54362ea890900000000000000000000000000000000055c5f0818f41e5d73e8cd5f70fa77cf477cad8dca2a88b8970a3a25c8f38382268e439642518f1974c5b470cbf29699000000000000000000000000000000000834e44669043aed8ad47cccaaa7476ad830e38fc1def66aa7e8207e889ac0fa1a931eb1e90aa6e1cd694bb95056c3e63ce55b3b32ad29dca1a0c99771fc8f7179851995d5eac804458edede9b8dbcd000000000000000000000000000000000190f8da34caaf472ea9b0f41851f808bba402b9be4baa5d02d1bcb2f66acc3172abe78a49a653cd24dea402dfb972f670000000000000000000000000000000019931343d0e59f0f0a060bcbbeea92fc4670db510c017fd94e0650ace68c2925c627f373d8e755813c199b79c70369f20000000000000000000000000000000013ee811cbc036d2786d8ec0339627d6134b10517c8858f6c6db19a9319636459ebaa217649825ffba32a224175267de90000000000000000000000000000000011039d587f3323ea9d3c50027c427fbcbbf7e097533d8a5f7a61520f3eb548c399e401df0f51884395ad6a338c0a3500c6fa7aeb016b3e3f599846af83f426b9ab85b6857f901c49554d03d27a390f5c0000000000000000000000000000000011d5791e9bc632eb63bff86aa433e6df463a84570b779c913f67e77fcfefb6af48f3df2174096a511ac35eff64e0e5f3000000000000000000000000000000000282716505907931bc93748ba1729777b959d65aec5a78c9f829ae6f2a94a022116715a8c2a653a832a62625473a0cd1000000000000000000000000000000000f694a16ce7a69f0261a0ae19478003dcb61bf93a2ff39f940fc4718a38b9f4b6ab13527c5b438d22499ba29c0b5461700000000000000000000000000000000031eab53440757e4065804896e9e811d459665598546796d67472054fa60e5da8685d8e847eae342e44730056757c6287275a8d16c02389795d54ebdcb70a39fa885320d00cd4e5aa15967916e46c61500000000000000000000000000000000138862ee422bc0f38ce3e27ed3c1b71f71a03d61cc474d989b0cc824efc512ef173ef17bbfb2090997eb9435f4d23e0d000000000000000000000000000000000fabf1fac2ffa25d9c8cbd49b3db5dfdbee52adb947ebc1a3423c9fa2f9d3d29329b60ce0c1c739c7fc6d5a5d3b9e96400000000000000000000000000000000090d92e8763d4df49b8121a50affcecfcd632923b5fede480a3ee79128781f3f49b592d8f65d30adfc75d8a1922c41b0000000000000000000000000000000000074456b341565b13ee3862bd87b72f9d01754c7715751738c5b33ee85e3d8a6f731d7292bb485b5fb59bbf3ddf9b0d0dbec9767ed2dbde21fd8f315ed6292b5b0b1bb6daf2b62665c34daed00a679cb0000000000000000000000000000000007b85110889fed72b3654a8632625835cc041ff0a827f3e1b86c090d816d98cb3b4be66b6e573b3dc05b1998f2772f0e00000000000000000000000000000000160524507679ee021f4307e5a9fdaf01459cbb9a3fb9dc8be5599431e2a8bef38bf8a05d601580085da503dfcf57aab7000000000000000000000000000000000f98e2e7ae9cef2b1d954b7f26fa1755258112c496605c3c77408786d4b210e51c76f10870f558296993e0ddcec3d76e00000000000000000000000000000000068841825f5f5d8f622c1d43bfe090d11c6996688589c3d644ff5da47b94c0638128878d51dcf6d43637781f0ab21a68ff634fd89223733f407c242e52f034691036c7ca69f30e6cd444c561de9ebdaf0000000000000000000000000000000013ec97016dc3d6a3cf41edcc18f88f58b1b88cb2616bc2a8f96af3e7774ec1aaefe86a86135a20ab7592c874a33a8e1b000000000000000000000000000000000021dc7e4be6462d64ba6c09c2d326ca0164305dbf5ca1981f265a1e50f1a646748ce66ae07297230325937faf60709e00000000000000000000000000000000121bda2855503ef11b043301cf331a0fda6e5914e5ca657890ffba2542d908f8fb02c2c93cb4ac4fe5bb92eea757ca7b000000000000000000000000000000000386fdda56c778a7552dce451a6ade55cd24bf9eaeb837ebef898e2e868d05eb5edfe97bfa8eff8ab7cbfaca3c918910461d349e9711fa701b92b62dd3e3569d1203b6a35ac8600367a4df9a9484bdb0000000000000000000000000000000000763746ba87e8bb547180b0bf18699ff74f11154a06cd77a76cc9c264db7c48286fc52e3ef2d30ca914cdcc5c4ed46ad0000000000000000000000000000000018037afcabd273413eb4a712f5d1888249dc987a6fdb8befb92c02660604bd11deb33f283b37f88880cf1be2b2e71f1c0000000000000000000000000000000008ecca3d1652be4764720ef13a6ed6164a3ae89d160cc8c2c8c37bcbaa52db0fc0de84fbe2a19b93b8100556fce0fc80000000000000000000000000000000000c5727babfbc5c36c1d57b9f69c5b41823882e0196e9e0a89d5f4380c4257818d90b1fa6d782e774f2424209bf2e6b5fcc110fd7a6ae46ef78c0e26183e707eb5e0a2944e3afc09e435d56e91584b93d00000000000000000000000000000000142d41630fb9db2f9630e4d5f9c13069242fbcaf1dd02f93224174567c3f944fa02b9791a409d9236d89df6ad785e8ed0000000000000000000000000000000002fb5fa0b3a7cef16e5638f217bb946085fba870836c618a7db9b4394da9144850572daccbff8208f14c8082aaf1ef6f000000000000000000000000000000000a6be9b4a6a9b96d2096eb3a95780f11be1e13bcb6e625517191822403935c52cd40481bce2e782c42b11321cff2cb7f0000000000000000000000000000000019e2d94e35d608a50b5c8b371044f6410dd6c1988ec7a677016d4b52cc3f21b82fbaa7db897f7107d81a177c31f8e52467de5b9bee26b26b28f81d96e880a3f07dd04eb56c15314f1a789436e01adcda",
+ "Expected": "000000000000000000000000000000000a6f3fcd812e3878cccc6967d49b104599fdaa80cb5dee7298c3fdc80477d277f2c68f1c941f6e03441eb176c222a448000000000000000000000000000000000a4007cc5586d677e7945dc8a5872b4839d5b256999166e7fe8efe4d56895f93be4659f43aaf68c6070babb6d3328168000000000000000000000000000000000cef5304a1077c8f31d72e6f1f91ef5a021d8ba64719b4527225b34e615af388d9b1391f65511eac209ff5e86244039f000000000000000000000000000000000c856e7847ea0b4a8334d124417b45a8689d5d9f113b99ebbe3af3f9aae1cefb236d751c40488a861a8f0e0326b42c4c",
+ "Name": "matter_g2_multiexp_54",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001805009a7fc3d1705936696191c163a07ea992cbb4bec66884a2d58ac3fc0e16b6e0d2292caccb3541f39b7fd6098100000000000000000000000000000000000f3bcfcb0c400d3d06184563204bdee465de167c7d17bea2e2150fe12eb9bc3285f5693b222fcd224181f8d193b7d95f00000000000000000000000000000000028d60b7fc3790aac7f6b3ec32c4be626a2c64c6348fb8a1f39e58ee56b81469e04886ed9be1388958550c02ca9a75b9000000000000000000000000000000000b60ed8052e43e99d3c10a4b97ac3197ee3cc04ad857c5cf4d8ea1df2671084d02fb683f28f5d499910351354d5e6288624ab43047c02e30ba2ec671511d06f869bf736a9866192c5f2eea6c065acea40000000000000000000000000000000002ddb1a9a88e3a0697540cb008bceb075e87e2331f6e9b68f8ffec48752d93cfda5fee121155ad2a142c0ec42808fbc200000000000000000000000000000000144b694018840835fa9c50fdf62c2e32261a8350d2ef074dcf7d016af982316a0c6f9e5d15d29d3a54d8d25aac5534940000000000000000000000000000000010a3765089ada75e9eb61328756ab9ca7b8362cf86cc82af3cf43f390a0745954f28da72a6ea4eb904a040596795639100000000000000000000000000000000056b51dbefab453012b35fb6e06af06ee92e4e84e92a9967b379af760fdca4a3f10f938684a646fd70a2188721c92e98edfdf850c0d3e3903404fe3e0f523cd230cabc45946c4fcb6d0e5e05e388c23500000000000000000000000000000000169effb324d60b71dc7ba975e3d5f18700b34cb9017f482f64be37c4df01fb66ee9eb5870e43649225c9a88a0d499b890000000000000000000000000000000016c7ad9c5f7b65a9423f642d87621a5192d7548e1099d774a99a34dd4ec9623aa1168b9adab092b3cf450f369bcb627600000000000000000000000000000000123b35bbcd791ce0d00148cdb3d35ba39054a7126ca5ad3351fef1437461379ef639896b271276a9561b46e270f7501400000000000000000000000000000000161fca2deb729fc55f1102fb75ff466319f18510fc66d6cf95a8256118fca618682f00318b0a5297be873a2f7af1915afeb34852ce0f3b5730962023418ad6cb860716dcb526dc53e8ab6a74a6a3910b00000000000000000000000000000000073ad8c2f713288313185c3b2455ade93d58e70d5df6b8dfaac8eccd990fca6843778fe42cc8aa6f34ee44aefb49397100000000000000000000000000000000012eb9cf288a366adc58d40c9ea5f2cb5dcc5b04108e3822266ff20eed71f56bd74f1a2727f20d55917adf20b6c4d6a1000000000000000000000000000000001463db177fe5c0dcb899797f89da963731dd4e9e8b2eb77b465b98415dc95f6d5569df51bd2b08a13838f4cca4b62fcc0000000000000000000000000000000009c0bbadad98361209f36eb23a9eeff98f6eafc7d5327fddb6bf43898a2be704520a005b84c5b45c6a68bb7c98d65d6dcf25e64093bd92a8fb394511215a3fa674db86d7329ac5ea70ec77d24d4ac58e0000000000000000000000000000000013c63973ce6549ca3dfe8ea8e3bcd6b0bd88f7c73730834d9ffe2076cd4345090d0364d161ae8998af1048d102f22e5d00000000000000000000000000000000060cd24eea4177c9a5c37038d4cb62aeb709218fa8e64b9084e002f53a0c4c411825812c20df282345bc4a6aabfff6a100000000000000000000000000000000106ea864dd52933be02c1a79cbaf6dc81ae9a2d619bb368c4abc36226104f3b74fadfab906e36d4852a6412315223bdd00000000000000000000000000000000192e45153e4942c88bcce76098fa51782a81b53abddb4c07bd79a2391be68858e2d278969b9fe75bc652d02fe4db1a130b40db4f9e5c27a3208899f4f536880b97f4c69e7d889c0726d87c3fa27e097500000000000000000000000000000000101ca1625e9d4a51e08f5eb81387b361f6445eb307d9bc92acd29d62735d4e5078b1a9b36b94e4ea0a314703a85ac4cd000000000000000000000000000000000f134c460c6d931396a0aa397558975ee973e642f1c4a32a3d397051fe250daf4215ff5ac4b2863d570c87f0e32c8cb800000000000000000000000000000000008eeb127a38104351298ad77481c32bf51bc5d3910b03da0cc34062dd2a8766adba6891cb9fc579672276666e1242730000000000000000000000000000000010c896ecd4bdc1ce010da81a51dac96409079853635e57e5c3a5733956a5f5a9c3ea6838849e286ce0405dd54d7e32d6730bc7f68d8d371d0bc51d95f8a5899249b8db5cba0d21fd88ba6f86d8691659000000000000000000000000000000000be489a1c71246adaa1c1dd6d2ddfae9523fd1d58d00d4f189f56d08632dccc694e63b371db6922a7f3faa05afbf487500000000000000000000000000000000174212b6840a797f0fe9e209b41f55aa5dbf169a2e2ecf05de48c44e608f6cd6d98ff5269e5412defb431caadc8a09c3000000000000000000000000000000000f4501715c0c511703f6236caa82479b3368de430f2c2d95b39193537be0b990fec1ed8e4d94634ee6233cfa359b043d000000000000000000000000000000000f3b4712f95005004d99fd739affc532d2c4c45970316c1a43f76fa9b57f6676c709e8791c276237b92750f5bdc94492ef06360717cfcab15be966cba2836b97deeedd20a52f88c73e2a583b64c8e5f00000000000000000000000000000000003abd36736fec3e8b89863670666365b169d8510090a89007c7ff3a82fc62ed371544013a1444fedc4358e92ceec62470000000000000000000000000000000008229855468fc63f4024938cd6f41c6e6a5653319cb83f38ab7efb9e9d281166261e7c854bfc08f55a0a9ca47e54dd42000000000000000000000000000000000463ccacb341fc5874f6ba2d44efb5cd24e9409b2ce7f43e9d39466288dc833a45988261f45d34332f416a68c5d10ce80000000000000000000000000000000002baa086177394203a04ce1b46415983399e60986531967b690b1a13cf8ae039b56f0a00bf9aff357d51ac57f8fac8b282b7d8b8b9345bf13d0e113b662141f5ebfc5888a5ef8ea06f7d5d137324ebef000000000000000000000000000000000b25a203268100df0510e4155c594a144dbdefbb0ac95e02bb4b3799aee4e738ef4c52f03c6937cdfa7275c28f130778000000000000000000000000000000000c432347a2534e86e90ca346a7b8b40f45075727847fa3ae2f2e297baa14aca88ac6e08342f0d248a92e2c272841fddf00000000000000000000000000000000057ec8099e1e30329762ccf0641b45e1a226f7b66b80644fd551d6fb1f2136afb8e8ab5c6905ffc7c24e67d7f21863e4000000000000000000000000000000000a9e472aa993bea05961affd6782efe8f50d746928efb8fbd328fb50a254db861c90db8df7faa7da8266ceb47fa1a13a2396fe15751bca2c4a651445cef236a865269849908df53551802dd378b892cc00000000000000000000000000000000025484652f18e2b32e2bbe79916c8bad42902db5528fc45993e04daeca008f3c2ff38fe4b48c292f70a7dc57654233400000000000000000000000000000000008e403f472b60a6046fd190544a1d6b249dc97cbd8641c62613f4de0e0fa9f5456d843ece4ac2b9f4ffa2c0278e61829000000000000000000000000000000000824e0b9b03198597fa54252b3df9690df678e9c6d82301848939dc55ab25a7751bcc2b99786cd31960ee7030bf68ac80000000000000000000000000000000018d1d8c7f2b20f0ba66db616322e48ac8f1d6f4205f228ee8ee6cd13d1f64be9af338c11f511859baabea3e15d165fc09a5897c9596223ca4d6628ca1f793a000aa21a739a37faa28637692b754148f80000000000000000000000000000000002845c4255819ec6e97abddf4c9db7d91658dd1d55328ab0565144b377e20ca0743d93fddf68acc985ceb7f7431e30b0000000000000000000000000000000001577a5691f2425e65ffd59071c2bb167ad05a8fe23c11c7f7464764442ebb2f7a75a8d02594d4426c1ff022f7a6e19360000000000000000000000000000000012c6ffefcd3964362f1373348404d04d1849e98ffbef7b5ed5704d74b9550869e30a4df26e74b5304b85c7503f7487f1000000000000000000000000000000000faf3dc42113f27ac27aae36725221d04fb1ab46b59e16277be0758b8fad706fa237c0c7627771d8e8d3ad610f63619bf20a2973faf886556e5329363bd9b9c96424fcf2e953df90bfd011ec07bc66eb00000000000000000000000000000000044de166200ec06bcb88720e57b84cd8f9534d1fe303a26aca08cc35104ffd7e81a6473c08b28037118dd8a61d090e910000000000000000000000000000000000f4325ebaafc67945de2418c81f5da92da4e67866ab5965eff0f392cc527fc34ba4e7e16b91c26aa370b27eb6a07f6b000000000000000000000000000000000e1d77ccc1c196cf1cdf0dabbee4829d56e937372e9f5613e261ca07e19b3fcf10f7a45c490b98b5a64b955eab5c4f2a0000000000000000000000000000000004ba2e81f901b0da1ead004c76d43278d372456c0c0a8c6752597823d44994177734ed3f355aaa22f325ea36b7c9eba1f4ddb773155a27badba330ae5d26096f350e9ca2811feb227c4eee09d2baf32f000000000000000000000000000000000c115e270ffd6f2cb9bbb2a62e04c3bf7be9d7db783d292bed272c297773b39e9e51c75e5c79a6606ff7d0bb9ddd040a000000000000000000000000000000000a57b637126b16b23bdaa6a7cf2346f33778cebdc0c9943eb2985ba5c4114674cd596ecdb6959791139c36c22148ab8300000000000000000000000000000000177c7ed16c29d99d3d98c6facca9cb5ffe72e6aa63959dbb51d9382f0fa49b02a1652a398eb223e093516ebf134448c4000000000000000000000000000000000d6bd518678828f582fbb3b1bef725e66f442c4d3e6325fa571e13db492300d03c0188399a2ef9d5687a76e647873c0f52e4030b5a4bfa767ae20cdea7f464dd2dba51c9c698556d24b8f3d4d1afc82e00000000000000000000000000000000085d4f90336987f99d250067c2331e7de8f09a80d71fef0570ecfd99e409c1f405058bd3461c9f8ac5ccda406db89bca0000000000000000000000000000000015f310660ca6a0c06b458d0b840a5c1c476d5175d9ff6dce6334466d363d319939572a2b00662247be1ed0f4e6676f8b0000000000000000000000000000000011e9352c0f81bd3857806db678bceb2150848f2224ddfc43fb0c733f0689ab4fffde50d5ce04d54055d27d7702e5d2d40000000000000000000000000000000005d835d04dcf4199130d6a16e86cb97f4ccff58c496594b83524dcd88f5570212f06b744379288f2a737c7a82e897cedd32e0429e7934faa526475c5c7fb977c3030ed74e145eba21af2d2cc8461580f000000000000000000000000000000000f7c4e621c37bd3068a972b9d4211abf9026e438ac7f8cb341516f7e6aa4d8bfb3536389e9155029ce9e8d5d376eec1c0000000000000000000000000000000012a46cab2624797513f2acaefa26fb22c4bf29188881690c350593fd1949cbc243c9d1d7d27d9d76aaccd347359a45660000000000000000000000000000000002dc383d4f9b75907f74bace1769bb5bb1b27a597c9548310f2b5f90098596fcce6b5fe0c72bc8be9037fbf31050d74e000000000000000000000000000000001900deff7ddc62ac302c941e1d2a28a4bd2351edd7700042ea4c4a48145ef91688666d8d7de503913ea259f0b58809f21f700d651c67ca5b8d95fad1a8e412befdf691b074956bb8092938bda2ad26940000000000000000000000000000000018ac8048d58f7b1a9407d3101824e3640eb20633f8ffdcc97d43d1b25329a2a1e91added42801c03635ec904e627eb690000000000000000000000000000000000b499fbdbe2ed41dfd6c454796e1ba57021f355a4de8f60964c78dc685e2ffe9c90f5a1f6c9677514ae4a9c95c8d6450000000000000000000000000000000009d10e5e2bb69ea6fd820778f75a2a60627802a49128c3f999d8c1cc2ba56ed18acef354a2e06fbbdfa7e7a4ade7529a00000000000000000000000000000000082839d66a18763656c2ef7196a1d83bd162e1f109b54c5a6095cc7c436e8a4888c4001696958270f54f61b81b00b32d83052a3bd7a13bb1ccc22b9519c7ab12d2dec67924fd9f15f96069de22e7b692",
+ "Expected": "000000000000000000000000000000001463ac5e269d286961036db48ae33fb868a28b0dd828c3a66592ff9dc115303bdf3ab78a8e1f5df68ed1f3b4c6c3f2440000000000000000000000000000000012c64ca0ac10ab616fc733f75fe6181814e9c204f9e4eb79487ba49e3a9746b9b7916a1d768f2ec573a4c4e226365f48000000000000000000000000000000000a06b5b745dd92adbe1f4cf30c79ce0c48428b3e3b05af1585c4ca12eb2e763ffff46b55a060913e1f77fc9b0b085c9f0000000000000000000000000000000006271931ce9c8b9cabdc932297f3c87128a5af25a9f77e71ea4e588f1e88686638e89a8e212c92f6472692be2e05fa5e",
+ "Name": "matter_g2_multiexp_55",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000001bf5b74c1ac89d4bab4663943e19128619731e315d2d7b39675f7c43493b338020190a72cc7a6edf0b8838886a7fe6000000000000000000000000000000000713f413bab7919cd57c2de3349394121d6bace3c10df0e41a0ab895433d225b05cdb1587deb93ae6e56ec26a29c39f4000000000000000000000000000000000dfb11c9c0bab7e4d1ee39941d5f6b932ab473567be2329c94bb0b146c46fc1c2cda25dbef8ff9b0066bd4ca3b6da67a0000000000000000000000000000000014e399169243bd619be7f2120b2cae5d19b2f04185aebc7d948007c4d3345a9f45249273b6290c2e86448648868ac552c40774f67a651ad70f17393b386e9ea9e81682ffd78db7fbc17cc5084f3c7052000000000000000000000000000000000a67bca1f8a0b386b2a67158e80262f025b225535a294394584118f9a701e31e91b2c7eb8fc7e28538966b967c139dc400000000000000000000000000000000185e8aaeec9b9abb9f0d6f34e2480e9abc30208eb1c6e023d4986d544b356a387c323c9edb5c52f5a2f0bd59cca7df98000000000000000000000000000000001877ce1ca6e8b30df86de688d950755f2708fd6f933c07ae45fad1b3e43337f1a8454ca5d2a80940e8fee98fffe953a700000000000000000000000000000000117a0ac9d27292f967ff5bff2ebed5d2ddd9f453d6aeadd9106eb52b53447974561b621fdc1d973c055f1cdf824c367bccf1e36e063a5fdd4b735dc18bf07703b80c6b72f987c05641612d7ce73562c00000000000000000000000000000000009fc4e9e816ff495dbfd4f745106fc90c023d95bc64b809801d02dc7cead905177ede5016f537243660e4b7f54a02ea200000000000000000000000000000000180aceb6e9851a11a1e34502897299e7db3e09f4970337612634fd9848d1de2bb3de8ede690ca051a75add5810ff777600000000000000000000000000000000199f3c43d429fe8f73e20f81ea00c4e78294eaaa29fd67563664381db3cee2186b387b880089cf96fb99c2e22c95449d00000000000000000000000000000000040b20ec4e685f104be188d0f15a79f27cf34dd01f813275f6019a9ffac56e234b6c967c80745294d9fa46e0083cdd907ea75dd2f54fa6413ba77f10a11e12abea3a4b947116e1e7c9334a0a37c3963100000000000000000000000000000000189fba635109ca215bf3a09c3e44ad65f7eaf653e0929aed39042e3b9c8b1132c5fe7cfafddfdd0646514aa1f9e7e1c0000000000000000000000000000000000c28f598c80ac262ec7a0e0d1c867e01ef26f182c5df9ea7f88fdf8bcf3a5d2f06128526b1ce72cead8ab4286a0b8d030000000000000000000000000000000008051be3328df43b79dc9040ef0a0263d474acc0edc023f300cdf7c13088d1bb21b5f37ed81b38dcf8718bf6441605f8000000000000000000000000000000000d2d474723c6c246dc59e683be147b1a6bd6e7d3cf12aff7b636802a99954e7a13c9ea429b19833a985ca5649b1a998f6855c61bb7d72b022c16290c6d3ca9c1255cede8e0b827b43e40fbf01840397800000000000000000000000000000000058bf424fd68aac77c42a046f78a55729e6b5b3fcaf436d0d98354b426a95904b55cdffdd9a8892c9f56f170ca8811a600000000000000000000000000000000142c1ded08928fd155b89bcfaf9c8194f4569b4cdeb3bc7286f4dd79e822f5db497768220533b71be8c71d121e557020000000000000000000000000000000000a9c753686534bfcc295eba0a617f86d7f9e78d3fe6d52f26cede97a5b1f107210a757a2d89361645856b7b20e89185a000000000000000000000000000000000f745541841cc4b5352f659c2b7cfa8d51b07f91b0cb8c787b4492bb4b94ea27117695416e2806e57c38d7e565b9eac67fa8503101f392a6c6c27300b6992af3fcc48d47f73db67615a44de883770d4f0000000000000000000000000000000004445d4464b51d6b12f164a49ee3b610f11738d60cfa6e02f8c33b168d9d5db90e6cc558cd12c56069571567d91183a30000000000000000000000000000000009e4b96c2b533a16803a36f8d1f179313b7adbe6c4b90716855474ffb2fbe087df3fc0b4ef14cda7d958efc5c92574ac00000000000000000000000000000000104dff7c859eec61a0ff8e0d831bf9667226d5bdbe298400b4f9e3159a64b1bbc7cb9f4ff9604e3ced40bb0de0455ce300000000000000000000000000000000134bc2461459ed6f0d96aca02b62e3110c2009e1ba7d3258656e9cf97c2a1685faf1f61733ce6ac3af7ef4d73d0b43b1dd947617bcb7ca1c8fda0d49e6d950a84d60230bc2411d42ac32e3651f48524b00000000000000000000000000000000104e5709f8edd71f50eac1770ff1c2b21f5ee8cf5a310fd1201109d1b73cab69913bcfa2d27a8ba16d974e9841586ebd0000000000000000000000000000000003a4bedc6277c61825f6ea1f438c058a1afd494c384689a8479195646888eecc7953b8b8aec849fb5f19a20071261336000000000000000000000000000000000856ee8eafb9b3d25fde7e38da4acec624d1444337b87b0b1a660bf497ff37929b1ef9aed8e1fb0ffc6cacd8f0d1a1a00000000000000000000000000000000011b52192c88264df56de3d7b14372443e25183bb816ea1c0346f15a1f324527ef8531e27aac3112e2a497a0eff0d5485b4cbbc6d537ed2b69c2c32c84f3cea3d2db180b64861859368e98aca32bceea6000000000000000000000000000000000a696c83010719161b6624aa7756e6e84980518416554ac045a93b63c2561a68ca2ff2fd5b6d2d667822ae4e3b3a2ba2000000000000000000000000000000000fb8fdab4f177b0dee52bb5ba615b1d548130deb87b14d05d427984ec148a7a94efc4674804b3660d0f7aae2b49f7b1e0000000000000000000000000000000004914c0359c8e23a7e431e517cb83e5735cb2876e8b53ad45abf1e9eda06e736378ce03ff75002374d47f1bd45b08e8900000000000000000000000000000000139abe340c2d773cc45cfc75c47ff31b2dcdce27ada3e6d6c0823f37e4e693ca30342fe41eb96dde464d14668eb72c5e457bcb8c44a2d9d1facb39ba7ec8ede5d5962b3256d9fc2e68a1ee5a733ccbd100000000000000000000000000000000180345fc01e3fa349c45b1a7fdccde5f9ee70d7d65510e8b4bce654f2541fae7641ad86f9bbc1f02e93e94422433f8b40000000000000000000000000000000006cfe7026cd423be189c5ade8de197aecbc9aefd4cdbbd2aeacda816247ad59ae06a5c49b0e29bf1140f400d46845191000000000000000000000000000000000cc4f240a317ae9ce75b44fae87c92fe9b6de10e1191cdebdcc37ac200957683849d8a957216676db1af51fa0a2a1136000000000000000000000000000000000ba84d595661e5d9bdf9d268a3cc575fbb6b0d469b58b3e43f80694c78f4e9e501c4a4f9c42ee4518ed7189a1c36ca0c19f254dbf75f1c42046343b0060e71302bf6c94ca2fb8aec74fe7a47a3c9c3ff000000000000000000000000000000000fdf7e2372b01b5d926a18ddd06b4573248c02d7debf944312dc06f76ba08a7be460c451d296b71e9e81cf0956b974b80000000000000000000000000000000018326d0e1bfb4a62ab6f772b47ed7188035a62141e6b2eccf53a299028902a172771e8e46c0b1ac4833ab12045922b3600000000000000000000000000000000072107574145c6afdfc7d618f2dba2b8bb01d92007dafd476e4ca62e6053e5e9f2e34243ec2dd16ffdbe3488b925a0f000000000000000000000000000000000070e8491a835ae96087013b0f8da267a7ca5b0a600d71b8c76fee35f41d8b5c1ad82c5170b0e8d1cacfc7b7b13938e96f08cf27a47d89ae6e2ffb27870d613b9ae586857e4ea00670944a2883ba325af0000000000000000000000000000000018f4da37ff63f66d68c875def8c758d9a5adcdc408f0c12b3a60ee4a285e6702b1d5b9326c61f443dc71ae83c7bd21e80000000000000000000000000000000013a665e430141cff62c25577798473a645d20321490bae7689de6ea223a434c7d3b16ad004b24a82e2c62879b2408cf90000000000000000000000000000000011b0108562f53bd47d9f8ada54166854bf758ef3769ca1c3b7b006fec8707107fef0b6c7e59feb727646b74c27ec699600000000000000000000000000000000028799b52107d8965066e2f629b30c0edb490a0f4d0b6cdfff89a9f7763afbe6217bd42c2059042397b6c0443465fdc050aa333bb6b44086fe6211e89cb70b8467eccc228c09aaa1d589cfc24771a11b000000000000000000000000000000000c42cb42e389f32926ef09584516249ae332641b573ed29bc0884feda08d35c1bdc6c3d4a69fa15105de95010c6cc24600000000000000000000000000000000006c57fbf93c7959c562e0f3ef59966c1640c706fd18a6b539dfd711b0ad79643642038954bc866d42d1c04be375b95a00000000000000000000000000000000039ca3ad23b71693e02af36a4abe6ccd0dd4f4aa709f74d900b9fd015a2eaed55bdc2bc0749c995783a7615971e8a1f50000000000000000000000000000000009a08596b29da34466c8a7f46b805f1b6f2e48bbba614d728562981d3d4884de9a3c1980d398eadcf69e90c851d48526d9f7f74a5ccbd01afd985d3259739023cd012cd67fba3a4ab5597e94d8fad43400000000000000000000000000000000123dde5bb9b7ca11da9e08a9489cf07d147492be8041a5ad0b70715147e21d6017a58af23c47d77885a7830cfbbe5e0d0000000000000000000000000000000001527cec3c393d03e74ee8a7b1d6a8b6398945cd284b59a93fade9839863f0af591c287e89b3b45e6048f2f9b518208e0000000000000000000000000000000017ac3a2d9458bbd5f38d584b0fe4b35f3a452e22161564a7582465d2068b3ba4dc5e1e24a996596b1fb553d641996a4e000000000000000000000000000000000ee5ed5610a78dee181750e35a8ab91c001446f04124930c2ed85de74c6167009af45a6cbc3c59c4915334d7853ee12f85c00be7e66e318bed8e66cc41e7fd0593004bbca20f0dbc28efe4441acfc9ae0000000000000000000000000000000014d60c1d436e4486f35ec85bf2655ba6b752a36c86fd9088c0ce46363e75abd636052f876986fa0f4a59152998c0e4a800000000000000000000000000000000083328e38373f1de1049deaba78f568db818b1dc38d981ae92b968134d369ccc399bc3bd55c841755beb484cbbd60f4b000000000000000000000000000000001788850a5508d81df9af1f087356bf8e63b3c8a4e209403c4de7b3adda07684a08f9de6f1f8fd8dd4b2bb9b75be329cf000000000000000000000000000000001506a37d222173f0098f56b7c443e04ffe08b376e1563344e7bf22b1c9df0a1292f70ba51cbe554843fb93a7f535a4aabacef63d90ad11bbdf0c5fa2db2838c238ad3049a3f47b7f67361825efbc6526000000000000000000000000000000000d5f153952defdea9309269bc996a7714deab12e7644f8f8344140fe53034de538aae6c3af7b06687684edcd2c5dd19e0000000000000000000000000000000002da67345153c87ca65012b8703acbe777900953abaedca4770fd893275948d150ca3d6694d58bbbc9e62904448a8d2c0000000000000000000000000000000006e8c95d22f01fd9d56178d754f0892f46166282a27e6b02826478cd39119636e811c03fd835c714a59bd2f7da5ce5e1000000000000000000000000000000000b5ab6233d8dff50648d89cd65793640c06ea784d00aff329e882ae04fb466506cce3fb6c381b4eacef8b5305953f7b6473fa3d16e6431da14b8639d4fe316692db087a167a2c4f07307e770bb9e35ae000000000000000000000000000000000595edc440a5c94506a79f3b3fee818256d7c4185be40c1953b46765b2f925ed16a476b07a267570c727592dfc4a0d8d00000000000000000000000000000000079ad05473fca57f26fd068ed659e4aa4919847dd96e683e7d4b3a731cc9ae0562a693abeea4fd550e644b43b553118500000000000000000000000000000000176a9751dbfe727a442797551254cf904862c4d590892e019a54b72f6a5a124d268777b82e19d557690ccfb81cbe949d00000000000000000000000000000000164ab74c150cd151b70fdd7d63d0404214fc9cdafba3bc642aa798b1c301c287ff6d05ee7b3a3ce997072b8189d54aa62774741f87af1d6942dc4ed79b70b2d706f3db6b6d083eef0475334ef1e2410a",
+ "Expected": "0000000000000000000000000000000017d73e29f1d555a10272043ac0900e80883c185ff7d087ee7f5a3b762213e658a42d1b4fdd435d1acb9d5587fa7e8243000000000000000000000000000000000ddc440795d0e4308577fe8439d43418641538711972c9744dfc8a4c206c193aa17958404bc387c7c2fa30bc678937f7000000000000000000000000000000000d7e43c0f99adcb02db99974e7615b4ca0de72117792ea515bb04c4bc8680a3fdb0afcf6a3bdfe16bf54c1d7336aa185000000000000000000000000000000000bcec1d7fc9f2210be80e90631810987801fdf60890ce197db041b6a62682fd7e181c6110956c5f5e9c196049e39100f",
+ "Name": "matter_g2_multiexp_56",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015425cbb7075a97dfa9409d7b014127396056dee6d4bb63ea285309fd91280fb691f9cb9572b544b332324f6cb3b1276000000000000000000000000000000000c5b9634e6748d5819396051322d9b7e0377554613a7fd8dc0c71cfb7886dc0ac29add7265af84087a9df5ae3799ae30000000000000000000000000000000000534226ad7324ed5600b5438b659c7b1e96f27ee1d77163f2d3073418f7ded5c613ca4b1a686764ecc43ce3388e0c32600000000000000000000000000000000198267e2bd474dc0415f47f5c87a11fe0945a91cc0bfc37d504ac53f9b9b0d087cd5dbc9b03972be03d4b3f9d2123945d10ffdd3797ad13e65a1115cab6529d0f87b91eb41d6265e694eed8f02667214000000000000000000000000000000000389a084d95445af6e0afaef21d3676794e45986b9520035111ccdbac4ddc1b23974a686a900616f878f3a06eec90db500000000000000000000000000000000064c75d1129753b5f399c1a5166a0f6a8f427d65ec2fd84d0c7339218e0a396681797bab68b33653ffb9820a6005fa7500000000000000000000000000000000147e199e8c08b9af38cb457b623d0fff32242b11e695f2adc0f136c5596db313b03c2466fb58e37c94704152e5c8f9dd000000000000000000000000000000000e8fe5436baf3470a19891b85d15486d1269e1b13098d837b0a510e71b0e6260700ea85f0bc6476217cc73615370cf003e5da5568a9427e0cbd7973a34c147ac2f3577d06f68280caecf8588ebf1591a000000000000000000000000000000000a39a2032858a57ccbfb940741f4ae21b318a56d5567cc0088ed52dddf1e0d5de60bd2da9b675212a9a28ec17fca7c0600000000000000000000000000000000039e2a4bb1b417f8a94b02cad60a3e1c4c4bc5a86a23def7cfaecbfd97d89a5104e0cd13870c9fbd010dfec3ad9b1df9000000000000000000000000000000000bc29c5623f9f18ec2af5bc651a65d89554705a349923ee15a9bfb82c114246b404a1dc1c24d65c8749e7c9cf62d963a0000000000000000000000000000000001496d76f7b8583a64c1627151589af876a2f5e7677611ea15f14606538f6052c56e9fc3ed145c313acea69a51547fb6145b5f1f156f3c823cc129568e7602694107608c1f9545edaa897df58d27b18f0000000000000000000000000000000015f83b2f998691e504aa740b4db38f5b0236ece3bc1ca933b79999d55b737bfec51e590c2127d57625a9b7c2960c06280000000000000000000000000000000001b7b117f5d722e320b7e90307ac1423aec5e30c29602d314bac9e5272ad3990d31999bf3f516ac78b2be0e16c0375d8000000000000000000000000000000000fa7992cd7fb679eb5f9f9a9febe9c3cf41a717c8f6fffbab5748572098407174f09457e13468165f1c7275d52f6c84b000000000000000000000000000000000737e95f62aacd12f8aebc288c5cfe052f34c4d16e7b44df4497d9a713b77485fb0efc09aef11c7b86eec4d0cfd9b03ecf6760be82cefac2843265be5fc0fd6d308c1ed06fc684c4693de25372f09ed000000000000000000000000000000000004d48d72ad4e77954ec6a5a62299f0472bc52b556cf3857019f8efdd694758f13029f9d6832ed672cc210f32033da8d0000000000000000000000000000000009b2394755d0319741d131b012ba0ece7e2044def20ae73fe73bcc276af9d807ad75be79202963f9a5c512a6ca53197800000000000000000000000000000000128f856fc4790d9fa68cd2a3c152d675453dd81dd64f0ab084c6dabce456f78c2bab0e7f315439b34f86e8fa61a33ffd00000000000000000000000000000000173dbb908ed617ffffb6aeb212cfe6c03f7ee51c84134fde67de2ad9561a897e28a0efa66257ae0c21ebcee3fe4fa68cd9fca4d166149ac9e6159ce95a06f790a96243662373637f0c6a59764b77b45e000000000000000000000000000000000bb7b84476d4b17f4ada0b6f50d34dfaecd611356862895c8d2fee6707c4aedbf565560d4207e43c179c5cd33cbb739000000000000000000000000000000000112d8b10c775218d318090dfcef55a903953f7466c50417125ec0b2c20a24fb50bd172331c0377d4f47aec99bd87a3fc000000000000000000000000000000000cf4e4b3c600053f45f350c8860e47621f50f3849872a91ab115f71a2b04657991217e2f0844b296d3a6bc33ee66e6a80000000000000000000000000000000008f625da164bc9d96be3e78df63bd1633a2951dbea0b98e359c6317abe6ac5799c4bb00bbc2c5d02048539e753019a6241733039312347a0c9d760c1bb9a1209a34a02b359a9c52a57eddced1575867000000000000000000000000000000000028db057ab9421eefd1fd481c91153b5c1ceb0f2dacb0097298cac986f036572c6ab0c8709325b3bc25bd494bb46c55400000000000000000000000000000000024be09301c9be4f726fbf7796e8336c50897e8534614c25f65c37bcfc6e724d530c2782bf483668fd08e91ad09484af00000000000000000000000000000000037bfdaa11660111ce0a9c3e18b5da74c004cb44882b1aea4173e18d3a17f04fefa3b319afaf4af9dbf3d4b9ddb2c3a00000000000000000000000000000000008f2138bf621237a286229fe762968a224358b030f6c20db58043c13727b516097b42d47781bd0f0df2b155197ca3946b21b18d883ef62084ce4bd353d7434d7e220e9cf6bd0e8d0bed1ad0a4ad94c7e000000000000000000000000000000000b4e2b058d6e77cf95be093375233e5c9c8ee0cb2a3aa93172c08faea111df81b9721a506180b7b45bdde4b58b0b7368000000000000000000000000000000000f7025cc33424a7c11eef47baef888535d938d50c0f40eb83ae86791834770e5dd95b30aebdd2c13eda3447d5730ce3b00000000000000000000000000000000088270ef05480ef8aac5c284358d8e06c3482c26279734b8513000019924cefeb396ae79f5d9bd863bdd9b22e3ac3c54000000000000000000000000000000000df75afafb138fb06bfd905c87035bc5d18c45a29267c3965131083d7e0112e10556d7693d424172a53e8d3120f0cf2aeafb6aa11296facbc13936bd2ba09a2cf9bbd9dab6ec8cc5f73d78c90b471a3000000000000000000000000000000000122fdd3c83c01c7cbe71f54d783181860e7dcf8406e3966e910f4d0ccddae3a245d6b1f94b1182d1917fd63960cd75d400000000000000000000000000000000043592e5797cc1409d6d42dacad628448799b24320acbda83f6ea9d232968efd021058f540e3bd73a7f95761efbb5fc400000000000000000000000000000000025b5a8577ec1064b5c557415a50e84c2302df97eb65860f979e5b1e261f47c0f305461681beb07e521cf03f0e21fd030000000000000000000000000000000017e86f3ffe72bcb71d46661a1537918d52e886e362d78ed756140a6b5083a4eebb5280b9eeb8a25251dec43a5cf509b13d39a61323c07f9f4656a6c5e6ba139da8175ebfb8a641de50cfa2290884662900000000000000000000000000000000122f26b4561d1f79a70bd0e401f25d50891c0fa0320579ef21aeed7c191fe1c75403a09260c3872cf74b798eb1587ebe00000000000000000000000000000000039a261d9f48b9eab6e89046f333ac328cea287993166057e9b99fa8a7d7eb3e7c34ecbb353b7427b235084f47f45d1100000000000000000000000000000000015d5e297317684bd0169c795d9dcd209452d024ef9a450c41beb0f6c7e6dc5fa0f3ae24c7cf2d7eef97bdc51788188d000000000000000000000000000000001487564f0e9d3e0d2d30ec9930a00f10093e29f2f195344f567960be323ca21231efd8528108dbee4d5ae4de3930ddedf6374d0849a4471eca96c5e715b10505c4c49664f341d04705fc688c8479cda4000000000000000000000000000000001965ac3a520c1ac39b86832ecbe226ae0474b76659076ccbb550a0daf41c40d424ceda084dd991f22cc53779085828430000000000000000000000000000000002e970a4248823049bb4339d21583fdce9540ec103d6e9530b89e39ea875b1c333f7f5f859be39baad34b374055baa770000000000000000000000000000000003460eafb3e54ec03fd5cc1d460e1359b97f5543e6231d61614c1225ab7545fae079ac8e65668b83d022031a7a54746b000000000000000000000000000000000321394863e7c70df3934d874613b7c9d6c331e59a599be593c82edb7a26eff9bee8e4befbf122240d2deb2d527bd38c0b7cb52b99abe10d1367f8d3def38221c18657a1114ceaa1c0673ab13a6e10870000000000000000000000000000000001a5eebe200ec041476457f8585cb4ccdda936cca4977d7701c44e0d4fc5d9c206682a23348013a055117028c16914400000000000000000000000000000000003519bd1dea70245e521988336eb41870599a877380c0a9eb19301f9b2caf963eb559070e23eaeefa4de0173bb1fbd8a00000000000000000000000000000000125707f5a8e26b28968dab97ef4654c315b0a118c20935e38a5a526d9ac0a0e18355d8c9f3f58c082de98691957e2d5e0000000000000000000000000000000010b58dd683f73a16d8bd5557b35b7003a761bdf7d90ef576de8acd420bc74f5219fe7f9d35667feeb3ddf1d568b56bf1f49b1fa80a321d4d100069b2c4b94cbda255d8e9f1a7f14ddf4762b76e4a386f00000000000000000000000000000000018267d8b83ca59d4efce7ee3d73f7b984f09556ea4fa5cff5997a1eeeaeb8bdc9185176d77ad0f4d86f2e429f4015350000000000000000000000000000000014114344d6b7c976cdaf2418d7f72c120c2fddcc65c3ead067482e7073e2a3a239af19f862ad247e3181b13f5236d1040000000000000000000000000000000015db961a093b248e83deea0ceeebfc3dd57c7cf8b48cd627c5c566a4f9bea30ff0ef9cab9287a0f520a72b02d9092a0c0000000000000000000000000000000015159439fbfb91d1e24af611563aee3eb498fde666a1014a9f645037995d72dca0ed5569da7ecd084208b7c228e8a2b2ad3625b0839cc1ab8c9798b2e9706ba6d7aa623f3c0ce0985bccb2ee5c05a313000000000000000000000000000000000e1780b32a7b17464cf514efc4bdb02283af396ffcf6d1ae023e07fae02becdcc3c467f89f8edc9173a71aad27b200da000000000000000000000000000000000c3e7fd95dd823338bdf3d82fd46c265a3f794d4065d83873b1aca66da5f80c5962c9dcf537fc315d024d8cab7bed89d000000000000000000000000000000000e4eb722080e24f54fac7eed4b94e7b1eedb081c3edd7aaf5433d00829929d8bdef940aedbdd7dfb0376b3ad5544d9cf00000000000000000000000000000000158c1ff057f7ffe6492097e339cc4ce56bbefd39658ad55e08d5407619d1cbea7c83b977a1583ee48897a5e9c0d9ce3e150e53fb45ba8ce5ca917010f26451220be51141fe21cfc1cc06a5557e8e7afc00000000000000000000000000000000138e8bc8cfaecba9fd1322a3c1682c9fc1286d78e5b6718da00acc69f811fe9f94c9f0dc9d80e9002c0022c6dfcf156a00000000000000000000000000000000021da679a068b2f5f473ceed588f07adc7f485003f7d2286a18c07b09b835881f4ab94c7d4ec742c33a7cf01801116fe0000000000000000000000000000000018a62c2f4a02b73f5a91f503b53332304afc9cd8769f236259789277599a203b8b304b38993835a87d7cc970ad514d2400000000000000000000000000000000179396865f859386df7c1b8fa84c4ee71c14daf695fc0841c293618e6f8c87fb56b924f3f91a273b969e8635d7f90985d69ec73df67feb970f1c7a3880ee84d948eab4d8672a6c1481d61efc6cd710020000000000000000000000000000000004a8cb437297722c0c1a9471ff083ce60ec40c908af4ebb570c87133df705e725e3209152bcff26a0d6e4602030610d3000000000000000000000000000000001832e55a9e703d727156e4677ef4f82b86c6764123c3ed1dd94ae3b46d7eed459114993968eaf8e21cf24c59d042f41d000000000000000000000000000000000f606d5ee57b188636334ad60057cec4008ace88f14ea06324edaecb26da627670b44b6ac57b9fa2717d03096010785300000000000000000000000000000000145bf70f90a9d98f56ed38b3506556a48a1340ca6161806d055d7a1382eed54e294564de7fdbf525b0012de3d25ab5c838f8acba4782dfbc02a14d4b1d7b2b0a582f9bd75642169707a475b1a7d2d7e0",
+ "Expected": "0000000000000000000000000000000018ca453b9d832f029ac8c7c70df846be97b530e6e42de3ba6943a7d0dc00296942f88eba6a9cc3352900ff124efaf7d90000000000000000000000000000000002e4514102aa3f772f2659ae9f1e2a91c7fb749ea590a3cea2c1a2e0f7236f71e182374cf7ebd2fa086dd921c29013910000000000000000000000000000000007c025696cdbf403494c5fc7f9a10ad0c549f84d1e06c5c4bb22f7a039486909c540776224bcdaaeb3880ae9d745dbe5000000000000000000000000000000000b5b5b70fae8b3953ee6661a0f4a1be25596839482d78710e584d3bcd93dff2b0bf4c8b20974744667e25fd8353cec0a",
+ "Name": "matter_g2_multiexp_57",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001265e90c564693db716f17d1a8815a8449e43b5a2d5446ca65160d864718cdfd413d5aa024e7581421c7222c29eb452b00000000000000000000000000000000133a6558baa53a2b8d239198e1dcd81af1ee46d55137177be467a99edf282edcd47b7861a3c822f9bd0df2e86aeb5dc2000000000000000000000000000000000d8287564bcedb1e57c3d74b0d484a9b475ce3f5b0322bda0e980de8891e2e8663abda99744b58032b8d7d3adddbac9500000000000000000000000000000000013cc35410d7fe07eac96abd2b35ff656e17b6b1eba2bd1d75ce5c87c5e76755ef9c2cce70f05cdec15d1bc44bf902d4cacfb05e5d10c41b06a487e9f8afa38759eeb55f0a5bc8640164bbb081c1fd2a00000000000000000000000000000000193f0cd6b4051cfd89f358cf6643528f0f042ae30ba3627d297b4fa2c2936426a9c1b65145b8192f65dfaad1f2fbc358000000000000000000000000000000000a92ca8943e64a391aa39126f093f2b530f556c1e3ea1b55bef1c264909dc93d260eec6420fb7a4e4a45f932d57951500000000000000000000000000000000005c7dc5832f744089d5fe034bc93e0bcca042ddd1b221cdd5958be86214831906ddbf82508dd91dccee467fd1625dd740000000000000000000000000000000011b11b3d24f44bcafbcb9baf62cef3f18b56ded696b73577375dae8108dcfb663d437e4cd9e44b7e6bf49741e058f8cb9a0b88d946231cc484550a87a548719f0a543c0698411f230a966cf602dc4de300000000000000000000000000000000073872ce0d74ea368df132897617aa8f941b67cf3fb395ca6c2f5bb2c551f17d68b0c6ef11e742206d6559796f06426c00000000000000000000000000000000156cc28eece7bed943c8410a44af112edd8576807e25701093eac0c9726f93da68a19c1d7b294f3ae6c84e32e7c2d5ba00000000000000000000000000000000050fe5987d5fa678be3d34c50fa6c5296f883e65ac3201c333b97ec0de00dee6187d2790c357a3f8822a174a534539a900000000000000000000000000000000177fee6e2d3909c0536acdbbdfc716f6ca19b6bfee7920a78ac9725c85114c69cd13152467e72270e35006b3c6caee8c74e3b5ff944bbbbf808f1f469a3380ee7dc37ebecdd8fcdbbd2f2561e0dcd68e000000000000000000000000000000000dd147bec9e0d1727c9d7597dea4a5b6b15c0a603dd1b586835580468148a502289fcc38194b2fccdcd8fdf0d8ec1904000000000000000000000000000000000186501fa4f3a20e80bf297e8ef1885b7d157617701839a3b524d61f35b2eb843ff0af13e253bbdef653a83e07a5871e000000000000000000000000000000000023eda2ed9d34aa253c8bf2f3b66b3c0c2551cc0e74f43dde2e429d9dea113a62572d245b44708bed79d662d9cba487000000000000000000000000000000001041cdaeb244803556e9b20db95f2a66830cbe47a68aea262865da50ab15ba658116657625318fe46fef393eeb6f3e2ec23064970a4ae4ae648a79edb193d98208418d3489e9b5b8517ebe99cc32b4d7000000000000000000000000000000000c27b1feeeb38068ee52b0fa440af2e3bcfd16601c8af983d259f2d15316b513ac3e89069bc141f02b934f2e474253ba00000000000000000000000000000000183f966cdb28f344ccae4cfda63ba6a6f29d00ab942ae7db7572cc09305e4f80c11305527b8ba38c40aae5f23165cf9400000000000000000000000000000000049cf59bbd6c26ab3e25b3cb94878271c73c0b4436573d612311feceed0f1668f4d79aad92360c1c97d60b540239ae630000000000000000000000000000000015f35eb8e4c40cb1297f7128d99b109ca75944c1943abe9158813432145a4a2a5663b55dbabfa48bfd9dd01907e1e8d3972fb60ccab83b6ce042c09ead82fea3d2cb891e21ddc5af7b5d8e334d5a3264000000000000000000000000000000000e5d9a671862733804f517dc9cae2190ef0005f26394e3161fbe771b9a486368871f4b1f10f405e45048362f437238260000000000000000000000000000000008100c6f96ae7af5fc86d9d91fbbefcc1bf5873dacaba9c3adf1b2833dd529d87f303a55e5d4098153377effd0f8114500000000000000000000000000000000010e4863a9b037d4ae6dff827a34be04c7f1627670b40e5cafb1fbca2fbf56af9ea6b24548db58e3119db64553d18cf200000000000000000000000000000000036a298ad5e8b32041a18e3f6c5847eaef20a5b63ddece41bd7dc4c4a54deb9c6d7002e6621aa01d78d64ec9991f68fbdb68c389b94c82f006fdc637696d8085b24897177d2992f504d4bcf5ff04d173000000000000000000000000000000000f62c0bad83c41887bf1ebd2644cef0577d793c2f3d67cbe43974f460a4afaf2e412fbf9ec97404e5e882ca0b23bd1a400000000000000000000000000000000191562ec9ace63ad2aae1f7fa977b9e0606e1da9775a978b2caafada4f6b3d9104562f2055fe037cd06df6093123a08e00000000000000000000000000000000156702c3feef1baf5ba202a25b9dfd5c1fc620e837501b0c5bcb85ec8b6e3e92bad1fc842bd1a0dac363e4bdf0fac87c0000000000000000000000000000000013a4b7e869ed9bdbf9671a5d8ca9145a2e97b6885d2a93b33f378e649e0e576be65bfe849119381057337315363bab2f4510c100005f2306f4b474d3843b4a79d04f0171afc5c66df70f631b0481dd330000000000000000000000000000000000a4b273438168494f0db235f535bf31893bb70f4119dc4741aa3c5e63e93b9a8bc001faaca10e37f36e130ef53853900000000000000000000000000000000010936551b148e16249dd934fcc83dee55279495c2a70d46dfc45945a69549657c3dd7cce00d8136e28d64b0c800344cd00000000000000000000000000000000115c053ac0b68573c3abd5f047b8fcd897e3d514945c5fe6efebf1921563d0079eadf32f7428ecb703d9163bc7811ebf00000000000000000000000000000000162e86af01daf552589b62be849e6176d74fa5da9b214a5cf2285802dbc44f346eaee5cc3d93a085740f74cf7e1b17e1dc682a2be4d67852d119795988c52230d8273648cc176ddc012a4b4da5a8636b000000000000000000000000000000000d77cb5045f7d4578621c76bf5b3db076661c72174508279280de3e92f0aa57057ab50180f0f908561a87d412636d964000000000000000000000000000000001853f9cdccf5e6e4b87231b153ea5257f52ff10dcb24cbaaaa95426d0231dbb355f9c47475d125ec1079b9bf26b23b560000000000000000000000000000000000fab825e06c2329a19de853a05c4bc65f16fa047eadba8e79607bb31b84ed6541b00f7f14b15687d67cb4cae0ef9c600000000000000000000000000000000005deaebb5f31a62fc0bc1af13da63d0af3c716df8c9bf00f1e831af5882b88974c49e8d35db2545747c85ac35156bb668af6b200fc8e6a57a954226d9a0254c8bcbbc55fd6c3db5cf8532323d4c50b4b0000000000000000000000000000000016faa5e91048badedcb33e83684d2670051c82b7a1d0ead0e28f4dddccb141a8ed1fa7606e4b6a3a893c55344263eb4400000000000000000000000000000000019b2c8758abe5d339afade4ad0c1d44d651f185f8a0030b81b136d5972510b353d43cef616ce04827d56255419831a400000000000000000000000000000000124b1e87f343a890fd690e384cd156da57f4f0fc5b1ca99c73bb0571332ec4c12d3ebe955e3ae792efadc1d5c0c67a410000000000000000000000000000000014cef10e4a9a41bf117aacd2fca5f1364a46b0c4aa0723a369fc6ede09dc76dcd8cb67fdf87ac49bd4bd9981a2e589647e2036f73e8cd5e42ad86914e192dd969465aed0c3b752986b84a0c2444c90b80000000000000000000000000000000002862fd5f38154dd452f65de0d3c1d54403cdd2a397ef416fb92e570913c543d3368a95fa114fcf48c3bb4b68895ba33000000000000000000000000000000000e7185443e5dbb656fcb9ed100949f8f7052ee2cdcba4f5c687a65a1b45bf66ede5c60b0c04845b9a870e004f8af8450000000000000000000000000000000001817be6d13cf2a67225b2eaf073e9f1614f3bd32cf5572766ace4a91f6b6be56f498b989f1c3dd3dbc9a819c029431dc0000000000000000000000000000000001cf41fe428b088a17b8ea93a653677705d5c024db530b8300752c6b100f2abe4c46dfc24afdaa2b3d53cd8ce0df1b6a70cd5c1545e76027c389645da1089fa88f675b5b6ef9217b584d7202b797f8520000000000000000000000000000000002eed272430ca3176988272e6157a18df7151bbfed5b90979752a02619ef467af8083208dcc9c7d926490b1283baa21f000000000000000000000000000000000a644f6137bde232c3a909b742d30bba096ef88b711ef100144276d0944487f9ebe8331483978a47c07d3a42c441310900000000000000000000000000000000042c67cdc10efa8301ae95d6d4f21cf152f04b235bad2dc5a61724cba64083f690b3158676ee6ef10f52dcc7061f7c7d0000000000000000000000000000000007018d0aed5abb744cb998f84140331fb2cef8d9e09c76176def48a85370c6247c2ac6fc726eea891b2041ad5edca7f0244041bcfc21ede8023ad80b6d4af4b2777c0204ca5f61854e6da34ff5e1145f00000000000000000000000000000000141c0edc966b7c845d4e68272c6a71f8ffb7fd8d56b7cabcd556a98422f830d7a81d123d701ce1479e84047328ac1f3100000000000000000000000000000000105c1164d721b6dfb05b6b69955b2f25db0e9fdb58600a3229dd516076087aaec05b837ade68bd2a19917eee7b9a22bb000000000000000000000000000000000da3dd97e693948fd6955ae52d493b3a2d2896dd4ad00a0b549d4d392e81593472e4f9435a8b7977f3d58e324c5b9af800000000000000000000000000000000068c531ddb26a2299cc584b5bbfb0235fd774a2447134c06e7de8b94993804958bbf1ee80728cc6db647e8a244462372ad7572da641373708bef008057aa5af1cc76ccb882bacc50a77b37d7047b1bf3000000000000000000000000000000001881432f4742dbe41bf774930413c98d49a781a48d6c64ee1a18f3076bc6c0e1214f92d5bc84ac65ee1c586c437d697300000000000000000000000000000000067e0a95f3eb826f3efeedc1882ecfa30b8b96c92f626aa324f4044ee74531fbfd50a221b1b0e0182d759d149d51427d00000000000000000000000000000000173f5be7098b756ea84f030e374973feb4f8811118ea6673db1db75ec6909303e571ec5a1d55a6bddf32fc80480cf103000000000000000000000000000000000f28540976a6ddb277df5951fe58e7310861af837cf31fe31c24f7b979f72ef1549372e7ea1ced15b655d24293dade7854b51c78093cafcb57c4c1f172d08257c379a9caeb5b5478cacb4887119a08c600000000000000000000000000000000188f296e218719bb9cabefd4f33d5728a1d280bc59c3d826a0f3b5338f92e6544a4cf36f1a493458e0adb246c01a415a0000000000000000000000000000000007dc8e4222c7ba78190a8e72ec7e6980e2581f51a8d6c41669b6fc9e16d50a2bf4d422af73398e76b2f39705eaf8a6da000000000000000000000000000000000b25a44523323301cc01b50d58726768c2cf61e691203dd34a0ce8d58fe4f72c1c33abfb2a56e0425fa9b7e2fe48e870000000000000000000000000000000000c6f11ea269d9061d2f462ac37401def1b2b28c47b84344d04d1f026add3237d99a586e3fcbae347a4ecb5646c8c569fae3bbf55186a89740af4da6c073d8c0e331542a2c972a49dd3bf65261dda6e49000000000000000000000000000000000c41a02e937f8cacc0be5d9f2d9fff0d6d4302fd252f32145974206463854b3a7d09b3b147cdf2d7536e970dc13613ab0000000000000000000000000000000005f9367f4e31f7e4d6e21664ac13d55f501f5368c1ca77fc439db60e1846861e6c4c3c44909469f88e02cd973499992300000000000000000000000000000000131fe6df7fff97f132bfcba1d2599a862c1feb514a05b4b7b0bccf49e00aaad043edae9346bf726e2eee498dbadf2067000000000000000000000000000000000e59044f0950a741da3881282697f4a1a522b026e493f6009227da4c0a963de622d5e421c30e0023f4118c9a036274f859b43915b15c509ab8930979312dea2ec9cfa9f679b004ee526aa5dbb25759a4",
+ "Expected": "00000000000000000000000000000000144433ad3afca0a9581e7e87220a4944e26ef2eef6b887ce77d2a2559ced058e7349b36efa66c492cc75b014b3448ef9000000000000000000000000000000000267b90e45d7001edae01fb198d16dd37c43cadcd2ca87bd7cd1f0f65a95148144f5ddfe75d344eb4573c1376aa2728600000000000000000000000000000000050ade28b09b0394b08d128c089808021e4c65dac49d9fb45efb93792a4faf210230b650fc3ce810fb8d11947e9af5060000000000000000000000000000000003b1d7dd7c6d944d16724fd1bbfe0f53b6b50a70e133dc5998c82b51f817f489bfe1e0c361be36fa41f5af7c1577f2ea",
+ "Name": "matter_g2_multiexp_58",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a081f037738b0d812da43a907e7c624e331108ffb72104d82725b9c14dec8449f5ba0e8c1a3f1379cad2c3e7aa99f70000000000000000000000000000000000937fb5d8b3c258b7b28555fb59620f114816f0fad46818a5f100bf7dc3332a03d285eda18e31e4047cb2606bc53b20c000000000000000000000000000000001574e355b7570043bf36ecd52f9c4d9ff556146d81a1e9d088444805db9b3b678fb55774865ad34d21022afea2c154590000000000000000000000000000000009f70a5cc658cdab280ed65e13aaa319049b9534a222217a08168047ee2491f25a9d2620c7343a6426bc54a0700bdb4fa53d5989b63ee5f157cc44c684ccc7cb4c74338b12fbfb534ea33db341fa6b460000000000000000000000000000000015a76e89c8938b8a27e4857aaae8c942371b6979605adf774827e9438ef739428fc53b65d32e4e152cbc6a4de42b8bf30000000000000000000000000000000019494030ae0507eeff20b69b4913596c1b9ea6927157945c8295e273707013ef1f2cd08c058f6b469a6c99ad73acc28700000000000000000000000000000000122ea7ac21a27ca7c4b00207538bf561f688429999332c45de7545046acbd6d9e96d31f5f6a00595eeb212918a28d2920000000000000000000000000000000018b023e7da67cb8d9159746bf700f9e151fa60ba8f5a28b3739de005822929cd28c49b9dbb4ca8a10729dd24771730ff4d840680013af06920dd06bacc0ce95cf0cf79e8ccc0b10027f2d28c1d0049980000000000000000000000000000000007811c759634904765029e955c3deca648fba6a9da6433b50a6d2086a59e65811d52d41ed8ff2e9bd63a4c0828bc702c00000000000000000000000000000000182c86cddf5e20697462c829f41c7b49e7976880311b01ed4d12d7174340799f19db0f295263a2617182bfd1b49e0d1b0000000000000000000000000000000011824bc20bd1b27876b4f48aa8fe3063f826b6b2c3dd777fb8999a25d9139f218f6f288955274884ce96ef2dc6d34d120000000000000000000000000000000000dd310d5e141e4eb13380db828caf74f62878959b6b2df998bebf9306965f723fcd4dae7c25bf2f79ece3e8e9b92de61b67d661ebc9008669bb4e5cffef81a32baabd71667a72f1d202ced823f09c740000000000000000000000000000000005667d8c4f8dc3f4aa0021d1026a1d0dd0bc3576c49339262e84d20198fffe33a389d28ab1d782e9d19af761a2f097b40000000000000000000000000000000002803d5ad6393d7072e149f1f2ebf70cd8961ba3bbefd648916a8ac5a5eb893b71bb6015e201dc241537ad5890024239000000000000000000000000000000000122e1d0e0859b04143f23c4d2d2ffec09ca2ce5eaa9429dd0c047032d180bcdb10c106071d9f9701c006e5eb8ef88130000000000000000000000000000000008347a7bdb3b4f381b58ed3a128134c09563b345380ec948943e738347de5b5737540b57c28d00b9d060c60942446617ee495199ebdebda02179432d42d5d9c76eead4d4993cd09a93d46cac997716a5000000000000000000000000000000000b26aaa46a279c482fb395ddb84d5b4c9c70102c336cd565ca9eecf62cb96f59f634adf46af748826590fe65beea752b0000000000000000000000000000000012cc63256a9f73f450e86ee38c54ea78baa5bf87d3bc01320f7fbd85bf11e19f75d787b9b12b8f2c7634368a9023de880000000000000000000000000000000006392fe611835f6fd50229725d71d435f704f78cabd1b5569e1c5a89d4b11f911f0e34ec034369f972a80eb407938b97000000000000000000000000000000000f4ff2d6a991fde9093000d7bd9cecb289383d259346d83bc9bf5389d4c39c82a0e1d7deb84b90ef370e0a19fce28d2b3e038e473d6f965751ebc5f69eea6f37be88cf001de0c4e4b700823d8326f17500000000000000000000000000000000193752c40fa0f466f7c8bd26658f133d0283d2ac3b02eadd27b3e9681329307f91a1512fbc53e537f9e1025a3d68a7ca000000000000000000000000000000001106d751c9e1637f00e51e0be856405e6b69421d81bb30b9b8718cbc9cfdc36c80d2848bab0d5246da84f10b478fe48e000000000000000000000000000000000827a83f28678c4e39c4963e95c2404a70691885788e5457e149c0c45d4e8c74eef55223ed15cd75fad9f7209a6ecaee00000000000000000000000000000000072667f02b781c8e0a75d0ed8f3d55e668ddcc8c61937c80653e240c3a744c961055c782ca41b15211c0f1e1ba800bf5ab2af2590309c9b9177e4f6f0fa06339fa720cf1c9fc7c001785d7145a3c9030000000000000000000000000000000001419629aaf0baf779feca264d0d9846b987506125b0049ebc8b307c4e3ffe00da1284a94a012bfd60456a4a937b2e0e000000000000000000000000000000000119a801bd0a5a1c1b25cebbbcccc7d2bed9baa4995483f4ae94121a8c6cd0c3f90a26234f51590d66cc38b8bef9020d3000000000000000000000000000000001125bd15fd9814ddd15be0997a6961b6f1c05ce7944514371f10c8e5bde271c4b936d6537d91ebed740fbefe6b281a0d000000000000000000000000000000000982a2904a524b1fafc50d540506b8fb07c3b4978310bf3cf53ce570b1b05e746981bcfc06d59a78d170573b09347f3fc9551f12084ad7d4ce346f841fef785d644821b5c2d3c8db3145fc26e65666bc000000000000000000000000000000000b1da333e508ec6b0329747fef35cb926d922091d4a45eab7cb5358f20496c66e17e46874ed9600cf4252432c29aeb07000000000000000000000000000000000c757daad8f3ed7dfd64782548eedfe904f7ef3bcc11eefc4781fb37159d07825a4c9f3fdf9cb3d8f3944277bf25f88c0000000000000000000000000000000011160e21503d6fd61a2ca0212a7d48317186f259a987a17cc3eb04a6d9251736e4a66b739a8f3095684b7d91ce6f79730000000000000000000000000000000007440ec0f9197352a3148f9bb3d3dba9b1d5add903e48b50ef3f6879859b22ea0e31b46ea4ce566930d8853520abdd14ef5823541696ecb88d0c71e00a15282c40d4826220a202be09c47fd6891b93ba00000000000000000000000000000000070ffa4d522df8b9f62aaf36132bb1b857e177280a7b6d3af6bfc79b73ad3848241df18ca7f8993ae3d67005ead9264d000000000000000000000000000000000e32b65bf035bcb11f86c60a334622d2367797d0226761b58a7db8c7324fc4bb498a558eec509c2326fbd0e7bb8d3d19000000000000000000000000000000000dd291a760393c6e962818986727e5ca5d46544dc47eb49dd828c6f74caf0599e88c4293881714c425b0697944faa861000000000000000000000000000000000f7ead0be081467f3371ab92c249cea73dedfefcb6aa16a162c06e30605e104844c3dd194b4a89ad5230f596bef64f19e32d695dd02323d40ac1eb9452cc53376ef941237563b1ee380c9824a565008d000000000000000000000000000000000ca545b53836899e507880329799e4c1a1acc17275f5d71d87b9e41ccd7a090da854f9936254448c988ec772a813bb6e0000000000000000000000000000000016c9b03fd01394560497d6a03add63c034f96744d96a13a4ec92d28719018d1eba1465e4332e53f37f2aec4d93d4ab7f0000000000000000000000000000000007019f5201dce326d5a6a1ebecf3fe50e22335593bc9d3e62256351c591f0a1a577d916055d79c0b4abe191b6b8011fe0000000000000000000000000000000017acbe72fe30c386e463f3e9b35a474b902f6712b30af88ef340e6fc6ec0fe2e606c7e26432c2a4de33a12e35ce41868f5e23ff8acf88d18e53bb31476f10fef288e20e818431f9f0d2ffe1265e8ea8200000000000000000000000000000000057f856ae648279f2b6dd17584e1388e4dfdc9e870db48ee6ef5f58389ccd4ba17e074b79ae12b728c59e2f91bac5709000000000000000000000000000000000e0f39f4beddbf05fd700458448067b52c11e963b22603f10d697d6b6286b1449b1663e032bf7bea48f2051d8ded923f000000000000000000000000000000000022cfadc1dc399ef5f12afe1349d9274cd595a9ab6ef7ffdd68f8bd2d170a4a783ce0a7303878d809a16bb8073d79860000000000000000000000000000000007e301565124eb66d59a70897f2ac356e7b0c1bfd4e3b57e508ba0cb5c9c881f9de86b91fd5133aa2977c8e81138d66971927817449ba5f053d0ed1e567b53b1179c6b62a554c8be6764d7ce203f74e4000000000000000000000000000000000edf3fdbfb03bc07871079aa4aade538a97e1619b54d0692a7f5f73d7fbc8abbf680ea3a99325e03c0501ef174deedd1000000000000000000000000000000000b8c1b5d3c926d7da6e0583f67d981af5286a04429e857b0aa4b1120604f9c8c93f04e763da169137416dc9ec4839a910000000000000000000000000000000006ca2aa4c7109f043da9cd90bc801404685db802eb8bc925d9d098e7af3d9f95ca490790b2b1c77995c050aaebb935db0000000000000000000000000000000001f40a2090b63f94f93e8b61b5ba1ac62a37548342ad81a9bd99ce8339435a7d7477c3b9cee9b531a1ecdc85a72041555ce5d6f0e44a20d0a0e2f1cc523455b001dbeef772d84b2599daec66b285027f00000000000000000000000000000000021464dded318cfa86db1e4329f302bbeca7095d910c4260799cd2a60ebb20e60152868e67a48b86f44000f267d11c33000000000000000000000000000000000ae45fa46fc8e043c3df99bc0d87ffc5867208fde0eaeda782230341a8624b101346f35fa24e1dd67ab200f5d6fbc8a7000000000000000000000000000000000795b9afedbb128a46c1eb25c52a71375903adf7d3520535372d9af5023dadb1dfefdcc0cb546e9d218890123252946d000000000000000000000000000000001852511855bb368cec51c54d95b430259f05dba6bae53b5c42d69f31371c30cb611037fbd81393a896cbdb6240114549d37f7bca1a59f65982294755ddf8af7f1c953b6e482fee854e0d89e9b269e0e900000000000000000000000000000000113b883c6bc41b0673145bfeccda414af45efe5710f436977712e7227f38911cbae851dbe03928f38e310033458eed72000000000000000000000000000000000853e32773ef1f95a3936aacbca50cdd5eed3d08dc467d7ee834487e445fbdaeddb0df394bd0c91fdb06d2883c4dadd60000000000000000000000000000000013a7f9cdebb2ec37fad172d31a717f4b538a8ee74432c5a5e6410460eaaa3b5f24d223b76bde4277097e93087b7136330000000000000000000000000000000003d6f141b56e1e2e400fe821524017cd972678a7d64f660c313e6a8910b72b5ac04328d45945077aa2946931c8dbd11706d0535e3728b9e358d9ea82df4f1137db7a02f79c0cd0dd672e24092bf7f6b40000000000000000000000000000000016adbeb3530f6b451d870b2d8292a01143986cd9890c79a64764383575771b8608ea61beb2de87bc034d3b8a085958be000000000000000000000000000000001125d7cf83239e4341c286fe0c8739e7013b234814b26a079ffbffa329ee4705da81fd12f34f49d821690a11b8f83c5e0000000000000000000000000000000005873dc5c0baf0f3297d884ac7b652c749abd0405b96ba60fe396efa179a79fa55be76924b0690c9a528c605ad4f9e120000000000000000000000000000000000fceec23f479c72e0fea0d10d3394d7121bf1673250cf1ebe72eca60af82f232fbee342e2c8705434394d4e519fbb40f56d6810620e8da932c202628c2fa9f0a9f3fda3aa07c262924aa51685d2c9af0000000000000000000000000000000005ec966cfa28e105f3496f977a2f046fb206a190fce1a6062df0fa1946f274cde9f6fa8a71089af8cc2fbc2b60746cf40000000000000000000000000000000013c77ab66fa92a2411391d366a331a40accd120db1c6a656bdd92858826fcbded296293c13ee189ea3f34635de56732c00000000000000000000000000000000162795b6feaf6a63e6ea2d34f2bff2a4985ad26463b8fac69f8525eb0a005bd377fe7ff4aae820d361592d2d88f98f5c00000000000000000000000000000000044c9d5d3bc0d99693f5a0605ed467cca8b5dc7c7093294d14015b59bfd8ac6bd479b73ed52fd30d8bd891ed971912c571e7f672ad398f5c02c989b475d12ce86e6e242d36784308e56178f2a6a1517c",
+ "Expected": "000000000000000000000000000000000c3bed2f51a60f9afa6655853ec2f0e9d46bdc1277bfedffc468d9f36cfc7ad9e70365fecc84a5a40d863dcaadabf22a0000000000000000000000000000000008c5894a4f93b02fa1deda8b556798fb7d71f53046ccc305588bfc00b68bdfc34b3f0bf154ce7cb50c9536ad45e65f300000000000000000000000000000000003699501ebb9698e98dc998fcdac54dff895457d2e4e0a0e2d65d275b5798dc016e921bf1f65fec0f284a563aee66ca70000000000000000000000000000000010389c73de7f6d860c972c1f09dd24137c898e92935c45c10565ef3da3406cf521647ef80688f6e799eef4879ca9a6e8",
+ "Name": "matter_g2_multiexp_59",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000114b9c33bd09899c684e81a5a4e620eefa4e620c01c391a4df5caa75be462ec7ab027a9ae2c31d6643c48e3d75b6ced6000000000000000000000000000000001925084d2a1f537329e23c77b8a820c385ec5e12e4a145888882ec611e99b05b789d79bcab48326db4424309c24d1688000000000000000000000000000000000a1dc78c25cd16211a38bd0c70d24c84da1b83adb219e1b9c06fe6a6669d6e0281a155b4cec32d32751fff653aeef1990000000000000000000000000000000001daa74f19cce1086a87232464ba903938465da5e3e1f9ddc05a4b4dc13f1026e1b07af7254d515d2ad6960ea62dca1f77f9a79850b2fd5a281b22f52de085f12bd34e56808496e1c1388804f534d2da0000000000000000000000000000000018810adf0cc793c21726e9a27b7c558aa16b81af73f22629c478d293208a107fbfed4511d9cbcc25fbc2826bf004e7dc000000000000000000000000000000000356b25cbc7cf65107438125c930dff24b7786cbd7eb744d7f27967619d5cc02799451ac8814782eaf9aa331e6f8dbe7000000000000000000000000000000001164ab32ddbeb11c2c8baf7f311ffb01bcc367395bc7ecbe5642d344a8e879c74a554b3f9e4b6ed7db4ea0f872cf96740000000000000000000000000000000017704b1dfb111807d1f5d90c370a5b2968008a5ee9fd72262b6543c93fa168285c04931198f5195f1abca648722ebdc5630c1fdad9338fa5236f817bada168a737dd3685b327fb59d8a37329920af4cb0000000000000000000000000000000000a336a04a8fd8e18dd9a582da897016983d9beb0fdbcea6c88b7c0640620be52bff32afbe700599e3c08669c457b760000000000000000000000000000000001765fe4faeeb13fc2c007682c031ea7ff2899090e16a9a11959c5c3ae7881a1dd2c6d2b7f5f708a92349a2b0de4b92d5000000000000000000000000000000000e7c57db660133ebeadc2cb2054ab4ed16355466932685d4d11038e1e1f47b0349b68bc4e918dd48ef8e1c5d7cc53f7800000000000000000000000000000000169b629ddd7add588b91d9866a750570dec58662e43409031a5e25f1b2913c5c5a7a7cf666953c99835431f091ab1b140969599bed4899c3c47e1d4081027203c73233536cc6e45aaa78a4f1150a51620000000000000000000000000000000017d03e9855f3bbee719a15208ae24324ebf1879972ac134b027c9e03444a5736863bc55604158e81b38c7fd78ba4bee7000000000000000000000000000000000468f7c5478cc0faab7098dbcc455bf18525b56272c2d02cc1febc1825579a613edc6b455764ffc71c903a0704224a4c00000000000000000000000000000000067104ba5366e7e11bd4d516565d9cdd93d4390f2af3c1ef2ea3b1e84ee8e5c0e0fd8ac11ec9d2553e4cc13b277d473e0000000000000000000000000000000012e10495ba15b29c669cb9683b2fc7a45fe7ddba743b4a39677fbf85aa738480eb9da967eee69b02ef14137e102e240eddd438de35651328de7183dd38820ea2983488ba31d401094e59cacfcd1d031900000000000000000000000000000000078f8c17427847ddaa1665d206866231a5f36d3a7b4e8fa13910161566163006b5aa5d9696f423d0c44195de65326f21000000000000000000000000000000001613c465b65940f43c61b5e3c93313ae49d92728518d9cdfc57b49d6924479b70e281e724e04fa5f165b5999f1c1ed3100000000000000000000000000000000031741b6830c16d730619457d42767a51037fb4118e00bfd6cfcd8baea35ae76a5159bf1f4639fc2951f0b57446110e70000000000000000000000000000000011a618ffbafe4bad0a435d04084233495e5f7fbeaeb66d0d49a8177f562329b52a5ed4fdc680b791f273a7b0d3d4b349191f2b2cc76d848e456d07c84c0826a8861981dc84bdc671bc9b5882d387a41a00000000000000000000000000000000043c09eea638e524661c60ae3704fd1c18c46443ae134a0ab7b9a98cd398377febd9026c28b3e1e50de98766aaf0083600000000000000000000000000000000105918aa1476cf52f91b9ddb7c23ac18af3bd5269dbafc369713687010720affed6b12af9414cecd521cf0c7f5416c350000000000000000000000000000000019ab4a3eca904a15782f560bbbc8819dc09275f1f6d7c3b8e98aa0a96ec33dcb528284636b0f42ad0d503489d17161ff000000000000000000000000000000000a2abada18e79c548d5829991a65491ebcfe0e1a2c89a1e05f06a0ecd197797c5ffea0ae90b61f54c6b3fc844e0eb3ddaa76094782d0c06f2080d699b81aa04a60891046e0053d2fa757c7029df8f848000000000000000000000000000000000d457cb2c77acc8ba4b19ade0c724a2b6b0966ecfbbec8cbea745439b9bb7f3dde2febf9fcd6c5e6139fd7175e57b1720000000000000000000000000000000003154466283addb0d0b5d86a9633f8300960cbe8bf6a1405a3a040472542e9da63fd4f79a43d641a47c2b69a31298d3c0000000000000000000000000000000006599794823797f8ccea9daf0459b9d26e0d207f5fb95383c6b61eba38516b272e8ae6ddff2a9fa791e69c0eb25f3e470000000000000000000000000000000018be316bbe0416ad7deced1486d4e31490f5dc7e379c17542b7d3e9dc77bbae9c992e657c884db320cd51c2141a4abd2049a751a406657dacceb3721461417571a0104e11c1e00805becf71ee77eadf10000000000000000000000000000000007ba1ec5293d169b88ca4d2d92eacd51f0b8cffdb403632ea8ffdebc37f3997baf736771231335d12717cb45b51be31a0000000000000000000000000000000013505cc24222fb2ba9e25f5f3497653462f5b10bdd0dc88f9b16d5643a99ddd4a7749dfa6b566f41cd2da7c2b1ae93d2000000000000000000000000000000001465fdced698ca76d5faaa7e4faf1260cd5c4fd2939b16d3593e3588c92de3d003540ec989be9632fdba4ecae889ef180000000000000000000000000000000013a20cecd5e8f161ac70e40b8e9ca4c23e2b267690a3abea941c293b03acbbe4fc68a1e7b6d35b79ac46f65edde73a3e0502d56084d1be7179fb735e233978a5a3c2756d780cc0ea6a8aa92b1d1f7c4f000000000000000000000000000000001936436783f02f3a5307bfc0bd8c0a00ed8013508a440d040ed4f45b37a4e89986102964a328e93fabde6d9dc7ca424900000000000000000000000000000000000f16408b869303181b4b4877b554353b26a7b4750b711f3c41cc4b6682b2113cc772cf9bfcd0cf60e59ef29a5d0814000000000000000000000000000000000d5880e2ef94663ead736687ee725f7ce98fdc594230c1ac9e8345d39754bd616e261076aa5362776a6026129bff105c0000000000000000000000000000000006865ce3cdb5081e86535beb990d95ec3d75f67c7e881306607e4876c42714d627f8d548849aece4382d1c8f2b693bdc9787a6720b8db1b4f0e1d535833ed20b519a0e4d2e9fef75022aafef523713750000000000000000000000000000000016d941b6a0dc023fa2699c836b74e16c31b4cd51538f73fbb271d163519d4de1cb0f6ec2f8efde22c74ffb532c576b16000000000000000000000000000000000d10a7bfe9541a7b22d455f1b68cfe2422a83a070d93476aa0844670f02aecb36e9f41b9d66e8e9d0d67c0ba85c99f44000000000000000000000000000000000d7873f96d45fa8c9ba9cb4913a7b01c8e38876b6bb2a05506d23df0491bcffb42983ef663db85bc3cf755f476291a79000000000000000000000000000000000c22fdb83f9991c85b3577d1ed5a171f28460d79dbc6167b0c30b200235c512f999066eb1fa449115aab55128f8f2dde10b47b662e8cc8dd005bdc81dc6d98d0eb98f86b46c0c8f24481af9120e84a820000000000000000000000000000000010faf9cb9d0fcb487c9e86a2d2123105baa8691d82ebae8f5bb7d5ae7b7d8154837120eea86dfcd35ea5482a7ebf7f8a0000000000000000000000000000000014e40640eb6e8e38651a2eac05165f6cf5e0178b3711f34828766ff9db951e1348f0cdc652a78840dc24ada8b1c835c600000000000000000000000000000000129db7482ec62873591018a8399a8c5e4bf00e8bd9dd78dfa3d0b4cd1d93ce5ec7531e56d58b7a1cb3e58f062f6895ee000000000000000000000000000000000d8db3b54b6e71497faed107b31f5e44f328780cf01c62cb5ca00f99f10385ebb22a367cc89505640d1106a9ceec98c4072460e3c5349c8fec9944dc99762625262e84c70f10d0a92077a351335127470000000000000000000000000000000011ae9bc3ce04df2add17e57f260a72f88f19a1e44b0b074cccb7fd547035038d19e5f2228db46843343a69823decda370000000000000000000000000000000015ea64b6147ef76212bb5223d6d5ab9ca866799365683720866d8ce1117f60bd552a8e9981c095894258ca3c1bb5150500000000000000000000000000000000173bd5cb455b80b78951b15180fa7f8fb4725c1a12e5c53df1b9b31b45a29083e66c7116741d9aa93448c81b5e6014610000000000000000000000000000000007eba059855ab058c2066c643ef5268c864d09ec9962537d65a1686322c374eb5ab8eba4c4260ad0919dc18b4289a694f3177c4d865caebf1ef6565bc85e0b0bd51365a6f321e26b97cce887bc3f44d6000000000000000000000000000000001598471460ae082c2e2568602c99923193c913b9e803cbb7a4503ceff369e8c4bb3a19ad245c08192e12a2e9b3e75c4e0000000000000000000000000000000013b289bec9d97c529382388f7037749c10a64f915746d23d8f37e15db9dcb173b3a6d00bf45e67b8c70959472148321d00000000000000000000000000000000094a99f9b031a51b7d54f7b8865621b204c85d23fd66fe8ce007f0b852f8b5b895010745b2fc469abb670e38fbc41e50000000000000000000000000000000000e36daddab2134f65696ede36c50f90f9a1c56165e09243cd56fd3d9902d3c78cd85e7028f6dd466f6a8655da62ecefd393654ef7ad8687c8878c55a8240ae9df04805d3e2f194e960d5e498ae3ca17700000000000000000000000000000000050a818ce247367e8b57673d205d6bff8c650bcab7bf794dd32494669eff865fd4e05d7b4d35eb579eb475a3a0320ff80000000000000000000000000000000017ae5d612bdd46e1351dd1367c08c16ceb002a29832eba75e48d4c82e364f17c58525ee653a0940955b874da6a5bcfcf000000000000000000000000000000000eb2075367b42a0b3dfa30799ce1ab327eb583316d15b8cae21b716e6c7fd8cab96c67bc39e353f5e842e74995356c070000000000000000000000000000000018ca4b533da1baab37f05afc3ae0afe976e4f4530401d2f97176f5c73de3eaa75b8a34e8c6c0543ca0a08aeed28e478bdb9f942124a381b150f00a59e4579d0a2b7b728f62715633288fd03d01dd12dd000000000000000000000000000000000b3f4bfec920018663bb39c5520491da5c538f82138f03390c768e088bbb2880287196af937f1f70e215edd49d1872ea000000000000000000000000000000000037e7607a60cf235d8e4ecbe69d378dc02f0a8e40b7f23745e15a73fdcfc971cc8707d55a8c5b91d9a5f42c2f49c455000000000000000000000000000000000467df75c2703ccff1a01fa5bdebde210b61b5f3fa33e76e55be5dc953f4758c3a2c499cbd42b256ff5a2005949d9bbf00000000000000000000000000000000010d574c69050ce9e909dc23a76e9a2106870e8d8ce2a0e30d42cbfeea56ce3167535a9af1d453d4d8e6a450eff870638e6eb65778a328cf899f66581ac7a4a89e0e824c15573bc68c02cdaad89cdf24000000000000000000000000000000000907fb825f247c85d93fca36dcede9c22a409fa82fcf540593e8247c17875a1385fe009f0ff43853c404f6c96e2809ce0000000000000000000000000000000012bff10bd4162207870f6363342f2541804adc6a4e3f7b8be51d361be34def7a85fb39357c85a4e8df670fe39233bed00000000000000000000000000000000014f7e61ccd52bbf6d050c9d506751e03c8771b320872179a9f0161ac5736edc13bc133bda6239abba1ae09bd6c16f0c3000000000000000000000000000000000ca78624563584f8929d72668da70218a2da12b42c4b894108e6b103201372554fdd6b3bbbf2d94a9d0cf4053eb07d460940e3620c59504062e4e98b5d4c8cbccdb017c47a094d06253743c29465731c",
+ "Expected": "000000000000000000000000000000000de8e87899b294575392d523ff6e153a7c2038302ac74574bfae7fb222558f2b4c9556be1bc2757b83ebc180ae710187000000000000000000000000000000001881c7688debe3ff795788c90397c3fe3d6d9f56da9221778d7b12f5a54d8c0a00e1a8d4bb9c0b1d578dff862516b5dc0000000000000000000000000000000014cdfdffbb956a20d8521ccdb214adab14975d22ffbac107b2c15f42e97bb823c6a3945a5b299d3226e2044e64f8d1ed000000000000000000000000000000000eb769b301cb7c0c976623badda4db8ccb18dc7322472b5fdb969393d5d82b3ce94bfa59dae06ece424bfcb88e24207a",
+ "Name": "matter_g2_multiexp_60",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000164227fbb787b2d47ceea93faf1cf7890f48107ffae3628192235aa57658d9a2861db13fec0e58c347571c2ab0cd11ea0000000000000000000000000000000015478417b6758826b1d6fe0c562d43451e289dd50de31ef365ec70faf961ebb65b510c4788b6c7da2dda9cf56d3c8a74000000000000000000000000000000000f9e50d802ca8cbf80caec6489fbb24a2761db1245d9f7e820e6747bdd0855902ff211c427c00157ed9b1bffdf39eea900000000000000000000000000000000128f69ef5dbea5f80dbb9558a25f133b9ad77492250e0654f8fa5b55266f2fd26826a5c373afcd74990ebf768d6d8fd20f2f697ef6783390724e04b81d0e18dde6533eea9f72c1e10bc72c7b954659660000000000000000000000000000000005f7cfb31492dacae51caf4036d99d917fa13b0d2353bbce4e6547ea744b3a49b162deac2f107149ebc2f79e74828f720000000000000000000000000000000015ed4627efa9b318cbb52f518b734327f5d1cfbb097adc6184c5034620504181a298ac7e52759586dae2e107f121a9b600000000000000000000000000000000023e832638849599d9d7854d3ae18648e67e8938ebf606a7c86c3a7ea21cab8d4dd5d9cda5c482e05d351ea3ccd854710000000000000000000000000000000001849665396bc36d0301f4c9adbce81fd2f2d0c7f89925487d91a25c6bd0730ce31678694a319666cf42162608ef15a834680b934e67bd7518f0d6a3a809dc7faf845eb71d0247291d61053d5cbe0ba20000000000000000000000000000000012c9b607e29e35f260f3c4617b4217d5dbc6953eaeffaaa903710195e080d593972e7794897eb176aae3539401a483b10000000000000000000000000000000019cdae8d1d9035d1fc4b4db09e7da3c20d3b8777523155d407cc6565a71a6c951eca609d328ddbb165c2b5a3e6b081da0000000000000000000000000000000009c4629b67c1c50e5fcf316136bc645e9e62ffadac8495c084f97e32b0a3990b3b1019261f78de576ff7ffc89e36e2af00000000000000000000000000000000070a49e8892c5b523f5914e2341dde63127b694eef556de6dcff603da109a53b342363d9a854dda3d2833e25afd5b57eefc024dbceb522c02b88810ada9a814bfd085fb63d570663a64bc0658e5ad0220000000000000000000000000000000018d3c9259f70312c803dd6bac6488541f92482f7eb61ead71fa42bd5e2cca9338218d62835051bd308799beeed3b422b0000000000000000000000000000000005e0da6859601b6ada82b1826a455a846f8b4e54d9f22c3c639835a8a89e17ea2d76e2f49fb151f519de3e9adb78f0590000000000000000000000000000000010113d2fdc1e8ce0027b651cee6f9f6832b531d843db3ef7bf209aa00018715c1c42c68a82c53247a267929ea3c9363f000000000000000000000000000000000e7d1152af6448aca78aa7983013395f0dfc298848d86def6f017780e9cb144bbb21540a14a4d47b61d7a9b8c62376fc2c136f00c97a515076f6a0b63faf7e378f2cf04f8a90ac942fd70e25e683cbe70000000000000000000000000000000014125c81d4d7a8ea18004d798311f0d80c41c8e3a08366f686145e867192bbb13244f9f77217559cae72a150faba12a6000000000000000000000000000000000fdcaaf79c0607ebe9c8ca309d29d32284f3567a18dbbd23da9d96bad7269395ec2445d153711df4c883e8e7f7b02ab2000000000000000000000000000000000d34dd6636ef18b14f011fbeb62d33ec4358166f96f38a54c36b8797b51c1bedafa43d9f51fa4afcc2acc0cdd991997f00000000000000000000000000000000017337fab49d545caba55b763c23ce9bb3d3cc475f5ca37a15322e94c37825fc800cc7ee67bdcac66f9b5c22b03bf6558b033f2270ad2416d03dedd4bafb78ddc598810768fafd349a42438923ddfc930000000000000000000000000000000013434d32deb96edafc9a0e855281970b7c748c92b3472b34cc758dc3c17c4e6fdcf3190c910fa54a0259ef8bec75a3b300000000000000000000000000000000137df92ec14dd2fc02c0ec15a4e63547492154b4d4809e25f3ebbf24fe84255babfd6949770ba61637cc67e8ff299a2b0000000000000000000000000000000012fb20ef106e8cf3c79173e15dcdddb216c25a4de6797e411fd11d5632aef1304b36f8135c915c8c38caa2d778788f060000000000000000000000000000000014ef5cbe5711a815b9ff845e9201745f4117149b54ea3c6d1606060a192d513aa8ffe73425e37a42537773796b6fac8f202d0d506bbcd56c92bfc6fbab36bc96716de1af02aa166e7db2e2a0a4c19cd7000000000000000000000000000000000b1581a5def94e95e565bfd402cb84f2f21c181639c047d8f91044da84bb7854f5cb4eb3a6cdeb66569d99410ca3ec6c000000000000000000000000000000000d8029828f4ca245cafa7f396c25592ef08f6768e1a5b806450be6ca5b548cfb212d8c4787c3f15fe922f466dbe518c0000000000000000000000000000000000f51e01a044b6da437e3850349476437e4ff8b94fa190387099b17e6462040918cb2eba3b10d6044ff2123242005bd6f000000000000000000000000000000000991201229a856f88348381e1f2e282f0487e7daf1e5a4ac3854e66fa3d1303e3c20eb9eca605859e7d46dcfdd7615cc8329762dde1c4c91043a740a8b9639e83e809f749fc8c4853966cb2ea520620a00000000000000000000000000000000011f1bff5df413ade311b0bc3b46c4ecb11e386b886b71226987f14bc1a3a4b986412c2bfe8a4618ad5d70afacf4a3b4000000000000000000000000000000001972f49fa8b36d11d9c9d4ed6197261506b892ce6dfa932b87e686cb197560dfb8718aa413c38ee1bb771a5618c17224000000000000000000000000000000000e563bd240f5e18b518a792750c00aa5dfbea1f79b80a71369238ef15df9885d341d6901fb9168a2e74249f036e9a688000000000000000000000000000000000670e59ebf6e30b458ea505075840ed5348563efd536c31003d8d0bafdacfec7ba1ed401c616a3bab431a0fa71bb6188ea46572fdb37fe282203172c147715bf0a16e02a62bc79f33cbfe36703c95a7300000000000000000000000000000000071319574a93739586eda876ffd3be5d982e6fa04f5667873dfabfab83ddf603513394e0dbb9f418e725b02d2dc7b876000000000000000000000000000000000c6a8e0261da2ab499bf9a639a6e261e8c479f3f2b2d12992b41a3267e034c25373d4da4645626e6343e867466bf3626000000000000000000000000000000000045a0312dd5fccdd19edb65e24d5ba50e44689a9748ed9ec208320bd9eddf8d606b9340cd34ebf983e69a65c242fed900000000000000000000000000000000090b3dbebc7dd49e9f764e99c43b5915b67bdebd00d22c80e36e08873e5c5186bcd082dbce94f4f230b237d60cab7107b9e49472b9b74cefe5a951febe595b0020c43fd54150445fcdc4292c5ffe65f60000000000000000000000000000000007b04063dc315025b8545cef11be6b601fb4ae02597d75979b4946f3872764ffdbfd309f5ab3b36fe47b810f8320c1b40000000000000000000000000000000009361927d02192433a8d3c3d7871d76c6d88361774913067d16b68625aaa60f5a4ca19b6fd4140a5a11f92dec57d783e0000000000000000000000000000000012501f19b73fc6ddb4d194895e5cc2b89ca84defb7ae94f3170f25417965102fc195f38dfb7a2d88aa4b24e4a2fcaa4300000000000000000000000000000000141d0a0be60c32247f6cb0e0114251ac68c90fd43651d58c3108c728601ad6efc27c27a331a2f086d55aed54b3585fd1b6bfa1ec877010aeab030b96e80d2e27b45a93c6a99e2aeb3ccef22527c6e47200000000000000000000000000000000043f74a82ebfbbcf4abf3fd02eaa4483108a3446c9cf041bc67f5078d1774308ddcb3f918d7999d1e2c0876177cab6790000000000000000000000000000000000da7d4fa72dabb314ad8f68b61fcfa38627d1d7719bc07767f596671c58cca16e005d36e42413d03da3c643eb46b1eb0000000000000000000000000000000019f3f8f1a4008f9db1b604373d3566ae7c14a9147f80597a31839b83f0f8dcdfd829f7fa933fef3499b671867c3121fc0000000000000000000000000000000018bba4bfcf7629fcfa47935e36462cef4fa3751c7affa2ee2cb2fe3e3532d46ca1d247393ea190fb3f48077270d6a8b22810705458845232e851b33fdbcaab01966b8ed53b455873a966c1d6b89363890000000000000000000000000000000005a1e0e3a023f67aa7ab0109814f130a05c8c739036b98c70c8a8ddc1828d2cc4e2fcd16de4ef038a7373d15c78e81f10000000000000000000000000000000019e2bb467409b3dfae0b06244b4140de7f75cb105ab897d1ffb999c6b53bf3b60a3d11354815621c5d9f07962a237ffe0000000000000000000000000000000012e745499d5ed626b4762b57923bbfae7f1209408e7ecb8813a545c4ece0ec7c48a4015e0e264b47fa08fa82c39d3a110000000000000000000000000000000008acfd3c2a2e17be41a70ebbd1ca2cff2eda8a359e0969a389ab0a6fa51db5601b386dd035b26232be08d704a02033a7175fa4954e56dabfd1808f93d2686e0b4fd285bcb78b80d15e10e63ea8c7b646000000000000000000000000000000000fb464af51161f9c2758acc09d16754d4d8ac52a37baf2fb6ccd3bca3058bd3cd204de6c8a0bfcce8822f16ecfcd0601000000000000000000000000000000001819075eaa6d9e3f0568ecc2e507370f938a65169cea1ecc40c9cb4d02c83d7964254602e3d041ba0f93c24369fdf3940000000000000000000000000000000016c179832739a8129d2ef184f4d1231d24bc8d4093670a63d73771983152ec322b6a8c954565d61c2af76c4f6ef5e8a2000000000000000000000000000000000f6623578a4fa45614f4b74768adf65a753a35dacc84af005fa4d7328d733a09f12f709a7bb7f89060f60d4fac85780ae7dda7e5373d0e0afc3da1507416f47ea8b467a5b6c2fbde484aec8777ab7559000000000000000000000000000000000189724a2a0723e7727d224ced126e4288f4743f6855b035722f2aa36cf2f0a6fc23f6835c25222b670c15248884451b0000000000000000000000000000000009a57d85140f31ca58e38b4a99c4ef103f0a4af0d5546d416134fa8adce6ecca6588c3c56ba06b2f59015acc1a081099000000000000000000000000000000000dfc67b7644851c3e928ea33aaa0f745a18983edb7488b148736e81ec0c62345c11e3f0dfce729d893dce27ea249860e000000000000000000000000000000001712009a81e06a85a225a46fac056b139c8da05e6b72074ee4079316e490a06f51c62241e380909b86239d867d631be16aa731f9393d2bb32adf04f19884dd1a5e7aa36e46408b847222a153da95aea5000000000000000000000000000000000976746ae4d9325d5e8300b57ce99650f28055b5e020700ee5f124fa76ef3bdb9923101c3a1f46b6985b8203b4e8c60600000000000000000000000000000000057310c3b6cff6c849938f533b401b0cbe10b6ff3736c79a968009b2c0b90708b6b9a98b8e594cce09c579a64ead846d000000000000000000000000000000000d39511e47f33e310332178b8a0210e76e4d4c7408ff5c2374f5e7bde8335525e03897cb3e2bdfe59bb76b21cc6411df0000000000000000000000000000000010c46a621b7fb2e7ceab8943b3371475d3d6f132fb658b8c6bf299888711f1b344ebd4a5793ffe6a7a7eec8c66c80303985f367919b0f3c667b1c1cacedeb0be1f9cb175c899992ef55f14e9b7aa6ad10000000000000000000000000000000011ffff38891ee56cb1fc062d02f6c9993100f991a556445b5ee1b1b0d56d8e64bc6eea4d7f69a6b6dc55ce7d8b4ba300000000000000000000000000000000000d6cdd95d1ab2a11ab424d7aa596cc7e5de025c57217da0da143887d7dccd6fda0addae7c2fd9e0996bdd0d23128e807000000000000000000000000000000000499b3e69214fdb4db7dbecd619ef9c6b5c8343c808e4953f593cc89adba02b5cbc56a5e7a3046c6023c5cf305e54e85000000000000000000000000000000000d267e21606c16479065e47da8e3c058cb59f55a1316a87117a73dbb067ec26f406eba6a40b30ecb00f506bfd3c32f4da3041cc52c6f1bf62dee4c61b1c5e35b72ebff7e8e89b05353388b551eb10010",
+ "Expected": "000000000000000000000000000000000650fe9f3cb3620e0bf1654a7f1dee503b79fe2218739bad608dba9f1e5330f325b4fb7c340f118eb10dd0776fbfe63c000000000000000000000000000000000bcbf1c6a684dea5ad6c1a540b3525cbc64c7c431f37213bc8b08c8d8915a331c07bc899d3a2ea72a9a4bb2c539cf56b0000000000000000000000000000000008fca1c364333f558c7284afa1be486e84bb035b049a2108b0df99395149de83549de153a784e4df2b0134317c85292b0000000000000000000000000000000002784cc1d11667bbd0759bca35a16a1baf49a21765c6c2c3bcdd4fc9697ef20f1274be5caa0f820d37e843bc38c68957",
+ "Name": "matter_g2_multiexp_61",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000051646993c3aba532988d7baa07eaabeb8366853436b8b19c0fe3e14ed45fdc65448d749adf745291ab5ee62d4e824880000000000000000000000000000000002cec01290d8e51ccf751183dcad20bac20b8231804a2b6f87f886aacb61d31b14f2335629e97af0ae0546a17a4cca49000000000000000000000000000000000762afa7b94ed580fd07d5141a8e1299c6ec439bbfc6c1a4d695d9aba4ab5d6dec93dc4de47096d72e5ad87d879eea190000000000000000000000000000000014769208ce8a9682c8e0340f68a0290a7782c2b04e3c13027f0b23966eada2ffb2156f6e20539738535fa0ef097f78d6709a2e80dd96eb12edc481e3d58893bd0d789a499d5289072d58c2ea80b036cb000000000000000000000000000000000acc4e3ccc3574285c19d2545839d1da9db6770b078aa399262b7c91a7c41fb4c83fe7dd0aad19f4e3eb2b56273f664f0000000000000000000000000000000017851c99881677b89956fcdf1b8c5ca5dd0997d810f3fb89f7378dbf7964926cfde315f8722531d6d715b4932179eeb40000000000000000000000000000000005e374a4c7118a76e59cdaadebb1c4e635b4dd18665010249f3bc78d559455d27d547856573e264c98ba39f6f3abea69000000000000000000000000000000000a532979cfd5263c774f629027f7624799dd0f9d6a77f675d790a85fccccad6e93c00ff2e5536b8e9a92443af14611e69ff35bc510c86a9e72c3e9c6b49d2abca546f7a62330156ec09c6fe6847a400e00000000000000000000000000000000056f109801b7a4a36fcadbee7219c06ac74e4a3f7b81616076c33ba2a71d7ca0776b596fb25d29992fa26d416272a4b4000000000000000000000000000000000c02d7e6ec50b778a7ff36fbe5751ba32beb1c2024b17bd99b46239e6dd5a708d2fc689e8e8924902e0d80287cdbd6e90000000000000000000000000000000016f18df97f48aba4d1b64e71eb894904d02ee7f6ba425e58f38a08542319e2498cb0dada8dbbb81bb398c9c924ae44270000000000000000000000000000000017dce98b335f536909ce01647aaabb918942ba2468d9a07c5516cfd347e1baa02029d39de1b2602932630e4819f2f00f391dd27628d0808d4a0773509737597230d7849418540e1fe4498fd70d39d16c00000000000000000000000000000000005b23d6f76b8bd4f334e91771383856794d1dc65b365fbc0c94f21fff049761d7379f0d512c42ce13f878e0661712d100000000000000000000000000000000009dcf70c16f524ff540f132b35074cec6ed7dcc1f319432a0dd09b3ded0778ec9ad0f05d67ecf3ebb7947951fc4b25d000000000000000000000000000000001075fb15240d532a9543dc59cb0098cbd03da77c3bf85a0ef8be1560958f8ab57d3777fab5836ba98d67c721a4a8cd460000000000000000000000000000000003511525fcf6fe224eb87b13999d2548b6b8bb8069fd354f298a025b04a33f48be72d8e82a99b9aa34ce5ccdc1f1a59c94f11b10e4c45f15d811e3db4b947ee6414e262965d7b5c23a731b019e63d5130000000000000000000000000000000019039c69d52a66330d2d8572a1308bd88159f0383c041ee7605d0aa86f1d0fe3e884d0a2ad9c72405149b5fd204ec3db000000000000000000000000000000000942163eca08672af3827dbd876b9c1adeefcd5ae74a2768fb55f1e8b342aefbf76bc6546853a2b33e26fa866e60a4e9000000000000000000000000000000000c60c6bd103ba5bb5323b5107373cd8d706038bf5ec2b367a43bab72411523bea35985b974c756184c346626ab2622d30000000000000000000000000000000016c4a2fc8a9b3c54f65cd150c80a3bf70ae8dbacdcd37128514b4a881239023e427f0b0c8984ce219207c458bb380da970f7a0ee05cfc3f63d46a3151c20da53604628bac70d7b521b3be65d7b2abedf0000000000000000000000000000000003e3df9a8ce220be05f15904a3321a6805ab68bbd539479be56b2a870c3d61234e9cda8190bdc89f48e7f0dd9374e1d800000000000000000000000000000000040446db3ec43e3e67dce62efd741a4157e8ea2597a143f7d6273b66c7045daf31f72397b4b9d374328520893157c1f1000000000000000000000000000000000c3a7dde5b02df5f7c1e750a9ee5314a580cc6ed53d326a9157b507ebd6c2da314c37a7f1837f7fcff7e8754ab603b7b0000000000000000000000000000000005e617ca4eced853f8f2e9fdefef810c97eb27d5c8bd06c5b4ea50c03761c01e8adddfe27d2d72eed8cb25ea7514a4aabd991eb5e8ac8ad7cbf8fe64a5889b715a2409305f2366b278adcd2144d7be8c00000000000000000000000000000000104ccaee210aa8196010a6478702a54cb7ba49c80a98ecbf5c0920408ff8b4a7568212bfbf3561b6a7790520bb73bd42000000000000000000000000000000000870ddd51dcc76c8a97ac4b4f23819df48dc8a8798df0450d7a45d273f830c908541dcaab7b066bcd668b289c846ea000000000000000000000000000000000012fdae32b020a346ad5edc3bab360fb5ba55004ef3dfe5f437e841b5dd7284ddb3880051956c8068e49a3fd165143ac50000000000000000000000000000000019081bf768dae314fbecec408d687df5b6ecb32ec24b41f9febd583c05693f80345e6b9d81322ddc72616c1cc39a86811a9caeccc2a2058c2f5a271c09036d73320f9bcb31b7296a796ef94ca4599757000000000000000000000000000000001316b5ce5bcc168d76d2c862230ce604d02cd3d242c51c250bc6b6fe5c380c9e83fe7041049f2272481ab38f44648f4700000000000000000000000000000000079acfc2b9629da9c9f3394874e64aa00527de21e726f02db180f86cc0b9a97138c2c567832e287635721ca40469e00c000000000000000000000000000000000e11807dcd4ac69fdcea71e3e6a93dafc27afedf12c2998dbbb2e4f33e37ea736df73af791eae69bff84f3bb212bab47000000000000000000000000000000000e834a34fb63d9df68d683a26d79ecf8ff67066586e5f760d4468ad196c66d4ebf8605ebfbb7bde201f47b35cfde3a5d8ed4eec02c2af286ae19ad5f05642587cb9ad93196756d269c783a11f23393bd000000000000000000000000000000000990f115519d2125d47b925b613edc3303110e9040fa705211e0d772edb2e0f7f88ce521d1738a5f65c9d158e9d360c2000000000000000000000000000000000bb951a16decf9be8381d0c88726b53d90bb32cd8aeff962d48e43863e4eab1839bd80d7434c7eb808bbc0e32e92a4290000000000000000000000000000000013dbd5bdb7caaecc42ffd81f14be0ff3d8fa228ff121ed4f2f3ad5961fbce617d7cbc8133fd49e03caa62f7d1567541b00000000000000000000000000000000195fd9b85e19d0e3e1c93bab0380cad6f6f3bdbdcbf5c6ec32b7de7972421d0065cf0b265f6250c02eada67e95284bce26f20eee9bd019f9e0f5c794e22e770128737198b5f5dbaf5b7d18040443a0bc0000000000000000000000000000000009ca977266277bdeb985750df47353a6b81c5f0c473eb3369d25a01df67610bebf66a6de5727a465131404025e90441a00000000000000000000000000000000054410a13287ecf4aa18f543916fcd65b15cd5d54617433217b0a2b91a79fea764b511b3b270de3e8985e8f6a2fd8c380000000000000000000000000000000009a9802a03a7c9fb63c1eb13972cd42ea2df614a0972b914c4015c2e8630af319d12fc8108b4c88db9508a9a77d9e57d00000000000000000000000000000000094d83483bca296b20b7bee124f538ae9c659a84541f5c9d9fd22e98251d2b48051ac55ebe07bcc9d2e9109f526d60a6c470a66cd3428a44a7d095ef410126257175597a333cd36ce6c9822d1ee9bb380000000000000000000000000000000003f2d93ddb6d5983fd5521c1d1726addf662af0945aee54788855037f47a013d2fe595231792a05e1259c5e5a8c553a900000000000000000000000000000000004f4f4e7df5dee975fb440b5a217c27d9d1eb83a5ae280a2b147896f6bb864abe04459c17ef56d784d3c4a0b7ad3f3900000000000000000000000000000000069da36057aaa89cda458af4ee27fd9ec969c8f7612cbb153da0e010d67bfdddadb2941cfbdba8c43019a9f1aaf9c296000000000000000000000000000000001545b8325a80176ea148a3d9301debd7046f33a1b419b4ed01916a3d0a072037fd617d96e0bad32b208983ac3be7dda4e53fa8fb708204e619c221b8ecee14fdbcb1f94731ac2c858787ab33906c9269000000000000000000000000000000001536a81b203df2640bbe7e695b5fde186021d21685f24c25966cf11dde554d49bcefca64f16697509a9ca86e58b75eff0000000000000000000000000000000014348a2bd4907cf081f2f7bc944a98d3fac671abde029995377df190f7f60319b8de1698b99be39c821328e32a449c760000000000000000000000000000000000e18d4da3823addb2a6cef8336c83f99f390e23d7129365d57035d4363aac7e9c4da9f8000f086f7d2206666f990dac000000000000000000000000000000000d6ba54e2af9afa57ff4536a35e9b61c8d8fb3d431b653a0c66a2a4b8f11d9b5c45389f894d64485233d4183895921f3abf8de43c54ed59b936e1d55032eab5c9d9e04e83e4696d969c24167b4239f62000000000000000000000000000000000d88d5719e07e2332c54ba41f330c7763d2b2b7c4140d19b8b0972fae6ef902415de5f2abcc2342fce24d3ed8ffe156300000000000000000000000000000000163aa2c768eca58194fb76822deffc37cefe04ceb70aba38a51f507be7cd64c0755abdc2e49e7db234cd5d68575c2d7a000000000000000000000000000000000e443d9953468b8cea4eca4f5968e214888e2b95bc20ece39483ac551d4e180c0b0a41c4668c8ddaf761a0ac03fbcad3000000000000000000000000000000000691930530ce86a1354d73cb21ee32d968e6d89b12e5a09a7991c7d27dec302348af7f49c3e0de91e1a1838aa11651e795f59041329b6c3e6aef01d3410836852f79cc436fcf23199e0985c56f65c4f0000000000000000000000000000000000d7c6f9d4aa794f34596bb9af4d62363462d9804898ebd7c7db7544be1f46b4bde488ec59004adaa0cbe40aef525ce3f000000000000000000000000000000001094629b1428c4c284b7a64d0623e10ca0c4d395bccbfaad89d1a737a3887c10b714541f2681c33e674c3b99a36b7a450000000000000000000000000000000000d6812fad9c5ea365a64ebd3150238349d88b76d041ccaa7e637fdfa6c715d9d6dc3d3315cb95fd6919fe419d028783000000000000000000000000000000000eee5cb772ce02fe2a4883008f17570aebb902ad7c40b4024a5b24ff75b3aaa2b54ace6fb4601b1c62837a20204194dd740e4a207ab5dd4a0621fd65697f5d30b8ee1440a5f5c5e74a0dbc6b6391c1b0000000000000000000000000000000001026d21e075fb8921dd849c98252a565d39ca9f5a62a825e7e3e77ab5be6620e76e45047e51350c48d9a4cf98a1222a9000000000000000000000000000000000f6459a8287bb2da77404a515dd7a35f46a4aa49ef72cd2cdefbc5e5242872df5f7b7aeae6848d59afa1dd142ae7caca0000000000000000000000000000000011e3545151d4e0b034b950cd2f1a3fc2d29e9d53250ade2482b7ea6075dacf7e8e777afa1e8e612b45028205235265970000000000000000000000000000000017a869d75144ece603c04d39cb56a487895cc882fec613f40f6a66601bdbbbb7748ec755553257d654d1558b1104a981f49a3f82d25c6e0d69207e6dff010d56f0d99b28fd986c5711878dcb6665b1f50000000000000000000000000000000011602a23c9b5cc091a700114e5d3557bd4857c4fc44cb8628ef327ddeeb728927347438f123e2011f9cfda9b6dfc42e4000000000000000000000000000000000c4fad264ca95827e9cbb9783e36cb0b683fcc33038d47bc7ab6b65998770325588e5b910e811cf7d61fce13c3378d6700000000000000000000000000000000009b4711aa67e84434cabc289a78fae48ea86641a162d48b79bbcbfd56237705dd2d1e9ba3a18d737eec29eb8e940e58000000000000000000000000000000001160fc9e2a488ad9385140bb62ab48ee613c2284208cf2f92912e1b973ff81a5d3de338d9aa6881cbe437907890258fc8390fa1b452f887ef3afc7129ad8ceb9a8397f7625c2b249d7442566814ae0a9",
+ "Expected": "000000000000000000000000000000000cd0d8c746ecc8d92fcf2232793282d7e0e17e0ec27ee851487eb7788f590db3487296061075f36c24f67cd4c4bbf36f0000000000000000000000000000000010c5e1d05070c27f19c228813051c6a830254542eb71469664c842695b219670dba8ddff858e2d147019847866f01084000000000000000000000000000000001799ca7d8f2637da761622b793a3ed3317d50b902a1cabefdfc776b0d0ef88b707b8a5c36786d5ede3d8a381de4e069d00000000000000000000000000000000129881a3b56e0014bf1dac4775f509f309c33406f2cf22df9a0ccd15c87ea48a868d4437303923127bf580b8d6ed0a8f",
+ "Name": "matter_g2_multiexp_62",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000d087c1b98f8c67c1bbc4389f21d9dab02faf46ee4223c609e7b9eb399132ae168bc12847c580f58edbb9255dca3b000000000000000000000000000000000065ded24bda39d2b830639fa511bce8dc770eb95e349d6874ce63b3355d23c1da3ee9771ad44e57c6c661b7453076fe7000000000000000000000000000000000fa3b2ef40a7c3d41f0c3a5f86afec252c6ce89bd1bf1f2192026e22fa256365360589c788753033658b1ba151797feb00000000000000000000000000000000105040ff4dc2bc435c2a82e1174e2ee0b94043d69074f01e8ed013da8c431f33c94a438a93b06774411780cdb72abbc8414ca9894bc15e6bca798544138689b2471f8171a5dc48eccfa36c83af142b7d00000000000000000000000000000000129c8c1db08ccd0dadd59b04df67a91fb6547d97ce23e59aa57cd3d38458e6baaa67285800809856e7e264d812e584390000000000000000000000000000000004a0be934248b4e142fc51745233b6d0ab2c46f53a8f9d4c84981e5eacff146ee6227de289c713e4ce24a4341572c9d70000000000000000000000000000000005916d14a8592af57a40418b10376e8e20f70929d2ba568c1fb70e343a1dfcf3e63c791cb639bec49c50aebd2f816fdf0000000000000000000000000000000018682c66a461a69b11d7c32f7aca07749e05a23fc46547bac121752aef64e9bb98a274d15a14faa93af8f284790acb9b99eac8ce85a1bc70c725a2f04aea3749d75d22c0df7c0755a5e76ab4d82ef9420000000000000000000000000000000001552053742eb89ae3d0b95be919c84e53919c898ada92d3eaf05605a19ac910091fc08a65e9764f3108877c837d478c00000000000000000000000000000000118e5d22f6df0e6bc7447177ce06659f94315478385372046b649fa6d39fefeeb492e6623e0160bc47233f4d3143e326000000000000000000000000000000000dd02c30cfdea5abd3550a9f28b546d82d5b3043f012de622d892062945847748ba820555fb811fb3382791ec43ce1f700000000000000000000000000000000050373898b396d9a641e2f2ed832c7619515fd9070852b891b4ce0b5bb5ea8b5e24248297d53e9db7cb946e76c4433fa49b25140d7967b0438e49f59a6b04b75bc8745b84d7350605be548c6b4b3aeee0000000000000000000000000000000006b465f4b9d60a3a14e119c54a7c35172bd648c86a7cf331e80ba849fc87b9dcd48410e3c9a07b634e83fc7dd71e5b9f000000000000000000000000000000000283ad9c77f549042f79c47b8a69e72164f0ee77aee50c20519d2b89029c63ea86dde2744cd21eb5d37e896c3abbdf56000000000000000000000000000000001668b08a87787928afe92d941240e503da07b646a34cf82ed09d4c2f4d479aa24358c8475eebd9bcfaa6bae17c430cfd00000000000000000000000000000000150e5b28bd901f7a2a9af44bfd6b78cc84900dc05e334de306f9a45f1e67708adddf4dcede8150a39670054f97a643436e30a51d55a1ac94089d0f3217c3a2182da6b02ce70ce7dd8e2d4e938bfefa9d00000000000000000000000000000000060d75764a92e30e80e7c1a6df1482585f4de901bbc36dd9d8978a76c12c739f85a9ba16741d0b19ed480fe2dc331e5b000000000000000000000000000000000024fd15c9e5b8872d2e9dae9ae96102bfb0e31d15e92a24316818862dd8ca7a6fef271d499fed5e0db6dfebc4c72e0200000000000000000000000000000000058cda551e1fcd701c6a3880b276a2f7536a26aa366a6425a1c42cf31eec678551f489a27f23ed5dbc76f19b0fbfae43000000000000000000000000000000001152e2cfdb584295563af8120c523a9f4c01cf72da64fcbe0a90a284d693a3089f299bc760166be062cf9f8efb6a951ad3da3db6492ff36102747d9d663bc6e9cf8f75b1cf77044989c7af3f11d66ae700000000000000000000000000000000116fc24e980b2e7ad6bf17bcd7c4f06e654bbf766ea0238a66d738bf3c2d41c8c63bd52f81553cca5fea91f5f9b74a2c0000000000000000000000000000000001078f19ecf785a5e0d3e764b7d6ea47b2d077b5eb222f4e6a9451f134ff0d77a0b9a3b53caf599705d131e3b17b6ca9000000000000000000000000000000000e44c07f00a1f198583a8ffca43da45d8e54e1f2a85bee7afff6c1c733b5d0b5712961c4b6d344869a8e4de3b34218e000000000000000000000000000000000083c78b3568cdf808b75d9ee2b03b98cd516bb16ca8cc35757f53f12119747bf6b5b0605bdffb2f079cbc69e99ee0bad6de8753f3df8be42b6d6ab578096426f852de4ff545d2e4ac12c3943b044b43800000000000000000000000000000000087ded6945bd6fae7a0aebb1ea68d3cd34588035531a6cb00fcf1b83e06f7ec21cd3486580165c1364027b43e238e34d00000000000000000000000000000000005a2fe8a9871273bb60cc7ebef44a361300a1033f3f0230a731f5723fca124ec9d305cfde45802482a45942154398cd00000000000000000000000000000000121eb94a41f9e133adf082ef651272c178d780a1c31ba8797f60a208ad36b4c703c9b6c08be845f8844dd14d6406734d000000000000000000000000000000000e5e3da7c91ab4cca1c9286020aab9795e64e667d55a5a700241f9589aa3519639f168d040a0027ac057f334a9f740aba28f7ef4b12c5097a15fa6394a4dcc3ceed6cf3c6240ec2ac949bc21a9f6447f00000000000000000000000000000000041f9117b426938acb40c905bbcba443c043bb55cf9b876edfa2ca051b6354124f0fa54d6a88ea172c3f5c10c6d921b3000000000000000000000000000000001828dc0b9533274db6afc802b2fadaacf57f28126094b6b9038ed5f6bbae0112c873fe5eed15bc49b970461abc2f5c3200000000000000000000000000000000107df6da02f106ae47718959aeba7b4fb4a8f0e2651560e2f2266a62566e13a5af86430b8800543f5eb6b1e96be79c69000000000000000000000000000000001628fd4a598813133de75cd7c96ff3711b6bc826806b96d07e5a89cd549592f0f51c84aa9ee0642cffae5630ca1ebae1a3d0eff3368b10d00566f35391bf43c9d204a4444b7eb91017f1b2d8a762d90c000000000000000000000000000000000e8fff44163cd9c2a4e148eef3cbbee19ab8f648da1a8d438be27d2b0bcab393fb7d49e096d9a7abed3d8f82c11c4e03000000000000000000000000000000001274335d8bde3d14924f8d7ba18fea82bbc85427892f18fb741c8ecc5f2d6d7bee74c68058164c55db3cb8da8597bfe40000000000000000000000000000000010c7fc728c094e47569f0e75446c399d20a1239b511e34d8d6193dd32df607dfaa4377a1825b3892a9f74ff4efa0d9df00000000000000000000000000000000067d904122a6581b5d5a60acfe8156dcb6c10ed083840e506487b5dd9117927663e0ad883fb91b4914778ae082de0a7eb90d76e660389e570bef756e9785e39b9748aecd7a34556bac8399aa5564d12d000000000000000000000000000000000a909706e3ce45c86f2c30de5e820c8c9eefef207e530fd504511827f5e6422714d3f4224afa6bbba22ffca533d647390000000000000000000000000000000013ff61472ddc0d70207692648087c283763ede668ae380b0b9d6ae6593498b0adc9d4e4fcc73b5cce250e7563f7577de000000000000000000000000000000000a81db69eca785373c4dcbafd8635b23a9f41265e91152f309fb2945622937e65b5c17656abf8aff042a1fd1e5e50341000000000000000000000000000000000c66269c3ccd9e91766d1a640789bde6de752d08ffe3b2955df8dad3d2a0b6cea9013af235cbfbccee8271a7242e310614f18dae096e4de75de3da284a5755efe51e912e180020a20adf1f5de43cb51800000000000000000000000000000000181f3f4a16696980bd0eb9bd10ff1084ffe90bcb65f12f505b25f0a26dc1d4e16987d486b2c0b117fd6f2e356b83a5250000000000000000000000000000000010d7be6788da3ec56c87acee68ea8a03e7d467f816060207bb163dfcf8a4e7721651bf2bb23d5bc390d50fb1ee6625a900000000000000000000000000000000196c1ac817493f51d9ca891b55fa65ad5192df83cdb63eb1a634ad54e2d627f7feaa68780418f5354e6cc09cdf2f6c5800000000000000000000000000000000190f36690b8d36f2e295b9625f23afef9d9babe87c1ba0303f60c6d44ec952ba6bf8356469cff9d952f8e26bdb86ca06e32d4645ce0172000fd74f30937261de89753caa716dd03a8b3269747f2349a1000000000000000000000000000000000f77df606f0611856c449c58393f4ee7a6225a5bee667382a48f59dfc747736a895d598f90ab26002dd0ed3a5a8f5a200000000000000000000000000000000012aa50d0ec440884fc6c2f7a0e8db8a5e79160f0c482209ae1a1aca2b9dfedfec6d6ea09252a373ea57905130220a4820000000000000000000000000000000004773f46165cdb19cae49cc42663316df39586c62be5b827535f138e1fca8dcf62ba42ab60ac6dcec85e8496f32b9eda0000000000000000000000000000000010c91923c2c7b3eb2cd9aaf0455c0eb035e38e5352d218b07ea23f50040ea58fd548b373c1bee9113d3d44fcb25f6ba08c8722e3e929ba21f1ed6c51fe5ad4940fb13d63e0293893135d0da5e6e0389300000000000000000000000000000000044b95fd5f0e049abfdc2adc699646afa5b0f64464779efacce85a5279477697090615933069992bf30036c6ac70dfe50000000000000000000000000000000002778e7dacc5566354c24ea1144613a5ce8a38eb56d53d230ca145ce83d5ed88596afe243df22cba10f423e64a7c103a0000000000000000000000000000000017e87cd2752d8674c373c557ab2b922e02620a070aacf6f5b3d3d07ca35d89ed2666da7246b800717c0e4763dc35f5f6000000000000000000000000000000000a3ed312e5f309eafaed486629d953970cb73f839bf30f506c2f393df4c283f299d6c643ae6c229430d919e8aeae8bd839bef6ccc893f6eed62e68f5f2a07812f2d3066b89653431e7e39e8596bc3652000000000000000000000000000000001082a0edac6267151c8ef11fac7614b74cf58b39b72fb71e4d66467ed4fb3264b177c691e569230f2a13a64b4a48c6fc000000000000000000000000000000000073a8d5f96ee580741bee1f82cacb6139d962fec34c44c648c8fcd0322796429bbaef083a11b4c8fa376d4c00cd79c00000000000000000000000000000000008d41e51dc2822e0f14b992511de799fe4db3783a05ddc1026a53faa89af000075ba5aa830ceb7551e51f0fff144c1360000000000000000000000000000000006bc4bf0bdf350af417160d06e8aebf2dde02c9b50be39b0c4dcb3a045f9e04f1f041f6de10328e287df6121247dd4e9c395ba8f2553e3eced8a42b221a710a5cd2a5ffe5834d3084dc260ae0f51698e000000000000000000000000000000000802e7b71127a15a279a629e89f194b51d19c4f329efd8ecf9fe69d340dd06068c8467da6ab39be25c194077d3ce2428000000000000000000000000000000000250172c787afe866b428748be8359d8e0bad161832abc108c850362c5839237483fb38678d77c94696260508907726a000000000000000000000000000000000d46223c1666f314f9a1e32a94f83d8150755d71252e19af91a3b460ab0ade2db2364d8c6217cb422095f0d9a1ed648a0000000000000000000000000000000002fc2849014717d1c07935efe601325e1842ed333897222f6de322dac8b50bf4d9859eed8880a34676af0d0e3277639053ef5568a766b6c39854ba059f3130b75d7fd870bfac2b00b626e2d71c4968e10000000000000000000000000000000004151d78d65b0c9eb26822e20d90ace8fac209a1f08f62ce722ae3effd7fcc476f4c0179e71b09fc181db96fb2ea4eec0000000000000000000000000000000013d17ef429483be98411947ca0771ce671fc38e27bd0aa4abcfd5ddf1af9e138404d86f4c2ed74702f80a573638d92f500000000000000000000000000000000178f2a7eb43b9f88acfa892b5868d7f7c5787a399c1c566de39ecedbfe88357fd5256ec57e1ba12e9784382c14331756000000000000000000000000000000000253a391373974beef746c4397654a30a68992fe9163f9518ff0ed9b7be37b858ac60c95259ab894bb6acfd123333b7fbadefc3880ca8dcff10b8b763f7d15f88965c2261b72ba879e3540a90c59effa",
+ "Expected": "000000000000000000000000000000000710bfc39e92b0b9d15ee9bdb4959daa3a78f66aeae29eaeb50a0aa0460f3ff703c86eec8903011b4b61a0dea725ab08000000000000000000000000000000000856fe7a074d37786237cc14ff1bc53c735ee8133b231dd3fc63dfa0dbd1979304bcc7b55cd1bb66fd7529e15d15db5800000000000000000000000000000000014757f1fbfd4fa7935ebfe65e150519d6eb4f4831890df4b236dda98804b79862fb6699b587c3e568fd6de1e582409900000000000000000000000000000000000f7b54e4961dab9e94b1c4b897177dfa74be9937694a38207ddc9d6290dae1d5e122cfe4c8c31d853db3783999a7f0",
+ "Name": "matter_g2_multiexp_63",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003bfd2535c6d8ffb44670bd02b5aa6f050f5cfae7266fc3225865bc3f34320820eaeaa952f80da51671f6d97b3df9d4f00000000000000000000000000000000026c1adc0ffc3fef9ccf018ff9a647ef5c69c5133fb4a6566cdcbd3180d9ee784f34d667edb1dd54ae292253b45576b4000000000000000000000000000000000ee90fb541becf96b4728f1859aee5ae74e30ba9193b90569b66b0e1d087eb81f30c21774298cb06e7dbee8f8aafb1930000000000000000000000000000000000a4361867bca952446f64c273735764e141eef43d156d6cbb6e68dbf3bc940e935f7bf3a77b57fca4bbc74bda2f26532c1a5abbddc02f453519563d6b6e05959d8de5feb493f7c58ea5e548cfec2df60000000000000000000000000000000004bdef85b0da28e0531734016e5953256c75c3620937736cf65de5f05b8beff294677668047a3b74f0f135b846a95bd6000000000000000000000000000000000b754df2aef855b4a0eb6f6aa03115ee8f38a31fc852381deef2b59bf23e2c885ae166030ccadd5673bacc35482f81e9000000000000000000000000000000000f1d760ac6dfb65b39c999211d4e4c3623c3fb8ea59cdcf926249a07285a8e4da1890327fed20ff07f12359f6d9035980000000000000000000000000000000009f2698239c8b452748126ffd83abec768edffb83dfa3dc7943fd499c8980e2d9aad76dc38b336a4a63eccf5c4150ce0b406eb0c097237556228f3a48b7e770c1707fd583b91b4b6b70f398b7dbb0d3c000000000000000000000000000000000cd724c51fd56528dfa688df46f71bbfc9144ff98958b559fca8fd05eda01c38c28630ee19579012b9913a393264cd90000000000000000000000000000000000aa1e55f2b6d9385ec6a9cbafcdbad157f7ebc06b2e30e2380ac54e71db5259cb919e17042d6ba6e045f1358aef276ea0000000000000000000000000000000010181ce9ffe235b6b271d570b3c2d6e1be60c53b4a98ef5e8d7d00b463e5bbc9d8d96dda881e58746090983d6f8edd35000000000000000000000000000000000333deb8b14f499319ad675f482fecd80f9a69ba369425decd441cd2ff5c3c77f11075f61bb1d90d0be850ff657d6b7cccc30cf1db4c6be6dbc5830ee37b5782c6dad215334163a9d9e4deb962186f80000000000000000000000000000000001581a5440fe892ee6eece5fc2227fe072dfbc440e0620a1e5fb505ff0b16d9e6033d83c83576b4b6ff87a807dc81b88400000000000000000000000000000000099b070a0d7497f33c1c478ac424d5564fa645d836a3d572d98782f08713d8e425b571433fee928475688db2b3a9a04c0000000000000000000000000000000011e1cbaa09a6361aff9e199e21bc52e98dfacc49ed83e732d4b4f2503b3bfdf85d029dead4412b6f3d7ea447e20d669b0000000000000000000000000000000005503e151d620e9a5a142e4f7940ed88375e7efc1109214141c191e9f38a32a40d3a92d6094584e763e0cf13cbb54bcc99461c0f12019b344a7f322900b64fe81e0d8a052c0ff5e977f58753b1b6edc60000000000000000000000000000000007c780f119bbccfd658f3f1b69ce9c56b1f5269bded713b6827d97d32b2a6deadcc02c410138d984d977527f3609cc2c00000000000000000000000000000000095aebacfa33928a916ca7b0ceac699c71620781b35cb2f3b254bdbd1544b728a2ec1fb35416ed7a8a3a630bc07ff8720000000000000000000000000000000012194abf7e411f4961b6f8a1e2ad052c27624ded863d7a9132d9c7ecd3b4074ef0060cd86adb73056323f4227ba5fa9e0000000000000000000000000000000002fde2be9ac1e8265f258a09eec85a70112ef1eadc3a91429c9206555933e2b89aaf7493fb833e33e5d61be28a12a1c2338ef9fa825e47b46483ed8fd2df64bc7b56da8aecbae704b7eff2e7d426f27d000000000000000000000000000000001586c65405e810e1d5b59304bb4555ca43c04a593671ec64d5ed2d2e626b1f8a89f48a4b21d38fb49909b8c614209a460000000000000000000000000000000014528cdf994e774b8fd54090cb45b68098c1ad9a351bc1f36a9393f3b4364f5beaf58fff6e5f8b21a85b67bc427c0e920000000000000000000000000000000000b48d8713aee51d80c79109fb8b4e0c6e32e25a7ca24dd3e7700f8f3195730375208b241b2c722af3c2295a1704cbb3000000000000000000000000000000001913cf6328429cf2966a48117dc74db0d45be7800f93cfbebf597fb48a8bdcae4fae2df7835f9536481f67261755da2a1dd6656a34f3b12e5568b9c348fbf4ecf50d65a89e63ec0936591f01e6cc7a4a0000000000000000000000000000000017e45a481449f167fd579accc896ac65aff6f1f7392df47d006b404de3cb7ebf6cb59d0913438f3a51e55a0ae3d446c9000000000000000000000000000000000cf4b7db343bea29af6e244a71880538b41b826bfd1d06a21512d00ce58f5d7500ab1ed77b446b1e3782df736bf3dbb6000000000000000000000000000000000525d08e134779ca7614784818876514e14b65e799b7832f61a63601fc491c8b9cb25430547f961cc1c22100170a2065000000000000000000000000000000000450cc2156c4716d0343f32aca82fd2d0712389b1aa984b31d51edc2aa0545c88ff52e470b15eb6b2c22e30f79864dc85202f32528e795e0fbe6deb4ef6e45efc70019520b01fa1d71d5505e42faa69a0000000000000000000000000000000004147c105ee8b4db68482b9d7f6a716ea1474b6c62efc41b9444ed1ef9e92e2b7010a1c1ecc59038ac37b385074a6bce0000000000000000000000000000000018a600a85c5c38be835d2e91a35cce4b59e5f5ac3b735fc007bf5498062beca9befc9c8ead58f9f21f6e08266b149d800000000000000000000000000000000012a476fcb81ab66e3101de2364cb609b17e06eabdff5246bf736eb9d5c87fddd404e8867578262f07a05731b04069164000000000000000000000000000000000c54a888678c28766ad17a18507e4bf5dc57dd394eb6e9b69abaf15e645cf4779bf6ccf4314d2756584647cf27af089ba2b39f2b893be03ab4da77ed518ef35b2e24278d707a20b67ab4d1e5972f9722000000000000000000000000000000000e809152c44cebdd8b40f0d22d57c3b31f29700e0cbc3e69f660bf7270e59093d84bf7ac358be7e45e799a75cf9c13df000000000000000000000000000000000c6c61f98bd4e3b7095fc7f1196baa98139087df00fae2a795e76544ca47e453f75929cab07c11cd3595de6ecbbbaff000000000000000000000000000000000171c70446c19fec3c152741925c8db28ab0d140720cb6a6c45e9bc66c012a421d12271889ea43fe1524944ff572fe6850000000000000000000000000000000006e4baa09b4660c69cace151e60320b771e56e7460b01442bfcf26823c17779034ac241b9365dbbfade770d2056eeecd892eb7c361f05e114a645caffce9437b7b43fa01dd66c1e75b30f3abd0209bcf000000000000000000000000000000001917a23350e94963e3a7488ac1dafefe9ab11856d405eff39d655e31ba808f02954b63e822613d3c6e5f358be04be4a4000000000000000000000000000000001620211b06288c16aa02f4404192e9f57a048e900f0ec5db9b478475f13b142f924c6de720031b3fc12cf869b422af470000000000000000000000000000000011e8ded9ad57e46713e7ac0044ee4edec12689cdfb98838a74adf1a35244e3d9a4a34c81323b089c10422abf26b044e70000000000000000000000000000000006f85c7478cec590fe3355a8d6e9557c5be084c161e090c72f1281be4ee56f36aa1e3c9c844eb45d9e295c15c4cd903efdafc3f57d6116163f1da9e70ea645243c5911cc4ad4a969a57c46c6b5c73acf000000000000000000000000000000000d555d9f23de97318dafb257cf444952bdd3e844e9ed5ce193c10b76f5179f0c6851f93af1553b128f34d3a7e75339f3000000000000000000000000000000000132704571a12a58f629dab48f1a3956392b40f801c2b3757c15f7be46ef1d9115d89920c460c0e2bb062b3cc1aaed7400000000000000000000000000000000152829eaef900fd2f19d6fdbb8f7eb3b02df35d218b494d075219b69016256e572eb7f555f6fbdbe17c59a666d190055000000000000000000000000000000000fe5c67c949b7c89a867301528f0ab24b04d31d6f18f575c475ab5a6098f7187eef20a9ed6e810684da9afd8de96ded6660a77b2be50eb72fd108644d913b9253209972fdec2d107213ba47357c96e9e00000000000000000000000000000000128bf3cbb5208d84dff719ced229921a889c9a4d02f5a508187662f03852531fb8be1f4c2aa9ef01de7720c352dbd19d00000000000000000000000000000000158d89a44b8fcf9ca8c96a8e516e130ae8af19ed71c2b8487ae300c3cdb546e248728bc58fd9cfef21107e0dabf44fc20000000000000000000000000000000012b70b42c8af4551267a94a795fe18e8d054291225438adaa33fe2edafa87742fc3709abcc7bada5d26e3a14649cb47f0000000000000000000000000000000015a853160b7666ea7d64aacd931314497ac7068a4b8bfe3a7deed85df2bb8dba277716a9d1ee50c56b2970016ada509d1ca575cca348dee9adfe68f8a78d39bb998205da2a5285c12141a77ee7af840900000000000000000000000000000000087c7bf08e085e19f0cb301d2e36478357e835620b1cde6e132c237ff6fc63e6fc16a8753550d50fb93a0a1741302cf9000000000000000000000000000000000615299ccefe4da879e5f4b01d6b6ef8358bb59ed8a2b365ec72003c16486d3266243db81f48855d81b6a25440bb861a0000000000000000000000000000000001498fd20640f39dbc03a474f4514e5e283256ac19468077af1c9ddaa40759dcf93afe256de1e49be6469fa106394193000000000000000000000000000000000cba50fc4919a29be2f4e74c261487dbf855db1856e8d5d008cc3f4ee5eb3babfdfaff878adae49b96db99d424bc4dab2e1e4537f855eb478274992cba4e3f50fd9e944f6246cd52dd1517b55bd7f71f000000000000000000000000000000001369dd82ed013474581ca1ab2d2133341d7c1d52065060d72b8317e899e79e9077bcefe6c76c3c7f67e54f76dd3c246c000000000000000000000000000000000405aa84d3ceb02bf8eae989a9cd65afa15451443af6f3cf5e70f5cd7bb8d413c57ac3893a7e8b888ae93a92dcfa2b20000000000000000000000000000000000378d003988f3c6c16d3b12ef47a4a49e2d3d2c7c67e384bcd510939581770aed92e06291ed3b7c742769f0d1ef740c100000000000000000000000000000000048bfa6550711a17d52f48377821baae6f3de6ad99ccfeb8302466047dfddee8005240cdc65b3ab11ed85b11f128624957f9a729aa01c8bf0271052202a077913a9e0c87201a367845f9b271c130e95d0000000000000000000000000000000013370ab697da0ff0a0efa8ebc7589b465374c983c13daee7b5451e8b299933eb5a4d255ffe4aa46782ae0916fd3990230000000000000000000000000000000002ee77be6e0b6fd260ad660a96100bf3259329faf2ff9796102928e70cd52c2bda8d0d1da1d484d7b023d3d59725d12b0000000000000000000000000000000014482fee88e02e61b847c08e61d7ae6fca2d993bbb69bf1653138150d5d7fed09cd5cd4097cb4b6368ea8023383477cf0000000000000000000000000000000009d0380d0d6fa39c9e242b9a67336d86445551658bc29fbd594239a76d7741ba388450caa244fb186afc36d35c8740e93017593cf311989ed8fedff72bb1f14f72cfe5bb7446ace5274d8ded54c1372f000000000000000000000000000000001537d4a47247af8f60f77d309666056c412ce089f3f011457e894f74fa4ad5168baafd36ed3294f5f61cc9cd8f87554500000000000000000000000000000000119e43382a846c8945e58dc7723a0f24b24d9cd487d436a156156a6da97795cf3f4ce382d21435695949b5137a2bf1d3000000000000000000000000000000000be5fd015998bd6043f124048c82e4d848e1b8c87442d0021390cba41c294de17648a47dacc06268606ba73cc95ae6e70000000000000000000000000000000000e05a3dbbf3da8320c40d51ac44c6380d56ecb460b0e7094819aa6af4d7c70d1541d4bc1fc5afd453b165f3d48d09a708bbe9e7a307e380c238ec1f8e2010a95fff8b03923ecd9b012f99e56c77a5cd",
+ "Expected": "000000000000000000000000000000000b00b5c14685ddd17ee99c74598e6bfae5bb1c103f8ebfaec3a620ba57312f3093f9ad5eac820d81096dfece90e72ef8000000000000000000000000000000000dd81552160d449cd787ac27c76685ea0dc993a9fcf8ab182f1ff5d8a484a47c14c1c1a785285b44336c7f6fc0732a0c0000000000000000000000000000000003008b6d97a12868554d294faa26e2ebe2920add650f841adfbf0ee89af72fc4da5dc23b45b7ff191a58c17971b50ae50000000000000000000000000000000013f438d927f35b04bee8fc55693d5c97229c8548ff9de39fae6e26c26f89623d3b0c810b9be8dcf0445910e8eac5c58b",
+ "Name": "matter_g2_multiexp_64",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e1f825b71cd9edcb231c178e160e37bea70108b369afb248edc7c6a59114c22e843fb5541e0f26c77a2b589ea88fb3d000000000000000000000000000000000d65d777e91920b17400955a4afecf82f67cd13f3e7c5d9c2076c4a4d8f7f26383d22d9977dfd0987f219a625c8a621200000000000000000000000000000000045716092850318c343f0dc5337df1a72f8c74dd729831d12103b46127c9180fb50cece34986a94fee6119e72d16a55e00000000000000000000000000000000083fac698ce800786719d1f6063c87d9f728da03cea2545b4ad8831f6c24bfff73e80f2c2fff1532f6d1fea60e7d438ccc5e9d01f6ea67dc3f943d57d9d8b5791d823592f7fae6719804c1ca097e651d00000000000000000000000000000000171d60b76698d4d3f14b4eacbdce9fa66b8c3cc7ecfb989439330fbf0d051d95f3007c389113346e614f5ec8cd170a2100000000000000000000000000000000151a96beb250bdeca3cdad1b07322040bf1cf2105dfa854bb24fa76c8abc25ef4fb924ff995da641244f9daccff2ff970000000000000000000000000000000007e5818778a8331cdcd1432b46abf1efcdf7e4aa8907fd42d5e7d14b57dbfc48125246b57587755ee1571be8b52d2c57000000000000000000000000000000000693eb562e22fa8ca4a655b76e43b50fe487ca1d65cc3867eaf793e50496f0b4658bd92199104c2ab92e4ac53c44db6f57b8fcb85e4dbc1969805d814e75b2b80f5cd1e5562bfc1e28becf731aadfc58000000000000000000000000000000001059d23ec6e472937d80829256db506d2d2deb37d4b750a980568cd5b0db085358a4d610d59009b64db1a9225f9f6f5300000000000000000000000000000000053d9ffc47672f1058856aa08e51aebd469111dcd129ed542454d6401e7893323f8a9c63641f499cd8617c7389518f8e0000000000000000000000000000000002b9b30a5e37b18af4bb02ae8cdd56f6a87820716ea1522a174a0d99c3716295ad0ff2daf663697cb56bc6053c9dba610000000000000000000000000000000019d3230c0bdc228fa0cfd5e0d8bb88be959e70e59d931d9f9e3683d5e65d8ba0d121fcea329b23c5905b80dac34de33b03edc53ced9ec5d7f302216fd30a81c3554a3fd04994f62b5e3da74c8b71bb870000000000000000000000000000000015a619addc75f425596f9a51c6cf2259087cf32afe9b1f07e346a2f4e1f8caa001dc10098d1287b89837f426d073982d000000000000000000000000000000001660598fcd3ab6a55423138ee72a4ca7b57277f6ce140f9f992dd9934bcda78513516df0d309a0e8ea151b2742dceddd0000000000000000000000000000000004cce7d84e0763fbbb54376833ddd7408afe3f741bc2b7e42fef3789a005134cc5540981a15a9f256e0e541ac58ff3b10000000000000000000000000000000019c20a0064f89d37548e06d63d8ff4fbf3584d5bcc2fc2757339b7c89db6d5da76d43b31da7364259187ed602e79bf4f976568ab779e335b8dc67a64f15b947e69cd3896ff393f51fbd3c3e3a157543f000000000000000000000000000000000d7ec5a27ac44daeebab7658011624c441e45924cce97d5bda354f1daf9362f5bce2ddf57151fa07f78740a7db170e8300000000000000000000000000000000121ee325f4252ae5cdd3e3495f36492d68d9dbe13249039d1185760e6e48a789744b2a9946a3d6478a64b378f76b0de300000000000000000000000000000000014c6c5b98c1e214f78b82f1b3be4c32c5013934b1231fec942b5591d3f0440bf63b1505cfbb7a8fa78a85ba58fd4aa90000000000000000000000000000000016aaea3bd0ae91b9d18ff89a40ae27b68d74f3a227383138ed737d59c19ac578da03df83f04c8d962cb9d6f84a15302f3aa5eeded490a17b1cfa66d409811741643b7beacf312b9d6c8e7e7e63579c8300000000000000000000000000000000188e5aed425a768f89f5ce09b2cc909b28c6a0165787c8e3750fca8e8162128ecf62ef0ff853d206d23bc076335008e70000000000000000000000000000000001cfd330da0d1b5b92b6533cf5a8b6b70bd93daec4373f28d669f5e970a947fd813ab1d1272b61afbd2748922b87c8c300000000000000000000000000000000002aec750fd085c99c3b9c3af62b6deddd85e49eba0293e6e8160b26a3945af546a760b8f8f85120d6a51d22313cd33800000000000000000000000000000000162a109abce2edef753ca6351aaa9cecdeac20919681c672dbb183b5b26649e885ff081b9d3687f802dbe20fda43462af9f1f9313bf966ea3b8f09bbe9dcb66a7f9e3e94e2024c49a72ccbbe03fe4662000000000000000000000000000000000f7ad6a1dd9f8cf52bef02ae1e82b0d20dcacfaa5c169a485bf8becec8b51373fae851ca29e64385f0b7024eb0bcf9270000000000000000000000000000000010412a7a710f842fe836414e2729d0ff2e145709d8f7b5e3964af3e0ae267ac53dac3db1e6d2b7f7671ec34b18c844a10000000000000000000000000000000002d3b96fab0e3b8fe44e316fcc5e35f06dab83f2c531a777e162f7521cdd5767ad0b6f877f876f73d2ff663d9b71f462000000000000000000000000000000000c09a98bf623e82a4d2d4b63fb867fab5d3bb1f85a0669c4c11cebaeb357c0717a0f246a9ce4064b7351dcf1e77cdbd393be64fc3763d06111961bb208a2b858aa1ff181781dda630ca41f0d45ef2a9000000000000000000000000000000000114270d35ebff55c0341776086d893513595aca3b200ab98c8b586029b19a360a04f2e77e90d382174296443ab8531d10000000000000000000000000000000008b88849c3cda9a23d37ec9f4700904edb24be95fbbe6d9e20ced0d52208b597d44bb9269830a1ac5cda35d0c0a03c9e000000000000000000000000000000001144466b13427c10ad7679567067dc47c671107064fbb9bad287924c9bdee653c395dc2654caa5b3013ade932fddd5e50000000000000000000000000000000008e14e3cff3bb57f0d87680a0c09d745c7272bd3c216ff9fde7c03df2caffc27e0bfd9f99912855c156a787200752c125d2a2b6008a3b4a4cb3a8c28864214c7fbe154fedab1f9ff8c96eab6a5f28fd30000000000000000000000000000000015cda76d42de9fa86f900a5180ff016155f31b9276c617ef664202848d2efd2876d412402516c0c3d26d49f71d894acf000000000000000000000000000000001307fa2b963fc19583b7e4ef2e9dddbe93e2505e8f4f00ec52db26ab411002136c1f646b1cda71e19480c767906a6d03000000000000000000000000000000000ba87b08173c841a2bfbe424584d4685c39bdd0f83f278f9fbafa8111102aa3acfad5aabbe032c7123631fb8b454255b0000000000000000000000000000000016c525c1dc247fdf34344168b7cc245579585fdbdd6fd783cbe60b727cd11ee97b87a86647f78dda207c98e65c2ee7e6854e742ef7c76ad438cbf30c30103741f57ebbcdca4d6c4f14e554dd1ed81b24000000000000000000000000000000000403887fd4429f44f8da7f17ca072f867e88ac046922ebe3e1e6c4f9d8e174399e7648aca924a557dbf7b29c540db33f000000000000000000000000000000000522324700fb6b2c43eb5b39e0da94cb60e234369543f530ea47f4aa510ec0fd79cdf4dd3ae046e21d78b9c0e35107900000000000000000000000000000000015e946b90984257ffe3814dcc3ef065fed1504f0790f3564c8bfad4e97cffdb61c0d73bb0b1dbe78c4266c773abd56b500000000000000000000000000000000078f604630074ebedbd836c463f3879cd5d4a2c947da0e47740ec369112f4fedd787ae59bea69aab61b91f05d92061036f4f00b2494a32844e01d0827ca78b06f5eb40b6769f36a04f20eea229c305f9000000000000000000000000000000000f722bfebd55f75f3bbd0a55492499c3a3f637ead0e54270042fcc88853df5bc5f11a3677efa26d31c28368e00c8713700000000000000000000000000000000182618bc8a4b3f6556d79848f90efd6883df90806a8358cb6852bde465a27a70644ac5d5040d4f64ec355763f1a384990000000000000000000000000000000015f717739a1cbb2eab30e7b1bd9b25f57ad56f36016b59128ea1f2089f2d1dd0128b455b1b0e9e3b320f68a38a1bdfac000000000000000000000000000000000b855788d6b6a7748aa923dea3163fe525a7b43f4619c1eff3f9219ec3d98ceaf34b97bfd19aa6f91f7fcff728728978191e47a0b0c72bd17319063abde7df51498cf0c980c46946bf80ae4c9864e2e200000000000000000000000000000000120048ace47bc1ab3fdc07713b91a9223fe0fffdcbeaabc8a61351d756f936e18177f672c5a4db7b9dc29bad16bb7c4c00000000000000000000000000000000101275492a6e843306f2927b6ab540d7a5ee925bdab40103b4ddd885e444e6a6ec2d6e99c061284a1967797d8a2e9e700000000000000000000000000000000002c12f17a5dd2c56aed0d308367f37510f83c94a4482e5f632161dd0517dc2d4f46a90bbc13034c63dbd04fe4c616e320000000000000000000000000000000000e4b9089155ce2178f26b058f4bfef57b73aafb83b0b78138a01890a167709f79100a1e4d797c5849473eb3486cffa4b7baf8816db56c0a602cfb4caa9089136ebde05722ad4838671e45ada5c716f20000000000000000000000000000000018180eee7e72b6a4bc2e60555236da335fe05fcbe2b3cca4937e73a550aeae6274122ba84ace78eff84d323b4196f58400000000000000000000000000000000147659347e0fac7a16c92950ea5fd115416072f339d7de3cc0f00ef369f5122ff050d8515effacc825c807f7e19650e10000000000000000000000000000000017bdbcae7f63052af9a7d8bd71dc98b6eca7ecf5eee7632959fe56ed51278099690c534ec33be4ace4612b0f516794aa000000000000000000000000000000000d6fa233be4d6d783bf973cca3740cbaf0f719827d7f9310f38d1dd9d1c1f125cdfca6d12fbf6a8e8104f79bf30b00647d9ac1699117bb9b8b90e2fb709eff4ea0f7882bdf6acc6885c9458703cbfb3500000000000000000000000000000000082f3beaafa575e86be53b4fe7b93835b00759f921933402282e5bb0e643a812e0e4b676ad51ff2c6f5332d777641cc3000000000000000000000000000000001760b87bc4d2c13122fd7acc6d629c9f9db9bc9a2c49634aaf33e258ceb3106bc2755b227c6660a1df1d92c60067cf5a0000000000000000000000000000000016a819d7109c9a12199eb98537a730908a693767cdb35a69b4c7329761939afea766f0b91ae405e273227330761a53dc0000000000000000000000000000000009d14d7138440349e83f5ded46d18b886ef3cd63e0e5bfa0a8b50985142b21a4733813ec347e40cabe28e6ec1e068c24a22b6c1a24eff71f0fc64b6aee8d3d2dd0827756f5c959f68f1216c2dea58503000000000000000000000000000000001676d7f489219b56c198f8494e156fc0672ae28dab20021b7a6018436c7c0f107efd2493ddc2a1cfb3ad490ef146348300000000000000000000000000000000001106e89fc098ce7bd8bead5d7f6432bc54501370ae6544f34cfd996b3b610f9cfc7ad366751ae1211b848aad7d93d30000000000000000000000000000000011f8f0bd037365b5427e76d57b018c1c644034b28d06c8f68c59bff45eb4a2c4d761d066d96c13f7e73dfd80c81704a0000000000000000000000000000000000fc826b5957613f35bfa36d3ce088dfbbd06c8f2e88056a22a9f35db561e06fa0378ccff29ba8b81cc12c7a504f8c704c0431e6877166686239f014008959332d9d009a801be6a1e68c2de52ee264bfc0000000000000000000000000000000014f0f64acb0d9638a68278099abf5b5da3aa087792bef15192cfe3689b69b7ec1aefbfa14e659358b5410d98d2eedac50000000000000000000000000000000015ca79c92e98cf8314a2f6319520e1eb7d4656ca6e51278710cefd9c768a25691fc58e983aaf858d3c8d0ed73e2beec300000000000000000000000000000000007a5192f1dc906693568291f163e9632c53e1f418a87cd25656064adffbf31863680468f3ea451fbd22ac990dc870b3000000000000000000000000000000000131d2e3f6956da8941e8340259b8a15aee9fc6f23573f9a348ee9a51bbca1308dc54e7b4675357e3a9c5971be3a5c16af833a784d22b99537236fb07ab7b59918783e35b89fc9692d7f76a03e024c94",
+ "Expected": "00000000000000000000000000000000163da4bf7e159e05eec90318a8ddad4a59fb02d7ae2fe18795d38c3ccaf797188fa16577e6a421ccfb12ba1ed573c4e6000000000000000000000000000000001256654eef3352b09e0027277aec042519d99eb2567fce2cfa50a0c251c12d3593604739128171bfc13b3bfd1ce8f9e8000000000000000000000000000000000b8a46123bc863bed525f97166bcb77504eeeb66d2db207eb8342a3d18f7f5a99910fae3e6423c6e84e437a2c4b24363000000000000000000000000000000000b73cf08023c8572f48c132add67dda7a15def638a01b198361b9d21a4634ba76ceed9819b37c12e24f148d255483856",
+ "Name": "matter_g2_multiexp_65",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003113ba8b216d933fe0c81f23f75942c0065d21d8f009d73b1f698281408874e33dd2750fd4298367b81827cf6fdad34000000000000000000000000000000000b8a921e840fc665a786d826f83ca5a9c8f00e7c802bce5473a7d1ebf63e8bb6cf5c4b426153508d874064d1f1dade09000000000000000000000000000000001492ab584088d23d3b0d1283904f9a8f29f9efe47950c6e9ffb9db2123f3f9820b906d672fc7f97f0bd38b8fc0ef44520000000000000000000000000000000010d321c2538f92aad4631af44ae39e63dc06becd2460f0cee0e526328d167fd6cfbcf4edfaafe32d13b5fe66c009533bb16c1bc60e1a9be9a82c93b7e0311e7516a57d687d8907599918df77b3b6caf3000000000000000000000000000000000ae75d01481a51294003041afc4802326ab878a3a75eafcda43cf873cc65e300d28aa986fb82a2d1d649e5be00f956820000000000000000000000000000000017640eeef8982250f88a4d187dcabfcc9adc3ee9194dbc3c04c741690fce5bc7cb07cd0b7c3497191d9ed8558fd0d24c0000000000000000000000000000000007527fd8dacb81b8d1abc746688db6a47211fa71556155d38361921c4bdb2a9e9921a3a540bcf55c6dd751b84c04a1040000000000000000000000000000000008de9109ba354d7426a5313d66cd747a54df347f0f86a3c0f99e9e4b68fc79641fcf98ab39fa23ef6f1a781c48f53f76cf301dfca76a83c70552c9cbc9c80cb20f0d82a70a9d887b04b150fa0764ce2e0000000000000000000000000000000017331b8367f07756e789f7edce4d22f6886656fed78ddacef6987a2751dd3d5d49011a050e7b2a3e11fc8d90266c9d710000000000000000000000000000000016959c303e11f23392f95c1402d1d1ad7f38343c711e96f18d03f832f76e3e81de789a6eaff797ae51079b13571334d40000000000000000000000000000000004266fd13db1ca80196a91263c79d1583b717fb61fd9ce5113e4cd94c59e605152b244e10e364b468c5a561c6fa9715800000000000000000000000000000000026f67cb263be83f3163856f091e9346651c29d4634e242da53b22eb6e66018d235b0f30f8833310dff9f3020e5bd3811cfb94c4e029a2126a9cf5561c677687f52059e4b7f8b7e7e73e5b1dd7f42129000000000000000000000000000000000114d8babd11c81ca2b8a7e193afbe0a8fce426b83996bae6f77201870e51c9355c319dd86b985272f73e0804c0f53700000000000000000000000000000000016f5ea7610891d0e72975816c08e6e25a75c7c42500655f26efdfb384241bbc825358a21caff347d00c8b2391501d15400000000000000000000000000000000199c8c74a79ee90c3606906bbb8cc163c214259e4d0127cee3283bcd9c1ebe4090ca7d7b180201910d3f6f51566d3bdc00000000000000000000000000000000032c785165ad4c1a2846e15318bd7cf5b42ce8b675cb18fcc4232e28701f225f1ea384b276e7a38b2c9e2e8b112f1911d8386fe6f4303959e58165b422e98c4813b1bad7808594473e4e66df09698cf0000000000000000000000000000000000842c65006caed9b53add048a2eea89e1b4584e1deb4365e3dcf8b9ecb02f337bccbe5d6929ef8c20461847f171fd4d600000000000000000000000000000000100dc23e6c1c6f6756419a9bad3133bba052f408a424c5239b8528ad4429a2bce64b72f1463625f7599ce43865581e9600000000000000000000000000000000125b4d71333274a16e52829ad5eaaecdda5c206063473dedec5a8ff4424def70e6f650926948dd2158b403f985a3421b0000000000000000000000000000000006a031e3c002702837e4ad28250b85cd94d42cf7b0d765b980fab95edded7636d13bdef1be63e66682c4e297d0cb2b0302e1c432f3b55ae87ab815647f196be3e138b2f6e9fe7acb9459650246187eb90000000000000000000000000000000003f7091a25da7d5afe6fa6b254604a1abe7a0c6ea11cc1a4167f5f648aa973d888383bc7e987b620d23e688868d318360000000000000000000000000000000016637f888efc3e057227cbefecb3037aebf8e330c3a794e51d691e3bc064237b98351beb746868aef977a83d1fe163ac00000000000000000000000000000000126d2884487984f851d1bd7d61bdb803321f263918e88e0677831563bacc9f5207358d1e9c76a5a25a66f0294f459e3900000000000000000000000000000000125c61b387a4462fa3bb2f06a4cfbd7df082d20cb23ee974aece2ec9a3b0c084d13a7ea83725a05d9f31b8033d2888ef9b0cc0ac499dffd627f5d19b87817dcd67e87561d5244a4b5698265f8c5b767e0000000000000000000000000000000006cf2bc7c691c4f8a64d0aa1ca3760d715b3188a2dd299ab09c723315acba8b0b4bbee819ba06cc564f0c875a63a415b000000000000000000000000000000000bded3d695e471f30f9d723f55826eda112eb0e3fbfb9a377cfa07d6233ed84108b92a79bb491a2971e9afdf83db8e9a0000000000000000000000000000000009b0e9928cb267508d4f9444c6ac3dc6f64f49a70c82c0bcaf4022e97854e5d9ec2612a2cd4d67642dc0451583bcb24d00000000000000000000000000000000009347dcfebe93a2f7674ad02ac48794e7cbffb04dd85b0c8c192fc85cfb9cef40fd11def6f63ae9a923960424eac6a02f3875f81fd39c9b3ec74eb269903dba4173d8eb0e41a196d3131252207ffa040000000000000000000000000000000013e8215c7bbdca445555c9fa0ae44e1905703334bade3294fc047ec262b9e4903880d52851967339eeadd666200b25ae0000000000000000000000000000000003b0bf4498103ac03601a8594b154b59a2a93d663f98ff8dbd2c85a1902e572a9456c629a12651aa87a1262102e1c770000000000000000000000000000000000e8bfd7d3fa0f773e6bcfd0d43a5c436862d1cb6a4ed715093c6782cd94699090c4bde597f65768e963fd0f8644e09b300000000000000000000000000000000064dab4d0d0c6b94c58b067337f2fac7d0d922cc822562b6bc941a794d96aac5ddb83d1d5844440d21d0a72a69303b8b2d8d4341822dba68c6fd58cfebd07b134c1d0c4e32ff63f7d59addff4df1ec3200000000000000000000000000000000098dd9a20f84fc26e78993a9de4d519aa2f8d343fbee501af945e5943e88425d29beb7ae54481b04175a07bf69b260a30000000000000000000000000000000007ef43e7a56e4e7d532420e152ce566d9055eadb4ef13d5698c49da905a4977fa8a7d3f51c8f5275582e1647984be61e0000000000000000000000000000000003755ee4432ea90f2197c7cc2e191dbbf7950c52a2c1b723f26d2aaf7a38c1b97efa29a312fed599f1199cf186400adc00000000000000000000000000000000150edc463f0a55fc70c2ffdd1f73a3abbdae459eb16adf79e96d18849ca638e6f41c6805b73755968be5cb110d81faa4efa3dab1d7cdf949bd938ca6ac371f953b3bbef1aec7ae76bda37db4c940b3d8000000000000000000000000000000000f7149602cbb3e5f2c5f8edfe59fc0fb8e1f03f89ea192bfe3990d87ccd28d4a80d7cd3003a8cfd669e1b6ff7e3cc5890000000000000000000000000000000006ffbc965bd06de07d8c0a9db8db5ab82d5f11afa1ad8eb92ed4453489f5899cc8c46ff02743956bed81229f64cf6efc00000000000000000000000000000000164cd3271ace4809eadeb1c0f769094272f3b66968690339bdb5da92e920cdc80c9d577ae4fa5b6426a5a6f46fba80bd00000000000000000000000000000000098f0a14a511ff424847d2b4d1b80a049b1f05ecd40af96b7a81def54486e4969011c122ca7dca3444029daeae2ecfc79848d3c53632dc461619c8c522013b83550ef3dc7fda197ba37c9cfe4340f5a50000000000000000000000000000000018409c0d0f37f4932cca87e24eb4d55e75dc98f938420ce036d43689fbdbbd839dc608b21d12a8af1d0a780aeac6617400000000000000000000000000000000109f2294669422a4946f926b1f106c2887893a042e3bf900559429c7fa484da4909216c8dcf826871534981021256741000000000000000000000000000000000a1ded19846e603b958d0bdcc9b554beca784b017d2a35ba117890fd0dbf729428bcd9823c7a378706220377c82a215c0000000000000000000000000000000000eafc89e30e4fc0544497e27674ec5b37ec0849fb382e608e09d0c1c94cb78bcb96ef4ea48e374aad1038881706fbcfcbfd192e917f2e0c4d6253c4e4755f30812149d1ce1ee4ae5540faf1dbfbc13a000000000000000000000000000000000e02cb3e099792ae7508321ce7afa323fd499de90c4006621ef5ce1054d0c934ae058a97ff8aeae0c88709c4d8ed0adf000000000000000000000000000000000e19318f5890320f17d5243adb4683a97e3e9763102c4fc93e3c3e3d24f4f61e0500be916c249dab00094b4ab048fe99000000000000000000000000000000000989faafcf6156472368b282313e076613cfe7ff135eb131b49e58932cbfafecf6585009d1f17ff8941d7f871be23e9e000000000000000000000000000000001167419d097ae8b96993b2e67da79b658adde1e12e43c71f27835845c7077f385612158d3e59fe2cb32b9418463e672679eaf11b3a30c7771ce63cec214416d798de20432670280d997b2f0631007d63000000000000000000000000000000001579b7d03d3d2c8a280e8ca113bcc98afa6a2705a5d228d92807a85cd5a1ee97510f632293a478c3fe0bd383f4b69cdd00000000000000000000000000000000107cc2e6bd02251bfd565b4b848adaa84babe9d4f083e827ceae6bacd9c9c221f0dbbef53278175bf27ebfe5949fcf8c00000000000000000000000000000000018d187c566690e4edd8d8abe5e0a448e352f622c96680378051228b6d081a4914aa51383326aedf45e351612ad6c5d000000000000000000000000000000000197427117a52f82aa6e931ecb0c5ffeec7f73ee8f44c5816935d26c06cc8285200ff9240d98cc244708e00669460f98b43077447b67f65e16a8aeb3564b2d13822e478dfb4a82a15a1c8fb7cc8170cc90000000000000000000000000000000019bd947df5a437a7f1ca2340bec628f2783cc1760dbc4a97ae10093aedd9f64e25ba79d9f4ce678f4fec91a3b1eef2d7000000000000000000000000000000000770e0c39988c9d8eca076464a3e10e274b06b1d2f6230e6dbd8dd59dd9c062f8958c6870c44ff196341bb9f65b8db38000000000000000000000000000000000a1833ef19e2b8e31577e5cd26e0a7fa46a5d25355d8b3dc0605f53714a60423556f3bcf17649745695f68f26570de0b000000000000000000000000000000000f449aed4120f3bef05506f2463f4546c7ea67b9e9110d3942dc256400d063dcc571305b1d4cd2bc3f18cf25319286e8eb64479b496c17d0587f6f26c62752881b6a9228643e8c43f21c441eeb643107000000000000000000000000000000000c1f9688ea64165f894e85b21761a9b2bfce891070103119ae71ff7acd164a57b0e054319631180c22f19eab8607f5b40000000000000000000000000000000005ba18dafcd3552af464acd469b133896e90c9ccd7e3bfc6e05db883f3c6aa1cc4610ec47f6354f6a7cff4385c56d2b3000000000000000000000000000000000fefbd9d78f48683b378d2d6311bf7ffaccaf7aa73a0bb4ce019a0c1d2e1673e52c724bf3a782729ec23d258043efff5000000000000000000000000000000000ea47ebbe3e858c5fcbf5b0cc9017d6ea23bda36e235d2aecbec827fdd2e4b042d1108d5f645b6dcdd786304e6bbf81b52b42f75aebdad1bf433917c025800c4f4e985cc077db3ba36f7484f95764e89000000000000000000000000000000000a313e1bf72d9a176bbad609631192c779e94c293463507edcd1c38bee8f33cfe6104d7169457ad5ffd9f045fce1cadf000000000000000000000000000000000af8db18938c51742b351fffddd74bf1137092ecb50a7e749391bacc9c1a19c7b9cf235b52ed577e7855d4ec1fadd940000000000000000000000000000000000febaa128de79274ef11d3e6378809d5b319796c653604723693c335eda175014b645604271429e3d449e756c85bcf6f0000000000000000000000000000000006adb29cc4ba053fea56d07225d2f7735651c0046f5cbe4a350dcc20431ed9457651d46a5d23d946959cadfc5500b7eae83106e9ea63791eb192e7a035bee27bd049b3a37f080076146eeeea6a769384",
+ "Expected": "0000000000000000000000000000000019a5b588aff8853adcfa959afc5135807d00196a75acb3536ad4fc9a9df3803d919a2de7cbe9ff762913225577ebdbf6000000000000000000000000000000000ac8bde939ba2f164795804d96dfa8d3a1c4d9e4eafb000cfccd956c24f4d594b30bbf961917f625c86270cbe164cc5b0000000000000000000000000000000002de09fdf52aec0b91bbe99fe2eb9043b19975c6fd503815264ce030dd5e5444f0f4275ac9a07a49de775335d52ea3c40000000000000000000000000000000012457bb55876c482e5b907c765b476dfe6ebfe8e588cb7f630e58f78942bfca57e6c0d5d7b0ce80e48960e297863d212",
+ "Name": "matter_g2_multiexp_66",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008f3f1f04fb80a23d348e3e25dac1d732265fd4a71ab8dad3718d268e49c79578e8e1ad1720e70357439e57df0791d64000000000000000000000000000000000fa4c15c76e395fa706a55d1909ede2163274a68b3e7afb8d2e0bb176f60c06f5a921c9ace35bd311bd79ae86340ba5000000000000000000000000000000000173633369e00c8c5528bd5ccf95c6af8b012e5a31941c134ad4541099c7c33c5ffd29a5a31e18be720f7ae85132cd6cf000000000000000000000000000000000800f5eaf7c8b1dd2787305ecc637a0bba8eac807a7b449410e48aed3dae2b4645b8459fcdd477fd92fa5ac6291b800ea4d710d2f632e3ed0ef69fa0219e16ba30d3efee99386f1a5c921f4548ebf64b000000000000000000000000000000000ea8057b2d609ac2130b21e0b4a41f0aca20ee7751f55d816ea42cfa4612b67c3c556b01b0bb1c5912a74c50a420407f0000000000000000000000000000000007fbccf8ce8d1a92756fe80b15c7d9342af4e166d3c1c7e35ea2fac34851cfd983633270c877224749365720fbcea54a0000000000000000000000000000000000885e173b73118721d28fd26f3a9c562bfbb878ce71091d7ae4b37c1f2625777d67955a2b7458af71077db7557171f2000000000000000000000000000000001754edbfc3f2af94c92e6754d6bb096bbc4b39bb1128dc6bba8b4d4d9fac6649598be90b06b9d5db44c4e77c0cd1537cbd9ae4597aaf582857b40096360ced0f044ea172551c6f9fe3a15e0ce290b56b0000000000000000000000000000000008a1a751b5f9a08e2bf5b2a58f62f0af6b8773f88e50f658ed220c0134e83c7031a288eb50a8a35016d2362b431d809d000000000000000000000000000000000d7f04d4a6c36cb3d105dc3915cd5d57f56692132681b3abca4b00e078c700931848e34ea1b7ec663f3886ff766fef41000000000000000000000000000000000a06c3ac81d6d0466e1ef21115150d04c8bd6dc3e4078e46eab213203c3226bb0c6500ae4fda591d6b8a791de598edb90000000000000000000000000000000014d849ddba2fa79b6a7107efeb46e9b6231d65384c69ed183acfb922d55b790d4fc7546afadc190b76f7da00103ef565efbcb4bad99b419820eec388f6f62ac8d87866d7beae6d431dfa48d4243b4a4b0000000000000000000000000000000014dfcb5fdb38cf09c1ecb284dd4f2de0c3d70f90d7c167a442d84e9a29bf43be62cd319b2dafdb6ead2c6596443a00090000000000000000000000000000000006220fc05c53f48e7e4104422b0660ab67fd88a695a201366de570f0ac0ad30421d5e37a1575e6b5ba35f45b441b297200000000000000000000000000000000077cb8ec1cb83c4974f6452ce0de630afc82e283eeb55d3b7e9969bb44bcf0404deae617393f82ac228b836c3cb6f95a000000000000000000000000000000000e2bdf539eb45a125112836008effd104e881aca397457004fbda4a40d152817801bd259434481f0509ab1838cdd1fd060d89acf5b49fd1f70fc54756c4bc1972cd8818e36efc37b422ba6a9318fa134000000000000000000000000000000000a09843630131cc6feeeee8aa8214408235655e4733badd6fe20c5cf1e45f6a61a5216e0cde937799437962706d3bfe2000000000000000000000000000000000ff518501614ed4a199ca9e9aad4e8efb8e9cffa9b4fa683093a49cef4669198a7893db998d5777f2cc8f4bb130c84360000000000000000000000000000000010ea66fb5224f4508ec100cdb611be133c4895a8de1b4c475b097494ff0f1ecdc1bf8fe467c630233cac2ddc07935fcf0000000000000000000000000000000009d22c0a45c82b0a19beb94eda0b93cbbe1f2e5f2d61279e1e1c93ba073cb766f5637195e6964a4814e588e44bb03f03386af376b9b393dde994da419d1f7aab60023546647f7b069ede939386bd6ee80000000000000000000000000000000015ca795fc7f0d169ba8abdafb1dee80b67e7dc616e824959f84c61284d6b2e0e8b9f99b414f5bd96d0e59b66ee706fd800000000000000000000000000000000042f473d1fa228961aad526efd003461935954abaae347dd6c9bc7fcd68b5f5138e57ab2a160cb19d1983089b58b51ab00000000000000000000000000000000188eb160cb968b4b048ce14bb72be27c228df1a6c014fa7dbec09a30aed8c71e8da59d3d5f8073b6a7d70d94c0e59dda000000000000000000000000000000000d467e6b05f033f3923667a82d5b489a5c90c99c5f68078aec700fc67a83d9bb4c09f3f00b9fc2cfd62bb098f885fe295ffca78eea65c00e1128f8dcfc96b39af1c4472b461ba5262307003bc972023d0000000000000000000000000000000003bec45d94f3073b2ca54d6332d36fdb8f5c801d9f70ccf6e3666b66ee06c0fdfd741f74cde1997aa205fb0318c9c4760000000000000000000000000000000014009b777b660264eedb35ec2e13ea586aa9438c47b3fbfd095ea3d8688a89c85bb4052bbd3edd450c19acea6372d0070000000000000000000000000000000017f26d3cfcb40fd6b4f3f1acb6d47a9b54c232aee484c7a8992a3d1accea794dc384fccefb0418d43e1fa7b399bdacaa00000000000000000000000000000000153c6cafbff3c53114c96d8caeee2880dc063d7db5edf5f14157117387f368c76b739553542bf6a9bc4ace3694de885a92837b4314e63ef5a153ea2ec4bd373cc3cecfa3e892c3a12aaac8ddcaf5905c0000000000000000000000000000000005d2481438c03493efc9f1e8e9ae6ab05b7430f7fb82e108aada0e886b14d769969d54b17b31e5bbb63d40836748f541000000000000000000000000000000000971deac599b2161a4baf1178feb81fd4798ad5cb063b1a0cbee7cc33b8fcec6c3f43d1d46d9ed45555187db636af99e000000000000000000000000000000000222acaf8df647744859e04104a5fcd546949feff6244e192a9031fc838f368aa465a3799779c637ef0087183f30731d000000000000000000000000000000000b8e8f1889816f89401b070db687aae47f7264c9be192a8d6e485ee71a5a688070d57ad8928d09d9a4925f1050e2c69e127ef2309c699a3602b0d86a070baef0eef90f539aac3cb6ff42cb19f284bd99000000000000000000000000000000000b8a5b0dd422469a8d6d7603e9f3179f443ef3fab0016afd94e93e2ea9e84b332da4b59f23a5257b99460efdf7d2aca7000000000000000000000000000000000c28e7068769c3a79bb8d92c3b89eca5d6eb42e3e18c2a7154f43a671f8670f878c4b110990c2e2b163ba4d1155319fe0000000000000000000000000000000001804302246fd07d86f4bb23f610af38deba8e324cdedbe5e61cf0941281cda8fb5dc211fbc0ce6fddf30aefa9563a0500000000000000000000000000000000015813fe0d6bbcfdc8e7e40b6141db21e1b490d846ffe82eeb3edcd9a024315193259612155b0179a4971e205738af74ba0f9a93c2fe35877ddccee5da39ce5ae60a6a19e72481319e3b3fa2eac614890000000000000000000000000000000011ac1ea4dad0f650fe0844ac3ab9434ebac6eb70a5f77c8f9c892cb4cb06639a15c63a9b820ef8f7a720040ae5b9e49500000000000000000000000000000000117da7999552e7886a25a939ada0944cdb15b5c468e9d1c3bf5b6af920e470bd648d24f3cb7f91e670f57a52cd65f7b3000000000000000000000000000000000a24147ef5f2b8ad888899c1db8df0a601eca9d76f1b934b1627e7eef3efe542f51205b96b5c00916688579ece81336900000000000000000000000000000000151863d964b12287ae4278c905341124985410f1ad6a72bd5c62230b7d8b0cddbea0c62cb2a7147afb5bfb03348be53363da2f227d636f10e814e360c2156e686e26ce3401dfd15f47c4ed277d05353f0000000000000000000000000000000001d32ea5faa6303c530790146df7cd5cdee93c0933b4cbc1c2b8030bf0a8d2600dba1907df1756152625cfccf8cc7fa90000000000000000000000000000000017b05f549751d090f42ce8a3ac5d959cf988ecdc485f51734d52c40a3e22a097917345978209fa74a0a05be0a66e5c6d000000000000000000000000000000001481fab7750380626b174602d9fcbc97555c516f4410193d2849443cf25ec22840e4fd00b225f98d81b38619e8844ce90000000000000000000000000000000001d56434066551c5bfbaf8c9007874abe57a6f78de9355a297bc117f2bc5e6e3f44b248037f400f7caf83fece0c00ba0ef79e3b6ce752d140c3dfb2007a08221d989038c921efff3bc4e150a6155a33e000000000000000000000000000000001667f1400973598ad3f56c2e49dcb5b556cc38ee3e5801ac4943f3c4554205d8fa69831e582a084aae1ef584feb0a1880000000000000000000000000000000003f0bb26ea548e498f05a5bbda8b8e536613f10e7165607ab77565b193f794664c8ab0a5ae2368d7483b77bc1173d14500000000000000000000000000000000176d8d294b4d975629c6a89bd6d45f9c3924a621259ab43d33a3d5aa1f423b68e3cef96dc103494bbb9036436c170f5600000000000000000000000000000000002f8ed87c584e69de59cdde02b6de9816c31a6efbebafb6ad9cecaf266f5bb9c8880f062dbc9235c91c668bae5051f4bc08091af8b8c6ea5c26f1a7d795132521350d774042d3a8c0523e86fdd23a3f00000000000000000000000000000000085fee95b859c52e44fcb2900a9aa590b1a5c2f981a388d6ad7b81ffbfe033f648c4a84e2119cb0484e178ebd3e220d100000000000000000000000000000000171e6ca074aa97981d2c2ab000a8bd12cbd5f5d574cb83158a6ed734e8f9b7aa4b74aaa43b7aae31b3f4fd3d82fd30ea00000000000000000000000000000000004fe6099a52fb491a0624a8d787d95617f6c64d16d20d1b3769f60d4721f7af66d7e3e905b3e08b2946ef7bff4806ed0000000000000000000000000000000004d3d1a56af91377ae6b00e192ad64fce6dd43a37592fa8706c9344b3d96b1f930e03be85a5ead3007f9016255d2df7570363101b87d685aa7314f6569fca0775bc6aaffabe136e6c336e8fa43dedb8a00000000000000000000000000000000155830eff04ec2f4dfca4f73403e408a68830bc031555433fd38ab3ce1035b5f882bcd6032aba69ecc43625546b4a3a8000000000000000000000000000000000ed5b698b1ae23769cf5b6dc2e39f8500fd8a881eb43452d67c6b84ef9f0b3c7d81db1909b646e92412acc7365923a940000000000000000000000000000000009f28ec2f949cddee9bbe2fac12c2c029f4e472afa1ea56d0edfeacdeb9f43a4a43b79ccdfbe8957b4cc16bbcac1857d000000000000000000000000000000001474b435131301db9e232ddf54569ba99bc476200ceefc15e4aaaf1a574c1de8bd2d63c8280e23127a7a036acae223b1997ff3852cd97c3a65bce9083ff66197fd5c70894641195514d556102f091e8800000000000000000000000000000000168475854829d47356d9a8dc13a94e8d169771ea0070d9ef45e666d5378dd676d603c2eb57a3cda072c11e0926b02d650000000000000000000000000000000008b493a9f4c19831341782fe6285db2f7e8250d72952351ddcfcae6f22a2ec0935e29d396ba32f72dfa4067d0e7ce7cb000000000000000000000000000000000d9e72e22f2a1522babc5f2e8dc7857ee690f60f7843ffe15a080d56bf63db86f124cac039cbfa16fc8ace4d6268a1180000000000000000000000000000000008f3db1f6c0e5e7b3bb27abd34bd877cc3c373c681a3abc88eaa91636924ee477ba5032801dda091dbc51936a90c84685ff95dfa306f91196849d752569b35812e1db7946708cd06df9db9ee75447bc30000000000000000000000000000000004e34bff7e9e3ede02df950aa0e8c5f4c5f85cd3be89d211e957a7de95b8e321cc11400c3dd5b2ba0d1a3008462cebe7000000000000000000000000000000000fc1047097f01fd2079e6357ed379ba39107ec41ed6c6dc17fa6248d52be2b1cc2593c9735a6cb48e6d6e0434028f755000000000000000000000000000000001896fc5e990aeb416cf21ccc73f02c41d019d0a2679bd533d0811b7c16ad3ad3a6988170fb2db030b5fa7c3e4df5acf4000000000000000000000000000000000b70e14ce1b54d7913b9f3782b2b8ff249967a6b871dfac7f54f959954febb2783cf20e20d1710e5526ef8aeafecb3d603c4308f0467520343825a91c0421f9c9c9d06957fa2fc051970f14085339e26",
+ "Expected": "0000000000000000000000000000000008056d4dfcb593c10a877cc8a4accbf58f360256b76876ed2b33a07be3110f8e295ef459dd6fb10d12bd02a8276351f50000000000000000000000000000000005686da1a0da89074c6b13fe9913f5cd49e0ecfea46e06493510625f1393ba4cc2e13f023fbc7ec2e130bf9a4f7483ef0000000000000000000000000000000010cd660001f65876db5b2cb1a56d85171d4cbf037f3bfb0e01bf4430c479237cde5b6cce5839a4fb22b406846e757868000000000000000000000000000000000809d7711211d37df76cd1cf71001cbf02c76df67c83e4eccea3e05b11d196b5d52ad7c3d0a00d9f0ef5b018717fc3eb",
+ "Name": "matter_g2_multiexp_67",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005d6cf50e3add0e5ac3016b394ec363d6145ed66ef56b07bcd33c90600e83b4277558695222062e02d1e2b0693858e73000000000000000000000000000000000de8caaa810d4ac39258e3d1656bf7f2fb7853a5963ecb989346abe90d5d35d3662f6e283cec7bc386a6a8638ac395ed000000000000000000000000000000001849ef86eec16b0612f214c5ed52c0d50a90bd65b623402879f2654fc578ab680d49af9afdeff546702304597a20f1fc00000000000000000000000000000000168707730c4e74eaa4e85e48e7239b9ba3e8cb74c24b7126a685da0fcc963b9f9180e252adf7d8c521deb1a2ce0099582849fab097a4f71bdfcfaf435994a0c6ac3671a4a9ed0402010be83ff95228fd0000000000000000000000000000000007d4fed2fbd9e9dd19e0af5c52637b2cd337e0bfbcef0384f182a56189a7e7304b9d2144266ffa79044be90cb7ede1b6000000000000000000000000000000000baabe8c23a10cfe85494c693d1b09fc8e43ef5f233052d5b6294dae14b4ff9e5ec240a1c00a16a9ddc27cf7b53bcc7c0000000000000000000000000000000001c595f193229da9acff04ef67ca444b0cec75db5b2c1921502e37eebdd2bb43ef47290fc6f1980abc75ef4c50034df00000000000000000000000000000000010fe7f3110ed3a240366ad7ba31d56ab993468dae2dc1b667a46c7759baa37b865d02834e14280a2ccc062af5bb2b7d6e6558521e301eabf09e80a509b46cf8ec118ee8586f4e46a7313a96dc37ba69900000000000000000000000000000000150350d8a771c79268606d6a5e1c147dc9d92e63fdc60b20be688bd52eac697aa5d90fe1b7b91321b2af87c47ac0d5060000000000000000000000000000000000fba8f4da448b8f2bbd99014bee2f9c581f2a974bb0b54f41a84a7fb359e9dbf88ba59a705504140284d486241e94e80000000000000000000000000000000003bb92d6a603bd93f8e987071a7385de68d10cfbde389eaf01ba6480caf1ad8aea03c84d1889b7d5b5c5f72e62a2d75a00000000000000000000000000000000193342a9f15109367030724946342e564507b26971caf75190e0b209e429a948d8b21ca16041a01010b68222db66a16b8f2f7c525fc0f353700fa823a5d32a93189699206c5ba5ed271a158ebb47674b000000000000000000000000000000000bc4a46eea57231cc64758560e3032a8ad8f1907b3cebd7a8faeb98c4216cb8a0c8fee09929ecefc4bee7955f4e799ba0000000000000000000000000000000009f9486257ae3f94a2ca48eb203e2ef44ecf866ddec7824e1a4bb3b89b320c38b3c46de8202480628c53c415433383a3000000000000000000000000000000000d8e2b5d0825b11344d16dbb2cc614c6b84eb1cb43f70d70e272123867b731775b429aacde611318b2700aa567a84c7a0000000000000000000000000000000007f720929287a70873e9f2f2031b66693eaa6e604668219aa5aff3f50e720b34c5fa3f5c66eced5c3e86e8b34a81b984c7e8adc0f0a042a32c733b5c3356cf4a7d648be51c1d78534ca65dd43a0c13e4000000000000000000000000000000001537ed68e203e56f31498efa314322694ebd74cd1dcc3145d534299fbdadd4256f20b9f74b895931a60753bde6ff9030000000000000000000000000000000000935c6ae847aa7f47bf427988665e5e18a32aa869e196cf9d5bac1349c650219a8d20e01bd8d49bc7e4bb8d464aee84300000000000000000000000000000000013e0661d7254428861cc3ed47c3fc9daae8b86db35d1c64f8ced3bc18a89202825f13163ff94ac0ebf046a0a99727e200000000000000000000000000000000039a6b0b2cb91e460d50eaf9600c29fd4f82a81c283ba4fbd9a7d103efdaeb1e82947f5cc1a7a1112ae6344c51119201650081a6720845a20164ef7c06ce1e73286a32dd64efbe57fe46765008dc9dd500000000000000000000000000000000071a6b0267806f2b9e0ba493960fe0e43f135c739a54c8daf5ef9ee348a281f19876f80c0dcea59dfe9457b49809c12a0000000000000000000000000000000009ac83690c30a4afd78f94b2493674668da4efc84007d2a08fc78bba271ed1f43e2a9e5909149bf0811c44dbe07c52f9000000000000000000000000000000000f5d523612fdb2e7dcf5da56720057dff6b0b80707cf5924d146c0c072edc0635c73fb04256e06c7c9355cfe77a7af0700000000000000000000000000000000168431fc569869ebba9b4a72371e3df232545b5fb95778baf3d9105930d9a89b4cb7eba430e9162a5589c7465e54ca3ac067d18b95591f7f14261f95513e1990f5a4f6908f94a015a93fe379726d5120000000000000000000000000000000000ce836522b983fe3ef6a502a0de4c599fad8a36a60d914218d5d2cc4d56d69eed8d27b2d50899639d1a0ea9dc7597f900000000000000000000000000000000014110ac048ac4c20e53f2214df8c06d77f0b3150077d027691cacd3715d4630a387d5819ef58eb1bce2e8669be330a3100000000000000000000000000000000178e5cb42f56df2f1b255a028a00df96c02eab0a79aa0ff3e9772fbe3eb62174728259b3a15e356e6d9666eb65fd6b7e00000000000000000000000000000000045197f136649b61d6e0e7b9a56674e769e2d26716ee7a63fd2b83b767a9ae96694e9cf81375d0377a1b27ea6dffaebbb448bb01a1963bf74e0fbf99329005af8e932074358d855ff43c213e02bf26bd0000000000000000000000000000000016a6a58301c243b0c59d6934bd926d6440b87b49f004f411ab0fdd924480175052f63f594c18007359055dc776e7f2d300000000000000000000000000000000176db4845cad46a13d9dd0f4077cd22b3458f64084c7325e9885f8ca341ce3ccd4f634f41efd6a70f16e1f0c9ae103a900000000000000000000000000000000068ba68f652c4f072a64d56618f93a1e148274b1b835433be878c06e11f65ff45b7cba0f67fbe80327abace68396da7e00000000000000000000000000000000047a699487964c98453207c98cc91c980c1ed37dc26e17748e6ee88e5f4c0ce424d87c82ca6db2264dc8aa9e437a5f25441fc4cb1ea8f86af8839aa40c35c0706f3a159b4bc902347009f744b73cee35000000000000000000000000000000000bf7e4a9751d4e3baa7ce9906f4378764e5384136944f6d3f3074dce66ed017759783c64fc381f0dd7512d6f6e55b4aa00000000000000000000000000000000006ae2a4fda156818cb5ea6120edf7ea39370eeecc3f306890f47a6dcfaffccbb69fd21f33fe491b7065838b277ad2b2000000000000000000000000000000000d3ce00c2f5febfeb232dbbb74fb0405bab86474d1d9c545c93b65c7892bdd58aa56225641074ec9b428efd9063085d00000000000000000000000000000000002552a8c1848fbefd6b039d6c4bd47c34dc34ab307163c4f6d337946f1d1b41aff2f7e37f5fd94012f0ebd21f97d18a83020a1ab853ef2018976e43cce2724105a2526b28d23b0226c49ff3d4a03d40c00000000000000000000000000000000105320cccd67b6ea78e96e66425a10a6911d2d348fac3231af583146273609fcd7fd27a19d4614fbdf05bcca0f92b927000000000000000000000000000000001204229ee1f66fb5a5dcc4ee978327e35d703ea310901be9c100af824e39d24a028ef8fce42370e5d734df02a26c145e000000000000000000000000000000000dd21f31f116681c1810bc36141cc18096cc113faee7db2c189abb7a746e398e272fa0cc61286aea0a5ec4008c8d03b60000000000000000000000000000000007911297718e98588844b9022c825bc4b37f2af30e1fc2d9cfb58b4500dffc8e9949afddd051e971fe78d4e1e7ad1b4a82702398b8c95c3a8cd163a8a3cb2a7a04030ef99404c325115e9a9312e8c1bf000000000000000000000000000000000760787190048e6ec8bc3bfc368f010e2f8aadd53164693a62b0d7207575bb2597bcec4bb382c57fe9053e90fe2f7159000000000000000000000000000000000ec525abbf13da64a8093c5d3fb800440f4c1fe798bcc71eb97bf2e0aa9e8be4b08afd2313f9143260058132d2607141000000000000000000000000000000000aa12c902084eb843daf7b351989bbab7a86acb62eb54eff0c7599bacaf44653c9fbf53f47f6ca72d22ea1671842eca800000000000000000000000000000000082f330d9a693f2bb9386fe5274aa79ac73a17688821f3c705120fb2aa76903627786a8614053f21a93e0aeb555de64e338468a325384a9367c90bd0450816a22849b845aadaf187c27b3f09800e791b0000000000000000000000000000000002ce7f08b8d5052d8bd07090744ca067700eaa1db61dad3e5086661850337bcab485c15fdd36c309a9e5169fd2a2b55e00000000000000000000000000000000073fa834cb4dc4ae120e738059749bfbd86b9e64fd71b1d372dcec8474f3341137ce8cb97a38955e9081f9bd5e07ab830000000000000000000000000000000001568df6806d8c3cfc9231802ebe5edc5d505198747a0adc24d0ac59f28d32b7b379d1f2c6b8352389057c7465692ded0000000000000000000000000000000004fb4b08a4fbfe197e924be3f7213a769a2bcd24109ae69a32a197b6212c5f50dbe8f46f5ab6044a4c779cd3e09d13bdd29136cbc4764346e7ae1af92fe64560f453821f96f32a42a2006b6edee75021000000000000000000000000000000000c07ff656904a47b0c7bf77540abc47cc6eee3e76b6ff0983151de9468ce3a860c427f3d5d489d096264159ab0567cd20000000000000000000000000000000008cce094ae1d9fff246a0e76cd67dbf9808c94554372fc4aed4879487ef240e45047dc201dd8bbccb613feb9c4623a0b0000000000000000000000000000000008a25297940a1bca1267fdce450b0cf43105eb4a21ab14562116039bc8379b1a3f58a7c117e9ba735bdec40f772465300000000000000000000000000000000000ae17a9b1fc3b0b7803ef48cb26643e8e78ef133f94bff5f87739182e662e2641e72383efab1f3ec58fa20fc816d56c675a59418f1462247d3bddda5937553e96d854b5df64a68145a193b2b1a7eb250000000000000000000000000000000002357e5a04b0dbd7f9a1709bce9b7afa12b10c7274b440b4dc3bf51a801d483804b1b4b9a096c3205a0e2aa7c0100c6e0000000000000000000000000000000002ff20af67f126c80293e44bb3c9ac74a94586a2de4146588c7ee8503530398eabc30f7e89322727739618087fa55de50000000000000000000000000000000013c6d06ce509fd557946479f2768f62474e6db04b2c92c5cfa86c023f79d05a387bd4c9aa618888476d4ecc93ba0995e00000000000000000000000000000000000fa477870c952f7506b879b17fb0a1c31771ee832ce0ab21a513fdd91b7a2a78a03d297c55558b834e255462b15520544a345719b40f973398a6fdaa2044037cacd7f6c361921c62053cd51f2e5ff700000000000000000000000000000000181336b8fdc03c02e23cd06ac975855caa2bbc1fe78a2fc7a9d0963c90a1f1f9330d50b88bf2526db6132d336ea5b8e6000000000000000000000000000000000f2d94d3fde2c0f67dae5a6ac12f713ccce2621303762e01961843eb9924d1d3c732b4c977d8cd0e5668adcd7dbf7dcc0000000000000000000000000000000005ac9ecab11c3368c75b0d396889dc34bd43ccf550d817c1dcdc7143c15d5c0e241add37328a7bd8556fde87d75d67fb000000000000000000000000000000000184704eeebead43f85b32d7f3efb9b9469f3ae10b73a2f034bd33e6e66da0bc36597d8e29ef5585443a655e24ffb68fbb38b4cd72eb18c3ac87860aa58b4b439712562f742f112b5d769415e9c19d0a00000000000000000000000000000000046751743f8f747e378738c265c1df3a368cd9570a2bd7636991045974c34039161fb0eddc6b813003e0908915b402170000000000000000000000000000000003341bea6cb81fc5e7baefd386a518d17a6f752c0e1ace5a9580a1b1649f5501c7b4639ba0cdbc33808d78b025a31f190000000000000000000000000000000016e3b9e8e189df73574a00a721440379589a7a6df09eca9a790e04c729400323b2110f63d547d83664c35227bd15b5760000000000000000000000000000000005ebd94e4640344e99e7e0f1619c6288665c985b90d99921ee61bbfce921265c4881a7e1034bcd840a665bae44467f5a94a849f6fb5a53bd5957e53ade1baee05702185b4d0fbb7c1cc0f46cb75614fc",
+ "Expected": "000000000000000000000000000000000d993522760839abc960e99d62dca1021b52ddc8147929c4a064ec72570ffb3793205598cefab8490446453fb6da231600000000000000000000000000000000105db1e83fdff735d06d34574f962e70d84e2c1ceef4d8a8f14c2673633d7dbc7b97ba6dce9013f06fcfb134ffa2ef98000000000000000000000000000000000363be663cb0d36b8eb076df283b075ab9e568e460be804f197c51cf7ef611d8783ced304407d4c2540f1a4a04c18467000000000000000000000000000000000ab2c00473a2267682ecb356422aeafc893fab96a3bd27ae58d9b0786624c8fde446cf68bf8a003d9449702e345b1ace",
+ "Name": "matter_g2_multiexp_68",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000a575d896b06c5ebd7459a70b9321cd0de082dce7dc0ce7e39581751d01b7db810bca80f39f521df0bf70ef642bd66a000000000000000000000000000000000ab497a9590deef40f6fdc0d4db2ae7b6ad9ab59f112a5a0671b48581f1f2b6a71602c73784ca6c0effce66a0a9c6500000000000000000000000000000000000af3812439e44981c91633f73d1a92298ca1ed426c98cfbdb50643cee36affd5fd02886349aa608f4b8a27452a51a96500000000000000000000000000000000013126db8b642d33dd988b745b07084ef86a228767f7e8bd45aac830dbce4136ca5febca5fda9644d3292203e27439d9f5b9d270fe31c772e9a0bb409d9f08a07887f045f906f30e2653d293b6c2c277000000000000000000000000000000000cc12f75fe5e6d6f082f9977dcce64c7858f3b6378112e7e083caf0c4b33b5811d62a1130c595937983905fbde8db1fe000000000000000000000000000000000308b803bcaf4f63affaea0206aa9f4770c21b4d191890602bb4151b80fdb42af0cd9f8dd2b1a3adfe28d0e49712d2290000000000000000000000000000000019f83af5cbee858fcbc9bca0f499222849b9e80dde7ac79b7c46785a484fecf274e0d4326469eca647cb223068a183d8000000000000000000000000000000000d0a8334171571bc63054c032299824523bd2476b1150a67eb17b84bba01d8a65295624202c3874e0302159951734702dcbf4fe86140c50618598be9185830bc1da11429162afe0528f00eb6698ec088000000000000000000000000000000000141cc01094391887f46391bd49fdedbaaf524cfc94d741cc7c8cf081dd7c425d81ea3e407be48127550012e39d2b0580000000000000000000000000000000014db31972eb242d6c2912b418ddf416fd7911f13aede9194559b05d1c9e12056deaa1e56c155cdbc231b39f4f9aa91ea0000000000000000000000000000000007b361beb6c156b5c8b92b489e6d6c05e32a4376d20ac3e1a54c94e678c88480779bb789c3e1ff7a021aa6d872c98551000000000000000000000000000000000215d270f2d3c5c5b9fa99a873fdc337f4edad6889f7a55556d8ccb5ee86b592453b74a720ef6a907bc342710cfd9cf91d7fb7121ef0baa85046567014620e1adfb9e8b3bc95adccbf2e0b0ea8f37c670000000000000000000000000000000017f5d31987655f8eaf046d6ea4025444924befa51c319b2bcb02dcdfde4d80a1c48049514e0b580e4bb59dd2fe40bb22000000000000000000000000000000000141ab771c08ad7c592725630aca0b2564de1ed8759eb3afb10a4bf451eb21d25e8d917f49bd5f7a06894baafdebbe790000000000000000000000000000000012dd82703c939cc5e7dd5bc3b924d744f0ef1a95fd0b9e57617e822e3fdda05b2e5a9959ec48cba0da40079da2253cc7000000000000000000000000000000000c53ff34d875fec4c7095af324d15921cd775873a3ba67740b2c123d6d482263b1cf93585dc810d19c68965cdbd9e102310d3b0535e78d803b477e5dc26c71bb18acfe66bd5ba5892d924d265afd6a16000000000000000000000000000000000a6514331035d42f58abf98b805f159921d8c4c935f88bb5493c580a6ce14a65e243424b41b3a9188e26a7f0c912a378000000000000000000000000000000001351e48b2d3f619887f4e83823dcd9dc15afb2800169ab78a2cd5ebdf25dcb6310f1051894bd2b549e509c55f5286f600000000000000000000000000000000007900972b84b6a76b2e686fa5757e98b8395bfc99da86eca122ce209afb39e8f3b07603cad92623774ed54d637e350d30000000000000000000000000000000002c68c42b3924b89a67764990478e48fc17aad4b5543bd38bcfee34fa1cae7535671f3b885852aecac53a30f28b0d4aa2fc9417e65cb76aa0093a7deb3d38c111c68f461a4aac57d8f09189f94407ee8000000000000000000000000000000000152d2c0e798d85e4dbf35dab808dd29d724e9b6c7ca7f53ffddfe1aef5976f2d3079eb1d3099e91b37d9fad7f1af5750000000000000000000000000000000015059423ee4e7201aa65e39116a2a49ba715b15e4b9547d18a0efd355de6f5a0159bc9047508bd3649407758d62887f0000000000000000000000000000000000e5a823fdc69f3928b22c542388f982f8131a978b08dde80d44e51d9eaed2ac4a1d5fa7392be6c7edfa33e833da4832c00000000000000000000000000000000044285f4e4ce526f96f9f512c5be754e0b0953744dcc04807ec6f041ba5c6fb9d5d395e93317064d50e61aae26810df0aa0b2d714aff175a0be2ba9e675a2be8936c42f15e304a146622a95dd6b3e3ef0000000000000000000000000000000019c457e369dbfaa130ee79bd33ca70d00a3797b6cf62126baec0c5d7c3fdcf5ba7f41195276dc412b6862b71560aeb77000000000000000000000000000000001206f67dee6521ede85573bbd5784d675fea42da16010544857d4e2d81b720b6f85f646fa23540880b44a6cde9a39f5d00000000000000000000000000000000142018ecd7c7acd4f4ae288e1c6a66594f1c7f31bdb9bade2b4dc4c6455cdc685b716382c54d67373831a19100185e850000000000000000000000000000000013b0b57463a3e4cbe063c0d4f4e998cbeb132a41c2877106ee60e83d4ef7d339a5432d30a3c149a42dfb1da9d61f34030227c3510ed6e4c7f84b11ddd2d6caa55e0e79ed59e1cc0cb325d55b5d145aa80000000000000000000000000000000008a463003900194e45fc2610fb461fde538b17c4fd516919000d423f5a1b582342ab9ec20d8eb6fda8fffc6a898e46420000000000000000000000000000000010eef0f7bf73e35dd75fb924bd9759c09aded9cce46b05e5d3c5eb3e93e5d5032ecc459e2220aa529d2f773c4b8b8c180000000000000000000000000000000002a0247f82a25468ee74da555218cdbb6405871f7097c24e89db3f3eab59b91ce48ac06e8eab2c049346436c846226a3000000000000000000000000000000001895b58a50c025e46a2cd0c59d5437f6eee75fac949adb7ee12d455c96206a33ec9ac17d5088fb773618fec131981ab6ad930000a9f82e082d408999b396aca2b0e435a66faba1d95e10fa0abc0625cc000000000000000000000000000000000cb0f13b0680c2f7de522a59f4e46fe1d4af3a64cd3ab97a2523ad3c3dc42f5e6760e06cf48e4db22ee64c5ed8273dd90000000000000000000000000000000016517038ecd2799d787c5b6ee93079c93f78de4a96449bc82699ddd6eebcedaa1d02981ab47c529652cc21663f1a665100000000000000000000000000000000067ae1dc093d4aa2ddd8b7127dc60745ce9c462a066106b099a7a07525597c72e4920bf64c2ea8a3fef3de51c703de8b0000000000000000000000000000000016374f51023e2448eee7c64115d85794996fadf4f76fd4266c45093c266f35be09e861d07ff194f3d15e310385705f0e1a6799cab8964c7b79b80e76be237ef49c2bdef5c99a38ea873af6e9d49790ec0000000000000000000000000000000017479396aeac06bd624a47e75b066d6daf5a37dbe515650cdf3e16be21e7d3a1f52a695c1c06382589eb7fc869c7d9250000000000000000000000000000000015c31ff36ed4eaec4d3927e62c111d062236e19fe6514236e6e3f7ff05ee96e3e4c084fcafcd21049a81faa1f84b7e7c000000000000000000000000000000000341b440e6c6273515fa7940d2f77018169bf6362b70a7b0cd6d66cd332ccc30e3ac48f7581edf47ebd137253a9c1369000000000000000000000000000000000cf424de046252efea9320b32b79bdab58e0e04f2916b4e8ef475da7b8ab85d8d5fc793a45ec6e6c035b6331a895d3efb206dbfd70e4b24bcc09ad35ce7b3aa62d17f18347f2bc5f15730202909c93770000000000000000000000000000000007c9111a85a6acb851e9cbdadf182096b720913ba3fb357dc2cbf2b8e796e9a8044b6df3ccadb740c73a16c3780c640b00000000000000000000000000000000059543a955c84a197d23cac22e15d82363c881026e41c57ee924da2a8c044f3021b29918d1db7926ddc2fc7a662ee7ab000000000000000000000000000000001355d8bcbea65a50c9b6ab59881e48e8e5f5592cee6aa69d5d01b033a84057cb6e74d911769bd2ab5f9722328aa204640000000000000000000000000000000011232571c95d0cbadf8e70454c851974efa4b326370249238db159a1224cc6d34eaad690e1840ad887a875b667ac1f193a607a7301bb7dc5b9c82d956ebb0bc54568d0654d725d4d5f13ceb6231e862e00000000000000000000000000000000088b7cbecf91721e01e5e4a08ea3b261febb58cdae3056d9316c3840b3e5720a289739568bec7b899f4b1f4f5372013b00000000000000000000000000000000001f8835d4b0e3b957e46b718b6bcd81acdb50ab85f10bb70c6343a23970efbe72bef89dbcb24d66e6a6be3eb55665a200000000000000000000000000000000046500afd292a31bb5a4a9bd7b5bd0fe608bb1265351edea69162e61f1623cf58e34e8e1a8ec58ca166e8203c86f84c00000000000000000000000000000000005d6cc367ff9c88fc8b6c35383f147b4f9e3eb21268a5a7405794441d449b3e1b44c8f66e30783e5f6c3567adf0d80171231e0fbbc2d98bfd1039a889acac471110d568b0a24ddf5eb3501adcbaac6fa0000000000000000000000000000000015bab57412cc5c7ee0147b0d2511b7836a14a82df06b4eb2b1baab102840ed04cad81da6e920ee000751e0727091c1460000000000000000000000000000000002f725e61e82980e6164cae7a2e30a36dd7245402f4933697607640d53fab2d5db57698be33a0c9b5dda14aa846db7c90000000000000000000000000000000007fdc589448887f6986efd817c63954d350511401333cb0df89214317dec0a82b06259ae9263f260fc7f21f98ad2630f000000000000000000000000000000001324e3bb46a1c69fc550fa8f2ae2d0ea74bc2d7159bed03c13a9d232233449e271ad1c3922dac5d84aae52606f77dcc0393c5c10d4bc4cd1567bca6960051f818e5c53704ce44dc4582767fef1092a870000000000000000000000000000000010adc26d73007e3b1cc58684fbdd7d197550658b4c66c702e9cd0f4e481f23a26c94c6798cdd9763110eefdca3d802050000000000000000000000000000000009138258ad1bdf6f9cdfb943fa32b42c4f1d834be536ed365d00126227c78b0df2776610fe5cf66a937cca3e0b088861000000000000000000000000000000001991db3a35bd2cd72377cd459502a84315422bed92890af906fefcc0acc4515fe7cacee1e4f360ba24efb23292482b8f000000000000000000000000000000000d10dfb682ae7a78b23b37b081efba32ff2011fcdae7b0f8a794a6ec33d71f5d6055f93e3b68a37086ab190d7d9bd7aed412195e347b680430c4528987859a1552ba8383cdc075c437ef19db6eff6e1a00000000000000000000000000000000182795b905320ee69281de833f37e040a3295e23be05ea7ae4563bd49d8b1fb02e95782c5c19645244633951cc29c5c900000000000000000000000000000000053368ee1412723b5c6465ee5ebddcfc00812e0e12e940f8485f44bce475c8897b324eaf7e66c0351ce9a6c92758c337000000000000000000000000000000000279f26c1e76e5f5d0fe1240c0956cd6025f6520ec303feb383b69525ebb6b2f199808a578a91368c3881a4044f37be50000000000000000000000000000000000ba4012c24dfe1038ec4b4565e1b321bbfc174cb197f0b0914bf1c126bdac9f423845f6742129670b7f3dfeaaa62df45b6701bc11c1ef3c9389710e4dd090e3db481c5400ecb91655c20694207a71f10000000000000000000000000000000016c27a3a950fc4857fc775441947f7ac02af9b3df6422874507b11f7b005c61d7d6a4a115d3759fcbd64633a8ad95611000000000000000000000000000000000e92954034df4f15450c32be31d4e146c4b0014a2b81e2afe755df79aa962afb05ca4d03577f15980fc6d8a34f2cc50200000000000000000000000000000000032db3e3c3617c16ceb1c8fae83e806744ca40cffb56bf9b79997cf48c55e5fea89db43b368cd922cd7ce30dd3984d82000000000000000000000000000000000d153fadc3854be49b2376ffcf4e5a46b9dfb4f54e580986767db13127e2d4d10e465f1ca932d79ca90f1971ddc0993dab45b07c059738ead9709bf36ab20b09fd3368f7aa12c6d9f3acf3f145c83fa5",
+ "Expected": "000000000000000000000000000000000e1968e131e25d3f911284c369eb63aaf264ee82f4d9bd978b7d02470feab68ae82aed8509ffba875798a292f012c9180000000000000000000000000000000011488365570d9bff018ce6aa15e3d7e078368f09873ed5e0b827d1c25ef369d6571899c8df38a3df3135d0db814c87a700000000000000000000000000000000161973f4949bd72b9f010f017398778e0d7f0c8f77e12a87db1851af516b4540e3f4df314381f295c4d167fd9ac091a6000000000000000000000000000000000ae16f0a4a597159195aa47862585839485615095e538b745c1081ca73f202115a438d279dfa45bd3aef8d4043ec67c6",
+ "Name": "matter_g2_multiexp_69",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000046eea8e5af344dc8600ba7e506e923f6c356f7ecb3b78bb3805c4561e808c1f570e122c4fc5a1fbe433b48ce0c15d510000000000000000000000000000000006f1ab405a46c825e104bc963d2b2f573f0d345bd2b08a952d8793c0297dce267a754b802ded4db478399cfa88e7e255000000000000000000000000000000000a5fc4a09019ac9649c07b623d2cbcd9f0cbb89d28c01b170b62544d8da8ba3f236ca3172ac754175a3db85d9b846cfd000000000000000000000000000000000f7580110db2549742f69bbc2850e4ab35a6e415bcd1b06220b9b009c1f4c99152289eedbcba2aa653f38f6b8460386b3ca13f8540eaf45ffdab5182883d32a1d35e7cd956092221cc40232efde6cd1e00000000000000000000000000000000026907ccf4d501265cfe67bc1c0b06840e9dd94a614c873d676b5416457d98a1dd744322887f1f1f86176b11a27d2830000000000000000000000000000000000cb08e541a5b32fdf51acb28ec64d3ea542c7bd75179fa3f74e9588156815bda9d027dcf5597d714aa001b2dd8a9553c00000000000000000000000000000000103ac1c03c16706d5936f216a6445577c96acd3a00a3d8a9c2c66e6ce568dd84a4c4db187a5fbde24e6ce60e037f53a90000000000000000000000000000000001da5cedccc02d0f8d1dd7e4d81c3ec47d432e81e941ea1452b112eaf40748a6634957c90f32fb0385dc5d642bf65acdb3c8b045ef559b76005875bce09a66b36f295070a73ec8dc66c86bca51fa5d4d000000000000000000000000000000000a0b8dd68918b58ca6b113e938f8a00b2595351777aaf32dfbf703ef3884f02c798f1b5bb78cfac32f196c1fe88aecaa00000000000000000000000000000000121a4104e374566f8d582f75a3c9b70f09628f116b7ab22679ee13a1691b0b0bdb0d737833fb606c746fafee5859f1ee0000000000000000000000000000000000b8bc89d718572ebdd6e3100769f2571cabdd79ef5ca9a4b9bbaa432b1a4dd752f9af9d2a9b1f1f32d76d4ec2d1636500000000000000000000000000000000129f1d760a12eb1a75fec1d2ca438189c933e87095b9fbf9a0371d64eb205d8f0932fde9ee2ab9f36f8b6e5d4b5dd31021953ea264f74bf64378a339461bff41c5193e17913c67be7e2a249c9737b825000000000000000000000000000000001499e5481ceeefcd2ff672df24e8987fb60872ed106c496178d71c68e9078409a80016e1f9727ed0d5922c93e821dcc80000000000000000000000000000000007bfb606c005c7da6b4ce2d974f9fdb2e3710c8f51f18257ced7663cc341ff81fe2e46308a2b62b13408965949a6f08800000000000000000000000000000000003fbd951e860e3a4724b667427fd9916ca4ba511a0dcac7b1125b14d8a4f4da82ddc0b0edab8ea50e911b0fcb5c200a000000000000000000000000000000000b43195a5f0263307e85408ae4eb046e06ddb1295a490ac4e0e654324de53d0dd023b8cc159d86b861dfcfdf7ebeee4a505655d72f1128ac0204539f0d823f076cb3a57a7e74e896b5019c9161d6486a000000000000000000000000000000000743bed2c17bea1ebddf750da504fe120f457cd3b1754c9413757cc48f7aef07eb4fa0572cb853cb72d68427e875456000000000000000000000000000000000102ddfe3dee27186a9484f74b3cb3aa366a79f0d2e36063af6e484f6a459e9168d7a4a6969bb720ec694a52db7ab34b40000000000000000000000000000000009bdf5b86aba4845adf9187ccf9c74b1fcabaa05764e41fcce4b38356b4a0ace8e7b16abfc7f7b96b785ad47fbf8e90f000000000000000000000000000000001934fa903b71d234c4341b2f49f8177334142e7c401553dad38e66a2c157fcdf7637165058955b7798a59051846dfb8cc4c861cde3f445e3a78d1498d98b2b947056cf578652e19be88da4a786af196f000000000000000000000000000000000ddde953f59b8591a83b0cdfce780ec23d052037c26d60cef36522d0f984f907315d7b41c8be9a9632f2b88e0ce950ce000000000000000000000000000000000b8d7bdd94a994901a434e6ea5d03ea45dcdb859e560833d8ea0bd9d20c7db9c16b2427eac27d8f1eb640b7d28a530fe0000000000000000000000000000000017b5b3a3097a74d9c1f1b23783723235b6148023b6b060234dd9e2f6fd05e38668167136c999d91249963e224f9bbcbd00000000000000000000000000000000133da0c217c31ca052800315aa8a3b934fc1f179e6247801904bcea1e28dec0b65632ab2690bcca3606bb1461aeb147b99762c5189cf154e24238e4b157caa1d8759002f69b289cfbf3f24f5dabf20bb0000000000000000000000000000000012778a6fe79b1f2b768432df036543cade95504bb7735ff547969faaa8db84e3588046a074838c9a551a4fb48f4a66140000000000000000000000000000000013288a3413d7e7edebd118463d5eea9f9ae2e10f51965480f9b5c244b05775d04079a1dc75ba0885aaa9e2e4bae1ac750000000000000000000000000000000005b766ad112b8d69f1a28079688942ea146f8f31616611909f539a57c58ec5e857da9fce415d683c1c6dcb5e74da9d17000000000000000000000000000000000907e5c3c83d3f12a68d6bf812e310f5a04f1417094301fab7d4f41007b9d01fc1bfbf739dceddef756417367ed5b1d0298b5f6b43074b8f0807086b03f5028709209310474c35c7ee232eec8579147c00000000000000000000000000000000090be6ce5ed09e45a6fd9ea3a9223fe43a835141c1c29d6b386e085846869f9c5798b80c3bddec8bc15171906dd417dc0000000000000000000000000000000019bdf67eb16f2708ca55fd20af8deca66e2ae270b2f2f9736fcf49dbdf7cee034cc956f6fb799f0e87c12f283a11448e00000000000000000000000000000000124a69c723cbd366d52919a72dfceb7e4cd9ca5b5cef1784bfad3f125b11d810328ea1c849602536af500261aa684f5b000000000000000000000000000000000bbf05318ffd81495efa4f4c271c8b1c669041a6446501788f49b8739a934f09de9d976fe7300b0ae861be567d35c992177bfb0218ecd8cdbc6dd9484e74e41be6971ec2911bacc8b53b9b4b8c70e5730000000000000000000000000000000010833a3e7329ad40c1a8cef296b015f6ac6542c612038ce00f13a99f673783cb7eeb14796485c168d21cc169065d051c000000000000000000000000000000000d3b1416b23453b893c92a6c7850cdc0e4a395459140391b1dce11055da10fb68f318c5561e1c12d991a28f3f544a5230000000000000000000000000000000014721dc58eada80f2d0574fb4e2c1c94c45fbd90c2d2fd666fd618a96f4736a5ecf34cab34fcbdcb19b6cf7b44098922000000000000000000000000000000001905d34029bf84617a956d1edae090853dc1b622f560c5289251447ab6bcea5700bdd80d6ffb2dc12fdf3b0267e74543cac52219796226385aebf9e85f5f179362d4149c33582a97b7d2aeb05a8e6a99000000000000000000000000000000000b4d380f4f4eb976e6121b933be8418c536f85994491b0b93695d50473615e41547ead326bab795d4d59524a61d607cb00000000000000000000000000000000104b7f4058c9b355d38908d715c311a53169b42d2434de0876f1c4ffce1c39603c4876b33fe3076528be15fe42849d3e0000000000000000000000000000000017e2fd647e7739366ebb606e8a326daa5c03cd2b726cc4cec7747cb3468419f1907126d7cba98bbbc659478ce3afee7700000000000000000000000000000000183be0a976dbb3b5385b544c194e111729c7a8d5aa98eba3fe1c0a5b69b5fe6e5d0164e96398cbc61eba5b86d91b3c94e03afb2efea85fcd035cb4ba09977b2e1c84a0d98edf88e9f8d2c4f116d0f50300000000000000000000000000000000023bc7eab817fcb9982cdac242cb6cc0ee1779bcefaecf144dbe57d5ae2b2ebfe9088f39f416a56de4b4dc04d4bbce7a000000000000000000000000000000001318e728c271746905788dd8f5ab22a3a10edce3fa063438e54ebadba22c29e461b2ed78a95a8f26a65b47022291b8df0000000000000000000000000000000010aab000b9c5de56623f18861b343ffa80da5ed4ae0d7767b7ed791bf3dd507fe7286447b6a07ea0fa12c19f2e4d8e8d000000000000000000000000000000000770e2909b5795a08d98dc66389655b1718e70b93c5bc6d805c3945cb5fc0092a5b390e6497b550988c28c58b6e016a3804dec43760dab29c161b8f4bddc52379a17f3168f684267cfbbc3505e32d5f1000000000000000000000000000000001259a4e36f5bce7d5f97184948d57fccd458cf7f2ae0c9e174f537bece01d744fef544447959cb73a678fe2c378ce3c900000000000000000000000000000000131aa575b2b94232e06879fa1f6f145a0bf5dd12456b698f731a72bc587e6def5054b3b2afb6dbbfc34fa5249dc673860000000000000000000000000000000011d64b923596c316b097a0752043efad8b61fbe068c58bec7a6766d9bc90ed965b3419dde3b96679426f72184adb8931000000000000000000000000000000001653af784cbad5a804e3f72716bb51e0c733014d587952c47395f953828566cbd7da811a3da1d48681998d569db00a7bed2d3daf616df3f0061f58c925e9dfbbf6e9cbfd4b0b3896a596919fb3d243db00000000000000000000000000000000077a9ab830f7683b7fb46676df09f72d773b65286c5f5ea86623306e5de51e63851c18d192c4c3b20af582bb7f017ff70000000000000000000000000000000016dc185f4158e249939541d35ae8230fd749988b9174c40c40b8c932aec625a7e94beaef9a07f492445d4675a01b7453000000000000000000000000000000000c107a895bfb45d33136db6251c76dc0461a235fa5d1ba7a5d216bfebe15691261b46c9816315c146becc328acb6b8c7000000000000000000000000000000001151cba240678efe61e3a36e169e314b3610e9d4df6650507f53ccf635d8f1277a80d86baa85a2d4c7e2af73934a7299e16797ed90581fd8c3cef1f30abaed10997f13461374ea649b29101959fd506400000000000000000000000000000000090a1ee6c611980e0421b72a122cb39257dc38d1e74ee41b809ad76e440fe307cf45e79afddd8d40b94382d48cdd4c450000000000000000000000000000000010f2e6e610eec7b7c2b95c1510af1af342ac19fd3b01dddf81b8961ead2cc57a8eca36c2f5747238eded5914e484c52e000000000000000000000000000000000acce0789cfff975b09d687ef79535c536f3b799157d3ff731915ea5b323ddd9f6f4750dc8e00a879d4e516bce8cb3e40000000000000000000000000000000008d8203dd13aee7363f6b10a9e1ae9b713bbc8b8fb2c56f05fa71e8d69ea571384d150e8fd01e855b1b0054fe7967a052f9f29432638c033ca84422b12ca80ac4ae85fa30ff56c913c5737aeb2c84d04000000000000000000000000000000000b332430c518d7dcd120b346440e5b6b48900b5c3656d84840823a96e5bf002816d583a989898cad9e09ba978ebc58a40000000000000000000000000000000004197b43877b833de7f69cc1a43ad8d6d3544cd10d42336d4b19a187f31337a37b10cbf48e72b77e4d8e1a1da68e5e4c0000000000000000000000000000000008887d5dd08f45034584f40a2a68254baf2104f9d6a4c2637ef79c5ff2503c246f7adc36559758a0c07533b66c3637d40000000000000000000000000000000009343819dec1d4569683de4596621c19785d5ed14ba13e57d94b1b1a108aa62cc8c55c58dfa18c06883ce50cc1364b95e6f1e5df7ff90c4a4fb9a071c0caf3a3997569538ab9837ed41d9d0a8d7305370000000000000000000000000000000003fc7f9a0804e7f1664f8cd3ca67b70ba128529a611c24214fd09674072a6b8d652ccd37bf5d4611424688213a41cb3100000000000000000000000000000000137a869cd7bde696035bd9353662e0d37d2aa0731ae55357df3bc43536b9210f360324cbb3670362cf9ef607b1919bca00000000000000000000000000000000045d9d39c04e257fcd912c54e57c86d2d4304e6a7cb95a83d2bff07964d0a5dd8b4e42bdb91a8b245e512395e6749f1f00000000000000000000000000000000120e5e4b04b8a744757812fc331e7c98b35624faa1cbabfc1470e4c0804248bfb0c53a484107a677a7d3f0d2b533e7530cf3283195707c30880e50ff5ef605b561c3c3c354fbe8108f93b36f212f9ef5",
+ "Expected": "0000000000000000000000000000000002bed414afe9c7a630441e7b163280be10e502cf877e94b6521d14baca0087c5dcdfa39ff4a51c8376d99855e1e6f36a000000000000000000000000000000000dcd54727a7729408e682c6e213005687ed51fa7935c522312793fc58cdb273eec9c61cd8b056a26619fc8dc006b066800000000000000000000000000000000137286f4086763e6ccd5ee82d3bda712b26814a17c6a71006a3e6dbdd919e469bd0e744bcdb2074679e78a1e7d56ee7d0000000000000000000000000000000012d75de1310199c0e556d61d6c0395b406afba0f13bfb37486c05d66b446809e8b1a024e8fd2c55f1b82cf2aed99a5e1",
+ "Name": "matter_g2_multiexp_70",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008b83142b22f6d6496cad0dea23c71355e7c5d98659580b5ee6e97eaccb9fbe523f7e3b925abbca3a38f67426f3fb35f00000000000000000000000000000000035f655a1b2d22ea21cf0081e78d7140bad08c4e66dd45230a113ff3b7a77e39f0f1a72991f85e2b00ff58b27d5cb54900000000000000000000000000000000105d04e38243ef1ad2f734a3c97e91506c5a7c5d95e9b8771b7fded8908f1be933a81a5769044b633d501c0df7b5d7fd000000000000000000000000000000000e670ae4af94d0df34a7f2d7cfbfcefa6eebcf2a6b2dc5b82068b023fe02ce8a279e1bb96d905ad4f2ffbd8214e47d702063b046a71c2674e35466657a85d8e02253b42517b033619e31a536659172120000000000000000000000000000000009051f1e636309016c5433cc7eb019c7dbb75b3a4a5b27f6927de08fdd9577e8eb9e12919157ed35bfd6607be7fc4de5000000000000000000000000000000001953b7a33695ede6d0792eba85567aa5052b8a58c1bdc94ee82b5001893c6b996d3e8f7af8b8effd6cf50656d8b85554000000000000000000000000000000000a2f769f00679b610bbe212c2f8045e7579a96dc6bff80899eb7715aabb1afe79421ad5000f2c7b85d4e0904e335ddfa000000000000000000000000000000000ec962a3d00fac14d05774adc49bbabaf46ae78325083c0020587fb85eb234387aaf6506f503fa988df8e9ecafb4a59992fa325cd07502c6576dfb93ee952fedb304022656597bf3bb03a2bbc471b32a0000000000000000000000000000000006823056a4da801cae430fb9e3a8663fc8f46bb6c180b743b7f9c7c7e3287f3feb1aad4be0e98409c74ff58004f8732e0000000000000000000000000000000015f7a3f692d55252fa5af5ec952f581b796d54089f13971fce2ef9062173664816dd9f37174294ed78681d8c8c5a9cd800000000000000000000000000000000154743c76f7de590a31cb96d46a0ec0fa88008b7d6684bd8f6fdaec70722afff7b6e88c1f0fb048714fb1072d30780e60000000000000000000000000000000006f3191946d0e7c1307a1a0d1ea9a26db195ec98ad88f9b8f08a03a3d48bbff1fa53ffc920f7db5ebd4c65911392bb834484e688799c3f0a3bbe00cec7322fba6245570685cd7df0d744473b72f03df8000000000000000000000000000000000355018079cd02dfcca15fbd2934a8e47c5ee89e679663488499ddd4abdaba7679fb1c9d2102317cf2798c47aff1ceec000000000000000000000000000000000c417d489a224fbba9999300eb65a23749194bf5302fdfaa33ff7daeb8d896e387e56600233038d5c5eb59f644a99b6a000000000000000000000000000000000f5a62e9d711293d4373bec1bc2637802938eb789c828939e6c42f10062ec171ac6110261165bd179206d649713f6fe3000000000000000000000000000000000b11f9fd0ef8dcac2e21ef09846ffe9f5a624ec246e31393b39082a47354fc9523dbd247f0059b6cc740d7a387b137f0fae2ef61a024e4d8c4ae277f6b1d834193df655ffb315da67afa4ee4ddcb7fbd000000000000000000000000000000000fbb5521cdb9c3a69d58e5c9cd7e4a50bf5469bda2603f5119f3209669eb3e374d700f851b0c7ac5ee3cc9de79e6a7ec00000000000000000000000000000000131ccc37581e64f6f9fdf675b9b63ceb67d9d5844bf512166f39b5bb09d8e031437c06b0ca01caae7ad6d8c9bbb9fd67000000000000000000000000000000000531cb0557fa18ef054dbff2e7e994f1af08aaea7557602a26fd6ff539ab3c0a73f1fe841177012dabed4a1223ffb5a7000000000000000000000000000000000a180e7a345d2b635be92888934608e8b6c17384c48c560f4cb9809ff995f8e70d83cd4cf0e96c458fc414e1275d2a993168a1007abd42bc398e317484149f2fa61174243fd1748deec6cc75e7c720a200000000000000000000000000000000125c83184f63dee35ffd2c0c7dad9010cd6a9735675099f24b465554ab3db727ee76b5b7ea603ead78795d33e37689a400000000000000000000000000000000141bdf7e270dcd356993327cdb5dabe38a5c5a9b53470d9a4aafc041c46fe8bc841089e337469bddab5d4f7fd3d6ccbd000000000000000000000000000000000f9613f6d05f38e3073f14d0c2557101a4864a7d6d0b5a2b931d0613f020adb99a1ab2037a39fea6e99fcfb47929827a00000000000000000000000000000000192d812e05a17d22c60b78c53fabcc55a0eef3656f8e84132faf16686ee18ab4d35767db9a384d42f392c40c7b0fe1c0f1525bba87baee35023d0976b4a2d87524ba74158f000e5501c6d06aed04adda000000000000000000000000000000000b6e1960e82586de19ffcf29a8c5f16cf2fcf5286bf42febef832767919abddc655a0d1bfa240cac8fdfaed5a1e8f389000000000000000000000000000000000fc1598454caf04414f1930f711d762f0d72f5cdc7a4053c92b916c742b00dd0f107aee111976c1b1218c4577deeb006000000000000000000000000000000000455d6e9e9bb848e0868c9d725edca1f50b279d0acef8c597927eda72763e3702f46b216919ac36b080b4865249fd961000000000000000000000000000000000174463cc7804796b4a6d8ff28d2e8cfd8361b2e38f368de30166cf3c20c474ea0a1e8d94749fc3e6468924a7d1369e62d3d7c014416f33724acaa46412348d350f93d334588d39c77dc0b8ffcb4cb1d00000000000000000000000000000000144e4b615ddb871bae85484c308423adceb5de387d0c7ffffdd2211b4ea28788eba9bfae96ffc46781e6d6343e2f501b000000000000000000000000000000000046e39cf43fd707ddc4b7ce9a8a22a2aa1e55aa63cae1eb23082f7b4b5dce49f32d2ff887b5108b40f98062c02d5613000000000000000000000000000000000b75b5460db2baca86528569b47209b5ac24930e2545cc6aa08c401a87ef2c4e233de537e5a857e533d0ba0981b24d7c000000000000000000000000000000000018f53b83072fe7daab226c831a89da63a0930ea86e301c97e639d0ee1609e298e2789d1a347bdb4afcd355fffd16d053bfbb1670b7045b6df689871d5d012dc93e8be65faa4a98a51db8501a4b7677000000000000000000000000000000000185b296e9c7209a9abcc3194b46be9a545666527ec9b0634a3e3be579447cb52330174c19e40e1667124552392a7a0c00000000000000000000000000000000158a053c788e5b914fcdcf1aebb4e21cc8bbfbcc20c4d692256b2ae48149f6644e1578f98d58b3e73d9768d0e7df643b000000000000000000000000000000001318ff4150bebd8fa612f4e84f89151d5c56c272969bc1f31a3c1fcbd8ded0e298914e98e1ca48248e9023cd12db0fd300000000000000000000000000000000076555254f382707fdb7419772a4978808a7409f59d1dbb8c9e648372e19c44573f5ce1888a2b570a83afc20e698ee44f944ee8d294d189226a6cff17456e2201d17d4dfcb78f58f8501870377a6e431000000000000000000000000000000000f4395e3f2e301ee3e18df3c23cdd142716c7fcfc23caed924f0561795948b0bfbed948a6f7c415ca615ee0ba4d5145c00000000000000000000000000000000176ad308c7fe8c3a1aa350fa82b8f8ec638f77bc703afe1042a6da22e5385cd8473ad789247f205214c9980532b12c7100000000000000000000000000000000092b0ec86c511992c66f320ad46c9d6d7c82df118a9ab2ce1f2c5611ff4e5cdc9193a39c3fc95f18ddf96e139688b00f000000000000000000000000000000000b4f671e334b7f22bd8d89d8c4eb8a52b04bbd4dd1259cc9caa1872093736680618930f3a469b3af4a00cb6e44b573f27de53613b7a31583ccb214726482b770029c0ed42f9528fa74da7d2d1dd915e100000000000000000000000000000000123b64561ebfe085238220eb1428b3a203acb01846d1e4428f3759db6cff4ed3c1b9d436706f28b77e3b92e2e39ecb41000000000000000000000000000000000ccdf1973693e4b43b6133563986f6c96e2b924895c813f8acdd0f39585e4ee95ef26c0d9d51d6ef88bb62305e51594d000000000000000000000000000000000f51693bd44b12188131ca84801bfee0ca853640c0a8d5b20123c97b369c98299ac04beeb27d75946cc6f45f8a07b5fd000000000000000000000000000000000804c6597810d2c75de94484873a67eae258fcc9577bafa778e13d4814ce099a5684b1cc94e0df5a59acc7b19328fb8bb0a9750cdfe0910c544668bc9b11ecdedf1b757ff69b61fcc838c502c2911bbc0000000000000000000000000000000009b02eea05c78a24adfb0187defb6810116e21894d8782605c1d590f8bdc10723bf71a1e5e5004b181504ac2deb142cb0000000000000000000000000000000015882389195128e20e50ec4f8d278e8b8791e362341be93c475064d640e1f8bb1c92a6c777d666f8644d471409bb9aa90000000000000000000000000000000000d89295f845f989e0fbc6e86e97400b08e39b2968fe6c9a141d1e92ec9c838a3d8e1ada5e44bb08189a5d514ebfc2f5000000000000000000000000000000000dea05d8e6ab50b8f8dd9632337948a60568724d5a03c7914e4a03e2af572dd8153effef1a7d5c2cb27765ef2c17bc5b4aadecb1111ff43894123648eea9e57685dcb7a25553233a374479c24f2f8899000000000000000000000000000000000bacd14447ede6af0e92e19b54c4f5b6ebfb94207efec3e9f385a4c84a7d670514ecbc28ab686b383e239ae7f9bd673d000000000000000000000000000000001698bc92d146049174b843dac8c5dadcee12d1d503b2d0e46ee68139dd43d3aa797fd5bd06e2b214cc9ae3647c98394a0000000000000000000000000000000018d20cf6c84446cadfa1a26192a04e16d2b2a053705a89abc51bfbfa35c2b03cd58021ad95a35364ae1e2da5d233208300000000000000000000000000000000113268e360006294fa0203ce58cbfd05d05fb625e1f9474c96c89c0ec1ea80fe834030592c2f1c182ef8a3d5c32caf71adde66cf749daf69a30f41ca00d251f7f1e93b0e7f916a1ba6b994d946b12ca0000000000000000000000000000000001727b6bfa9c601fe84a65c54f556887c4538cb5383a288156fec87420ae7f15da395886e1ac0e10b8fbbae8bf040f4ba0000000000000000000000000000000012127cdf02ada71f28ed036a417971b87fe443b8c65b7739795dc7067082cbc9f06f7bf10c709969281cd072490c06fb00000000000000000000000000000000134f1fa1d277d01e2811c118cf10e2de6324e2ba14efcf717a03c1a10dca0862ebde0f6328839da63d7d85f573e8501f000000000000000000000000000000000d20a036b715d18ac9e2dbe009dd0063a4b13b3ec6fd060a64c4ad2b98e05e069060179530410d154caa575d504c63b7b2f9b44c73a1a6dfba6462e1202166b63727f45dc3b8b3b73b5d06459a1beec20000000000000000000000000000000000bd5375e7f98d3972b93420a39fd6c31da86d0d9349ac3774bbef15c2240437cc0761b2f1245e805d2538cbca6f778600000000000000000000000000000000100232139641c8cd5bdaa75b77e1e1c8e33b3f9554e2ae00ec6315b82cc00a6a70d576d744e68938a299ee2b451558250000000000000000000000000000000004224691faacb007bde3e37db6c7486aa5d3b4259a24c8b7653238e7522604ef4ffc1eb3cecf719a1b7f52ff00c34399000000000000000000000000000000001156ceaccfe0396374c6dec5adb39f14b6f08a32b88ef7499756f5cc324a9f1553bf5dc106a97469f2c49be5d563e1100cdc89e668f7cbd53a2ef6597a48b93d7d9a78950d4f821f3935edf72649e0000000000000000000000000000000000010a549108e77f0ddeacdc795517ccdcb357f909264457cab22fac2b982d10064756d66d0e48af02a59f58eeb1e8ba14b000000000000000000000000000000000c68703ef1c1e93c78faebc5f7ccc69e39046fe8af92e12469e9fd6baee62a2e8cc06fbbb3def81ae5cc57f488fd9c9100000000000000000000000000000000064ffb6aeeed432629242c3843f8cbea5bf7fe78585763926c5c45dc3cb4d1c79b3715506d7cda18c531ef890b22a1f7000000000000000000000000000000000e0eeb69f28a552cc6563f5fdc9919423c4358a2b70ccd56b048c22111454f67107513cda2a5aa0efd2af25dc74a1c47e23b377ed80bc90a4645df09e825509eebf57f59d7a2aa1b9121ace80926ccf7",
+ "Expected": "000000000000000000000000000000000b1913c672760f98fc6d4e96ad1ef200f99add6f233b17291036e187ac6692ab0a29a4083dcf86a532dd06efb3d9b8c6000000000000000000000000000000000323b703abed59a9824f34d97851546a5e78441accea4e3a933b9270f92a9dd1aa056858ebd1739659018a0ca13b96e0000000000000000000000000000000001603cb3ed75c09ae5da6b94eea6017dac0c40b17d9aa8b65b78f2ba17de051bf3f21109d9afb214d260a09391f5526c10000000000000000000000000000000019f3bcdb8f16d9a2bd11e3f9491266780aa9110f447e19f12f7a2d62dc4f2c7b5fa18e13792007f5f361e20656c8ffdb",
+ "Name": "matter_g2_multiexp_71",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b7d06c16c77a57b5ed74d829ad6acd665e73d20f1d9285ebba67b60c0d1571e1b02cabe5dea44499ce6d40a83288aac0000000000000000000000000000000007e6ae768ee3d149c7130022f9883ed51e4fcf68c91327ac1fe85aec8083aa61a37e9afc25d3352e144aaf888f264ab20000000000000000000000000000000016f2423478e0388e8495a898c23d63a0929a2ee7cf848034e4c1adad3460c7070caf47631eb930678d3c85aaba044dae000000000000000000000000000000001587e63cdf50d6e0b6b3d7652ad0a0a2497e70259d73432831781641d3a76db4ac7cff1bef165fd8ba29200d7320e43475888762fd1de395fa80b6d8a751f280eca568de2947e953feac343fd6bd592d000000000000000000000000000000001181bebe3256dd6ed754b8a1d77ac07e9a341789b3f4a4988599c7c60a36f1e95d3e3cec52c54c0f0abe312ac358c28700000000000000000000000000000000189d224b2904bd45cd1e8fa72570a1e35c94680d03d30292892462664f9d7aca3cc45ecc0773e66a10248df28ba9a9a1000000000000000000000000000000000f654f4c8b02a891e14fccbd5a96228afaaf79ed8306c7c1267715bc934e5f2568ea06de2bcdc2a55ef708689d90108c000000000000000000000000000000000c0a413f16e1aab8b91a87e7027f067ffe7de65097da37d67f604a184c7e7a7af6fe59ced8c03fa32ab036862868b35018ce7941da132adec1eee8d81facdb5012a15ddfe0cd6751ebbf66ce6c495043000000000000000000000000000000000dc972d55b7e68f97191d988ae7be5f5301bce5c654b323d4c17bf6e070f7227c0789ee38af3ccc07b04f0793090c6130000000000000000000000000000000016288c405bb42b4e71d12fd0a798cfccc7d33aba0500f939f5fedbd0e071166169d3072befcc5549cc6963b6dacbef4100000000000000000000000000000000171ea4f6607d6efc875cd9cff203bc62eb83bdc05c07f702143c23ab2770f50f42738f748e6bb3bb5d6f51f40fea1d910000000000000000000000000000000000fb729cc9716bf2e9e30a598ee7c4281163b287422ab66b414da85b0b960102991c24cd023791e4241bda5b0f6ddd3424a0497c642dce3937d883ee25b0ea577c729366c7d67e2e5ff1ccde3b19a5dc0000000000000000000000000000000005720bcbc598c4eda697406dbb390c2aaf4bc22c794b4b664e9b85b7c2079b90f7678e69496a4a5cd3b46580b90a7a30000000000000000000000000000000001159788c3edf619cc5e6f77c4aeb4860764d46afac4cdce54cade63155040c631eed65c2fa11b9cdff14847950cddc2e000000000000000000000000000000000d61bf02587e2c61544ae8a98b4c742c26a3d6ca49c6ae1b19a9d69c7f8eca43cefd555c973145566f8332902217cec3000000000000000000000000000000000cc0da96623432a2c170f07a3aad2844c1c2aab9d1bb5d2183928c818e681c66cb3767be372be4ae65fa40bf5483258ce4e0ad0d478ccf5381470a3fc9b882639dde4a0147c7c82e50bb93431b07a1350000000000000000000000000000000016efffb5d4ecbd01567c1e6099c0f06644d4312c599579b4cb780fccc8a425f3d1263a5f0c957dda4508202a354162f600000000000000000000000000000000115686a37624ffa8272ec7dedb7a632ac568245918ed91be6c9116e0fde290c26b5291e5f57ba6a779750685b0f126ba000000000000000000000000000000001852662b92fb49b2f0359255db8a7a2d20bd37705b7994cef1eb8e318aed70fc37bb7af9fc0c32ab3efa8c0afad640570000000000000000000000000000000017a691c08724ccf0e668f2f4eeda692e9ac21385fea243dc62c37ca73421eaf51c3a60771da3fb3e3cb578de37d2d45d38573db9346a3c8de41af54048cc51a0edcb86f36372859d0d794f7560c8525b0000000000000000000000000000000006fe4276e8f2e23127853eb929ee4e0c6ec4a190d46ac222dceb995c2e1d8fc9f822806a877e6cf87cf579cb2862c25c00000000000000000000000000000000044dc671bcd516cf03ad98ccc55266688856a4e4e5a59d6a6bb93e9ca77c596b5ecd2db6f3cc6377a0086c53ceed5487000000000000000000000000000000000c3ca83688d20519423b2b5547afcccbfaaa088a90523272c7cdc9a9b0397340350f2a5ced2a8153d69c81cd79732bce00000000000000000000000000000000069916c468f22bad174522d7fb94b4b7d2a664743b4689daa5423f470014152387a29425642b50f9e50fb679ddafdafa02257ed12262d00e78bde574a9ebd2664484a446c03fe8cbb855bf92e56bc1630000000000000000000000000000000001fd452b8685b0806545e09783947551bc5f6446c9d15d079a8968a448a6fd6f8b7e91974b71a4b2c50954be299c4885000000000000000000000000000000000f28bdab0b0fd3e05d08ee2c51f1bc0d30380e3a7aa18d6e04b47018d6a8d2b35a8f06df3866ccb95ffbd9c5333ca94c00000000000000000000000000000000035f3aa1cff72df0bb10f1a6f8414aa2ad0289cd15f56d84061a7cc70562f1f12304c402c388e48dd3f34082aaf79eef00000000000000000000000000000000034730e3ad7a3373b97279a00dc7a053aadd088557e0da61b9aa132c5b402fd9aef73cc45dc1cb7f2076cb2ff27ae2fc76b9d21a3da0359a377c11a6d0a18bce7ea81d4128dc1e7618e6c35b9149d5c80000000000000000000000000000000009c91d800cb1d52501520b3625dd4c20173684bad8742c7ac4b35c0ce028556b6529de5cb7541e3c146b13f58ccae57800000000000000000000000000000000124259d345bf2f8c16215be4b6b7922f4e2d6b32f91c4b1c4f1d4974918fa9e6fcf10e46f0c0b55e2a7210d1a5336eed00000000000000000000000000000000072e6231244ed14aa0f5de06e2f953371995a567684b00e459113380c1434a8faaab8b28a0280336ae35bf1f90f1d4d10000000000000000000000000000000010289a63e0e5f1f35b7af22137e117a85df27874ba15df39b7c26801c169667a3afe9a14663d7ac0c2956f4eb70cf11fc9cd895d5d1ae0ae704e240c10d8ed4a01b319598d7885f7c3fffcd9b491f5fd000000000000000000000000000000000d0f22a9bcda47ffcd034618c15daebad8160f9ab6b3148f1cacb32e713df2ef19f706f14131f8ab1181b7ef7598e3e4000000000000000000000000000000001680314cd79fec583c8bc0842e1750b1318f94aa7700c6662aabd4c592ca61ad51a6876b686ac3fe3f508cb40192c31c000000000000000000000000000000000a172bd8e49637fd9eb611b590c68bda707931e403db35cde1c10bb74c389ed725aab54dcd7048285352c56c8bc5fd920000000000000000000000000000000012589683ff3f85ecb006c5c435ca7bfd9d5a6fd06eb625bcbcb18577cdef610d912e783f3986c965710269b1ff79ba972467604875028997efdf5139180a8d530a1e9f18c62ddac7753cc370bf25254b0000000000000000000000000000000009720c2b3a0658a4aba8e76e196a558bd155ff550b3e41bb5b43e7c5946bad803b1de64e342956a11627e7f24f69fef7000000000000000000000000000000000decf2262e8369d6a2b1ce07fdd257abe1c7610084ae2f347640c0cdb98c7cfa732dc609c18b7b6a51b47ebe4b07a586000000000000000000000000000000000e8a0158702ff6d6c3a7ed9fbc774bc329681130840d86ca3f26cf6642cb49e5f14ad95fff1c94151457b1d5a142bb5900000000000000000000000000000000035ae66137629e95539e09ee99b001d5b9a6ede79727d7deedcbeb5acf081cd05ad469ab06c265a5224fd5236db160b62f47637b64d28fb4facc31d5bed34b22e7b270431f54a689cd0fabd205e001ae000000000000000000000000000000000413d82d0b02ca706f0266051445c04f3ac594ad82e2f1fb4e8e0cf23a6c1087c29383238ad3677f170e99259e2fe93e00000000000000000000000000000000070af21f84895c0193f0b8174cb20b11f45c845a8d782b1f58182b149362e1368ba076ba702185fc54b5da94c3172f5500000000000000000000000000000000182e124ca29d66f9f6c370f6065f60928b6a8f445a74800d59209219add6cab0d1b79702c31d60e61cf56874a4eb6717000000000000000000000000000000000b94b733f76067a102cce9659292f31f3df2cf2770e3a83c1524536e29d0a84ea5c4883cb4e849830384dc7e157d8715474c3ac61d4fbece967fbd0599c9a92c3fe0e53899861f044308b0ea8df137880000000000000000000000000000000004b2feedd5badbbdff6fd0f33a4bee17b38cc8967fc72206246c349e1017ed0407fe08e0cd9208fa9e4e21eca4cfbc2a000000000000000000000000000000000df0d74d5cc17ea94457c0ee26ef24071700a0fd6bfc762e3ec69b8f1c096887f679e312f07cce8340686eb2716c9a96000000000000000000000000000000001878edbfff2efc5af64aa9a23589a52d63749b7ab2970f256874fe0cc15091c4511050b0a243d421dc6536f19b5977cb0000000000000000000000000000000015951da3b20494a266e4d014d0ec70fef4586c8656baf536a0ea9a48dfa041624e8154989a2fb106189217ca979ddbe8eaf9da65e0e1752a982601e9a070a7cc77d5007eb641fffbb78d2a1b02dcffec000000000000000000000000000000000657fdf40c829719db134acd6c2a9ff904681b1869f28512cbe2a64d93e5b62114a73bdc5260ad9a1f24a3ff191b7a3e0000000000000000000000000000000004e77bf63eb9c4741028dffd0591b4f525d533b455d35e51cd86c7884d63419a162b145752bde188d2a622251c087f870000000000000000000000000000000016cf02af01fa6750b4d862f0cdd5a87a79da7c3fbedb0fa356ef2e7419e25b3a2bc8cbfa97463d463d0ab349efaa3f2b000000000000000000000000000000000ea4468fe6a85d36ae990d0ba959ae050756805c4c769c829de475a2990ef1c46de20d5b466543978faae0f6045023e85158bfe535fbc342e31f32ab4723c0d9fe95a2c64cc4e59bd41d13a08ac811780000000000000000000000000000000018d42a2df8ca475be6bdc468a82c313599239b974ec3d27e8b8c534aa4d6b85d4ee9aceb15c38b3bade2bb1706a2c2cc000000000000000000000000000000000124d5dc60527faf48f5e9574308f8a328b410de1cb49f2cc6f76b8a1f2707f2d1a94bcbca0a97bc38f24545a8013b250000000000000000000000000000000018b690b3d1e3b22946a91ace004e1d8f92eb5beb284eb05b52ac5ba003d7bc387540d33d088a02711522e3aef7f74f4300000000000000000000000000000000103080d8bb379d961da06bc4c148cb5b056ae115b3a0e33f0a8c99a7fb7b7ceda35d3902e0733156d354dd0240e4bcabd66f5a8f37a7c6a32088897abfaf5a98bd4722c411bf4b52f0f5b5648e89df29000000000000000000000000000000000f4d068354cb5b51e5a86163978386533f8f9b6e388c5e75f7d9ff5e1ab6d1637717d251f2b723b7d683e26a274d610c00000000000000000000000000000000001ec5a0d408c55f247d62ffef172ef26e45c41029f1d04e36f0dbb4fe8af414b0f7fe7ec0cfda66a2855b58592486fc0000000000000000000000000000000000cb1b68045076f457746621cd415d743701bf3ecae8d52dd5582c3e0bfb38e6cf2651a5ebdf521afb1ec5b8066444210000000000000000000000000000000010f5672f813470378fa806abdff90edeb0239b00d85ff23a3fc6798779f46d6b43071d66f7742897a4e53ebf6c7dae719acdd24190589ae7823a42e8b59598eca12bf13b97aa9a0eec17f5f79a01e8df000000000000000000000000000000001422fbaf1bc2908be5900968af61ffa7b3af46e7250e4663ff321f42e2db057bcfb2106c433a9eef8fe20f7138b71d280000000000000000000000000000000002176e68cdb0ada2d7baea437bec8754ea293d14afb85a811f7a5d740d645a53e511b5605445b110174ceb5e6720e736000000000000000000000000000000000a69e992b6f4f7eaad2682cf9ac2e58faee9b3341e852543c2aafbff390ae067a641b2b5693319618fde413fdc64d6c10000000000000000000000000000000009440317af8f5c753b5de4648b06212256a39b7fb03678f1913b0a3d402a50e74e2da5d29c211cdf0b292c132759c36d0291be87a213b0a24c92df5ce42381ca378dc4b9aeb4cb9b6918263bea827bf8",
+ "Expected": "000000000000000000000000000000000fa31d16d9625200c13a415fd61b7552646c62fb8db307e92c1ac3d2acc92336765a1db42407ab0f774ccf01291b9ee800000000000000000000000000000000156a77678873dcbe4832b9fc7f516eabc1a10f4a6576cfb15765cdf999a771a6a6d41021897dd783e9beb2db722a6fa2000000000000000000000000000000000ee4599a6ca9642cb4cf38f5f2af23271cc8c5bc6e2cf6bad572b618bff9f8677837104b93ca8942843fd5db5c30dcdf00000000000000000000000000000000138986714a4053618e66a85835d105f4aa2ef38ad18e34b2ee7ae30a4282f7e543c80c94bd12c244506e7fcba25f4c1b",
+ "Name": "matter_g2_multiexp_72",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000083c515ef8509b12ab85ad7d0a816d986bcdefc14778efcb3bf7c2ab61991849f279ae6a9f5342880837c0d0f4a4eba700000000000000000000000000000000020cf5196b5d567fc429cb9ced7b55e4925e18c914caae216a736886a8d886c4bdf6d704bbd0ceebdc1975ef530c665a000000000000000000000000000000000f3d0a217c224434604d63cef559eed3864d2da62ac00d49fab8c2c6e22c688496adc30c8d591e21bc0be404b62083c20000000000000000000000000000000003d0bf7f25bab0bf2c768b44e10a6022650f7d5b7d568d502b9d0b28209ee69b1d952ed848572d3e966e8771c20becc4b14c6a38cc998df3583228080ea10f215a6e6a4b02ddb6d43e8f459d494a1ec1000000000000000000000000000000000cc4c4b7eb7e358d4133b65e635fc13b8a92229706a6dc5867171a60a99a8e343045a794c368f1133ae6cd2788c3a7db0000000000000000000000000000000019508aa39fda9c3efced287d2571db97045f8b7b0c7a9c9d51796aa8017fc0e5abb8fc994700dd5c9f755edb518e096600000000000000000000000000000000049f68b0ac142715cfb385161ee70e453f0e24e2e93f3f96c3d69447f3a28b180fe76989427b2e392c7ff939011e04ab0000000000000000000000000000000004903c0f8e0757dfd3f5edb4f54a0e292df15ff70757df7b0b04c99f590a3dd13c6ce7bbabf3e14daf9f3ec60e2379aafee8614394c8109338432ec72f2d9babba06f1e7b826b0f2558c3247c923b23500000000000000000000000000000000041128064ac768664f076116247e0f8a00adaaa824cd6fff33bf524d0c76e61203408ac13b294aa41f5c462cd42d3cec0000000000000000000000000000000005e150c27979ff1cbe307511816be900648957624caed1f08d88347061cd783179c615258fcf3619bc4bfa53d2513c610000000000000000000000000000000009d2b3d97d29386b93d7af014ea8f1cfe2c1db5a9aa0c17e8430b0fcde974a4e7b8b42ef041e9a7b1a8aecb97cefb52e000000000000000000000000000000000d86096ebd88b2cdaf5cda1e9ca6b7f12ed5def629354b0570eb084bc7139cf20bb8ebe4438f87937b8b554e2201344c28728d06cd90050e44a827b44f14ea35e83c9b58ce4c3a7a45aed6f31c94fb960000000000000000000000000000000018d677cd67e96b10b671d2ed9234d7708042ddfe6fb804d2e9371a80ad167004f9d6b92d26b3d3af34ab7caa0e03964e000000000000000000000000000000000e34a6c85187d328eb33c2d5b2ca96b5210d47a779ab810dcc380dcb7e6b3c334ac8fccd7354aa9108136e4f6dd4ea0a0000000000000000000000000000000000ab8f7274ee3fce1511c58661625c766ffb0ac68bdb835a948b09b7510bb573d49000000e3d3cea772bd71d79681e1800000000000000000000000000000000135ca42f2103905748a1c416d82170f7d24b49ff3f859d6cb7493cf89bbae0217529a9edc835be1f9890ce105877af630fda665c40d1da93b1f132070e0b7c8c2c0ea0e66993b5a3d7419a33d118d25f0000000000000000000000000000000007884edaacca499491580c8c7194c0d60ac6eba95f7a81f63742451c8ed21a223ca545d5cc1e648b9d2dd05016b4fea20000000000000000000000000000000014c78d5d1a93760096bf6da73bb41631e94d6a1b251ed0be7bda93e4c50568420bd4d49e4a46e5be4bb204cdb6b0ad5000000000000000000000000000000000128a860c23a183c5bdd18b4a1853cb53475f1a893420bdf3271cc4a65a827eba6b92e1f9e8ac0d10c73edec5160c640b000000000000000000000000000000000ac14b2170042ee6561c34f77fca40e1bd2d40d01798417dd954905135ed9b7772e5689e6d4e543d44a4563da8c3ca40c14f014117a74f21e0b698a257ae8e3d6091ba76bff7912abb6bd94d41886d0500000000000000000000000000000000144df2e76821c19167f60630f50c939b66867a82c2a5f807e943676c876aeaa2aef2126bef7fc431f0c7b39e648542fe0000000000000000000000000000000005e463627bb2d22c25520c27c05cdc75e1f2ee3b91e8088399ee42ad13ca217284596e5404b4370995f71fdbf1c1c7860000000000000000000000000000000012323010d6aba1bc6b1d6e7f7e8c7bbc0838564b279d5ae6279f7f7d3cb5d96273e27e7096e9a8540463ad16deb3780e0000000000000000000000000000000019102ac6bb33bd1c5a158a584ce32308b6ee5679dd6d2acdcfa4b9c54674fecad7489d1e39c05b1ded88e4ea93620724d81a1239ad2c945f1c560fd1674ac7e87d49aa41a1f4a5bfffeab1147c0ef7c6000000000000000000000000000000000faf210330693663c8a1d1fef78e211ed2542f7ffeddca3e19be3ba77ef211da1b8bb5abcfc96b692d74f8c7df40b0ce00000000000000000000000000000000134153a252fd8ec5d9aec08ba09a94c4416f95ff6f4ccce59bd400474c836af5bfd941f03384ca4bd5c56fbe81d96ea2000000000000000000000000000000000b4532ff1ceab2a3a177cb83a75c16a833a2ff28df447def351134ec4fcd608b2b75b1f8035ba7d40a737087f3e8c1c100000000000000000000000000000000127e3ed13384b69819b34ef8705fe9a66dd01b275f1f74c2c724420546b39c70cb7a8295a6c1ec4075ead4e3312b8b603a02689cfd2c353fc1b4d3913f5a43745fffe6a87a7c223ec3b25b321584a75c000000000000000000000000000000001351d0d5d531a63a5f56aaf1d7906b7ad2bfb4e9d823e2659bed4e05e7edc9179a7bbf13405ab5cf410b25c7d476c342000000000000000000000000000000000f0ec96128e058e8bfb6e0df1331887245dee87c4f9721fc7f1d20c20a2feea7a7078a4946803ac093477707598d59b70000000000000000000000000000000009399034e4aed13cbf197d8c4753285effa72fc53493ca316db11b39d5527b009aec6350d579f9dee22cd6d4cabd88ad000000000000000000000000000000000002f41ed0dcfa2437cad7b12a94501266d670ed6956196c438241aeb90474d17214eec5d5217090d28892d95f4e40055af95ab3fd062088ffbef6ed887fd39aa1d527fe7633b876187ae12e736fcf2f000000000000000000000000000000000ae208978a751f8921c6067ebab4190ac8d3608dbdf50222eec59460095b8ab2abadd97616c240edd0a9c53dd006e38c000000000000000000000000000000000905224b317a1e64d8af075b6db9de46ca4481458ad6bceaf726ba0f63e81e2a0322e79e70a5a82034abf00d47fccc300000000000000000000000000000000007173c3359f0c2e315d11d646a76e6f500c0922401e4bf9f4ccf2f0801a567fa653f287fdbfb878ba0d9ee12e25396ef000000000000000000000000000000000161d4cc71621e5df13d121c77105af195c2adff5fc6b656b0fc1dd6eb2518f474444d8bc526ae16387f23a4ab3f342f6541c6cf8217c2a95792900e8fc39581b177a57ca00162c57131ea4fb80a4c60000000000000000000000000000000000266af9991c393d3b55f9e0f22b0967d47dbc5b0c97947125e220c4bf9f4bc58d32ebc7bfb02b2e329c933ce41d0d8c00000000000000000000000000000000004cf5748aae8dbc1e4778dc85da575de2b6d9d346f5dc5ccbfd82513166384111f5e5f2f1c2f7ae367a22146d1fac027000000000000000000000000000000000095dbe68521b2cf51283a8cfea1f20eb7ae37e6e945c5f879ba4834d20918b74981f9e0eff4543a79ff4eb36d84a9c60000000000000000000000000000000007953cad14379ffd4309cef1ed6a2dbb73a93db0bd3a256753402e525bb62b10aaf22b662bb2c704865690af995e7d284b7c3f3c4ed10bced85f36fd6dac2646c65d3c810e6d2d116c38aa5e10b29c2d0000000000000000000000000000000010e99f318111baeb1b4611847fdaea7cbd5e3ae532af667ad2498fb2e97b1eee0297e2811c7ae854b882f616da7733fd000000000000000000000000000000000e56cea75b4c4e4c669a492a6723fd60e351a66dc5c34c46469dc36cb04d2c23cfd4aeaa23d0e9e83d5b78a1b77696ed0000000000000000000000000000000018f838d6a582a52a508cbd6bbbb9cf515e091deb7a640e141dea4018af6593c001dc43a8fe4819a7877d9ecf53d5752000000000000000000000000000000000119aaa2ebcdb6379f7ae972cb709990a3e8254f1025cef308281bf7057295e3099d1f3127f76bd2f9ce0a03ae0de8e8d7e33f394e96d17efa30d34f57eecc45d7b4ca150a31b8d0484578151d6e65c2b0000000000000000000000000000000008f837c478e874b857f1c939a26a02e13061d50728c10939ffcf5e862cb177993e204590699a28cabc7593056617d433000000000000000000000000000000000432d9e66dc78bb58ab98771e7e8b5fe51835f286b488e2df6c1991fd36c3c537f2ce30abf24f9d4fb13941189972e39000000000000000000000000000000000b202de3708984f44f7d05ccd9e574a2a93a285d5ca262017346580be273c58f13165437dc90d1d4103d3b9eaac536ce000000000000000000000000000000001873e1251d9ae9448de8e7ccb7ca59a21bcc0d07a2819d140c06ec33cbba559ba90647494a7ecdec8b609b58cf7995cbfde92a31e571ec03e509ac8a70ed5788869854eef0bf578efe6c5e6468315553000000000000000000000000000000000084e07b6576c73aaf43c0ef9c5666dc988ed93d1a106b71e4882fc0cfb5e710b91e5d5eff57327f5678f662f4a451d50000000000000000000000000000000008a29751f1653236a48adb5fbc59059c7137d36139574c6af97314bfbcc22f77a4c5162092762a26b5da7887b94f2da6000000000000000000000000000000000a4fd84c4d58cb9e18aeee180fb05f07c3e1d7ed8d09940182e9b4738744fa6faf600b6f720441e0ad6391a4d502ac040000000000000000000000000000000018b356be2aebca82c54988ab2a2ec58751ce7a815f3dd58a2218a638753d4734d38b74ca0e00bbc8681768f5d1a02b646f7de01ad0f7b4dcaee1123bb80a71d3bc1e63ca577a12b14ae2a11d8c0fde46000000000000000000000000000000000de0f22cf05620a5d4bdcf50ae179f23a9c089fd6eaeb14eca937d9e2480f1782a1c67df76e06191a9b87514daa8bbce000000000000000000000000000000001981cd1f260e7d96e55533b8e29867f37af507b4a58abd69e0ad6af2a55228ab1c82fc2de52deb7b7b7deae2fe621e10000000000000000000000000000000000d22a7a567ec8826391ee711768e612c403e3c16e20947ca5861185c24728b6c7e7756debb333e7acb53d86032d5748900000000000000000000000000000000016fad52e1e86b9e092955cefdf93a10f30db896fb519fd2ca12571d8dc8aa352cf4f8092e0e973d0b0c66df78433251e2c69d21d40813ee40a718f0ead36b51f3a50e9e4e4b2de8acd33add62bfc1d20000000000000000000000000000000000484bb2452158bca93dfeeedb40745bc5d9a9ad49afa20e6c29fc9ed1a8fde33ce508cc252ddd05fc486f8ef78738ac0000000000000000000000000000000003c2d6ff6f292b0f0e505fdfdd2940e72bf8c2837da4ec9c74fb593fe3318a9b9a8592524bb5d40f6c38ad871ab7b6150000000000000000000000000000000015f888ae2722713e1b5b02803a5b48d53116c1a4bb1191c9da77ded8c6ab49f1620b0f7c7867957d84503cfd3dca1be7000000000000000000000000000000000fd96baa382cceadc252eaf000d47d8c1e2085e9f274dd9dbb571bf85bba612836e1da2453fd914135842e2750796b54762d89025196aec4f87da2fcc5a9188b4dc7b1c014dd1d705223bf9fe1e7a7d1000000000000000000000000000000001820de289f62058920ac3d4bc60da023ac29c431ee429a10066f305d2b1a333ffaa906404af977cfd3212b53e66726b500000000000000000000000000000000094e448db84421e25cd03be3867125cedc7f77f286f404524757f3c1a9cfa28ab6771293da490a4d75852f515dfe1a6700000000000000000000000000000000097dec124970bc63d8f62f9133157d412f5ad3fd5eebb444568cf0fe2825d6ef6577ad302842f35570c9977638c6a827000000000000000000000000000000000490bdaabf4db27dce906cfacf3160c0fe25959df4af89301cbe6eeb29f72e4c55bb467841ba7d0750a59a32fc8b03d0ffb9f3e1d43aece3af1f59319a8228cd81e668b1e250d03350958dcac9e23843",
+ "Expected": "00000000000000000000000000000000193358b283147ed5848559d4d1533734822b0248dd17b2effa80920a853b70e7fb683b08aad6ad4dbb91f964ad1b3bb6000000000000000000000000000000000649be60ba72734db4cc307a2fd8be57857f60660d0c496c0dad73794296552e17cb2eabb3537ce677edaac1c6997341000000000000000000000000000000000f91ce27345e86003c99d133eca50710c0722cb35af2ce442ebd74b46d659e0118be9bebf32111c258e4cb4ab795a2cf000000000000000000000000000000000d76ad65233522b1e079fcfef4dfa80f163682d7984d5062680a5dd4cbccd5044de4705013c6bce2140f7950032f90ec",
+ "Name": "matter_g2_multiexp_73",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013fe4afb94d08ae311b7442de7291a11e733d8e555f2da6f72bf99da780a8f8d357cbf3d8959f6aeaca7bf3f5b5bd10500000000000000000000000000000000025af713b18cbdb5a960371c2dd0317f4bfd0182f4bfd6b88d588b56fadc1a0398412e7e0a786c326aca8779ae384243000000000000000000000000000000000581c277053c15df8eec05c34267f62e63faeefa2d124c2b4b84d2a739ce5484641ce955fbecb901d1e8ca816690189b0000000000000000000000000000000005355dd304b9b60498a3fb1f08e1ba0c98db327365ca9a0365a7f1e5cb56aec43b7fd2b4aa104eac7b1c30b6f53cd422be285a119dc8cb32b1a0c5380af736114a32e9d1ca870abdf278dfa84444f70e0000000000000000000000000000000016b5b3a6fdeffe5b9a0244a333ada4444a2e03771f94433832a4617be696e467b4e88ed80b174809dde4242bbb51248b0000000000000000000000000000000003dee846c5b84f89734016e547c63c02e4be07dbbecc86f811e2d8d3245f91205bfc055882565371db532240da1a845900000000000000000000000000000000194d53bbfa962def4da2a9bc7129fb6242a3922fe26cc4e603528ff31393a31d03dfc3463704250ea2ffa973ad175153000000000000000000000000000000000333768faee332d7468119b9e0469bbc7bc98a482562ff2fd9aeb6d9c67daac9c3da1db41c9e12224a2eff2feee51778bc0535bd504d7b9658e459c2e79b86bf4e718baa82b8d6e624fba0eb141c7260000000000000000000000000000000001910ded86d79f9b043bb79cc4049e0652c13d0fb8db2f070d695124d7a42cc3a2238282fc8a424fcd8d9ecdab4bb6fad000000000000000000000000000000000dc8d6caf97416928d2d58466219f054c6f28f49b2bc04d8a80cd46a308bc95aaca3a8df1914ab0c7da341862fdf47400000000000000000000000000000000004380ca7b1f7ef96295589f78a1683a51bce4b2afe50bd6076ccf5d07d35e6cb2ec7f74fa35097b2c0b9fff3f4797c1100000000000000000000000000000000054f492d7442b1c0d1293277d95efe822faa7d8881b9afde20db58d6267e049b90d0c8828a6c12540f4ba1e7c9ace6d84f3fa09243c01748954d84f4deeb460f3ef78f9c34296c6a092952bc463d7284000000000000000000000000000000000bba4761eda87a304a80180c2447a1d5a52f743015ea7c728e70d6a5defe3139c80696f842da3f06586be8d506ca4bc90000000000000000000000000000000019ea930d5733f4a1ace9fa0139d412d65b2886b659770e388894592de0694d38876fcd86d14580f9b92518d5496fd44c0000000000000000000000000000000002bf5d9a36d641d1259c1b30397aeb071b88844c4cf17e3de0984129d7b4d67865157ee2f682e7cf9d968fc07ce43618000000000000000000000000000000000f9a4f29868654abafc7ba935aa22d3d010023ef5112683a037a6c69b9e89374b256b8e1329eb5ad306d9f2063c22c335d84733ccc41f71a11d61852fa336df566109c5538c2c5f5cf2af961e93797fd00000000000000000000000000000000004f194f21373f09f8cb4984169890ad3855e814a4768c84e9fc97dfc181c60114aae534a27d3eb225b2125131c754ee000000000000000000000000000000000e6f88880e9645e35806d193f5d16799d63e2f9edd8ae28df54d19875c61857b0a34819a70ba3e9c31f00b5826b0cdc200000000000000000000000000000000193293c6cfae9ae4b24519fb23469e2f8dc4eda8524ee0b00c7141587b07c8a26a29841d41cafbd24bfbea2034a9c18e0000000000000000000000000000000017433efadfe9873dea9a68177af3d5dec4a13dcf4a710422d52020d4d145e2523ec0b48acc533a1ac7068c08ae6aa28bfeeb95c32362014caedf2a9e066a775e2db0d1322edc86759faa99bd70c05b580000000000000000000000000000000011dc003f7542f6822cb872117fa658638dee2a15429aaa9dd576a7e895bc0a2160bc120558a32aab9e646354233a1afd000000000000000000000000000000000fe9ed8ba572ef7d1176176a31fa92a5ff3dc38b0183ea1e22618e3b3214ee78c53074d4c60b5056901c6f046f8210070000000000000000000000000000000006ef1c20c3bd88bd6787598dcfca52da4e5e0e7c7643af983c709b916e71fd15475da30d763ddba0899b182cbc070ca20000000000000000000000000000000001a38a2e54a44ade572ecde076038f5244f266cd99532024a377829a64c20fb2cfe1633367c74b5990febb08e776bc34edee2ea28b93b2daf4ff927991769a9c69ba16490b5676074e64f5e91fa994a60000000000000000000000000000000011ce7b2cba037e5f3ff19b36371d34e287eec807178dad4118c6d43aba68623e182aedbf911a2ae5cf3d0e690ec3ba790000000000000000000000000000000017a617453f391e6e2437d56ee831ba895084f60d1a5f342e19a242b9661c703219d90a157e1b55f005f5059c15c179dd000000000000000000000000000000000746ab134c7f4bc19583a4ea4991c7cec3f651a60582b40c17b2d18cf6e252d93d2f3c2a1a3399be70512ec9eab251de000000000000000000000000000000000698daf214f2de44ebfaa36379862bd9ffb40987dfc8e632f14738c93c8e5c3fc7be9fa9100fb5f7440311cab34fe1897a07e50c1fbf1b388e9264c762798c31fe76761508d070f06adc63130df07641000000000000000000000000000000000e4ac65ce62180ac602ad68098ee31cb747886e95a183e4f819d54af99850d70496e6952076084dc7bc2d3f7a273383100000000000000000000000000000000182c718fc9e5cc961426258e82594a5cafc36270af0eb50646d161fcc192c30d40d06647e14a282421638b31f378de940000000000000000000000000000000002bf448ebd27cb6270e1b87087796ca6534ff51ba0962f3290ee1d06dc18ed39fb736ec95632b483f44d3a9d0e45d1d50000000000000000000000000000000018b956acc1300e60b22bb936b2b52e2ae82e256f15f1415263157965179855137715c321d3765c5227dacb63ba2d6225f0056903b4508cffb6334bb5f645cb553a8cc61ea6765283f933686f172f8360000000000000000000000000000000000f5372651ffb40bf853f6f8396a7c7483c401b89b67e098ea888fde8d19e7552a006a127af1f3311203434126ffad85800000000000000000000000000000000050d7e89b21c7484cc5831885422fe7aa8e898df85cf7a3a275370623eb9660611610cdb829d3935f0d0955e0ac97506000000000000000000000000000000000f83a3f79f1dd110bdb8521e18a64490d567210801d77fa3c0c6e5cbc7285840da325cab7ab08494c8d516511eb189dd000000000000000000000000000000000f72904131be66380c5a18af4857ada7c15e88572197e100de1cfcc9fdb4306e446f2f330fefcccb41b676f24e3e0bf88031f363c8b0062b34d48f4c2e5bdba884005e52f77ac04c2f29dc7ef10fac0c0000000000000000000000000000000009ba6bbf102d390638ceb9259205a1856def2b3a4b5209eb3e4e54074347f71b6c06b70764fe85c8dfc9074067b8d00d000000000000000000000000000000000339c30631229eabc1230240942bdbcfa6e18f23bfbf88b7b8a8fa92f18e35d2f7336f0b819e875ac643b43e6d931e68000000000000000000000000000000000600cfeda6033ff51c3bf9182d22abbfbeb6db46c0fbe15ba82e72fee483744ba5a57ab2eab6f35927b4ba6d2b150063000000000000000000000000000000001530bba4db8a60bb6b7a05f72dbcd23044011d75221d114b839aaa9535400874472f94c849597174322291b5cfec4974cb146e27a9d36dc698e1982afc945af9500fc5aeba719d06d0c4e4eb245034c6000000000000000000000000000000000c636ac98557e22897fd101dc6c54d87060f460b4cf2c5a88ea14641e2a8a9395492fc5a946eebbba36dbe38f6f5c0c60000000000000000000000000000000007fe3a557aa93f2e9aef4ffc55d39a9172475e6595fd57409df3a7fe3d11558c4d3dea3396ee62f61190add83b85813d0000000000000000000000000000000015b04e0daf4a10541623e7523ac5fbe57dfff9ac17afaf4293c493c1982f3395980ec63046cb1d424c6dec91899202c10000000000000000000000000000000019617b191e9e493751b0a02511a18757330bde56722a72a29a399ace983db7114f84795e2b70bc9d670cc0095220454ed983f98fe5112a55c23591bf4e259d072f893944741d9941a00f907749e3c9990000000000000000000000000000000017472b8c1cb3ec528400649fe7c39e3908b16ed69b42d967e4d225b694544e8bc7ce5bec87019db5539f1de39dc6807a0000000000000000000000000000000012b1c4884c37037a94f84c15061df5ca6c05c5a35ad9b37e3ab8e8297c9000e715fd2bdc3f2b485e86c415bf656392a10000000000000000000000000000000002c21af2933029f04b344be76e18ce499def4a0671a97dd9b6a108d0fb23852fcdc56f882be0319978952ef04a207a6a0000000000000000000000000000000015eb31e80fb162d5fa392fada8d43648ef54d4f9ebcb0e9652dd501f55a8875a16a148d42e283ea8bb2c5a38bfcc8843a62f99ac46f986f2f29f0ad3da0310f061e691955c711850a2816ad7464614a70000000000000000000000000000000015e68e011ed063a9fd9cc8a806d8e3561e4f449526ccb6e5ce983ebc4fc49d61d26dad7db64f56ad5ab0b54fbdb76e61000000000000000000000000000000001617d7387fedcdd772a34b267a44315212d21b798c0fe1e7a9ed3caafb678910d9c9c3bd1fff4a3c8e339d0c90a865b8000000000000000000000000000000000e2b3c9b9cc10f41c4c0129d34c62d526aea47c77ded91a5ca3afa0da1801bba81def3ca66a978ebb2d1f3227ea82a9700000000000000000000000000000000096b6caf7b6f29e91bea370f91c2576c188b08b95f9df6c7df995fc9879c11cdbe2af86809468d472fcac8a89716d1d87ee01b0c9c6a6ca1fdac35d89c803bee3595f03d9d200affc5292d8a7c6720b80000000000000000000000000000000016daa86ec04f57c72395d96b6ea5d6ba7cf2d9d4a50eb90f7121545f17c1ee16216f4086481d91e59fc5ed8542baeb7e0000000000000000000000000000000017a783d60be67206241e0bcad20e371d86d47d88ba1293b73f32999b0a1646967e5d031a5b28517f035168d7c7d7927800000000000000000000000000000000058f24fbe4e9befd8abe364c961f0ca4d9083260234a939bf6103a3e8f10a8381a9e3d74af7c13f159e5c7dcf456df00000000000000000000000000000000000485c9448fe3a069eb024ec43aaf563a98da09c02c294da2a94a98a95430e25b062e8ff886fb5fca240fba1abf7cee60297fc700698c56877be6764f48a836d210bb33e99b5735da9837882269af9b45000000000000000000000000000000001230577527a0fde2e8e66b8c4d17594bdab8be1339866819c8890c600b35889d1e3a749fe15fd8182001e30e6420ca6d000000000000000000000000000000000ce03cccfa87229fa8d560884d8c7963276d79ae9873a23d550b4555cc4bda35a242dd2e70cc730b70cdf898609b3d8400000000000000000000000000000000174aab1f142fbb7a45bcdffd64c2d38b99c8919baf9651aa430bcd39613d7565196c18f0f4ee6fe05f5c40ddbcd4a67a0000000000000000000000000000000011dd23f59ca2a033ee5dfa50afb0c7ddeaec6d4f50e1866cca3f061fa03594216f005bc65b2c97ed1109c305e16222671b7ac02db15cebb8af459290c35eb5a86cf98b86d8336764c6bdda6698b49b640000000000000000000000000000000014e1cdf4f10b11f47c15d0b6b7dfccb6081d05d116c8149989cce4f1c53dfcd2d0b7443677b03d037710eba813f6f597000000000000000000000000000000000c8415c7d5508010e0db1878ca663d359525b290b2f02c61436e945145a7a4e1b3ff4e27ea1b2c8d3adbe737d8291b14000000000000000000000000000000000e424ece68003cbfaf65a54dba51e7b0942cc53b2fa9794b4deb6aef1dc1ba1719cba285f9a1a59e71a881eebffe2eb9000000000000000000000000000000001404f9a3146b7201b09c5fd678fdbf2111c48130e82cc95012e5aec1df7e64a3b3c727afee4f603e620925686e126c0f5d1a3f78a2c2ab7b85cee68ee670f50a176e988a341303afb7722917f442fab6",
+ "Expected": "000000000000000000000000000000000e9f6bedba1f6e2a3ff33e0e4b18fbf8e77558bf42e89023df6338b03a648c591486c63c2ecc8ecbbce23b3ff9a7ae6e0000000000000000000000000000000013d2526d83b4495b5af645d5a1af7bd40bd0ebff125e0fa14f10d1c08511dc29643dcfbd25ca0bee5705a56b26c558730000000000000000000000000000000003fa442ab532094d47f1a9111c87deacb15d80ca6e76bfb5f9b9a209bfe196643351d778b0c6d6b274b4799f733abacf000000000000000000000000000000001278d51523d5d9aefc0d3783e745da54f74a88620f2161090a398defdebf82d13d5b5a21a5cd466352ab8685b034fa89",
+ "Name": "matter_g2_multiexp_74",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a497e74635fde8caaa5c9dfe666b1b40732e58b93a72d39c8a60c1f4b262e1f18f62229a30fb8257bf895352ac4d249000000000000000000000000000000000c1b2fcbd7f78d85c73ae55f67110b575750bec353e55761de0ff09a9f8a2d916c336655d8f6a78dfbae13fded5a9c36000000000000000000000000000000000173893333d998dd32cc3e82fd7ad8ce77003192ad2bfa1b1d2b43f9466898313276b922f9fbd8e83e86b67acfd9ad780000000000000000000000000000000004ed01b702bbafc73dc1e6846bc944be297ff08d1dfef397603294c7fe11668cd0670d386a8fa0f0f02c52d47f54a11b34aaf86eb77ce03f1d8eacab84d5ff98a565fd33a9a2c40f2a19d7c041a7e2a6000000000000000000000000000000000b5ec74a2150dcf5ebe09f39234c4dfec623318889d92b0bc1f197a69650bc48d28a1112306be763176b691c6915dc7c00000000000000000000000000000000028db19af73ffdd0111dabf9c7d6879cc7389320a249f108b41be8b1d4c259d5889dbcbb48b30a288e26cd9926682d1900000000000000000000000000000000172fe526c62f9cae49e6d3284170e6339d5af256441590cae9507c61f987eb495d340500cb761896163cb8ec631434690000000000000000000000000000000013bbfcf9cd3167b47b48af5f5ed7e6d45a5fa38192756c9e140eb89a85c75602814f767c57108cfa2f726e71f31548f808ab2065f1d2278caece0939cbbab4bcbe3eacdc80cfae6e4500a5195883de0000000000000000000000000000000000052d7a0f93142b36489cfa21d76c0eb96904a3ddd946a53b8a6730036d88d30336fd8aae3ab29ebf62a48c6e849ca66200000000000000000000000000000000198350abe8cc91bd675f26516d771422c128d5dc0af844c6c1af07bf04a1d3ad9654cbddf2de5b7828d1446c45e7828b00000000000000000000000000000000198f35692d5face8dda4b464ff48d650145242852fe189748783b1a2e48806294368ae0a99481bfe739fb4962f3b86a4000000000000000000000000000000000e3cf2e018a7e0acfee25bc3a82cb282cb377bbd72ce3044dd20e109d948f68720c27aea3d4663ee45b2de6f178a00ac58c69b55bac97a633f3ed7816e77e2a26cccc029f7e7429c86145ca4645eb41500000000000000000000000000000000150e6b03a3052d043da6514bf4ee09baf1a35b2a909473db33ea0bd4c6af7d7aee9a8366c1d08d2adc5998635eb0dfb0000000000000000000000000000000001370c2976b0d36fcb955e797087e6ccffc851d2450cd63833d6cbf52e1fccbbbbf9dc695ee45c7df01c2828051bcd79700000000000000000000000000000000048b5fad2fe0af7ccdf675328d8ff5e63b564d8436d04c55b23b6ab7d2aedbd25d614d1780963fcd03d569bed2085bae00000000000000000000000000000000141f94b4e7ba542707d0c3cb69f8dd79e499602952be2374cead840dc669c5ac57089c5fd60c44291703b872098fa2daae7faf23e841bd53683521cb3cf215577fa51f0f751714b6aafe5c740f66208c000000000000000000000000000000000eec51e0ddb8cf9914304e7766a7418e2854ca71367c1d2b3875c12b7dc5c7cc2fbc136037bb7ff72458027104ed3f270000000000000000000000000000000009fe5e8d1918f9b5865a8b97c2c2cfc8bd750a0ccbe2942070827a09d8e41ca795a86b2262b10462795f833c73e788ec000000000000000000000000000000000b95c9146f3f560ad880ca905b5f297e48905680b4613e91f393f72ddb042f6a6201628fb5f75fc23f2298cde66a6df5000000000000000000000000000000000a29a8fba7644ac96d77ee73a93dae23b03d81a57f6cd8cb4594b23571cc1f658f163081ae50d72e09c6513d1cd2c8bf72022cdd6d942158bad47a53a9b0c3be910a41036874975724a5cdd22c012871000000000000000000000000000000001807dd8d2bb40a642fef693739b1df12fc787db0f031306f31970d0f59f0c97c0894afc34b9a9913726a20dcb7d5191200000000000000000000000000000000096fe8bb5e911c1ed9985ac08d864c7020367f4259a0d074973a26cc421a44e8034a7007f6d1639285cf8acb8b2d64a60000000000000000000000000000000014026d43eceb26b9ab5bdd4139d4f94349b273e43f27737f9ad26d23454cdb1d35ea793d21f057359d28328a82d5290b0000000000000000000000000000000003dda2a84bd1f92524a8ede9f5e81f0f64b41b24510f4e0b8146496a776d5b509968f188c12c2d66cf755e5000cddb3b800ae0b956e38bc34cce55bb7e88f1370a30fc8ed0e3f1126c68c30792a2cabc00000000000000000000000000000000011246ad07713d1916c662679ab757c053e33def437d7a976533f0ce80ff6ffc259489c26524ea96898c3747c4127539000000000000000000000000000000000acf66265811a57e47a4c98b40b12a37c6f439550b18215fcf856c167b7218397d7d559f852fb45077945a5074f460be0000000000000000000000000000000009badf2799f1c43a2e3859123aca91e894f86d6298a06a9127249100ba270f2bdc79cf511691bf2d7faa45ffa17490eb00000000000000000000000000000000069438b1d53efcc4277ea7b41cbd28a19f80b5380136f62121e766bd2845e13d5cb40b2f15d508414876ddde491a3830a57c3322133d6ffac661c888995e7cb067ca1309f3e9178a266f1a410a79c01300000000000000000000000000000000112c4cc34da9e83207b5ea8a9251ac5f004546596f2294b3fd51b77ad8d8e98239d53ec4f527c7280801233175500b1b0000000000000000000000000000000011dd8627748c9a2b08524f88e560cd3944bfd1fa17e1d6e2e9cd025b04f2e3ed35125197136afa2848d24fb5fd19508900000000000000000000000000000000093219f9ffbfdaa60c5965b45a5d5bd923eb5d3971542ac147de3f591a5fbe31b30704a0061a524e2ddd05a45dfcb6a10000000000000000000000000000000006407dffb5580790e250a72dfe68a488431f61f45ec9df279217b8800f0ac1ab585d84e486487d5688735fe5aae75bacebe67f3d067b0d011abb31588d1b2fa9fdf8a56bc46b1a0196e926d4ec73040500000000000000000000000000000000107ede23f8e4f273ac2647fc251008905966dde32339c023f1da3c4d35d483a55b54f4157a303e68e1dd7fa3f3b14c8d000000000000000000000000000000001739327f282812fbcbeccb12e40df049284562d8986b8d4559787e1d5247eb6c83d6b838d099f36d8d0e32da2a7999a10000000000000000000000000000000005e5b6b2baede3ceae776da5adf075c1d774e83d6129ccfe7e835862686bb4064b187cc0be0cbfed37e5cc039f3a3fb6000000000000000000000000000000000249554dcfa53f73ef8f08daabf20c55301f75c8ce095cd794061c55e195221602a54ba54260980bcdb35685e41d0f4ffa1d6d0d1876a67337d66c596fbcd7eb22ee308e4a5f66cedff584f1441be6a700000000000000000000000000000000048b7fc5a71787231f1c7ed2134be528fc8d8f77102bda806ccbadf4f9bed79ee94b43c0fd3e5b1d776fe73d786872d1000000000000000000000000000000000152a1f005a64e16949d7249c3b391d5c1e0ded4893d0ce926cc666f0f88b64e8dd6ec4f92ddda18127ec24cad7e40b40000000000000000000000000000000013a2e1e7958a53307adf3beb32a88b7c493df0e37e074c9105da3c09bbaa01fed092fce2b1800790c6e8af3d30ec5a81000000000000000000000000000000000e2d405806764c75122c1b5e410673b28759f26af7489cfa6f35c6c0dd16c508af045009853f3329cda4a67948232bcef0c4ac919efdf3d0e649126da7f8ca3daa30b6ca6f3be6854c0f447a63cf2110000000000000000000000000000000000a71d61dbb3ae37230a2dceb54061d5f8c1ce645e20ec39785c229cf79aefe238959b2745e3b50e4b3c20c7a8e2ae27f0000000000000000000000000000000010e82b8dd5faed6bbd5755c4e5a88edbb3511d3f4442d1e44b82cf72a6414bf6558d29e8907b07f71c00f537637605bb000000000000000000000000000000000d8c93f1984b742b5a02777b706970215c7d8eeeb7377cc26c3af9005648c2eaea7f7a3177b6e049b132ef6bb4b188da0000000000000000000000000000000000ff082a252082499d70eaeba6d5514fc8d641404b48b2ecb256eeb40d9c6b68ad5af58556c9dcfc5667621c549b8ee760d8bf380bc2223efc779a747c0a36f8c2b18c3e821e96163bae14b18f3739f9000000000000000000000000000000000f4cf354b8de6dd2231448bb235af3c84daac2db49abed345da6ded50eae93982a4f2c27b07ce725a062b07fdd9058fe00000000000000000000000000000000076cf19408f0f0379c7e65a6675b9856782990986f5c6d7002e9c9c74b95ab875924bd7ad5e4812844f6d1f530e58deb0000000000000000000000000000000007acffe32f96f5e56557965e3db8dce87eb7140d93608cc003bf4a43fb261bb7360c576da0b7c4dccdbdd9cc53b5c5f8000000000000000000000000000000000eba1c668fd9323d42d6a82d9f075cec2d278cc57122e25ccd72cf8b5a569552cc6b0e9f88d23b9b7af18f3bfa0cc820006c3a7b5ae971e4b0ec34a1007a02cf8c55f067115ba00c5967f70a7dcef9d60000000000000000000000000000000006157cb6e2dfa2733d4c489ec0334f0303ff1ad410f329cb59f99a5fa3ed2cf84eb7d2f231078ba5db0954badb58425f0000000000000000000000000000000003dfee394f4c140e2cad61e8675b26f91244880d9a0b6798d6111090dc9d080563db5c89b7293dcaadc74ea5849a08aa0000000000000000000000000000000001aa1e0683014d5b6f99f469a0b7beefaf05a7ac0298bd1a3e2da409f6cf856f70bc067610fd705a851cd70054df9562000000000000000000000000000000001571b129f69f3a6717272ff75351fa053f46294f68ba3f859208d6c91ba5eb9a0f2133a5e139d04e38c7f7aa303451768f29e330b48230de23e0393bf1614cd26685cafb899db5a164497955d3e98be4000000000000000000000000000000000c4e84b7c8e46daea67c8090b27dc28b7867b89b92f56232bfd8ecd9968b865a057957292e79c6dc08162f9e91e6a4b2000000000000000000000000000000000b8d1eadcf3f1de6ee608a4a0ebb7defeeaf4e251bf07717a6a8e50c07223ca32a2ef290f26d0de14b1942e02acba39a000000000000000000000000000000000e901b546a4d3c68e4432f376c97f42ecf0724777956c4ffb1e6ca4fda562e57be788ecfa45ba3afadb439c2ea546ff30000000000000000000000000000000007ffe01da4fbda9fe5d47c3bedb4b92fdd71ad73fa272b071a7a7d1cdce7743a535da7dfe05a43d03368eb97fff54b2d861ffae8f62572938925593f7271a56e0f559b56bf97c454c38547a2185e2ce70000000000000000000000000000000008da0fe413e31ca68f84032f23bdd5399e01eb3b5ae47033c6834a39645d7b5cc2ec937067b91ac6d83035a86fa841f9000000000000000000000000000000000b950b982323f747782d9065dddca5332940058a604829e31560a6bf9b03ec72b09cfb87a1cd244ec694c7cf192c37ac000000000000000000000000000000000f4afddd25eac15d2248c71d76c9aa27323f75141820efeef1ab4f5003141053f138d9a7d1a901961d0f2c210ade27ed000000000000000000000000000000000217b1800c53d53459b00b8e463df1882b2cbafe85043f08093a5414e58ea7fd4dd933c601acfd7c154d0e4ce187468a2dd907071c2d39fe710215d174452459cc31d36007a1b5570a27ca2e42c8be55000000000000000000000000000000000046aed1acd19201553bb6a88fd6a6c0525ed44822d2a4ed3bca48a0a2b75e76cfcdced8f342b81ce03ffa72e667b3bf0000000000000000000000000000000009a5adbac43cca3402db016a2138342fae89285ab1fa16d7acaa9c3ee2b4e3df2641f7392355996bef7b1578ce1ef119000000000000000000000000000000000c8ebbcbdf2ac3fbb553a2e589f4b7c259a1621b83b14fd1927f92d9f6cb27e82507d7943ff5930f0c14b9fc38c9857900000000000000000000000000000000105b729f678db31d04ceae0aa37f9cb0b0319c4da9a1a4702a11bfe3a5f2f1f2af09b9cbd5ded5a930e2e65f4279a31699893c06db2dab559f2c374df4298707dc1815e55034dce920ae7b1df2ec8d23",
+ "Expected": "000000000000000000000000000000000708e9b926f2536731b02b6b75305c549da58e312d9c53701a993624697af2f3469af34dd4634467f8c98a0f721cd9c00000000000000000000000000000000019185b84fc0511a048e3c39bc10334c91dc1052d323a31c8bf325479a2fa3e4228f8260c0e725c2b89d5a0319e6fbed70000000000000000000000000000000013c7c441d5cca81b48d43e908d6a3bf8b5057cf19e4884227cefa9b235103b46edbe01bada06bb9b620ebbd016d537630000000000000000000000000000000000431182c8a1eed66073956fe5798a894be396403c072e766cdc262b719d1779f960f4aebf61c1bcd4d005d3c7413e52",
+ "Name": "matter_g2_multiexp_75",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000199f555aa5c651183f52470e36cde438422f41c9b2d1947510665254b74ba0bb9cdc6e6a1283b0c8f58d8f009eec46900000000000000000000000000000000018f1d8f22f43b4649300aa23ac92a2e8f17e7e3853b912bbc8e90588125c371084cb224c2d54dcecb4946ff6db53cd02000000000000000000000000000000000efed0bcc83a52f0faf9e260815da8d4e5286396081268485aab052a96af8eea0112be6cce1486b10b60551ad6c810780000000000000000000000000000000013a3b1ca3b9b7d50083c10d36997f5f521d4426af8d2905aa5d074ff37e218a0c96c74387485c2dae24c0842b7a74cf0d8555388bcc6791802ddb6c0f4cde44f45ac0b5d7ecd918bc34fb9fdedb65b94000000000000000000000000000000000efc5a5c506e94ad2754e235e2da866d9c46342f14d518f12510c93f13a619f6bfefec50c146d6d6170f190497eff229000000000000000000000000000000000fb91f34356005f38c9804250549554cfe67ce195d5e218e4e1b1a4fb904257bdb68d6dfb013e8e85fb5a4cbdbf0f21a000000000000000000000000000000000f09903db4c41fe3f11c6f0cdb7c31a131033e30f52cb66ba10c2e7da1ed8a225ef280d313630121701f9a490e8a0f5c0000000000000000000000000000000003484f7e8f7d67ce40b4cccef110bc255d91f61a4e1968a9ad37e25058eeaf39e9f1ff89c9b2e515388a7c1b49a84a2c33e5999498978d14c9de06f7beb2fd870f6f16dc42125fa496606e65c7466c0f000000000000000000000000000000000444215c3d4a7d62201ea1b69890e2ab90b5f5c6ff56fdc9908634c7489e785521b8dcd7ed409cf09c585cae8414a3250000000000000000000000000000000002d70674251a0c9ba76b8bf3b70547da77cde5592da9204954abd6d8aec82799cc0fa4fcd42139357043fc867b3d0e0d0000000000000000000000000000000018c57fafbad2351a3da695f8b523443e8c763dd7ab875caaa6a494a498cc40b1c0d44488e2dc80d1f0bce00a2c90c67000000000000000000000000000000000125d5a87ee3f558b5e1e7664b0cb95c195bcebd5e43b930fb47d15eee4fd50b3fdd0a401c9bb011c326acc77645440137894a51dcfe5a8fa4da1745a696c870b353fb03a31238b8744840a78084bde480000000000000000000000000000000018790123ce8b3b72d626493a16936c47770a9b06ca45b17c6fa5c7759f088cf98de8ce7b3b5d6082e9e42b39acf76f79000000000000000000000000000000000fea86cad8b40f315d8378550f6d3d831149339a8e8dafa77295859ddd2417e8f5c0ae2baad25fcfe00de14f45a537170000000000000000000000000000000014ad78bb2bce966d52b1fe1a273bc07f2f24b354465edef6dbb1e0123c7c3d7550983b3793ff1c7db846e88eddbf33c4000000000000000000000000000000000c0daa6fba40ec59f6b34d413130df5d9137297d1b7b71b83114a6570fef8e7f83d6f5689527164782f92da4b1ea12e8fb6a294589c816e18859cec34262df6490a2af6acc7daa3de861198c5bcf4b13000000000000000000000000000000001186b7c78952e5c32a9393eab07ad4532471595bc2c5d8137c61dd7fe6b6ca3aaba82dc205a559bdc15421a001b7270d0000000000000000000000000000000012d56b6fcec3d6511d2d723601cb8c9faabdcdd12efdd0e2bfd7c9292f2c3bd7f39c6e9aa53e6955727f88ad69c5b4f10000000000000000000000000000000006a5e56e4a42b04c03619c78232104f1f1f39e755058a19354eb230f2f09bf486b2586817aa6b88f27b884957ea0226600000000000000000000000000000000118c8521dd4866df907ecb252d9ce7a489f17d0f240d054a5dbff6c35895ef20b205236aa6e5be6f0825f9df87878ab783c4a3460caa35fc0e7342dd2da5c7b6aae818eeaf5a2cbf4794387180b95dfa00000000000000000000000000000000092809d18926c20456857826491f55cec17803e9e7d43f22faf4da18ede3bda15e3319539017ab20ed1de2bff490a33f0000000000000000000000000000000018d736b967eca64234f4e0018e5d6c902608e265037d9b8ba42dcc923b84ac62599e153e1c7d00e552ecc5aac57d1a5d000000000000000000000000000000001804aee99219354d4a5c46328f0658a417c85c6bc89af6db29a4911c4b0cad5638fac5ca61cc997fef3450cfb4a6c666000000000000000000000000000000000bf99dc4a400adda5bc89762e9011dae8ada23b284e52e2d49f75f1c75247f6282c95a36f7a72f896ea308131215404bd2b65c1580bb46e3a4cd9d9c4eb7dc998168c66982448abf3a4e08cd12f612b1000000000000000000000000000000000604f8bde85c0b26894e0de155cf896c911bca47533362a0b59ccdad0dd64108d33af8262d3ca2ca399306723f2482a8000000000000000000000000000000000ec10d3777aa54cd0cfd84b4062092ca3ac840a24e8e8aaad5f4c275e4d45091f838ae522efb1b2a0fa42229157297d300000000000000000000000000000000132cc70638d02186116773b31ec0e571a55c1cd78ec055fc647ab09cf4d3c543e0552d559b3daa4e99cef031e583e61500000000000000000000000000000000194a6a32a269692906b64feef9e4e8cd204e560b98db8c66380758d2123babae871273b4c571a1570a317c13a51d0fe9120892aded230949b83bfb2dbac054b83a9dbb852bd0ad85dd1d7f715852306f0000000000000000000000000000000016d05912dfff44912bf34f242ac85eb55bbb8a21625d45496c76d057f518352528c6632d6e8adbbccdd5983d13c26953000000000000000000000000000000000b10aa1402c15fd601ce605ade8f25531ea8f95cf592bf4ed86c4a3aa847dc8aa2369655ce5348da30a897fa8d71ffd800000000000000000000000000000000183f5a2f40da0a0f4598c6b9ea7b99f8cda1d85cec0e6da5365d7eaad1e9a3167bd647e5e654985f395ea72257f61e5d0000000000000000000000000000000014e615e2d5072c1b536ffa607f3a826ce297800b0da329fff397b6327800ecdc879e91f1e3ebc26c18e188e1ca66bfd66af9777a58539e5aa8b1fce0994e0e1cdb5877d93ed4db715c5aaf74d6a8bb1a000000000000000000000000000000000f3cd275d72a637bcce855e2e20727c6e5a1f15bc8d799231d3a7f61311d4cd2f58cf38448675aee9910c1a3d0b576210000000000000000000000000000000019efca445312f568727948c803d06b8d4e2c5289015740f2626fedbc0047d344aead06ef521ff7e139312fa41d1c107200000000000000000000000000000000141384e1c9f79e38bbb0bc1025c079741b93f56e150df58cf9a61ec27c2877c4188866fa197242965e3feb47a78c68380000000000000000000000000000000010638286faa6c45cf028e8e3d200edcb348560e2e35902927391401b3155240b62a40784db88e02b874e128e3a2132b5f37e2ed8e96921a0f9bff8b43d432b382d7b59938e269c381351ea49b8c1ba2b000000000000000000000000000000000c7fc4216767ed298206bc142862c138d78726e2d39afa18fe5732616c73a965d95cd2032d4b2f5a4d562be48ba6885a000000000000000000000000000000000928bbbd76b87f58ecc850e1aa4a2be11b15a81786aa7ca8cf0f6cc342db87b66c435f009f88ad97b747400fbcc651e10000000000000000000000000000000019f5ae9f06f2bc27a39bafacc7f3745fcdf8c78c9ae8a3c066ffd704aa4117eba773691ae43387b93e86d2e2de3688700000000000000000000000000000000014360a7ed73c05ef5fe651321f7e839c920bbc1896636143b88357cbf76e15da839bc7e1f1e629768d447c9d313cec8e23f4a77a2c34a370a9b59ab1cfad77212e433464d0195f0d2fd20c69141389f50000000000000000000000000000000000b9d955f9d28f9485d0bc4a961f0acbf09ee5fef38ccd81a2c73cf87a461ff1bf28d4dd1e0db3ea522299af67bff93b000000000000000000000000000000000889061e71866001b0760f68e20c7c0c033d782e6e6752f11502a0e8b6b70277a985dd13dd83424d1e5cdb9eb96a01c0000000000000000000000000000000000e05a26686667f44de2bef53c36c82f1fdda13dd3f7f8fe1fb026273dc4dfad18241d732ccb757e2b46ed8317dc69fad00000000000000000000000000000000038b55685b02231905dd9a62a709c0f015cf5650b3fa469462b3e9d06e3af8092d998c8e08ee61db1fd5583b0809a38996c59b0bc6dbf66f42cfee34413cc4cbdae7a61e232757c75474818591764d6f0000000000000000000000000000000006649a8eabb25fb7793344a0b29325a88294343f6c69612ee9d9002154a49791f6cd7b37b2bec69fa8ce11722e9f8a03000000000000000000000000000000000e10f2f3de16fce9b9817085f0130e1839d9aae949170ec16834732a9b12f589a2b00f17d2fd3416ddd020b7421ca20500000000000000000000000000000000016b51112b3c7c42a8c2a0fa7f286ec05cd07b6cea5675bf1132de99cf42b450b3c2a8f02ec821529a14a2a0fac3a751000000000000000000000000000000000f471ec8b65bde22e003500d1d422dd0d163abb424dd261fac588333755cc5124acde328085d8df852c61e024155564781c180924f1d982bf4b6a2bb1cac590cdfe84198fdecd87364e163dd988f9b1c000000000000000000000000000000000ec162d22b6516c309efb6a4577c5631a5807bebddc5fd1be5446e4a64785d49eed80eba2e89cfefe484ecb8d50440a600000000000000000000000000000000070c252caf6c56018af6b281b829a4fb8dbab850ba0446d233dcd4d87bebac00e3e5070bd41898dd561526498b153199000000000000000000000000000000000a0d76d1205c1f520d82c85bac4473ea7cf5f68022d95b1f04d06062197973001234d86921e70a94e478eea85264f14a0000000000000000000000000000000014c6a07f0d568f2103ccf8f61278e916458820bcb61fd91479b0dee874fe36c063a34bcb14ee434b68681d297637b5bfe44748b9eb1f44b5fb143cc8deaad23047bc5ecb8059705e7905c37625d5e2d3000000000000000000000000000000000aabac129385d145243c3a1f357ccc963ff14867ad039827488128ac639dc62fba82ace66f889b47d8eac39802bc1af900000000000000000000000000000000062bbbe8c72cd6f8626484bac159b7e28c6c8c3261edc6a05a30c308cc9e56db17eb58f62ab755f04a5c87e58c04c7550000000000000000000000000000000011a4a439d18501142350229778f67bbe0c9b948229dcecf70a8b09d1df6c54801a111c603301da2377d4198d09dd51e70000000000000000000000000000000017de3d9bc6fc5f415d04ecec013a635fa200699c496f4d0bdb5cea7d446274dddd0a7f6b06058fde43fc4f1457361558ae04d7723b7c9cb0574ba744bfed8f8a347ab740bdab99136aa71a6d635d0d98000000000000000000000000000000000c86590a02fb5c9568af4e69611f09980cb5a7e040c94ecdbe64e40005783fd3305a5657a5c6bebca7d20ee123a872b4000000000000000000000000000000000bc873a9bc694171d2606f4efa409897e03198a61b1bb16ae90f0d12345d2650d93c46e0c22b717e2f0504b8983515990000000000000000000000000000000001df9160ac3bc54c0121a9c69e9065f4266202f755c961bcb8641d13720b82ebd73eb3804ba44769fb2d75144442f1c400000000000000000000000000000000045e9c8ed2fe1e5c9a2a5bda75dd60f6bb5dcd0a805f68c1f662a5960b025ff29c8e21857d2a61bcd65c747d2a2da8ef6a794685a342ff25dd706e4df725e3466889d8f08a27ed2f32523b117f01a84e000000000000000000000000000000000f94df8d267339bb4f51b21014ca6d685f7657d0f0bca189e53cf19e0e5e05bfad773c0553daafd80c86f302b1907ba5000000000000000000000000000000000d92905addc028a1dfdad50e909c77662e10e4689e7c8a4a0174a3e1c746b361665b65e17fce02b6c067a5b8d7a6a6f500000000000000000000000000000000183444f0665790c48bd3c07545115a11f82463a092774234e7b33aac1094761f213235895e5e61ac1b0a15603bffe2140000000000000000000000000000000003cc2cbbf181fb023a5f6088d8a9793b17984b3dddc8c3ef1a9f82f8f436002610df60b2d35be212da9945bc8108c0bced3f23c51953e46d400802dde46c374178ef379d5c1b04d25449891f0d5623e5",
+ "Expected": "0000000000000000000000000000000011f85691799cb76213068ef4f997af66c349bf707295b969d85fe637d4eabf54f3f29e739152aba5027c1b55317a27210000000000000000000000000000000019627f9570f07f44f326b5b3ee19bc477e92d813be2865e00da93135645e02e6fe5507ac4d50085b02149667794609fd0000000000000000000000000000000018fdc97bf0f88b2348b436d70ac4e28b5ee5ba21e21e94808b8b9e401c0c7d688974fe203ebda0b23abe38018876f4930000000000000000000000000000000019e28c9c936ea5a0b3b41871c3afaaabd53a93902e44a96dcb7651bce7e6143d81cb695fea8b94aa32c09ec030dd9ac4",
+ "Name": "matter_g2_multiexp_76",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000703481cf48efe78fe8dad34184edd1765a1d01846de74a45b43d4721bf1af116c229f969868b0e6e851f22bdfb0451300000000000000000000000000000000063d316d495b1e82380c5b73bd61ce7f2159e7714c50e374e8a91dd56731dbe03a3378bf8afeccaba5fda73b4c2dd166000000000000000000000000000000001012cb2f6578065c93aeb673f447ce95fb42927ef9d12e07968ec04b6a604d785944620043dee5de4de33d59e67d64f20000000000000000000000000000000018cc7cfc360801ecc420d77ee171fb3eac3be0cf26b3f36a6cfb7c6adae7bb74c18071daed8fc56b8fa639ea138267928c8e071da1ae8f615631759cf33fdb876ab289a6bcfa6fba2693a58f8601dfd10000000000000000000000000000000011e0dfc437a65c6fe37bb9e554b5138f68a3c52816807bdf7d98f13cfaf86b37e9669f4e0db1b7865d910a309f16cc200000000000000000000000000000000006f2323e01591a7db1d3c7fa1a2ce4540cbe0396cc55baa3a3e13650a6f6b926a7cde0eebb45d359edd52137152fe360000000000000000000000000000000000066bfec8df4ab5f5f5eb369b34e8e22fe32abfc00ac58b68f2d3841248fe5843d6d29ad012249fb9ee851e40b940dc2000000000000000000000000000000000f4ea977d9249bc05dafb682a863ed17f7fba0a06c4a13cdf5a836748664183272eed96bc4109bc5beff61c5469e221f8371fff9230243d2e6cb6bdc4cd97260a8cf0362d18b9ba8df512d2a6f5563dc000000000000000000000000000000000fa3e3e77112774fd6d6b560ff88cc92ef8d009675d0ed65705398ce727cfe786684da50bcdfaffae97d19bdaddd81c00000000000000000000000000000000019e98284b8b9f53faf3b73902cc322dd80fc330dcaff2a7fceb55db6a4b0f7f667297f5e4650c797ee337985dc6b54310000000000000000000000000000000004e30acf2ba66d842575c8679caec607fd090f0aa2350464f3b6eef22e2b9a1d9d5fabb0f3909f1c19f6b8f27c53b040000000000000000000000000000000000ad76b86e32f84ad74bac68909da0c271571606e071b13bd92e387a8a16a1c4002c5a5e94ecaa1e8d2d6e051e19a45c763016c9a9cfbf336ebda090d3f2a1a1b265787e1917f0148f82a9c0b66b21dc100000000000000000000000000000000019bd07479b234bba974ca2f39b317d5f4be33afef66c1d69e53c44cb5e44c679775ba141f82486424110d186561777f00000000000000000000000000000000130002de0d453abe9052a5f70a9d55de74939d1c8e6ad5871a669a867861b1359322eb98539f4a21597d806aeca62d18000000000000000000000000000000000b2f0c649fdb37216c10762f510c3bb4c789dbd29c4f9a8ff39f74ed1a96609c60473a50f5ce3f6535e4af0f2f0a150c000000000000000000000000000000000893b9af710787361a32fbd19c380161c9a214a1bcf3761563424b8546f6068ba650d9caff3e42be63ebf4b6afa2de516c9f679167d5fbb29250834c9f65d3025606e2af20aedec309718f95ba01e90c00000000000000000000000000000000019805c0de5e232632228e2772dc79712e3d863bd6fe56932b29ee99870d2ce5eaf90c73632d1dcddc093e9b6b5b0f1d000000000000000000000000000000000405d77f4b3c44f99a956ef375879e62df033aa408127e0fee013b74675a8c7d999c6abd30f459693086bfdb326d67af00000000000000000000000000000000110f2c231998aca3d76e40055a05feb37eba76cdd10106719f2300f57906424d7eb6d9f85115b78b7371ee60e26d02b5000000000000000000000000000000000593a4721a67caa7cbbe1566611a1d48532c68adcdbb67f362c9ec21e08aaddf6b5e09a9a96df9a89bc25f11665f3a36aaa3300f5a2fafab132f5f4662c1d288210e7502ca2472d060aeea6f2eab2d7100000000000000000000000000000000151758f1921743d116f1c4adfc09cb68b3ff911329e2f6d6bcd04beb9c109568c796f328e1f04381a995fe89aebbc49c000000000000000000000000000000001388c73b1db46bdbe70540c99db46b730e157a23afea97648d73f9d5f7e8b073ed665eed9e9e2500152c87715f1c4d4c000000000000000000000000000000000284ad228867ed14ade5a327ed951ca50c87f0a669e59b7a75d17feb54bc5d685245448a912590179db1e84f1eed1e5b0000000000000000000000000000000017d3da7c167733dd88f1c39315e47cc80c3310cc431989d4cc50ddb22e9fa481c5dc02d94dbf806c4c8da16ba5b24905f6608f7c036c8fdc335601ac55e869215eb4e626f52bae813d45b827df2afd490000000000000000000000000000000016064871cb68f748939a839800afbb018fd5836914a2b76c51818e764628a76817c7ea329e6b2f9de653c8162a2a2e0c00000000000000000000000000000000082fa03cda4c617a780caaecd7c859c5251b56b61f70fb3ea8c05b4c11c030adb8a96d715c1325ef3dce9b20e8065b6700000000000000000000000000000000174a245baedb7e1bf1368212620b850151be41ebb00c977d85da499223c207ab6f1a1d94a51aa9e90d07764ec3615b3a000000000000000000000000000000000df5b81cf4b008480775ff3d7644f546a60382e92a98b03deaa4a20f831e69e14a893ffa731c4ae9ee237d747149a9080cd68c59b1371c7063dee5732182961be90b95247511a5b564d7eee8d2c7c64700000000000000000000000000000000019d36b8dae5e1083e687743f7494b7f9dd0923024df81e2f83c78743e227ffce588a16630201b9909daa6c9207b5f430000000000000000000000000000000015659059cfee7850e1cf0e49abeef2fe5837cd128742e62de20dc734f1bba343aee1c9f1a59d920a0519995561891fdc00000000000000000000000000000000102b7221257c40d9adabd0db3ec9f6348487187ea1110773fcb2ac5ce210dfed167a4d15e605e9d9e666fd092147a1c7000000000000000000000000000000001402ff9770d27d2d82efa6abe4a181e3c1d944e97a06f670d9e46b24f9900fb4a838b32e17482f25be9b6f3240870c02ea52329555d9b79eb1fd6d186df80b25245ba9225553f402cfa6037592f0b10f0000000000000000000000000000000001745ea52686f87a39fa42ddb5b0f69368db3757394fa7a1a93eb20c398c26415c8a7edeec7334df5b15345d6174126b0000000000000000000000000000000012b580e6fd228f087c7584cd95826e56d1c074cf16c35286c45d2067a362529d241c1e24fd22cc9727d423551de1a1f700000000000000000000000000000000104b46c42a706c61610f8c0434894c7cb9ef878cd0234f8aec0825cbb8297bed3de349e7f6037dd19a159103ca7753390000000000000000000000000000000010b781b3cbe6f415af15e37be7c60dc6703e6e79618cb3d8d9a5ea3b17c00822aef1eddacad66a646c009dac887bb070caf39f2a517d432d1653c37fd9a6c4a8a811107dae428f4b2af3b12e4b6acea30000000000000000000000000000000004b172c360fca555e65860c7a294960f506b562e012ddebad5803bc3f4b93159c16cedb73f339def9cd1beaa0912c93c000000000000000000000000000000000242e37775a042ccf59e99da667c67fc49e80e54a1b438a74fe306d668059ab4dc7d9e457adb45e1f91b3e6bef0a130f00000000000000000000000000000000186eb83ce3abe66b8760dcc0d375eb783d175b0b2f36cc08793d8a86cf76b7618b826f50c6b02ed586394abe4efec2f1000000000000000000000000000000000bf780324df1cc5de325a796f1fde367eb52dac76c0632915dfcaf01f5acd6ae890dbfc2e505bafeba7fed8fd63018c2ff0bad6dae80d5f47dd8c208fef0f3046cf1040112d18c596eeb934762977cdc000000000000000000000000000000001231b52c8a081add6e5c250caeb9467335933c2ed66826e4ab44561eda9259acf926f22ad0df8e8756aa51279d12bc9600000000000000000000000000000000051c46bb04d3e035d324de681c772e4561cecc6a5bc4ef0a0cea56618e09b3f39f5085e208229e50164bcdcd4abdefd2000000000000000000000000000000000ad7ee610398935a02c3a7139185409d7fd4681ebb74a239e15d1c092ea913016d3f585d8224cb1d109ac111660a94aa000000000000000000000000000000000903bb16efb052b99e9c46f3478b4acf800a173b35b0079d7728fc25c9415c8b05ad520f31e6a3c867245f64355cbc080d0c40e5d422685c5c83716380eed82392ae1dc6074a7edb5759fa34a61db2d0000000000000000000000000000000001788efb21597aaac29b7bcb9ad6cecb89267c757cfcd8893c32fb13c0f3e1af7fcccb9573dcffe8d9220292b7861cac90000000000000000000000000000000015f85d3686148ad62d7fecb71920981117cb8759ab249d0ceb45f9e4687914536a1eb16ccd0e185d1352a8d2b4a8ee7a0000000000000000000000000000000015d8ed94c0415ee0f7c9854841bac5821253bb2ed4d86a61f494cbfbd61614983e4279fb17802ca68aba4a0302ec1d8a000000000000000000000000000000000f950a4c8aa18f4605e1252c367dba1e170ad00376a8560c2fccfa7d5487b0d1d5885cec16a0a17d81b5a584d473853f7e93a16a443d5f981a02f0b6866536dadd276abc0998bedd76b168ebc8e31b82000000000000000000000000000000000da25ed9154121205ab6843f603a38a6892887d2725f16ff87a5218586c6139188f46da5a42b5e05982468e8115713ce0000000000000000000000000000000013c13ffbed4a60bcb8659013b022012ef3a4400f506d65aff7ffb1bd5a9a5e030a298e417cc1ec8ee7ebc06455dbe61b00000000000000000000000000000000132d83bd141c434326d4772de7f8772c30a6456de7adee7de66a04bece4c0d20bae5526c8eca5af5ef2eebd72c90d54d00000000000000000000000000000000131355c5e359081dc86e0b15c8aedb4f2016b41e8428051f5132258eaf4392fdb63a91452dc56aca20b7ad3263ebc8c92a1d13a64c03585715908744481c79f340b5bdcdd88d685ab8b91722ee7ab7190000000000000000000000000000000012dbe1327162e4176b4988cec23df0c1b0075d0dc51ea8afbbf98f00891511d9023cf7538c5705d59b6d6ddcc90b101d00000000000000000000000000000000036c12c7f7627b6d6fcba9a303248c38d784a3d1d0ff02e550565efbab68c5116e9a88faaaf09bc72bcc3358e9dad0ee000000000000000000000000000000001578ffb68cf12dc9a5ae6fb5d822324cec9e3f576ce08d45e24fec9203d36a6461c5b8ea6ac50233e8893b07ea6e71e00000000000000000000000000000000015cdb43c82b20b8ab270b942b9e625ada9283962a7ce95eae156aa4355e1123ff87ddb1cc85b2a94bf36102ccbec33fb2bc6979fa2e386abec058683c6d74de31af3cac21283cd5e4244d7edd94da9600000000000000000000000000000000017041e16975850e6445c7b4896955eb5eab383ad3c3031aef04e8fdfb65a6d52c9e647330bfbb0f0eab630c9f9ef7a12000000000000000000000000000000000b62757ccfb913ac4264692053f766e142697f598a3fe26e998119b63a3abc7fee03db32a8af36aa21181fe9ea89d12c0000000000000000000000000000000006bbb842a889d7ff3c1eb5e0b16e3a921a11d28a251c488a8a17a29edd93672fd15974a7e972a34c47283c583cf2d29b000000000000000000000000000000000e94e685fb1751f8720b8af79aec7b245ae8daa195f11f485f2c0c5dd68cf39eef848a402ce2342a6b3398cc7879c6010f1937936cc3766184e47f39acfe5af4497e8edf77ab34083135a9ced61d25ed00000000000000000000000000000000100d3fee47ae6c8c7981c8cc615870924fbcb34c2ed817d6862e2e6d0b4612222a4c8332c7d51b58ec59df6832139e1d0000000000000000000000000000000017270fa71c34ec84043ef64c5dfd61614b5b3bd99204f9f70994d71498219818a5f16843c67c668b06aa5ad3a6ba8a0a00000000000000000000000000000000057948c0ebd14664bf33fb282e200fa0e641764a353e8347586465dab0c79ca2caffbdc2c6d60b2d7c8cb6b088bd16fc0000000000000000000000000000000012747eb070f2de18f517648395109bc08b4af3f04d98e23eb6b516199b4eefc5df7d57baec736987139c7b03b573941f639a8b60a1849c71688a11e612b315439161717f525b5deabbce75808470166e",
+ "Expected": "00000000000000000000000000000000128c6c0283ea35c10330502d6aa849a909df6b8dd927a24f08072135b8e21e40c495c42e742160363772569189d73ef40000000000000000000000000000000016d78dba1e0feeab46f8cd38681a9c2f6490ecc3a6e79b31caead256611d133090a4eaed9691a87b66dd1c2ee50d5f470000000000000000000000000000000016de93e176c950975abcbc692384996315a98065db6d6a6214472e5a338e291b36abbcdea1b8be6162fe578acd669abf000000000000000000000000000000000d7155e239e9b15ab64a538b0a0bd53936df4ebdc3ec9b0b1d494e4df780bd014425759e9743c9b262cf48cda01e945a",
+ "Name": "matter_g2_multiexp_77",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a653e0c24eee1cdf8e3652809de0cd159f2c541981a4f43936e7d41c0f97ffe2f1e1e0d1032f0970023f1d27241a16a0000000000000000000000000000000012d1d8d2f96db0e5f97be096c961e3b90ef3d88492fb756894979d2e8104791a5b9a43888043ce9e543691f15d2fdb650000000000000000000000000000000006ffb94dc3c2d07830498260ebe4641b2cb64df61cebfffaf2d4ab5b6ba92cd75de209e8d7915ee744c4db5352ff239d0000000000000000000000000000000011f25722cf9db77ef8adb9caa250175e12412e6350b494395a86c31e1f5dee6c89cc6603f1dfd08a70344cdc44aa0c2df3efcda934ec9d2ab05f25d618e5a483e830d0452a88e980589fcd7cfc39e5d80000000000000000000000000000000006177a74e3551770e7d906222590108bae7b97a5dd3bdd2344fc12e7005f2c1a188ab9dffe68f5ffb0cc36294106f15800000000000000000000000000000000041b140c46868767119a6ebb58562570732198854c92bcc070f2a8d9be91282a70c5ab99e75cc9e5064ed628aa5c59de000000000000000000000000000000000f318ee33fccf455e46add44922bb6e99afd4354bbc79d7550f8d12d3de4f75e5ddf4e62624b116f91aaa80a148adaf9000000000000000000000000000000000fe012bf88e152eb62c0c906dccba469abe591687573a59d3debe747b7d895e4b0755f16e67fa9193a2fd338c04d243a4507a696cc57c0bc49fb4d1686752c71c9c816d7d09bd66910b23810d475aa02000000000000000000000000000000000b26c6e0106d4efbacf2dd0d15df17209b1306f388f493c096429c031bc4a6a535b64cb02b400433f948fd6004df2fa200000000000000000000000000000000061853cf1a32fdf4c370cd413754ea584d3722a08d58575075a7371e57a7bdef95386ed72f91c4893377f6b551dd6b1d000000000000000000000000000000000ebf17e60718c8563a1029ba035dbbba75e7191b4339d5d33f64bb35f34866081f26f4815e01b02e8330e7b7e9c428cd0000000000000000000000000000000008ce40f92efb5c5be48c814018fbbe45f1be45f5b607a6600cecd50d8f791de7d91939ab61204c2a1337c3f21b2c9d26518c1259f23de4cecd5e3a40abef5662b497ebaf16240f40ecd651d2ba50af0700000000000000000000000000000000123ef52cc44f36326b33234ab3348893bc722bac3674e43385b201f372fe4ea3569d69d4d561e26f8ea903e017d7376a0000000000000000000000000000000005b1707ef61ff9acb9e8b4dd6922daaaa2d8a7558cb55b1b9b96eb6d57c23f50a7955763c9b5ef04f52b09be8d55f4b50000000000000000000000000000000015b6e35d14da61e7a7fcbcb0dddaf0071d8d2d89f7179f44851947a2b9b0535d6fa86b5cae9713a73bbed909a4c6deaa0000000000000000000000000000000013463e135b1fd460cf042dcd0226e229d60cc2beccd8a1832df241e65a644159722a14297c0033eb499e5890f0caff1e5561616c195ccc1345421d8a6efec48f0a4dc8e89ee89599839efaf95c386551000000000000000000000000000000000fbdf4a533d355e232723fbc97352fc5d7d3d199934883a61a9ea116830bdf9e40d423256225d9a3458134332ef6e817000000000000000000000000000000001195f0ad227941c5e383c48f546be34762d158e6cee585650b6ee987f7b98e802f678abac6646832b30b6e12e90948cb000000000000000000000000000000001820d5fbb5a62140c6e8cd105a70fc2f1ed84e254c839deadae5eadbb75e1c33a07ad12ee92900f55478e91958a3147a0000000000000000000000000000000013849bdcae33fad27f16e91c6d46b9678a00491e3d70a8db905db4b1d2c6f02a29392b5b77c1472052d6f4d49f14a16737c77734125181c72454bb2d37c3725cf1f9b6d6f42b721bca469fec154b3e2600000000000000000000000000000000188fe1e394b567d71099fa13b5c8a5891636d83b6b8a08f410b080658a0663deaae4dca1afe8b9023b5e8e573c752c92000000000000000000000000000000000f66c65dab8e1b2912fd5285a4c87821888532f5107075cdfedacc4d7f75c6a74b4828d0b4c3a2c0ed94576654a7047d0000000000000000000000000000000016af44a6df79c8c9b6f1d8aeca24e024c454d7b94c9ed386858dd35c4158cddcad1207f9fc3ac9e3b748c2314f875dac000000000000000000000000000000000315e5e4f78e9fcb93aac78025e95b8bf82ce4c840cf565e0a868b0aac22950d62f7becbf8039a16ca3ea66a7498327d981483aa66e04351f4340fd2b461165b9a9983e91c148da78d3c8e0c69e77de4000000000000000000000000000000000f9a61dd1b3034b8cd7408b0a44c8d02f4fe0e87778d5d34f5e884ccc9e2d51eca6b6060b46b66843e8247b3c794e19d0000000000000000000000000000000005c47fa7799a0fffcafbbe4694dfe8d0f47b60f712d6319e9a56ac459a636460e700e2af80f9c688208978aec7c413af000000000000000000000000000000000ab1c55fe2207865ecf12e372a341c776d24c08dba10702fce1cd2c01eda314852d81d0ccf1c3423c2a12e8960677f060000000000000000000000000000000014f8a1964aa3240d788ea40bb51abc50fae2736a34120ca9585fb2d5bba4e5cfa201c83be1e00ecd1c46fcb2ebb4eb809913da6f756005ca8ab900ab686484483af07df768209a16d807f8b88b9334d30000000000000000000000000000000006441fcaf5e68b10e7e511a95e56b9613453ec6468bb126c5eb12f204c9681c69b5c296320f92a6fbb0b848f8ab5fcd1000000000000000000000000000000000141de16aeca0a2f991e9fca4b6ce8fbab3d66ee3ee4dffb0124384a7d4ba51864a53e005fd34516c92ecab33165944a0000000000000000000000000000000008543656b5495bdb726109cd98fa18e405648fa88cbe2e5fea5380b7d0ecb207f0343dc7888b9945e55156977336226b000000000000000000000000000000000b53d4e392f304225b1ef363a3528daca1d3a6ad64ee99d58491863ea432a29cde5edd4f390de45a567cf32112ca5929188fb33fb359f21bc5bdfc85d39676c2ca0a1e619bf8a8e8de62da8818bd6cfe0000000000000000000000000000000002e0c55a43078df575efb2c99b27c5632dd1c08bf28b6c0558081a78de58e4258d1b57d94ec6fa157add04aee06e7b6e0000000000000000000000000000000006d3f4f0791431a56fb386f4bb8e6744cd19b10bd0f2e65e927371ab488d3735e3b83400ddb25ef9d740a8620821b0ab0000000000000000000000000000000011e9cdfec8a8f8eba0de6809485911711149ca0ebd0cecc033e2e5ddfc195fa7de671a686edd2f56e5f7da7328dfbec000000000000000000000000000000000171f188afd5d9568cc5648aefb65cd715c0293344b9aceac1031f10b4a1e4b9fa2ab11114bd58f28aaa58c10ee0eeac65525ab4c4468a2ec0beecdb7fb072f28260ebb3d9da1a4c274b2c11a087e814a000000000000000000000000000000001651d9bddf61e5e54f86609c2479513ae84b000ad7defd840d9619a8361922dde81c999d0e95d8a3044c46fe0360c2030000000000000000000000000000000014a68c248808e826a3bb50f3c1c1438483cbb9da8dd67a0c9633a47f733e6aa7deb4a13aaebcd50de6e8e8f00000424a0000000000000000000000000000000010c8a94b9e0ec9965f6c8bd0c4279102ab682a14fc3c22e9640d68f240ccecfead9a2c6e69f7c8ed369cce7e2da50d5000000000000000000000000000000000181493e8137fcfae203e1b45189fb828dc9eb56887c89aaf9aad0380fffada423f0ab48ed068ba4e67a2b01a16abbfe55ab5a55a5cfc49cf6c36b5718e108f8d006bf7fa1ec3dc7a7f9c02a2d1e3fc57000000000000000000000000000000000e3e33fa4d85a35e8707419ca6d4fb6a61ee6b07ce152adfbaf6b5f1d7ccc253b59f91e4545848b3570bfaa804ad9767000000000000000000000000000000000c923a4de074dce3ccc94698bf6445af5847c0e6f22f225c589f744ec83ed0810913af2a6d04bd55200ffc738b31b01200000000000000000000000000000000186961ed1c6039476eb6f13bf1b5f6627b3b017ece57a4a5f33db8ef12347fd507398a421932d3d2a1d009f65d06e42c0000000000000000000000000000000011e10ae0139f95a2f1144810894fb98f6e5e86ce67877b949a2a7134c446dfe53c23dfbfd12919b24975f26eafa249216ce7aa7dcd01c1b7059ad3cc0ebf5d19ceaae633160a968c33aac5dc6adb942800000000000000000000000000000000029265ecf3c81aab289c98d9cdb917749ceef56e2e4d59de2d6c83907f394ddd1cce9d093a20206c2c1c215493c41c49000000000000000000000000000000000986ad139381e4dbabd6beba179600e1c782f436f84a7bd58cdd96a22269f1d937f88f25059214fe2a781ac519aa621d0000000000000000000000000000000019e296d5b17f78b3ffbdaa2ef5228fa9dd65abdf6b2c5b0f99a708c4721797b3b156b8df98a5a879f17f095548555da7000000000000000000000000000000000349677d4719445d5525cd65e2338463d232eb75721ca51c48fe52d0fbd299ddbd6cbc12546f056bf212d5700c3c4100854bce63dcdc0cf408b43690abbbbdacda5f3ebd9d9e462f89f9f50a9f7bd44b0000000000000000000000000000000016f5d5eb3fc3ff178843a7d21d3dd628bda120321ae44206d88f07ac001651428e0da95d3f0676e1bbb969a300406ce000000000000000000000000000000000029121c539ef1d7b9888497a362fda2f8402adf10a1bee11b53cf3dfcc6f99d5026bc386f86a2eecd0c276494878104f000000000000000000000000000000001320a402922f2a0bb287464854be6782046dd9dae4c0cd94efcb8ad8e0f37b7889bc97a3c8b4d3b3670a6924c8ee23ec00000000000000000000000000000000101fa8bb2c90b755bfba9cd7a98790b7bea2ede4c806fbd9f2006d10cf87c44172d4ba46ea40fb75afbbaa2abc3b6e9d7603824b834a83c1c408243b51cd2c2d31e2ee763d69e2ad6d369bb6aa2396fd0000000000000000000000000000000003285cb099b04b6acd333c7ac76c839b6c09388792d5fa1f2af0821e49dfbf40a06803c4cca92512bb76d073129a48a00000000000000000000000000000000005b2fdbb25381b3b67814bf6cc0a4cc17271416d16ee369b723b1711d968c355b755183f0bce519709723250515ba32a0000000000000000000000000000000002c7062ba4f642b95e028a364b0698b801f48af3c336fa09d13d83ec6cff10d210b55b23cad1d999889c83df7d1ab7e10000000000000000000000000000000012cdfdc10bf46097083294259754453e084010f7ee928cf540d44c80aa4f601247223a318700bc24114e7603922d15ae923c86e91c48582f19409b962be361da5936db02b6862eefc288f9a32d5f54760000000000000000000000000000000000669d760352e34a407aef8e141fcaa9468257b12ec08ec218f49f0769f3acd5068c6dc9d251a1b2af02a2d091f8ad0000000000000000000000000000000000064a7b4026ee3115cb730e56c4b9bf3e1527dd0f0ac6015f43d30a2f3d8d8c2659cf50247e70ca3c93d7e0a404d9faaa000000000000000000000000000000000979ca2e81663ed61486c1f841c19d83549388d798da72feda82283406d4964bc9991f876a6032382c35b605441ee7da0000000000000000000000000000000008d92cf77b44c516c243f3e6a8a8d3f9d3d7405820ab972338f700de1dd9a66d33b4a70540a30f630aa81fe1cb5bf057e1b3071b561a80aaaadb5cc24b348a2b6012340d3aebcca7e2f56983a8a13bf900000000000000000000000000000000198831a40fec54a210a63f5e00b132bb1eca6408335b85a75e28be6a111beea3b99d9f2fe5091ab0eba0f082c201c14d000000000000000000000000000000000fe457f8d215f390000efbb7fe7193ba02a2ef78e9bff6539995f01604fdca9fa3c010276afb90215890f5a5df3ae21500000000000000000000000000000000076771823180422495d89c301443a9d1fa141716e5e27205b8cb6b461a3ded7e6f196c3976cd6ad56b2e6ebb6b3a70860000000000000000000000000000000007f666efc677f6f767828e1291bde0ba0ca445ddb2d69d5d2fa090ca49e697ce4e00f55d2b706454be6d68f012d76efbb6863b755d3dee61328a60f585531c436663bbeab9afaffac49b6f0b57614eaa",
+ "Expected": "000000000000000000000000000000000e1268a5e2f654c4038647a910e6cb4bab1d6ca3562ad4a9ac18444c8b8a3fdfbd35acf37f9203041fd587a5175ce86d0000000000000000000000000000000005e701a8ddd15ecb0231b7625f7868c81467c140b2617e60440a9b348a192e5248b1b3c087545cfb6d173fafe48d32f600000000000000000000000000000000071327f52b1325bb664d32c513fb12afb96dd8da23dd91bc4c3e8ae5f97d6bf673a5d03bb8bdeb6da3144dedac200dbd000000000000000000000000000000001852b86d3ef45aaeb691f454a345ed61104cecf0f444e4d841f2bc0402ea1291ef056eddb3fc3929ef4623f31016c3b5",
+ "Name": "matter_g2_multiexp_78",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fcd3f253d018ef09a7c6e8f36662ab4190867a197e0c42a0b425dfb5fe61d57596ada28dde0b093676ce15d03406d20000000000000000000000000000000000df00598337060d603607f3b8dd16f277ce1882a2e9ced48e1944662323efc29b33c807653f31583a5d2198426019ba70000000000000000000000000000000009876c81a76986435d34c6d44d51cf1016c19ceed2432ef1e68decd64da2e31e42372c1a41a514b0eac0ac103ab6f43800000000000000000000000000000000121cf298ff8f610c64ca4a887c52cbe940333506ef2afecffe266b5b585ff737395e2c64adc23b5bd232250e67c7a62613ca0cfc742607bee58988df361d7cd5d809ba4fddb209c898cd555369fff566000000000000000000000000000000001885d5cdc3e0e0c8cffa7519e6914e5d85962d07633970c4174ae4587853f13970a1f5d7ccba97458b9b5046847ad29800000000000000000000000000000000105b7c0ba96d5ce32d7447351ded3e3f491a0e741e921447b91f22a23b64c2d749055a0593e5b47f0ff7815e1a4c9943000000000000000000000000000000000cb88fc10c94642ae7e1d7275bbfd51a2d40e9b29f3d51a1ceda577beeb131eae4b17418f9f358d47b4b9c9ca4960a3b00000000000000000000000000000000131a3e080b1d4e936d97d255b07b09a6210b5fe6900da87b5cc595a72de2b6ddb01809e2dc63ad460a2926dd8d3b3b2ebcca8ab454fbc576a2b910f140b23c23b14301c19e1f47989d78eeecf279862a00000000000000000000000000000000066b31c0bc4b3b9fe420dc095d551903a2859556d86e210c96480f1d31d449d85ea292e2432babdb71c151c7b215cd6b0000000000000000000000000000000019d79a60793957745077f9233aee7a4f096515eefa7c49473f09bbc73fa0ee13a2a30a08bd7f3bc1d5c412d671fc37ff00000000000000000000000000000000006882160e4fa8ae2c2d48ae389d8f023e2775adb7a815edeba13728b8f6b343c45788c8e9116445e9989e01eb43e1500000000000000000000000000000000000ce53ab2d81ebaf4a85b3e12a6175ad7fb6cfbae207a69a0fe2195ab916fcb582b097f09d9fc565b837925f68855c4b59f82ceeb6160d3256228d7a41fb3caa6f305b23142ab979e728356a13309e27000000000000000000000000000000000a30d335c035afe459dc262fb1bd24dc0bafbc08fae0bed47e4e204280eb96595fada9c4332df1218748921bfb1274c7000000000000000000000000000000000e37eb189560211d6fe56faa3b6e710878a21907fdc1a9f8becabca290c24b8831e28ebb48d06bd822300fd09b4d103100000000000000000000000000000000104842b88b9df6a7b8243494eb11eb62c89d1ccbde9f55fe221c2366d6bc9149178f177628c6fe7c7661318640295e570000000000000000000000000000000011df8599d72b85ade11261076e02c036be5dfa3b6fab4ff72ed7413a879c0a0742be6c36a32d0829a4e3171b0341c6a3995f7d2038ad02deddca34399e5b5653fa471d998c52bd52241840cdb9202b2c0000000000000000000000000000000019f6634435be45b099cc739fe5c2dfa01f61fd2d466d5ea464053e2d5acf2e0e9448b1bb7770b5ad426f8a872c5764400000000000000000000000000000000002bbd52efecb10b3bb6f8bd04a5751042d8598cc34e2837184cea2b5953ec125dee871d1f2f57ebc84849e3a7ee5abe2000000000000000000000000000000001962b716342df9c13c21d89ab5b8c4c0ca191440fa709627e0f240a7ba518f4c95adfc5973b6ed0af591bb54bd00937f00000000000000000000000000000000089eec676276c52bfbb2593ef0362c12a5f3c1a0566d5aa862f5f5ba1580f4dadb36c15fdcf0c3910ee14487ff146c8997b67e68bfe2d7fc256e6aa610dd91dc1b02c64186d24702ad8fa9f715b582a5000000000000000000000000000000001556d081a489eba4fbb0c20e22b8cab432a9f6ff459ab9b0e7ceacbbd46c8e24a2ee70151b019a1b4bfe47d934afede30000000000000000000000000000000008fdd7391113e8d9865ef48b60acf921b17c50744e6ad62fa24abaae54836b3d59a7441371bdfdcdb251d252a43aed7b000000000000000000000000000000000cc66cdb1fe32beb91b05922f3920060e7a95467381d62f2f036e6268af4128c9516780ea53e873993744ce932b901f100000000000000000000000000000000151f94dec958859ecaeb810c4b1cc7a707d0e1671cd4a1e3c811910bc8b95c6c944167dd280c7fed22f92ce7650beef998115b9f84e3ed6947bd6f0e3c65361cf360a65bc059515da852a72ec5cd178100000000000000000000000000000000004f88568c7ede48d7476175f1d2e7ded4312c24934f0d47794705621f8aa8a5072b86cc41e187f4aeeb49bff17a4c9d000000000000000000000000000000000ca6c579e86a68b4041150fbbc36da744d359028993681c34e66c537eb8a0a0d55aeb9b8da7fecb844104dabeb507805000000000000000000000000000000000fec63c57d3d3ca98cd1735b2f59217e163ca53b07b4fabc4415b98377d87e75f0fcc9b51c99a57ff61ca8d0016a206d000000000000000000000000000000000940e9f93f3ccbe74c7be93236a2c440b213a014ed51cb57fa053495c3d6f6c8edc08ba8e10be26e5faa898162d67fe327370e1037b709015e0bf178a41ac55774a813368e11ef7a764eb48abe75dbf500000000000000000000000000000000055e4dd9da22201b5eb64e3b9eff2eab614c48450424491a85c18e05f50659b88e862490edd11ff980b06696b60c35b00000000000000000000000000000000018fab38f58d3d541666bc29b9e94cb3940f1794b2aa851d079b9aaa1cf742b07cd6dc7c985c7e4d7d3fe683bb15d618e000000000000000000000000000000000534de5e1c1181e951b437fd17993e995fd4aa2f6b28fc3612cd4db615de742e12d66c03b9ced538c1c7cde27752c190000000000000000000000000000000000aa8580f1da71f2ae9ec26f3b6466813a40ba5bd3f89ed0d42695d420032540194617fcc2f13e36219fc0cc3886a69c36bf5fb297948e0ddc60ba26e49ef2892ca008e64a22ff2bb21ff70c56112f710000000000000000000000000000000001804ed7677fa3842bdc3eba708bf4fb7f7d4eaf2f1a46193c861595f64196398622df4358b9526f33663138b24fef1310000000000000000000000000000000011fdd7e1d0c5adfbbbaa69ce63c7c54525091289e4dfdfb3de772a8d5a958581cc23933deadcb8856540e2d0dc564dbc0000000000000000000000000000000013fcf17235506fb194e3adaab881c7aba4b87e5aef739e0547b858410e3cdbff0dab1980b1b30a7d03d617179ae545c900000000000000000000000000000000004eed0ca479cc458231ff969ebdd4e33732953e9f5610d78d4753b99c5f8cf73c742387b8e71b9be074fcc67acd71cf6b488b6b63cb8bf34efeedd9f95dff4d3d8c067c0d807bd1e20bd267748275d0000000000000000000000000000000001082b7796d35e387df689bcdda6e0316d343dc907822d1a873adea050374962b164ed27cea0e1b834997f8274e4c5438000000000000000000000000000000000b1905979a90c7a61f4ee2cf3a9f4d6ed4c724c9e216981b8ec34fb9b528018d237771ad620020efc2c3cb104df667cd000000000000000000000000000000000752663e72390108288ef4de3c3ea409c74e7051505b12083c41a2e8937eaadbd8cd61f96f7991722226fdd02dd8d252000000000000000000000000000000000f8e4eb7a3c78b8040a115c42b5d2fc69405f8334e948b8553f444dfef29bf3920892da431cd8394cf61f24e356e95694f661845e91de1c09f581c7612a25bfa0889f77c2add31b493b37d20bcce11070000000000000000000000000000000010884516bb9916084709351ed8768c6105fa451e08d5acb233511254ddbf4e72baf9c43b56b4d7dd129a38f5b34ee5f0000000000000000000000000000000000228fc5fffef746419cc69abb17cdc63ded44892b8c5d02f0c72bc8506a61d15a74ec4ea0e1d78f555ddec07f418539500000000000000000000000000000000048a4192c204b7441e871076d91d4f610c347c2d71cf495ffcb2e2ab808a8c1a549eae96e657d756d9a3b94db2892a2f0000000000000000000000000000000017a94d2472df89104ed96e24d166f922bb852b5ad80f80188fce65b08d39cc3ecf94991c6bec5dc12f9337e7c087db2f8b3bf8d5e529912b1b6e445f592a6d151c6f5d01d3b021a31a2669df4ce02aa3000000000000000000000000000000000f6293fb0e19ec85f43a1a02df9f59ad4fb0e49b16a216ce097b8ec59e781fdf176360d8492e8b77674ae2c0ddb1da70000000000000000000000000000000000e354d09aad68fce6cde40c787ba1e4488999d5b9f3fec25c9994b56bcccaaa746c958bd16ba271485f461b0d4e983200000000000000000000000000000000014fca0851b0bfdf2c69fb346f23b46135d2b7914bb49e297a0c1304d8c2851ff6bd0a0bb364938dd44680fe86cfe12e300000000000000000000000000000000164e23a53103dfa332e5ae09c7c898b95773c20f019d8b794a6b49594040e2e090db6a8047c943885dca95188e89a63b30e1c8f222019b877e66df0b6201b5bfc5b6c10aae340c55e74410a536ffb9b200000000000000000000000000000000146d37241ce4f71017e4423dd0bf907a12c1364ae9fc6dfe535c25e5e99e03ce157cbba2675829b396a69f92668107280000000000000000000000000000000000d5a992f5357615f436d95fa516212812f6811dd1f1921ba4129e84e3d487b6c97520995d8a65f6771dbba9d150c7ab0000000000000000000000000000000007b01f86574a9cb7eb3b9a19b6040055a5c11b13e7071078d16b9ad71f714ed28ad25db9511964b156ee34db22385cdf00000000000000000000000000000000154c29c6e2b21a75b14159b183e625c98a04be1850b22d314225e94b313619f641ead73130c1d6feb85abd8c9e172f6323a258d66f2296fa1c71065cf23c994eb8c6c35d35120d16790fec791ad215fe00000000000000000000000000000000075be2703b8416fa07a7cb6ae8841dcab1e36b0ea24231dba617a2fed3bebf8d952d31f68c149dd17eed136fe37b01880000000000000000000000000000000001156563f1401b731cc23c4be59e69b0e6a0827df4889cd9ef9e11310f679c1603a0d9c9679c29b8dab75ae51f49bfe3000000000000000000000000000000000663faacfaa92fbc095a5dd6b1f2dd141e248f84eff1716ee71bdffd4d28ef1f4c88828e3457e8ebf0daba1416d2d6070000000000000000000000000000000018f2871f5897aad9ff6ac45a9c0e78be8f312f07af5f1dab2bc4705558070abf367f1782af896288a7754da82bf1a5141ef4055b85f37b548dac2b64608d99ca293548bebe1e24355393520c34eda60a0000000000000000000000000000000001618a284286899f501f46c4761c93b68bc8ab3157144e4013e242e1678cba20a2d978ab53b4b43145dd6062748df541000000000000000000000000000000000c25da737368775e41ddcd9c64cf99a824afacb1d404f1ef46ec7fe4ffd89673648c5207551914e6e0d12c57e7d7682c00000000000000000000000000000000097ff49c4872e2da1f6c24fd6dd4667f0bef4eb30fc197d13e8b66adc425e39841dea011d79e4d775106a19ea1978f4c00000000000000000000000000000000147426b7d9b0bdc2be051d8f6cc4249014e1bbc2369bc32eca94684483f50ced2c07be6a320effddcc1ed5cae455fc92212529248c51c95b5b26961f27e6d44ef1c2b9233bb2ed32c3eee79ca6c6eb750000000000000000000000000000000000cf68f7ab056c4689af95b361ee3e3b1c1c48f18b5aa655cce1a2be217010814b3f07dedf6f9a7b835cb13e2afd7136000000000000000000000000000000000dd6d0fb94048dab34410dba4e682f020ed54a655099fbb6f6e94a31511960f0447d7e94143eea88195291b225d11246000000000000000000000000000000001864c6ad3f2f794239a179647d68734e23b3520b79952bda20acf2f5afe1b76bc18e35b852d35a5cf3b02a3ce86f640700000000000000000000000000000000015ea24562d7bc59d813b77b2a4943f9e98842b5a41c0c7026077a02ddfd3d5fecf352d4399f507fb12ada4ac495ddece9888dd839d9b8c236394c44d358f452a4588ae65d24ffe2bd345fc745de9d37",
+ "Expected": "00000000000000000000000000000000080f0e50f90e001a442965ba7900997fcc89246742590b99add6d90428d3b61516664654bc8fb423f701e85a342a668100000000000000000000000000000000003fa9e84ddd754047649b7cfcf5bd78852abb298b3bbe6575c4c7dbc2e7595499a9f42f379a2463aa74f29e5c73a9040000000000000000000000000000000009e72d3c418726f6400b8cd8b9b649005f3b25ade40cd6f77a0c3cbdbef461e917d4453c9e07ded45301d21df4ec44db0000000000000000000000000000000015a06cac223217602ccfba4f4586cb184994bf08b324bf977dbb3884c394aed0622da7dcf5712970554d73b18e2733c5",
+ "Name": "matter_g2_multiexp_79",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007340f432a5cd5aff1a1d98c6ea1c94be24de2d15a4e112925586c30979e23a5db93643308d3299e370b1f26bdd09eac00000000000000000000000000000000155027caae88381a60af71b2fa770e58efccfbb7642f5ef6b1591bf77e415eb117ab564aff8d9ebcd576f813b793ad2c000000000000000000000000000000000f604238d1b28f010ce8e45f2fe61d3ea20b902a4debbabcd54ce0ecd44a9540fe2bfe847178656fef0a5fd7e6d012b3000000000000000000000000000000000d7f503ede395dfa5682aadedc98bfe28d3fbfb52f42ecabc9eebc0e0a6616d3671604709f28255f50b62bee641d2711f812322dc2a7d5faa9e4877638faf8492d84e0f4c4c65ca3aadcb7eafed2106400000000000000000000000000000000176e1f9eac4dab0d253c0ff41b7600437b53a5ac5278d544a9620648e0bc4dc56aff0bda973fd1338f77fa174d8b13b90000000000000000000000000000000012919a18343cc166e2dfb92ff07bbf838779ef0479985bb85b3b82f9d0632b3f7a19d387f725a21729a77c58dd4d1d1d0000000000000000000000000000000017eb269ed75fe0403021ce70505bb60a711c91c551931605bb2a0773fafa07aeb47cdda382c0aa64f40f5e6e0e6bc77d000000000000000000000000000000000bed8ca999a4691646124a140fcc17dec02b74bd28b599c807abcaaff13bff65aff3892897652cd33b4ba5e4cc0198a9c1f6d538c5b4ae15c84581f8fd4c61160ed395816557fde197e1a013ba41ba0f000000000000000000000000000000001344d6902f5fdbb59a4c975847db0191beac284eb17cd92360e59f42cd7796cf2aa282bbd4cb074c4ee10b489ee3f2f60000000000000000000000000000000002158eb3429d0532792532fcceecc404e95a879be68b3685ae94016ca3762438b3320553ab6d5fbda3a0b615a04d996f00000000000000000000000000000000118f6fd8f60edf7088a0b4b49338bfcfc9c38be230460d7516f317b27c07600f504c8cc87acb0c95515c3acdc1b125ce0000000000000000000000000000000014eb422d44ec6931ac9860a6a017a907e8ed76de91bb7557e818dbacb19fb51457a1f45cca91f1d1d75a3567a3375b5cf2f6a4713eb692f7667fba2a3dc35363c3ba163519d95757daddefae11a95853000000000000000000000000000000000f2c72c53fdb1b0cd13a1f20407c64c46e4a0e461778b0e2d48c4f20be7c655c639b38f758fa9199b8395f706df10e7a0000000000000000000000000000000016e6c75cdfbc20c5dbc2dbd1caa66be92911264d407ce3c689ef3ae1dca44dffacb4c0d8a78ac959e47ac5c454f607bc0000000000000000000000000000000011c5d80d52e864b0a46fb48488f497fb85f51ac040c77b1d01336860b972858c0a6e59914112f6cd6c1612c604d26f56000000000000000000000000000000001136aa7eb63d6f85d665d0539975a9a51a9a3f5bd8731910c32130b1ec8b07c39eb42e4f61e7d22bed933d9fce1810581022e50c3fe7b2a65aab79de6d9e47c457d197e145592dd0611b1dc39941513b000000000000000000000000000000001306612f5119d33f177b8804443d14d04c8e059e28f63aa10ac6a1b25975327f378d5d24f0236e05849f07e99af93ae20000000000000000000000000000000017340f8887292264d498f84fce4af83573aa6cf1d57d99d364f2b84e1734fa4f9a1e07ddc81a2135ad5f5e0ed2989585000000000000000000000000000000000f65073250019ea69339379aacbeae7520c1ae10c8912ff827b702bdab2e15404cfc939389587364d811054b7d9f2b350000000000000000000000000000000019742f83ba0c9d36aa1d595fcedc3cdfa6c6f08579e66b8956fb32ac03530114ed4266738c57175e7a10313c8dd42deab80011c7a4aa905d4db6d4f6ae46eac9eb8bb18613d4ac5e5567990d7e8fdd96000000000000000000000000000000000b2513f906db531d052e8e6f1cb8d7d3c41c7ec3158b370268d1de204ed8fe7618b64ae35029d1718153b5bdb8439dd90000000000000000000000000000000001664c367a2d4170f463c90351cb321608e2a49fca6f3258bf10d32c39747084cf9d2c38d5241888aaad97985cb09a450000000000000000000000000000000014de15b86461cda9f1be69f43a9ceadfe7b7d1548a206f3237d93c7c01ee554c4245fb73827ed0ab72b99a62215faeae000000000000000000000000000000000b25e458522be9fbdde4554b1a0d9af157aeb7d3ec1f89185b193c0429125dafa554d7a531ef9502d443a26112b940b8f397789685a736375ead2312874174795586e12b230669a90d072fa636128c7d0000000000000000000000000000000006862c0b0e3d7bc4507bea1df82080745aff21b7549b372085776be2f88aedd4cff00ab8258aa21e63340963bd0d937b0000000000000000000000000000000017199c5ec3a2dbc1f1e8d74648cf8da247e35cb07df22629b3845274d29e473819a31bc344f2a2bd6c790530cfcc0126000000000000000000000000000000000e7fd1ff41d86a02014229c5085c886988dfaddcb60f5c7c81063e8289aba846337d61bdde57e276fe6c65bdfb48751f0000000000000000000000000000000010efa6aaf7650edb0c74d30125e36cb67cffd1c7f57932d92ab4aaf36f8d9245d7c75dc2b3bc8f3f328589b16e26230e28e325fea39d61269c576626984f85ea43cd683b08c3ce111aac0005adda39c5000000000000000000000000000000000935de4b16f5f9c0accee77b5820cf36c24aad9953d40a2409b7e6040f09f85da7d2252843f9f8005316146caae539800000000000000000000000000000000008a8c542111951b32bb0b50f7631f8938d22e298193edffefa3e0f5c861ac8205ea9b865f9420ad74cd22b37c5cb56200000000000000000000000000000000012ddd660879a1f52ae6284e14f2ae6ea381ff3f321458cb76bfa566b04ae19f3793468d0aab652a82671be74332a3b7a0000000000000000000000000000000005eb148c35732f7ababc73861b71fe4ea5e25bcdd675e975fadd0a9e0fc54e175b2e39dcf0323f4a9802a68baecd25df3cfd9bc41303803a0b4edd121b818a126bece309dfee4133aa5314cb8a91d08d000000000000000000000000000000000bc351eebfd3f3c332268055af1655c8729cea44eaae803607198cf747280adc0d3dedba137828834af3e7179ccff4c3000000000000000000000000000000000d8a6cca17e1c6ceace7c0ab1333ba76ed6c3b114bf99ff80127c6a17eb0585bf6fcce871deb7385e9a8896a21c065ba0000000000000000000000000000000013222db97e31e28946adecda10c9ccc9aa9fce33e0aca51d6483d2f0c5bc3f33994ad516215f8333e22167164ef5459500000000000000000000000000000000144d3707b1898d35c65ae2c89b1570971a9494e8bd23df835f565059554eb7b5cb66a6eec890058316aef43d6c6ff55c8e08fed30e422868f37c422d1efdcc93912d55b0a731479af863dca4705e0c5000000000000000000000000000000000138da93a9a4948d41a6fc6d057a217faf5efad863b45ae8eab311360c033362213edb0ff90bad6c95f60b8e1131336e6000000000000000000000000000000000f41766d9b57b3210d315a2b8f90aabe591c1de6037ec79c0d72a283f0ac3094436bb97b82b7ad12ff4f471a41227bb50000000000000000000000000000000009aa4f5b674782b7adce6bf75ad676480f96a58d68dd7ef8d1fa488cfab794f06e7754e9315430189eed265913db8b300000000000000000000000000000000004e2a4a48f02079c0ed50c1daa91b1216af481a982c7aa64d8ba90449ed886cdeddd0cc08f1f8764f7f8c5988fe677f5674ecdf795b48d62f0db0f9cce057fe570d15c78f2eb7a77b66e4895a45804880000000000000000000000000000000019c927bbffd96aeb9342666e1974d30f9dc215e8eca41c24244c63c106331ddad20d64c79faf8c5baa45cd30b561e167000000000000000000000000000000000523f063de96c9b77bfe5c5045a007e155b45dbe68c5f1162884f1d942bb385bd34c2a37e5e67e6dae4a23d600d75d1f000000000000000000000000000000000c221006f5bfc8baf43826258d0588d7c0fc345d68de1add1693bb897959c2cfdbb9c165e82c0c787529cd7be85afbc50000000000000000000000000000000004218e3d52b42a4504611929f94024326f38e78bba2aba105db3ffb4a51f8906b060ce2302e22ded60714d652a234c1f288fc80d07393f629ef2732879332a253b49d26ca7b2bef7cc49ee40530b2b3400000000000000000000000000000000189e5063a36b0edd736bcd9f997f4b08c62d33b27560e2e2b7b40039e7c63b75757f23746e70a330110d975ca683941300000000000000000000000000000000013393485ae494b1f1467cac9a8840c695d619aa1a78c40674038c053f264c1e20481f2005abc7f0545346f5a982d05e0000000000000000000000000000000003f2be501504f4d37e12acdc54b3280671ca0762a063fd3bc04473ed5a051cae3767044c002b7ed1abe88b2143af08750000000000000000000000000000000009d5952af88514996336e1ff19409e3e4eb3079f6dea22f9738f4a331ce842b151e0b842b68cddc10a711afa6d3242b256e69f4ce8fbd8f86f546fd6d129f9760edce7c5e178dffaf987bf565e9bb7e9000000000000000000000000000000000a79444c673e630f46bbc5a9e06e8c023978a78e3c58d72910a04c3733ad873c0d0de61448076b2fd3764cc17d86d94f00000000000000000000000000000000110cfd215d67d4a091578203855fa0e85feb4dfd0076fbfad20bd092fb91b528a4117850955f5fb6568fc5844e17bbfc0000000000000000000000000000000012ece0577512182c50dbb4a485256e705410108d9ba9c8d57780d49e2e25a0f89ed1fe917797b902aafcb8f7d98fe931000000000000000000000000000000000217cf1dffac7ae162181d43ef12e3e88da4840f1573d7ffa271f64d8d54861099be37b644e96e650dc613975d8a00a4ab40e86212189e6f5925df810141c132eab20c123166cd8d3c6f40f5dcf1b1cd0000000000000000000000000000000010bec428b2865aa7c077c168dc28dc549481c6f8367a5b84cbbad661b0225cf0fda3e840d96c4e4efc36c20d48f23d5d000000000000000000000000000000000ded3a1e9e2eded0a11211a217f9355070361f0a5887a7e19c74edc8768000311cb9dd8513977ecfb45416cda0908cca000000000000000000000000000000000b99ffddc79e825f0b73f2d0229d66e51624d854d00bdee5aa7a884dcafa1888963e2a2149db0f6e40ce3c67941a391000000000000000000000000000000000147618970c71965684bdf0d6cbe1de189bd23bddb2b861c9636efdcb7a96dff27bb1ac70485b562e78485a1e8e56531cb96a5b6129c58113bca713e6905c026c0bfdb6d679c203cbe2b256b0a49ecece0000000000000000000000000000000001a402aba8fb28dd37f1be11fca037baa99a6b57188ccab66208a50bb6967dcacd1943cca73e34f6b2e2f72407103a73000000000000000000000000000000000c0bd64d043fa4e3ea566cb84f9139091891231ff500b67e5fd451805f79003f6303352a4f0c236063d60d9088fae88c0000000000000000000000000000000002861fa7d0222711ffcadac86e7b9e7b494f5561c22544bd0876fb6e1b2e680d0f7074c2800312cb233de2412ccbbc8600000000000000000000000000000000015945f0c83e738a17cb1283d08d63ecf12a7272bc62812006ed78254bfc45ca7c42306cb79bb16ed17bea600a4d62b5d9d8147c4453cdeed971242d316e350abead3dd08e93ee54738a4a5aed23affb0000000000000000000000000000000002268793f6872f7715d802c0d96f3b3d850249d8e70aaa97f19793d2c92e7cef384aaac603eb51525c7ceccdd0211fc40000000000000000000000000000000002507d680a2db16746810e966d1ba5547ac98d08c8402aed0859203e6dae0cbd87a9ddcc05119c1ca08fca2fd733882200000000000000000000000000000000192426b6438b2abc7386599afbe09081ed4908fbeb807a65bcb7c6676aa76e5e0c2c87612cd109cb124c73b9c8e0591a0000000000000000000000000000000017f125a2ef5246e7a19e1b2741b31b9224511ffefe63ccfffaef1b7949e88af573e267d6c7617ea97bbaee6d50eef67e1ba8e52986d3bb0421eb53b18ca8c21b9f7e631f16b99ec56748baeb541b32e5",
+ "Expected": "0000000000000000000000000000000018c2f533f464f9768308a56209711cf9b6653e8d38591d782ae2374905f99f75c0d42c63af4b534056c28599a9da874400000000000000000000000000000000071d4d708f00875545f381e164f77183e14faab599e472b2857c15091254ddaf5c2e9df809875336f92ebcf5b7628da500000000000000000000000000000000099b207cf6ed022289c27393c32d0b83aed6c7b57323e746374c1a8e2ade071a5293168e72f7aab82f6c2e39b97b03830000000000000000000000000000000005dada01b4dfb6a52d998210a67ccedc11d6aca2405e0836280e2f7c8fd7c8dd271c815a2e9ea1dba6f1ab0d6e89d756",
+ "Name": "matter_g2_multiexp_80",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000195d3f440857011bf9b764ff270b8ba1d9d13daf48933e49c12ea20d335b58bcbef1353d9698a7e795b4370ee385f12b000000000000000000000000000000000716c151efc6e611b5b15c749eaf02816a86e267428750741b167404a21116f2025d0d07c447b9c7bee8edcc2c7b76d30000000000000000000000000000000012ba0bf62b35327111d09b402db2b75b2e835cbe581638af2fdd6d06034774533e6501be3de84e7075e4184e11fd81a8000000000000000000000000000000000329b14859d004c146047b03870371f53936e078ddc69294ff1fd6f42cf2a354a921e5f2e5c125c454e20af97dcf769e7d39b55aadd47afa3cd35cb85a89e729ca236ada965b99f64ab302a84952babd00000000000000000000000000000000042286dd205ac86fdec3fee779059e2ad59adb62505f7b78606c128244b031c53dc40ebc2f5afdba348892d5ef4c10e7000000000000000000000000000000000f960010d4818846b3a0291c6fe1aa53bf0eafbc0e0968e3ee82324452a7c1a8041c06b4db9cd36a07c119c9fd2f9038000000000000000000000000000000001876da0dca72869708b8ff9ea0b74ad6be25ba82ccc76660246413a04344f2b72e5a7f6fddb58e9dc0bfaa6b33a5fadf000000000000000000000000000000001538ad1673f117493d998941d9356fb9907f70c279bde8ae8813b9c7b371344456f8e67cf02bf3401ee06d55604cadf9c41ece17a6d8b4a22994227b37a9d73e17a88859683afd5d226e113246e70cb1000000000000000000000000000000000d91319b4a5e047ffc8a68e10c34b2b90e7f3f08f9e3ec53ed12bba5f66c168c20c6583ba2016f0137caed834845f7470000000000000000000000000000000018d5542919674d2fc32430175405d806ae4abe3e1236df2188bf4c9ddf66c0974036e28414890212ff8dad244d11e3c700000000000000000000000000000000160b128f1ffeb97edf0e62dff85e3f90fa48567ab777a7937a2c0e4659df180fae4565107c2236a5f2808e42a03a4ab40000000000000000000000000000000003ee74d214ec491331fb9db8243e75570daba9feb587671496cea4b480d80ee162c6294c082203534bee450c384f645e69700dfa3b6e5fba735d1fec3b3adc90719ec301c406ac40673f4e5677da3227000000000000000000000000000000001951afa33800a366944c43bb42b8c5c8beb9ea2e1cead8b84e0f94af51e4a156d9454c0f08d1b13c692c41cc480fdefb00000000000000000000000000000000077f4543fadad6f2f8ae8d5d98f64965bf9626971e7efef5221cb4d95d51b8764324cf4a11d0ff5330d58df70cb79d92000000000000000000000000000000000417251cd0c1b32505377e51bb30ac8a8a3c059644b9ddb5a058b3c6e1110e1c71ee19f549b15090144dcf4668d0d50100000000000000000000000000000000052133be345adc562238c4ecbaf76ca4159fc11ff563ab393317b03065ab668e7df401831baf7027f0577f5791b1ca3019e8eed297661c06c92075629e163e80a08835254f7af8c0f179400be114ba7b00000000000000000000000000000000067bd52b7a3193d31a4f1ffb76432c8d4108442616f17056d310fbfee2ffaade9437e2bdb8425cf83233f0c632efc1170000000000000000000000000000000011b045d6eebe1bc8218b696b5e81e78db78eadf1b5d987060c1bdd73aa65666f77e1d6bb6f3d939d64cb3e6bda08994c0000000000000000000000000000000016eb5ea5067413b72632f5300efbe0d01a284b2a59b68d0333c269da9302bf0f0cdc923acb27e51bbbbc1d4086e6b06a000000000000000000000000000000000ff37b8812963d9efaa1e6deb5cfd34eec70620fdb65808739295a819e03ebcc8f501b8194d0b3c72717fc922b785194199ca6fb7f6df8a2e72971c5738ad75d84935e922587acf3a6b6debf3c37bb5e00000000000000000000000000000000149b5e0df255281c1b518427094cc0903fe89eac9a6dcdc379b8ca30f3696d89824c201601fc4b0795a3c859a82893170000000000000000000000000000000016ee9e7d957f439d078f3c5da98d114a1b5bc4da9c17e117e1f540dcbf83a349bba94def4b87b63247f190e3b5813cb00000000000000000000000000000000005d4f56bea105be4bf1fcaf4f25df30f85968d59e60b1c438c28ea0f480851f5ab9c05a7ca6677e6f12c7dd3ed67c2e0000000000000000000000000000000000dc0e87ca5a8b339b485ff3da2b9854a07e9663c43344dfb5ecf3ea055eadf67405c43013e15367fbaa55f1bd8e222f98159c6b98bce6ed31c30957280d8f7820e9376093d1ec9ac68ce0777d02b084b000000000000000000000000000000000b0575fe2adc9ad66209cb2191efc2946672e4e81b96d50493d2125d9c83165f0c4d3f714539eecef9de0706cc20da9b000000000000000000000000000000001511649f0cb6b86111d2830812231ad37df5500d7ce1086241591dc3cf40b30f1c53dda3133b2f7fff253c94d5eb98720000000000000000000000000000000005b15e4e32f4f4e46c1560792a9973f6ad63f5176694734f379375f16a08c162a4a820385d3ea6c191bd87fea4f5c8cb00000000000000000000000000000000089218403fef08dcc6e679b49a74557dafed3278d41ff36a9801db091b91de0d46d779a40574fa4a3f2baaa1a14be098ef1bc580e0b52b10b049f07d5115a60ba96d14a39e48ddee3c219f11c3b2a82a0000000000000000000000000000000001c35a3fdea92b28c9ab4bd9ea592b998853a73be844b9dcb500ed6704bbf3ca4ed4216dc24b50254b6ca75c4ca3e7fc000000000000000000000000000000001815292d2a365dd7f41ecf3f9a89e040bab717241cefb3155a097eb9885d64fa55f5de7023f2ecfd33f483ff304666520000000000000000000000000000000013df522c72805b890aef97864ec6769f569504fca2d6a6beae97f80dc92643f8014daf3dafc0040dd7b985c0d9b2c462000000000000000000000000000000001155ad4373a8304fa6301cf48b4ace135d6a0c08cb06d624f42f88073e43612ced3cc37235422171b43af2b4ebbd5662d06f6ed682c56611fd060ed2b3b1dc48974769ed6dc504ca3e0b9f68b77e63c5000000000000000000000000000000000bb9afedf7417ca31beb96486b024af13c06007585d785efd1e78444daa9bc3c03e1d64b560e8d6a18ccf77a8c3c8d05000000000000000000000000000000001652d3adcf1612e487a9ca198801afb9ec30267148502684c2b91c05ebf6c48e2ce33f9c0a986daab81d5359ec1b503c000000000000000000000000000000000baf3d34bf4a78e3b9dfa637c6392c7f4d7ad0ec315d10748784b5b60221bd9da0f4b75c57c139ac2db329e270d559de0000000000000000000000000000000000c30e553fa2324d552bdbc7d2dc86531340c4894495ee9a38b64f5bb6f92314021a2a00c4bcd8837e55a0ae2676a9b761d7b314ae9d9e78f628ec5a207d12e2dcb690688d256fe46e0affdfcc9775ae00000000000000000000000000000000159a1e4e87c35aaaeacdf21efbf8ed99fd6a2ddd7e990c12407b1417edaf185b8f1df9bafbddfaf3d581b5d97d7718300000000000000000000000000000000012239ef7b1e1009c81098aa4aaad8ee9e003530db5afd49867aec47f46d5e29d44b5e62d80d9e832937a299633e863c80000000000000000000000000000000016af6f74392461a9294d9f848508651ca5c0cb50494ee7c6a334bd770580b924a17beb7824b489e7e101ccd50aa0d5cf000000000000000000000000000000001912a0f54ba4fbecaa55c150ae93455e1db6b238c032fa7992bc8456f183c09b6005dd6398a77ab91cf547919ce7485b03a0c47621401fc20d2c78f7e30814de9a6f838d4328a5b5be628b833c31a6fd000000000000000000000000000000000cf1cf7a09a12f51d10059425042ef8e140718ff11d2f17897a0156034f73ed29496d93b8695cdf609280d319c9bb742000000000000000000000000000000000b2c4d26fa1eb72eed1a24f27229d2675e0c6f91e3a4eba7d34b0fc1bf5a9b4eb49c3492d9586669abaf25a656e1f95d0000000000000000000000000000000012c5c83a03087b2449b71e9037591fa265d710ff6d869bfa18ac37cbdcc93024f673128db3dbad9e3517501af12f2540000000000000000000000000000000000ffe5824245e43953e3d0adcd5fdc1a97ffc87f8c5473fdb0fed57000fd126a9925ba7415c698248c51c1f3e12b270d5e4ac6a5e740e073c5ef8af389e70c2cb8ee8c4c04c2ab4c48c579e83e181005b00000000000000000000000000000000036aa888e40882b2d6ac71d66c88543e32b4a0a7c959eec560e3d26114d8aeca63fd87dcbb3171622c989a6c7a204ac60000000000000000000000000000000006a5e552e6d2dc95ab8636a8be16bc79572b47860bb88934bf04c195ec01fd71eb91e45f24c58bc2812ed5fa10c8dd7d0000000000000000000000000000000015fa3ffcbd4e562a4bc29975cf8c1eedf442e37374fc87128e6f68bcdf6e996f6f054e0b8c608e651753de96655b2c100000000000000000000000000000000019bba7c0b170dfc1f8fdbf7a2e09ca0c4027a6aa6930d15dc2772a0f20e5e56f0d11644094dc866595f801ba5552e6c4c1e20d8003fec60f68c03942185fed934ebc197c2863174442d1a1c8d1424d31000000000000000000000000000000000341f46ec06a8def4f044328bcdaa308798469c767d10e5db34b0ffb6f550421c67c6fab7b63cbc7504e55847cee419e0000000000000000000000000000000006952e5f791c37dfebcfe69cdef196dff66563b29e94927e3ab34365773b93e72251a63af4ff294af88d45fe0899a2c3000000000000000000000000000000000874dfe75b31450e99dea063c090e32d24fbff9b681b64a9dca5f967f82003005b003d17eb869bd3b37d4a412bcb28fb0000000000000000000000000000000014203b69e8af4e25232777f503d5e82d6121256fafdff1b037f65d5aaad0f09ce882151d6bb4705328400f00089dcc7a7713ea72a2ee99442232472ab3dea9307a02fa1279129d994af5588af4fe7af4000000000000000000000000000000001403fa3f418107e0bf7f3f4bfcf621812d32b1b744ab5a4c37b5cf946a5e5dabd675c2b70bd355590a9883436c5e32dd00000000000000000000000000000000069e006f168bed4439fb46db9ba4f279f72ed608c12a05eed172608693f42cb1f04aaa54191f4b0b35f967bf03d0e63b0000000000000000000000000000000003f9ce029f6fe605802de64701ccdf52bf4aa299400a6e1c36f5a1f9173bc11a38e7628f123fdcae01d2b260f77c577c0000000000000000000000000000000009c9732809f60635115cb479c80457c6cd8dad092111d663c0cda0da1fa71c9bd6795ad013d2efaa4599c8ac5c88e5f26f128420cf6ab4616a05b287191105f25c7212f2c39c3230fa56bc27cd06ebfd00000000000000000000000000000000115e08d8e4dff7adcfe46a416625be0ac26ea2d7900f5fed497809a6d46e7faa5b47c52ab3bbeb9fb16d82b549707ed6000000000000000000000000000000000dd1b31446e44f64ea5046dca5174ae854f6bb5d95886fb95aa136d432f1a8c03ef1a5f9320f89c82f764049a7f678a40000000000000000000000000000000014879783c07e6986cd393fa1e0ca8a7e23b2c9efa595229fc0b6a11b9c232ba33e92962a1087fe2ba0532d7b541827900000000000000000000000000000000013dc6e2bdb2801333e7f914b99f30b40125fa1ebd49b141d88a8c090b15ec3250a13812a19c3c0751a4e5ed100a6f0ba12bacb3419c34369dbfd1c968334f76bc50885028758a975cc812a04e6feabd6000000000000000000000000000000000a2cceef36ec78dc702b6731dbaf8cea1dc2b41fee1b235673c6941729bc5631e69ff37900479391a4d10b300fbf3eb40000000000000000000000000000000002f4881fd626f4ac434bc1e59716e5e5ee14dcb9adca4d639ebc9d86e323d274ad8ec0a4b1e6ff92e1fe7928d48924b000000000000000000000000000000000174cac80e7bc63989f58759e123513b611e9849b44d43a362f2eb84421ad008f3ae9e9f0f233e49fc8e10c1824ba948200000000000000000000000000000000143641099c8a6c8153dc8ce74debe795dd6c4487e8234f164f9f8dcdea6a53619c04a8fac215421f985557b5b956c20a5b00f26af6f59620c7130a6d12cf2091b5f52a6b638484fc1f242dc1773be256",
+ "Expected": "0000000000000000000000000000000009807ffe8fa881b235b1181d2d3f147dbe21042524fb0c0b4c90fb122d160c7b895034ab32e20324dfca564ca6e3183c0000000000000000000000000000000010f6da88525da3e86ee56cd5514a436e3ce4128e437a876be130a70c42444a05ac269326c84dca532ca2e546860027c00000000000000000000000000000000011396a7317918841ba171ea46bbddc9bb5a08db7c82b90008c6982b4b79a4dafc151081bbdb7b9fb79784e603e15eb9e00000000000000000000000000000000070b8580f303b83c643a484dd031b780ff4ca2ec805d8c538a0b0c791cc7f8163654f5e5a41776a8681500a6690e24a4",
+ "Name": "matter_g2_multiexp_81",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f38906bd058e4d32403fc3d39fa57bf49c0da65ef42fb129332b91c184185de4f9f0bfe8908a44833ff4ac4d65b88180000000000000000000000000000000014ea6fffa6dc462463c15feace841697698bc521f608ed0d16be5097bf42aefcd1f73182f37b6279f989e9668a8076d1000000000000000000000000000000000f56d296323177ce53c6977fb60e445278e59ed1cf92e3f68c570eb7a9e5f8afbec5e2ef64674bbb54d7016c829f72750000000000000000000000000000000001b29012ff3460cbe4a07bdc65885718f217cf177866823a7cbeae18bda67f65913ea20bb69e0ffb31bd82f19862113dacc5a8ec806f2f273120457865582b08697904a2c6510bfe9ea21eaf682fa4fd000000000000000000000000000000000a4126bff91ada057ceb9a75d577120c7ac8c9ba62151602414364cf88a3e12dfac90b5590db3e40c16163177ad4e7520000000000000000000000000000000004a3768d326c4ebcd5ffed89341e8d04f89e674f3f2aded3205a7193e11c20115b3c4d595b959d6e39a03d76f6b5925b0000000000000000000000000000000006e0ae4a9c45bb69c3a1c65e26e4869f2eb18fefe584e4598ba99c0044e8d911145a5db3f57194ceb6201e7eab9a81b20000000000000000000000000000000005be2ba6b147f3f2052c4877c90ca364427c6721ab64dd35e89f14f3179564d8812b9013e3e3db22f69afd739229682b98c15a259b4dbb8c300a39f0af558a9827112f6b4c5eae3d43bbfe057eb113cf0000000000000000000000000000000004c36cf955fc81bdba4ea8d2ecf934adaa57fa4073199f77bd0428d3ef80a7d7102179d4a44ef0de887bcb3ae915408900000000000000000000000000000000138bd3ec7a1b6fb65d1df6bc1d2ada35aa52b06729c10b5d45b9bb7cbbdf41677942b99eb9c2d32e3e73da7d5f9cfed40000000000000000000000000000000000b0291ca10245e2f7a963fa07ec62b15f6bf9e7a5a7839840ebcbe538dfecaf2114c7864a16564a5b3c85c15d97fb7a000000000000000000000000000000000b436e912b8a71cf8050d10d59017eca6e494e5440f02d2816924ac9cc2034bedb1cce6eff5c42f3dc57a74cf1b51cc0a0e68bdc97fd642581f7e62ecf134df2c05570713c96fa733d3db96ace88f0f0000000000000000000000000000000000c105ac7475ed9517a0b07f25a030a5616952d817f3893181e352907c7cf4ec9f5f3006e37b1da97e9cae4a1213584e20000000000000000000000000000000002c112c18268934823d5946d2322d0faec497d8e18736da91d2af744d90f74136c49370a4b43952152c62820d25e52ee000000000000000000000000000000000fe2818a397d70543e752e7022f12bab10f1b1289cee61a0230d545296ec872e34d8df6edf7ce9980f3c153e6e51d96d000000000000000000000000000000000f479e6a52bfaab3a31aa9a461adbec8a390daa8eb6273f9e425eeed764a6dbad44d12778bb888aa5808df272edde401e5512cac411cd103fcd7497fdf47d1221999bcecdba30467f06ec356483484fe00000000000000000000000000000000016106cb42ffc41d5b23bc5b06001473bdfe556d375fac6a0cb0a12494e9c02ca2dd6133356846e1759a2c485faf5e890000000000000000000000000000000003cec25b0f5d1db0ead5319d6dd15517657d1fec442facda4335ae0bbeff606fa9caa6a4c00445001180aaeef895d7fd0000000000000000000000000000000016ce3573fbe27a8d23b3ebd22aec989d61fbd0e41a519c5e2f1d650f2ad73adcfc8c840fb12bce83b722a0cc69164e21000000000000000000000000000000001434d13d44fd8dcf776c2a045734dff7c09ded31c9e3a4b5e765cf26fbfea4cbb4ac15c06599012a7f2cd572bfafd78ba32f6861298bcfd4668653544b4551d7357d64f733365a5f08ebf297a09fd4ca0000000000000000000000000000000019923ffba0d08ebf1bd43393142d61022430356081c18e37804172082c7ace987ece2594f4852e84604a77235c7795e000000000000000000000000000000000123acf9e1a86846ae27d5fc0358afa34fe9d6b68232c9ebf2d47cc169779c4bd24f225ad30886fdf68166adfd9898abf000000000000000000000000000000000a6061d4cef29d1e3535d54a2e36373e2c16f91543f53e1aca94c4abdabc663049673f2327ea8bb574244d7f5c99e981000000000000000000000000000000000b1f3e1d43575a74584ec7a3280f8b7196f9b99b5e911ed33ba6bde1188c82d906f0f8e6fc2b285fefa0ce59116e449524301fc5c3ab842d7f6a278fcd32249f1daf86a31dd254ab9a21941fffca98a1000000000000000000000000000000000373d36dd0fac76a0fc46ba5da279ca3be5a1f8d799570004e429256787110d4fb746f65a8527d0ba681a81b9980bd5c00000000000000000000000000000000057933c2b3e482ae026159211c4742264f7e890efbaeb6e14f3bf66c80923289af095dc97b751a117e181ef917d049b000000000000000000000000000000000068816ad2369bb57b3430c657284858d3736c327284e7410b61ed444786bcb34a66db9c16aca583aa9722aa8d7975b440000000000000000000000000000000007fcd7dbc062d28f6ef906f6a455337e517e1d6e6c02c7c0b2b2685b79f56ca3436c1bfa0ab96e4a5eb0c2e2c321c0dc17a920aef58100de67c482ae1fabf7ec87cf3447bde1e19d9aaff825695706740000000000000000000000000000000007bb0ab060cc12002e043724c0fd0c8bad30e08b65ba9f2fe5d09d18cac4bb2d50e29ee14590ca7bfc505f3ee3d4f93d000000000000000000000000000000000e680653d29eb5d90f21802f543eac3102a1de6d2a5bc943a53dd9b80bdcaa6951ced2eae5e2a25448b40468f1923ebc000000000000000000000000000000000b7494b494019e3ef36d5c620ac56483fc6b1c8fe5c6f67537b19f56ef01db327812095fdf805d3dfe678a3ed8bb6226000000000000000000000000000000000291e5b98ecaf7aef0374647d28fb9f8785a64d9165de407d062403047da14d4ecd19fad8575070b278608e16b71d387d76d5eebc3d099448ce4a8ea6dec047b0f062c6361ddb9e95ec898442423a31800000000000000000000000000000000186536e3ae3edd9cc6bc24fda6589ed26e72e06121e97e1ead65b200fa0578c6e53d1154dc7b14e7eccc3a53237685060000000000000000000000000000000012fefaf6c76ae7197b99571e41a19b14846fc4499e8e964ff750e7c3ffef6ab3dc19eeb42c5f6ba44a573bca7a15166b000000000000000000000000000000000a135db813a44a21174cea3a0b34fb49f273877203ccb66bce44b2b58794818d8bc1df27544ecbf780823467e2e4ee6b0000000000000000000000000000000009b08f70cdf4e349e1a73935de9fb2ad9f4feb8cf5f835be78383fda2af94d81af253ebce08cef825764151d5713ae60cd4cc1453dec7ae335db989886fc0964ee73e12bab69ce1f1458d1416471176a0000000000000000000000000000000007976df2d47c14374e554401c4d3330bbf6f1e6b8fafcea1e1974af61e8ebf493dc0473d34b30b0b1cbee082550d85c200000000000000000000000000000000177cd64db8334dccb17fb207e467e5b09e891b05df7658d9b439e3cb72bf3e0a70e84f96fb5e448f33c003c279cb38d800000000000000000000000000000000094d739a02b8ea6ff8113019597f41df4728b270770edc5e68b1f5c32775f0c706e3f31c0a82059c1ee150b89097376a0000000000000000000000000000000006ed888aa4bdbee94ec67500e30d654071774fe22464dd5b900fdc17b445754293504b10d044aac8fa0c289f0b2d9dce6d207c08e51d64a9a47f5353faac77fbb184e1123d38e39bbada85534cbcd3150000000000000000000000000000000014a16b856b04ac4b687c79f2b4e1dd6d45db25b382e0ba6687afac648c9b6384cdcfa89812f1a726bb4d1c22ebaa6668000000000000000000000000000000000764088e337df6db30ce8aa23aefd91d9e35be911c9e89ac62a1e06c3d06e28efac256490400fac4490f595cd03c127e000000000000000000000000000000000894856fa1c8488fce182a9c7749f7953e6a73879b6e743fdb8c780275447122f512806fa83d5ad528f8f61598ed01d20000000000000000000000000000000002b33bfd09e0ff452c3336bde08df0102162488bc83c27052447a1e5d16c9c68bc529f96ee3787a26d2009f22a1246342e1910b704d39b6a64cc7a44e44ba3e8b7e64ddfa90dfa6b5ef571f9ff7d7f0b00000000000000000000000000000000133e2d092352d3ecef5b67a09c2be268fcd4fe1f7360a8ce3ef5f33bf689242961a140d9c8afcc1e2fab3ad4e3dba49d00000000000000000000000000000000101eb285f0c462a22406846d82ca6a278520b65132d2008b124f6647a642c221b0c3bbd4a0abe8af7417e7aefb81b5b20000000000000000000000000000000010958cbc317f1186aab69ac24be87647b8013b678b0eabc6270167bdc9c0cefbaf4d9a34dc41524b709f1b881e6bfa34000000000000000000000000000000000d92c47257fd0c4d6baa4c81efe65852840479b9bfda5cc06b253f167069ca7367924c0c67d6497a1e9abcce7d0ce9502eda0eb154d5f9b0e25a828c6f77541701004cd0293c61ae4d36aa3038d0f1840000000000000000000000000000000014ad0f935ba129b47ecaad63b9dda44e7ef7933f182a0f5226141c8f0ede026ca2f11db7f4924b5c582461688dad6359000000000000000000000000000000001453716381f13bf6ebf8fff2ed7bcb90f7beb44269008af5880a355dd03de5c84c14f5aaf69fda043b422aab0c694784000000000000000000000000000000000e983c9e9b799eccfdb56444d31948067d46adf275d7f39a70aaa8bfd0fe1b83632c23d87f4e993c8191901e9a607217000000000000000000000000000000000267c8b8c5e09b59277736caad12ec6986f206d1c1f48023356d8bc877a594c8bbd98981cec6382bf9bdb9a5fa38275ecaf6dcd51a851eb200c7f5fc3e106ac5ffc432f756b942b1b9a5dde31cb2a3760000000000000000000000000000000002e28c245e71a7f6206427ee512f3250612785ce29b369682fbf767d06ac08f91de8ac9f82951574cce46cee1aa757720000000000000000000000000000000019b0dc35eacd961e0ca7d54a0e37c4ace37eb0200d5489316f3371412717c57c8f17c1379721f4dd67b3fde24f50d4cd0000000000000000000000000000000013b9741f7a32e5e5b1ae5400e32dd6fcc1fd43b68df54ade57c934720b1289a51deae77b1726e1955b6430f37928e2bf000000000000000000000000000000000693980b347ed7ee6cd93f565c87efb36fb304d7e9ae24e2b9f902bfc962b6c7fbab93287147f5ac892db2a709c9ab42106d4a893a68b7fcb8be96faedef65181c239dc2cd752c85ae7800ca84fc2dfd000000000000000000000000000000000ad6b7cfc6cefa5783093b7d700360b354d0698d27ecefb7d5928ac5bd6c299e4001474d205cf3b85a32c600ddaf1a360000000000000000000000000000000017172c3d5acf59b70b340fc703e9b7801aeb4857ffbe7a9d5daa0f32ad80d1c0ef2f0b3b7d1fd83a757c076872425fc7000000000000000000000000000000001291f55fa7d14b14c578d57178cc707cabcdc4bfb444cecabda271cbfba2ab361947d045ed46d9edbd215fa4c8164e56000000000000000000000000000000000f64ed6c989eec5222239d888d08dfd638a0e35eff2266410dab0498941fcd1683654064107fb7e53b8c02fbe98a25622b9e1cfbf140f4a3b1d06be656ad6ee5169a9cfa7cbe6efbf8173843d406acd30000000000000000000000000000000001d25b5bfcedc6d7ff7e9fcf729f858759936235d23ad45b14dfd0229bf3e50fc68799d19ef019b36728285bf7ecd0b4000000000000000000000000000000000326e300ba07935e0233a03ac891f18dc7b5a9ad9a28264136228e9e23e8f2aa31b7f5e5f3cb3354984f57a868a5d00c000000000000000000000000000000000dc92060e3403df3a92b15ba3e437ef0c403fcfc9c3545e544a78874e5d9b5e63b9ba6060c29022fe2594c2e6fbb6a840000000000000000000000000000000006a01e85f59dc45b1501309a350137d71147c30fb70da6b7637a9b1dd884aeb7e554215474784ecd3bef18d15d2c0524dbc68f77d40330ad5b8cfcda42edf57899454571c6c6465c4107e662a269aeb5",
+ "Expected": "000000000000000000000000000000000b7fc0b44723ff0d1cb7c43e470d4d432fc4bbc7f9d98ddb3d91434a5574956fdf15f898e579236426ea44677998665d00000000000000000000000000000000176586b6f157e408138391e3767d0c1c8457857f4cfae571267ed64ac86ff8a4b61a28b406e1caecffaae6a399f4ec9c000000000000000000000000000000000a420992f850db20d4f7d2ddff33e4dc79bc0c39caee533920c5d03d1c2619d8ced769ac09f664c0921829bd7edb446b0000000000000000000000000000000017e4000f4d03a6707174c3adb74966896bcc0eaabf4ff83cce92a666fbd13b59efa2c767442062b6c8b1a3abd604f0ac",
+ "Name": "matter_g2_multiexp_82",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016ac5146ffc26d1f0c33645931bddfb84756e1c7b03f4838467d1b6701ee9478ae03c910b6b4f5c14135487bd2c14bf8000000000000000000000000000000000e1d082f16e4d5c5f0b6fbe5178aef6f781a6fb165f775cf0cd4dd55f2b498a79edf373007113dcdf6b977a87e1fded2000000000000000000000000000000000bb94be280df1aed761651c0292f88037d172b675bae1933ec12323b947023b437d080aac9e196fe5e06e5c4137284d200000000000000000000000000000000064190f9725bfd5d56c31aef7fd1590c975e2ce549fa6d5c71b254851149e0a0dab0b9de3acfc2d64231c79bc0ebaa37ebb3c942d3a1a15cee806fdb0fc3635483743a5b0ee9c40a48700bad5da53ae70000000000000000000000000000000012199d02d3f1bd8c4005878c3302e6a731ea69d69accdd690b4667e847b079563d32e18eb7a440b8005ca936da5e73cf00000000000000000000000000000000125b0dbdb0058639513b007a84d3a3e6302f5d846f22f99a55181f097e200981d9013c00d688a11eb976120f1a5da64200000000000000000000000000000000081e723506635433528fe4a40fe4ecb8a9c3d8cd701c043c0418d149951651e21632cd85f03db33b89efadd69e009ebe000000000000000000000000000000000956af2e67f8ae676abc783c4ec9f85c50ea130410cee8216fe036cd0521b8ea38966288afe7d35c28b30f7ca5c6edc0c193d751c4f24f4808621979f07f03b2eabba75f08bb49682b9df2da7a85a7730000000000000000000000000000000003e11a4e9dfe82cb495e9e698b16c257ea3f4ecb24749751e7334e0f31fbd6677545e4bf9ff78a82853560f7e7ba2ae2000000000000000000000000000000000caea2c527cb3aeae427e92fc364365b1f55e7128a544009be2ff7a5236d1cf8ffd5a5cefc87820bff5bdf1c6bfa165d00000000000000000000000000000000064a3186774da8bb5d013debf46ccb0d894592c414f32de6f77da47f4d42b0c8a13a2ba4f14b9883d564fd8ff6a4c90200000000000000000000000000000000072f6c48b6a05039e3a4dfc6b73501d6d4ca7e840b119da9c074bd4cd2adf4f2c6e9e6325ebf6f97c3f0b00e6b9bfac6dee4eef524f133183b4af95e4445f3ee5084b96c32e284ebebc5b87f3d76150b0000000000000000000000000000000019ddf708ab31f6f6f725f0e4f65d11248d3a79af30927a6f2673901fef9819b189502cb952bd4742d2b8e84acebb5196000000000000000000000000000000000d928535c47eafa5da4ce4f91467fc31aff8b86b850e4582a597b334491b14da71763f9aedb15ed32856382069c094ce0000000000000000000000000000000004d6b3545d067aa0768cda9dc3cca0f58eb546345b96f7d6b9355d47770e00286d962a6b3a64ca2ce22fdb4834a4bb6e000000000000000000000000000000000f4ef9366d342b309076299816c1ed9b424b68886a5c69e21e785f97cb0f99ae3a99ff6b5244dab817094449048a7552da514f21c8eab0edb2405e673297bb595edc21027890ad680f1663fd960ce478000000000000000000000000000000000236c5b4c57ee4facec5d4ff37a478c505217af66e029c3382613442c58875c75cb423789f6703ff3c1c0d80991c9e3a0000000000000000000000000000000016c052de3336002f362d9b0cb386b800860527e0fe81a1a6df0ccde31f3265e6246191b3febd1ea48e9391c44593ab0700000000000000000000000000000000078dcb04ca93c676a9a924e59f924d9d3af872849bc30ca633d4025aecd981ba12e626337635ea77886a45f4da84104f00000000000000000000000000000000027df6394b195222bb8357bd684088e3e2a398f0fb0cb812ca5dcdcd1fa1279cfd03db62e0f8b2800d4b8b48238931656aeac9a669c962817c01069cffbd948d9d8ce764e92859f31fdaf85f5aefab77000000000000000000000000000000000485ce58b387083172102145fdb3e26c6ffca8b35af0e1d84ce9cbd89055be083bddd3da56443924049a056fdb2ef092000000000000000000000000000000000d998b234a69d584c78ed054b1322ceb33f73cafb5b23c1703a9fd609edcabd44f1a642802b9c0b6fde6a6828b50c1200000000000000000000000000000000019235ff13567bd007d77e4dfab139cd57dbb309a3cf6a6198a548c4e6915778094ddf2b05a91f5478169757bf5a56cb300000000000000000000000000000000110f6ea19a7f62bc3e78f4c5c1c6d3efdf1a7f563576e758218b2c363fff8ad8fab0e72431619e4ebc93d2d739fc786c40273bda92c9b1b677edd905d76d75875e5b77841befb2bcaf1fca7674dffd5a0000000000000000000000000000000001d45da76e3016c00fe65bb50f7067e4f06364ad8348184831c4932ea0e0f3a170ab5147e4670ee1b16924105b6fdb6f000000000000000000000000000000000b3468206db0613369b2b0750c98da65b660fc07c30cab4e459c311dab683b6b313b99ec0fbe92ba07f8aab43a12a2c9000000000000000000000000000000000f58a57c449a41105837d5e2419a34201cc921ec77408d6c0c7a2eb227be98ec1f6f6eb9fc088daa0d4c78928a1eacda000000000000000000000000000000000ba53b872dcb9fcabf35e673b467523ea77accfc1b38a5f92d7b9d269c28aa00d00b08d70eae6ed4d2e82bdb06008f9ab77e16276f9464fa2063230d6c1a4152553536c610062f18565c030e80b5cb540000000000000000000000000000000002b82e2b582b247271543117b939fd17ba8bdd617a223873296f7bd75de4790f0d5d8fe523792bc7fb4764d3739669d80000000000000000000000000000000006eb554347efc5f2ee79949bafc012e6d9964ce19459b3867865709d903fe3d11bc617f30f6279a9e62ea104565953600000000000000000000000000000000006a543fe5cfbae629fd3256575e3eb4e0b65864aad6c7f359e169038bf090ed9bd92fef32fe1ac20b2a8c90fbb6081690000000000000000000000000000000013ee42b0693b2f3b9b977fbae5c856e9e4c5e70120b5c29e0a9f898f6d04b7fe351e17b02716a44febcf0a00a9cdd9220be15b654ce22ae4e32987babc4863ffe2bd8a459d0f01f68fe84a75326889900000000000000000000000000000000001ae7368f84e354e5758554aa9c72ab4b00a644cfb9a4ecba38dc72227d297749bbc98c8f5d6149143b31442359d8013000000000000000000000000000000000abf087f77c79cb8c69e4289fae87b2ed483442daec3851a5ba32c43e342be29433b2deac6dbfa7a787547a7361ed0a00000000000000000000000000000000000fa01cff7aea64b649951a8d85fef0bd475f31e47c706b96ee2753df9987508b5e5456cc49e88ec3aad720a2535f6940000000000000000000000000000000018874d020e2eec0e286dce324b91f15b2a4f293d32956b27524f478983f0e0c5b43df802b60f4f001753f12d449cd821c8f1fe94bce21966427380b6d357a3599e9db03a7694159335ffba26fe29e4650000000000000000000000000000000018f7d19362e2cba91023455e115cd90f02aeafcb026349393ca4105e270ab1cf589621b40965fdc9795f66ea0f6a053100000000000000000000000000000000170ce0eb304e0e1047617b709c834b67a8989212e5bf1cbd5a33242be94bb141d5366e636c01a229943bead9a7baf43900000000000000000000000000000000077a17356b3b31faf90f709042938b9e901817f7379b7bd486d18e47d22b0430ba70fb3006e9afa67d7dac71ffaf152400000000000000000000000000000000064aca92c41561e195fa8239800c97d5242ff0f8ce76b0d119063e2ffa09c26e01d23d5728765a59bb9587e885450ad1c6d34471ed00035a484f97f4e8123d40ca23b017b94df65540a5551b905e57b3000000000000000000000000000000000876a57dc24ad58416f910ee3ce220630a1297e6bc691c908e6cc16f975b146872d71661bbb869361623c61670627eb0000000000000000000000000000000000760fc65097d215ab9aeb3d5a5153977e1e399e2cc0b0cb9befb0266d98ac13512a0eadaba4e051bf56794621c551ec60000000000000000000000000000000003c8e205e53075a96c14ec26345c75881a0d67c7ce0d62d73c83dc353cd7b555cde52ffc5659ab0db2179a899f0fd694000000000000000000000000000000000d7e8a7fe6b751f7f478698f4f0d30cd0a435a2295a958cabedf4668769819b4cbd4e8b7721eeb5ced3f913156abcaaff3abd467168bf5e57f71017b5779bdd400dbf416f34f105fe747ea2f8cf4a21000000000000000000000000000000000180546f697349adb2918129f4d0a979bb114d1b58e5baa6cc221a09d7083469bfaa61f80f1e3a6ccde0da54b24d59db70000000000000000000000000000000004074338380e3d7c0facbbc71d83e78b53191af9ba13ba0cba6015bf4f28e4b0b52ffb34c7867a335848f57b5ce5ef5200000000000000000000000000000000148a800ec38cfc2386497d9aacb4327d5953a6612cd4067ac13fb977046688e80032125d4b0e7cb49913e489796a50ea00000000000000000000000000000000132438d18d942e6dd3f69d117abf83c2fa18418e5145cc43b3cb8d18c873935e41279a9e13596f2863be7aeae9b73d172809801eb18d38a61ef8a80f13086d6b1f85ba751cdb8d17fbb9ad5f8d0f835c0000000000000000000000000000000018b3102ce91af86cd10162d3a43e488a0d7b7807dfb9624c3cae76f342e86f8ef1200444a57e2ed7f819828357a6dfe80000000000000000000000000000000017137b470f3c8d1a03e7252e18f4466c9ff809408cbb2043d6b226ae2746d890b267ce3255114b2e073eb66e93c55eb200000000000000000000000000000000054dc1c981c9166d0bd3a54064c33f15ab856b240770ed44adaf9f32d4429babcd0baf2c5b8a1ff80728e9c63e806cd3000000000000000000000000000000001897595f836342ab54bc2e1b72f433bfe3b5bc989727de48575abe89386aaad9b1549af3ca55f39feec14355b29dc9e33521c9cf035b094d754db994fce3161842a9509ec8288699680c0ac7761eac68000000000000000000000000000000000467f1a3093c72aba4c2d9e8171057cf88146eb32f38db0761a5ab2027f2213c89e12c67a338b4b342a73384109988d2000000000000000000000000000000000ab26c871d140c9c4e0512afe9fb576409ffdcb95417f8c6cdc0d964011dfb1e745045766bbbc08ff7dbd6935934bba300000000000000000000000000000000183488902b886200e63465098be87a905810b2e8ebe0364316da798e423dbb267743a0d2e3d93303623fb17df0e74ce30000000000000000000000000000000012c7e79f9ba36cc47762139d191e6625c850a03d5b6e0648032d1669575704c91e48a9ae432bb3553ec66e86e082de689c8c2998d141b9cd3a82507b6dd97e8d32e9e759169c575eb484e9a1559427da0000000000000000000000000000000012ef4988956e026a79e5e904ad3d7ca56793321d62cad46de3cbde8570be5f0ac86d386216152b37053741fe342de7c60000000000000000000000000000000014ff7804312754d23b251a42aea65207695d4df65cac4f87fc96cb920843c022f24cd27731224db751cfb621886249540000000000000000000000000000000006ea693105a1b2afc79dbf75504c256c519f927ea0d79ddd1997a49638a67151dc81b84473208e8078cf71d456f2de0c00000000000000000000000000000000122d367c147c91517679432d3c7b56f2d529d70040109f803b89a04fd8540a6c565354ae420e1bd4ad4ff61427332629dc83c1ea9e4f4fc12a7190e6c71c4f35d1a676d39e30fe688a05820dd989664000000000000000000000000000000000156e7f8f1412cec315eb76f10c92143157313b8eda0677a6c0236de5fd27e5660ec3eb7369f1604082c59e1aa5f94dd900000000000000000000000000000000018ca9f505a88ed2bf595fa9b55d2356748770af16b35bd5db448990b7d41c3aac53aa490791f7ac09d2f5a087f938f70000000000000000000000000000000017c76ca9ddfcc26b028928364ee35829c6e57fda40773a6bc0c259a1b3cdea715c664d7bd0340192aaf7dec7ad20a2ed00000000000000000000000000000000082a255966c4f9d0ad6bd3d88b136cb2cfca09ed6ae378c914c28ff3338a2cd466cafd839f3fff4a30b33ee56e684f4e00be1b9098f1873ce155a66899877c7b48ddda363ae1d2353cb3816f1ab15ef0",
+ "Expected": "00000000000000000000000000000000075c71e21ce327a97024c8ab5fcbef4fff76260a4f8c8489167166c4a85d25096c617cceef73097a4bb956be3eae8b780000000000000000000000000000000016270f3ac86c0ec43b9472499c4d845eab488a34ad9e2148c72cbb1db13623c5dbbc8327c47ce596521bd1f54f119a660000000000000000000000000000000007ad4914ceda9fbc161121c818bd05953836a581dcdc78bebcd82ef548671c899581681c908a337618a445f77c6b7cf400000000000000000000000000000000173f401cb78024e844adcc88fcf0e52d32de134f6300216ea0da7747752ae3ddf4d181b8d266b53d1b699921f9871425",
+ "Name": "matter_g2_multiexp_83",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f40eea638a3d4fec417701c936d61c5b233c9d6b3e94ba9addd0fa0b20adf9f8e07c6b629977445c7750acfd18001c0000000000000000000000000000000005f1ca1ca9cf67c33e3ff174a65adfde2db62e74edf30b5b0156d6b9dc86dd619ad8863c055096685d611ac015ba884f0000000000000000000000000000000001683dc67710880b8af76b464291c17fb0ee4eff3f648ac0772f4a777025c8cda0342d8f5aae3123da7fac57b965685900000000000000000000000000000000143d919ce2cf00838b10fc65374e770bec3db8ecb17d2db08b6a10ac38657bb109f54c1b3040b661c3914ded6f7eb80fa9cbdaa0ddbf854861eac6621255b2102e5343666c735d0384049d5680d105d4000000000000000000000000000000000616299341f2921adf083d1190c212a7941bc0d9fee50b05b265f2e8c339fc3dd9f94607631f485e394f5a7d71ae73d00000000000000000000000000000000006b2f12e22369e8aff45b6c05a2bb72a706dc46a5d1393aaa9e5a7931ccff33a5df2967189114c3fc5dbf69d080e39dc000000000000000000000000000000000981e1b119d04343e075a80dfc189000b4cfb4e321575817aece6009e6b3a6233d1409e8e584f0ac9caaed1f43e40d7d0000000000000000000000000000000001ce4693e8c14032c35497e0f9a586a4541d8a1a68ad014b0850753a04215be2bb60cd7c2fa9be4f4f09a562d7b29f3892073d958260a55b70b580f3ee27c42553b5b858b66f6928fe74b4de91c34bda0000000000000000000000000000000012d634764207dd7a0201703f855365f7750291c810ff292b3e8dee682d7d8eebd6d6f3b3dc8b0c9e25bd2860e031311b0000000000000000000000000000000000eb0859d79fcdef546026fcd380f5c936e64a5665d73f56d92c03dfb50c534a00c857c86ec43275ce69cccc0b53137f000000000000000000000000000000000131bf000fd117ef722b33a1cebd28899fb012e1113f767d0ed46fdad82a32e4327b883fbe29abba1bb7ba3ecc1cbab2000000000000000000000000000000000e24ef1e44029366ae1daf06524d8beacb2b99f60f419cc2ec1a49013b79fb7a4781dbd37785f32ec67c0a28d61a3cea2117f11d78dfead915a94f11fa7e904a96204ddf1835d3501639b83cd5f716f500000000000000000000000000000000067b6eda41cb8da47a424a02a142e2b98b9c69e7023cf616040993f41507798882194229cb6572806e82e9e5eb837b37000000000000000000000000000000000e38693cddf130d3645fd60ade780db84fa700e5bfb74ebea49cc95ab001bde442f363b4e4c61f683b3e67f1ec8c2af80000000000000000000000000000000006d593005cbccc55c5e336e19aded70da65a7fe42b6a85070e491a4ae54e18ac213556a91d5d62786b6d4d1305525a76000000000000000000000000000000000ff86216f5388114dc06deffa7b52a273b22fe0bc8d50804b491fac83e13915c2dd1b8c2779a46b5c313c4e1c05eb2979087caa1e89e48f05bad1d720477199410941a6105f911d589e1f94a851e0715000000000000000000000000000000000262cf4727703fb227bd7fce6cd3f25c1897011ab892e79fa47446711d6867ca82b9b95f129f7ca24dcb60ac75173d4700000000000000000000000000000000136b5a304807e029d0a77b2ed505ee5c920248242f0f95aa07e9bc2e13d35f6f67451d028dc19d26095b55cdc2fae4fc000000000000000000000000000000000b511b2e19da7bfeb183f0aec91bc7db3e7c913f1c282e12d5d2f422a49e7fa78a5f35656dc9c980324717a5ad386dc30000000000000000000000000000000012eae443aae59fdf907bcfe3ee4366e252bb57e268fd569d742456f348429f009f67bf92f9dadd401104ccd2549cecc8255603b470c056b3dfb3acae0dd45bcb3d014765a5181760336deeabff3f00be0000000000000000000000000000000016a827938d8b98e3446445ce23f48a7ba0d634de826dd1ee3c71467eb57bd4c24e0d1b4190f47bd841183baceaa2593e0000000000000000000000000000000011d360e0c18b45ace82eaee902475127d8f18aa4a2ec2081a453f1c85ffe3c59c0f7016f966574a7c51bc14f1935568400000000000000000000000000000000186b5d452c6dcc1ddb4f47b07e01b6d64644f6d01cba8498c3059cc494a68bd25eef35cae05885b9f2689683e65161410000000000000000000000000000000000ff826e5a62affbfd6d2062bd329fcb561f287046870b8be461767759cb0d5f1ac904ecd1f136c5ccd784bc11088233e0eab0e2486316956291feb44de6389b20f8bafe9cc890d86d27a598bab0f3c4000000000000000000000000000000001010e75c52ed0acebe30fc588961c849b7b6298bb8d859f9a9401737c467921c5e3cda101cd4e38e4318233d12b6c7b9000000000000000000000000000000001884db518fbe4d621403ce00521878c0d419d8cf476a1dfda59b7d3c7af2bd91058bbbf54ac0c5cf9a217beb78e3f98e0000000000000000000000000000000001272cf0ad917738bba052e88baf88347d60f63f5b875d604cf0531c1ba7d43e868bc70a682b7274067106f611f08ae60000000000000000000000000000000006e3236f6a66bd37af4be230d4edda6eaaed661f206ca4852d3004b5f358f184d80be6af81c62e5bc8c88e7a1072fe21fb9436456262e5149d02b33a1078e198bbb681699b3f485625784df444bfff670000000000000000000000000000000004fd1e2fd0d28db08224fa7e880abb8c48dfd0e488df4d2ae5f6649f448193acbe943baf22af4b12fd763e3e4ddaa08d0000000000000000000000000000000008df68f276f356ade28500eeae3b755c9af9b5acac5f5f60827b5b2044b2405129b00e5271baf9a80847d3b720026b3a0000000000000000000000000000000005e683d1556f513e6d093704405f312687c3b9e2de3b2840fff32e88186c89b18d1ac558d960b1196594730a9bc107480000000000000000000000000000000018161f8d23c394d10ba576fb0ceee530ebb95a670f2589d84c0646f693086ecb7ed80e556f3ed9434d7fa488430ccf430e2724d3501e3d79b85266fd83a2a6156eeb48e749a61676a1c92ab9bdd6b8990000000000000000000000000000000017860708943449c2227c0f50cf1274652dd32e999d5f9b1a8d672feedde15e9f1af484a7b9462a62dd745bb6d3c7295a00000000000000000000000000000000064f8cb707494f82ffb6374641817a466af65f5c7d83cc2964e6cb8efd021e0c40934a3ffbb0d91bf8a7a616dbe8d220000000000000000000000000000000000eb37cc9d56fa0dbf050b557aaeec76f9f6d0a6c448ea298af78004e41ecd8a1df8fe8640e77cb76b593ee17658326ff00000000000000000000000000000000092ab597967544fda640b145edcb3ae6c3f027c2111dbc282ebdd48eb93287ae4729cb30e45c1c8999b3a45b099dbf0ca49344fe6ea9274a103f323f3d9381e91ae48233dd579944e12afdeaf854000f00000000000000000000000000000000124fa4d48ffc5732fb21d465b559e995891fef98370a1eb73c9264988f75caa93fc134fde7f93c794582ba5cbf6bc685000000000000000000000000000000000b71d012abc1558e49831f053757518643ae04f79234fa92023db9c5483bbd872d24eb87a78960f12930094c4f8fb70e000000000000000000000000000000000651cf0016efea086d98e5bda8e1959e20e4947e302eeb021d196897cffde3e2c28f783521b2a28b8de1ad1a131f5e67000000000000000000000000000000000555ff8a930cc11d320afc3e0635a6f93da1487a5764d56636be4e5803d740a73d84666f6141ed5ee6b778a463823fbeb44aeaf3ba8b03e7ef7201415de7365365b828f2c1a38d09153e51432d35b9a7000000000000000000000000000000000974e769869719f0ee30895df837cff50d47382461c557abc4b8806b04776f401b76a5e630a6ccbd3484980d03ff58d300000000000000000000000000000000098157f0190e6bacbf34c20310f6471166750ea1b235e46a5fae313f90dddc799f21548088322910bb0fd7e41beb23450000000000000000000000000000000007f00d7d18719db9d91e2c32f51083b42c4fcb43c38087f86879ad6bc99600d4c395586187d26d041ff49dbbe517fca2000000000000000000000000000000000510cea4a7463bc5882d0cc25fa967a0b02072627bd57f9a5863fe5255953732846d4907fa301789bf02af9c1b25211c53961d33104649cbfccecc7eaf33b7a2a486c77dca363ffc9fbc9ce4e8c1adff000000000000000000000000000000000bf264c0b7bf68c595b89453ebbd7fe2e64f4ae2c7268ad51f4578c35d48040277f3dac9021997af02e492039348efaa00000000000000000000000000000000083a4fea41cb1e02e5002259f5f7b335c81e15cca93cbc884dc1b08ee981c55f2dd3c0db1a35ac9907435edd7f0ba625000000000000000000000000000000001468e508a02ed7b61f752ac38313345338d2b2d018f719f391c0f3fa1dd1602d9476f3d8829720d17021a459a2732e96000000000000000000000000000000000629edb2530c38ead8717b289c08036c12630cd8c9ae875111749ed893b8cbce40bcaeaf13df4044147bb665ecc2319ea04e97c20b42dc265271740f27f1a833bc5b324bcb843a8f9f8a68231c663d57000000000000000000000000000000001635830ebf227be126e13c634a84f3649d498e0999ad2dc73b9c7360db120dc2216addfe18c00676ed185efa1e789d8c000000000000000000000000000000000471e3cfca449bde0ba2b1e2a5b63d53badcb34da3251313190a35daf694d70ba385976d1f875242386fc74ae0173d18000000000000000000000000000000000986cf3f1eef587bcc70f66f25c60f353e6b15bd105fde9254487e9b522159658d0fc6b6a8a3ea38c27865f1ea4d76490000000000000000000000000000000015a2eccb9c10bc273cb712ee04bef01a11e486bc6a4d220a0f653582af6ba1bac0b5108250626ddf126f16f4015c9d2cb688426bbe9ae054acb6c1fdd4195f8a113727f5617642a5b3c0c65566e22527000000000000000000000000000000001213cbd035615f09189171b3e22630d72df2df93fa8c14427bb00c34f5b55bc8d1b1a59404bed6549b582537a397eaab00000000000000000000000000000000161072d8ebec2841f0f34cb38a3e1b2094a597640a34178ee951e5c993646ecfc3a4c0dd753e7e76f3a6da5a091f9f7100000000000000000000000000000000077e9c95b6c6f726902392c3a16b5cc71cd9d4cec58c00eadca6091e45bc095e53006ce8ac8827565e867531013821950000000000000000000000000000000018cdf909bd9f38e57ee24c0f51a5f9f703eb3d190dfbf75be00969e9e8f8fee331cf32d93c3a956d12f374f8752c2c79cf365a86a8d08db5cd95f239a2f3d22279556975ecc3baae0b774b0323dbb1b6000000000000000000000000000000000cbc27995eaeef2bef14919d48a008a0b0467856f8a6659d6e68e47a2d9d41d217c5913aa1d67911325dbd4fc38e36eb0000000000000000000000000000000010639740654bad5c4ec93f2496f4dc54a7642bc92ed03372ad4edc5fedcdfcf37158d3f02279d4e15078e9d5a7f8b5df000000000000000000000000000000000155ff4d6dfa031b0cc2f57df41c1e1b1c81bf5a5cc1e3aa93920e93c2e2e7a71b56ac410a87855400025badf6dae8e60000000000000000000000000000000018e637da048e7e84b9d1654113978fb148a54d86e1d011d7f5a86cd4f1e5bc15abc5b67d00129f53c0c021cf933f399c528715199c9f47fd6337b6b0e807e230b1397885fded024431c70e453f55f3650000000000000000000000000000000015d8f6e47b8f07b3e07ae0952a7c8f79519ce2828e3e26b284b8f2fae7432b337de17089b5c32f0081ec6c6916f2f53f0000000000000000000000000000000010ecfcdb02cff772db667266cb3f99f1dc28004ffcadca7a9c64b3b5853c09b7793ca0aadb155257bd64fa7bccb390450000000000000000000000000000000011096a52f3272955947304ba037e8b3fce6b2f07f2352c08d5932f4d2306ca511a74dc044d0f0e1e260ff40b0fac5e0e00000000000000000000000000000000130facbe0c1c6d077e9dcab647a44b049a1aba3df500bf27d1c268f71a59635e702c9ee1bdd68fbfcff7ae5b3e6bd83bc32e8643f38f8177b788b8c2bdc25b668308d914fce35c6f9023a769334a51d1",
+ "Expected": "000000000000000000000000000000000b47d58802579e662f34908a4060becd40434e4934ff58790df2a69a759223ca29f42e658ab475cb92bd9c46566811c7000000000000000000000000000000000091d3a4c58a669d3bf0377abfe28d1817168b2a86375928d95df3459c83334669a59aba95ab2b9957d5ded0bd8925910000000000000000000000000000000005aa9c3fe0067338675099ee32f93bc8a5e9ead94b120dfa391651da40cf1ef5ff79d193b0b14b5926f10660aca6c11500000000000000000000000000000000058200992b111461f4d737533301734a5c3731c9f2e7b55e18887ebff4d5b74dbbfd23773606f54cd6a930b85b89aabd",
+ "Name": "matter_g2_multiexp_84",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bc3eba5594666cec699a47fa13ee74722a80b4e5a1b28553de37c3163f2fdb8b801e35a19f6d99cd207d1642c0d4ad400000000000000000000000000000000104b334afeab36961824611f0fb58bcac55c9d36604ba73e9c8809085c019bd967cae7147c766df6565ddfcc0cd5fc9700000000000000000000000000000000026c3a6a4ace8638bf8ba7434b59c3aebd4bb274cbdcb898ec6a547b215f32d10395f3bb85a9eaecff5ef6d5ef2b50e000000000000000000000000000000000065bc419f9496b5e81ce72a13fc1bdce4738c2e3faacd80676be31db65ba3e7941ea75e370b6d6c0e7b2cdcce80a2fa14f8bfa3d47ed33a05fe3da738797f18ca5d5b8658055de5a9f85bafe6078f7fe000000000000000000000000000000000e7f1f5ead0f212439b4c47599581982712d2e6ba056f36cb04033ff5eebd81b5b41b874a78aeaa98562899418ab04c900000000000000000000000000000000095e45da9a4b2578cedd13af71e289d0067ecca1f09c014a294e0b250d1e8243ff98a9761030ac855a9d897cfe9fafdd00000000000000000000000000000000030b44b150d1337a3ed6a77f7b6332d7c8103da1aef0d445ff7467b4863e4c830fb782a81d01a6bf97e8d52bf333e78d0000000000000000000000000000000013bb76800375a45b847a96ef6edff3fc3c30e3d45bb4afe04230107f6a1802794e1dc23431797bc5e79e0d5ac6357eee4b0d302be94d437b8055586aa77ec1fe616e30552b4d7d3471ea219c148be069000000000000000000000000000000000602e0bd3d34415ddd517a73acaed5750dcfd68b633d51003edf79a169ad7a3ca2541d7a131c317c957a9597a753b5080000000000000000000000000000000007a964539081fff51e0ec24bb71257f6a1c513fb0047aad84b80180b22133246a1f62958ead75e4b2a68f973d17f1230000000000000000000000000000000000f48fe0f5b5a95e48bde4d8be1b2f352d748c1201b064bc88309a709b285f81260d4535d3e1dc7f1d6ee23ead35abd9f00000000000000000000000000000000135b480fc8a72248f7a4898fffc6c18b7f2f5b1af5cc3846610c299c8da252fb71190d9f761e037c6b47595bab6a03e56765d7f1079b142e513e604d577e7caf82cacae59fb98c6f8990522372dc906f0000000000000000000000000000000004773cd2884e52c2551c1ea0abb78fa17caacfffe13f18b75588484b8bfe781e623075bdf827fc82c6ed7e1d4d62081d0000000000000000000000000000000007e6023fc0e409bfc7d0b7ca65fa0e8d88bf1b4c202a8d1f0e1c3479b0963a646d16795fc5a128a54e624357050fed4000000000000000000000000000000000039f6eaaf99bcc9f4d8fb994a040af0d29c37960e9015d4e48466a9e554da30975c5534e76a1f08a55ed8ce7375b70100000000000000000000000000000000003d2b097d4afdde83a01cf2b4f9d12f77c8e92a8cadc225d40f974ccf385ae65bed1972a365d55e24231d58abed4395a2eeee02d9309af8c74c78e21836f4e6a7a6df5406617e2b4e9d300e37d8a2bfa00000000000000000000000000000000047b8c550310ae246e43b513d39e507f1dace7bcb543a49ae0854a397f62c408ae3632c94d172669ef3e013781796ecf000000000000000000000000000000001592914e260afaca80c0a240426c2828239ad5e256a707530f49cd65e9da2e4bb14a7d6d5978f52c04130a0d434cf4ca0000000000000000000000000000000006c0b8448ad87350db130373778d414deb738d3be97fba25c816826f59e3e926f44956c2e2056b7d769278cf56cf6fe0000000000000000000000000000000000a42d716fd83071bfa014a9b7af6c164d494f0347aed953bd2c1c97ade087a8bbea9f53c507fc0b22d520f28cc5d480cf8449caedd55f0a08825cc1a9e985201c8a7a54d1c4dd96f0ac54214743941810000000000000000000000000000000018026c9f6c86219d0be88955ce0afc3cb637b1c3a531aa2722c56816d368688181ef2fedf1525daec6d9b1651b71f27c000000000000000000000000000000000b40b15bb0621209bf9e33ebc27a7502d90fd3af62a1bb8f54a874a14c105df34ae34a43fc3805c1e4817ba30c048ac7000000000000000000000000000000000465262367e30ccc24632d39bf3af9cb160e97049d855176f665a185c138d5c529d11e53e56c65506e3e30be7b48c6730000000000000000000000000000000009485991319a311052d883b45911be12cf7648b5ca104ffe77594472f7047c803b8e9fb753b98645e630b9913bbc947e28ec5f9dc48931da70ba0cfa7251953e24c4c95cd019e00ac6fda095c1302a01000000000000000000000000000000000fcc0aca0d873cb8733ff7e2ea02b3736b737821af2db06ee6508e161f6159f9d944372c513a03cc4c9e30a707dca0930000000000000000000000000000000015c3774f4e0b30c9532beaa2f7f9b777f8d46bfd3888d6835f4a5a046153a98062efb17f78807fa17b3a995ce720c0b900000000000000000000000000000000083d48e01d2fb58244861a74a1261063f7d20b412c8a44f9945fbe373cb4b9a7ffd4c4ba4054ece0abddb6c14c013ceb00000000000000000000000000000000133c4976454b7be427c4c2ed437bc2e882854d2ddce42d2f97cd3fab1fcf60c3272aaa123a0cbecce1a774946bb7a8a0dc6046b43e6982f11f39412cbdef14f8e330d37fbe6dfa9ddf3656b86f4f60e7000000000000000000000000000000000f6ae7de1dba3b3030b208f61d182013231c4666f134b007b52d36bceb6f3cd77577be7b11abc097cf9618d351d61e270000000000000000000000000000000005803904e3e640e51900805f930638ddd8b86cc1bd50cbd32a142e10d85044cc52ff769bf1b40dcfb7269c913d00b01e000000000000000000000000000000000e6997b1f8bb649c56de5c4bf9968d19712abd22fb7dabee19e0aebd1b13adcd3e8b202975b4edc917d93adf087fb539000000000000000000000000000000000a32384fe03280962c5f575b47192e5ef3111fbbb0a01bda2db1e9733471f11eac0a37df8ae1a891de311770c482c06b0adf4625ec80149b7810767c985c2aa0187987b3649cab8c59a892404ff2aeb2000000000000000000000000000000000531fad86551ac6dee15fbd62cb13f38d8d5c89d23a031b9977f110efcf16501534757bc5b93f0250ff02d6cfdf2009a000000000000000000000000000000000e6d78343049a68514271fc785de053ed7f50a7774b87f264c42e03e6f8f86285477f8cc57ae066ef0fde237c8d1ddb30000000000000000000000000000000013e313484da4d6b85634c5306444bdbe45d7db823616d72821eb64a2bb5f352a4f7e4273fb6557039fa563ce1b091bea0000000000000000000000000000000009a40a984be66c3442fc8946cc42eca722187dd819be9ab34a9c3b4b0de7de3d5f126c175fe84c51a6f09e18623214f9345fd17367ecb06b29d764b22dc1e262ba1a339b6f0e0c77384245e3d41cda970000000000000000000000000000000008a76db551280cd43d4608e9fc629a021675bfdf9bc5a021546b92f3734acff1e97928850716b94d15b7dbcc4a1e0aee0000000000000000000000000000000000b2262872c268782e8f27ee8fefe0827d45131555e755c0a65a7c8b4185269bd621412b653348d7c1111d681f38d946000000000000000000000000000000000dabcf0f847045e01ef70ceaa32455f4c962e4657b840f97a1cff7cf5073cbf4ca8ea75a4887076f155e27e8d7406c95000000000000000000000000000000000a9c0ed94170eddfc485d9f1a770a8b493d4a59bd7156d6cd4b95b55bffa1b597ae9d6fbe529dc0833634d75906a4aba5ce5e62dd15958e6298cdf4a4e899e53644a48494d04fa6d1f73f2dbd645817c00000000000000000000000000000000170ac69c2bf9b48715f445524cab902b18ce6dea7b258481cc59986ae61c8fcb6708b1457be299a6e2f6f34dfd936fdb00000000000000000000000000000000107e855593b6f3bd2982a65167ecead47039065c9ae6e1bf963f81d441f0ebb411eec4b3ed1cff73044f68a4c114806a00000000000000000000000000000000063b470d158ebb4828e875c3dd0ca29a4fd2cd2af356233885a871cb5b77402090f29709c6d6a78f612c8ca4df2f4119000000000000000000000000000000000db75a60fa0b425b8cd2c955e21846ce3c407cb3f96c472cb412498143cc60212de0dfd0bf4de53ae3b345232180b4ad853396021d32530351deec5c266a65519471dce2087485781f33a1423755ef38000000000000000000000000000000000389e79154f627463a7966252deab10b5e809b0c2a9e90989c56d4076b834e2081ddae1c02a9e01b71d96b772766fc680000000000000000000000000000000009109473c7aa614334fde410951a69ac45967f7550890e01b05279b6dff394775dac51d583ae0aa82edda18ecc5e66240000000000000000000000000000000019dd51ec6783c1618a7f12298e38cc75d4fa32fc31438f67eb15419a2f0e9d4b5f70ea59b69e531c868475cada519569000000000000000000000000000000001121c7a6cbbb54d5e30a11a73c158237dedac46385aa15d93592a30fb64fcd94a674cc77afd21a611f704734337905596dfc62eb59bb84b3b6599bf3ce7af229096a8fd5925d4743a5ea386a26c9a6d000000000000000000000000000000000178670fb06f5eb8a4f182913f46f66147deb3f9f634d620ed55da2ccc88895e75f76f55b979e1ba3c3db29710050c7bd0000000000000000000000000000000011adec68ef139716ee081db7122e911ec5a6e1fd7f681a96a713dddc2b742b6e7cf7485b8f45e7ebdec8b1174c02eaf100000000000000000000000000000000089dac9a47cbdfead8536d6cfe8b94d316123bd92ddf30091e16711ff4651c4e2d8dcaf6c72bc159d7de9fd832c6f5be000000000000000000000000000000000c40b871930f0c6826a943a229112f8bf9a3b7d7e07139e1a7d99f97601b6ca8cf3638e0265743dd732cee17fadf996721d35ee6d29ee4816b91d1664b5957767b4b8066775b37c3b3d08729c949d6e5000000000000000000000000000000001040c4cd3c28a752295b115fd80c8ef0e538e1a3906e0d326e46585d633140bd6b8231f50d50c8e7a9018a625c4bdc530000000000000000000000000000000008b966d9433bfc3bede4ddb005cd0c256a168437c31b8ecc83e6fefa6f4b1f2bfd057c78f82bb76279b74a2f7de493b5000000000000000000000000000000000c0f75db7a17e4b712666b16c31b10bb935e7127eb9a0e59e35ec54814a9de9012210ff1862aef5f765d4f7f673c4962000000000000000000000000000000001015e63589a8b56aa643a79c5a433dcd8f4933a10edc9921bcaa7098af435f7879a40868e25d1ca6f7852800df29c2eb3d283067bac390f556891a531dfacfc4795358229bc9a651c0aa71d601bdd56d000000000000000000000000000000000fab22ab380043b01d312004057488ffc958168f8fe4d9c86af622030121e14a46c4308d711d5fa9a414b9ef75d51ba300000000000000000000000000000000047c738fe5272e695f421ed463ce0d6308e05c23b6bd0973df9b55ca96d89c0771a45d53b4d17f30d8cf08edbf94490c0000000000000000000000000000000017bcb3ed735e5a302f76002ae82f4ac74889fa0e966f0fb611fa6a6a09440bc923f447eb6aebe47eef917753b7427efe000000000000000000000000000000000b189d5b64578eb53ad850c826082265e506ab620a9ab9684cc2a53718f26befc35e9431af012306a6190f144a9632bf873724ba35e4e8b731db36f5067aeafd33f2e966977bd0962fd57cd5ccbfe87b00000000000000000000000000000000049fff545ac239696c995eacc560580a0328af07376f5ec819902e30d5e7e40d5fe07295c4ccf54d5c06134370373c1b000000000000000000000000000000000bff448d5ab544a8cae0cacd216a6b6d48f0abe1b4bc946d95c1a8c4ae44bf049c3b572675a5e20c1b4188fa27a867a70000000000000000000000000000000011dbc52baa00712f66def2fa8fc77bcb07431d3285774e2517dcca65e611f07aac265856cdef0c1637def44c382230fe00000000000000000000000000000000090af0898dd578123c65d1f818c3f33866e4acea19aeafbb31bd8da029ed1daa2d7ab3b22147eb32a09021f7a78fdf2acc5934c02b63797010cc8474e90fa5dc88d73dbe5f9be605bf335057fba47ea3",
+ "Expected": "000000000000000000000000000000000d52fcbe9f1776477a9d2149ca55e0651fe9d098a67209ce2e7d772d4901ff2c70be432b53dc94886651865a81ba8c620000000000000000000000000000000006b54871379e2be969f86c72cda9acab9bc99f73de987f17ab8b25c63c55ffa2cff61b87e8c30d9f712afb62a2b9cfcb0000000000000000000000000000000005652612b19c38650d1babd4772722ae2c560e2914f2e246725cea86dbe1275a981a592eb55077ee4b7c6090e84d2ed3000000000000000000000000000000000ee37a6d42ce69aa67cdcacb19efc230c6c34969a2e081ac77e8f9d45128a6e8fff923c7647a0f168fee18342bc6d845",
+ "Name": "matter_g2_multiexp_85",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f114e56d10dba7945d125fe1ab7871d9510771548d8388a2aec8a481de92572645b73631f9a60285c3eebcacb3bc0f5000000000000000000000000000000000667d3f31955df11e4e7896a1856fbd4e573f1cfc906b3953b5806a5d01dcdb96009d9f148156a3828e822435f722c5e000000000000000000000000000000000d7740ae776eb4766999f5671315c8965ccc84ff71757e361fbbb55babeefb96265c97df8892acdd6a9166641f656e62000000000000000000000000000000000166529d1a76ad784557384cb971728dba298baacc2f2a39ee36516bc7a761e9a7c29e385cf5784efb9f6e60e998b01e864a1ee754f6b0a86923e5501d54e6f47d7ab9e1483294ce98be13b7db52937100000000000000000000000000000000133e0b08430d9318d98bcf58b3d8f51c7b717fab56fe25f434bf521f830c7d4247d87d3df910490be2ad38adaa8eec26000000000000000000000000000000000e15afaee4f1ce6290ddfbc13cb887e540efc3fd8150dfbf3a5e7c759ccb8f334ba26953c7bbc43b5234b857159f6722000000000000000000000000000000000e4cc685524d42ea5e435afec7b3d7d025e93ea06407a28c246a39dee8ae77514a0bb2d5031f7367d658027299762bea0000000000000000000000000000000001b231237f7b0538d51adfa4ff92bf313507996cf5255f191875970ed4d946cffa8620b44045f4bcfd8f89baadd331fd93064d187f7d21b8b0a7092943de13b96c2e1ac9b578637a6e64331e2d40f53900000000000000000000000000000000084128f1848b2b244e4812eccba01287b9d07e85450459c8c42b01180bdd843058d9926f39e2fb5f610651a00233e31f000000000000000000000000000000000055ee70765f2cccac966dc08abd4bba0d004b379a2c6bf188f300f5d413f84e77ca1d462219bfb820d7f585b914a52f0000000000000000000000000000000002dd8f1d1cd85a5e6ac793f7e1e3cff887204aa4a5fed92f2088c06eae95842ab2c04d30d56f4b0fcfe61379e8e7c6940000000000000000000000000000000013e318f8b6f4165a8096c76ada440154901de42d69c38e66d9df4ffe5476666ecf7068e7163f29f04972682c43f3b0fd5e676b40c09f80be5d9398a9ec20cb811cf6819a130445203d792a4d34fc3e950000000000000000000000000000000003415c8bab713aa18d3f0d54e0101ba36793e6e9dd3471f8eed9a15e00d8312732a9ce88b5f0c30207aed92eb173ac680000000000000000000000000000000008a7e145e9576be8ba2fd980fb1735a2b73d1bf5f3e108878b721b6ed8378b5e0f03ecac179a6d148541096ba483b40200000000000000000000000000000000029e5554752db8bb87d58275268f24ccfcf3e0923744d57473d54a72e2cccb847eaa8f3bf638833a934c43930fbf30990000000000000000000000000000000000e0f2ead2697110a132c4ce1643b97fc652dd0660deadaa4e0c45e7ebfa64cb6a6fbbaac7c4e2b725beeadf6881ae5893f63a87972dd11f5239c35ce269e4b9239e3ae906ab117f1f045d3acfd16ca00000000000000000000000000000000014325fcc087aa108f152b42759cbc02cfa24e7e7cb995c78ccaa9a283ec2029c08cd747d599e0685d365ee99eeafca880000000000000000000000000000000011da603d3a1128329af19e596ebeaa4bad034c59581e9fa2e42a0260032f84654bf5ce22ee32c34eed7515d7fb0fade0000000000000000000000000000000000189cdb5b934cc1ec7ea0cf4b8158a1416712bb59c1650e6d244de33bebfffd3691b499b3ff8255b1b513deba709f7d3000000000000000000000000000000000e7ab2b279d0d5933df25d8fc4faeb8ca907e7bb8588e618b92737fcb6959380abc205118d2e3fc128b89a2ead5ca906145e3456d5ca6aa5910430e5a19567c327b757377aef98c4f46fe9a1f52cdc5e000000000000000000000000000000000895b6777e677732c74cfa82d5348c4c8ddd63ce10347836f5140b9a64dfe631804ea3be8e20bd4438f5e7fa14a121d80000000000000000000000000000000002422cc4781f007f732239ff9eedc126777d6ca0f0365dd90bab6b68c9e3d02ce726726a6d30d7d51a1f0b45aec1854100000000000000000000000000000000048af8a79663aefaff77a934f0af3a09ba02077c13a794ddb88e5c679ce348b3ab0fa217954ce1422f4e212d1383ebdc000000000000000000000000000000001190fec6c510b0b16e1505f737b25dc2401e9fc2c95bca92aa5d6e93b284b766bfed93a80b137e5fcb339983a86acd41ce27de5d3a5ef941d058a458f3ad2a386f1d66945789e51fa330fd65da4cd5080000000000000000000000000000000014fbf4d005f43563fb7408d1f20f672c8983120c66462ba9156b64a287e66960fecb41ca129b6b14466a5a0de91b81c50000000000000000000000000000000004fb283724950174d60f64af7bc8a7d059431332c8f17769df33f6607d72633aae3a8d595cb8d5af3f8909297844b3a0000000000000000000000000000000000e187476a19280ad9f33a55c50f37f765e343f92938e247ec9fe099c7f3df65e24af14885539bfcf3efe3bde9f2700ce000000000000000000000000000000000f086e6b9e845fe3b0c5100f82bc8aeaed166bed9fa4d34bc03ed86342a997101c508a4c096c4f67cb5791cc1a1fdb8187bf5c4624e86aaead712987f313e5db8f2fe6787fc33481ed6e5c4d3e96d5be0000000000000000000000000000000018dbe48c54347635d4b6bc17ff5ba390a73925f1b180d2c516eafc0936aa9bddaf7317cc0c211fb2a7f7bb096369a45d0000000000000000000000000000000015544c177a4b8018ed60c2639b43236957c2d995fb0f32523654584b0bf052e0930366a93406e1ec5c6d2edb955e811d000000000000000000000000000000000802d2cdbc5e15b25c77ded4bdba087f1d5760e6ebf9549a37f3314b1e88d3d6f58da9d8c6e9ef85028a271b83dd6242000000000000000000000000000000001577bfeaf213ca8b0983cb178e9634dd18f74baf02f6ca31b2e3b287d80a32d4cf11afc71df09ca5bb0bc8e60fc7ffa968cfa3fd0692c9ce56538bf70e77e2a47534d9472ac702c53f2dbe68217d53df0000000000000000000000000000000007c059044ce0c15bc527b19ce85cade8b1d5a9cc6dd304ce9a3c461e631e17c4feec52a0ab5cfab6a2270c75f73df86e00000000000000000000000000000000076344286cedc8c180e3bd762f12ac08f0ecc51293b9f9b8e7c0056ceba1bbb6fab4ee39cf559fdbd601db6c3d201199000000000000000000000000000000000bf6e708d0a4fd85c7566804e19f21f7a00bcc3bd7135f6639ad30aafef2ed1e72c84c8995b0e59738c2bf1e4040621b0000000000000000000000000000000018ff3d0ade15b690b6e306adaa5c10796b78ed7f8a984f637271cccfd39fd17c1e8288a11b051ca94de2a9bd04fa96d7a36b13ef742bfe88882a4e635b5fdbd9b079e1adf3423dd4962835c68c9617c500000000000000000000000000000000025cb808922f6deb0bed979b80a675d9324cf25c53de373534d771afd919a182af9aa1dc26a2d0284887121bf4d6b6470000000000000000000000000000000018970aa4f456c1b203817322df2e222516bce67ff9ace069599061c6229596e506c0286171f3551302e45b7d3b69a39f000000000000000000000000000000000a57d0da60f03fd4a5664546f9809c771ab6188aca5102c31f26b09950cadc26b0275417ddd9c4f4cf29794b739733cf0000000000000000000000000000000004ebf2bd93d7921d8bd97ee71cadf91145e064a33651da2604ed6fc8e08b1b8305005f12fd4e6b68b7b6a3b5cf123b1324c54daa7de8446e5a26cdbd6741cc90bfd26c544fdf221d47d509c978723c3b000000000000000000000000000000000c8ff29d0333e3f38fd8af91ecdca49e54ea5dced71b60d693b1bbade99ae668e4f994f7a5417a08a8ddafa410d437f300000000000000000000000000000000078ac1d0898a9e6cae29fe6b50e435e5f543d0ee233346728c46d659c4338295f27b42fc4b2851ad5035feab2bea8871000000000000000000000000000000000b3a566d2ef4467f21c27e4a3dec99a26c304b32ba1fcce8276a8518383a7de44de5b4011ba738dbb8761e67e36115560000000000000000000000000000000015a0aab8c3d51fc3fc8aa35dcd07f8a08188976883f9d3ccc87ee148525f2115ca46726a2e3c550167c169977b216d6217ff7a416011549f144a3a65238d62395f4f76afc09496902c064b27739c6d0a00000000000000000000000000000000115589e8e1440edcfe72c008f6e9cdf13fb7baaf70aee16166e7f32f4651db784f4c5cac15d91ee13001169fa777f0d00000000000000000000000000000000000f86710678b01c8f648bab2289e8f90648d9470cb13d5145ade526696d22508a4a59164290586c2c000dfc55b4a20350000000000000000000000000000000019b300961b40b0d9fe6e292e9357d04f0483ab3a8cc6f8f522153c51d22de8e96a812adf720d13ff7d05d1e68264638a000000000000000000000000000000000a80b61ab051ce413ec838167fce393f88c8a25f403bdf07cb60391fb15306a5271a7042d36f7c46b5978106a7b5293c4615de9bd7aebf1acedd9d40fddda34e4a85bc253c5e92c20d984f6c4cec533c000000000000000000000000000000000567c33d22805319418cb1ea7eca6205a6c44f1f881c03e37bf3c66a1baa5153473cc73b8c25d497b0b0057ceb0395960000000000000000000000000000000014d7a2bfeea6a746e709f6108eb32581ba38a617e4450b3567c77a992988d91f4da31b209286f8e9fd0d7b8628aa6c4e000000000000000000000000000000000ae6c9fbf0e06f2e38e91699cd21596ba90f92f6022a4f3c7c8a6557b7e1331283bd4d7a7d31d77d9d7cf70a2945ea1600000000000000000000000000000000066b8132c73e1da8ae7fec9169770a188b686f223fd0306441356040bc9070f34a47fe1bb8c94de9fd7606c18b1d2b1dd38f1a0417a5a366dd2d8f5ce229afb6f34c1b663ad6eb1d9ff12f38412f00f7000000000000000000000000000000001460040d0a19c37fb0736ebdac0324d8a38c94a73fc5f602b7ea5b7255be9d4b6ffc22fea5043d948420e9ae3476f56a000000000000000000000000000000000b37c0078ab8babcefa8874c6cd1c5184d713b976852d087ed84337073fab3054899859d0fac2f4351bb75ee0e534fa70000000000000000000000000000000004150f3b98e6166d9d6b0388342042dd8eff9b8e1239f479330b64c5b316f98fc7bb401b737efb87e1f6663ca4efa26700000000000000000000000000000000043e6131c1ff621fd6f8caf0939487a927550343e24425ada33cf622de757e6e75c9affff9f04373a954557181641617364da9c6b07aada98107447afbb189626180c5eef31f7f2cf26d5d76ab0c74590000000000000000000000000000000009fa1754bbc957d2a8317a2eed859457073571379cc7c6d65bc6a0b5829f8142db77654eb98a2bb0cfa5223a27d756cd000000000000000000000000000000000cfe8b8fbbff7507d3d74f4f550b4c85e19b8929d3728a462e12b4008c79014103153c69ed8dc6b743e1b6fb4720bad00000000000000000000000000000000017ca0c08c320c12502a1dbc841425694bde68b7806eddbb40702e58ed26c7e112f9a821a6c67afed174f51896ec2287300000000000000000000000000000000014d08df9cf825b07a387642ac9959e8cd15ea8e752231a3047fa30816acb1ecb79f1755484af9a98b993f50128c2bf5031aa8d860e3b598ad0c4e9f93f26d153f8a8d8d0dd614ba868ed055c517532f000000000000000000000000000000000273b64e867a9111e257c9b32484655e4d7e676ec50f174d9ebc9fc4262c037b176ada941dd8c1abf645e275dde04f4a0000000000000000000000000000000008a63b9604e96a5034d92e3790411f3112c2c7cdaa056f9f1bdfc0b164c37fc9f58dbb566337132cd1626f9ca2618f800000000000000000000000000000000006a661167c9fb6c26bfe0a3902f309fa683fd22729bfcb433756182e7e1a406bf44ae1d13ef0228534881daa339394e400000000000000000000000000000000193c6c5ec200d225c43c6e37cfd15e16e49b7d87e5515bb7b4c918903966f4f6ae0d42af6b98f6efdedc9b0301fa1c0f290c467c4827c9252b82ff523633ba116c52d15df9cd4e3121ff0e9f754ced5f",
+ "Expected": "000000000000000000000000000000001403c7e3059135ebcf5e752011fdfaf66e348135314f3f4239b066e1c6192ffcaf89bad4228fcc2be19a64f4f5386f5e000000000000000000000000000000000aadbd8d0e53d5b409f7fa508089337bcf36212a3f613b37a95757793dd6b0ca99d1b3578ad8020d46e29c9c4197ea070000000000000000000000000000000019e43bb32f92ed187fc32d9dbe24a486e38316a3cec0fd7f7c19b313af43a10fd63738b78e609e04a083de6761d53a90000000000000000000000000000000001490da7d36ff16304b27f6e57412975497e9f3a6d35cb162464bcf69fe141d34ae27a33afc75a2802eb120e90d4897bb",
+ "Name": "matter_g2_multiexp_86",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000038ee0c2c409d8832437ea450ed705589c82791b8319fd0ba6fb4d302d3c5b73ea0521a0253716e5810f03fca2e9dc720000000000000000000000000000000018c9d748aa685bf6e11e6e4b6ad2290ceff59c8837a088b41a08983fb2c5ef077adb0730b298c5df9aa02a820a19a4bd00000000000000000000000000000000015d248426e362ad2489c0c6a567d80b22d54d6a79e198198a771fae4c4e97eb317da9feba8eaafc9460ef45b1a5e5690000000000000000000000000000000005a2342412801cb37911a04d7ee3b1e5d3dce2a06e0658d59f2ddcaa9ba32804a1ddbe8f4d00f4436aad1346ed1ea5344aaa57782608de34c6334ce5039c67767f6da7b315dcfc772f03aaf3dd1e67b90000000000000000000000000000000019d49748f05458cb9b316e433b0d341e23bb5aaa724b824bd147596761c11efe8f4940eae09e302e563e14e96b814f4a0000000000000000000000000000000018011e7ee4988da168adbcf81cd14a9232edacc06bbfef0fc78dc0f96b5ac86ea67be8661442b5ef60e3889f3137182200000000000000000000000000000000175a2ae3bdade6551b23656c16884ba0fd4247df4ba7471cf81022d7e224b23490db153c8289f95467ddf9671f8b6cf90000000000000000000000000000000013c58c0f55c46bced98faf3865e3b6a836252f252e97b6d2a799b574dc569f09ce33082880a4d0c3b8a2c7c0d4c30eae22c1cde67b0e8ec7217c6ec72f36d8a1e73794297819de9ef6f1e52acbd3ec4a000000000000000000000000000000000ee45d5689a8ea6132d5ace000699a157c1cea3c0c98b38d504153d64fcaf1702ac7a1cb0889539d6b15489fef415aef000000000000000000000000000000000b320e0cdedbdc1fc5733488e6d2aece6386a030adc36b0a69dc3809827319947049f3861c2edc859797d30a3689322b00000000000000000000000000000000194096079b3a1d6ab1080dc71bf6d5734bc7b5e7f30bbb0f9b95c9495a6bc4adf76e198fc66accbbbaac215a8932d8c5000000000000000000000000000000000ec07be0cfa9b3d3a64c016471d9e6d25228b46dcaca6e197be00b9ca5087162c35f1d6326a3cf83f568cb06da8c5220895341f4363b688c4e9660fb0cd17f6c111a5c92e732205fab0d0da0175f6832000000000000000000000000000000000a7f3a3fcf2e7b0ada6d4fce179bdf229454002f1271a39d5e99daae72da549c6ccfc7c574f35bb9784100675c30b1120000000000000000000000000000000000fad14ab095fa09bea919ada313727e7aa5aa06a1cc7746d006e3eaf70f79c5e4001a8a8de03540b45e0598b22710e00000000000000000000000000000000015345ade62c5691690c181da09d8f39c1ead42046987b8c7c975d40690a286a816f8cca519731d0ca23349c54b30d8570000000000000000000000000000000019f0a32361bb6ecd8b1d87c2e15d31c0e0cf995eac9facd5eca123c0799c465f156b0142d98e0f315e9b3595974a7b824c5718fed7503c5e2a97fd6ab0294d6c42b1d35067e9d5ec1077176a4bd3126f0000000000000000000000000000000017af46e78904915e348734d2450fc6e1938bcf002989f855082e3b4ff3366d81ee8d28293609c3c3b11568668b1305f80000000000000000000000000000000018b0b3859763c2654fc00792a5193b7317fa5051bcfd15ea42be2fda0f43adf322219f34e54b2446ef73a4562151f9a70000000000000000000000000000000015c23509a1b324c649ff878d004ab5f253d041670ef172ec4dabec7a525d5ddb8f9f62f383e3f71b0e9c98532e247d560000000000000000000000000000000003a38564a55fdbe05b047281fa153f736edbf48c901749005473255333590f967171a6fc88751eaf57a5335bbfb6ebe86d055ad484f5054e8bd0d073cd556deba05418ef1235d08ecbf8717b550933fa00000000000000000000000000000000100322c4a92c136437714a6586c82a6842027ee218bf1fdfffaf95ce47c9c8b6c8f61115b092dff81ff2e645d0a7a4340000000000000000000000000000000013a91ed8629acb5e770683015c3c248255d673d4b2e6c96334d1c80326d1a8b4b655c81175e4a914a45fb37c1f178bd10000000000000000000000000000000019075c2eea3f64f42be82fdb8f83f2c68c08e858702a0225d869143c0b017b76a7a40d809116ffbdff6700b288f5ca3b000000000000000000000000000000000598ee9ba9d56400b59c7f5977aef1e179855a37179fbfe97b95f19137b6034568e5c7f616943b4aca804272955d42334cccbb062c27a67ae2783ab65a47ce166330cfced1f11b85f87483e0250b138400000000000000000000000000000000025a526b137aaab5ac1b5f8179a18b06feb7c905b4a843cd55e31b7464c2b6d432b569e9bfc3222511c18255102aba5b00000000000000000000000000000000090c20c9f78a242e52daa339d5cc1c3f35aff7ab802a3e4366597db8b6ca43d30fa0fe8d9484e49fa4fd0bf5509f19e6000000000000000000000000000000000e928b2173e32e5fc9c373a2a6f126e1a3a472c01a5e87677be0d29907022b9a7dbec3340cfc89e67377ce472c2d5d4c00000000000000000000000000000000147b4eaa2dcee39b918b7cdf24483b29466120677e5d42b51353a9b2fa207bd911d9b391142a13a212d0ab38adcbe10796111cb1181f048f51349aa2953bba2af50f7b7b5d2328d435bd63a7df5cfe5c00000000000000000000000000000000007790cde9ff8af2d7597d33909f00963eafa228817de1ebf4233ef0831202700b99641318186aec80ac913a1b1143eb0000000000000000000000000000000009d42ea1386d8b019dcd26068ab156f399c35b7d492722a20da0c915f7abe44ba688d9486f4bbb44268542c5a49168930000000000000000000000000000000010611f233bc1c4af0a14e1d1b945c91c077ec3dda592e2f852e2de41e09331664e1a92f9a0b7416c50327bc943a17b9e00000000000000000000000000000000048614243262dd070a754f40652b96a03326fc51273dddabed85df0654890ff38e0da7abb8190e4ebefdd6f78a5fec509d7f0c0c7e927bed3fb930fe2d0109f58678969ac8e14fabdf4ccdd0823f706d0000000000000000000000000000000008451d24fdc873c61db44e57372d43c35a2a8098255f9aad3a6b244913b86bff6444042e391685b1244f009c5ccde935000000000000000000000000000000001177c2da9972a2b96afaf866f97dc149482fbaaa93e194803c09c8334c2c7025e08cad4f7898959a57b07a545ecf76ad0000000000000000000000000000000016f40426cbd1f0f4ca5ae1dfa4c3960a6fbd51a1b5b24ff5d03fb9911e908406a0ecf4f20a78a280d24dc9bdd1c0799b00000000000000000000000000000000194a8c55f549da1842cc3173f3eb7bfd70df26b43a3059a3590992e34fb19b2caac4149f64d442965e166225b9013e2b11ce517fad2609f2ab8d44ae6263623a7903b2cbec683570949a96fad78fc6d3000000000000000000000000000000000a97664c1d7624cae0e969c728a84130fe260581305435ff8ec701cdc51a73977f58c891ecee637eb6b7c972069ebbb80000000000000000000000000000000003f4ed6a9e9f4229f0fb35394bbc10da9adbf4985d4453da64eb312ec88cb15bdc189a3b5df1af3107a36fc001ec92ad000000000000000000000000000000000ac552c5f6170a70563fcdca8e0c6a7c6135af2f9d5ae6f60a2c459d1be4cf76ebcdf9bcd891db8a1e2fc905a23a97b4000000000000000000000000000000001734a46c99e776d1ed4b807f5b313562e0989ad5c67dbcb961c134f8b7b7601c23308839569dc224bdf7c370c4498303b17d28cbcb9efde6d9cdc4c9cda385ce598ac8468d4fc94cc8e98ca3bfadf440000000000000000000000000000000000a523182c886671435ccc75cbc78293274802c6142465acb31a1809e43b1d656ed9c808068de167b1ab126ed0f73a4490000000000000000000000000000000007c4616080b5a002fea3589d54c7510884a3ece705d27dee315851746b1ee748e8a08d3516d8c6afe1c0482b960a9c62000000000000000000000000000000000dd1bd9b4b9c140aeb97887a0266bfb5696813fea034b78bb7d0cf1cca15b5bb0ed92a97841c8d8cc614f7721b8b7e040000000000000000000000000000000012a41a8941b6f0e4c87f8188718f9bc75305d41d6f4441eb9682473340fce0bbb463e1b922d3af8daea32b8a8ac9c3b4a9516e93416bc7b0f3c5ef5da6112abb73fc285a14093ed19d8eddf241169119000000000000000000000000000000001763ab2b361681955735ae00b69f26e06469391af993c8dc6f2e1dffb52ca01e49d58d6e2249e7433ccfb5ddaf8fead40000000000000000000000000000000003858f3bb01b2393aa4d4d7889bdeb0bb9bcde0dcb9b39c4ffe0fcd0b865baaff75b676c715be275929ff4303c416e0800000000000000000000000000000000086d64bd1302b0b3a620b87ac29cac3d9e606513ec8b47898cd852bf552c1364291aaa842616b92c8936e076e59451bd000000000000000000000000000000000967c9f59c15ed02c9b2da6e76fb0bf3d445ba849010afb7f9c994b1ef6a05ad577570d4adad043796eb90e51537ce5187fed462636eb57506f870ed1c8f66e211758327f4c19bf909a6419312c58945000000000000000000000000000000000e6b0da7b406bcac2dbb90fbf430fda6442cc2860ce633ab84404dfbb426949d55ecd72992da1a2e8e1ce229b599232c000000000000000000000000000000000fbe3a345ffc8fb85cedc4b8dedf9d952c41b4ff6f1c7ff4cf91b2276621969d905aa9aae5fc89bc516f96b9bd1bb3c10000000000000000000000000000000018c2a7fcc35099c41bb851ff66abb047e2af9cf4fa9fc45f030124ea2c7efd26e594abbfc7a7f258c8081a3a80d15105000000000000000000000000000000000a27cd33c2121c9c542e27b52a13275ef7e81dc0c6ece883b65e71d2bc3e7246f95aef7c6b41eace382a1400568cf298c373d64034c78482d6673c6906553151887c8aa28ab2930659671b8cb98a595700000000000000000000000000000000158bd8e6198d22b52efb7f3b945668666e1190a4a8e70307ba5c1b737316a8f8568092f219f683c0f53f56f25745d4e600000000000000000000000000000000097e64e4553371c81a9bf553ddd9719f59b329284eca0d76f023d603c29a034d123ab777cf173c5f2bbc66412d69d4ce000000000000000000000000000000001298cd5501e136a06ad4fcf87a75c0c7b96c73e844863b74bf6aa581a0ea98c2b1f608c668743a3e37ad5ca2074af9340000000000000000000000000000000017ff9f1336d7f2152f17daddde9d3e1679cab8120ed2c0288b0908d4e2099a08c9bc6f79425f004ea3ac4d684abff6dcf29c901f9769a42610958a8cd53eaacd9e5c4656106fab536052518b4989911700000000000000000000000000000000115baaab8f0331894da531ab557bb454e2003010ba1dc1d96e3d983d49b1312585c6d4c43d85dc074b23b2fb28c8a1d6000000000000000000000000000000000db1621b721c8a54ece26a355b190af5f3e1dc1b43e0827a1912ace651cbad4b980e77a4c3566aa809157229b234c808000000000000000000000000000000000c594e0ed3f7ee55886e251deef9732aea3de11f094ec53907a843b755add8fa5d00779a66621e615ba7772ee821c4030000000000000000000000000000000004e80aeff6c4b85188903b4d2dcac4f94f7cb4285a38f94b0becb556d83dce8735d1db5810b409d45a8dd1b9a6dde29c125c12599e84b7e648aab52cd68fcca7f1a5f56c854f3c36e0445ab7e2df2b740000000000000000000000000000000000371a74468ce2ad90e19b7fe3f57159dffb1b0422b32ad693b2fe6c45c5d371b97a90054095da887019d25c1ee8197800000000000000000000000000000000010575e1ec9a3e609ca086ef8bca679c4548482d9e0da2e51878158ac8e5b29d824c31ad7ff642041e748efc50c2514e000000000000000000000000000000000ef36130380f1e84b2f462b5f970abb8535431b79813015261015c6d7e74f038b47504de01794840d93fbbb4b386e17500000000000000000000000000000000018419e85fc2d75f007d1e0e02c1975332e03d42c3b41c50c3538c3625e702161cdcf8913babd2995aea7566ff15abf2bb9a1d051e33a617c25e17b7ca8ae6b02f16c759cae0df7fbd403372eb2407f6",
+ "Expected": "00000000000000000000000000000000125406a942ae0119575453beb4c093d2696d3bea7bc031d7a586439197f848e1d5a82b925b4e96138a3460eecf198ffa000000000000000000000000000000000befcee6bd1412c54674a3d519dd2813b87b18f2ab3375a731197e9f539f8f8fff634f15647e7fea3c65b93594343c2000000000000000000000000000000000011e4d432ee6babd502a9cbbb5cf4839dc6da6176b6bb0ba51d99a3587465f5f3f83f4d4cf2c7e6187de93b859ca61d800000000000000000000000000000000168509010b867aa198fc294a5879ce14a51503c1d0e8fbc02ec08cf62afbd357ceac24b633bd0fa99f83dda92e10724b",
+ "Name": "matter_g2_multiexp_87",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000070a0d060c6e9bad0d1bb15417578daaa8b7a5c984c4947dba10fd874d93fd1e3994337c87799d78a674087678d9168f00000000000000000000000000000000128985b69d5d6ea0ad0b19eba7c2b430f5242a7e89626c66fb83b58ca7cb65a479de4b2fca6886cf55b8cfb52394102a000000000000000000000000000000000bb0bced708571662af042d18956b5b7d797b61aba70823618682287deebe69bf1f9a94ca4059e0570e25a39e60b9a8b00000000000000000000000000000000193f0793324dc78c40f356dde030b632feeb1609a1bd75ce88f0d313a0864dbf1f5e92826870866ab9b3c98cd1c12aa508c35887835bf4497d673936f40ed44145c5d5009fae16eb0f3ee9168831abf7000000000000000000000000000000000a61a310f90a5ffde617b78f784b2e699cd77e7c3e7c483a2ccb768f94d68e59a2a4521410c22ef6f21ba589ec3abdcc000000000000000000000000000000000e6568c83e0f7e459b27a28e5bf954983c5dee478a009c244da16041e710ddc67479cdb3da6f47e7203fedb8f765b2490000000000000000000000000000000001c5cf6b948b85a1c426fe932cd87605f1fbf6c932756eb1bfb43beaf012bec4612d8dd0840efd4cba3f5394beb65112000000000000000000000000000000000e02d5bc20c40d7cc2165a21ab37c6e4eb71322c01a43f2085f93b5b02bcabcd668dab90323db0f9288737d757997631a0154f7f8d52319c9e5cd59052e91b84640efe83ac814d95370e46aff4334cf400000000000000000000000000000000165287d72eca1ecda5fe16a555245b0a34a04beaf9177466bfd88bbc675442d206e70f7a2063b6ed0e15e9406232f5ea0000000000000000000000000000000004c0608bd7e01e65a15716b0c505111a3abb0abac3efb846e05e8db59c063950dcee052f04d1c4e9e492bc6740fafe6d000000000000000000000000000000000de897f7ebaf9089f7e198ee41e1efd7d84fbec7327799b9293a489965cd36159442eb0dc1f79f6b1f122f592b013bb30000000000000000000000000000000009774586dc359e5d20486f00dcea6ff93948c5a8b74058645d1048fe46ae3330dd56d85204d328f43f15e674020f353ec252ac28ea29b5459cd2ae5bce4bf08a102280c093b9962cafb481016a212709000000000000000000000000000000000438ee51a560aa419ad6ae45e1014c38b7c43f1f6a512bccc2d4f10a35838369b71799fab4b6a754fd938c1a1b874fc0000000000000000000000000000000000c1491c85965c0b74d08f5866ca727fd30bf641a6ada0ab8363ff01916c37d10b1b7eccff79b396c587d9beca2c826c0000000000000000000000000000000001452f254ceae9626443265ba31a1a750a425f2a7789e69cde16b70eb319c744a6221e74a9e2881c6bafea161d29638df0000000000000000000000000000000011bd6a1bbded174e9cb95d74492f7b07a755339a6c40f2a1a76debccc0f3a32c7017ca4e6679fb2c038c751f19986f526d3bb5ee3410dfad575b0fbe71ac5df2048f74b52e777fe0955d6e244d434f3b00000000000000000000000000000000139157c34aaf70cbfaa82be655281b085e37d6406df4cf8e291b221394e91d9e3cf04d431f15436064d0bfc8cbe13701000000000000000000000000000000000353fcf6e587e71e59d8f05d4085961d37b1f62694dd5c7f40efb5875b90459dd66c4d2d6c01a40834307ae9e82c2e08000000000000000000000000000000000a4975c9872fd167d0ff4cc80a6ce179b1e6e1eb21c8de80321451b1deffe68d8a13db26218f14935b64af25d63644c10000000000000000000000000000000001e8a2824f21cda745a24844ac0336994fb18e30608ac61201a932c0a5a58f1acd56cbd9353bfab4944efcf2859ad5915c30684c596976bf46384e6afb2bad6f821c4a62338d7a6eb204ed75070b1973000000000000000000000000000000000537d7a9d7d9dc451cba4d50630caed32e182cbbd95212577b8c2855c327530e447a4f3d73c7d63fa3ad5111254c9ed90000000000000000000000000000000006984b32955fac4ad3c0d181c81b98534ebaddc316d51a40baa1028bacd6a93a20d4bd6cad6a0f8cf7ade96bcd4d68dd000000000000000000000000000000000720c392a663884ad4d8daeb7279ac41717ea602108c76519da13a45a77d2acafee842828f5ccfcd786bf7ea88afd01600000000000000000000000000000000081f1d3e37ebaacc11671bfe1670ed65ece2aee0e3b5d746a8d618b44bd4b7dea905eb8e958bc026a092b2bd5a7b87cb11009058bb8e23b0a4294b5cae63aff10265e729d3601d85dd7f1e8063ce260a00000000000000000000000000000000005af33731879a574f39dca99c5c1b9517eda13121221be77a0c1bac82fbf29b37889c15a9d32531a3f6bf9137ce82dc000000000000000000000000000000000c62939f00d70a07a85804cd97fd34b9764565bdba225cdd7549729ceb9735bf4d09a80ec3055c483e1e24b66c41e403000000000000000000000000000000000e415677988c9d4656e59f77c608926c83028f91bf4c0634120b5f774ba07180b98141ffdf727cf9d0fc7a4cb52f4393000000000000000000000000000000000c9c37eaca857151a0c4a49b079f2f061e6a8ebb77e11eb32b29227529562f8dc8e2646e25469491eec5a07b11943f203e5489447bb9a5b661bcff2d9a4153a5aad975abdec380301b6d4ce019bf2cdf00000000000000000000000000000000015113f8f9100cd18427ff48038e1070fd835fce6c0812b7bafa679ac733c80bef56492ec3ca08c1117bd0edf19cb26f000000000000000000000000000000000789cd90c0be1de5d0b359c030d4b9d8aef93951e26870e37c375b9e7879cf277971a05babd319a3a6ac53f00f3254e40000000000000000000000000000000019b1cb91c9a1b1ee49c3837339778806bf0c093f171c92c9931ad43e35fc61cc08dafaf55b7b9e0f49dac28a12bcf92d00000000000000000000000000000000066c7864631333226f191e313436453e59f48f91d42e68874fa4da45eeda1f6f7f6342204e64e124d5ecd861f02ef4f00444d520ee01d87407747a4ac37abb7bd4e4c4f1735ca7458cc2e4dcb1d6297c00000000000000000000000000000000129d887d694be0ef2f84c343a9aebd0a2aaf19a4e78586470351ffaf0b1309593363bd9c6e7fe39a6e59445d935414ef000000000000000000000000000000000596d7061c2399b6a9be7d4d495e58c0377b18db1e45cf3eb431d10cb8b15ae42548a86a26086d57b1a71cb5857d7917000000000000000000000000000000000cce7181fc87dfe1bb493043279a5d93cb2d980eed38dab2ace8c9fb335c2890447434d80df6e7c95729933ada7b9d8f000000000000000000000000000000000f0e1274ff70bc6d3f1d0d5b251ae528ed94aa3a1b9bbdb260892bfaa6213892071b8a6407abe26105b2f81df90569492035cab8f8120ea8e91389707a290db4ee69875d7429c6857e74e8bd40dc7360000000000000000000000000000000001192050735b114c19eb2bb9aa01f04d1fd9bed4df877113a14f7fbc9c31acc10db3ed0e0d15d8433e7408bc237c985b9000000000000000000000000000000000a8a66cda780790311b56836fe69479c7b94dbc6c82ed5886887dbb539a40390ebb2683c04078ed105e639a2ed8732a1000000000000000000000000000000001678ddff677b99011c73e0c9875b5b2ba063170f4d565d261b4c6d3263ccce0334b5bbb7ee08692568037fa96782e48b000000000000000000000000000000000ae15f79ad7f790f8ceaf7709f4b5da71642da0c1f7c442eeaeb165c7dacd8a4892fdfc8447a03a7c56e12513499e43c4bec711286827f0941ffbb451a8eba871239341a60e3aaef23487175c9d2e8260000000000000000000000000000000007fcb5ea5358074d06b64c5f46454e682dd9ac2127374c83f3ac5ad46bc5fd2fff7c5a80ffc669a1c159ee8c9a01bd37000000000000000000000000000000001010ada1bd493d6282ac2d3582480f50074a02fdf412c63e93c5857974626ff464150c20bdf23a87692bfe69a075eeb300000000000000000000000000000000086bb5664a8738f02af5517aec4c6db47653a6d76bd4b5e37ba4d8b27a7819e82e6a4c7ba4f8377e06a5878e7c0bffbc000000000000000000000000000000000be1463ab76e468e47e1711c158dc9bb10d1278f5cc676cff937f60ba457061bacdad7b8d3286f40219963b147cce4bd369d91a4d575d4c142b98a53115a792ec50a290608ad316465487762e83f3a86000000000000000000000000000000000c3329d1e1c76b0bcc7ca3766b2cc5ec8169690f45e0ea3e37b7173bfd6c884921c7523ff25391a85b47d5de395ca63b00000000000000000000000000000000081ff066c008d5a4c893a636d24e9752c6a06666dcbf80082167610e73a32d70aae3e58c88ffaa27f05260b86b11f72a000000000000000000000000000000001178e88c652d257888cda1c0b65ee2c0636184194fef9e6ae3791a85417c43a31fe75893773ff3e7b4d4cda9eafa8de40000000000000000000000000000000019657ec4604ab5e8812237a28e5ff320a0d728c60c541142ffd87fec2c703665638e5eebc33e308d5582cd043d08d788ee472561535a7710db521976cef0c92a4ed89861ecb397cbcfafa477756e8e120000000000000000000000000000000010789200f69d8acc70f108145804b62b521a30a04176c449f52bedff5975ad7b273aaf4a32f8461ced8e92b2229e2cef000000000000000000000000000000001178c36174cdb783b5b09d419ae4a154512bf9ce07368521d1576b2f1bf39f98be29bf533bad16ba9d96aae621612aa70000000000000000000000000000000002580f2115d1814667b6178b6bffca6a4d992eb66e9601c0d21e32a5f3b69e3f85e1205c877b2dc2696a0e872c5bbc6c0000000000000000000000000000000002c94d7ff016d57bd5f589971344c6499577bc2234e18e6c8dfd7d27a205442a4236ac54fe279d1bbca76467530140b42cfdcb8240f183abec526344e8ceca6a007c35b757928803f854225d3a6ca36100000000000000000000000000000000108b6fef7396ef71b46339d421726f83b08320599d66da18234011720d2b524d24075a255d2771f1ae904958c50a9046000000000000000000000000000000000723d5045b65c0887da1bb01d874714ac86d21441119a93a1d5758957215f399f5ef1cbc00558db01b295bf0cc988cab000000000000000000000000000000000994914a3df9d3094dab0c0c41a45315dce5968a99e6171fc609ac9e50bee5ccac771efaa04067467e95709bd924973f000000000000000000000000000000000ac746602f804f52e9a485c30412adf92eb9af3f6daa8f23b974339a0ffa6f5aa1b70a80a9f19cde2a69a4b7251ecf5d60659743dc1977a698371cc302b7579b6d7d13632a31b47df369365fb02aff790000000000000000000000000000000000a2ffeaff148dc5f70fcf53e7e8d7b6100cd6e7df5b3fa4aa33bced243f15b4f77f48d25f74366a693404b6ed7d3075000000000000000000000000000000000f3e1b34ac8fde4caedf3d8c3e24db02de3f91487db300f09c779e7e4e96ae55229288abd946abcc3a8adaf18a0c89e000000000000000000000000000000000166a68c5191dd7f9d44eade2ef1a9b522dc062bba9c55e2ff03aef400e5d2765a12816b4ba51e10bc21e06113c8ddc5100000000000000000000000000000000109c00de20f7e827375c1841348e684fdb248fad116e9643dbda8be2bd06b71db264e9f2c40dec2092e7d518540a6d82652a5d4fdf6d6703c857fc7b10a741b95fbce91fe823d827cc7203be3b3bce0a0000000000000000000000000000000014ddb61173359514226c150a3343576b04fb1b06fabd8fe2f921fb3b90baf5513447c107f6d2f96c8b03274bfe451dca0000000000000000000000000000000001d1064860f6c4d62a282147308e80ceb0c5dd62f39b3232a231b1b287e497df31cbc5a3905a7687eb2f24447e50a395000000000000000000000000000000000859611bb3962955f92bff861e03d07bab7fe1f69e90c6bc7928be8d1758c9194ff7a52b16472d04564607b742543eaf0000000000000000000000000000000008a3e8396901a205a071aad06ba9812207171f33775eb358de4232826a5f0ff50ec3e137b1344b583849e8a5b424b46676a30abda185e7d280804952fc0c074ad907fea2aa54da4c3190895270169b20",
+ "Expected": "0000000000000000000000000000000008c9db83241e7f3ae6c2eac8fdcff5f2d35318e24c3b4130e9bb7048a3b84a52fa3f222a8190121d2a5b8835bf911bb200000000000000000000000000000000002db79cbcbabf41bd8c715e024f4687bc0d058d76b8dbe58ffdb80918212ab6e9b35256fde583c0fe903c34a4c41ba70000000000000000000000000000000019f37d05f5c9e65c6f004e1aef03ff0e1899f0739c9cc4e9038e18f9d45678388454d144495b2cd993eb3691bf3e96f5000000000000000000000000000000000d8e0d7715ed71291729bf480f5fee7ae04264015732677488472bedc0dbacf8b35eef7adcce196e3bba9cac0991be81",
+ "Name": "matter_g2_multiexp_88",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000064a134260b753af73df3764ab662e3b1bd624c8f3248e9bcf7676d8fb0825ab85ea33387d4641c81fb8ba3757e0870a000000000000000000000000000000000d67eff1936a395cd3f808ed7fc89f8b6a227c4849a6941d4bf762af6e41ae41c8114aeccc2565ba01fd902df530df1e000000000000000000000000000000000110ca2339832e7a9468844b94b3ced0c9216654bef1c8a5cf66385a99d5d452f978bbb7fe15fb477f56753488fc909b00000000000000000000000000000000173210b548d1b98b926539049996713f53108cd2911105235c1d5258360d5620d330951db67219ffaa304a67fd6219f39f4db766964c7855daea58d1205fe8da572aef06e0ca64912cec7c87bcb2f51f000000000000000000000000000000000f7c3795ac3d511f93a3d85e65261e4c09cd316787f74ced6e472a3993b7b5b0ce5a7c91d99559a8e0791f712cb4e1700000000000000000000000000000000018eacb2c5fa9221881c6311256a69c7616748deb3235c61cc11412860450151a25e3d6a220bb23e0b3e3325044fba68300000000000000000000000000000000121827286873ad31f58cb3889fd01cb7d0f91ff1c241295f6ef2dd0e8aa8638b63a7e6061efc2e7ca1d3579b4868f0460000000000000000000000000000000003a57315175d70880b2b53c67d61831ab066b08d7ac68637364ab1c1f3efad96d42a3cf5189c45012c1f73a1b97bdb4c1deebc727d98bdec47b5a1fc48916dca1e42345ff5474a5fd6cab0ae99e9f10800000000000000000000000000000000180648e5d0bf727101417f515cb9578bdde3e9f6c4176d516454ea7c32c1712610cc8bbed303bd1afd48f580ec11b77c000000000000000000000000000000000d6ffa9b85d69b67abb77f5c8bd776eae82d1cb055d2dcdea31ac66b1825014ec7f7a2aea320ef9f6897c9aac8c0706900000000000000000000000000000000073214fedbade28cc60ecfa4e1fe2fbc05f3d71528aca315312d50214f680956bb9e0fc12783843b00b3f4f0f52efe2700000000000000000000000000000000128f87e7da7b53f28944aeb26ef0f6c99d84038af51a1d242501ec84b5a6a8593ef1a0f6b523478d9fa12e36c2fdbe694b964d74259c216c1eccd7f2b52ffa5fcf151d47bd69bd2768e6466b32eb4fe50000000000000000000000000000000001443980d7450af1e19949fb328776cb7238a9b26240cddc565aa9d52c5592083b1533e8103dc07eac80e4bd830f209f000000000000000000000000000000000afdbea7f1cec534c03d3269d50017372f7ccbcba9f096fdb2754af4d6b4956decbab2b0afb69f97a03beeb20b4ccc31000000000000000000000000000000000a83dfa3197dc65097601457a97d0df7710e001e90657b150e289515609f13997b454167a7589ef218893309460139f300000000000000000000000000000000029c362244510c342358130f877de947acad5a379295f3149d5c713274316e06a169501f889e4b9cbf86f10b9521c1bb124ceb1dbc8004a4b1f8b422d394b0480bca7c0f38aafd8f06ba090a98a1d3c60000000000000000000000000000000010a83f13a185c70ca3f724dd84efcfa3ec463d7c05360056f8b5304864b20025b0a82c9d542ba08b645e2334f176472d000000000000000000000000000000000848a6a18bcf64d083e118190805d68f7ffea8b5a66e0807b9cd3733d31ffa5cc25dbfa6ada604646dcd8dfa622e08a30000000000000000000000000000000009962205c0ba43e5101fc3d5353f429a57a97bcb84baa0942a7e7facdfb0d032b9307aed8bd2ac9094a2e5b1460db7140000000000000000000000000000000019b1012661a10d31a4a73d0cb31f7eec0e7be729a42baf560c1e90a9124fe8d5fe31ecbb6d4954dba7d943a7af773eaa5a2bf15b2ed08b33056a0733c920741f86730dcda9c06aa0e3c135a844cef916000000000000000000000000000000000e7f02c1d2ceae60f314f51374b338c329f2eaa82553c3fc1643c7f1910ca24e277f3d658f552a47f780d4d9e0ac5e030000000000000000000000000000000014b6b56afc4afed5199191ec13dbeedd797f14ed493c25658a9658f031ac8d43de12e6a8c4b1671c9e5ef78da1a55e2600000000000000000000000000000000194d8a50618ff55ba3fa5602d41cbbeadc01a348ad1484c5e9aee5fb7241fcd9018f436e3c6c6dc64beaa241513a6c8300000000000000000000000000000000052681eac4bd59e160b67ebb27582a6d3ad5286d652787a0e160026607acfbfc5b9f38b9b171375079d052cb242b87fe8c3c919f31d72ab414f91938089430bbbeaa53ad7a73224fd3f204b80fa1ab87000000000000000000000000000000000d96ce83d917204e674ad9f5e5728651f5f23df25236b0fe769be48adf482ed8c36ad9c9abb6efa3719bd35324bd700800000000000000000000000000000000107f55ab0e5b60dbcc0632c345a9e93818014d7657b264031709275744e1c6722ec63aa209e655878a57704ca6cb3bc10000000000000000000000000000000018d97fba324431fa28b8845d94f62fc9eacc0253134b923908f06889d375405b51610ac21a75bdfb27e3533dd4debc22000000000000000000000000000000001667856804a5471238ffd64bf3bf266ce3a2351ebc68265674bc86ce6faa8dd50a3dfa00c647fb4265951b3a9607ab99f749063165c6db0eb038cb9f1a573de25bf377e1fee94f31df5987f7b2450aff000000000000000000000000000000000fde2fd0349e7a47a9b6858014d551aea569ef9802629bd9520e303ef0487c9d2d399682ac16ce6fa03adb6f4b478fa5000000000000000000000000000000001858ae58920dd0abd8ad94d2f9f946c53e050fe89c61f62fccad37e17f8723a4fbecb6b1be1e3cb853f045d0dca8e53e00000000000000000000000000000000093615a7f9d12e92c90706a47abe9620c4db41e95e42e478949745d6b73e021422e40b969e9e34263778c8a4d4907445000000000000000000000000000000001006ae7963b1e1c4d8c2c85175aca958758fb380019825b09ca3f728b5356254ae4fc670aa29812320b921b48a069df622d292cbcb836843acdd5a3fb404024174cd5c1cef632d1b9b6a73f2c5f705a3000000000000000000000000000000000ac407b75ea77789748e7607b5d6edb1d891875aeef2802715ddc393818fc8cbe82cde9f96377e3ac60107ddcda7e6610000000000000000000000000000000006e63e49356c38b816736d1d7c360ceaaba875c53c98ec68cb825962531855dc6410a125b914b0ad99f6f4327f5450890000000000000000000000000000000018ffb4ac95b8ffde112c8bdbf07a1c97b1d30a42dd4a97c82617698617ceb169e8702437ff6082a2ae387b462cd86256000000000000000000000000000000000497c4b3788c4d6c9b4cd8b3d3569ac4b4332b2f76c5f03f112e089bb79d33152b2469f7ad3eadb8b954775aab73f47de816dd1bfe025685f2eff0856f9c162d73a58fdeae0dfbeb5ce076e9f9ec1a700000000000000000000000000000000003e16f2f5a2fe15fa02b6217aed7dc688dd2670c09c02791cafeccfceb7d99ce826bccf213f6a7c6064687519f9283de00000000000000000000000000000000095e6638ac74815dc451b3ec85a6a8cc18643b541e8be99052ff6dad39c971f2e8bee976ab2ed5e1cdacf92816249ded000000000000000000000000000000000f2703c08b1d707fb6de215de80b53ffbf2ac48f3dd059d2a952b1031189248fad27beec5c8591ac93625a08e3420f0200000000000000000000000000000000024ae36412ba6f2fdeb0777b892f1ed7bab0527879d93f7b71b62f437f5c1ad1f04a5a7380ae5990a455f11870c7208304f117d41a011d36f55d0cb53d4f98de3b1a6cb55dc8a76b29d393bc21826ea0000000000000000000000000000000000f7ab1908c6d4b152835f950b604b55fdda7eb55c6b90c05e98626ba7cd014683bd3e219fd0d5983e9dcfaaa5d389e560000000000000000000000000000000010b285c2884dbdd540d6dfeca704e00839337f12d2267f6a3fc731fa0f724cde19e268782b4b9c2e11ec3aef9a72a6ed0000000000000000000000000000000014a40cc55570e8f45369bd9dc622e05f03989bce6a98a0d87f4fa7add67eee3e2ad9a297615dde05e64203e86153ec230000000000000000000000000000000007f2b6a092adc595e4857e821579801301396321d4a20bccb3296a031d74a62bd79ea4ea094d2e545943138d2fc930fb6b6f5ee0549b28a1bb317cb020ae0e031dbc381075772ff582718fa49db486d200000000000000000000000000000000108834a685455dc0be10aaf54607a06100673140b012ef23a16d3df204a81dd8505d62ca3e0278a2581abc59e0fbc421000000000000000000000000000000000bca7130de9896e8d6858022f24308af7ca66fb4c91f38b30f717c5491996ef4cdb01f4d38a730f9ba9ca5af5ad1de7700000000000000000000000000000000007d60ded107a06114afaf741dc8826f9e14bac6014eba26089c4e31a73b0f30c4b6e22533ac0db7e73621cecf753590000000000000000000000000000000000b538213a703f7a0bbcffb4aa8ce25ba2a538bf599d3c0251f5e8acddfd596c9912d4cf9a1bd8d3ec070713328ca992205edf9812adf95c9844b2da06f75d96e742c0620d1cb0d47dfd9b68d0bb76128000000000000000000000000000000000cdf0b9bc829cd8537918d665e5bf344d309678d01ee80c71a6d6efb45ee8a7beca35bb5ee046e0a3fac76e1771520ff00000000000000000000000000000000014e5be9dca2f8ee4da18e5ec9c4caa891dd78acc47f553af584308c72988435b85ad21b14abf8421bdb9e25164d568f000000000000000000000000000000000accdde22a1c479e47a17b8da6f1d2b7f780ac278c68a68090e5402977d897bd734f5af8164118d613f480c1f65e5d8e00000000000000000000000000000000029614458afdf6b572bea02a0af987d178c43650ca1c80a297b1d31e259aabd3e2a2c8e4b2c044466924dd6e5e3483e6f64a71e4e7652860038df67c99d97b1e5a063370e65217531253419bf2e6365b0000000000000000000000000000000004e45cc43d4d10ed878e18df156062c799a687b8e6beedad9fa6f66ad855cd053af6918e234ff9a43561da7e67f3dee10000000000000000000000000000000009c9ae47a76c199c93c38e7213c8d6c030cfca709714c703839b9ae9b65207e83486f9c8c16373e2b37756f3fd4355fd0000000000000000000000000000000001594ce9c2e229491b22317452938115747515ce62a0d49f4dd12667f5b3e7b541b3775c9b1363cc185a539b9f7596330000000000000000000000000000000016bf68e05e32168c69ad67331d7bc88a6d130fe8aed3e42eddfeb1d92add266eb69487b246a3ca961ea6ac0a35f8da78059bebd962501b8381b67c22055ba01667d916932713d7ca427cd80d8f76b41900000000000000000000000000000000080d165c57354f87008eb97610d4a596f180e48ed3190779591a0f7e07278f8d2fa6cd21d1b10e6347f11bd9731fdfed0000000000000000000000000000000008d5a1e66ec76743ca366be80fd1cbd5efc9112dbcfa84ce6c44e8df03140ca5f07d4bafc6c6ce5f2f190ede55fe8718000000000000000000000000000000000d0e1d2e5ef384a4fb314fdce54ab7895f895b3bc669acffd48e92c6320024d4f371f42071fceea550c8cf68615b00960000000000000000000000000000000010beae4ffbb68cf6e5d0683dc0629411ee14563f84788d50b1c8755b0b06092cc0f0ef7b55a39d51945b5178e374f8e047b3448b9b404e184f7ff20466aef3dbd4e08375673ca31fdb303c88243fface00000000000000000000000000000000161486d422462460923bd98834f0cc270982087697747fe40eb9153a7923d48eda191e4e7a75964f18f1df9365901a360000000000000000000000000000000017ab168a4ec81c8db4a74d529670fe6332b3870004f696f3a143cd1a62abd747d94afac9485e5dc19b0f4262dd379c990000000000000000000000000000000001e9cc85f03039ea53253f0fa2420012171fe39ed8696ddfbed57b80b73476171e59631388d75fe43aafde52aa14a64100000000000000000000000000000000109a5d5449002f4bdca44c0bd141175d5ca1cee449302f0314fcb5f282f022a7a3cef77f4e9fb515107e797726ff51d767d9d30b38b252a0661c12dc69127ac380f3f756144801633e99bc2ffa2f463c",
+ "Expected": "000000000000000000000000000000000aaa5de171664fcb45439b17a024806ff7e07d02294e0592ca74752a5b66f3365d1b49d6893b3bac3b8b0d10d026e48d000000000000000000000000000000000418354ce1820ecf848321a07ce22117303e5a15169a9cbfd141fb4797de8871d84d577e86270a9cbfe31c088ceed0250000000000000000000000000000000016884caa03ea641e0660a790975d77c5bb03568f873800d0559b69e3e0afcc10ddf031bb5c25c46f136f0791bbd3cc8f0000000000000000000000000000000002bdf659df76cbaaec030448e8f4bbd6b424037a8dfd7c4b8ccaa2224b0852c168f49c6f45c04f23abc85b8df21953ce",
+ "Name": "matter_g2_multiexp_89",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000062bad6816308f1c8c6941980caf71929a4006083dd29827902ffc92ebd9b14f1ef662f3a0125b1e74dabd039f9106400000000000000000000000000000000118e4ae76e2c321a5b89eb19b58f58f44e80dcbc7bd6d619579da40e1156aab32fe81df8eeb1bd047f96d65aed8b3b6a000000000000000000000000000000000c8c93e1beeb4efe52a96e5d5612338721e3e487c13c18b02475f9ccd8fafc2c95101aed291951f2031bee5216dba26f0000000000000000000000000000000016fba44e9aa39a12ae27e3c36de1f14e3f37ffb0ceaf5fed2a0d9815eab02c5aae91b254812a8f3a2e3654cec01a341caaea75e63204e177d404898aa51555767f813c3f3ed283405ed1ee829b04c85c0000000000000000000000000000000013716488daf8586719c52fcec80d35f17d4c595b66c7f2138244f3c8cea69b819778bfb50e49ca1d092e57c51674fca00000000000000000000000000000000019cee25c4731bf48602ceab23b5fc4f764993443e3622107b4c33b29c23d1b5916380431b7ecd94a0ce99811fe6dadba000000000000000000000000000000000562b28b245b7c1ee531a320fa0f4e12d7c171c7e3932ffda6cfebb123fa7f5993e5ed5e7b7d295405e5031b339994bf00000000000000000000000000000000180c4a8158a26d34123c870bc694382352a8e4de712b650d3e45e6baa16d6950ec15d3a4e032c1d1ae8fea18faa6f3d8db48a90ddcd791e6a9debfabcb1c71c88e7ad98f9e739ee752b381b28d7656f20000000000000000000000000000000008472d40e0505d6b8b92500e8e9711112048611fcdcca2377481ae86a7f6da1571f179183301e2194a42dac3873a3ba5000000000000000000000000000000000e2c5b61c050a8a12298f76b5f15383e72b90b001fa26889b67a24bb374b63c1e00979b05450e44ed63e72042af6d46e000000000000000000000000000000000e8723eace9c7a72b3e6097afc9bcadde61462e2ee03fcd5ad1b1c0dcf39f437f80530c2a1c5e6ecdaac14e8715f02e30000000000000000000000000000000002e21e0f451d035a5257fb09e9ed17b27f0994e6d85ddaf8d33153628adb194c97db17656351c029be4d3125bd29dc22ad1795823d3834496b0a1c2c07431f9d76071db77834005fa1228393ad4ce3f40000000000000000000000000000000000dce49634595869d7858e95a301bcff8112eb73dca8a22042137456d6d4887998a541489ff09f8e006176e6beee4e300000000000000000000000000000000010835f7336dc49e62706da4ef21d8e3173629b16742c317c1b397d4f17ced40a56520ea63557d7ac7f251568f4eb3a220000000000000000000000000000000017446ebe659a4510a362ee3b406b636bea8f381503e51ac21031c7cc92acd23046d62c2f32cda01b680c0f107142ae7d0000000000000000000000000000000006ef82deabd8983ebe4255d8e06f4a1b3585c057b2a1ca3c3e1cf04b582b65792e9980e3a1735a8ad58b053b16ca03d036d56e38fe63e573b02203be04ef9e1a044e1754eb2db50c6f9804abc4a40f46000000000000000000000000000000000cd8e7422ee179a0499178c3848cc4fbc87fc25c8c882f036a03cd9d3f273f7f2bf71bd3c9cf5e30c42b1ee6e90b36fb0000000000000000000000000000000005005a471d77a35e922b6d6a45b13a90947c2b31d8e7a2e4b6388265b039ce23ed958495dbf904186bef60fd547b941c0000000000000000000000000000000006c337380065eb8a5f63cb20fc61a9eec4ccf0e23c4e0f231a5bc4d765271b9c5697bbde692b4828ae22ea12423ad932000000000000000000000000000000000f7a0080cbe72a6e6473f66ed729f58683a80815a1748e52f7b67a6bf2846b7df8e7dd8599f87fe63706e9823bfe00d21a6b36f4674ab19202037d59fd8e14369e5d3d71acc3c76985b813d81ca6e24a000000000000000000000000000000000c94834474ac91547546d7d179b2091e33c8812c1b582ff186e69b63011177283a74b549aa342a7f3882ee82ad8ecc03000000000000000000000000000000000d72c4308e9ae695acedb9413445bf6a40d59ca78bd4f74ddbc1bcd8508cfb521bfcca99c98dad8022d3d1ccdd98bca9000000000000000000000000000000001487d006830d00d84a567c5d031019035443fae4791a05253f91249b32a4b3e7b3ce7eae885b8caeaea411a90b3445e0000000000000000000000000000000000d94f17aa100503f605732a48e4f55c394a8df1421a3d7c78bc85f4cb7a53744eadcf76e1620fc54204b123d6071cd3bad85286877fa7e5a9a61dba9df5ce35083beca7c2f5ecad13d226fa32b9720e900000000000000000000000000000000101cfa8d9c7522277f2bb4bae6c09e8b93a876c749c91c61784feeb105be61c2479375abdaa81deafc2fe754ed6cd9da00000000000000000000000000000000089ebbdd489ff670a70218f5aaca78d4e7ade483c7f20de4a84d39217be8f560fbf7bbe36f3f8b8361ba16d17ce609d200000000000000000000000000000000094f094372b2315fabc219099200e7b9e2f3a2f6fef2ede6f83c82f44792da03aaad06b8cd06dc3f140746bee2a45706000000000000000000000000000000000cde6cf9a3a7018b2b1c0c26b5850820080c7e4b56e615d577a78565431c93de78348d2851d5ad9f120ddaa9ff3da31b8fa5387c5712832b52c9c72e10c6f69e9c1c5b278aa379140e75e404c4f50a2c00000000000000000000000000000000059bb8e5dc5f0cd31cf674ea78b80b67b8a8a753e51284a2ab37d3f29459250d904e70ed00481b73556970a7f5424e5900000000000000000000000000000000043c6a53c413bfa2f4bb14ef296afd97ce801a37fe63d11a842f8d66160794c1a651d70f4c836af2c73cb1bc58c706460000000000000000000000000000000003e7b67da1513656f7b08fc5a77682477349ac57e53687c82b6d98772b5f929a2b06b0c7e14481d522aa94fa3a6e1cde00000000000000000000000000000000109e07928216eaea36fbb20a38711e73fdc26e18a6967b54f308b10116a5c8af0c8411406ef6ab1050b61c23bb746b0a3023298162ebe7f4ae6aee45a8a6ba602c3942a8bd6b35636fc6b85596a582e000000000000000000000000000000000166f26d3d26cd48e498578900a8c830ce9b80f162c4b430749651b945d9f60ae6a26306ad7711a1f9d3428946074912d00000000000000000000000000000000165f1bc59c9c36d12754097ea83e9a63fb4ae5d1b93a1b9239a6f338cddf4a9b30415d58076852288c6a467ce9b6b9eb00000000000000000000000000000000198e73619cb93fa6a2bc700cd400519d11a7d3d6d945ffac9754a6faf37da8596b49b7a3a4f2cd899ec9c84f1e79b7ed000000000000000000000000000000000a4740820d60034d37bb85e3e622783852779d36d6e61f81a7eabcd094993dd7d81900277550bb4299d550d2805466aa8ff2430d2f82c6d5e7424836ecea15af0ba2d0bd6498e65c65b6cd281a7b8f28000000000000000000000000000000001714857b0ee07b94ea928ff57aae9fe003c0c85d8564456955d14fc8d4ae14a7c9bc303983af3e2999c6db2d000ea51d0000000000000000000000000000000016512cb60aa372cf5098ad514291d8168ed31bd755861dbd9ef020252c01379d343a9c058839cdec8d14f2fb9da0db80000000000000000000000000000000000af74d8ac711b6590e7041e80ca40dd4db659e42b950bdd68c56d676de654c1a47867bfe6483dfe1971eb7c1d1a70bd10000000000000000000000000000000019e56ca1ef3fffa9e131fc5bc93100577b062cf9b2acd234c79e5e54aa799a389f30002b4bd683edec5fb100f1800d66415eea22058493dbf6ac248fd2ad8b4734ebe33761f2177089a3feda396001c00000000000000000000000000000000019d1d1e1e2dd4ab86df81a8246c902a573d1fd1598050663342e411a1d1b3c8849473c689afcc8e0ce5e51a9dc9c3b6200000000000000000000000000000000190d7c923bdd6336fe3e0509563b2eb6067354d8807f66e6052e97d5997464b9f07f29f3022f78779a5c4ac155a703ce00000000000000000000000000000000128591bb699c18a7b9e6e4e894654853f6a68233dfe8c744b42e057711b8d0efb3a98bab6aaa40ae7675d9200a8427d600000000000000000000000000000000045e0560e0936b16d1e055d3d3f4e0fb42d129546abddebeb78e871d1442f4796d939929d354b0326b95e50fd5208fa9ff79e3ef5d32a751b713180be37d44ae55c59c5a8121c132c5098ff972d8a97400000000000000000000000000000000092373dfd7d4375d6bcffa415e5b36a31499e881a80be32400105a6d56b34d64f4fed09f12640a43289a710f034b71e6000000000000000000000000000000000fa75d6510b3b58a32635a7a6cb4b9255aa7af46905cafc893f29b7866e12565765bcde498dbe87df3d1dd53ab5628320000000000000000000000000000000010dfd3456cb6a8bc853b390380a13f045ab43abd289fd05e7f98839477dea1fb1fbe38ca4f5bdd6691446ac0219e453000000000000000000000000000000000112567397f3fda84db6042817a99aeccd0c46a11fd3ba44e2600deafaaab7014dba98cdcadf81b97272fb7f275ee8a4e039bc7274a3ab172285d853d368da0950203a48ef61b3c7564644762279c1ff30000000000000000000000000000000007b397f093e69874d2bd3592489d93c80d0191b157e71d08a6ebe73063f77e7c5e084a24b34da2aa6354b1815a694185000000000000000000000000000000000fcede3a39dd5f905d072dafdb6f56d85726f6f362f91f079fcd47a8c1d3bdcf199d64edf17e3db1dfc96a3e59f69bfe0000000000000000000000000000000010cfa13c84e750d8af8bbb88bd6d16adf3bc7b532447c2e6accb359a5576be08c1b25f336047fb8e01a4d7f9080d0392000000000000000000000000000000000ca0e88b5c2035bcd3a65e8bf1aa219cf428b6f80617040ae02a0ed41559804844df373ac61a85899bec83e5a6243ed42c47d0b1fd24c1c66a3cb0deb7d51ea19f0fc492f637ed5d4d03e102cbdd055500000000000000000000000000000000021f3b793680e0e3127fa53034e9fcf286f5279cd167ac1e8ba051c440aa265ec6d28fcc2f6d3bad126180efd4503fe900000000000000000000000000000000182b429f27996ee070ed27e7015bd70191b814bd02ca6558a9be81d6898161aa525197c1672ae75da92729f2fae9fa3c000000000000000000000000000000000a20b3922e07da4ef6696de85754eabf1f58f7f5d37accb6cde4f62066e789bc64bc8ad6ac827b8c955acc858b03d053000000000000000000000000000000000814faebd3b60fa1a8fb86b3cb57d36b9c85d4b28e97a2251e6bc1fed1ccb18f17664321f38f3723cf8b09a2161c6aeaab4aca860ae4bc20d33808533c9a70108b153bc4b2256003ad4bbc11dc92898500000000000000000000000000000000159f9d329f929a65e41c7a0d4c05e11db61ca7d6d82f8b92a780bac66568694656f4c845a730861fde9a313fa49bdf0e000000000000000000000000000000000d556bdc8dc959b00f74209dff27023c5521d387a40bf20ae2a98f3f55318eddd347bf1e9d856f43a4b5fcd26c3567ad0000000000000000000000000000000009b4b0cedf477ef1e0f99627bdd7a7afeb9e29afbac553a516fab479913b23a9be5e0b38994215a9e23849bb664201ee0000000000000000000000000000000010899f4dc55ac5d1f56a7b8d55ce7f6a5e0a8647bf1ef6e9050f00c5fcac9f679f138018b9aa611be73d3bdc0af2056e297500a2747f9a68b2d8d9ca5b0390369d919897c53d422cb76c5a283c38669e000000000000000000000000000000000226c8a6b27437972ce29c2ed7e5cca4b6691e3a5dbbe713b5d309ff2f4cbb95e8f1571314444d65ff5fbc3281f9354f000000000000000000000000000000000282a49d0c560d873676967700c1062013a2d4beee96a09af7e14436fda4e3d2a32ab8ee4e591decec39a811ddff130400000000000000000000000000000000167bfe499f1f4609e67134e12ad91aadc37bdabd0055ecf7f96162c39a02a86e62a7b3d39f514f63edd82d04beb1958a00000000000000000000000000000000191673ea5470e4704e361f5ead1c56371d6aee3035d92d9e1b96fd119c4f877cde6451411e441fb45aa9fcb90fe4c66ba87ca4cf226c212c80f3db5e4e781ad7391fb73b1124d01cf893169d1c50ca99",
+ "Expected": "000000000000000000000000000000001488532d83fddf0bfd69b32f965790b3fe4cd9f64e8d17e78189c346518c91e69db2f0b742cdd5804b3db3777dd931230000000000000000000000000000000016205c470c6371d73b012a14d519bf214ff10de458605097da1b798977bd938727c5be19a10f4f492f301d2ab6c38ed000000000000000000000000000000000142cc08f61d3c9bd4c7bfd0b7a0b8693af6120898fcaff49a7fb5abdaf1d15bf70eb033d6ff09a75995547e6856c595f00000000000000000000000000000000164b2807e19135ca3b66bac9aceb371165c930ae063f3cb5a06efb8985a1e0c39023d8f01df517713796083e8c2cceb7",
+ "Name": "matter_g2_multiexp_90",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000023bec14deefcc20a90e439bc16912e90191dc7142234b1870e4e8d70c56f695d5cd30a68930ff9b007bdcae8ca90d870000000000000000000000000000000000053a6e226f3bd82150e08ec3690f36616d5ab745b36a9990baac7ad3429a41bc60c7f7000ceda4cc9298b10043639e000000000000000000000000000000000b81b331589ac332093928faa60d6819d3b5559d32d37d2cc13c78aafa1cc34e32d317695c1c4b4979baa1865ced90150000000000000000000000000000000010dbac5e52f9a046ab88aa36b3c5f6952720e174bf8f1732e886e66e5803aab63642185aa24ea08c991edaf8375bcadd9abfe7e05e8a210604355a77f64386a01323407d9f25397769cc6dd141bc6643000000000000000000000000000000001875ef3f90df03d49ce6cede2c791b4d8503b75acff2dcb1c7c88026394dfe11481da72de4ff58ee9a98e75577b6398c000000000000000000000000000000000c8ee603d1404e64ea3ff08c70b3dbffd318736ae95f9a96ca07ddaa449818e6c5a17b2970f572f53c90be893e5c323b000000000000000000000000000000000f31af63c68481f527092b261d29d5c2daa95873b68899c28ac7753d95a64f455ebabedfe6e72246e494cc5fa2a9bd040000000000000000000000000000000009fd06bc51d4dc51de9fad6d1eb763809cdb5ccdba8e0427859d878904bdf295983b318f311856728078e7cbbecb0c5b64be08e7c2fd15ac0116ca941b85615c6deb38fe85e2c0fd22997e394b8a67690000000000000000000000000000000003ce75ecf6b605ce73f4e215b1aad4799f91e624daf0deae3a273968490bdbdbd0250686ee91a1c24c2e2f2b6024fa49000000000000000000000000000000000e4d9b65d71b7593310fb5145677d170663c0ca29636f7b7c50ec1988bd2d2f1c41d542d4cd8fa23fad94bd6a84aef5b000000000000000000000000000000000fa4accea53a6362651f6c6ad2a68d20b5f549f8eb961718e0c14cd05249a121e442a6a588eafc83d6a43d8baa66882400000000000000000000000000000000121e325406767852620ddc45677495fe3e0851fd3c70922896a3e92033347d2fe8d07f4db8f26b8127ec39d619d596030c391dff1c0c303c77b2a1fff24f50250dc793338f7d7f8f1d54bf7d87ab37da0000000000000000000000000000000003a0ac3ac37932b71672b9c48bdbd368d64c11f57ccb952f633bcd10ec19134c65fb2cbad655d773a90cbec2d9232b3b0000000000000000000000000000000007553c470bd8f38a48490dadea29df81ad901ecaaf1eab35b1f497bb58acce77b883e03e78702930dda72e2277139a2b00000000000000000000000000000000044973913824b3326b72e62ccbabd8c9f1b5dc81b423d0dca37b6f33972d993a681c326730717036bc6f0286da9177430000000000000000000000000000000017b0407d2864cfb39dbb0a5fa8deb4ed4a690a4042153e829f51c56bd0f2953a440d8305a318e6d6f67970d473753021a2d728e013e5fc3e1ca24c105a0c268cbb4f152a97e318f3aae33186ea6bc93a000000000000000000000000000000000b7478dda7053590ed013b7c23431a21626e748c3843e2332bde0bd3890ecea95b6104bac420a8be5f3dd9b075203616000000000000000000000000000000000e6dea641181cf796f62b196652f952ee2a26ba998cce1cfe9d65ae49198d10badffa561e2bd818eb2a7f350c122fa820000000000000000000000000000000003c79917ad5a9c7f046b34e5491ed015695aecb00760f3009dde4cfbf88ad1c03e44117fcb6cdbd5ecaa8df8760a3da100000000000000000000000000000000034e22ddbdeb9dea46c71ca2144ffcc8356c1a525c5ada69a6d5e5c1786aaaf0cf532e31a2f78371e04a72e8222ed4c7e8da0c8da19dc441f53c54551579fec5d820ce2e3599824b24b7c5bf1847c5890000000000000000000000000000000017964112272360a38d3bddf89da922ab50be076bf71a094fc8afde109d3817cc2db633e6408f5716b76d70e30ae00c0d0000000000000000000000000000000009bed28bbf43846ab97b92aab9ce094b077bbc59db648dbb469f21842058ef20318a1a8c18045b3de555bd8c76132ff0000000000000000000000000000000001297110789c7aecb0fec577f6f4a4de14608d9aa26a8de68289adea7f6b53b766b840d315152ea346f8c10b2d2729e730000000000000000000000000000000002b551c6a7846b96c6895e55ec435397af70eb435dc1c562ac71a44c36936c2c6d3e6a1e3545513516513391aedaf9ca76e90965adfc2fe52e4341895e6b6154fd7a097e052b59e4935c8267a6f0e63800000000000000000000000000000000003d463ee4d177d78849fdecba52b7e83ca90d54177ed39e82b4e80c17994a6a2bfd9c46edc0ddb256f8955428f30eca0000000000000000000000000000000011dd976dfeb8ecb7d7f5cd10c235131709fb16d8a827e83d7084266c2504cd1f5276ae3333bc7fbb4ebab48c0d97a9930000000000000000000000000000000005fd19477fffc246f5991603b48085d95256b273631bcfc16f19c6980a3ba01ac098061faa149b475bfce37d586464b800000000000000000000000000000000103ac3dd682aee109dd7fbf60b50c28cf7e37642f05b424773a06f6cfaf7e9fb01d5074ade97ef6cb0ace2e1fe07d54c7f3f352c7b7a9e2eb6c87edfc99e2df3148966760168f6abb13ee482f223a01d0000000000000000000000000000000003208ce7f51a96dee053cbaa66fbdb921c2c3b42ead78b39b4f1df7ab49f05cb88d0f4ac18de5839749416eba5535d4b0000000000000000000000000000000001ff7f9db52aaa0fddc8e96a67b99353b92d7032f59d200bf69da3b446d08435d2ddaeb93584d3b68a1934566187922b0000000000000000000000000000000005f05ccfa5704652cecfb42979c538823fb9d11a00222a963d00f1a4b9a040a0222dcf45baad40c6574d85e5617dbbea0000000000000000000000000000000018637b8c3ef111f6ad4538464c250d780e7f081802bdf720f4c925154f4667c5d50cdbc4dbb7d0b2747b97d2ba2280bfd35c4286f19a9fe8117e37132ce4ce76e28afee25ecca2f66de3cd5e1c83235f000000000000000000000000000000000eb400becfa5521b824a4288885fe46642c31576238e94f95e9b4bcbf62845ee9d9ee122f87d36fbe668f0e605fa2ce00000000000000000000000000000000003c8cbdeea0d09590e1719ddffa0a116723f0fe85585583f3f271ead66fbc2107873181915cc41eed3ec6e2c5669e9d3000000000000000000000000000000000e61c0768561517405952c6462f1c5df95be272251d8a7060624b62f9be310cef64436eb2c4c04e8352d7b75fea1756200000000000000000000000000000000036cd74a8efa8a1fce7587f07d5c2a6c4b7ef161b0faae037c9bbe63bd0c92b83e514c8c1bae4a5d9866c0889b1b914f3c2b40b7968a39fe8e4f24acc25b6c727887c3c44cc89cf62eb14a78ae47e8680000000000000000000000000000000013019d0fc8b93da2c79e473d713d94af33eaffda65a7a49d0cbae9f5259b8323e6f29b83da9608ba7d6ec004fb0710eb000000000000000000000000000000001505d30bf8f7c51994d896d91e8e2259782e2b49bda834015477f18c29e64da4d31f8b96edd080267b77a9539afca06a000000000000000000000000000000000eba929531615d9c0f59c4b33c1fc34b81e9c77cd8c6887099d850b3e39326d7caee1feeb101222f22bea1e9853d06ea0000000000000000000000000000000019d88f62cae047ddf2cefe497495f890d9ab8499e56f72488af65095e992427bf821f63555a67b0afb00d6fb441080a010325465403dbd4898beb740884cc325923ec3e1d7483540377d8bbd02c11382000000000000000000000000000000000b7c8f3d0c56b3b7d96c0a24fea3394551a186f87acbbbbce41d1313b23762945bae2e911725da4211614b456b508c0500000000000000000000000000000000125316f64bdd0c5bcd26a0e5bcfc3139045b3a44c8a8dd1cebbfaeb83b963c5a5abd4a5961465cff261c0e49189278d800000000000000000000000000000000095a327f488b901fe7dcc9f9ce6f4f25876bb09b053b64e9f4de9506a0fb95fc0cd443473c2cc5436750581d39b8e51f0000000000000000000000000000000015d406b31c791ae2d25ce462304c0bcf341686d7967c9dbb6734bc28b02123b1730d0a673fa8071dd90950d9411a2b3909545b90dbe35b0d5764bc72d45717e0c3aca6aa77c73178fa8a3ee9fec9cdb3000000000000000000000000000000000c7029af9422246d0a30784431d6bf9eca09481589438fe9a6d2fe1d5e526ec3d176a3d550204aadb85353d99bfe3ce50000000000000000000000000000000014a0dcb26c40693ad19a1edccda05055a27ca24544e933d01dfb964571071f94c94233f81e1ead0925d24e6d3df2c21500000000000000000000000000000000147a55ebd83c746128ba9c7ac57be125ca5c95f80f891e2c5893caa779484bdc1f9c3b3ccc4223b2343ba939251f7fdc00000000000000000000000000000000125622a040d8b157432ad81b8a83a9b1f0920b92680bbb65050b4862b89017b3bfaf81a3402ccb383265ba7200ce677feef0f8014102664a300ea9a30fdc7afeae3cc338fd45cd421a1bfea98e304c810000000000000000000000000000000013b394fd7a0f3d94e5fe4cf5cce3627d425ec848912395565b3e61ffe89e56be799c4779d3b9a0222ecc6538ca3346e40000000000000000000000000000000014ac1a87b333caed0f557fa5692d1138a8c1e92d1f9acdc9f357e2a46f27513dea42f367b046d389dc831610be4fbcf40000000000000000000000000000000011fa243a0aa8b0c01c7636387d60021afe6efc223b7deb69d030651c369643188b9dd5e08d6d031d71dd11eca1e825ac0000000000000000000000000000000015bf8fd7fe438407db7f1b0b586b2c285777c5b6dbef9e45b46cc0a50dc831f32a70e7d4316d4869bc769ff6de58ac30c8f1e08cdd72ed200253211e3b9947cb2a5fa24079b6920b4a4d3f1fd78146e80000000000000000000000000000000005ea57c269c9d43d3f17a83df04c95ea7e7bd85aad1dc2dd285ccdbd52bfe707a1d2476417e848ab119e62fea30520af000000000000000000000000000000000b99768ffbe95e315b244bf996cf34f8ac356664adda5aa7f4ff8d513b2eb5934b8ffe0fd9af94bc9b934e0a8bbd51ba0000000000000000000000000000000003b02c259df189370dd2700c5cccfc8b212a4b332a083adf9771503f5bd0c9ef040590320fe4a86c555a4ea87531268100000000000000000000000000000000003ebb1e610bd055d037a410cce3ae06aa654950aee0210ed0ee79f7a332be7342e308347d7b17a146a8b4c623029e08a7e25b1a60b6c6080ccf1bfdc37aabbc2bf92079d9356844f7f12867b3e2b2800000000000000000000000000000000015c4da691b5e6242af870e06b29bcde467b4644f01080eca60a28c7f941590192be30e6a4270a36dc8959b80235600aa00000000000000000000000000000000080f3d3d5c35ee24179f51ad854a37ac4ff867a2736a0e3e8f3312ac98c7016beea6ffe2bad1dd4842d6ec77995ff97600000000000000000000000000000000130c29dc633aaefc831b0bccb13fde1212fdce8cdd17beaaf1d06e74ef5b1b69bcc219c8d63f054690af1b6dc7c0d647000000000000000000000000000000000767290aaa1ed4c1dfa5603d976df0715b417599445ca577ded7d99e685118bbec71443fe1d9a65e0f23436353df152cdcb456eaad2b7c71ca32277206c1a1dbfa7e0e84950cbf14aadd455fb58e398a00000000000000000000000000000000133e997857f47f8d6278b8ad86f4692ba0dec9da336f2726704db593af368dda7aefc0b218ce1674f415e0d9e2dee5c60000000000000000000000000000000018db87da1272bd386f7d8b5245dc2de30e82739723b680dedd36f4ac4cf5042bcbada1e1bb307ba444431d73a4248f9c0000000000000000000000000000000006580be3e67c7a615408aaf9c95c0956678af0e2b1f536f1e69588193387f8a05b03d5e1060ca60c4fec9eaf3e72d39900000000000000000000000000000000050bd9879ef9eea147678f552cedacaee84562e6561b3b7338fa8f9d514099291c3f2a3723fdb22c88f1c9243d411ccba6e7b19245341fdfc5927cdae57f59de5f3fc8c37f8653e5aaca87db682034ce",
+ "Expected": "000000000000000000000000000000000d8f69d90c871c08ae09e7b3e62e36514fd056c41fb596fec2fc9ce8509ab4f6675d7e85aa6b4b3197f5ab781f6f2e490000000000000000000000000000000011c4bd3cd156c34065e408efcaa5e13ad23d114458b71c2a6345f4aaf82af76cd4362db7ba9ee7e1e92ce72e242f570a000000000000000000000000000000000712dbbf20e9b24d20511d01717a3783608386408a258c2261fcdad5fbcab36c6bd21473c3d93ef8518975256c65a945000000000000000000000000000000000d13747be82153aea8076fd7813ecd7f60a214c31e88e25b14dee5cdb9336599e40b136d9ae6deb85606d35406b2675d",
+ "Name": "matter_g2_multiexp_91",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017da08f2faa32570d95b9efd2d2fe358faec1ffe304750dca1dc3a273be3427c70904d58864f76afa19b0fe33ab1535f0000000000000000000000000000000017de677b713202f23baecef2b0618da140af624e56b876f2d7a20cd437c3868ea00ff6cd9c8908c1ef323ad294edd9670000000000000000000000000000000011d50aad957c54868aed6d848b2e67094b129282cc2df56c41d6ffe976d02ee83a592c33370d3715588a074db503b3e8000000000000000000000000000000000b8aeb019d120959b21627c1dcfdfb67ade22a948fe433172994d4a34084ac9e1c11333a9c663c87acf50962e21c728e92898d9cbad829a5346c0925c15b585de18869adfe796e46cbd56828540571b70000000000000000000000000000000001312ebeee36fff8152324a3ed24c37eee50b3099619a33c7a6316470ae722548b4b9e0f0640453caf53f374dba504830000000000000000000000000000000005ea81d2e5d9edeb3ed6c200b75beb731c31ad666e6e37db72ffd0265378bffc2724047c7c0c6e3f1598345fd390e9270000000000000000000000000000000017617a836beb12e637c5bbadd4fbf1ca2f5cc3280814ff5cbb5890b31cf2d2faee9e3ea8134af97ad4feace50aa194140000000000000000000000000000000002606deb5d57dce5b3d2e5f7ccec3ad036992beae238673641ad6042479ec3cf83bcc0fd03b7dacb9b4bb6c181ea9cc8c193fe87634fb0bdaa1700466881b557c470a62464e8521be311a95dff65eca6000000000000000000000000000000001203ef36896bfad2a2841689a964328fe4ce3d83798671630d0c8876e67ceda03d99555aac46d984f1d3bc38ffc134c50000000000000000000000000000000013e7461c256c8ff9144b17f8cc2e270aa94b64be62588280baca2ae6b6efc4d32b3800eb84da62561e0e96d5f0387a3f0000000000000000000000000000000009454b6a810647350cf0b364eb1c2b719670af45bdba9d7d1a534e23d4e810c3ef4d9318532e46fd104a83bb10159a30000000000000000000000000000000001034546c4288f642daeccf5b56beed2ca2d946bb4391d056df9c6fd6771048903fa330ec16d59d05540cd715333c4bc73dd9c99a5aea019436e3c91030d03ebefbf6ea6ac69222f1870fadae32f55ae6000000000000000000000000000000000d7782404dc6721f52648fc6969db33a9aa209f8baf5faa9678437c76c9e1635fa6d22d94aedefc90112223bb81ce33f0000000000000000000000000000000001e442e548d3045d1589817d0b57dfcd66fc64ff978186f784bd576faf57607170d49364a72189328c9837c9a2d8b0a0000000000000000000000000000000000da2b207bb7720aeca2e6ea02b65076770b960d4b7a96ed941a7f409757b952031a472384298acc3948bdc485088501c00000000000000000000000000000000048f85bc05ed78c692138f27c3541ced11b6b0ec158b43d133c3450a905416682fbb8c83dea06a06d294c48289ddb829e74ab390c3f73c62eb1435226e9b4f9b921ea1918a61a614b9bdbe9eebd1cd790000000000000000000000000000000017134f787c920bc15cf2228a186dfa1d10194087f28b6dd8f03e1c86226928f0eb1c27020a5cc74d94b50c4b4e36b8020000000000000000000000000000000012fa1fdcbaa81c4cc1e37447cae51beb29e55bb19b91e2b575afa3754589ee0151cd9e83573edaaefd341f381d34f4f8000000000000000000000000000000000ecafd00cc87a773a13909512466ed11288c842716e1ca5c37a4d9a4cd7585136c86f32140fdf02e2997a6e19e3d76a200000000000000000000000000000000104cf007ea863dbd473d7dbab6f55e74062b18986e9bc09bcfdc9c23e4bff8683f73aa998a5cce59ded10499d18a0ecc4dee3e2bfae3820f611c30df232c1d9c6bf58d40b3530858c79f840720d78d72000000000000000000000000000000000ffffc98e55f4ba9a642c40678d625690464bea39d085dbc9c99b4c36ea8bff5154eae3c315e1dec29aa669840accf290000000000000000000000000000000000a3df9595167048c52b8170596d4127968194aef7fbaea4594a27c6af05c54bb772928a7749d74311038d1c115e91b2000000000000000000000000000000000b317a3abd808e94a7197e0d3b2515a147774f78d0cd7d36e1156da28a26e33bfa76d75c6e3ae346f9ace050c9911cc6000000000000000000000000000000000fb5fbcc2f74fc30ae7e32143f219db7dfe5db6ecb09cedad8f087b6df56bf9693c8b7d78aace064e7c31785f6869541795fc8e20dd30622876a94afce1c1a76e3b689d6848903c21103cfce6a8a95680000000000000000000000000000000011e4b907a72f34af899a6c4de211af5fbe0265e5bf24d406798de53ecea273d5df4f4953d13fd7c9dc3bb0f0c143e3e4000000000000000000000000000000001623de5e87b6e1ee920e1b7d979fb9c431c12abb47b93876f9ddfaf28a7b673c18be634f96b813f7e0574c55b628a8790000000000000000000000000000000018ba994b02dad759ee79301b42ea20d7545844c0ea4bff2f95dc9420194cc4196fff12cc09bc0cef03cb7ba868c273700000000000000000000000000000000004b3527c8d148bd9e6006bd298ff8d7fe320748dd3f6d23449e874fc0c2f58d933c1e038a74f60fb6032cce41a3dbf5725b49f325e76733eb3c1a2cee5467157b2ee80987abae43d2c4b93e5157f083800000000000000000000000000000000129641af11fa92056236ef135843b2189d46d870381261d5781a5fd6f2c5cc1861ebb2e801f19f3adf2216609a9e196f0000000000000000000000000000000007b4007c55e47f6bf3aa420ad75fd191ffe0fe824fd30c3f1961a8168922476fdb3869822704999b044feead470e3b8f00000000000000000000000000000000174209113e2d8c363b04f49487176dc6d9eb4ecc0b22daa7ecaa5548d038b3b7c23ebda4f1b6845425cee13493385302000000000000000000000000000000000a58c80a02b7f93db01d2f8e0005839625e6c4f121f3d69115f435526a7f7cb53177caab4db86273bc2d2f0474235f31df49b30dd6aff459f64906eb1a9c9b2067d4f1b75057874b2fee17923bcb906e000000000000000000000000000000001738a03b46a8ca3f3d1f4f4447497c59f114005400f06813b24ff462ebc6f27c1c3c788b5f83f65958cadb34fddd08f40000000000000000000000000000000004dcfff2bc9ca0282016f38df484655cce7b872b1ff047351ae6b903e05f457d7fefae93104f9dfb549980394dfad2760000000000000000000000000000000017cd89434225dba07be137a73892faf0258b3fb19e6c8cec412fcda912c0613f2a925ad50ae485187020a371ff2dbc59000000000000000000000000000000000f1f9f87d3401e7b3b59331a89d9535adc973f869b81bfd8892a37117d8597ebab2800c966e623469792f4ae2a8eb232959e0a33b1fa12e0ba960761b09921b81746b8df23e808a8de09e7f5cbe2bf41000000000000000000000000000000000bdcb1d2a782541ff7884dde4167ba060fbd4b117944ae69aa2ff685b9bd7d475f45adce0c9f92695b4f4ecdd48cb9b50000000000000000000000000000000012a55432678043888bb9e7e47efb17700b3e702e389d0f58dd454224a02da3f190b2fef4c9d3e2074c7bef813fb56fb0000000000000000000000000000000000efa51ba64f1e7a1a269dc083179a222afac916778a967098582f55a41394bff3747f8d024261959f6d399f44a40d0fe000000000000000000000000000000000845dd0974c5789a85c3cb09ea441f2c433f0606928ee1b177eb851530d6e6b620b4fdcaffb8f75623435dff99b3ad9526ca68383528f6a871c237ae5214b49c18c4f3e2f3ef5dfba39e69eb181143d700000000000000000000000000000000180beba92bdb95c7803fca0407e29929ee64e03d61cad96ea0e6c469c5a888cc5ca5eb20983b3418a8da6596a5f1b2ba000000000000000000000000000000001322f7356eb3069fe20063f4be22c44426162dc8fc117e4e382bc4e33bdf3d971ef662fffc1d58ce187c33a43a4c853e000000000000000000000000000000001601a0aadaba846f11ba5c9f48e13bda1007ffdc1b8bbc9e85e83e569e9ee17a1e9e780a50ce617e6c780b8155675f2100000000000000000000000000000000105b2c213aa43ead42d9cfdf1d6c0559c25b4b86af43d4493bd75b76986d0d4f1d9b3bf9e3922b5c08a37a1629cab7d8f1f95a9d1d4e8e7d0f17a954177253709d988c3a77c77d35b8bf70294bb358c20000000000000000000000000000000017bc70346765b7160a0a5e556805c7944304acbecde06cadba474c51f05f22445c3d943674cc8215f973cdf11b9ea2e9000000000000000000000000000000000bfdbe202619a1d95359941c249b25462d3ecf09fabb878943a8a37cb9eb94abd7e6399f8d82f90ffcf904f4466cc5b1000000000000000000000000000000000f048db8530a288fef10a5ef9bb3cdd9f3d3b0ef4824609efad96bdf52d7c3b10ef628fa04f8b6513485e55f653f4b990000000000000000000000000000000004ec35f59287eadb1738bb50b0e2ad9d280bedfdb0a201e72594bfc4322ade0b7ffd6b532ebc7796cfc71f88a194bef4b481f986998d863c98e55a7661136a8f19d7d4c57f6036cd642ae16c82cdcfb30000000000000000000000000000000014424c77af7ace8ebf66f556cf219919712d96d24438466ad620221ce1ae9b2cd75b9c526e25df7fbf3c9250583757f500000000000000000000000000000000198aa00723781714152b3494b76ea3ee043b363b3fa81806cdf7e440b4cea907f226a3c038fb95c932710dc9aad4c9dd000000000000000000000000000000001360e4c775f6fa5e987231dce25ec67f61429ca9fd8160c3074383c30a8c0d7ff068b1d1215b2c0cc87129d9c9aecbc9000000000000000000000000000000001280ee6160800c4b0f82d5c2775238b4b223d8a0ac9a8f8013f138d554ba31c9fedb30e0eb5c330da17f5785b2717422ad872848d72367467094675a819f9aa6107183aa0c8685d5d84c27b3aaab33c1000000000000000000000000000000000f1f84251204d9f9328f79a45d15b311984df0715579633a82b5a9f680f6645cbe748b0fa64b9ce1e696e20a5645d6d300000000000000000000000000000000156901506e502a09917f76d825614824dfbc34d019ed53c2ec5395b51512da512b27541bc53331444eac2f618ffd5357000000000000000000000000000000000ea8736a97a33112bea9d07b729e973e3a942422f1d2b24c30e96637b535ccfc10cb5930bb59ed90bef604453df8772100000000000000000000000000000000187378477f60e3eaa225e89d8532bd95babd4a5c51729cca800d364b61575704992639dc5035138664e8e074ed0820033c2c60541fe17fa8e71d58184a055fa8b1dd0bfd16ac2baa912b4472c6056122000000000000000000000000000000000e5281c1c9210269a7f5ccd02cd5a7d3648b56d9ca6a4ee50beadf151c2601e0291fe7f1b89b694500e6c636d4e445c4000000000000000000000000000000000d5d5399f49697e46013558dfff544383b25f3b60681ba5fa2c5e6edfd3924267d0992abe65cbd5109ba8a1c6eadc7e30000000000000000000000000000000012a2104aa92871dd8e41ae1ae6dc18ceb7d0f361a5a4fc67936454b8866b8aec1602dd596459cccf6d9e1319ec3299d4000000000000000000000000000000000268795f6f9892f5b476c3a534673538647300203a51a8ff60b530094608b5fdf16297f02ab7ba41d6fe556885f064a4ff07c19ad4f10ab47e73b6698f9febf3f28087614759e082e6e717588c1caff7000000000000000000000000000000000a5585961328c52e0fefff16e66e3367e34339dac1a20cbc5e89b78804b8bc265e6e3fec1da6a62cd8a46be2f08a6d960000000000000000000000000000000016fbbd698784beec5a636332c0b20fdcb68fd3015cc6d18b541346a5e6af76613e6fcb14c888a2b8133c0f4132fc079300000000000000000000000000000000041805e0adf2a32153b89d1131226cf0ebd77cde3116a168e792ae8b88ba2edcb1fe7275658a384251b805d282ee039c00000000000000000000000000000000024213e4a8504cbae4875617b9b78473e7842ff72415ceacfaaf2e8b415f9f7e411989bada8101be72f9295dfbddfa3f240c881fdbfc414d3e85ead1cdf166ed6929d0b2ccbc35f0811473757b6b41af",
+ "Expected": "0000000000000000000000000000000003c4f051d528166f256d9356aa9cb885db5680c51990d9474a948848888fb82a9b86daa7a2273725ac8ec564ebbf15db00000000000000000000000000000000010a6c4c7067f511ca8f1b66bf9ffcbb275c7575540909262f7c4332c3d75b2f6d2f3ad2848c0d455410afb1cd60c835000000000000000000000000000000000ee5e582554b3930c5670d4e3542bf32e8b871849d7859eafc077bb2b533e936d462f614057f9fc09c4010afab501c1f0000000000000000000000000000000017fdbcaa065d301adb94a60dd20dbae71512d369fc82c556ea0dff66843be768be942e060752591c6eb0718985d8e313",
+ "Name": "matter_g2_multiexp_92",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001353960aff58d45691c5378a0676a8e837260f5819cbbac9cd75c8cc4c6f1e17b9dc9843eabc0b1dfb27ff7631e4e52d000000000000000000000000000000000d6279a43d3526c035e88b0b640b04d42ea573ed07323aaac1d9d5570a8be64782682892415ba2be5cbb13f56e3a44db000000000000000000000000000000001250fd14fd003f88eb6e0e80e9f2ebe204475fc6c06cd10fa45608a17b7039afe0326474ff80c357f86c2825cdf7a16d00000000000000000000000000000000186cd91cfc8ae625e302946f2b393ea67e1107c0bfe938f5f36d28879fa0c0780c847aac77d0310d43211152c1d5f5d314d5455ff1717bdd545f4daa37e145121e7bd9636d7a2b65633e5ca5a63f2d98000000000000000000000000000000000e55a98e8b1e59600e86cabb5e8db8ee622009b1618ff0df3e93fb55b80985bf2a8ed060aeaba53773274d4186934f75000000000000000000000000000000000bb7215fc43f465f51fc8265477fc8c79493966f040e02f0eacc4ebcb3414b84fd94ded822bd24dd5ad5720f12bb8313000000000000000000000000000000000b23328e15cda8a576ea352b5dd7ce382ec781deca6c23f646e42f0cf63e28669539579ea51e3c0afebbb58e1e8e3243000000000000000000000000000000001716019236169bdb4af7bf7d7ce0aeee7900b74023acbb16f6965c2abcf28917bf88d0f9d5bc26a81710496f7821fd4682cd8da62bd901355a60b37ca14ce65d427bcf9551203cae7c346a49b4fa8626000000000000000000000000000000001718a4d6f5e78524d8df23d2c589abf04e3567d2176539a30b9f73c6251de573caa60c2881f3da99c48d48e9aacd7402000000000000000000000000000000000ce0e35721379077e6eb3b572f7f7718bbf775b116521c14acbd3ff19549c75d50bf70ce84326cbc3f9e5e53605d8ecd0000000000000000000000000000000007cb3305ef0d2cd7de4dceaf25d2eff44d4f437e065f6b244bf1b0611c891626eafc4b759d55b45d76e94b85852df1de0000000000000000000000000000000011cb56d2ed32a46bd951836f8e0f92d3824a4cddf011eecf1e2d92d81bff407a04abdfcffd60ccecda6e9443b328d51eea2c7fc2050e9c1ebd05d15f197b4b1be61c6820c8d27ade57d85109d7f982490000000000000000000000000000000011ba705da23100f853882dd166d81ee1d7621550d156b14f7c2123e2681887ec3724626061db68b2c63987325b27d6230000000000000000000000000000000014271414fe078a80587269398afd127ce34c8dc2a4851f76613b81dc99d766d75c703949c1093b04d66a301a79d89bc30000000000000000000000000000000011b7935ff284b0f812b5da5b28ed338dc4c21ebbc7fee04db834732b11fd76092db0e8d80368255b0f1205129081e9af00000000000000000000000000000000104ff0ad2e3db08d3b4890b2e54f29e456e627cefc3a4f07c1109b764dae4142480e3e5312ada43fec9ba96ce587e8a4e3bf7e661d54796c71437354d7d3182770f10ab450827512a423d3dc82d5b43d000000000000000000000000000000000c60749ef36d63960022f3127d0ab4e12acf05ba1e1a136dec89be388b9d7144c1d78c04df658727763dbaa9725bd8b90000000000000000000000000000000019932b1c205a765bc9de0cc136999deb153222a9dd9e9ec3660fb6daef56242d08791d440888e69ca0da2bbe0fcb7d79000000000000000000000000000000001764790d12f5ff79ee4f2c9fadd5dfb1cf47db70b9e86018bbdbffd1be18df193c7dfa71533afa381053a77e02719c6400000000000000000000000000000000044b2b0211cbb407281ab2abc4725c2cd791b313bab8779954a2461ce445cdae60d4a9efad9f90f80e66b1438514e0f0d3a364e7b217dfd649d1e08f76393372d8768bb0fc85c79ef4652417ef1637fc00000000000000000000000000000000175cf9e7eead650e7ae4fd657bc288b6b6392773bf1bbea48e17172a5019637fbb2bc0a3d0d1e3b8054564935c908db200000000000000000000000000000000136da2a625cf72403d0861b9cd947cdad12b1f1e6cdefc4aab6756536425285a7953a1b892df40ec12ac3430fec889cd000000000000000000000000000000000c2d10c6d71cff4e1deba1984bfd17166571e64659ac91b64c343cdf587c29d52a2266c00a57c01feddb1df6439d21d1000000000000000000000000000000000384a782fb31278f49c840bb8f0552ac2734ef36bb3d115be7df20333aa747c92db990f7e879399235d122fdba0eed76eef7b05d5c725ed31269ae9c56dc7ae35048af39ab114319680d4af69be7e7c3000000000000000000000000000000000a9a821cc63e7c9857b0f39f7444a1e00a422f7cd5d0575c26bc5c6b98313abfde51e3f6d5f4c817193bdf391344e5ba0000000000000000000000000000000010daa8c7194a75cea757b6ae4eee85006eda459ff2cf155b1b5f19c3ad341972f72e28b781c4878e8919c7e5abe9a1d5000000000000000000000000000000001154d5d5764aa2b8818a9dc5dce30ba2197a86d0bdc7dee3e600462e295cc3a69dfbf8db34acf138e7a1f16b62a45717000000000000000000000000000000000b4243a09b05a958d78ba8ae25fd3fa85d520b95e56f1dff44e556b221a075f8dd3370313886d9dbfc56a75697454d72acecaee3dd4dc11e341b3dd0073842d90f641d4dd467a6596f337a6147bd30a9000000000000000000000000000000001820f953fd22b71ce00bbe9e9b78fcf5fb28bcb925f6b5dbf5711e00470ed7fd2f38d7291d40514ab4258807f29150270000000000000000000000000000000007b737b56a2ba33f76bcf66c0b26fb44d5f79879273f6ab21ecbfe6a5744da289464ca2b46c55edaadfe3210b907f3f7000000000000000000000000000000001735d1b39c5369bbf886c5063a96dd12b85e56fd9d8ff9d84520918e1dfeccb62bbbe1c2ab440ccecd0fe66f6ec55853000000000000000000000000000000000e591b7709bf00bb2a87e9edb95720de19adc41a42378cf9ebb930c6d3f5993a1d7b6320040d5c69908685d978be8f980cba585b847bec40515a257cb839c7e5d677d17b7313c258e83d630e65cfb5d2000000000000000000000000000000001732ac410b2a7d10110bbf7709dc6fdc91ce742f8cb9b2c3ba37ba5f0934f8622c675753a26d04a176e24a630d090d81000000000000000000000000000000001111a52da6aca10cf40127fa8ab7683505305e0d474eed28a5e1735ee6877aa00c1bd598420876f2154b814660f3fe7600000000000000000000000000000000098c6d19c2ff42c2c57a4924693325de1a91135e3474ec699b70439d034469e72e844a5511e23dff3948a66cc2a2165300000000000000000000000000000000175fb79e5e54963cdbb133f38dccea2d1abc3cdf005c17e8f2de6dba9b9dbdeff7719983aa9ddb602f0cf966fdd430e0b8cd305c650d2e1cfa91ef0aca9dd0d785d7570d6fb67e61fb9b6817116a05440000000000000000000000000000000004e88468d35d72dba6b3e4b9ca216b75b5d20c447064a48bee6a6ddf994b1e22fd6ee8abd60c627622daffcda219645a0000000000000000000000000000000015eb2ae16e3310b4c4ff557f0615519c13f29109d9863418fdfbe6309b5bac4463456df8ebb0b6d9022e294cc16265ea000000000000000000000000000000001288ffe0ffdb96708558d914bc412758770d048c4d50523e2b134f8468d11a57da97e42bea303ab7137e2d26c0b3b8f30000000000000000000000000000000003ce563b63c50b09a80b71a1a82995238a9de31aaf189c6d29307924b6f0990854507b7dc1644f689c5abcf931dd5a3c825e5f9d81273f306a065fd064ae24bc2c5ce8dbff6b22128753663a218da8a30000000000000000000000000000000009e39ce653485caf699ae1d1d9cf2b8c5ea85b80ea042279e57f0beb81056159e49f73d67e7b1f9ece9f9ece7dcd2cf50000000000000000000000000000000008d6492cc335660c54e4a34b29b337b5800f1ef992d124524c799c04c852ccd3cfc01bf39515cb8b96151753147e8c49000000000000000000000000000000000ca779d87aaa3a6552f9f1a10b0d2e635be90022326db04e6072f326b919ee55d4124b9268f55751dc0f18172bd327ae00000000000000000000000000000000112eea543d6609d0acfaeb7be98be609f03304f50c3814ee8a010283146e6b5dbf170c7314598cac06efb9ced1ac2930307ff9660ad0c24cbb139486638a2556687f88fb93a290a1d174bf87d780b3fd0000000000000000000000000000000006624dd7f6eb043da41a36a15752f370eeb3cb2e6bd88b337b370fe0660c5ba8fe64f62e112f91d2524e9324f3a049fb000000000000000000000000000000000415b964484c9246385cf95461ab955ed0390e20209ed405d84fa8c8af9fa7ab39ce89049691a63c61b12bbf6aa2a4e80000000000000000000000000000000014411d7b2db7c9ee78ea14c6a315df3d90827b511db2e2423d660176384d8f8afd284879b22f5aeed73afb2eca4be52200000000000000000000000000000000105bfb471340e76f28901edbdbfe2ba246a8824b501ae2d4a73cffd2690181347c1e6530804614e88e2bb13a8edef8f4bfa8ee3b44c70ba2512c00a1aaecede2180b08ac3ac8c550d70407f0c12e027d0000000000000000000000000000000002b17f4b0b0231be229d87f075998435560ce9046a8b0e8f15e3a9f07cd52f3316f6d8c00d6a872362e7066715cf990e0000000000000000000000000000000003110eb232154f8a06834e2ddd33c0207ea552f439a6127b652bc261158209a00654e50341d333cd1b206a915fe0691d0000000000000000000000000000000007940e209c8934c185e4392f12fc0afe3d234dd1ef3f92df18d76be8fc42bdcdd6d1ea8d5bb6f07b3f3caecbeb5ef27f00000000000000000000000000000000012ec903a8442f68c03300ab02ddd08ec935d97bec9050d26a5e276584592df3ab87d596f90768d2c0918099b28963be58aa85b50e5f4ffe375599cbb912f41d35acbb85a324880148f9b9003c4265bd0000000000000000000000000000000010fdc16bff0fea02b325c672fe06297e0669094e2710d0baf3838f3e234c3f776bb3fd41b967c9ebbc72a6bc6eca70850000000000000000000000000000000009d64ce322e39d5b2d0872760a61a831877c450b1cfac6cacec52d4070b0f179dce90afbdefdaa8466f6a6e2e83ee8da000000000000000000000000000000000cddca46f3b24e05b76e61b4584bc716ca7036afdd914731a61347e453a26d07549e9808e553ee056bd47e53c75eac8f000000000000000000000000000000000451cccaebe1a188d3eaadd40090ca594f071c8b6d0e0d82f5b2d43fa784f8437e4226104c4cfdb24ece1ed75375aa616810c6cd59b14ef4f6a4c2702cc53c65b3dc84988372c1195980417c583fd7ff0000000000000000000000000000000005832ad778dca8dfcfbe741dcf311024d76341d5920b6830cb75893a112c9d86719583d1dfa7287281fb73fe21650c3500000000000000000000000000000000044feb86b4816e45ffb98e9a670fcb039fd9d8844a2c7ff9b7752f20e619195fe6ab1148f30afa393936d3605fa4c8da0000000000000000000000000000000018db9365370a8c703364ba6d9c48b3512da46cc603a43c3fb91c0a8ee59777d7cf9ac646c3e4274bd950d7de92ebce840000000000000000000000000000000017bd82310e251701cafbf8c4dc5b9e6c88085b0df287b6dde7887e1f64f2d9487a25b31abe07aec7d99a75baa5983195c5ebc09190ba3df49d8ea55cfd18370b9d443f9d9084cf84f2236ef4723d2d470000000000000000000000000000000002c1df194f01dcb503dcc8a283f059b82d141274c8f37cdb6441aa33f84f16dd288d566752a93ca23d26ef5834c0658c000000000000000000000000000000001700fa4459dd4e609453284f4f7dab479342675a87c1cb42b601908296557f39256f1597ed3b9ec38ad0a40a2c728f0d00000000000000000000000000000000135ed4f475eb99397cf204f971215a0303316a3ed8b62b303b4bf756ff753410b7fe263c4e97fd4c4b399c319ff3ad98000000000000000000000000000000000a487e179bf1b73627af9d7d2b43bc0e43127a8fbfeaea7ce958ddd53ecb27741eda187745e3917f1cbb60adf0286f5413a56b176fc835b7e825c817d432b9ec6d51b0a66483dfbf12166ee979b664cc",
+ "Expected": "000000000000000000000000000000001327c57e16f03fbf652bbacd16cf574113860eb87b8f2f6e498dc5dcc4f2fa63859d922d88ccd6683d503d0962db5336000000000000000000000000000000000cb06948c539cbf686f6936b6a1ebef2e148d98c531da36272e0334afca5c2b16a52da542a0fdbc3bf764eb877f5778a0000000000000000000000000000000003acddfb5bc4fd5579d3f592977365840be4d3cff96434e5ff4f01ea798e4401930a1f5d91f8de3ff98504dce398c2ef000000000000000000000000000000000a5a332805f704613eb085d6639f99667d0d9247cae34eabcfa399eed551f24c5d5cb05d6458530ae270b1be682e71f4",
+ "Name": "matter_g2_multiexp_93",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b1b06a76e5bdcb6c1c2f1952b49e1820a9d8557229fbff8740269a0b819b91cfd0de20db0afd76a2cb0fbc5fac12ec5000000000000000000000000000000000347654df2084082efd32cba2b270f66b0ed30fa8713b27949fc9d270ee8eaa9b9a7896d7a52dfd8faa3e0cd112a24e0000000000000000000000000000000000bf5b7a2c0c8bc223ab334bd1df5d9fd4bc0c635379ed2b32da13f6178e07217bb88a4bc2eae0b975f2e566f657d23aa0000000000000000000000000000000017042f8585a07304995853270b1b03bb08484104f7498a12bc865f2a0e37e662fc4b0331b94ee5690efe74056567000bdedf65658ec3cca48fd48e844337159af090c5d1f5e9d713ac6d0fe1e1f193d2000000000000000000000000000000000fcbc73d0628537eae417f8efc67af0a4c9c375d82406086bdff669911fe1307576333c389f189f49677cbbfe2ee98730000000000000000000000000000000019d552b85b1445660ca49518d202afdc67b0eb5be02c8d3482dc1b12e5d40a4ff95a49ce47809e4d6644d04aeb67b3c2000000000000000000000000000000000ed536c0f19f592180291bbce59a72ce5e516199dcbd4fbba736cae2edbe3cfb860ead0325dcc8f8d9be1ac126dc6cda000000000000000000000000000000000f5d4f0c0ae3e76b1c41edbbebcf1ff17c7cefd41e7ef8f75dfc10170834d05820149d5f721a8c6460cd0181571fca97db65ad6bcd6f485eefebda0badfc64e9e7dfe7e911f3ccf4f4fb9528dfebdae6000000000000000000000000000000000d6207f6684f8d2f083c963551bbf0a674ba40e691a34ebe6164ff80ba9bab2cc23024a896d7b906fb74c95016a9adfb00000000000000000000000000000000145855e7d610b50cde39db8995b127145d68fc9bea3f075f65b7793acbb14bbb313a1a39bd96fbea6641baae02612b000000000000000000000000000000000005b533ee83cf72f0e4d9c9ddcc6b91f4364e50a106becf766987c490d559d0f733839ecc706bbc9c2c75b243814068a3000000000000000000000000000000000cd8fba13b9ba7557c7577da183bf50810fb14eec7380e3b3d4f2fed62bb36f2b5ff288736bed0578fb6f47fb6d22ac86e0fa09884a7ff4c801ea0722cf6bfa58a46fc3d36058e8c395ea8fe56d9fca4000000000000000000000000000000000fd6a466f2eb12f6337ae9f9b847ac1481820013142af1a474229c5f5f5e1c0bb2d9678c19c7a3a1aa22cfc7b5052e0e0000000000000000000000000000000002a0340f5a0caf5c66719f7d546972bb4b89147989280542787d281901ff036b7c69d41418c21c43127c0158593aa5cb000000000000000000000000000000000deeee37ef96f26a4907e1a8a8f3f030dc09102799bd0c6dbeb1d208a0c86a423d0da6313e0be03c026da5614a6a576b0000000000000000000000000000000007220475449add59b3cc6570701528dcbdedacb9a3d39674ad4aef4d94114f24d2bff32f40b25af97ba883905ea6838a27a3377d7b9ff3aee2ce1194a22d7115b09a9fd53fcfa5e7f76bd9fdd35559610000000000000000000000000000000009d7023ebb73df81455f74cb2708c14ccecacd49521a0cf67ecb6edc8756e286ede59eed54d89eee5f77f178ea8fdee900000000000000000000000000000000002ad48fc3192634e7b01604678473e286afb0efe67a4377bb885d38b59ea00202241fb28c93232ce7c9a3dabb136a53000000000000000000000000000000001934664f2bfffb254f0415d6769f4e2ac710ee88cd822bf5da5df3a2541f887e4155dbb7e8056efb2a0370d6f9173e3b0000000000000000000000000000000019df518e1ebafe95adf683279729a3298fc8d7eb39c9a3dfe4b6665153f970e243e50dfb16fb87b3be54192f69766659446a62ef5760c995cb3cd0984d607c232c1eb0df5516a501ce448a189a3134d8000000000000000000000000000000001870048d360f397877321904563d35bfd0817ce464e0078e9605a4744e2723f49f9cb21dd3d6f37f1f9aff5a6a99bc530000000000000000000000000000000000e29dd0da13ac451d013d4a38408827cb0e739772e1f250d31e4192ddc13d651ab576ed6b8f4ee44e928fa663244999000000000000000000000000000000001646183099579322e0115ab0b3bd6c814e216ae6b2b80206354925565b7bcd97bc12668b7f3530a95409456ac99bf01200000000000000000000000000000000092f6f594ad0d92c9c64f78c819c44320e6bb5dc1dc8fbe58acc7ce3c101e49a74ae6d50b1a668a3b7436dc445e3da345f0c1a7c2dd281f7d2f006497f99f65d6a1e22f1d9aacb08724b3576aa19e19f0000000000000000000000000000000000428ff447de18dcc11b2c5c679bc2efd125464f589013c6964ea6cab33d9b7cbcce3a5d6177bf43114ee256f23fefa10000000000000000000000000000000000d1ded695e88dae6dfa702375959831f4bda688fc0faa289dcfb90a07f3a7963f2c9070958561909a2051a852cc15e1000000000000000000000000000000000c39bf1d11fc5693167890246c81133faee93a8639f459429757965e0b62e372153ce53c61f2c539247dbe7747b27d1c000000000000000000000000000000000e84ecb6dd9cbd4133c22350f07a976ae13dcbe4c6ae09ccb023f2118fa2dec68c20ba2266f9b571bbe30dde97480e0a94c1476ae0a62c502aa096a371e30ca885dc13fc417e3dc9bc00bcdf516764100000000000000000000000000000000015e040fc8753f06ed1112cc06e2cb7142a4fc984834f01faae718c17cde782d5953547857ca9aeee1c4a7d91df060d330000000000000000000000000000000006789ac15d719a7159b650b757f7d3cf58fca02d3b8f3685478ad5e5b1dca0508dea7a8203ece97c7c6d32b2f194458d000000000000000000000000000000001824d75634043cac3fd17ff0bb141daf7010f70b5941d8f75f1ae076713afaa7e0a0a25fc71038baf1b1255d64c914c6000000000000000000000000000000000a2f71bf85af6392a8a070596e30225bec9e3dc12c70e8df7c545bd6bbcee56799db2c9a8d2504c4f90ecf6a5e18abc9b677bc9f1f7572f808e969aa50efc519192ab8653c71090e5cf8cdeb1a3544dd0000000000000000000000000000000008bd859ff1f22d682f86e1a0e3bdf3a332ae78d64814720687a3de44c9bdd7506d2696b4daf81a94d33f64983967fdc2000000000000000000000000000000000d7b4b958e0087f8edf18a4370ff98700764c126808d5c52afd3e71ee326c766c1e5712dfa351cf5b3c518e52133ce780000000000000000000000000000000013a145331bdd9c93e63edbabb9f6c541a7c4dccb1705f07eb353a0407074a76022a8e5f5f2535b41ecf6474649e257bf000000000000000000000000000000000a12e461b7439bff0dddb560dba21ec53ce88f71fd3dc10723f3d8742ed63a1ab725f7e9619ca1ccb729564dfbdb1be7f5ca580a25a5c87015f57f7c23cc51a0beb5926c84d44659e45512da51aa0cf4000000000000000000000000000000001430a8184c5055008a06ea22ca9c997d1a24ddce7e374937c32ed1e487c80537b238a589b5e50b86fa194666bd3410e80000000000000000000000000000000005c78c94f457bdda242deab79524bd2beac82bb1cb427dcb2872b56d1f46d11fc9d69ba132004958fabc5da7d6d103fc000000000000000000000000000000000e985e8ca038b5dadc9fcaf22699e75cad9d2effa47fe7d4c579ee056b1e34ccc540372111a665041062fc6c39e05d170000000000000000000000000000000018c865243534fbde740de0ffbdeab0d38ee878c20f5d84c0226d1f2b14ed3359f5b5b909808b6b3789bfcab3be75c4cdfa1cc45c35e266a82899d8ea0c9c1f96f96140eace41a8758a87975b088f0231000000000000000000000000000000000c5b10541ec34dc0a8b8e42d9d6fd6f4f71e1fe56b5afa323f4ade35c0170b5e224a66771326d9edbddf2bd38c6c68ce0000000000000000000000000000000019cf33c19936f7489a1bbc095d0f5c6ddc1f43bccf7e8d1b30fb8e8cd1ef747b483b9a8e9faf21cba7cb17fbee887ad70000000000000000000000000000000010e83916faa7bc9de9feb8a7f34ac6f2aced06a771b662cbce846107245edb9c07632782300e838957788a8d88c8253c00000000000000000000000000000000066127bed5ac9f2871500fdd68a03ade57c35449d4b4186b9fac7c89e91b4ebf2f2a02e94d0b578aaf60b32017f147a493d2908aa9266844eb265c2b1c17f8357a5ff039836ba83c837909f6a9d0bc03000000000000000000000000000000000cb5a734a28b44f04d39ffae049fe8b63b138411661ca6dba00c72cadd47b50ad4b71e858e817561682d6ca378ebbe870000000000000000000000000000000000baf4d689baa09aaf763ae7e142b801223c8ff58f2b541ee4c44ab2460fb8f6dfc1e9f61a8d73aeb92d7d08c281cf410000000000000000000000000000000008a0c736f19bd0005c9d25f88565b1355e53fa3403021577de536712ec986567184f4dd626127ee80dd03cdf9044b2ba00000000000000000000000000000000063ffb7a3b4e057a9ffe233296c11fb462136fc4b187be6f9e36f9e6d335a3d673ef8b9ae6f60c146a075a1789f389cf3b94325aad8a2c80971a781bf6f6bebad63ee37405ab7e903fb7094beef14d06000000000000000000000000000000000c33d89595d039722222b9b9ee7ff1a0dae896a8de97f202d3aca00bd81d0169f14676efc4b051bbd339dce862d8b60b000000000000000000000000000000001109a24dc6f70bea47e040b24df395bf561cf5f1ee79e90c9b0480fff0795677483a85e6f2e9ded4f36ca849ff39d6f60000000000000000000000000000000009c7878f3a4e4e3149b72149a7da91bf527c4d7c94b15ba80b02e0e50b02a2c482ecae9f458a881c87e669986514f6d70000000000000000000000000000000004284448e42187c128578b801f76d421fc508cfee9360a7203a91d6f9cc7ccb6ed3211fc5df9e15f14aea98bc298b2f95143a8e734824840346078aec03d6760564870c5ee2b2dc13f8a39ac452be9f5000000000000000000000000000000000271ec1a3f8e3364ba8e101b49c0bb17e2b7c7f27a4aa4d4db5c07203195050f30c1a05d33c524a84b1a2f0ce31a587200000000000000000000000000000000082ce9d1da5d7f192c537b2bd617b36b65f88b308fe1ff85e47c64b62dc62324458493d1cd1da9f5fe308d27545fb6510000000000000000000000000000000000b30356b59eb04258096d0c3f357fb04471583cfe6a060de5279bf2cff4413678c1716ba87d0b6de6b6e79a96ec26030000000000000000000000000000000003c02470a14211fef14d754f6f71efb33a06a76e099093a5b9512f907ff819e1e0e15f14995febe48852007bb5c380bd0dbee37fea759c2a58cf360c654f85298e8ff44b3f900e8229c3f838345d053b00000000000000000000000000000000172df3290c3c5044d590eea59980d02e02d4fc6fe7948168492362de8f0a85df0c3d09d8cd8b206cc4d1608311ef4c130000000000000000000000000000000010e4d14065315a0d9e48204e47955ee9652b08318251a7836f32e6fc015d4856444172de44b3b88efa1b54dad346e9b1000000000000000000000000000000001549b9c85cb2fc2c7495d7ef6aa1452e58937baf58717037069e6bc6d72ced3a163f800991cd26510e71aa64c44f66170000000000000000000000000000000007814c2f1734fcc8cbf9fcba06b936c86d0452a2370f8c9480b97105e42f9babfe0869cecda7e15500e9d8d868290201b92f9db82d0976f4c379622c4028002ede2ab17f647bca3bbfb159045cdb342b0000000000000000000000000000000014f849e9749a5ff6b7b10daac7f5934be5f783d49c8593367c4243664e01b1d3552e878802d7dfee823e0122e9fd46f90000000000000000000000000000000000d0b32d7904dbf08269ca3c6ae3fe582501f55e32337ae361fe4a58dada560db54205e56a399aed33bce8758a05ebcb000000000000000000000000000000000cb21440baba44c3cc6943c8cfa2fe544a652f06423d3de06c2ff734ebbb544da07ba8982b3009b6c4857b73ceca570100000000000000000000000000000000174ef591975fdaa0e3cb05bbb4140abcb38f685ce4de77c95e2cec1911985557b77d9229940b8c9157ccf9fb553e8e0d98df4ba50cd5cb5a02d5f50b3ba23e5f5b0172a46cc315a0a94fed05551a68af",
+ "Expected": "0000000000000000000000000000000006da1222c7ae02843ff289931fcfcb315f621972f45e4fb4160b8bf48cd8102d50fb53d2c699afd36892d91f5e608784000000000000000000000000000000000523048c5de2d0139965c976d8c3328666e99c249104712719e992334442245e955cd6b14a1e3d666220617d78edcc630000000000000000000000000000000009f669d4e7d89fa8d999d8d5a6323da9445583344276bd6a29494a91174aeeb29132926a893d5a0eeee9c3048ebc0dd200000000000000000000000000000000099ee1c33d6f09a8d063393d2a8debeaba93027e31f7b23c5170b6747f56bd6e6494de966dc280dd67a38d39ae35a336",
+ "Name": "matter_g2_multiexp_94",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b46cd281a09b85d977e88cb2251cc61cf13181522cf1c344b114783c4fa22d08f2d008faea3dfee8ea7c56aa35ee39a0000000000000000000000000000000012b530bd34f5b31161355436c7dc444d41d634b0ac3292c0096558618005fe82d189e4b208a48240dfdb4d50ad44dc620000000000000000000000000000000014d334e7835d4bcee2698ca4f643f9692f28d8090ebb8ed8f67c60639c64eb116067e5e8a6d04a0c88c765c608d57ef1000000000000000000000000000000000578cb4e243b4b20c99afefcdc0e0a9e308ab4bec6d655a8c4981a711515c807067472a6fca30060d776213b8ed98d74e49662df81f6bd455ee554704ff0c7d5a589d91e017d7ab4c500d36378c17c8900000000000000000000000000000000046ad1212696acdbb686543d284d7cf2e1e8e8c10af76c6ba51d55f060c006dbab25d3a789c71c428f5bdde9aafbf6d5000000000000000000000000000000000a6a880d52fed6a45bdc61d9ee78d8fe472e76ccbe155bddd0e2a967f4d116bb9f2dd4c62cc6f7224b835c8060213ecd000000000000000000000000000000000786544589eda15edc433edcbaa46d4953da72473f04169ea64dc114b99f0a58181d41dce1fcaf7f3109f66aef02e53900000000000000000000000000000000030759c3bdeafc94fc8fc0b03ddcd96869459bf54ace74582aa06c179323ef076aef89c09ce8e7bf9109ab2e8c8fb0be79eb26c79d78ab84c4d7e48e56889a601fda17901037a74fd79355e7536f3953000000000000000000000000000000000e6addfe0db96a7377fcab1fb92183fd7d7f13ec003fdfe0740bcc8cf03d8cc602d5d808b4bc874f34944a65b249997a0000000000000000000000000000000014a4337107e716113d8ba0fc7f75e85edd1c132e2b3dadb3f9cdec1440f261513646525314b5c0de6fd372472aafe877000000000000000000000000000000000d472ee0484ed831f8ddf7ad86faef5443df8b943c6fd4c3f94c8d52d9eed6fbb53107170a60f25be52219ca4816788f00000000000000000000000000000000035d06ffc452c65a31f80c3f8a0c1e2d15e32d993ec06c50499bc0fb8f669acd3d2182ba23d942489ea922baf61dd49cd2918ddc2bfb7f7cb3d7e74b43b9a972c5b51ac20ea83f41d5b51034b5714c0b000000000000000000000000000000000ef1f5f6b3041939557368d613279043d1aceaf5fee3ed90b3b756ad409d700fb41e62b3758c8c2d325db7a37f339c610000000000000000000000000000000004d66040a8e055399bacb6a1e762b698afbfabf789caeb957fb7a3dccb01d7dff5414e90f5a14961c4e980b298f834ec0000000000000000000000000000000006efe9e66078000c26d375e87ffaca643aae9cd3f8337f5718e0e268b74f4b7838f7661dc0ce60f557e162a21ff467160000000000000000000000000000000014ab782a3b2c06af7e9c2f28f1604cbfa8a676a874853bf38195780751d306936cefd1cc38c2192cb756e28793d2abb3e9a8159fd7915c15db69355514d9dd26c66fbd14af969ee576401b1b782fc6d300000000000000000000000000000000057270788a199a894b37a526a26bc4d293780d365a6b66247e7417884d543dd752ef7c89f2f4b38f4b51e6f9d86b45ad0000000000000000000000000000000000b59fedd6798487ec09d226a7406b27f04f7983075b4659ca6a78c6bb8aa83828fafdc6488518e2cba6fa4193de938c000000000000000000000000000000001105c18d92b4192833302814ee9b176831e57fb64b703ab3c2d3f440ab302c8fdf7ddc81933d3b1adaad16038dd6dc1f00000000000000000000000000000000020509b08e6ed980df29da649051c7095edcd4eed4ce95cd797da430cd09062a110bae21b6f73daff2053fc0289041fac818ce6e33e581595e83cf8d33a62edc26ed38c22f20c6949a94e2652bb954cc0000000000000000000000000000000007be348ccf6a76827d3b9b33e7a89378c133c9b226e47dcb205ee061423ee6e1b838bc262a7befae7c15aa385ced00bf000000000000000000000000000000000689787c19192ad55b9c6c260a5ec3aa203ef71f0b746eebf10f82526c4fadaa8570936d7049c1a46e7f3cdc455a63a6000000000000000000000000000000000306965b09678d481aa4c754d56a0bb4565f16f7523cd0b404fbd39dfc3b6ed483f5239fa30f13aa3e87918ca039d5ee0000000000000000000000000000000000a2586143f9610a96eb0ef86593988770db5ed49663eab72f8c368b9388bdfbcd02fc6bee09f4fe055813d140ca0fa89ab338e94b31d22947dbeb20fce3150127249d2db6107d95bdd032eb24c49645000000000000000000000000000000000018f46dfdde786a88e582ff6addbecb4f58e12c2625e3d6440f2e5b5781beaa95cad6f63b7d132e84700e7bd344fe3200000000000000000000000000000000185a4fc339a95a50551d53c18bb0dc3b74e9c164729c2b0d919392f7aad2be3ebae3b8f676ab81ea05233b3039918ab50000000000000000000000000000000015395b020a9d0bb336066c1347dd91c557b6ae7b8817cd8a2cba9e5bb149ca3401d661227c26d52a9be234faea894c8a00000000000000000000000000000000103d9d7e33a0767554e13b57dc756981488a3c7dfcc026ea84b35b0af21193e301226cb5a4760962707d19a95841be9296acb797236dbd0316fdd355f07b9b45c9bc626f73105e87c376af4d7dc075d30000000000000000000000000000000018359aad8af59cdda484232b885d1b14956ec04b5584684b13a64d97b8310c283e5d66637dd75de405f5f4bc65a6879a000000000000000000000000000000000849fd55e4f3d4dfc643dfede6356826eef21290b84f7e8e226deabbc84273d95f7be5479e9656dc907ec367a7ebf8f60000000000000000000000000000000006ee01b54eb7834b4de53f821ad46f467cadffce6df09751b728d0952bfe615253d7ad173892a52c6181810a815bd90600000000000000000000000000000000161472d45b56dd9fd276fc607f2eef84c5c843ea05799e732d7eb6dce96c632335949e1b3a06815e410e919f4cdc3fb360bc12a8b34e717b2c410d026660c14182250d7c66f8f88dd4cc94e550421caf00000000000000000000000000000000107ef91cf3a3068c4e5644676f7bc7c5f9ecc361524bf3fe2ebfc606f22f8f83b38c0d4bae89f3cdff6119cc27fedf820000000000000000000000000000000006a7f7cad2fa9db8824e4e30da7158f7737d2536554b904ed835c37add0341c07c5220db0f9801da2587a456300c7b75000000000000000000000000000000000f6dc3adda42dbccb1d1e3fea8918f5572e8b26ba3011429e754edd28559b731853761d33777f4e767094f80e63d417700000000000000000000000000000000107d93537a79173ba9367732fa3a28113ec37e053cdf31ce6970dedfa8a9b4cd55238289be9a6f40319e3dfedd132f95537f0f732fee8b882d254a81704d2310c05dde186232f3cffc05401fa98302150000000000000000000000000000000019dc19a1663bb05ebfc0b7cc23ea9e07376de413f77e15a685a3f11fc19bf0ddf38d5671e2a5e6e31624cbcd47a19cf60000000000000000000000000000000019e78aae57f327fbe8ce794afc22bddde08ff9bc9ad3527601cb1fd5dc0b8ed8fdf3b210f86760954b48bf61d74162220000000000000000000000000000000013954a533bf871e99f4a7d81a8b9931c480ce7fc47260c3708c590ade42e6b7bb887d4d24aa18642d010a8170cf85d34000000000000000000000000000000000a561d3f64ba31a6d45ffcf1bcac95f8f665133a1e962e31351ec78e369042bd3afb0c43d12b3087168c1142107241f31a22bc0bec2501a505cc8e00a24792bb380ed451ab6f56fde07ace8b6c9348a20000000000000000000000000000000007149094366e29537b0ad7239ce04bf49f253e4b746b9fe440dbf9b425bfff21064fce66e286e08c87dd83e22a3b499b00000000000000000000000000000000045ead132e0d03c842656cfc82a45c8b4a3b0cee7a5d071c5f235791ff7b5ead071b2c529b446a15aa8837aafc11222d00000000000000000000000000000000013159458f2123698ad4e7d41da47ad7d5083b928839e346a32f2307ee69f643ca11335d50e47d328b0079f1873cc7e800000000000000000000000000000000167edcf807ee723ba70e352367705448047c6b5223fe703381af6bb103cbb24da739ed005b14fab5699fbae6574505a7c7b10c801fb9d929432cbbe994b404d3baa5633628f396d20d047fe2c2ac2914000000000000000000000000000000000feb6f6f85903b3c8e4d6ec2ff234775f12727fdf7c35eade09c9773b004270f659b00248338f0b749d6715778f1f4d90000000000000000000000000000000003300794df19b9e472e8b869a2762c07a9251cdb96b508dfecdbd62fc3c3843b37118d216a64519bc3bdb71e40f9bd700000000000000000000000000000000005fa144135a5d6cf1c73055750ab6582b4c6d368566172b75902b1fc7a6f5de2a251ca7efc7ac6cc6c0bded14df02b700000000000000000000000000000000004239a7bfdefbe78116a588810328024b1bcebaf8f28f09387dcab66dcf2b02c94002df09d12db369fef9dd960783c0b84f2f3f31d9869799ed8bfc2cb129dbbeeb096d771730ae2863c4ddece66158d00000000000000000000000000000000007c8a24005575a3098c12ffa65095bfe227ee59e5e978a7ccab7a9a72391fea61690648c102ce24af723945bbcafece0000000000000000000000000000000000323d57bec7dfbb4614c8c3b286860fbadbf71901fa006149053ea614dafd56b1f3d6a86fa55bf1cbdfe8af4ff08dec000000000000000000000000000000001180b2b0b9c4c12f6d06eec07bbf6f5a220722015fe5365d1c4ca9e58ac9c8f67964d8230152d7a2220575c756bdf8b0000000000000000000000000000000001969a364c447f07d0820586bade587ccc816e50696aa0c5ea4f1daf6cd577769a890b44caa013d93e7f21f5ea269aa85c62206fadb762c23bf77f69f69bd492674bb92edb39248ad2a432f819304e6ea0000000000000000000000000000000008a51c01c3bbed13d42a4da626a8b89e2811db1d83d7de3332b36881ad14a5c8668ece4f5ed2b71204810457aa3d75cb000000000000000000000000000000000658a56aaf627e3f776d3f03caa2c00425bf197c6fa20c92f563f48260109a8f935d0d1638f5039486ce0c0100834fcd00000000000000000000000000000000126d1964f2d964c290cd7364e175ca4a855149e5c4ba488829a436b09ee5e21f6c964e439739f15317873088726bd51f000000000000000000000000000000001803186f88833393bd853970ca4fe414a43b7a619ded1f9c830444b4d43a94e9146146e2284d690436b395bf1e3fad15a6f950de53d07fda75ab43f73982c2684edb06317568df15b8712dff2ef782830000000000000000000000000000000002dc3756c7f4bb47559cd720a3acf4159290d7413e0498877d1fe321cbcb7cdda90b6c8b4ef8e27b2642b82ab9b3174d000000000000000000000000000000000c7490f1ccfdd91aa37a3044d265cb0612bfd9c065c370adb813b2d96f02d44041e79921d1b8935dcdb8c83ea4460ef30000000000000000000000000000000007beb34bfb9ba9b6fb590c7e830400888095d1958b252d187c184de91f165e12599d66345341292fdcb662deadcded030000000000000000000000000000000001ce203d58bebe1eb5b7cbc6038f75b2f7534bce9f50e7e4c91d6cc5ac1bb68d9fd8ce99206c5ec92bcabb71672c6ac195a373fab5176d124f783a36eb2346dddd5c4eba9e24e4c0cdc4f925e2e24cc9000000000000000000000000000000000765acace3e238e51bdaa08c0f6d737c9de55b5ce9ac3523335f0d35bfab6f4e7e2944b8aa4ee031ae9d39d4db96e9ac000000000000000000000000000000000b0fd488a6f9e92c4bdb5e82b52a0035f9a0aed7f69ec65303632017669f34d11552f849326e4dd204d58f50f3ad124800000000000000000000000000000000033991f66588b5e39eb78c7cbf62a74bbde2fa1b7c96164cb58040f0887c485b372e0ef4def9d38da9c6f5c4df2d59a700000000000000000000000000000000187d41fa7905739078d2c2f8775394f830d20352a9d91e97568c6929412f356009239bc9e1da3a8c766e89d09893b5b5319d855218eee020f9cf8e4c0b6004902f0b16eedba8a1c911476af34f65dd40",
+ "Expected": "000000000000000000000000000000000dedf92894c567ee656051a7f02384edc7206152af6d3c5f662ca02559a3cc349c6b034c6fadceeccf652a396dbec6c900000000000000000000000000000000089deb173bda620678247a7218408594efff7ab0cebbf627b93ed37e553cf944e09232b92afe2f5f31d29bb9ae442c26000000000000000000000000000000000178bc39b2ca8b032d3cde53d2da3f8797026d78c76c51381b377c79992f027cf55ba4e182773c99c99ea6293a948e5c00000000000000000000000000000000195d9cb91537e77e7a4be4370b982b6d36190342ef6ebc2250a9cc8ef6ef45211736ce1f41da899178c1adcc4927a9ba",
+ "Name": "matter_g2_multiexp_95",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004638ececd7f626a069b1bc3ad9d0f7cc71e5f0c1b11711fbfee1f81466b574f7a11de8161e55eb574ab367f56b9d6480000000000000000000000000000000013ef4f403f139771afe7e97815d3b3777818a3054d02125d3a25138e504c8c2c6696061572322aa19ace9ffd8e3ff308000000000000000000000000000000001910f776582f5acbaea626d2378e9da133b63afa087f25c2cfbcd1e7b34f6a237f2e9adccc303f9d5efe22496ee2ab75000000000000000000000000000000001963bd62098614c4ca2fc2a9e2d679c2b74bf9d322d34377cc63c3b8e7f8a4eb7d6d440d081e044606402fb3f51b0cee2a397c2f19a8c4e66df0e062f179be2f45a0c5e104588222a1a78447512f299b000000000000000000000000000000001935ecdf4f21cc6b510321b4ed2663e339954cd7399b9d67f1d9e2ea7fb9bfff8531f83ab59d3f0546393dc289ab2dd7000000000000000000000000000000000f390b86fb4cd4c1a072a83e1d1198a57a650fa6e94b69d983b693c592bc0c8fcd9a46c6883adacc4c7e2546dcd079fe00000000000000000000000000000000136beae11ea54ae26a8d69015ea7793675625b2013dbeb081a5ed877832849d67ac709b81fcc4fb322b262ec3776c0c00000000000000000000000000000000011f1df574f63f679b6464df463b58948fd337a4b3f159229ba0313cc040303345e75a3a2b0ed0dedfbefa89d8331d074f193d5a575c80a3e7599923bf5a8ba8a48e8f98322d1d8eb1da42e446d518c1b0000000000000000000000000000000001510378fdcde4027999edc99d49bfb46423ceb0d740829e310f8a381a7632fd0d6b6aa3533c2702a5ca76d386ac0145000000000000000000000000000000000bae237bfcc061552ca07eb14300cf557c974611885aa6894f7933f7dc7a0a1cc3b5587bbe1ea5fa604e3cee1db5f7c9000000000000000000000000000000001743207a1814990c798dc3de272a02b1b194a485bf09faea382dedd957861dc15cbf981f9906cda50cce2899785b9a6300000000000000000000000000000000106f902004c66c80437392e92cad73bed6b73010bdc7b6a75de4c01f0b6fbe5b8d1f47378279bfa42b3af05120854ced07f2013742ddf2d35448feb80b6b7aaf2925d3975ce28ed2b1ac789886ae26e400000000000000000000000000000000123362e41268f7821fcd2294b032c6a51c6d80506eb052ab6132267fa248a1a60c3e4eb2e75a1674bee1c9d46d82b9180000000000000000000000000000000006296670461ca67081cd76528446867e1a4905f88742d0ed8d1f7baf86e0a5e5ee86c8b0eeef07c14dd821dee0143bea00000000000000000000000000000000058bff9544e4e02c063158a52a68c93c7544e8157d37159dbb99b51b09e3d8f5b307bfe63a10fa409e20a35219ac244a000000000000000000000000000000000b135edfbf53187004d0977db94eeabf426ad7bea84ad76c6ac771fa186a073d430af76d717070e3c4057a7a2da095984e637a80a4eb1b2caba68b6828aa18f956c62baa7c5e9e591a15156c5abb605000000000000000000000000000000000133d3a223112dc5665e78fba8fc8d040d133858d984e66d2382d5e629f9369dd127e93c7a4da77fad98a0520ebedfeba000000000000000000000000000000000e88515db391bcdeeed2a9f64d27387af0391bf832164fba79100b560d8150debbd703c140dae3ba9b1ec35c1f45670600000000000000000000000000000000042583722c69a19f413392c6a2b75c8ca969be85eb951056d7e1d94e046dba49c346d5774009b8463a40b0576ccc1a6e000000000000000000000000000000000ee61a9eb6ad497c57405a44d798868e22b4fd5b8c480e9938cfdd3f1817eaaf331a9988368680158c59c2801add0a7a27671631f9afd9d2e86f263f5c17c3c11c7f6e43efb6d75cb2cb8250094f228900000000000000000000000000000000020352de9b4e8ea1acc8589bb22e23dfd0ae3a80de9e21bdb3f6391dd05a012e635de9e1f5f450bf4aab05728c054f8a000000000000000000000000000000001733593b94ec800bb59ed97dacbefda5ad882a8023346bdff8f471c5613c67247e27d72cb4ed8cdaa0f236018dd2128a0000000000000000000000000000000011f272a3b25bc519fc3e229211b846042031e22fbed22ecd0d1a4ef1d05feacf105772d71157e3d7293575aca257cd5f00000000000000000000000000000000153b4b4d7d65f7bd13d20fee4812f04706c96cd1a0d27b7e139c47299805e0ac86e8941aa38d90331c78a61c2dd56aa3c2decb1f482f3eb48e7f52b89f6452b659812ef79bb42fb25f03aa9969faf9bc00000000000000000000000000000000143e1f6dd9397f0e89a46c6ec995bf6c87ec8a72b309f050dc5b3134e00e2a16327767cb0573ca5ea9776215a5815df500000000000000000000000000000000186cb3af2cdb4562bf2d0c180079547cfb345cc3943fd7f9203fabbdc1547079cb9ed854f9b1a47f513e318cd409df83000000000000000000000000000000000c8c9197fa5a1e66b371a653c5d18c01fed8d17a8aa92d89b2cbd954b9fd2931fa61abb6676e4851dc9481732c6195610000000000000000000000000000000009026b259e840cb5264f6aad6ebbb09661f5b6d980389817309aef99e4e0cb228d3a7a06e6c25bdb1aeafe5acdc44441911eb1de54fa8ccb746336b681504fd08f995c864a8dae2aa866862f81f0e7850000000000000000000000000000000007bceb74ba86c07d0fca20e4febd3b12b1fe9f786c9a5da0531550244f40261d7ce728498fbfcfe16cc235db6ed42e11000000000000000000000000000000000883104ffcc0d040d70bda04dcf67c1197c39e200d4d9daf5f3c185638a13dffe3dcac94fce4175187dad867e8d2b78c000000000000000000000000000000001404e48e86f199486db7d40076cc8dc4e2aa2c1b6d4bed8f027512e2c71817905b26ff4f0551f9c08a2a7a27b2075b6c000000000000000000000000000000000b789a6addb98ea43c0f9e85831a75b8ee1977936c17929fb45d4c06b4f1ec33b9b41e32b52cde542c9e4b64d27c686cfd0a61dbcb0c657e824cbcf4670a31a95ecbd47a9b93812cd5124f3ac9450c1b000000000000000000000000000000000654e7f3985bf90dd1e3169382690fdc0f804eb6384ce407a060f539804fe6e0451094abaa0dad611c15d3ee52f31a92000000000000000000000000000000000deeec957d58a2246ff8f7b7448f5198647576c16c1717369ad155ae36d5a6bdb42c8d6a1f0a095891fb0890b6203f950000000000000000000000000000000013a01a6ca4c296f59cfa4a5f5399d28af76ffcb8b218c861d5e6dc603e140f730f632028c8da46c823d87bff5ca703280000000000000000000000000000000003698f659e86b96613ca74a480c81e749bce4b74324976c1d241a0911d078926fb2adfcc3f901a7a015a02f525ddbb808118e9c70cc5def8e7d258e05273937c514131f39e0cc9fd2a3620dbffc7ce3c0000000000000000000000000000000016ce72e1798ffd84b52ac664a184c6cf5ce1ca2aa263c9d056355cf610517e9c7bf7f057c342f6e3ae801b84c2082c0f0000000000000000000000000000000010992af1438eec10881b5e2e3fa3b1e91b6b5313ea58dcc0cd2159f8ba6ce5912d81b38956929620e04b3596f6835a6f0000000000000000000000000000000014315dbebd532d0c835e8e85a02c0814574cf040a20c18d06573718223c8ea15b7ea69f0cf342dd09037258398ba4bef00000000000000000000000000000000136d13a83e72525b2d4af54d14d5e21d8bd9bed18543836b02ae0a7e51d433c93aa1943e85f978a8a9ff4454d8c5d120c445931b79e2b826aca02d1bfbb00c2dfb6d30ac2ef97a4ded18243b1afce7730000000000000000000000000000000002c1bf7dc75006c2941b89a2de52fdcdd1b4fbda5b14fe3fc165915b90fd9d93cdb8105898ef59d5b374707f0afaccd600000000000000000000000000000000049a16efcf81de84e443666bf990f6aad2145f9c9c2c61a752e256e8f447dfb27b462e4553544971807f909a666af12f0000000000000000000000000000000000aa4702fb69d791ef958826753d3f74f61c7a591ab94bb6c1bd5d82d94c5877121ecfc1e769d0d16ebe491b775ad96e0000000000000000000000000000000008cd7f2562eca6c53a37382fcdb04be53998f45c2241bfebac3d1fb08d8e1d4df3182f2bd63861d0de72d58072356ccc982ae6de98df906922e660d461009ba6c04cc6497f3645a66385c775b21b210b000000000000000000000000000000000a6b30c4ddb692ae33c903693cdba00ba48efa48e90b9cec9dc747004e57a8d5a05b5522634fc0de306d38c28390dbf4000000000000000000000000000000000601341b3c4057767a910bf30dd16324ad7abcb55b7e98e73584f26d7f87d8a8d24ff2113c12ceb3077bf65e0912b2360000000000000000000000000000000019dc9c50f613470abdb5c763c0272e88e34ed38e617d6757f4e70d05b8ec9f67a023b4ec1363e7e60e38cff64e18f0510000000000000000000000000000000013fb1858f7efeec5fd03d9f7f4513e3e9103c340eee7bfe48ed3cd3dd073b96add9450a17f12e161f1d44669b1b2f813000674ac5d09c6c599173bbe9a43726c120c3a60a96d43954727a2f33ac4320d000000000000000000000000000000000d6c135bfe0fc7af93571a69b7c37ba691f051d69582cf159cbeb0bd59b48342172a82a3eec2e3d440805934e1574f2a0000000000000000000000000000000001b04e56cb3bb221caedd3582943f89a33b955f624f9e473941f1dd987f2898339142a654d11d87bf8bd2fd0fe0d4c1a000000000000000000000000000000000f185fd420b761a1e38d542558b0beffba916f369b37296fdd8878a7c3d2ac9d3ab1d8e45ad799f0d81bb439b5e5058100000000000000000000000000000000002d10ce460c414fa1094ef2b7de8f1ce024b6d086d10067be0fed4e45dc25c8e50bef361d39a2743be1e1ea4fb7e2ef773f8e9637886d795b75e7ecaee512005c1780e7ab17b9f20ae9232595478bb2000000000000000000000000000000001972ea36bae504d7047639ce6e0e6c3b16afe89fa3d6c6b33c910c8d4b70782d8165912e5bfbe8bd84f78f9f23f7f956000000000000000000000000000000000ae55c4fc1c01f1bbdb060191e8551a7ba5ebd3dbadd138202090d7dc6765fd1ef5fe8204ae76a8bcfa03ee5985a35280000000000000000000000000000000018ebed295805e0fc14f1c7b0e6ee12ca48cb7177c1d367a613e0d6cfaaac5128fefce0e8f38d4e2f11ae0d327be466a400000000000000000000000000000000157068d89fe48e77e0f62e3b5b0293423f35c5f4ffb9e0577f5aa49e91cea6bd312a0e65ec08af9c1f53de6499409c8d759d0bab12ac790cc3a16e88f1a108e670681f117d4fc7d01f8c5a2d6ca7fe8e00000000000000000000000000000000120e4a8935c08032dbfc19a43e2a770b12b05cf1dc229e12f683f0d7f604bc13666bf318fcc38038b618ef83c9448b870000000000000000000000000000000004e3f851be46bd85f37c8b1d84507f4ed63ea76bc305cc26a6f4cfa2135d5affcd3b319d9f57619e21c964c6246fc3f600000000000000000000000000000000138733f352029373b19e1c40d5958a04257e2b344770e1bbb8f377bcfb1c7225ae7a8b0b0e57795ec06a08e13c90d7de00000000000000000000000000000000093e85783c556a017829e28bc42b607b1035890fb9743bf0e279df4dd8a695c1dd07a76a213087c3a8a7e614b29b7a1ecce865074a8a41f8a3f40228046c5be68bdb50ced10bb73ac8472f0525302938000000000000000000000000000000000be1ae00f9ba0a2e57f94728508e0029b1bafd52c91ce718ba41790a3541117d1a9f846d68440978cdef016c3b9ae422000000000000000000000000000000001947683154204c9fc93e3aeac17b417453a24d01804e8acbf6f67947f5962dce875f49d05e6ae65384602828784f852c000000000000000000000000000000000859dc1c00b49cd1292cdc65c6aa4b11e27637b949c7db508930c557ee3ce00f98f9cd3dd0f6d73a646d176a91d75c070000000000000000000000000000000015a7a6984b5f42aadebba1e1f4682aaf1a2d01c9ce2afab7fed2269373467787bb1361b493dcdd862180e9159ec2ad5785e2f9597c9b687150864e90ab042f4f012a54d92cf9d2ece09e4a081ec9773f",
+ "Expected": "00000000000000000000000000000000047cc33d9decfd059724bbb014fb9cd95de187e2dd29cf4a9bf9ad06d415e2cacb5a4e49266c13e0c38f2563d1a21d6a0000000000000000000000000000000011c79d93fa870d541e79ad4037c20b85d3cec053587f9df60dc11e7dc2727d79059f75bef76474c09fe61ed10b317cad0000000000000000000000000000000003df3f0db20c5ffea4dc9f4d9333d76141447bba50da18e521e89aae1e63750c71b392570d79e597967dfc9952e903c60000000000000000000000000000000014e83ea645b1019ac2dfafe370f616af0c5baeabe217ac1f9ecf78877717475b25911b339557422526a8163434439923",
+ "Name": "matter_g2_multiexp_96",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cd1d25f285c2073175ecad5bba4987cc52012eadc7b19dbaa20fa82d7a6cfb8a52f33469b6308d921eb4b3b23f7022d000000000000000000000000000000001707b67a23d9212d30c06f26f0040c38389b185057e80236d2c828a8d9ade4f72eee1d6eccd78e4f4d71e2c28ee9539e0000000000000000000000000000000008e5c04effd14d915b9afc2083afa2b6d4008cfa0e47144a41982d8b5a8e77922a2609384e2c5d18c871ae24a7d505b7000000000000000000000000000000000f414acb056fff2cd6d9b408adb6eb7f34c8f66a66ee93945a3381d46c2d181613047ca6d4067614c190da444223cab685431a1df7678e49ee049b75ea968ca255ef456dd58cce57b64edffac1ac223c0000000000000000000000000000000008ea841aced2d0b8dd688947648a8ff18d0f6f03f63ee1c331f126dd4fc0da3d386535156b80902bdc1f65add7769cd70000000000000000000000000000000017a32ad2763d99c38c954f62466e78c0332e48875e15afbbe9c78376f1bab12346c73a573738353e2162d3928091dede0000000000000000000000000000000010ea738884dbfe5bc35d031bde9aa4109b1fca529502e236aebb5ad0bf71dd2f3db250d924415b0bfca56519f8ca5d290000000000000000000000000000000013699e29cc1871f51a469898be8b3c732b5cf7860286e655e65bd8176832804d17b48d0ff85eb023360db78162581297b6ccbc0b600f11f1b89061d94c6fbdc9b1d389244fb29a5d140dab8842d44eaa00000000000000000000000000000000004d504e62b2825651381ae862fd33407309851d5291591cd0f541fd092800d709ede00a9134e65ee752eaceb0a344b50000000000000000000000000000000016481efba290c37aa4ecbf940c76ee5df199b0c1f90fddebd2db28120bb5a14dd9f4a067b6d4889aeb683cca0f6ab337000000000000000000000000000000001400c89942cc63417ca4cb05c9d81dda3251e5611c27fc7727c3e803170672f103bff26f7216a0b646533aac3171488d0000000000000000000000000000000019889641be9db08880543ff476b9d4c72167092548ba49a3f3ace4518d3874f4f7993ae7b8cec90f092f144ec9d66c1a54dfe31190469897c30ac3736ab166220dd3702df5bc897835347713d03a8d04000000000000000000000000000000001927fe80adc6dbb581349c603103ad8831e645d9275af8669939b83829182cc6e2a30df2fdeda6d3aa2e2a6126e00ba3000000000000000000000000000000000b6d7934d5ca1098a85a0c60acca075220105e221b802b1be97c2967820bffc2937fc3278ed0f26905c60d44d5fd8dc000000000000000000000000000000000057acc1379f23c0d1d37427d400eb1b0a89f3736c83d3ffd797ae279e01e2acddd84082f13f3c8b8f1bf7c275702a9c700000000000000000000000000000000038dbcd7e08d34c553850a52336991a7d48968e98057e930790d78b5c6368eb2fe01571b60c4aefb653ec04122953d56eff1ceff9e5184dd9fea44da4f07529823dc9b100f776cef6f6881120f7de11a00000000000000000000000000000000014052031b88af979b7edb06c99c2e46bd9df2c862c7e1b71321754841fad67fc3242b51141e49ad86b61344aec913f40000000000000000000000000000000014806a86d078ee9bdde99257b67f50dc2ddf9bbf01dde931742ee6f739aa986cfdca06cd32d23d86f2c14c3b09033d29000000000000000000000000000000000e0561e795d35ceb8bd9e3b276406ec1f697a38ada25d1dbe08715a28bdd3d6ce6e0aac01f7dfc7c2b403850ab213b4700000000000000000000000000000000146a65209b09487e00e356e3b29952280ebc6a06343c4ce14efa0c6281bc2482698bd02295bc35125275ff5f5bb867dfb273e4c6266c1f5cf022902fe1310d2191af91c47995486342bc61cd361eab8500000000000000000000000000000000021592cd7f4cf9cab3be53561c889c9ee865961aad51339f6393dd6a0b7dcc8a7c48b753c947b15cd3add01abd3d76d8000000000000000000000000000000000f9e1a80bad58055a8577700c177889c4d702de04343c1202eaed9485a76493158547b20bcb552b66c42a0c86df809ed0000000000000000000000000000000013908dcff1945cf06f038e3caac9a7fbb3a6466ca18627e93468a875759a2b5599a96834ff21fcd6bfbba82b79536b9a0000000000000000000000000000000001b6354665109c5a64613c3bd7d805b3a34098708f3d41c7b77db031ac6fa0b2d4e2f2f70c84ac78687b0c0f9bf334771342b5cd4ad3179f406941ef6ea15d0aecdf9f6d96dc334c39b7dca89d256d4f0000000000000000000000000000000019394063202186e141dcebce7b8f0f267ba6057a0f993bb1cbe22a5bc528323823bfd1597a87017d478186a18f09a47800000000000000000000000000000000148437bcc43d432d70b47dadac8e738616c97d38d0f84dc132599626612f7bba74988bb23ae47ac15e6f70c059d607ed00000000000000000000000000000000180851594710f4bb5be7ae0104a383081c50f59e4e048614660ab5a4e2661e171510f5b112d8cf97a6af27d56d137c860000000000000000000000000000000000599f3f82f29b493ffe9ee3a8363b9a599a5ef3c9c5c680d4e003f4ac5a7de0562cba8e2a4c6da7d07cbe86c3f7bfb85b36620f65ed84fc0bb344b4b73f4eba4b1680a47b28b47f6d10f9ee82398125000000000000000000000000000000000cfdce7997601afbe484901893a1b5fc0b83e8d238d41d2f889a58fd4d884df1c667a000b53b587df2c42ad46aa2c3e0000000000000000000000000000000000c50bf3e06400cb10494cd09bd89f3c96ff49c9f74dd5325f9489ed6be13b59bd7b0b2351411ac854d430405b8a2a3de0000000000000000000000000000000001db313a34ca4073e4fa2287e234ac32bc579742de22e5218f7873b922f5804894826e6054925a394f125fce850f33ef000000000000000000000000000000000e0627a66d286e8d4d3654b32fc5f552a7ca12f0bd47eb6dee0dde22ee48165247c067a0f4c3d422bf3562d38a3c0cf1249ca9bcf879a770b0a054422a6ea97ae795118ae45532c1523c842696de6d170000000000000000000000000000000005285ba39f5bd981fce2fdf853706d70992acab2dc6d4c4198144fab397392a60d631056b580d0d98f3f350414ce554e0000000000000000000000000000000013bddbc1180f155872376fcdfaff2fb12d3d9645b81bd1475a5323ea855cea820ed7eb693791caa9bd3fa5c66036439700000000000000000000000000000000125644d32df397def58dff875d7e3f14166e765ed49a3991f45b38d74db3985fc7f5052058d85594c8b97afcf850e11b000000000000000000000000000000000fca4662eb1b39f576ee820385fba88ddd2fc01fcfb9d9f874453ad725cd5defb357be028fae97ce71bc5ac26d11c1bac014a0aa616e809b674390b4553bf2d9bf325e73d3a935eba94488dddee4e8950000000000000000000000000000000015b97d7c74c8ec102083b41d7ce5490466e1c0e261b5ea5c756d3f9ae79dd2d8ec6eb5075cfb76dfcf7bfdd80442f7d10000000000000000000000000000000016812f845faf96b8b69ac7a6af3c8947aa25877199e3c12552527706a17b768bbea259ea61ea82c4624a96cbcdf4040d00000000000000000000000000000000123ad55e5cb5ac5bdd3ca0a5afa7c3f8e4b98ad91a205f073fb546fe799ffc57b3c1c3a6209547ffc6ef05fd24be6f5d00000000000000000000000000000000017719f31946aedabe0e9d88ef3f90eb6ceda884f5e3d2ece368373785b2d8bf0f9677731803b25accfcb6cb716e0aa4ab722a1c20f068b6955a44073914c418a082345796912ca634e79983a24ec4bb0000000000000000000000000000000000497e3480d58027c780f47cc35a121ee0cd76c4e84d9a2f9002c04a1c286be990167a0138049ad70467132818f48ec9000000000000000000000000000000000ec0ddf938553105400f70989140ca322d996f48ffb1b35641ca36a6ba9ac1daac1603c100822f80cf62ec3bfb442158000000000000000000000000000000000a0b6ebee28a792df46d2f727af812c15fc91a471e0d8e34b25b26048f3b9606d8375b5b268c40fb04ef8f098e1d03340000000000000000000000000000000017843dd19bfabbd0cfa41fb58e70a8900397d17ccea783087ece90962560f5cf090e8d9eaa873a6a6ebac45219ea97a68b314f83cc3ad501caa44b4c3ca8cf68c70ff6920f445d3a7ada212b6a19ba3e000000000000000000000000000000000b27c82d71f7e4aab9a68596669596df3f62071e921e131ba4d9e59d8d81d370e077e93a4a6a43e059661227f40b38c800000000000000000000000000000000093004917ceb2fb4a1b33960ff74943d520f86e83aa02b9a6c85e4b9a489e9331863cd30cb6ad6f099d03289b4ada5520000000000000000000000000000000016f04e35186c7deaf730708e1678089bf3e73c1164bca24bf8f70c4f6cccd5bbb34bbb5dc313ee428aec4ac9c638a01a00000000000000000000000000000000011052348cec9dc3e85e01abcca5a652461f08a9f5d72b3fc27140a6a571137f0065ed7ccf9ec8cebe314ad9a214d5ed94ffab83099c69845cc87727d459ae300a5725ec53176424ab0ec8bd3f80eaff0000000000000000000000000000000007083dfb0738d58ba8933a1f60283e5da8bf90af5aae4053ca573ee7223d3b80e4bdc30b4a831ce6af9f52f393e9742600000000000000000000000000000000130c627b7d3a527c94cfeba9f514e75eac047e1b6088c082229a8c95d0765a0898ce1e45694ca2c7935bb8e41e44e8b10000000000000000000000000000000009610645b074e652a08f2b89dbe594afa3009d795ef211f7c036a56274b1e1bd69a035c4f356b6b21f69b9cec2bf7c32000000000000000000000000000000001020f3cdef468af700269aa1e9d928e71b8c521f23586c9b0155314f0073da7de04ca41ececd5edcc052af72c05f0e4bb1d80be637e2abd98d0433150e14b629d98fc0918c7dfc179204669ab465e90300000000000000000000000000000000123540047f0768b0af841aa4aeceaf3dac31ea832daed86c8cbd1d33ed0282c6f697d5881f9022af032e90ff82efb6bc000000000000000000000000000000000113daffbe413075f5f4f6fb42f37b6e9d5e5822aa24d6f865792f63e6078584246bcf8b17117385db1d6233974f6ed9000000000000000000000000000000001067b46fd221b6995d25d4bf0adb088e0554d858d4e5d9d6b59e1ae2a7d57188d559b0208918a8944aedd62b1ebd4f4700000000000000000000000000000000087dae77e483d5c0baa37b9b96dad5ca92b5869fa253bffad24dd8747446f7ce60858b52438e58233210d86f470f765fe670a57ce4dcfa680e60ef33ba99c437e4fdb160ea1012de36f4b59613a6af8500000000000000000000000000000000039d09a094d655c139cb9714aa258d9548473162548048b0f07c9317a41a7e5dbaa5aca156992c8a509d4071d9ae4394000000000000000000000000000000000f0273a38b1b9d006efa43c15a53f026587a676912d0275968608519e97994ea9c6a147e377f68b1738ebeaa178f9c1000000000000000000000000000000000132cd92417578d2e46884f1c1a1080b1916c8c8404d2533a4de02bf8575c80ce7e8097c2ddd1f95737355521c0ec21ce0000000000000000000000000000000019adbf09a268a3ed8eff936d25fbe8af2874e44d2580c7941dc14fb89c5da963b468a7088c4a763eac89f4d15deaaf5e54a999fdf391d3944318c54680e69b58ce3778683b6f2c607d64450ed32c6d89000000000000000000000000000000000756dced467ea32c3c425590b7690a45e250e464ac6927ad3f5d2d8d2826961b8dd7572db609375c8d06cc3b9bc3a157000000000000000000000000000000000b79b4eecbaf1d0f8a89f9ef8fc144b3aff38148ae260da7c20e9dd3866d946585df7ed12c8b7005e7b0e1387c9db41d000000000000000000000000000000000afc403b008b70e19f17b1ef37c9c396577a585b6c34b23d09621b891efc00ef9460c3f4b5f3e851ef63620dc06c824300000000000000000000000000000000024e06f3f3b18c026a166c41f75d7bcf699480f5b6811463c27606c9ec1232fd249a46235b7f5b5a2ed3b53231b333150563ae7b444cca7ebaba36b8d59aaa5c0e6c1454a4a2907866247e752e640a7d",
+ "Expected": "0000000000000000000000000000000004f2480d0b7e84a996965b76055f6879aab5bab26656e4e5ca7220adc17f14b5946047484327bbc5952d9f2ffa5f92af0000000000000000000000000000000002f7260c55c500b54df4391a55eb4adefa7d19bcbec82a107fc0d222c898b97360a679a02ab3023ce2ebdcffd125ddf30000000000000000000000000000000002cddfa94c8f6b3f29c2fe018b1f8679d0e98c8c2656f86f327b9cbcba574cc52643ab423b458994a03347460deef6570000000000000000000000000000000014eb4c84f71ef5935e707a11a92ba34780677ac7eb198e160585ad92aa5c1ea21e3a77be940fe344e7e170680e2a8d53",
+ "Name": "matter_g2_multiexp_97",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c2c4c039047d297049afd0e8f0375bd4294d628d3a22078d93b684b737e8c4b6ad3ee544ecbeaad6b3c75d8d217f3a20000000000000000000000000000000004c77a2c0943c6f997ce2e785461f8ec253c47273ded4e1af43ae882766ef8c168e66d831abc2b3b3a0849bbc210cbd40000000000000000000000000000000004456a6c267a5cc6b7d9a9f573270855186a1b621cfdc465fe71ddb4d614565d9d36b13985b31396587919226843c6230000000000000000000000000000000009487cdd8a0cf7f40e9087fd3121cb480730f4302339d25fa12128033239662ed65579a59b837bf1bc5fa87db15b15335b59d128b5ac47106b4114cf225dceb621d177141ef5783943f40a54ad94e990000000000000000000000000000000000ba43205e8392168824f77bac344d60c1a9a0b14ab55538c3bfea4a64984cf381a2f61c64f1ba1bcfd8a7973e43f6e80000000000000000000000000000000000e95e5ac415c3e3e7c9feb6e7a2af3e8189afca06ae1fe54bbeb31783810860921ab3c76a475fb227b3c8299e3f1caf00000000000000000000000000000000001e3cb2106a23e77a126013087751c4d2a419a51beedc3a33faa6c933bedb3d34ee9c6450c583642426edb352e04da98000000000000000000000000000000000ab5af4c98aca1fc3fa55355351d12f3bc639662bf8b5b772152988d676b00ef39f767237a2fa3be936e83d1dd77da86a057c0405e24b7373f67197b2109b633a02589711b6a92ff49ca024f893d7ecc0000000000000000000000000000000012f3d927316ba638bd6294f7dd2f3f166d20285ee1662ae4dc145835704a17127078343d26042a5c397bfef31754186200000000000000000000000000000000162893d6252361c340057bcac31986458b8b55a8a4283f5a06ce1730098f9838dad1bca264374e7261bb9d08c177c1820000000000000000000000000000000017264aead0ec41a079827296f3d32c12adfca7cb6c674070d54087438d57b6ccca4822b2337263e60075d469b4ce0ccc000000000000000000000000000000000480cae035bd3bf1b4a4a766bcd5f188833e9587e1aff0e1f10e36ebbf2f3ae76bc0946e7c336efc3ee00bf42e7efbb9677b05905180182427efeb848b2ba2eafbabc7519ab33db14de0746afb607191000000000000000000000000000000000d13375356b1518e37a13b43b7d192eb74bd69636f91c570c41a741a8763c03caf8d13c7364f57c867a4a3983e88060f000000000000000000000000000000000f6f78dffb404faab88ac7373e0c765209c0af80514d438e18393bfcfeb60d9a5e13158d399f43162033571ee4a75dbc0000000000000000000000000000000010c379860638ccf3b6cb8479aa38881b0004197e3e367a1d5ef7c7fcf075689d283b87022e2825b5c789ac6a448467320000000000000000000000000000000002dc392872cf2fcd8e196f10c1ded175300070e4e38aa58c89c81e1aa5faa08d770a5ad90a8295a890551f9329a13cee53e7f69582f4c106ee5bfccba1d5f557736c1b75b6e3777cfde47d552e6bdcac0000000000000000000000000000000010383a21acda7c8f3f3be980bff2d57fa0a5b2dc424164dd2ce53c0b20ca399d6227913b7b550462180b01c231e4813200000000000000000000000000000000078aec90354721f0a31e1377b3652bcb1f388ab36f1866c955f3ea8dfe6ac2c25bc4cea14f54aee71595c2c1bd2dc4910000000000000000000000000000000007dfeec77213d952c183452b98ad936e8854608d950c0c1451262cdc7d6de5aed0db07a8d74b3e8f674967cb4839c4d00000000000000000000000000000000015c09e4ed2ea76d10d196f7a733ccc272b94dc436d6bb5fafad2fae4a96372c2c6f1325d1554746814ae292d8e6b1e3634c87bfb629b817e7ab97def7400b0a83e47af8d628787ff814733fdf34ba8d500000000000000000000000000000000138656fa091cc6613b1fcff04a3efb4f9c393985b2c78fa838eecbbbb8b6dafd88d9c72441f9bc735649480b5187acac000000000000000000000000000000000a35cec4819ca3321917cea5aa589db8cf61882fd1135031dc41a8207a8e71d326312799291b160a646148c382ed086b0000000000000000000000000000000005b6e4c02c9c54630c96271073513cac3a42d47a7272f62a21c7ad4c85c19b60b70d04719626cf4273f6c5691719931700000000000000000000000000000000166a20da734a47d7e28cce8f0c2d679fa6c738a7a1ca9089dc67ba2b1c92a83b024b8991f131e7e8802a617153de4554bebb60069acf431e1671e3d00e4da0d70fa11ed4099b21d45a2b811f99dd9cca000000000000000000000000000000000a4432a544deda931b1f62759320ada2963062e722bc1b748c9bd0d026ffae10f228be36ea0ab076358924f4c06b6feb0000000000000000000000000000000000e955b1b1b28d2044b6be371c58bc85097c77145b239e913bb0729757518c465d9e69338066f7496aa6a2038ea604f900000000000000000000000000000000017ca2a7d52c3a82ab8abf9fc1bc187389b6e4904e161541008e5b3ba0981870e01060d1272a6d59bfcfb294c942403f000000000000000000000000000000001870649a50e0978185551f213eefd9305d33e92b3f8c39752b6ebe18ae86ad97f92acef05971dceee3b3729becea18168b1ee2765e762f1b8c2451270cd5a755758fd733d7922a537aa9f1fd7d0c95960000000000000000000000000000000013713effa20d5039ced751ebafe1516f062f11ee05ffad37281cfee9d7a49ab14c065709832f6674bfbf2c9f379bc9c9000000000000000000000000000000000295f7ef148430209b48c292b024474f05036edfdee082c56aea05a62f1fba3ee7a540955423f78614c8385da8ef60040000000000000000000000000000000007408c97321b6d7c27e5e442a9e35b054e743c34d845874aeb1ccf4e903ca7803ed7fb1288327865f9e0ff0a388e92b400000000000000000000000000000000081808d03722a2d48846a693059c2662dee614f181dc406825544d30a6adc0f9d84a712eff80bddd4a27a036e4bf7359d5009fd559714d5692de5500ec8cae9c04ae1ab1c7c6e08c8738ef22da19ceca000000000000000000000000000000000880b646a674723c15b240ff56d2031e5db724251b1402a68df8b26261ffc9fb60a81abf165c6832137dc7a7293142d200000000000000000000000000000000172354b62bfb8d388b5a984411414738302725a508e8abeacdcb46454371d5e9cf762028fb65921d5c3dd8c67d42a981000000000000000000000000000000000a1af459bc3122dcef78359e468f4094d609ae3da09ca5aa6efb71a7494dafa2373a3906bac1f324d98b3eaa982a27d500000000000000000000000000000000092ac3b47253c7f090df076914cdc08a715faf153e8e365392b4859fca1db14d3f7fb998c97de9ad99b7d0b357252f086330c755ef708d8eb129475785f24be9e7836385ac918c60ad36e80e2f3281b80000000000000000000000000000000003b23eff722c078a781771d8b75d519e7a062ca3e4252ecca877845920158fb20d79a9ce449d9087426b113da0091826000000000000000000000000000000000c9026e8d3fee6282492393db504a2c41db19d8fbb83260624b05ba4107d6cb2c90d645a3c16862b27cc3fcce9bf89840000000000000000000000000000000018b8648d0a42285d474f809519696df9e1ad5c35d8e848ad74fbee37425aee8844a8be8cb4d3331670ee294ddb9a290200000000000000000000000000000000068cad37ee8578f4b502ac2ef4371a10e5432e57fe20d0cb074dc427831872113d3514a0b199d813b796b8357fa2a3dbc2431888d05cae840dde4c26911db1893659fdc345d5433556d9bf75e51fe3740000000000000000000000000000000013200f0aea4c60937be47213b6149b0ae76767f3559e0519f774af4a5d9431e2dd7ea74b42cc3ceb28ccf0d2f01116f30000000000000000000000000000000001c5bff08fd16ecb68f21289a3e7b9a2ec5da1357d604710a18e78ab780f8ef0343d5d9ee7f7988a009329b17e498beb00000000000000000000000000000000125453772eb9d1335ce4dbcc8f2ab8426fe89a0e49fec51d4e96718a38570aa82dbef452368141be2df260fb131c50b2000000000000000000000000000000000432cdd445519775b9914a986a0941cc829b4a15cd361df9ae7129547b24f7a6a15cd8fe9393fa1551db2d761a208b8ec9a72369cda74e5c86c6559cbc4f4db1b3ab24c5150c7decea862ede3c02c505000000000000000000000000000000000396cb6d7b44f92b716ed02985d351b4e8cd1bbb95f239e4f29d7379428470be395e2faeb8e3a910007aaa490d3c336d0000000000000000000000000000000000ad0c0623fdf50c2b504777554dbab3cde1b9705e976561873d7c22b81f49c7654a7c76e558fad1518ed73a0d3c3570000000000000000000000000000000001241d5bed68e02a2ddeb3ccbe109a161abe81edd7affb72182c5163851211c4763e6aecf766053b61ce575de893985f800000000000000000000000000000000183696d2a48feef6088f4e9f75a5055e8c54b3813658b593958490ddd4245ac495a8ff966861b20f26047f07fa8609a0c2f50989b04fc29c4c4a0090fb11e860c15f89a66f3bb8281e4678ba63ff3f9a000000000000000000000000000000000fe0ce41aa9e7cb2bcb4e01721b7b1d99fca4e9b7c4df09bec00bd346fc57c25118ba70d5333b7f3eef2659c64520a470000000000000000000000000000000005c932e09c62b7ddaf3f5c420c60740befa7cdff5bb812e0f089c45098d71b57004b7a207f0cdd34daaa3282cf6e9f7e000000000000000000000000000000001874200ead9776c1ecd6a54a57e5d0f9577910a4b3afb9b051622f658fe3ef6cc5070af60e7ef910562720e9716158d6000000000000000000000000000000000c2c657e58e400a67e59deee8c28234ff4688e781a2f6f2f0d0b186a5e4012695a522dfa0770cfd543f55939a05e20b09fc9abf1c76ff11ab538f46ce768ba597eb5f2f63073ec67e8de10aa1d666720000000000000000000000000000000000f0b561e5860321249b9ff434c604d26c3275824fc4ab9c1ce5c5858605ddaafae83ae27e523bf6006932f6c7f33d0a7000000000000000000000000000000000b47aab85bbd909599aa85c5eda363b67790ac6729fd8b1f4f53f66dd796cf2fa3496407b1bfaea4dc8eae53519054e70000000000000000000000000000000000cab1ebd23bc05c53bc9e8481c469eac3ee1b140af545bebed10a8fe50698d2ed883219881929207c0addf2f687198d0000000000000000000000000000000007742de55b799950e6f786f4eef45d0fb67e0475272ad68a183135b70047abab6c2ed51ede16c39be7b986df334e9e75d4167723682bc0e7476797b3be5e14b8de3e4e23b4ca33c50a2096cda8766dd7000000000000000000000000000000000923861332988bc843a65ec5dd4637f9dca8a15e71b82c780fe60d768213d118d8948ab554e30bb9253e900a9b7d87f200000000000000000000000000000000132b1faef49e7966a05783ba526e71134bfb577b13116548352da37e91e617d7c72ed2645e672ebbc517e079247dfb0e00000000000000000000000000000000000a46a8893a194ebfe077afd05fb25d4680f1e4991a3ec29475fa5651d086d20b38136155a65a4c70af31de5a78af59000000000000000000000000000000001344eb957594028b4228cbdb8efb03cc7cf49ec43b2ca5481eae1df6f2df3d5be9a7c4e4e78f8c39be546e29a83c92f49644c3727f78dd12811092190d5d10adcd5b9fc581dd783c97d4e7b5130f309a0000000000000000000000000000000012d7111303563a6358e5ce9155d7a153b5781062c2f6b919efc67ddfb4c61ef03be8828ca6339397b84763a5f8a7e8330000000000000000000000000000000010a2a0ea9973728d3fb1b5906ee84b2635c687c11398ebf605cad30216df3b7b4e3ee1653d4b323a690e6ba614ebec30000000000000000000000000000000000b93d5de37b892d4de9407a820c73ecfd6cd9fa565db82e7e8c14c8406823f705ff0adf6bd6add5ddc5f72c91e52e840000000000000000000000000000000000dcb320ceba5436df8f099c5a77f34376c96d830f5e8ab80667d156d89f6bf8998c148ef9a53847ed395871ab86f6d280df9846c84354ab7f947caca7800e12e38d8e6651527e6831f4d8b1bd66c4f3d",
+ "Expected": "000000000000000000000000000000000ff3e299e6b9fc488d6db991cf9d226d330846e87c4a5cd3e5d4ac955bc2c3c2d1ee5ff230098b48f594d256495f489800000000000000000000000000000000097fdb8fc95d64c7070d8c71e0fd2a933d1e1ad3fefa230f079bc5743828317cd1b0c6d4253ba9c3c6ec6b12d53afa700000000000000000000000000000000002448bbb179d82eaa453cd5452752b9a083b52694cc65c5d9b47f72eff118d7aa06b0fba18eafe93d2937d7399c001af0000000000000000000000000000000009dec4c0aff2a46b07855c87e08832811633709ddfbbc30dbb7e78b3de43bd95e383baa6ff4c58188f0c7643e0ea5a40",
+ "Name": "matter_g2_multiexp_98",
+ "Gas": 293920,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008afabec8a9985cbbc6246825785654c1d2eb7da5a01f76c4af4d0096b9baed3c33dbe492d14a6f9e762f06eb3d198f800000000000000000000000000000000027c592315dee4bcc892acc6f41a6eff5219c308253f7cd715d0e4a32c03c6d0d0e8568e146e9e799ac3025486c77fc30000000000000000000000000000000015b4ee27a3aa518a1ec1b447bb8f9128301c85b7176296d68dad3339b1dee78715b2f031a7fb6ba376145c97ceafeef60000000000000000000000000000000004b7e30ec7cc024ced863ce511cef3cabe954a4e5843dd636d776645a44225a36ed7e153ab5bf5d18f23c6444751875c8a71abe11a893fce872f6b8a020b6d84241df03eb934b50cbf3571df4800a83300000000000000000000000000000000119949d36d8d8e2bc1c26ded5f5fb01225a980a28b934ed3862480dc9297a3758e0f08ccaab3a09b5e5c0e4215e3246c0000000000000000000000000000000004a82dc22316ee6af39d937b662d1f1f2dc855c2ca8f33ec3274d833e87d594633fc7fab247911e0f46564397910d6ce00000000000000000000000000000000196900a09d8504ed960d41f4a8a2cde2e5dac61b008d3f6eb47e86d7b2ce6fcdc0f85157e3ab1571094d9fdaa75d0d500000000000000000000000000000000010c52ef9407eb4ec57844aebbcc3ea5000b1940d035dcc2a873327affaaabdd79e3560cbd29c63ce04f6279056d6eed1bbf28e5bca314391550d3a0fce50b1220965860e72c8c3865a2d4c599d31d3f1000000000000000000000000000000000e43655ae05dc6cfa93113dc26cea895d1c5bc73f20454c7b441dbc5ac80035b290514b13b31b41931ea5336d8d9a6a7000000000000000000000000000000001199a873958c63147e6b82625dfea15ce90dd41ceb4e315f67221eb874ef32c6a2953412e7e981659c72239a7a72bfe6000000000000000000000000000000001845af5936b4d7487ffe59137ba2f86daea3770cf37fd560969ee48243389941a1072205e049ddaa06c0ac56b7edc8930000000000000000000000000000000003cc831177f24614f93a118b896434105f05a277051a852fb9973a775fc54f779c2a1f3d64c457e5231dc22d6aef606b58b208a6845aeb2bf31999042c59b7b130a7ce5297e88023953b1aef63616fe400000000000000000000000000000000005e63584bc85ba58615985f6a466afe05268e545e0062cd7214e0b6fc8b87537c745b754cd9a1144948bc88b3c43acd000000000000000000000000000000000635b6a49090ccede3ed2ef203f0ed164783e3df4d9a7d93319515cb9230bd841b61a097f39e30175793b3e934d8e426000000000000000000000000000000001861e65f47a9da1584c45bc79a66045d86bc1709c2d1cf6cd2930a9fcc8c4efaa6536b5015be8d54789e8f574f93f9f70000000000000000000000000000000009290ce63d55eb436794acf11be9d896f03e7608a1bc8528f61ec9473f054bc9fbbda1072440e58e2f6ba080a01180173b53b6cf9e0ce1661c4960283be790abf956c2d6433529b8f3a32b92b227aebe0000000000000000000000000000000018feed9500bff884d2bb58554da2180c68267b6d3a45c2c7cee4c3f8524252d3faaa5eff971bf40123587e669fe66bbb000000000000000000000000000000001441bd3b58b4a4a87c2459f873c0692f5977b775af984bab46dd76cb9f775d2faebcb77b2854c9f1faa33f6c5de61c6a00000000000000000000000000000000123a890c3362c77e5b5cf9846d9c9e43fb3242d5a831e640ad080993fa0547854c8d11cc22f7f7b426528bf1154d2300000000000000000000000000000000000ff4a59ea98d13cfd353ae61e18d3c7018688f755561e6a1da5f09acc4277e8d49645087115acc64f992ea778a11f39bb049228435ade4c4c565e65f39f13a84c747c312afcdaff352560b9fb3cfebcc0000000000000000000000000000000006b019d005141e82393a2ca04469d1f6fd7b9456001ffef4c34eff6b2e91df58e99fd07944f52b108bd41ab6c4d6bbf200000000000000000000000000000000109ae87042029856befff0c916db5437e1e058a96f2970d8816b3becc93a1a50d6d336d5451303715f3e272147a36caa0000000000000000000000000000000000fc381b8dc9dc02d34db13e34732a10d0dfcf676c224a05a3bffd888b0af7c415b38af0b6afe6b464ffca42947c6ee5000000000000000000000000000000000087040d09c39ccd06c9ecc360fa02147a32e8036ad6e4b6bdf5b3883722a4e5a887dd022d53706d2585fe558696be6656197f5ad17062d2ecbdc8887bcdd32e5ed4c48cefd9e14d622a0b800d970330000000000000000000000000000000000e35c27b29df0fa9298bb9ab6a38b3450782223e2115d79152f9baa924d762d583b3ebe88e42f33028814ec78e5b319d00000000000000000000000000000000190c65667627a16f0af0ac7f23af0803bca810f3986b906b7b4f126d98473d52badf45e90e2e45bb390242fa8c40135100000000000000000000000000000000103f0283a5673c16bcc0f74f259c2eb077061947da04e467dfebf62aa005491e32b85cb73418b624a30dbaa01672921e000000000000000000000000000000000465466955c908607191faf15f0768dce42488c488eb4a065977f21ac7484766bc0abf23961ea2ba46dcc04956abf6c7721d9d7fe10104cafcad71307e785321ab87b2b69593535caecbf0e166cfda5b00000000000000000000000000000000082346e352e845a54cd4267f93b85b2c8623d4650e00c1c56082b73ee31f63588d2c117d3cdecc0378fbbf8956b082040000000000000000000000000000000001a7f43c2bb19cb32345c43c950536f8e85815b86364f278f6ec8169eca80917c2b8fc08d59b20cf55f25dc468e7bd7f00000000000000000000000000000000085a5cb020df10f9b4c7afc01b1d11700579dec1e85e766507def2e6cf5b714174f7be9cce3b18533a5ebfeec2b4e481000000000000000000000000000000001836d7506d1cc984fb777b8ee935d6f5b110644f59e96ff44d8329336d59a3e1d2b53a05d35e97f634baa4fdc11a6cd8461531ecb61365908019c1e8074a4c322df2b356eea3f3eea9aa1e0e1fc5525e000000000000000000000000000000000c1c59828ec6257a02679cff0bee0d665d449d2a158bc6d877e84cc0fe2161c297dde09b778d5e1249c515833e483004000000000000000000000000000000000f5e82589bfb7781e4110f1486752b00cbdf96cdf4191d75053c6d6d646e1c989add011361031a11559e156d64139fbf0000000000000000000000000000000015053afa7fb2b4e4b70f3c8a570fef8288fdc22dd951b6ba8a40b6087b9ab04ede21f0ddfa84d6d18914041bcf244c110000000000000000000000000000000003f399800cba51ab35624d866831ab6506392cb3acf549787153ffaf08cc451acea46c7a612821dd96c45f8b75133d88569c1c1ae2d18bbe36ed50db1bf30957802b09a982fbed49d4968815552e010d000000000000000000000000000000000e26242c8f73116079369ef4265f624abd4377e4e3485c28197663de9de9f5618c3b6ee602ff6bebd1c242aef7295b2200000000000000000000000000000000066ceb3ea6067220bd28fa1164237782859d27c1d3087a42b4d09bcc343611e4ed2be014a27f5b394c67643dc00f57cf00000000000000000000000000000000157f9d30de52110ea7a2a35ddfe67d9fad7223c5e3307e797dd0df3621520a421958a2835205e3c4777923f47d47e5310000000000000000000000000000000016ebb41beb85b9489a6d5482f8a3330a5c5c5e5718e8efb8b67362f9d8e9c313e9e563275ba38c207c5bf3d89c406ea62061d33b2f7e786effbd2e93101a56ba1bb62c1a773a08b72ca82f5183bea35b0000000000000000000000000000000005d1c9109b5b7409f94ae3f7dd9e8ae4908a9b378fea4ea284cbd33d1e59b605577b63892aaa8ec14d415f34e22fec520000000000000000000000000000000005afed05e62599f20f7eca019f41d770c630cf6359cb5601464be821691fba5205c16e7b580e6881047214f938e5104b00000000000000000000000000000000105637a2aa4725d8e080dec3b731a111ea4c94b79f898dfd51f645501ef0c8d68ea8e80fde28ff96e927e44306ebbb1d00000000000000000000000000000000080cfeea754474ceb37973234d5dc3269f8ca99bd862d4d2d1a602321fc709945a3209e5ff2cc962cfa6d03017c9a1354129b150752d2d5551a622231ab067931678454aaeb23f76168219406f0d50ee00000000000000000000000000000000137762ea5c80033aaf17570451b15a062feedde810f11ebdbe9a79a3275dc12613e0505835c122bd5f9afea7dba84203000000000000000000000000000000000d89c04e45e60769a63fcd73df2a138c457bb549195f2c4eebb3be1ea46149f286756795be8328b5b886f497d8167b34000000000000000000000000000000000be43d515083c8c10f467618685a43d4d5f6457204bacd278445943a9f44f7189b561a0e1bc59d2757fcfab2e3f93a4a0000000000000000000000000000000011a52583227c6dcdc1784d3633fd584612a9f3bbc1922477396dcd5af84413e5e9382a34a71b3a72491ea09fab2fc6bf366c32d5d3c132f32a6ac3cfe1dabb649c59ae224338f747ad98b193e8346729000000000000000000000000000000000073acefe33525dd2d5204cce72371ed82c7e4b58d1b4e7f4b4994f9c58b02d9d6206fefb3552446b6b355e860ace43c0000000000000000000000000000000007344eaeaae71e17930e769e02bcb4f44ddf3d040ffa0b081f25901cc125a37a58a6a5d13e7b0ba493802ccdaa054e29000000000000000000000000000000000a65fec6ad29ec3eee9ddc7ded2297f49d03ff18a255f1e6d29d2a67c20713f319d79d513af0c58ae3cddfd1f6240ff50000000000000000000000000000000019d5f00d9e2b271f4e9ac779a096386f08ae124f77fb8183405d48ea7f16e685805442dc67a392aefc643ea95b4f1fcfd997516cac28a3968ac6946b5bffaace0856a52e38fdcca11ddfa16cf5a568f50000000000000000000000000000000018230bf1a873aa04855af1426da30f1b3ef4b64eec613b9f660222e3827b325c318baea031b463c7e9f775165d22ec8f00000000000000000000000000000000017faafa1294fac53e1de8cae9601acc62d76a5f01a39ce49d65f3f5d2cd5cca33eb90bb4116b3ea36f912ae2b81b6cf000000000000000000000000000000000fc3ef5ea59849a87fcd45500989f1744cb5570ee88e34a952cec32cea2eb5900b64d8d0d04ef5c51e8fdcccd46412490000000000000000000000000000000001c53aa8aaae8422fa4fddc86cacdefa89c37592c8e67e472a23627514623a90901a619af79e93561a0dc65215837274e881ec65fdc2f58e46d3ee45a06d0c5ac844ee5b62872c7ba21f6b48621a3371000000000000000000000000000000000e3db6885c2db9244548e11b8c49b73f85e4104b413f54308497262fdff1957495859830114528a22c45d39a554ba82700000000000000000000000000000000181b1bfe2d9a1c563e73356d73f4ed3e7061a79c610bc97c911ab1a0213d123c9f83ed6706e862087a796ce14c5cf53d0000000000000000000000000000000013f5fdceddce771588869b945bd6025e5ce485fe78a362356720b474b83998f27e535cfd8d33ee51cfc68e5d514f915c0000000000000000000000000000000007e8fd7ba457a3cefd50c641847425cf2262deb1d6945a0bd740eadf38dcaa616edc48c3912508d663349f089b8b56fadcd9b95e49473277a665ca0f9a8309df9ed6ee4f25d803aa967fb8f688273e650000000000000000000000000000000004b20b0408da7b704694b47607928a655077015f2174fe01bac9a0b3a61dae087b0b593f58d2947d8d84f75bbfb327c900000000000000000000000000000000106d623b2007c5d7128e03e540325ba763e992a651e2e5c78936f82ee2ff72d89a1a914345486cd0a04440c75beb190b000000000000000000000000000000001847348e5ef429cfdf1ba4d265d8c5ebcbec3d5dd4611ba36e2754fbd3d327273bf2eb7b7ba4b3888d059dc87f034739000000000000000000000000000000000bcb0a9dfe5189bc965e9721407b4cb3ed4171510aa4d4e5d5f0823a1c2827643e1278f9c0ee960c54ef8f6c208eee7b334582482a9038ab906880e43a4a9d39e73b6c63604eba0c8f6399eb5c288638",
+ "Expected": "000000000000000000000000000000001205b70b29ee04212589f8a70a71e004f517d3354e714c1b4fe42cf93faf1a8ed40dbc1b5089ddb53bb052c9cb74c0e8000000000000000000000000000000000f619082734dd9de653b61cf2fb927199f228637db70797bd2a21fdd48b6ecd4c4f712097037534024880a436fdd63680000000000000000000000000000000000592eca560be6ae256abe1796f7ec394a8085c127437f6590c8d41501a482c61456392cb320b9e801044dcba7802df9000000000000000000000000000000000a6d20b8009708ca01a274aed6dece732c5eed5aae5e4c2f3793b5fa1f8cb8c95037ce387bda2e7476e9c493507c7fbc",
+ "Name": "matter_g2_multiexp_99",
+ "Gas": 293920,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsMapG1.json b/x/evm/core/vm/testdata/precompiles/blsMapG1.json
new file mode 100644
index 00000000..07903a31
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsMapG1.json
@@ -0,0 +1,702 @@
+[
+ {
+ "Input": "0000000000000000000000000000000014406e5bfb9209256a3820879a29ac2f62d6aca82324bf3ae2aa7d3c54792043bd8c791fccdb080c1a52dc68b8b69350",
+ "Expected": "000000000000000000000000000000000d7721bcdb7ce1047557776eb2659a444166dc6dd55c7ca6e240e21ae9aa18f529f04ac31d861b54faf3307692545db700000000000000000000000000000000108286acbdf4384f67659a8abe89e712a504cb3ce1cba07a716869025d60d499a00d1da8cdc92958918c222ea93d87f0",
+ "Name": "matter_fp_to_g1_0",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e885bb33996e12f07da69073e2c0cc880bc8eff26d2a724299eb12d54f4bcf26f4748bb020e80a7e3794a7b0e47a641",
+ "Expected": "00000000000000000000000000000000191ba6e4c4dafa22c03d41b050fe8782629337641be21e0397dc2553eb8588318a21d30647182782dee7f62a22fd020c000000000000000000000000000000000a721510a67277eabed3f153bd91df0074e1cbd37ef65b85226b1ce4fb5346d943cf21c388f0c5edbc753888254c760a",
+ "Name": "matter_fp_to_g1_1",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ba1b6d79150bdc368a14157ebfe8b5f691cf657a6bbe30e79b6654691136577d2ef1b36bfb232e3336e7e4c9352a8ed",
+ "Expected": "000000000000000000000000000000001658c31c0db44b5f029dba56786776358f184341458577b94d3a53c877af84ffbb1a13cc47d228a76abb4b67912991850000000000000000000000000000000018cf1f27eab0a1a66f28a227bd624b7d1286af8f85562c3f03950879dd3b8b4b72e74b034223c6fd93de7cd1ade367cb",
+ "Name": "matter_fp_to_g1_2",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f12847f7787f439575031bcdb1f03cfb79f942f3a9709306e4bd5afc73d3f78fd1c1fef913f503c8cbab58453fb7df2",
+ "Expected": "000000000000000000000000000000001672a8831d3e8bf9441972969e56b338594c5c0ede7bdba5b4113ac31ccb848dc2a2c4e23c0b9ec88bfe7165f472b427000000000000000000000000000000000a86e65037cccb5281389512673068d6f91606923629905e895f630059cf87fb37e716494db288958316c6a50de65ca1",
+ "Name": "matter_fp_to_g1_3",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001632336631a3c666159b6e5e1fb62ffa21488e571cffb7bc3d75d55a837f242e789a75f0f583ce2b3a969c64c2b46de2",
+ "Expected": "0000000000000000000000000000000019adfbc918cb74abc6fa0664dfe60697b233f0663665d2cc133478db4d6c9a41309ff09f9af9240037a7332bc42ffe3a000000000000000000000000000000000d31ffd63837cdf1cf2a7b3fe23a9d86c08f3a7c44ac4fa52d21b8c235f0d45f85c036d80bab332034635845deb31467",
+ "Name": "matter_fp_to_g1_4",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000184f1db9ac0fdd6b5ac0307e203d0b4237a50554eb7af37bb1894d9769609c96c8437e9d6d3679ebd5f979eb04035799",
+ "Expected": "00000000000000000000000000000000192a005eb944f391251402ac3d31c30f0b2d77987ed9928d244f492f96c1a0a06a7cd0be4bb3dfe3c484ab8ac5279a09000000000000000000000000000000000b99b9e7f0b51a2e0d12272fd0d9ae65294dfd34d45f30fe446a25b225316ef467b02acc3b6a578e054e612434096d7c",
+ "Name": "matter_fp_to_g1_5",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000732f171d8f6e283dd40a0324dae42ef0209c4caa0bd8ce2b12b206b6a9704f2c6015c918c79f0625fa791051b05c55c",
+ "Expected": "0000000000000000000000000000000019dbf865a67157efe65fa7171279049864bf6c280d3c3462e93425bbf25f9cbad6c27885d7927b5cdca642df48ceccd2000000000000000000000000000000001606be1ef7aaf56349e5179b01b89e172e463bb3446792d5210452905fcde42522f9719b9e7ddeb8cc3f227eacd55947",
+ "Name": "matter_fp_to_g1_6",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001139e8d932fc0ab10d6d4f6874c757c545b15be27cdb88056ed7c690aa6d924226d83e66b3e2484b2fc3dcd14418ee60",
+ "Expected": "0000000000000000000000000000000017d476fdf0be6b09206dc83cce64c603a6b911f051e9191a2473a1bc6b1dd2c6e9bc4d262edc936f62911460f0b648a70000000000000000000000000000000016f824bb325ff7f485a8e9d116f4a56ea71ecd2c11b2a4d119c208cf323bc62bf1e9fc609230c571e7830a956e140e47",
+ "Name": "matter_fp_to_g1_7",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019a9630cce5181fd0ad80677ed5ad8cd8bce3f284cd529175902b78ad4915f0df56f0d8b37c87c9ddb23d0342005f157",
+ "Expected": "00000000000000000000000000000000145726f8479d7390e7a21cd31dfee0e6203115e72d04c5a735feb2cb688ff74944bff2b1af1b6368b4d095143662a1300000000000000000000000000000000002fd68d51753faa242bee10148c0e473f4110fc7b67848dfbab7d7105090648534854ba75890e099cb738d1dce604ea4",
+ "Name": "matter_fp_to_g1_8",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002cdd00b7662569c9f74553a7d0585312a776c8638e54ad016f8d9d25df98651789470b12ce2626fb3ad1373744387ac",
+ "Expected": "000000000000000000000000000000000671b0f33b0f1ea3386e6876452989416c7171e283c4b0c375e840ea05e7fda22aa03899b50e59e9ca5a87039b2e732800000000000000000000000000000000031bf8caad5ce6a0d94f14693da0d551dd4bfd2c2163c8e8d5a448956153f63ce2ab72f03b97b560d67933887e83be1b",
+ "Name": "matter_fp_to_g1_9",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e63c4d12a38837354bbcdf4f844e5dfe727ebe292016748007d162e74c1f849787767f7e77fc57a42783fe0b06c24c8",
+ "Expected": "0000000000000000000000000000000007d67999ac2fe6ab93591646905f23aead0d37ca43573ab02dc16c2b199086f788a8a1de6b10aef4f4d772b2e12e72ad0000000000000000000000000000000003700b150ebf60cacbb2b7bcf969b70edb57b34b5c772cdf68d42dc9f1513631799b9b9041c5e94595ea848e195aa730",
+ "Name": "matter_fp_to_g1_10",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008d879e4891a891f2e7d27eb95aef70d5b785b796620ec43dfbb6ae550b4effb9f24210dc20f401d54420445e21cfdd3",
+ "Expected": "0000000000000000000000000000000006cf4af50766ec08696c9bc0d9617c1f0fcb0ea1bcb576179cd4537d9d31b373bf8e3c5f5fde2c21e44917cf1f51ff0a00000000000000000000000000000000050a9f7d8490ba2b6e49762cf2bfce557e39edb51ef03128b64267fd3c6b996e95d73b26cf1965d427e3445b1ee4d133",
+ "Name": "matter_fp_to_g1_11",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000028d6de947a3958af5b53578b0ceacc7ef89d36526d8f3b6fbe787af69fed2c85cad3001643b81c575a741c4566e617e",
+ "Expected": "0000000000000000000000000000000009fbbc6ba7ec2315dc18aadda7b2e53180b904c5f1cbdca1b2f42ed9c6675da7beb4007ab6639520c4736bbf2ee3f04500000000000000000000000000000000113f0bc737b2f3a141121ef236cbaff2f34502aa13e121b857baf327f7be66be97867fc6f752555835fdd01610e30c77",
+ "Name": "matter_fp_to_g1_12",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000182b56202f0494bd8baf5c03969288a1288b8ed8e6c7f49ec9f7493ee3369eeb42fa8f5fb7b243fb2bcee6be244f02be",
+ "Expected": "00000000000000000000000000000000047dd479fe99840150e73e4a8fa6be74a9b7d743e21cf33e9d7a9fd8700feeccd5111fb037eb3b15b79d5737ec4c7f0c00000000000000000000000000000000000ba7f57ce062eb9c67d84eee64d64d250a18454bd63dc5a136f5341214079eb9269eea7c4e0d836dd8be63a8a45c04",
+ "Name": "matter_fp_to_g1_13",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016adb5935f32bafcccb81cf4d177dd8826013d85e11a4aad66e3aa596e1183aeb9d68eb8cf5b716a8a9445ea81b40d7a",
+ "Expected": "000000000000000000000000000000000e8cf94e68b03d1f6a3d4eac7898f143324d08f7544aa9f952947e9008d2c14e46236667173266d82f5e41887c6f614200000000000000000000000000000000089a1ada37f30b1f6e3a6613705992e9708d0437611f1de72a9f696ea5efea6793f285bd5badbdc20af64df8ba95c79e",
+ "Name": "matter_fp_to_g1_14",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018bee24b0c97af8aec210f15bbb6acbb76168dabe16e669d5558d8d32f00fdf5146471922fa98a28f238974d327996a3",
+ "Expected": "0000000000000000000000000000000011e4919deb9eefd13dd0ba5184003ce34ff6c2bd8920dc49b936917a7b6aaf1c7541780b5d0e380e6c808f093a877eaa000000000000000000000000000000000152dbb758aa5f60b8d0703eb30680857abee717114b8cc5f6466e70856f19c76a88ec6c536e7a679c177986bf636e6a",
+ "Name": "matter_fp_to_g1_15",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000114285411713eafd395ee43bf1728f52d17ac512b9d0cddd38c904a9a3a1b30283a3918cd2cc3da6a7d6b4ff923cbb6e",
+ "Expected": "000000000000000000000000000000000750f69c43c56df2c8524b4ead9f6cb3ec16d3a6ec913254e585b0d8518e53c18e0e93dd4594adb926c51820de6001c10000000000000000000000000000000011f5c985ed12f72b6ec7e222dc8d93da520ac65476c716e231e7142cd3aca49b25dbd716a8f587006e4a2af31c37956e",
+ "Name": "matter_fp_to_g1_16",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018a067f91f94b2904c5bb6900f427ec4e93374b5079c84707feabeabde20b5e49801f1f3c7504dd27da94d5e754df4ad",
+ "Expected": "0000000000000000000000000000000012652effba341826ee7bc3108404f5fcac84776c6f5fef5d440454b59f04afc2cc87f243265248445c7c2bfc14493ece000000000000000000000000000000000c0fd215b7c012da4532c882d7d7f83ebf133d58acaf8b5123c1211aae5929c6726410631c7f9347456448df643c9ed8",
+ "Name": "matter_fp_to_g1_17",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000dafa9fa843879038fd1566c319c24119989090c5fd34f6514e57f633d3709f0aa9954dfb289843a6990588e337b63e6",
+ "Expected": "000000000000000000000000000000000c444b07e9ee5dc366c63ba30f1b17087bc4c548963caafacf223f4bf5b5bad1f9b51433bd1942978f3f5e5696d5056f000000000000000000000000000000000453941626954845d89821df34efc6f81660684b08f03fc42da54119d10f1f95357ba75a0962961f1487df45b0c534ac",
+ "Name": "matter_fp_to_g1_18",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001742a98dd7d3671c2c64aa71023a0040e936fd726c062d520626113bed471e53ff3e85737e5abf9ee8821bae53135f20",
+ "Expected": "0000000000000000000000000000000013d5fcd7e4a0b1d7d8c7b242b46968519521ff8bc4b990a56ece26053d4bf884afd24a00670911f943522e06fe4f87d1000000000000000000000000000000000aab46534de37b5c6d206959a1023ad4f20ed5966bc3fd1750c1758ed806f077444ac70e9943b4e8debaecf208817a5d",
+ "Name": "matter_fp_to_g1_19",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019cda532e5d94f3b193b3f286a038637a736c2b87b804efd4779359db5bd95320e06d6d28da3c229ae48ffc02303fab1",
+ "Expected": "000000000000000000000000000000001440f44e3964de59be03a6c69affbb3b44ffcf4ec4976361ac49c31a23f9f154f91750533ff2425d5e8fcde0974a91d50000000000000000000000000000000002031eb89620736dea022880e5188145f080537b1aec183db70bf307029be21a167fb6456bd1a47a75626280f78442a2",
+ "Name": "matter_fp_to_g1_20",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018df89e4a545bfb825bcce2f4c25f2416a72e32633b3dead5205c8b7d69c78f119d0e940e5bde9ae1cf91574e5d6c175",
+ "Expected": "000000000000000000000000000000000a2d7297376216582c3938c2aab0a26494da7d9df45e1af7b4f826f064467a939ad99134be4c9b804b5bf273e082c4c2000000000000000000000000000000000b0a4da7cc585be1be6c091006fe831edb6f6eadbe3ef611041efa3d14f442c9768feb2958efa161e0adf5c321d7d522",
+ "Name": "matter_fp_to_g1_21",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008ad60829ff001404da40923806e496640a90c5c258a41ef5912f8a1a20eab84ce43b2b5aa4aa7dc4d8b281591d23502",
+ "Expected": "000000000000000000000000000000001314d7faac7b4d5003baa10cc432108d6bb7f80bb13991f6ac45fd7a772f31cd43345ea100b05f2ad73e3bf583e7e7b2000000000000000000000000000000000eefa97eaf2143a991343a8823d8b362f77d8370421bd13a9a6cc4988544feb0cafd3a797a28d27f4f8d361cb7f49ed4",
+ "Name": "matter_fp_to_g1_22",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000f13dfef4b3b83aa7f9525eae9913e10502e77c03c55a7aa2de083dc5102c098b6f8e36cb5247b827e30fbcded9e2d3",
+ "Expected": "0000000000000000000000000000000003ee4f3d29cd9f29a2e559a86d8204a1d65598e7788d585b145022de2c19022b122c1f10423d3bec769545d656726f5e000000000000000000000000000000001803f26af468740849a2737a42e53098b48c0709415247023aedb111c96043e3b13de300213e5196cc3b678f8be0696f",
+ "Name": "matter_fp_to_g1_23",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010468e5421a72ec85b63f7f3070a949223105763868111424fd151c8365eb0307dbc9cbc92e5dfb296d06ddfb58d9900",
+ "Expected": "000000000000000000000000000000001800b9766f3e621ad7a8d1870ce16c8cd054c87d7fb100120a38c3368cf1879859645874b23297957fef6cd8f9112bf800000000000000000000000000000000091a8b69a1f4eb883a25af2a3a0d1e384ef7a9ba4e8ff8811ad356781c79f631ea20fcd0590e94b9c1841e6add2b848b",
+ "Name": "matter_fp_to_g1_24",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008149ce856d489050ea834452bc66f7f3478c2056969354dca8652f3d0a349e40fae0c4c57ff0f5e022aa93c61f8c844",
+ "Expected": "0000000000000000000000000000000005fe170feabac3805c3eaace41fdaab2c9ae7fe609ba609f4ebce2d24c0d704d847efd510acd8abe5aeff2eb24e781b80000000000000000000000000000000003262879ff5c9831ebdd0de9df478923fee72a8829378f40cfec310a41110ad22faa759276e3b9e015c86c94c3594e0a",
+ "Name": "matter_fp_to_g1_25",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006295de7bfec61f06a56fe09afbb74be968329e88ba2e87afffe9ea9bf646ff5b4a03d6088e87644958ced95eceeea08",
+ "Expected": "000000000000000000000000000000000e4110b2efc984c4d7affcbcf5cbbf919c55f948ac7412dc120d30774924d6020a2292f27b8e716c2b5045a561f2b14300000000000000000000000000000000194649f6906daa0394fbc1d45355e17d62f6c22a9e772bd7fa5149e29ab2ac6060d83dc5d70fad75bf3f2c7917b641e1",
+ "Name": "matter_fp_to_g1_26",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001443e61dbf14b6c6ed99e1917ecfbe5a4a23ab9bdd3bb089fbba76d795d715d9d2e3c7d8db0b7a9434ad691b68bad3b2",
+ "Expected": "0000000000000000000000000000000013af2a5f26d1f51da0d80fe7c62369ebbec235faf4565e62ba475e6f58418183efc8b9906196ffda72539506243e0482000000000000000000000000000000000774f3096c99bb826792cfd9243d8cbb1bab54fccc3a6347daea74ff1c8aebafdd971b7bfbea5b9a0bce243372caad6a",
+ "Name": "matter_fp_to_g1_27",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b14b12ecaa94f9656be54772be9b22a2495d4ff873b0bb971c27ab1d8b940c84cabcf921f6f75e93942c38cddeb8750",
+ "Expected": "00000000000000000000000000000000107c66e91d518789be416606058cfa8e9df478fa097241fc109d065005ae927d83563b72410e5b207d1556c2ee4dd67b00000000000000000000000000000000148c208e55e834c4e4fe20c02f517c21030f60c74b1a3bcf70bb2311cfb9b7548837b9187910bb7e8d1faa40ca8d6d92",
+ "Name": "matter_fp_to_g1_28",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019eca0daafbfdcd3b56be863dceb21e624b22c0d376fb92ba606456ce3825981713b88e40b7fd801e915f97d5c29ba75",
+ "Expected": "000000000000000000000000000000000fa72de55fc2229c0176120fac3e0a64c4498bcc7b67ca40b92d47a76a9db87ba498b72f06345c61d59a3d37c51153a300000000000000000000000000000000001f0e176d0987b8ceb7ca0e5ebb491bab0be17282cace8e03d52c986483026180082f86196fe512ac6bac58ec4cd024",
+ "Name": "matter_fp_to_g1_29",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000104a452343a4098e9bf07380a8e52050259da95f5fc88f31511a08090bda85f0a08d49cef95bd26c7181aa3eb0be1222",
+ "Expected": "000000000000000000000000000000001655eedb905670d10d2f979962e864d68e9491aea41d073a6119e5bc0ae74216383501a48343d7099b93601f8b67c00c000000000000000000000000000000000842846147959f0f81efc6e8f515a9c59456637740bc15b2d335e0de45890cdd814ca7057c5d3e49e48e5a250c5dad25",
+ "Name": "matter_fp_to_g1_30",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000012400aaec3d2f4a1a8cf3f28fd396133c3999c074a565c110354472ae29479b9b62ab67128521c2c6ec4869811ba760",
+ "Expected": "000000000000000000000000000000001098de70e8748daba7bbad52ce344619d3b5374821c1f932a18666ea0a591b24ece05004546cd519ba4d78c9747c57cb0000000000000000000000000000000005f537b6a394458ad51c2e677b2d52974a714bcf6a7474e748ad7f1b28738b6b874b6f49bdf19479bce4ff6c6a47de1a",
+ "Name": "matter_fp_to_g1_31",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000093e04bfcbd77bc6bafeb77f02d0f794a20b155435ee3af1d667c025e7645d9387abe0ef281386339f461352da93fbe2",
+ "Expected": "000000000000000000000000000000000a27f7fde0c79210f4b6cf59c97ac773c9766fdab289225c97f6cf42179385cf18f47f14b7e481df7c19418c79dfaaba000000000000000000000000000000000874f21294205152df3a4fab2ced482d325274886d8105b61668074dc8fc90240a715c62b2a2864901ca7a30f12e76a3",
+ "Name": "matter_fp_to_g1_32",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000481ffec570d4e155ec10e0cc58effe7a5651795d604cfda6cdbf011676772fdce2c25227e7d5a1a26748d15b1668091",
+ "Expected": "000000000000000000000000000000000a6fd7355965c9514dc7237efd262fb9dfd8025ca2c56165e22675e615095887760ecfed4a2080cd5a2b8041ff26578e0000000000000000000000000000000019b1e02c9258fe62160d92eba8640ffd79b3bffb8ca4d602ca6c059239047c5563049758911d0e6034a25ec5094b1f33",
+ "Name": "matter_fp_to_g1_33",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013a3c5dd40f7d7fbba7563331917fe19a093d5d25ae7993200c39460e0c46d839e3958b672b4ed195300f398137faa18",
+ "Expected": "00000000000000000000000000000000013e4cd06b8ba7b5efb70feaa03550bfa45c7c2c79033c92b819257b2ddce28d501cc836a5ec81bf210bed671bfa66f100000000000000000000000000000000165d806d235d41f21e961795ec3da4f1b0334ba6e71ce384445bfda9e5d89e448d00253ec9f8d49825a230b25ffb2848",
+ "Name": "matter_fp_to_g1_34",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000255bc4d313fbd61a270dce8c851f1fa09e6ac5dff9b9e8dfc8a236a1d44548cb079023ee9b8f0f5756b39e44489c3f1",
+ "Expected": "00000000000000000000000000000000067c19b7c3dcf8b43d6e83dbda7406f5f88b06cfa0d7d145201164a1f06cb5549545ab28fd1ea8c1d5a662cced00822a00000000000000000000000000000000013aab7ac4ebce4686ad8a05e4eb2f60ebdf03c4f4ca0111bb1cd3dd5fa7558f1cf0dec394d0b616cf557f3811bc2104",
+ "Name": "matter_fp_to_g1_35",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ab7b4dec955de92224b234c2d8bb2e3881806c2d36a9a21036e9412f0a8d3946027cbb65b5dd9c975e01b3f235b883f",
+ "Expected": "000000000000000000000000000000001673e66a7e558d533be5b855df7c3bdc58f1fb0a3b268b84b4fc25a3a8a211c4c9c8d884fc62f00eccbadbc96dadd7230000000000000000000000000000000016265b691fd43045567ab4fc7e7efa63c8430c8130761b128f0ba7bf381a7cb81bf05aea2526b50ff6e48a87c8ee9cf6",
+ "Name": "matter_fp_to_g1_36",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ffbb55002d9e926b3d8e7d963ece82c14afaca8b4d8415df8f964a39db606ac99f9e442ff69f7ddbbc4ae563b836192",
+ "Expected": "000000000000000000000000000000000b36ad42aeacfa47d77f045de527d5bd4fa5fcf25ca3caca99e3e7980e283278e013611d1bc7694bb0b1b86d8589730700000000000000000000000000000000136290ed913b8669f522e16103ff42733a57c1026f966facf4a2d385b0bd52668925d748760975ca5a132d00deddf675",
+ "Name": "matter_fp_to_g1_37",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000103469c08562f6f72152db58b48811b0098b68af8de00e652bd5a67246459664cc8c54e15705d702d51e3f1d8ff76a77",
+ "Expected": "00000000000000000000000000000000076fef7b61f4c687246991d6f735d6f89c953476ffc193bacc1f3cf9573ed47bfbf6dcfbb3da1ec1bb764a9cc9b1c26b0000000000000000000000000000000012b6bb88e8acd6cd0ef1929a79bf4d8b10ec3fd575fe460686921fe94aa3a472cbc7aea543ee6284c368f5ef2c33ebc0",
+ "Name": "matter_fp_to_g1_38",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000059b326dd567fb2f8a6ae87f41fb22b3edc25122138a5f6732edb48ed7fa1949eda6144297f54faf406d873a016a1510",
+ "Expected": "000000000000000000000000000000000bbc25f7788b0031f1487ef154e877c5ae277a80d56b3a24a39c3ee94eb7df81a47bbff233c1baaf700829919e5254690000000000000000000000000000000019fd9d1237b508d06d7b2ff807c15c3ab36e6eab7e5b9f145bb2c0f2ce8ec96ca3a24932076abfb74eca85744eee4044",
+ "Name": "matter_fp_to_g1_39",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bd594d2f5e1472f85bfd550df3eb948085781459eb3037fab34186ad9a0204a0767c8fba571af858a054dc231931b80",
+ "Expected": "0000000000000000000000000000000015eca2e3d36d619601b0f40b01add7a708bbe59d04d5dfbf12d6e473e252505cec0cf7ea1c420000d49221d5e1ba6b91000000000000000000000000000000000cc6045184317aaf2bb8a904755bf48df9e6754e3a864037ebe0218eb3cd1c0a54e50b95f9e6d318799a72fac8d4e262",
+ "Name": "matter_fp_to_g1_40",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000087b8398406c1e707fe87a16118e2448d6a5f4fd1d6c9d7174c4d8a4314fc7b2c21f04178533480976dd20e28b278ad5",
+ "Expected": "000000000000000000000000000000000ef0a6307d4a3e92570cad673ca5212780902de416e81d15638ba654951f442e852b53255d7bc4d4e71098924d69f5a600000000000000000000000000000000156abf6f096326c75710300578f0cd946536e16bbf80034c6dbfe454565a501c268135118745989e5274ca2431ca5155",
+ "Name": "matter_fp_to_g1_41",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000673dface7041c3d7503ce4a50af946d344ad48327b515740b45276403d91bf1ef9deba79c8ffa0126be990b62bf3072",
+ "Expected": "000000000000000000000000000000000dc94ea6018ffc5838cb7cb00df9625c0c09701bbf19edddb735a3659b385bdd09e9a7d6e869720b727ec59ff3956d9b0000000000000000000000000000000000a20ea6360179bb6608bcbe4879df186916ee71b3ff7a1dd0fd137a0e9dfb135bfda2c66d1cf8d358d69934012a1a1e",
+ "Name": "matter_fp_to_g1_42",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000adb42b7eb0f6759a04da7b933bbc2b6aedde47da8571d6fa32268c606dbafcbc810844017eb6377493a12d76ca56c03",
+ "Expected": "000000000000000000000000000000000b4e11f70679333c064d06180df6b54dd1df20ea216415ecb9b704bf4b206141fd841770ab77de4ab2400a076cf9dd04000000000000000000000000000000000ad8c02345e141396401221bb36a2ca21096e89aa76fca4121066da74f2f54b3e2c4049483d9855b7f3159ef448c120c",
+ "Name": "matter_fp_to_g1_43",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f554e52c4a6c5a94fd09c617f57e8f87af57e73ceaee8997fc62c8ddcb2f875ee805e6594a0fb72738abd3cd4748ddb",
+ "Expected": "00000000000000000000000000000000136cd8012cebf1639a396f331f73f0da6c114927559cc595f01bad1a18046ae8364858fa262ae04ae3f3b7d13db55a86000000000000000000000000000000000393a915629ccaa9ea06be749f3053dfd07061cfa24bc0aead12622c7d14c085e2994178bfec98b3f8867ac5b4b7a05e",
+ "Name": "matter_fp_to_g1_44",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001876dd03316ff007a2efb4c5f452d8418edacc2881b20e8340895f6fc768d14fd89bd9db3dcfb53fa98a1e96055fa83e",
+ "Expected": "0000000000000000000000000000000019008e485a0a9c2f73a79bfe31782a17952edebca308bbc9f90e2ae15525bd501268a1c38c669de0b4e4fcaf1194591b0000000000000000000000000000000009c35254702eb7e3213fcbab62946ba79b7375cc320ee1733d8bf5729d378d1a98fb27d870e27c13626c35cb00a6bcbc",
+ "Name": "matter_fp_to_g1_45",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e8b2369fc2c584d78d52037b109aecc87dea0eefc2da46948b5535ad19c9abdb31aee66739f4852a2d3c51f2e7f74e9",
+ "Expected": "000000000000000000000000000000000059a3315f8b6e75c45e32843b4ff2401c41e1f6716a5909894cfdc71a49253d2cb04ec416d204bf0bdda051ace606260000000000000000000000000000000019cee852aa9fe28e1da49dfbfa7901220616f464ba447480c2421fd6d3a5a818c778510a04cb6557d27f7ef9a78f2fb8",
+ "Name": "matter_fp_to_g1_46",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000168b2d3e4b67390cb8ba5e48a7a823db08edee7d8eff41b88cd653cec1fc0df7a55303d3c91e92a2dc8ebdb327b225fe",
+ "Expected": "0000000000000000000000000000000001d157c963811725ad533539f17acd16ac3aa22917ecb2198d83a3ba396955f2c9654c02fd42e3d4ee6156cd148e9c270000000000000000000000000000000008fd299ddabfe525075f548a31ffc990a3626aba0369bd0accd0e1968204c8e1085c6b287b370808609178ec8ace2d0a",
+ "Name": "matter_fp_to_g1_47",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016cf7b1a9ebafbd20c078948fc974bcca9b8069edc1ca5e8f364f8ca2a52e56e1a424ea6bcc4240f46dc7f262760bf48",
+ "Expected": "000000000000000000000000000000000ee6b51c5eb4dd9c27a61bc2f3480d799cc4fb88414630adb3961508c7067bb186682194af406f811296228c068e6415000000000000000000000000000000000b878c207bc4b61e827ee09a7825fb216a63ddbc4ef0522b8a944bcb673ca368996c31e6513504c5deb5325ef4df0459",
+ "Name": "matter_fp_to_g1_48",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011a6a67d4501a8d9b3ab985be59ffc41e79c453bb5548299abff3b83ba9ff951025a68fe6a8ad3eef3c02d39fca8f909",
+ "Expected": "000000000000000000000000000000000658d61bbb2273e8969269dc16e16be93ef82be0668c3a164097a1c0816bb4aa94e5f70ed8d96bd15d9acb602d70f8ee0000000000000000000000000000000008f696d49a5c6f3dc971699a5837f7b3a20e222d9559d899eade367ce684b60153dfb75a9a8b81d7359a93069e2d7d7d",
+ "Name": "matter_fp_to_g1_49",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010e53fe9fa94ca622cfa370129c1619b2426bd9d50f4b5eb8a3f681479128dbe92adde15477ad8a4463b08f1a02a62d5",
+ "Expected": "000000000000000000000000000000001313f4cc65865c367cb5c1c96cf30c7e993207e9ef4b2fce9db01181b1192520f01a0428668bb9d33eb857d9435939df0000000000000000000000000000000006b5e883fc24585de3b0a0b83cc1742050e578cb57e89b385e245da0dd2832852c3fa5f31ccf55e6744e9cae6c2f705f",
+ "Name": "matter_fp_to_g1_50",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014d10a90709789b25369f0376f39b16860aee1ddc3a4340542abff0077a4af8da946cc29fb6afd9930b872ea98749be5",
+ "Expected": "000000000000000000000000000000000f3fdb57966f9ffd0e20b9ad3bfb4fcade56468aa598cacfe388cd3b647d5966350586daa4493de23703a1debc82e48900000000000000000000000000000000044ff5ce3b9bed637709f9105bec0d86b4f0ea2dd86c9c3b1324637cd4c0fe5a4a965021c51279fc03592414e7968d23",
+ "Name": "matter_fp_to_g1_51",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000194612afb777e39d0308a290bf823fe706487c3473412d1410dcb2c0016a70706e70e3a009c0bd61e755b1e4c65bcad0",
+ "Expected": "000000000000000000000000000000001288807e8f49323b39c5d592b97f19cf76f2f642dc4fa704004789d28452ce7a02a45f3f83a8d9875480d380e76df09400000000000000000000000000000000123b15dc7f166cb7c2c106cfd2f7c321a9bea9e3bdd118058c4745b6666a0df2a7c7fea16887a4c85faf860fe48a3787",
+ "Name": "matter_fp_to_g1_52",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ade016d06179faa8d44a9ee2542058bb81724d6af2954c0c09a897703d364ec25e62a3a917c5cecce5c96a7cfba924a",
+ "Expected": "000000000000000000000000000000000adadcf2f074679ef3523c10674260b0e40106cca8d94b05f83e2b27d8da8c00dea4215a30275ea5e1a8fd0beb45dfb30000000000000000000000000000000003c2d436e545163abbb18ff7c8e6db1e55c733c75f9594c695c66656690e88995f9f266c2620e99075d3b78805e3ad41",
+ "Name": "matter_fp_to_g1_53",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005aaeba19cb0baff9a8e46b901f15735a0c1f45116fe1f41c22fbe1aba22c0a7678bd4799db5cd9141f3112877e2c5f8",
+ "Expected": "0000000000000000000000000000000016cf855c1ea449c47236065ffe53a4c6afdadc08f1eaa26a8f79ea92a7a119b26dea1dfdab4db9b02b3dcad2c077338600000000000000000000000000000000071924c7d4e6aa5234dc921d288dcad3e49b44d2f455d207f3641f4b5b5c809b84c04945df08e785b3d99eda1807611c",
+ "Name": "matter_fp_to_g1_54",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003f54664746a5bc6f64021e2f18d8c175d96b1c8ce895809c0e6fcfbe896b3e8c1ac7f7556b9ef953371bb143bfbdafa",
+ "Expected": "0000000000000000000000000000000016d80d4689e959233f05a3266628e233b747705bf6d6236771d5e697da03a0daa2dfa88aa5a3a5b97bc4517c467e94510000000000000000000000000000000003bc451286fec0e7a01d29ffae4986a2a3371d4aab875547cac05f759f5a52b8cbf84798b5b3d664a8692b212d4e974d",
+ "Name": "matter_fp_to_g1_55",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010ca243fcabbdb219c5b30092d9d4595a4b8ad1cbed267229eb79a99aef9c5df03d8f24b71db77a5a76917c2fd960ffe",
+ "Expected": "0000000000000000000000000000000017297cdec2f6a54cb11c1fdac799f252c72dad52ead6c29de61d64e56ea0e0a1d3a60284029323e35d38a4a25f82fcd60000000000000000000000000000000009beaeaf3ce2c9bfbfe5e04ceaee87460d760c4c16caa7b37767e16b8e97cf08bdb6d30472b3027f66803dec1ce40eee",
+ "Name": "matter_fp_to_g1_56",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000135d8d92f075c219f8012ce6aebc8e48443b2f33382479a4ca8db0a4f92041d5b6b1e5818b7a3de77a5d30be0e461d13",
+ "Expected": "0000000000000000000000000000000015a163067e8039be1c365804887dfbb78a7a699f0308c8e26519bf1c86fbe6acffaa26f0e5a2a380d1c704fe84d3bba60000000000000000000000000000000013f94e107625aca9c4346102dd5f09d51e445fd44ea67f171048e8f9965ce3496e759610c078404d41add90a358af482",
+ "Name": "matter_fp_to_g1_57",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013e042ccfe0cbb7fa3b045a1fa1a86f199ae91721aaed488b96cc4f6de1899402f81842da2ab55c5bfa63f5b19ddce73",
+ "Expected": "000000000000000000000000000000000b0667e2b7c0fa318c5c0e66425f8cbb8217bec845bfe56997cdb9d0d915131b81e82419a4533eb573ffe103077f35c90000000000000000000000000000000018074b6e0cf144fff9da02a4b5785d21762952d4ed23b1430d6165974f49521b73eaf98973f7967ffb35cee92a2b5269",
+ "Name": "matter_fp_to_g1_58",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000063cee89d1981f27a4f4d4f23c4d1229fd3333fc8f371ebd85c588e751307ccc75d71d151f7481ecba1ef0cffbfdea5b",
+ "Expected": "000000000000000000000000000000000b5e953227f4f5e2070482cde7fded231bb0d4649a626d356cab2bfcba6c1588ef38c62cb2c550719091206727715dec00000000000000000000000000000000095f29eab98321d334f22b4db0c30a0604c5c385fd222a71399763f5c815e04226d9d06b460b9e3b44d1ec127d20315d",
+ "Name": "matter_fp_to_g1_59",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e07265d2762e8e398c83efe1c43452d91b90b7a4271c09ff693c83745a6c01b73561ffe3da9300c8e7e1602dbaab0bc",
+ "Expected": "0000000000000000000000000000000017946ce626cd11556f85d15b85044fdab0456e24b5e331886be860bf55411a03886738aed9b19d52e91a94ea5cc5f040000000000000000000000000000000000cbe613ecf3c8ca8a5f0617c64647a609ce6e8fd40ae42f69a928f4ba78f7038254689bac2dcde7a464a03d5e26e34ce",
+ "Name": "matter_fp_to_g1_60",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000375579c16a167fd9f9f61d5177705f157aa0df3451971029a9444432db119fb33b8c07de33fc822eab46ed4ae47cf82",
+ "Expected": "0000000000000000000000000000000003b425300fc1885f2e932a469a8137bbf9df9560279a5ba87a13e7d4a461489bd8005054f14fad881e06aa46e4333d920000000000000000000000000000000011dcec636ef785d348fcbf9c59a82080b8f2c02d7ab954bc17af1c163a5383a36dd3948ac9110c6afb363ccfde2b6682",
+ "Name": "matter_fp_to_g1_61",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aaa37576af2101d090139f562edc2a6e7169b0150af831d053a3a87a3a5518889a51871e02deb3ec154ccbe9dda46df",
+ "Expected": "000000000000000000000000000000000e545a87fb19f7943e18c75f7a173d18ef8129b200222bf6a2ba5a93a92c47ba7accecc4f089c42d6c6bb2425bd1786e0000000000000000000000000000000008c005ef6e5b25e84a8251add6112db49637c2b955af8cd65d029f8e17abfc660794b474689a00b5d2784163a9a0c241",
+ "Name": "matter_fp_to_g1_62",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000158edaeb58b99d9442d608bc8e6024365e9a81e0aa23bbbd466c9ccc8d29415352a153e1f852666505ef097122592ecb",
+ "Expected": "0000000000000000000000000000000004cedd2deb72d9168ab5704e21d9a5d85b65ae1510a628515753e85425286d9825dac99922be4a19870700956a65ece9000000000000000000000000000000000f5b0efbb2b327e294246fe862ac01dcedc7e728b938edb9c4a6128740b7d192cf8ad877b869207fb6d1453d85db895a",
+ "Name": "matter_fp_to_g1_63",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012bfaf34a8111a01d213f9a9fc90846335cda978b3df23de99cb7b764cf5db1a816f66adad1319aa7e25c0ab89e7de74",
+ "Expected": "00000000000000000000000000000000031841f58b82f7e44aa03f474f18360128aa5699e748e4e2fda1c29d3cf165dc3542b90f09e415e92d73a162af38ad52000000000000000000000000000000000028cbb3ff58cf28f6dc876c2c1cb147bd6af85f3baabe253e9a1dd69687b3a46d4604d2d92d08310ecd7c90723bc7c2",
+ "Name": "matter_fp_to_g1_64",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000fed118654a128735fd39ffd3b381ad2d71479054b6bccc04dd58fbeed9b255ce2b925e2141a96a12edc3a19188d1f5",
+ "Expected": "000000000000000000000000000000000e378bf9d1d65cf3a39dc2b3cd2dca8954270006abe048cc29183c5e7c1cf464b21a548679fdf5af8a31e198b69ded53000000000000000000000000000000000865c90b45eba1979e433f71c93c7b3b8e90d3d12a3c2153ab7c420f507bbf91edb593d3beb3899e76d41674b5ca33d6",
+ "Name": "matter_fp_to_g1_65",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b693fe53cbcd6f8d8c98900be1f9c85966cc644f0a900c70826c6573ee801ce7863a0b170ce0ef168fb1f0ea484b276",
+ "Expected": "000000000000000000000000000000000844679db6a74e2a1f7c342771616c446c5e240e40e1f994fcba49f8ab22a7fe06b6909f50ea3c49a8fbebaf2b22b0a000000000000000000000000000000000090afa19255f7b71630c466d6b180b2100f8ea6b7ee2085973e409af8027859b61e0c46b639120ef6f3ee1555aed2f94",
+ "Name": "matter_fp_to_g1_66",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c6bd688fb883f3097f8b6fd6fd0bc5acef9341f21d62a0706fb3625a70459c45a5200ee36a3802d4bb4912030bfcfc7",
+ "Expected": "0000000000000000000000000000000009ffb2b0054536d714944c6c96f8c1ea902e7109d4917a54ec551d811ab15042f843e158a9e4decab9761cb10e7c3e24000000000000000000000000000000000a6c7a862b951aa9f8c2d1e8ba30af8b7909e9721a06479d186e46ffae3ba09f5f52561c7c4c34d121be1304650cfc6a",
+ "Name": "matter_fp_to_g1_67",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ba7f82549ebfdc7f4959dc67cebde4720d76d5d4742af730d45d614133f0a7b0ae7b61ba5b914a997d9dde83b77b031",
+ "Expected": "0000000000000000000000000000000001f9035574fac4ddc3f114a79938105d95ad4947588028b60e2926a8e0fd78710434edb2ab6b761fec43e458e19f0e200000000000000000000000000000000001e86d391172978aadc652b1c5d28dbb26a5357d1deb522bc280a270cc63cc18284e5b05033cd7ce1a6eb962a5b7e268",
+ "Name": "matter_fp_to_g1_68",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b4acd8c203ebd8e3ce12b10cc791b9a4183440309f24bbd60cb2991712c792ecac64d3f878cbe407fa8ca0d09548acb",
+ "Expected": "0000000000000000000000000000000002583631492e3e0bf080a5f67334f7a2907c707a678bf63d53badb3ed90305a6eae895f7842a5d44a2110585d412ed860000000000000000000000000000000018719d22fc604567689870d5a5b043ee7234927b1e878dce88be212a8b0981e64f3cf9e03dea94439f504c846c6e42f9",
+ "Name": "matter_fp_to_g1_69",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000145f6f774d943a1bb753d5d4876b1a88a4021cb6a6607c0efb07eef2f90ba2a90a6e9dc94586de35f6047332553ce7b5",
+ "Expected": "000000000000000000000000000000000fc1acd8490dee632c51e67356601295291b107087efc2483c1e1a41fedcff244114608c49f6911a4249a59a891264140000000000000000000000000000000019c402eaa9ddd6ff3c72a7d3bbc736cc867b437dbf56c9941ffdb2e0cd60bdb7ccbecef3d62aad22e97c1d96a328e8db",
+ "Name": "matter_fp_to_g1_70",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b892f1c8d001c8aeddf845c3845c51f2e06c3c77e543e9721d797951b6211a869da97325b569e0de35cf3beda853ac2",
+ "Expected": "000000000000000000000000000000001785abb82ace5d8024c97b3480fa69a65f5ed48fd3f5416f068690f8f79295d13929d01922c562277f65293abf5d739a000000000000000000000000000000001076dbc521375a1431b24f7d03902491b80b1856cbfd3e759b520927fc559e705801460afaba6991b032d59739c25059",
+ "Name": "matter_fp_to_g1_71",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001878e791993186ab76f785b2c6b0fe08588b048007c66fc00c695b55bd17b37bdba71f34ddf75ac441a0c2687711b299",
+ "Expected": "000000000000000000000000000000000bf99b7aa1dd96f57974fd79d5823d1f379bc0e32ce416e6f89a499b82727081aa78529dcc76257d1d699b9979ee23f900000000000000000000000000000000067044e8b0cf455974850859bf76bca780f1908beb06a64a7ee8db2ed54703431c354cc3d7576fde0b45611a2f49f862",
+ "Name": "matter_fp_to_g1_72",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016598f630f72a0e1f39678e1d0ec6530c4795d7565c5d026fea2389ec0ceb51b434b532466fbb1c92c1c958041283baf",
+ "Expected": "000000000000000000000000000000000d102c354adf7380053c8b0c11a5c15b046516a87b3e98d1f909bdaff06eebfd9b0c457ec3741833da262f77d411cc500000000000000000000000000000000012cfcd6910ac046ab8c0b448edca5847d0f8cc2a4633fe42edd223ea1b73ec451de8d75cc3d37dfb741ee35259b34449",
+ "Name": "matter_fp_to_g1_73",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000134725b4d43cb87d2e4d3c43ca98b8df257acfa612ccd61dc0aa1ca749f20bd42c38d933d39f8c3c1a14dd8fec433292",
+ "Expected": "0000000000000000000000000000000013c11f82052df6294da64b16551e689c439d2d27922bef2a067bc49eb4718a392693570f3b3e58158dc0f5bc3a5b8f73000000000000000000000000000000001517ee24f199913c184181561823d7c3506caa09d93d506c7773f9f615169df444c9f09b518e840735c259ec02488670",
+ "Name": "matter_fp_to_g1_74",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000070ad61a7f5ff9f0b4e7483f5d56b0f315b5f6545b194565ebcf8f0b8d78519ec113af6d70550888be4d661a8403a036",
+ "Expected": "000000000000000000000000000000000a546a1f4d65a37d7d60468c18f72152473feeed100119b4518f4c778a7a37a23e8c60ee04cc0b39d5a1eb8c908856870000000000000000000000000000000009c5766d9c88dca87768c0aff4160ff0fdc3aa67dde3eafcca030eb295a6736e95e415f3f5a443f2545c7fbd01f97964",
+ "Name": "matter_fp_to_g1_75",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000179bc843fecfe713f6e3ccdc8ca0f48759459b675c8b96f5403e1f6da92c2d60449638f564ce179373bce473669965d7",
+ "Expected": "000000000000000000000000000000000a197b81c0950b1b802128a01e3b620fb2134115a0d1aa2946a82fd22e91f172785d19017fca385863ee1643bcd332b80000000000000000000000000000000011fba5b82b0b2726bbe7a6157ec9103d0b5a480066ce5ab7120294930b81c04cf6d0fb8b979d17c3e262bd1268bdf1aa",
+ "Name": "matter_fp_to_g1_76",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000082bd89b49aa62c94ecd4244b3077421569c71efccc62aed3d4bd492bdfe57c0d2cced568df5992a196a7b71bcbe5e3e",
+ "Expected": "000000000000000000000000000000001644dd543ee92960effec90347ffe5f06d6b087f13c6bd73dca93c9e16818d25ffafe3610260cd43ce9909e2ac2e2884000000000000000000000000000000001893436c9dc44500be831076b375d0feccfad2a126110fbcfb77acfb95d6dd6c6615b4b795c007ece6ea0c31915b8e32",
+ "Name": "matter_fp_to_g1_77",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fb118c86e974734fc434c3bcb783e4a7f9251d9fcfb9f4419529354c8a7a3d9f2215de2d1b9f0927b185c5b4db838b6",
+ "Expected": "0000000000000000000000000000000001aded655b8ba2739b820b894eefd7e60d11889d7321fdae5ddff5dce11551af24acea3f501044562237fe5df53305df0000000000000000000000000000000010f4f3f415891ba4dfb21307798329aac5baea98cdb44354d4263e1ee6436f613a3accf06802ce2c2782e8a15738bc63",
+ "Name": "matter_fp_to_g1_78",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004da0ce78f3068bebd0a59bc2e41e7ade737375f07d6c9ce962be022856c569a33e8bd6ae60c4bb1b53b3ffc2dcc2aee",
+ "Expected": "000000000000000000000000000000000be0b580d0f12faa809d589ba59c5810c18f74b025e6dd4dc49c83b6a39423c5cf82b0dbb1d750e1801e37a5291692fa0000000000000000000000000000000010891c5bfece55dabcd223518167c5b0663f65c001ed051735635b417cbcf2484a057522e1c3417e43c82095b0cbb855",
+ "Name": "matter_fp_to_g1_79",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001f43b86ec24ad40552dc4874a632b4ff4663eeefe1a8c613a19a798a0ebe321a3d543e2df28277944a941b4586ac770",
+ "Expected": "00000000000000000000000000000000152454ae7fed9c971cfd72ed054f44124d71542f9ada5a90f1601114289c93fb490a1c5d99b3e8c70fc44fd10322173f0000000000000000000000000000000017bf9499bdc15ae5091daf41812c74535ca31b56520e420edf9e5aa90795ce5db5fa42a06dfcbc7438e954db83f09b75",
+ "Name": "matter_fp_to_g1_80",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000baaca6bc34feac790807b5eb5fd173c86c12803b76b50be59b2707df765bd10eb467effe34f8dc3e1e79df8a54fde38",
+ "Expected": "000000000000000000000000000000001633516081b91621b786a09389e89b274c2d9ec616db5028b009ed5c0a1ab47695a0b95c53a45112144613a4af08e6ea0000000000000000000000000000000014b09586f75c939fd62c3d667ab6263367f8961ad4597f1b92d792e8ef79a469137dfba5ec0a6354d5bfe3a84130bc65",
+ "Name": "matter_fp_to_g1_81",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005e4751707f3ea7bc7a74d80eff27a0d65cea0c3d2e793425e79cdb0c41e6ad0cfcdbb4de604637c41dbaf30a1e816e6",
+ "Expected": "0000000000000000000000000000000000f0474d596ed86a0d664885f9c981228fdc352755d52dd7e979a85fdb1b6dad106d8bc0a1eac04b510829b7da496686000000000000000000000000000000000a72f532897f912eeea707bfd6d183a73786c7b2e2c80a01f3abe7b959467d6ea63093c16d6465382a7808d5f0edd92f",
+ "Name": "matter_fp_to_g1_82",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008f69021794d93826f8207b96d49214b46dfb1778603634a9f5194e92481465702a8be1bc49a7bb57527fe6f963ae04d",
+ "Expected": "00000000000000000000000000000000139ae959f9b0cc2d900e748220c4bfa7dbe22926d8ecb9a10e7d713fa0a6e147fa3463e06b791a5e604c66110b77f7530000000000000000000000000000000013f8d09915f77f4a18854dc2451cf39d7ff502a8184d3b4c59ad3317d62940e903d68836751172ec0b4a796db003b373",
+ "Name": "matter_fp_to_g1_83",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000116988a869cf552b2440e16569d8b6e30c6b15430855c4d6bbf80683c5497291bac7999c1f8f08f494fcb4a989451c3b",
+ "Expected": "0000000000000000000000000000000015d065191ab63df2175f821cf62a4b948a6b2389512c7e94e1fa3c99506af624810ee17de2c183ebd69b4dc485ae264b000000000000000000000000000000000fa8cfd94bbfa6d504497866c1e0d9e84717fbf0468a164e3b8ca46348789e2b7f08ac5e8aa2e7205062f3d5083dc5fa",
+ "Name": "matter_fp_to_g1_84",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e26058d72875fd3d852aa4139f71d35e1edb58242a4939da7986645117d027d20baf85770fc909d537524244da59ce7",
+ "Expected": "0000000000000000000000000000000012978a0da7162aa1e8b32cb6ec0eebf2c2e62350cab4534358c6bf80299dda9281e16ee40313e7c52c804b2f4de7f1870000000000000000000000000000000009dfbafc8e40d71a789a52d5f8b80e7c8510c58bc0774cfa84211a9c1417d75d5c7b06d7aa9fe052ad9c1f30c922705e",
+ "Name": "matter_fp_to_g1_85",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000078c6cf89561533810b583a88149586b29da5228ced10a75257b2587904217f63499d8b9ad2d536617247e12f8d1657d",
+ "Expected": "000000000000000000000000000000000de98869442b759a382d0f6ca45eb60424eb9aee2efdac83086cb6dd374120941343eb314756113e084f943cb60d91470000000000000000000000000000000019dacc8180e6dd09ac4bb97114d2ecadb04bd2aef6e5f0993742c5270267e42d052d436c99ba61f6c0fd1fd2cd51d172",
+ "Name": "matter_fp_to_g1_86",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005b016ede9d892fbd7aea4e8ed0f1eab70713557311481735a91308fabf76fe71e44a06dc23ea66ac5d831e982f401b1",
+ "Expected": "00000000000000000000000000000000123313e3cc006c4b95938f5eca903604ac9272c7a0c79cd932407b70635d7ca5de9297496c27406f180d5edebbb54c7e0000000000000000000000000000000002164460e59cc8788c96e235a6faa7fadb7e6ee9f6b0b95292992973ff54a92147dc7ae8e8f217515b6185875bd0bd7d",
+ "Name": "matter_fp_to_g1_87",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007160f36f0e5c4ccbcc7900c6504cd86fd6fd700bfa79af69841e4a6127eaad467ccc93c66baf7d767c3fdb1f31c527a",
+ "Expected": "000000000000000000000000000000000393a1b2395447b2e2838c2f49493c185424c4848f888616f16a95552671ff28b5ef223bf34299005f22a8df6efd68290000000000000000000000000000000012b1fe46279922e92d356355752ae0c2f28fc55de39ebfbd317a6c1c507d973f88c6282468571a1efc20c10314ac72f3",
+ "Name": "matter_fp_to_g1_88",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000043fe62b0b9be76a375f3be0d6ec891d5bf5f2982cb2390125ff8d5db57b6b18c5616c526102e4f615963d601d13f122",
+ "Expected": "000000000000000000000000000000000739f563b42648cde5befaf44317468982eb9d2fceee7d2efff1755be973cfc2beda829268246d09cd29fc3aa91f0b8a0000000000000000000000000000000014fe0b03ac5e0e03acd7811270d65742a3345bed7a4790d5f40097dd34050d0043104b65fd4691c251f03e67525d41b5",
+ "Name": "matter_fp_to_g1_89",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b9590b1d0d292d9967d759060a551f4e8e4c1c0066a9a3c0be515085847fa26b77462e3bae9e2621f28e01f897df0be",
+ "Expected": "00000000000000000000000000000000128e92c9c10fb9b065fe2c2dcfe365e98aa54eaeb3fae987306c7f0a227171ae0b3464d01a54a8d6b144ff60c45088a00000000000000000000000000000000001beaace4e23c9a31e1e9eb8596b3b05b9d72553f44c61627654757080171b05c900fe1b638193a69058e8d66cff1aa6",
+ "Name": "matter_fp_to_g1_90",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006ee7c459bb4da96e87eb1d39bd7368de5f60104f85b7b4bcdd7761ce08d48babe1bf5e765282779803bfa972d0e668f",
+ "Expected": "000000000000000000000000000000000a6099ebb3a1101206bbd21149cf22af2371106bd34671c1cbd4f2e19311fd100bcb56a6d9d77bd834f972e55e0fb75e0000000000000000000000000000000001db77a2045e54b0ac4b3d61190684b4eec9c4ea415e5c820992b70d6ee2e086c02892228c4465c8494f939cc0b7b5ee",
+ "Name": "matter_fp_to_g1_91",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000044612b42a2baa9d3e1d187b2a4e048773b4851bbd7d4025e0f7f61abee703b5a563397da4515c7379397dcde698228a",
+ "Expected": "000000000000000000000000000000001101cd37b61247a9859bb09ccf9eb416643f86b7109bb45d6827fbf424956c9a16b2a19c5e198551c43aa1934ad8ed0e000000000000000000000000000000000da562fcb2e3cba853de6d245a1ea0cfc3ac120b316a5f4f7072cc35a6634027409ad08c5d591a6688b24cdc4562cddb",
+ "Name": "matter_fp_to_g1_92",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000014cbff1000bc0f9b394b18e81124dc81f80e291e841dae6e96e0c86a6f618b9f6aa6103e0e7582e5136319a4dac92fb",
+ "Expected": "000000000000000000000000000000000323c3aa4b20691af32696c449668fb6da6a0c2e8eb176fb8fcd8aeebc9b5a3bffc57b28dd35e374811d420419fb0fd30000000000000000000000000000000019516a092385d8c917b46a742f086c51e2648c7e9a709ebeb5a0f8bc29c9aabf99972aa3a218582f37d91f9758a5ddb2",
+ "Name": "matter_fp_to_g1_93",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013da827dd718d3736cfcec53f034d34bce253bc91f7cfd6cd2666819bdebbfc43a9363f82bf4b580a7739b5dda9c9436",
+ "Expected": "000000000000000000000000000000000d0351d8557d21c2dd3b1be77bb01df804ebb9e2d7e80910264ff94861cdc0a4deedc1231c61b7503c5d653e31fe10850000000000000000000000000000000005858ee487860d1ba04cfdcedebda235616c2d271ed50f89d6cf2852ea7e10ac825dacd8b00071684858a12459d1705c",
+ "Name": "matter_fp_to_g1_94",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010e94039f37d218ad393e88a226dd324a37e8d5352dedf6d84fa2ed2cab2f874ccc5ce94599950f91b8dd6d6c8b84aba",
+ "Expected": "00000000000000000000000000000000176c50c2fcf1bcbe03a1a1ed2eb120f94ad4fcea34a59607ea595bc2b37cb92f87641191b65d4b5d57f5491ce6576a670000000000000000000000000000000000e177361e09975c98849faf8e24086f75a48df0f257ea47b659cc2a142a57ad1f64416f6dee5cbc4e57f780dadd1cf2",
+ "Name": "matter_fp_to_g1_95",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000010416da7cfbed2768c77b80957053030d49d535b21a8a3297ab257dee0463c91b87a9e571b86bd874522149d9af0c29",
+ "Expected": "000000000000000000000000000000000dcce000aae744f8b3b6754af57a36786d887d7f9857654f93edbcb6c4416ccfea5e859acc82860b5f706087e87cdc07000000000000000000000000000000001847c32c839668a38669fdbabb512df15cde2b28ca336b0e158d1fd57f74638d86ba40ff68f0a50cead7021e86c5271d",
+ "Name": "matter_fp_to_g1_96",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000197ef97f6d02a51b80e6f5629e88a3c60399bcc4a358ab103dac3a55a5877482558abed922585a1ce3228ffb507679b4",
+ "Expected": "00000000000000000000000000000000062a58846d39dd1fdbd34a7117797f2200d814b2a8eac9479885762565a979e93b5313575bff5ada3211eeed0a3f4ddc000000000000000000000000000000000548a24e7af2b38c4d16d8dfc8fb2d7e7669051e2643c44aee113f20d31f4853cef84e2dec20095c273680cca278331c",
+ "Name": "matter_fp_to_g1_97",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000025f1ac90f5b0748d57d8f7a928be875c5712801f70af0d057546228c1bf83d3a207884c0d66d0b5dbcaa736bfe0aa1",
+ "Expected": "00000000000000000000000000000000107f01e4fb6430e34128e3335872cf40df2b498a63e048d46158190cb627e37833d2238dd72681037ce376384736b43e0000000000000000000000000000000000e1812299403efe0f8d111d97a4b7e7b8aa1f4ec58f9935b1367d81a847fb42cf756154448f9172118123679a41a280",
+ "Name": "matter_fp_to_g1_98",
+ "Gas": 5500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f66b472b36717ee0902d685c808bb5f190bbcb2c51d067f1cbec64669f10199a5868d7181dcec0498fcc71f5acaf79",
+ "Expected": "00000000000000000000000000000000188dc9e5ddf48977f33aeb6e505518269bf67fb624fa86b79741d842e75a6fa1be0911c2caa9e55571b6e55a3c0c0b9e00000000000000000000000000000000193e8b7c7e78daf104a59d7b39401a65355fa874bd34e91688580941e99a863367efc68fe871e38e07423090e93919c9",
+ "Name": "matter_fp_to_g1_99",
+ "Gas": 5500,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsMapG2.json b/x/evm/core/vm/testdata/precompiles/blsMapG2.json
new file mode 100644
index 00000000..f30eef65
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsMapG2.json
@@ -0,0 +1,702 @@
+[
+ {
+ "Input": "0000000000000000000000000000000014406e5bfb9209256a3820879a29ac2f62d6aca82324bf3ae2aa7d3c54792043bd8c791fccdb080c1a52dc68b8b69350000000000000000000000000000000000e885bb33996e12f07da69073e2c0cc880bc8eff26d2a724299eb12d54f4bcf26f4748bb020e80a7e3794a7b0e47a641",
+ "Expected": "000000000000000000000000000000000d029393d3a13ff5b26fe52bd8953768946c5510f9441f1136f1e938957882db6adbd7504177ee49281ecccba596f2bf000000000000000000000000000000001993f668fb1ae603aefbb1323000033fcb3b65d8ed3bf09c84c61e27704b745f540299a1872cd697ae45a5afd780f1d600000000000000000000000000000000079cb41060ef7a128d286c9ef8638689a49ca19da8672ea5c47b6ba6dbde193ee835d3b87a76a689966037c07159c10d0000000000000000000000000000000017c688ae9a8b59a7069c27f2d58dd2196cb414f4fb89da8510518a1142ab19d158badd1c3bad03408fafb1669903cd6c",
+ "Name": "matter_fp2_to_g2_0",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ba1b6d79150bdc368a14157ebfe8b5f691cf657a6bbe30e79b6654691136577d2ef1b36bfb232e3336e7e4c9352a8ed000000000000000000000000000000000f12847f7787f439575031bcdb1f03cfb79f942f3a9709306e4bd5afc73d3f78fd1c1fef913f503c8cbab58453fb7df2",
+ "Expected": "000000000000000000000000000000000a2bca68ca23f3f03c678140d87465b5b336dbd50926d1219fcc0def162280765fe1093c117d52483d3d8cdc7ab76529000000000000000000000000000000000fe83e3a958d6038569da6132bfa19f0e3dae3bee0d8a60e7cc33e4d7084a9e8c32fe31ec6e617277e2e450699eba1f80000000000000000000000000000000005602683f0ef231cc0b7c8c695765d7933f4efa7503ed9f2aa3c774284eabcdd32fd287b6a3539c9749f2e15b58f5cd50000000000000000000000000000000000b4f17de0db6e9d081723b613b23864c1eeae91b7cbda40ecd24823022aee7fc4068adc41947b97e17009fad9d0d4de",
+ "Name": "matter_fp2_to_g2_1",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001632336631a3c666159b6e5e1fb62ffa21488e571cffb7bc3d75d55a837f242e789a75f0f583ce2b3a969c64c2b46de200000000000000000000000000000000184f1db9ac0fdd6b5ac0307e203d0b4237a50554eb7af37bb1894d9769609c96c8437e9d6d3679ebd5f979eb04035799",
+ "Expected": "00000000000000000000000000000000184af3f8a359dd35dddd3dfcc6f5b55ed327907ed573378289209569244e3c9c02bdf278eb567186f8b64de380c115360000000000000000000000000000000012f5ba8e520c4730ac1fb75dabbfdc0181855e5ba2968a8c0ba36a47ab86ac45d19aa3d55f15a601e120be1f75eefe240000000000000000000000000000000004e313db704b103c2c1e3a58f8e95a470e7199081eb086e9524583131714c4a3db551fd51a3f2314a19a658e7b1765380000000000000000000000000000000004040eab7416a1703b0d103120506f1de2b26b0f48c7a0ea63dca4d9ad1c478ae03b5d7bfd51f4cd6f8cea26212c4edf",
+ "Name": "matter_fp2_to_g2_2",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000732f171d8f6e283dd40a0324dae42ef0209c4caa0bd8ce2b12b206b6a9704f2c6015c918c79f0625fa791051b05c55c000000000000000000000000000000001139e8d932fc0ab10d6d4f6874c757c545b15be27cdb88056ed7c690aa6d924226d83e66b3e2484b2fc3dcd14418ee60",
+ "Expected": "0000000000000000000000000000000017fc341e495bf4ef5da4c159a28320aca97ca28fe3a0441242cf506b0f89bb52f5b5d8c6e038d229ffe67d00151912f00000000000000000000000000000000007666300b7be3d904ae3d19019f7be5cf5ba6161b969c1a78aff639a24387d8fdcc4d0e3cd81ba6f063ebf2d859370f20000000000000000000000000000000007cc705dbfb5c0418beb1cfbd864fa0631bd60eccfdb16b5d55b6ef3558e2ec87dac3b45294dcf04a064d6d1eba5a6eb00000000000000000000000000000000052cb9c982e6b05c1d2ab4eed1d8082f96426b55615ebc6a53bdc320ccad0aad044395ed641b3176b554f19e62d46b73",
+ "Name": "matter_fp2_to_g2_3",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019a9630cce5181fd0ad80677ed5ad8cd8bce3f284cd529175902b78ad4915f0df56f0d8b37c87c9ddb23d0342005f1570000000000000000000000000000000002cdd00b7662569c9f74553a7d0585312a776c8638e54ad016f8d9d25df98651789470b12ce2626fb3ad1373744387ac",
+ "Expected": "0000000000000000000000000000000015ad9155037e03898cb3b706f7105e39d413ff3a5abb65812b8d21d003cab8fbb607d3938ccd6a774bc8debfa30f42760000000000000000000000000000000019d6382bb2d78180a8998a0536d67412d00ec0ef65f4cbce01340b8d6e781c0ff790296f8cada28966b147c69e02f366000000000000000000000000000000001290c2c205b748069d0875a89ca74a3b05ad8218ed46a1570696932302983c090d96e17e0b828a666fdfc3b72cd348bc000000000000000000000000000000000114f2f7ffaa9f90b547e86c863a5d3585819a78b095848dfa39576a10874a905488687b73e613f3d426510f5d1d1ce1",
+ "Name": "matter_fp2_to_g2_4",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e63c4d12a38837354bbcdf4f844e5dfe727ebe292016748007d162e74c1f849787767f7e77fc57a42783fe0b06c24c80000000000000000000000000000000008d879e4891a891f2e7d27eb95aef70d5b785b796620ec43dfbb6ae550b4effb9f24210dc20f401d54420445e21cfdd3",
+ "Expected": "0000000000000000000000000000000012084a53cde353a46af17cd2fb02c477e47b874d8ff58025b5015837759032ff98013dc5bf01253bb964f035183c9071000000000000000000000000000000001659272ab7e3a070a5c7b25a5d3402f7371ed67e58cac8438df41c39c1acd95ac5886b030384bf537d7c4bb8ddb2c538000000000000000000000000000000000852ddcc37a09a0a8f62dfbd1ba5064c1f6afacc9a279a4d998bed643eec5a0d96d6bad95701a04f52c83e8f87f48d5d00000000000000000000000000000000097a399370875398028d42bde8cf4e9641730af7a2971e2f59c95938120603a239c65030ded4323c955f7fd24bebf31b",
+ "Name": "matter_fp2_to_g2_5",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000028d6de947a3958af5b53578b0ceacc7ef89d36526d8f3b6fbe787af69fed2c85cad3001643b81c575a741c4566e617e00000000000000000000000000000000182b56202f0494bd8baf5c03969288a1288b8ed8e6c7f49ec9f7493ee3369eeb42fa8f5fb7b243fb2bcee6be244f02be",
+ "Expected": "0000000000000000000000000000000006f8191123f1e8f6a05e4e663fa763c8a0ade5de3c7cd38ec1c82e1c85f123ab51fffcebd677afec8e9adecd8d11263d0000000000000000000000000000000004fcd825bc55d044eb70e0bdd5ea2ac58ec1487e903b431c57a640c756265a382581b8450fb15dc649cf22a8539088220000000000000000000000000000000015259f83d76490bb868bb88c2a2c3e07a326bd3e97fc2f552adf85722a360a443d720c328076e35224328e09494746e0000000000000000000000000000000000f76b0b960a1343b4267f5aff44901fd6796a778b1a87666b95b773edd0e7ffb6656d4f0cc3b9b38bc6c0ed20cfce153",
+ "Name": "matter_fp2_to_g2_6",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016adb5935f32bafcccb81cf4d177dd8826013d85e11a4aad66e3aa596e1183aeb9d68eb8cf5b716a8a9445ea81b40d7a0000000000000000000000000000000018bee24b0c97af8aec210f15bbb6acbb76168dabe16e669d5558d8d32f00fdf5146471922fa98a28f238974d327996a3",
+ "Expected": "0000000000000000000000000000000018bf5f93dbc2c37479b819f8edccd687c4d3c4dd04f8c73762fd89d0c003674e3b2ed749d23e775f925279b3112689f80000000000000000000000000000000008a033b197aa8ea2213dbd7ed478d98c25dc6e9f91b9924f3c14124da26a67bb196926e02da89b746f2a67b14ad226070000000000000000000000000000000006f7824bdc9c53212609512858278f79d9b094165ff178e3da8776e24311bebbd9deb29f366d4c7693a15c34df118403000000000000000000000000000000000edde25fc24b9ec58b3c317aa3ae48dd5fecdf6397ed9636ea042722d264db0b1a89a15a1e16e892755730ef52796527",
+ "Name": "matter_fp2_to_g2_7",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000114285411713eafd395ee43bf1728f52d17ac512b9d0cddd38c904a9a3a1b30283a3918cd2cc3da6a7d6b4ff923cbb6e0000000000000000000000000000000018a067f91f94b2904c5bb6900f427ec4e93374b5079c84707feabeabde20b5e49801f1f3c7504dd27da94d5e754df4ad",
+ "Expected": "0000000000000000000000000000000002d28025f4b798083aec3ca9a91a051ce27a374b115c944932026b4fe0dcf68b335d5e47212f800c241c2d42fd219635000000000000000000000000000000001742fb6ef8e9a5a7572b0d3fa4ae8ae56c9c6f4daa20d0b88212c40511c6f6b5ee98314a2d1cbe4bbbec907495a1ade8000000000000000000000000000000000d700a511a58c1b8f11153669cb21d88512dfdacbabe38e402431b4f7ba374b5f9a88614da2d56799d39324e9d19e27a000000000000000000000000000000000c6068bc7a43d614b8f1132b13e04f66d2fb5ac0c5bc8501b754a0bcf4f382db92b0994c4999e104c9d1111ef91d5edc",
+ "Name": "matter_fp2_to_g2_8",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000dafa9fa843879038fd1566c319c24119989090c5fd34f6514e57f633d3709f0aa9954dfb289843a6990588e337b63e6000000000000000000000000000000001742a98dd7d3671c2c64aa71023a0040e936fd726c062d520626113bed471e53ff3e85737e5abf9ee8821bae53135f20",
+ "Expected": "000000000000000000000000000000001350c68434a9b02392e60540a3985bae8daf9a170b30336ac73afae6f892c7ae8f5f1cadfb2780d6e5961ebf91cd69ee0000000000000000000000000000000000c20bd286fc1886b9b28dfa40d1a27395cf76a8b73946849ea0a7b5e12530de13c16acef8fe2a2c247ea65ca023eed70000000000000000000000000000000002d8ffd0235fb60fa573662034d46260e0c96396537b2a9d486dd03bdd13c5a1efd2d3cb9849ed11c4376b665f378226000000000000000000000000000000000d90ca1b73a6a9566832f9f19d8530a3b12f22bef853fc44088559b923ca108cebf4291e0d7de8f25c7429d455f5ae46",
+ "Name": "matter_fp2_to_g2_9",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019cda532e5d94f3b193b3f286a038637a736c2b87b804efd4779359db5bd95320e06d6d28da3c229ae48ffc02303fab10000000000000000000000000000000018df89e4a545bfb825bcce2f4c25f2416a72e32633b3dead5205c8b7d69c78f119d0e940e5bde9ae1cf91574e5d6c175",
+ "Expected": "0000000000000000000000000000000013f223602e8d12c3bb51cd393f6f59beb5c55fe80c3fc8fb0bc90eca533d9b7981563a30ebd727ab6cf0111fa2d3099d000000000000000000000000000000000962b0585c681894cb701f17ec06c0c240899db574c02d82d85ed4dabd4b8654c29b84c71d2921986fc2abc542a3ed9f0000000000000000000000000000000000f0e79245e645a6e3fb88b9103ede3e6ecdd7e45d61b5755d7a8d100d80719746af58bb23d3068cee7389b2acf17f8b0000000000000000000000000000000017fa0aac84c58283f34b9bf713cde98c175b38e92503c08205350822d778f3dd5bed8051e185c495831a628aa89335c7",
+ "Name": "matter_fp2_to_g2_10",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008ad60829ff001404da40923806e496640a90c5c258a41ef5912f8a1a20eab84ce43b2b5aa4aa7dc4d8b281591d235020000000000000000000000000000000000f13dfef4b3b83aa7f9525eae9913e10502e77c03c55a7aa2de083dc5102c098b6f8e36cb5247b827e30fbcded9e2d3",
+ "Expected": "000000000000000000000000000000001062c97c214b86518660c5e1c33a4e48923ae89ab7d8bc5c798e631de16fc1f104aa957d3e7915aee8551e24aaafc8e6000000000000000000000000000000000e42b785f17f25b87a0dc558a8d57b19d8f41767c3b4fd70c147e95443aff2d9a743003da41d578a2b56d7dc748cf59500000000000000000000000000000000111fd38cd2f5f681bb37f6239a5eea820ce3f01023c685f8e7e244fe9aa9dcbd18f0e50705faa5d8d66b28af9f371c630000000000000000000000000000000004726d3e452f6fcb180ce1d50bbee3a23f7949b635a058f12de1cf5abda19c042168feea53211dbed0bfca489a020930",
+ "Name": "matter_fp2_to_g2_11",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010468e5421a72ec85b63f7f3070a949223105763868111424fd151c8365eb0307dbc9cbc92e5dfb296d06ddfb58d99000000000000000000000000000000000008149ce856d489050ea834452bc66f7f3478c2056969354dca8652f3d0a349e40fae0c4c57ff0f5e022aa93c61f8c844",
+ "Expected": "000000000000000000000000000000001211bb8d3bf65b60efc7237ffecddb4e7e2f0dd36e2a704dfc9f4972897addff1a57182f8e0a0ac08c9af2c98eaa4c560000000000000000000000000000000007e9877280aad45a3b1453b6771ab509e4f53937cc6da73d3add50aff94869b27f49218fb479fe19a6176b9aadd36e35000000000000000000000000000000000ff915801695a281f6642751be77155a813847ae0237d77d2edf836aebac02b659b98d49842d4d10e82d9d146e63a3da000000000000000000000000000000000fae1c8c01a2dd94f17c660353d158ff6f3eed4e6375f1e414ade9d6fd040a48e3ff0d558c882e92e74bd6ef4ab06168",
+ "Name": "matter_fp2_to_g2_12",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006295de7bfec61f06a56fe09afbb74be968329e88ba2e87afffe9ea9bf646ff5b4a03d6088e87644958ced95eceeea08000000000000000000000000000000001443e61dbf14b6c6ed99e1917ecfbe5a4a23ab9bdd3bb089fbba76d795d715d9d2e3c7d8db0b7a9434ad691b68bad3b2",
+ "Expected": "000000000000000000000000000000000dd00d9f31cb5148048125668286c1790cb7294e740df978ac0bdaa6e1c4ba139a04f5770b194c9bcfb123d9b40b6acb00000000000000000000000000000000085d5f4cb831720fa13cef25464a1ba7af33abcc4079d2c5736a219ad9649ebb5dbb8687a2d3952390866587d7088f72000000000000000000000000000000000de377d773e40e1c76e218b969297d15f7819c525ce39aee5114e8405bd7361116682cf9d673574d415a7016b23b567d0000000000000000000000000000000018db26c2097f72b8788ef5aad2d7aa400627e224924afea1ac7c7a6b5cff4a55255e218572614519a536eaaf0f65533c",
+ "Name": "matter_fp2_to_g2_13",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b14b12ecaa94f9656be54772be9b22a2495d4ff873b0bb971c27ab1d8b940c84cabcf921f6f75e93942c38cddeb87500000000000000000000000000000000019eca0daafbfdcd3b56be863dceb21e624b22c0d376fb92ba606456ce3825981713b88e40b7fd801e915f97d5c29ba75",
+ "Expected": "000000000000000000000000000000001853b4c4e6fcdbed29c5d3aa4a9f6d447adc512f66a32fdef06c6ad316c42eb3ca47ffe6f21318ad610d0a68673d7bc300000000000000000000000000000000123d15c37fa8b1a95229e28500c9a767e6286b780138dcff2714bf1f8242f39bebb7d86e2811551914719ca90fb5615f000000000000000000000000000000000537498c2ec64b2ba58aa0a858b69990cac544d5cac29abdf6a42ae9c04061f83580b79c2a6104ebc55939d9a2bc5ae2000000000000000000000000000000000b348c19aad3b67c690512f372d995555ee38bffcdaf33bb827160d6929d2ce598523880f6136f11e1d6482a654cb016",
+ "Name": "matter_fp2_to_g2_14",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000104a452343a4098e9bf07380a8e52050259da95f5fc88f31511a08090bda85f0a08d49cef95bd26c7181aa3eb0be122200000000000000000000000000000000012400aaec3d2f4a1a8cf3f28fd396133c3999c074a565c110354472ae29479b9b62ab67128521c2c6ec4869811ba760",
+ "Expected": "000000000000000000000000000000000994e7b6ccafc996f672c42ab491105ffe1482e65aeb456de2213b531889773ad4d5e6ea1687d6a1f13e74878766f11e000000000000000000000000000000000b89030486a1d622c97970ee7da6189ac341b9cafbb4081463f579ab8b4b049c6e6c8b63157455770a79108424a14f24000000000000000000000000000000000ded43800a991f8c37282d803a39941d3bfbfbdc56dbf7500ef3d16750b27dcb1ad93f89714395fd3dffe318c1771375000000000000000000000000000000001994144b032e1f8c4d688754eef82cdba0018ac47030fcb77e8fd920e0b0336255d2cc8376c03e1074f91269cd2519d1",
+ "Name": "matter_fp2_to_g2_15",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000093e04bfcbd77bc6bafeb77f02d0f794a20b155435ee3af1d667c025e7645d9387abe0ef281386339f461352da93fbe2000000000000000000000000000000000481ffec570d4e155ec10e0cc58effe7a5651795d604cfda6cdbf011676772fdce2c25227e7d5a1a26748d15b1668091",
+ "Expected": "00000000000000000000000000000000195d99406baadc7d8740962cbbf4bc1f22b08eafb52f3cb3c588b6cb3cd89d16cb7b8d388563289f5b5ea466128525c80000000000000000000000000000000004809f70463633595dd763d658354df4f9b409911e1a0328fdaf486d76ffb410d7c6cfcc2d48fd6757d5c2a4834f81fd000000000000000000000000000000000654f8475562098a2cb27ce224674a383283cde35173e1c16b141998b641ac9ee663d766f045451a7f6d600973f0ec520000000000000000000000000000000013bac451a44982c7b1aaac7522dab598cb79b9a3dab77f4d5a4c1c97c154451499979af1f86ced8ce2099bccd400420d",
+ "Name": "matter_fp2_to_g2_16",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013a3c5dd40f7d7fbba7563331917fe19a093d5d25ae7993200c39460e0c46d839e3958b672b4ed195300f398137faa18000000000000000000000000000000000255bc4d313fbd61a270dce8c851f1fa09e6ac5dff9b9e8dfc8a236a1d44548cb079023ee9b8f0f5756b39e44489c3f1",
+ "Expected": "0000000000000000000000000000000016ea88d0bce32981f489438df1bc14e7ade7a45d449ee1ac1a041c1204460cf53ae5c0e111914d8af9e6b3b7fa394484000000000000000000000000000000000db571ca6a55bc8285421553a373048f7877ecb9683d52acf07d48e1026795993e4e7177490921bc6fe1e63d69c2de3c0000000000000000000000000000000011602919de1df6cc0dd36a59c84ebb8e209056534e336f5074c9ae5323f8a03b123dc6354cf85301d838b16518ab64390000000000000000000000000000000004407d30fbd632fd493055bd4d8cbed337767a2ac534411a3eabec570ba41d2ad28ef37512a7da3611ad60b6536b3f07",
+ "Name": "matter_fp2_to_g2_17",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ab7b4dec955de92224b234c2d8bb2e3881806c2d36a9a21036e9412f0a8d3946027cbb65b5dd9c975e01b3f235b883f000000000000000000000000000000000ffbb55002d9e926b3d8e7d963ece82c14afaca8b4d8415df8f964a39db606ac99f9e442ff69f7ddbbc4ae563b836192",
+ "Expected": "000000000000000000000000000000000c1e7b188697aa9a053f14e2d907f2c61a59e0b0c72f9cce30faf81dc714a50113500ca9bc3af6657a5d214f52c90616000000000000000000000000000000001544c35d712eaf79d8dd5a22fbab72f8a6843728898412a7f305b205f8a50e03c6c462b87b3ac165e9e6428e0a44a74a00000000000000000000000000000000029ebafd90a1a887669fd0ace762a66bca2bf0a216333b0ac97dedb6bff3dda2bca1e3d0ed5fa9081c2887fe6a8e24cf000000000000000000000000000000000e1a01ca93ed268e0291a937483f7f8e252c91f9bd8bde55271b0c97fcbbb9219009514217dd8bd7e0267f44e9927a93",
+ "Name": "matter_fp2_to_g2_18",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000103469c08562f6f72152db58b48811b0098b68af8de00e652bd5a67246459664cc8c54e15705d702d51e3f1d8ff76a7700000000000000000000000000000000059b326dd567fb2f8a6ae87f41fb22b3edc25122138a5f6732edb48ed7fa1949eda6144297f54faf406d873a016a1510",
+ "Expected": "0000000000000000000000000000000004e8ad9838e7e269cddf0ae5c8f0f57e7467e0b6f2b9e37e7c4bcae965e9582dc46c9c50aa01f5dc761bf2f1ad311eec0000000000000000000000000000000011b1438ccc668900914578c3ec6e1334d0823861c892608817498fe2e538deec73e0034a6e8ba9790f63fdd95af3714a0000000000000000000000000000000005b4c88196425d3ecd22bfc0cb1a95488493f85bb74f50315f0ffcdd57ad2de23c137cd6d2f6f6dca8af2e3f7bb0539c0000000000000000000000000000000017066344a0f345ecf6a2ba66c37ccbce26a3f551524f74636d4c4812bf5adfabffb0645b898b10c332e94e5f2ae2d1c2",
+ "Name": "matter_fp2_to_g2_19",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bd594d2f5e1472f85bfd550df3eb948085781459eb3037fab34186ad9a0204a0767c8fba571af858a054dc231931b8000000000000000000000000000000000087b8398406c1e707fe87a16118e2448d6a5f4fd1d6c9d7174c4d8a4314fc7b2c21f04178533480976dd20e28b278ad5",
+ "Expected": "0000000000000000000000000000000010d393bf893d589c578df58f4d0098ad3cd10d3a1d0f112f51b132a369e68c0284a6b70a5673383ae24a27a9043b16cf0000000000000000000000000000000003402afb77b187b45906d9cce348976ed88c758d75b9962a53352a6c3ee37751a9928097c0d68c6f8a315def4ca875200000000000000000000000000000000019b98631e53a3ffda3fb9165ef7236dad5c0c8d57c3315617cbd3ce77430bd89b9e1d88a019042cae0075594514a5e67000000000000000000000000000000001783bf1c9b0ec44c9191dab01ef5bda0cb2f533dbcd3aeac2b7c6720dbc8e3f770a215ec8ea2035129711ce4b448ba87",
+ "Name": "matter_fp2_to_g2_20",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000673dface7041c3d7503ce4a50af946d344ad48327b515740b45276403d91bf1ef9deba79c8ffa0126be990b62bf3072000000000000000000000000000000000adb42b7eb0f6759a04da7b933bbc2b6aedde47da8571d6fa32268c606dbafcbc810844017eb6377493a12d76ca56c03",
+ "Expected": "00000000000000000000000000000000086ac901098212acd091d9c4d42a1318c3b343480f1130d6e52128d61df9e19fb61ef1ff35de0ef60062cd99202910ff0000000000000000000000000000000019109b7292f1a420f09a56dce9694cb4944808a2ce9f1964cbb6ffd14a710c35abe81300090ffcd9e95f33e0de9f879a0000000000000000000000000000000012660c4e114a215390c6f6eabc4bd6e3d062ee28d0c87e24351c7d43195253cb7b5bcfed2b4abb2fdeb3ac04ee228997000000000000000000000000000000000e56d35a7e40a86ffd2088c81488265ecc4468d6cf02d563c91611cdf8b4333cf66ef50b993fe651b1792d2b242cff94",
+ "Name": "matter_fp2_to_g2_21",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f554e52c4a6c5a94fd09c617f57e8f87af57e73ceaee8997fc62c8ddcb2f875ee805e6594a0fb72738abd3cd4748ddb000000000000000000000000000000001876dd03316ff007a2efb4c5f452d8418edacc2881b20e8340895f6fc768d14fd89bd9db3dcfb53fa98a1e96055fa83e",
+ "Expected": "00000000000000000000000000000000071d3e796fb15d63c2d5cf68f59f11792b0b580b85c8839a02fad96664f14735ede2edfd5ba5b64045b366904f54ab600000000000000000000000000000000013fd1ea38d32772458622731b9e2d9d749f2b747443f7e47ef5e041531b56f86d1775d42a548b2bb201228f49ec9f46800000000000000000000000000000000099c2bd996c8c5ee37de971e8b75a0bdd4f69299778ee3d216973c9dbba97c7a93e40b209d390024bc4b5e82560a1a83000000000000000000000000000000000c4922ed9af845467440b78efa3a53ba904f29adf66e8ac437c8bb6624b5e5ba0772a5639b45fe167b1fb9283747c50f",
+ "Name": "matter_fp2_to_g2_22",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e8b2369fc2c584d78d52037b109aecc87dea0eefc2da46948b5535ad19c9abdb31aee66739f4852a2d3c51f2e7f74e900000000000000000000000000000000168b2d3e4b67390cb8ba5e48a7a823db08edee7d8eff41b88cd653cec1fc0df7a55303d3c91e92a2dc8ebdb327b225fe",
+ "Expected": "000000000000000000000000000000000e413d72fdc3db6fc79ef26ae8b37fe5c4356a80b3598513b5173b3406ffb54708b8794dae158060a1accbe956a39ff30000000000000000000000000000000019ba9dfa74fd241a55a3b47c9f37c6ebd1e8b51f46197881abb64b7f57c0e2d8f18edee35bb9da03702c0dc5cc8749f700000000000000000000000000000000183525156fbc80cc67d6cd15fd2ddf7fb0528656ec1d31b4c275ef101dbb635424abbff1154a3ee04346ac53148fb1f70000000000000000000000000000000011da0dcd666d01180902d8a7fd7d2fbb39f9c7587540451045956108a8579d7c116385a81627dad9d4cb8cfe68927b6d",
+ "Name": "matter_fp2_to_g2_23",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000016cf7b1a9ebafbd20c078948fc974bcca9b8069edc1ca5e8f364f8ca2a52e56e1a424ea6bcc4240f46dc7f262760bf480000000000000000000000000000000011a6a67d4501a8d9b3ab985be59ffc41e79c453bb5548299abff3b83ba9ff951025a68fe6a8ad3eef3c02d39fca8f909",
+ "Expected": "000000000000000000000000000000001932acb1fd0708edf13c293007a035991bdfbfe0089b61c261258e8c5c10d82a5318b2af221b372f0f3f43c391421582000000000000000000000000000000000973650743f0ec8e2acca33f2ef230ee7a05635d14099cdce913ad8678458ec0dde5c5a941097af2ee0c8ffb937d09fd000000000000000000000000000000000bdaf319044101ee9aa27b3accd36a5ecaf8b80deda4548377ddeb97283537be3f7199ad3c190ed23cdb44abb8786a080000000000000000000000000000000006c448827e3fe4f274bfa55a66bc76c5b01e29ac6a8dbebd801855ba4e93bcbd03292ccf804f07f21481260c135b827b",
+ "Name": "matter_fp2_to_g2_24",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010e53fe9fa94ca622cfa370129c1619b2426bd9d50f4b5eb8a3f681479128dbe92adde15477ad8a4463b08f1a02a62d50000000000000000000000000000000014d10a90709789b25369f0376f39b16860aee1ddc3a4340542abff0077a4af8da946cc29fb6afd9930b872ea98749be5",
+ "Expected": "0000000000000000000000000000000004aee050b0ea07118d76f835218b77b39854f5ababc4e2a29d7c8cc7c18a69c30bb22437049a051d049c8a84f7868ad40000000000000000000000000000000003b1b809d5046054924c3814d26fd5fbdc59e03e5505813bab73bc212b0f5bc0d3fc34478311c5e1ac70fd16a01c52800000000000000000000000000000000002249a026af0b49f4659eca2c23dc790fb36a7b2996188828a17d5852003f1420f11699062932835cfe6543d454521e30000000000000000000000000000000008217aea2221f8748cd81cd37777605a95a63aba36a6ddad72c1e1ac57b24d79ff9d9c4ed71a6e3ac8a378129d5475ad",
+ "Name": "matter_fp2_to_g2_25",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000194612afb777e39d0308a290bf823fe706487c3473412d1410dcb2c0016a70706e70e3a009c0bd61e755b1e4c65bcad0000000000000000000000000000000000ade016d06179faa8d44a9ee2542058bb81724d6af2954c0c09a897703d364ec25e62a3a917c5cecce5c96a7cfba924a",
+ "Expected": "000000000000000000000000000000001274f676bcc05e54fa4b0cce234870ba97a0b1626543d6a9f09afebd5a752769000df404e4d434ebfd561f8335f36d0d0000000000000000000000000000000002877c9438fa319dd1a00f381834e8f3d3cdebf4e1f7690cb82559a2e978bedfd2455be020d0353aa56d435c0174b5b10000000000000000000000000000000009487cc9c7a09be901673cb1bd9a51f45e5d2ed30c90cbdd3e2b294c8f866f68da55533b78152e9ef6de30c345fde5b7000000000000000000000000000000000a3a8d4aabdb260203898655745cb695e6dc90c6e7bf0248784f8aa2340390fd5d8f1c6a98eb1990eb97c2a7f103e3fe",
+ "Name": "matter_fp2_to_g2_26",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005aaeba19cb0baff9a8e46b901f15735a0c1f45116fe1f41c22fbe1aba22c0a7678bd4799db5cd9141f3112877e2c5f80000000000000000000000000000000003f54664746a5bc6f64021e2f18d8c175d96b1c8ce895809c0e6fcfbe896b3e8c1ac7f7556b9ef953371bb143bfbdafa",
+ "Expected": "000000000000000000000000000000000ef415dfc1e47f39e9632ed21c9c2bfcc1959299710dcd7935a757e3756a42c8f6c627c720fd62f9c486a8e88a64c76d00000000000000000000000000000000088079108fe7d9ac93590c045be0d41396f3204d83793c4e862c5360ddb3268a63f704a9d14323943fc85874cdadaff1000000000000000000000000000000000cce908e8dbb7ec35820f2db5ae1174e0f675b21ae416fc89a7f242df3ee98764022744842999f65132229156d2627370000000000000000000000000000000011e0e2f8513d0a71b48599139a9a29c8eca090c5b02292baba58e07b1d3898fe158cdeb3bbe8edb4a805e695e896984a",
+ "Name": "matter_fp2_to_g2_27",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010ca243fcabbdb219c5b30092d9d4595a4b8ad1cbed267229eb79a99aef9c5df03d8f24b71db77a5a76917c2fd960ffe00000000000000000000000000000000135d8d92f075c219f8012ce6aebc8e48443b2f33382479a4ca8db0a4f92041d5b6b1e5818b7a3de77a5d30be0e461d13",
+ "Expected": "0000000000000000000000000000000007c6f133647745c312695439f1d8c251e941bad6e988cfe324ec7c959a9e0fb50618984429ff1841d4286922a26873170000000000000000000000000000000008edb220f77ed17fa1f4757a42ec66ad808c1acc25c4b9311be4c09703d547f648d9dd7c8109ffa89d01a35c69ec2685000000000000000000000000000000001595cc05b04f557ed569b19d64c09f4d82e6617437571fddd72a672d07ad94bfbaaed906b3a7e3db519159ec8d0a8c4400000000000000000000000000000000041157d4f40bfcef680af0143ccdd0c4bdd25e598a470dae844d887c398bc498edad715fd7383421fc78758cc9b00326",
+ "Name": "matter_fp2_to_g2_28",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013e042ccfe0cbb7fa3b045a1fa1a86f199ae91721aaed488b96cc4f6de1899402f81842da2ab55c5bfa63f5b19ddce7300000000000000000000000000000000063cee89d1981f27a4f4d4f23c4d1229fd3333fc8f371ebd85c588e751307ccc75d71d151f7481ecba1ef0cffbfdea5b",
+ "Expected": "000000000000000000000000000000000f983607a6d8a5c3b8a577cbd5d81ad2ae936e714199e3f4095cf280b8fd6d3699acf4d2ef251a571dd1ef4ba6d838bc00000000000000000000000000000000048c12f8b95f9537e56479b1bc43a121e4edfb6477fcb090a5ea60c5f4d01071776dd0264b0250902448f62800f4d2ea000000000000000000000000000000001644ba272d7003d0077991ccb4569638de0dcc48fd2e8e9a41cee1d2200aee1a849f2d620f60beeb06b08c31cd4eeacc0000000000000000000000000000000018892d773f7e48247215484ca0c8d996833c43a5291b0380c97607c86f4ab2784e692673a1da012ac4fec2713d156a49",
+ "Name": "matter_fp2_to_g2_29",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e07265d2762e8e398c83efe1c43452d91b90b7a4271c09ff693c83745a6c01b73561ffe3da9300c8e7e1602dbaab0bc000000000000000000000000000000000375579c16a167fd9f9f61d5177705f157aa0df3451971029a9444432db119fb33b8c07de33fc822eab46ed4ae47cf82",
+ "Expected": "000000000000000000000000000000000a06ea8e644d2d762520ad956d41ac2086a588450bc34f6d070b86fdfd73cd0734341a751d823935a009b7517770f86e00000000000000000000000000000000140ef0d6a0482537da7db8d775ac3c4a93b16c15fbe4602b5b1843ce757aada5f7776a74151d0bcf760f7284d4ffe56c000000000000000000000000000000000873c90f56a2b99da2f0a1528b8e376a5912f9cd81a159379ad70b7c10e6ebb7fea0a90d65543d968a34ebd539372e89000000000000000000000000000000000b05ff57079386e4e18e73cbff5f7b0efa329ef7355f083e8be258922203240dbb8926f7d11c22ab4c16d1df4bcbb600",
+ "Name": "matter_fp2_to_g2_30",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aaa37576af2101d090139f562edc2a6e7169b0150af831d053a3a87a3a5518889a51871e02deb3ec154ccbe9dda46df00000000000000000000000000000000158edaeb58b99d9442d608bc8e6024365e9a81e0aa23bbbd466c9ccc8d29415352a153e1f852666505ef097122592ecb",
+ "Expected": "000000000000000000000000000000000e9d6f9e83a2584f2cdacc4711085bd251e060f8c87ff7538ce474d663c6f23361c88971c9da589586e754ed69699c820000000000000000000000000000000003fa90cc1dd81b815704e15c0448bd0e8e8d0cd7ad51237a25d4b8a0f78f532b18ec30a108930b7407b7486aad9824de0000000000000000000000000000000000cb97bce1f75b1df5a4b52745014eb632d2d2230e52a9767e3dfd76754e98252ca81ce274b92a2947f6a65fedbaa3e400000000000000000000000000000000090edabb37f411fae1764792083c8c7412fb470833a9f7399fb312c58687d4afbdc622ecf9d74cdfa3ea87382adcdd5f",
+ "Name": "matter_fp2_to_g2_31",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012bfaf34a8111a01d213f9a9fc90846335cda978b3df23de99cb7b764cf5db1a816f66adad1319aa7e25c0ab89e7de740000000000000000000000000000000000fed118654a128735fd39ffd3b381ad2d71479054b6bccc04dd58fbeed9b255ce2b925e2141a96a12edc3a19188d1f5",
+ "Expected": "000000000000000000000000000000000cd234fcc729a4206233e46875a557027cb52c96322386b56d6e50d95dd9d23b6f8936ddc6f8475b1076a855c1ae23510000000000000000000000000000000010a774120f607bf9ad2d7bc498536cc9d35cefe384f88a2439a75f1a4f6a9e4b4253daff0d2c91b5915ee0e9a99b4582000000000000000000000000000000001496e7181495114abc0314f580c16038a04a8dab43b5564d518dba5f5e48112ce9daca4b16b6ad51c3af54ec9ce915d20000000000000000000000000000000002c61691a96a2120663c726d7fba3ed37524b58c92a024c15fccc659d1d2cdce077ba233a0d4419a6f237ee4e09abf52",
+ "Name": "matter_fp2_to_g2_32",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b693fe53cbcd6f8d8c98900be1f9c85966cc644f0a900c70826c6573ee801ce7863a0b170ce0ef168fb1f0ea484b276000000000000000000000000000000000c6bd688fb883f3097f8b6fd6fd0bc5acef9341f21d62a0706fb3625a70459c45a5200ee36a3802d4bb4912030bfcfc7",
+ "Expected": "00000000000000000000000000000000011cd454f16209b0b7040c744291f2df465ebc786946ce3cde77fe4d4bcc4b60a51573c45b8bb2d209da69107613764b0000000000000000000000000000000018a026f29fc2f81e82015ef8610b4396f2e3514ab1a213356953804d585c5cd6a3c5cffbf70d63d9dfca50129021f0e60000000000000000000000000000000015bdcc8c139e636b05ba7376c1ced4a183eb465df53b1996f4ddc8cbf42cdff4ae2bbc2d24831a8ec8b1134cff4444ee0000000000000000000000000000000017671fc3995babcd2c0a1d2a71c417fea84e29df67fa1096fe6d3ec77c45b64fb8da6ed08a57726ab314fb860899961d",
+ "Name": "matter_fp2_to_g2_33",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ba7f82549ebfdc7f4959dc67cebde4720d76d5d4742af730d45d614133f0a7b0ae7b61ba5b914a997d9dde83b77b031000000000000000000000000000000000b4acd8c203ebd8e3ce12b10cc791b9a4183440309f24bbd60cb2991712c792ecac64d3f878cbe407fa8ca0d09548acb",
+ "Expected": "00000000000000000000000000000000156d8823c37c81d8f03c0b2e61a2342aab6e6c9db36cadc9eb741e085de711e9fda08ca78f21753c4fdd8cec059b6c2800000000000000000000000000000000064d4fc2584c78f1e92f808d4457070b0470eb8de9d558885bba8b03efd8d8e195e4923d8e3382481a0ecee905371ae10000000000000000000000000000000008f1dc4d2ba12e7e3e1b0ef3855df4dbf29468bc99d5cb29fa3058a535af2ba038396bccaa238bba6d538498565c2809000000000000000000000000000000000fc9839b6ee876f7846b5086d487360b8faf133b6f5bd2dbc92a7fe2261b91b15aef8d90c227cd5f8ec05e32d807e022",
+ "Name": "matter_fp2_to_g2_34",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000145f6f774d943a1bb753d5d4876b1a88a4021cb6a6607c0efb07eef2f90ba2a90a6e9dc94586de35f6047332553ce7b5000000000000000000000000000000000b892f1c8d001c8aeddf845c3845c51f2e06c3c77e543e9721d797951b6211a869da97325b569e0de35cf3beda853ac2",
+ "Expected": "000000000000000000000000000000000d40f1c25dd57e36ed305276d4505cb250d2d9da0d5b954fe5e396b2c17a5399613243216586cedb19340e80f898873800000000000000000000000000000000063367c4a622fc925319fc6d119d8592f40f126ae05eed86ee5e4f6707b1d234c747e698c40f292dcb82ac5fe74ea80c00000000000000000000000000000000199ddbb5d4b6cd0fb9225a72c53f4596cf2597de63da56f4a9a18be8321a982de17367b0f3d794fa799657dd8ca10c5f000000000000000000000000000000000f1ed84e4fd958547d40cd2dbf16e2da4cb6d0d02763441067221890ae27ea1f689c26c900b695464ededf083667146d",
+ "Name": "matter_fp2_to_g2_35",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001878e791993186ab76f785b2c6b0fe08588b048007c66fc00c695b55bd17b37bdba71f34ddf75ac441a0c2687711b2990000000000000000000000000000000016598f630f72a0e1f39678e1d0ec6530c4795d7565c5d026fea2389ec0ceb51b434b532466fbb1c92c1c958041283baf",
+ "Expected": "000000000000000000000000000000000ee446310185ce76e31c13e4ca6c43166d971d9b9c539c7d0e8dd8ebbbdd9249922cb674bf6ad6840c203a5e208911fc00000000000000000000000000000000037344752896cff03bc39a9d09757a83c15fbd90f8bc1d8d58dca9b23bc00fa2b0f3f0bd7c9ed857d285825d40afde450000000000000000000000000000000003ef77f0220d1caa7538ecaef1ae2924ac1a180f11004034fc118aeac464fe1ce684b5fc90dae3370e3f79619889f3d7000000000000000000000000000000000fdfa434e7bedec071a1a333088d06299f55735f085a1e907a1c71c312bbb8d27ffa7de7ac69d421ebd675c4afd37594",
+ "Name": "matter_fp2_to_g2_36",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000134725b4d43cb87d2e4d3c43ca98b8df257acfa612ccd61dc0aa1ca749f20bd42c38d933d39f8c3c1a14dd8fec43329200000000000000000000000000000000070ad61a7f5ff9f0b4e7483f5d56b0f315b5f6545b194565ebcf8f0b8d78519ec113af6d70550888be4d661a8403a036",
+ "Expected": "0000000000000000000000000000000000ac465de3832452edcead434729be73be90785158617b5ec3ad53b12653e43721eda7de6742dc51d4d4bb58a291999f00000000000000000000000000000000147c39a5c162afa1f8eef400cfa1bdbe5436bc59d93973f50384022962f828ac934a4f88ab7c3d505b0bc3bb002f5efe00000000000000000000000000000000141bcdad53845a7eb2ec08189a55445059dad24ae5d39fedce869791aa28459f05a6cdf9575676cc6f3dd7d6faf077240000000000000000000000000000000010e9f539a9ced860661472f53147d0347927f065ec09bc32e00c5bc157b07f8b41b05aa4e0eedd1f73c7a287b2d0e5ab",
+ "Name": "matter_fp2_to_g2_37",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000179bc843fecfe713f6e3ccdc8ca0f48759459b675c8b96f5403e1f6da92c2d60449638f564ce179373bce473669965d700000000000000000000000000000000082bd89b49aa62c94ecd4244b3077421569c71efccc62aed3d4bd492bdfe57c0d2cced568df5992a196a7b71bcbe5e3e",
+ "Expected": "0000000000000000000000000000000016479eca30f48bfdaba4c8afca63ddbf59fe3367b2d3c17d15a5869dd2956fc67ebde964530926598cdcb62cfc993d32000000000000000000000000000000000650b4fd24ffbb953ccdb1b112799149d29e2377ee233b9ac97f4db432da63c98b8aad751f6060d04fe1f9262b75fca50000000000000000000000000000000004568dc0b9b430596f2fa59291ea6f923d552683ab9ab93000788145cd7c468c5576efd981c9ecee2ee0c16eca1ecdbe00000000000000000000000000000000154af1490463930d6b8261aa1d066eeda6d65b742cb53c65348e5cd766d86982a1489ad191d1b126233f193d24823b9c",
+ "Name": "matter_fp2_to_g2_38",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fb118c86e974734fc434c3bcb783e4a7f9251d9fcfb9f4419529354c8a7a3d9f2215de2d1b9f0927b185c5b4db838b60000000000000000000000000000000004da0ce78f3068bebd0a59bc2e41e7ade737375f07d6c9ce962be022856c569a33e8bd6ae60c4bb1b53b3ffc2dcc2aee",
+ "Expected": "0000000000000000000000000000000000df692ca763a74877352af3609c8cdbc184eb71bd35fd86334cb88543637b40b3adbb5802dcd7b88f4d722b566aba7700000000000000000000000000000000181495e709d1617f2d912f43487ad3920ac5f8e47395ec4b58bcf0b2d986c674a0c7838830a039bfb5bb59cd2fee2f5c000000000000000000000000000000000d20b482dd8aad583bd5d08ba9c61b3e954f022d48f9f4f62ddc9f5015ac71dab7d206b1d8b885d5e605519bd33d93a20000000000000000000000000000000010d3deccb9364ee386eb35c7117bab373a76d024627b8a031f96465d5f75b029fa992e29ad4a170c4473cd1df585429b",
+ "Name": "matter_fp2_to_g2_39",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001f43b86ec24ad40552dc4874a632b4ff4663eeefe1a8c613a19a798a0ebe321a3d543e2df28277944a941b4586ac770000000000000000000000000000000000baaca6bc34feac790807b5eb5fd173c86c12803b76b50be59b2707df765bd10eb467effe34f8dc3e1e79df8a54fde38",
+ "Expected": "000000000000000000000000000000000a007c914ed40c7f2719fc70def0d4752cbaa775cedae9365c5afb61a5e1a2854f9e1ce19af9fc85bfbfd2c33f5bf095000000000000000000000000000000000d85b0d173c25c2915fee429d2468a9eae01ba43c0f1a661f2ef83c1acd726865c00c40ccbc3aae306f93074e5e7858e000000000000000000000000000000000b3df302ec532c8100c121c9a3455392c713ec60de1f9572b040b0966f8ffb888e8cd768dcf6d63d4835a52d13a730c0000000000000000000000000000000001123c43dda8717d03fbc02fa53c4b1c9a931db6b274162cfb02ef5eec602bd8161dedc37c7f6217c8e82236f06e49e2e",
+ "Name": "matter_fp2_to_g2_40",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005e4751707f3ea7bc7a74d80eff27a0d65cea0c3d2e793425e79cdb0c41e6ad0cfcdbb4de604637c41dbaf30a1e816e60000000000000000000000000000000008f69021794d93826f8207b96d49214b46dfb1778603634a9f5194e92481465702a8be1bc49a7bb57527fe6f963ae04d",
+ "Expected": "0000000000000000000000000000000016d8d9b1b59a22fd830f88b9850576488f75672a87ccb766e52da77f187a8e66071130c7e71f86675f8379b2a8802c4b000000000000000000000000000000000aa4ca84aa23f01ec536ffa25c4b7a6c822f588bc75a4a72ed9237c0588ab892c8474a0f23afc7ff0dbc3b08f8e35b60000000000000000000000000000000001425e759e2537d9e5f0f356ff1d38128eff3a771fa661a839f7a8d0f548347438574ef7d592cd4273ef9b7269c9c5d7f0000000000000000000000000000000012cf1c67d1ce244ae22eec0bf4a400a0f356b9dd075d87a6e61941933872d7c0e42c1d238b2c1704d2cdb2df75169f39",
+ "Name": "matter_fp2_to_g2_41",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000116988a869cf552b2440e16569d8b6e30c6b15430855c4d6bbf80683c5497291bac7999c1f8f08f494fcb4a989451c3b000000000000000000000000000000000e26058d72875fd3d852aa4139f71d35e1edb58242a4939da7986645117d027d20baf85770fc909d537524244da59ce7",
+ "Expected": "0000000000000000000000000000000017f6e2743cb30fb93816d0dc802c24509315363c3652b0244e1395cb9200efb4d7b9fa7642e8d165d28a00740f1a83be000000000000000000000000000000001483644fffd3989ac98cea71843e87b8e446a3d497630419afe99b3f1729a831fa6a49bf763b0c410cfc5390ac4ac1db0000000000000000000000000000000018ad20ae5012266d771b2c86f891f498c2e90a7df19561be240319edc1fbfb316948fb3f8a6b0e3720676b076eb372e10000000000000000000000000000000012f404211899d8fc1221ab5b82db9042ad37e63348871e5ac6cdbddacda0a564888f89d22712069b6096b58c5935edd2",
+ "Name": "matter_fp2_to_g2_42",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000078c6cf89561533810b583a88149586b29da5228ced10a75257b2587904217f63499d8b9ad2d536617247e12f8d1657d0000000000000000000000000000000005b016ede9d892fbd7aea4e8ed0f1eab70713557311481735a91308fabf76fe71e44a06dc23ea66ac5d831e982f401b1",
+ "Expected": "000000000000000000000000000000000d4d78f992f12aefb0e3a6b18fbe2411108327a9befe4a822618fecca4def3169972b4f1fb254cc4656a676529d554ad00000000000000000000000000000000145ef33250240a5c9434d4b2cf2404d9e7cc51b55e482ebc6a8aed85caa21ed00623b3cb2d76ce2d96b2f346d395dfc40000000000000000000000000000000011af2ee2514c58078da335c0273cd18b98d1ac6f0e67890677403f71b0e06863fc72611c0cfba39ac894ae500edbdbae00000000000000000000000000000000186863e7c24cbeb45f7a66b5dddc9b57c7e22c5139aa6bdb82e77cd8182bb8d2fb7bddd7d3516b5422f92e08d02606b5",
+ "Name": "matter_fp2_to_g2_43",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007160f36f0e5c4ccbcc7900c6504cd86fd6fd700bfa79af69841e4a6127eaad467ccc93c66baf7d767c3fdb1f31c527a00000000000000000000000000000000043fe62b0b9be76a375f3be0d6ec891d5bf5f2982cb2390125ff8d5db57b6b18c5616c526102e4f615963d601d13f122",
+ "Expected": "0000000000000000000000000000000002af4a301e90c71eb375110e7fe23f8f05e2ede86b1a9b240e8d1d4d70e96f1dc3640fca7ebbcde9918deb91f3592de600000000000000000000000000000000058b5f36cfb6b0adb14b397dee4c3769c7446426eb5719aef4965cde2dcb70e6f2fa60101a5f03517c0040093453d092000000000000000000000000000000000f77b560469cd42c5cf3458ae13020c6678af3cddf9bc559372d12bc5d6b930795e1eb09f27cfdb8215f39fb2a11b30c0000000000000000000000000000000003308985946c742af7bd7d29abc2517ff1d225607b5f11fc66695cefabd8f25e294ebdb7339949d6bc4d98db19533966",
+ "Name": "matter_fp2_to_g2_44",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b9590b1d0d292d9967d759060a551f4e8e4c1c0066a9a3c0be515085847fa26b77462e3bae9e2621f28e01f897df0be0000000000000000000000000000000006ee7c459bb4da96e87eb1d39bd7368de5f60104f85b7b4bcdd7761ce08d48babe1bf5e765282779803bfa972d0e668f",
+ "Expected": "00000000000000000000000000000000093c936d57135b25900bd5dd55cd579aa8b85b9c1b5e8dac6196c4450b624734d9bfc3fda499cedf2e877d79f2da650b000000000000000000000000000000001832306d3ac1c1c61bdaa73c9b6e9c2ccb484c3baa1de6a217a2884c72b72618e864f75fcc2dfaca358181ecbd3347980000000000000000000000000000000002b2e5ff1ee02657fa88c7d6f23cd4c0465152a9daad8479b4b68c97930acb22e4e2eb0011ec4062b8ec46991a7cc630000000000000000000000000000000000712543547e9d24cc78d1c2e3fbe0b51222185f4c6e513256d1ee066ba50beee20321bfd60462e2587c375a0e9395715",
+ "Name": "matter_fp2_to_g2_45",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000044612b42a2baa9d3e1d187b2a4e048773b4851bbd7d4025e0f7f61abee703b5a563397da4515c7379397dcde698228a00000000000000000000000000000000014cbff1000bc0f9b394b18e81124dc81f80e291e841dae6e96e0c86a6f618b9f6aa6103e0e7582e5136319a4dac92fb",
+ "Expected": "000000000000000000000000000000000f52e2f8dff9a93b2985d5c2b8b980e4869af53ce55aa48bc1c9295e557e3b5ff78896e5e6342c2d535d18b11950bf390000000000000000000000000000000013d36cf2805d350c5b748e639d20e592deb4c5bcde99a94fb539dc56d48a862151b925314f21dce4c9130b32e44f54060000000000000000000000000000000017728f485d881b861f626c9de8b3df7d807b266de6cf8dfcba262f40a6248fb5e6506d11e88f460f0b5f1a1907ae5f3e000000000000000000000000000000000c0ab998f63f861c82106dc3ed5ea11a16e98139e8686f8442047a1cf9ac48c3d34b5129263767830144e9a13d4a1f44",
+ "Name": "matter_fp2_to_g2_46",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013da827dd718d3736cfcec53f034d34bce253bc91f7cfd6cd2666819bdebbfc43a9363f82bf4b580a7739b5dda9c94360000000000000000000000000000000010e94039f37d218ad393e88a226dd324a37e8d5352dedf6d84fa2ed2cab2f874ccc5ce94599950f91b8dd6d6c8b84aba",
+ "Expected": "0000000000000000000000000000000003463d887c4d0aaa21acaa308d77f2c7e13d10157efa9ec3fb1586a8db5ff1a9e807c91c86afc4df34c9fcf06e8561d700000000000000000000000000000000128a81efb9f30ed811ea3163c71b6a46ba2cbdbd3a9f93cb8d0f518747cc860431c6e93bdcdf36d00f83838965da4b50000000000000000000000000000000001777802b7c41111b38da3fd8092c280b4925827b2c1592f779a4ddca71f8268858855c413fd5c0057a652155261d75ba000000000000000000000000000000000c88b522d6dc2000cfbb7052e141ddfe15c6cd7fddc970edc4afc36fc59e7f8e31415706a8121e8e84348be0b50d0d88",
+ "Name": "matter_fp2_to_g2_47",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000010416da7cfbed2768c77b80957053030d49d535b21a8a3297ab257dee0463c91b87a9e571b86bd874522149d9af0c2900000000000000000000000000000000197ef97f6d02a51b80e6f5629e88a3c60399bcc4a358ab103dac3a55a5877482558abed922585a1ce3228ffb507679b4",
+ "Expected": "0000000000000000000000000000000014be96cfc0dbe09155ac8d8233b71ed584153e279b2b2be88471eb653aa4913fd2c33947547c61f7fd8bedbb552a8b1b00000000000000000000000000000000146b9a0011260e2646920894cf405bdebb101db12da7849b30868655fb5f972113cdf2fc322cc246d3dbd9f20b98fe2f00000000000000000000000000000000104bc20e104da5173dcff3e195f80960819a0d64e922bb484c2739c4b7c22535f7faeb1c85188aa853277740b389eac90000000000000000000000000000000019f5aec599f9ec286aefe48eedca3f929ac6c758c231182b92dc965d6ac1f3db53d93f57d733ca8425a5dde070b0dfa8",
+ "Name": "matter_fp2_to_g2_48",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000025f1ac90f5b0748d57d8f7a928be875c5712801f70af0d057546228c1bf83d3a207884c0d66d0b5dbcaa736bfe0aa10000000000000000000000000000000017f66b472b36717ee0902d685c808bb5f190bbcb2c51d067f1cbec64669f10199a5868d7181dcec0498fcc71f5acaf79",
+ "Expected": "0000000000000000000000000000000004ca0149527817b4df0f08acabd4e8c6329c0d1bd9f2e8211cbea25d69b84009ef158c770f948fd67e4609ccadc938680000000000000000000000000000000004101b351e2a9d34042291f38a289d8575872104bcf76f60bf888c60cca5101c34c247da30f7a8db4f0cf2f32abd302c00000000000000000000000000000000167e668de3207ddc60b8a5d5d246bf2f63ceae3bcbc4309e73eebf4d4234c2785bb13e4d5d8fff9c5f205e4fb942a2f6000000000000000000000000000000000491b965ed005065abdac53e3065781f2fd23f6159debc64f01c9f62073c651da33c05ed84617efcb5ffe08ce05e3b2c",
+ "Name": "matter_fp2_to_g2_49",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003f2dd27e3f0ab503a8752c0802ee14c655271e8cfbc734905b4331fb4e70cdfe291ff71053fbaf91680b1dd108f458f000000000000000000000000000000000c62014b7694a3e81370761e0adcc32430547a1bbe33746637e7762dc24f8d04b4bb955f17ca901659482c622d777642",
+ "Expected": "000000000000000000000000000000001541320fb6f8a8c3c67278a7ad05ae7927d3555ad562bc8addb54c6693c51fb1c7355d2e74ff10f6bc3eb182d8f5b88b00000000000000000000000000000000172b65b110935b116ee683c8680ef0a660afdee43b9b8fce08ef3a70b352f8710c06b820348c338fb903a165cc5376da000000000000000000000000000000000df529b0e274e2e8993dd89ffef487aff23d31f502a19dd7d383de08fc77f1308a59ac5bf7cc899e81d377b2422187850000000000000000000000000000000010b40c9063d174b358637ab710d15c80d9230a1b3a056cfac4d583ad8c5b79c3d9bf22a1b0a4e0f629cd09ff7586f886",
+ "Name": "matter_fp2_to_g2_50",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014d1491a45b4b0914a6cb2e4dc7de9d0962f5c175cd571057cae1e17d2c943954d119690ea14f5815f858d277a9ad828000000000000000000000000000000001650771e0f7b33d235f229b7d49a7a5a0f00f78e5f4abaa70f39ec452370198a8532b5873e41f17c449f9c565e6adea5",
+ "Expected": "000000000000000000000000000000000978ff68d94d33703488298658cf2c1b6034d3d8d21c175d71a0545bc2f99eaaf131f061f3e4f55622668e686e691f53000000000000000000000000000000001124804b252f8187178435761897d00c43cf67b588ca69f97c20b0ffad3ed94acc2c0f85f900713dd6ee9f38e5ca94490000000000000000000000000000000010ca2a8ce71b9a096c132c4a060a17365475b6556d4fc6284266ae787e217b3ceaa3a32bdf751375eaf6ab49800132fd000000000000000000000000000000000a43b435b116d9480497f6b2e1bb377550cb1a7ad59e4214bffacd517afc6b7bf91112fe57b17a02a86876ea07361bca",
+ "Name": "matter_fp2_to_g2_51",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aeb244909654b3e1df7cbeccf297223be57c2f514474edf0740dff48dcd5898b6e49eb65c787aa56ef79778249f4e07000000000000000000000000000000001007c89a66dab07f54313db8682f9e829baea229b030b4514d9c93686747207939c50a198e83ac2cf50315e02642a24f",
+ "Expected": "000000000000000000000000000000000c3d87b1b78fab65cfc853304c682b39b6ec2b4ed005e9108f69daee5aecbd586c9818c37cdee865ba53eab9302320ce00000000000000000000000000000000062a7203cd2fd04a957cac8b6b6bb51e635ed7165c547ace10f93a32b7f37747a2e63d5767d966684409a6c748d4ee6c000000000000000000000000000000000526b44af8157dd68725aa8743684e020c1e385af7413c9dcebb320568663d18b6f29edea26f2628358852b794ffcc8e00000000000000000000000000000000098126f486ff55c21f64421e85b09a1b54f42d3499dc0e198db6f3bf7dd8476cad97c02b5b366e5ea20d8f83cc223f7c",
+ "Name": "matter_fp2_to_g2_52",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000398d86b5206bae4ceef0bcc6335b1f6bf5d17863ef3a5e8463aaa69d9f73f8227263964659d4b770d6d9813f9399b9d00000000000000000000000000000000096bd18be1176e16a0d80e60f7d7ec9d3b6162f683440e3cde70082a73605da3783c8a058bf76d7e25056f5cd95c31ed",
+ "Expected": "000000000000000000000000000000000f3e76e7d1cadfaad08d16457b02d89c40c157225eec7916d306faca8dbda008f41792888c647dff1acb4d4ba3b43c4900000000000000000000000000000000132bf730456e2afe745a58cdee689e37223292bf682d5b7dafa7df99e40d385559d0b3161bdda0bf5173c43ee46412dd00000000000000000000000000000000141b36ff6890e35db0054358bc0731b3aa0efac1a247a51daeff3515746456216975f44769174a4be41c109d35e4be33000000000000000000000000000000000ca401ee1addff8fe87b600e057ae34ba297886f92c5be8a8c00b360ada71831e31bc4ea1c309c7da31cb28d1011ecad",
+ "Name": "matter_fp2_to_g2_53",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004ca5cb60c32edfa385baa911ccb7fd1f383824c22b945944b0f3f7011db8c123efd8fa70e4fe699d40c6716021f0151000000000000000000000000000000001339adb0dd8d83574c2008f0a7ed001b0808d2fb639b5e57e1d293884247d5c66c948ecc60caeea7bf440a3a44ed296d",
+ "Expected": "0000000000000000000000000000000009d0af77517b654ad97de3ee1dbf69ec1eee901facd0f8c39b4af393d0e63957292a7529b461f7fa58909acad32ba3a2000000000000000000000000000000000fda17cd878ec0f8c294daec1bd1d56c63e875b002a81c9c41146dbb564bab6e4eae2717c9fd718af1ba816a1526e8fa0000000000000000000000000000000017563b7ff22b50b6d9e24b1e0d89ca5c72e68d4d3cc24cce36856191111d087c3dfb392070462dc7850ef5a1422931c600000000000000000000000000000000020001fcff638504055ba35230b360e6d3cb5777b959c194d6f9b038b58d3ead0b82b28bb215378abd85d357b85ea260",
+ "Name": "matter_fp2_to_g2_54",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000089211892a61202b1ad3a85aab9f08f8d028f3e3deb16c1de4d62c1a403fa63c6dbbdf8cec37f0a9d6f346b1c7ee179d0000000000000000000000000000000012a9fc2070b326f4d7e64804b3a2e977f4bb36b6a4afcf27252af757d8535e8172a99dc909fad5a3ff8df23d6d6c5948",
+ "Expected": "0000000000000000000000000000000000d51c77c2443f00d965c0d7ec9b5a8a8003c2a77b0ffce3e47bcb55420e8690a9c2ba9235b62a4b351d79d216a3aad40000000000000000000000000000000013cd46e3ee6cbb3bfb771ee30b5f5faf0a64a9efa1f8fc57024c83ad07a9b25e513f211ea604cfdf319dc42bf4c067d300000000000000000000000000000000009fbe1fffc67220067c948e0c80de23795e045fbe8031c9010eaa69356ffd8e5741cfe12731ec13aa236630f1b1dab4000000000000000000000000000000000e5ecdf808d10d47f041e4b078e79b32520ce9623b50059a3bd8b59daebf9103c31425659ecbaebfb2384d1c2f1b400d",
+ "Name": "matter_fp2_to_g2_55",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b37365748fdb21fcb46f94edf86c586f17d0e042c4683e68c6cb83e7c0ed2c30ed260c15af2c9dce77bb705debfa7590000000000000000000000000000000010d7c02c6c1ba3cf6ac09a05dfe043905e1a7eb32b67f2e8a5dfe82eaca66ef46cce43aaadeff58ca85345dd0d3bf3cb",
+ "Expected": "000000000000000000000000000000000f3e4d2559261829c0f4816f8b571170de1f74d75d74997cba56fdad42932db73504691f9e001f5b4604705a8c1a38e40000000000000000000000000000000018c72136bc7d3050ee693270668e706ebf70f990e447ecc6153a10625cccc9deaf5ae82d2a656b1376bf33b1c1fdc2c9000000000000000000000000000000001754f2725bfa76e92a74ad5b520ec2aa82a1f86e8623a054ebba489adfc9e71d1f14d4692ff9fdd8acc3d768b67e1b7000000000000000000000000000000000096f1373434a8822569cba0679dbd2abf619bd9a8c73e54e078688d4e2615d45431ac8cf3da5e15a83fe77d14b339e49",
+ "Name": "matter_fp2_to_g2_56",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000aeee59421c8ee65f8070b9d036e6bacb39dd2537d02960a3a57da4f0985cc7b27784d60fc1613f5a83c34d2250395c1000000000000000000000000000000001715ddcbaed0a05b38b1c820724405a713cc0215a4c497892f00746c0f9af28b440a3686178d9bfcd41944a224311306",
+ "Expected": "0000000000000000000000000000000018d515b8c99f541c7dd448c3564c1909b84517b662d6a2d1176d3bf5e70abc0a2995c73ae3f1614bfed2f64229e173e80000000000000000000000000000000012126ab671420933cc4fa9206311200cc5241ca3eec54f5d97a426a72642bdde32a65c79735446779cd1744d112d544100000000000000000000000000000000190d836312ffb0d6bf493f4c942263922659abec46ac4de639efc311753148b445509f808c2fd813729b1bd96e0e663f0000000000000000000000000000000006494f9a451460ac658ec17710bef79d59b6e0fca049804c0954c5fc472bbef520f75d34408ccc62cf2da3deeb79acc2",
+ "Name": "matter_fp2_to_g2_57",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ca4b3e1a8351057ba4a2ffaf0cdf1c3c0717ccfe26433f6c40e2cc29e32ed884f63d25979580fb555a5a86c9147bcb00000000000000000000000000000000010c1db593af38aa14ca9dd588f54b219ff1fc9edd25b3d16c595662ffa7939879244326b14d978e0dfdd25e37776964c",
+ "Expected": "00000000000000000000000000000000173fa567aa952bfaa9a60b8232a185475cbb36761ebef49ea5fce900a06043d0e2c1b6024e40eadc9f4bf04b077201450000000000000000000000000000000010fdc32ff84f79fe39351cee1ed6b67dbcf2956020e2518d5bb5b367b61f86f1bce36f75516d9551d74cc3a567e6c2be0000000000000000000000000000000007abdff8a8967eccc4de6b4ce142173841c0e8399f5a67dcf0f7b5e5b4133391b44bf4d41d3ae3426839b19aa4c5d40c000000000000000000000000000000000c99f160062566418c09f10eb80f005f2c8c12825435f354f1d65bec0322e9b8ee968c009a84ba792a7ee7334b32bb3d",
+ "Name": "matter_fp2_to_g2_58",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017cd94e7e672f0dba9a3c1db742d87cb18b9401e8311c4badc24f811a8f40c27942da6485807701c1a12da58076c756b0000000000000000000000000000000012f6de4ac9883e78f9d658cede4c70b44bac6b4c9734cbf24298ddf0df0cf54164aca245d8e313be4aca66ba3cab5d70",
+ "Expected": "0000000000000000000000000000000019dc92f1da66d0855ebc8e7a2ddec623a2f843a97c7385364a631671be7ee3387a0f98940b5a51c8d9e23eb27e3133b00000000000000000000000000000000008493903c5c68b2847869b8c3b0fa9b8ba15bf1f11a40a29e6e82942e2910901044254cc8e8c3c3bf56e1f1b6dab7e86000000000000000000000000000000000bd3c1e302a191094059a6493e59a11ab05a49faf333f36f7680ec9b1043e59dfd7f0fabe9f334b97cd638dbb8bb664b00000000000000000000000000000000141c9b07ff33b6ab55b320dda6be54320082f0057c446236cf3d3a51e674c26a5241f2c702d9989adbae9045942eeab6",
+ "Name": "matter_fp2_to_g2_59",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001b2843d9852feae3145b242cd0999877c07785bc72cc2626f388dca32edfb112bb90f9aefd6953eb15a0babe748573d000000000000000000000000000000000a69bfe809a67ee853cb96b5a7a72798748cda56936e5664d509001544539730f57a7541ecd2396c9225818b9dbfa3c6",
+ "Expected": "000000000000000000000000000000000d0922466c358cfd756727e134b5e64d211244587e4eea036f0959e78570dce3ee264c703cc356cde20637c7560369340000000000000000000000000000000011a66d618f79fb662ac2b2d3b50750a5567e36d7092dfcc72d8f340c04df75ecc0ce4a01b410ea775dc548b8dc66c3d8000000000000000000000000000000000cc49cf4be5e2df6b43054092afa2d6acd66f5a43ef0667f6a2d660beb7fec70558ce02d7acbcd090df91fe833326718000000000000000000000000000000001270b0519db083f903a3dbe0b1b1bd5ce0b0059ea2c2c50335dd80b4bf154fc23a3de1ea753b0e279145254d8e5bd045",
+ "Name": "matter_fp2_to_g2_60",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002479a989dbf27141bd9f467447218dfa6ef60781a7231f089d5f1f1d8dca2ce9606a75c09f63f37f9cc1ee61dceb32500000000000000000000000000000000037c2f1b96170f6847138232bac663e4940bca602717c877f58ff7f5259778246085d499ec6bbeaade18f738df333cc7",
+ "Expected": "0000000000000000000000000000000007826398b4ec35ab58ba9fda5c15ada2a41d3854677172ef6a4a54087b64d0f73fc875ad62236eb7fdcbd94f14c8895b0000000000000000000000000000000016b14fa92de5f6e43988829ea2f851746efd6680b0ea1283264f803c8ffbe85a343bdd42225caefd1b94b8b311d2f4950000000000000000000000000000000018797093ff82bc10e6db60b1da50b9a60da01d67673e9bee8c7af2bfa2d57f409f7b06f53944938e5c73b049c2d3c6500000000000000000000000000000000000c66dcc3d30f35c21b8a9369c8f6de28af404e8b30d3c9a7f09c461b0272ba6d5a29e716012536dbeac1d9672af8427",
+ "Name": "matter_fp2_to_g2_61",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e6fcc48312831b910e52aebbf19869b3b32f05db8310b68905bb244ab784df5732db2e72183de5d231d803d92aacff9000000000000000000000000000000000f61f9e52fe3afc2a6bf12e420cebf83bc55a449d6a167779e5b6ba3281c51d790a045643aa75f2516eaf6ae2a816ac4",
+ "Expected": "00000000000000000000000000000000191aacce60a1a83f2c453fe196bbe5839a3a1178b147580435f7de8a2b0b4f65b3e280ac7a67570aba0fdbce6c11ad9700000000000000000000000000000000075ddd6b256f53a6ae6758a5158508540aa99b78ca069378f0ae3f5621ec24b9acff1f9b61d378334a63682a33fb0561000000000000000000000000000000000b06e11c9f858446fcc90c69d05cc26c33bafed0feda19adbd838c9c24bbf567b673110a1b248d0ee97fc682e561298e0000000000000000000000000000000018c75dc203493e12e1523af50f85ed648130ce5d3e9757f713850c867cc95c7acbb66c9733dc4f53d6a0e64bfaad5832",
+ "Name": "matter_fp2_to_g2_62",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018efc6d366d79a09b7d56c81c17c2eec2ef7395fdb5991f41273329cdcf4537d342bddd83c3994a40d5c18f6afa054c600000000000000000000000000000000127021ce28627a9d6a492720f728acef3b38c12b951f70a932c7fc0ce3f5b6c80783351cec55d7d1bc4ab964bb4913b2",
+ "Expected": "0000000000000000000000000000000012931f51430bea6e96f8ec456ce6b3c9e058b0bd3bbfbfe8b6e84fd6110c3bbbe0001018064e8981797f9c93713a0e4400000000000000000000000000000000196b6093dd2276098853ef2bfac84f0cad06b67a12484e98915dcc756310b818d8136954de1b602eb825ab29a143cf4b0000000000000000000000000000000008284beaa877b25374571dccb218c401cd905b351dd96700853f01920e409d11c4e440e90dc175cdf0fa807cb9d1e93a00000000000000000000000000000000063c6c238485c291fbb60bd2824154a9e23dea374292966d271ae94875391b7ceeee813e3fb9504223bb86f0ea3b6cb4",
+ "Name": "matter_fp2_to_g2_63",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a0277228ab4e880c12f957a6fcdfe49e2155083f3f93d3f00c68622415cd1f5bae183b7df9e08328a8139392772cdc6000000000000000000000000000000000de0ab426e56029790a5ff72f34da97e11c028dc5d31e448c49ede004102804d2bcc36d509640247a4c8bfdf5104a781",
+ "Expected": "0000000000000000000000000000000000f7bd0705cc4ea96ca38314cb85963044164b83a506ffeaea6e5eb8f7c4967cab1f1658f33b5435191427aaf9605bbb0000000000000000000000000000000007a93e2a5c118aff6ceaf2370ddad52a82854946ae595d384ee0b2b4935a574ba758736d84b0ae792f998ec6a707dfbe00000000000000000000000000000000090936add00fe5c7556610b28ecb4466ffc37b95b5cab43e072a585920b3cbe70faad01ef75d1dcb4f7d00d900bd99600000000000000000000000000000000006ae82539c68b7af3143e23229fe320924472c2b3e15a2e27e94cba674d30f083dce94706da094435c53285a43f89e56",
+ "Name": "matter_fp2_to_g2_64",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000170b243c5aa49a0134bf3d6494cc1e55a1c6ebefc6117eca3b343a48ef0a2b077c443ec5b9201b198df015a38e66b7910000000000000000000000000000000019a8ac8a3be1d45318801bb0a654963b312540d24aafec46bb7661cebeec27b0b345275fd53c041d02b1ebfa27fc3854",
+ "Expected": "00000000000000000000000000000000024c1b869fc13191b71d7159a07e869f1b13c11c73231b82e9bd0a7b4c32d7b376fb73d54f7231dd4974713179f235140000000000000000000000000000000012b9f95af661e8452aa5026302a7c28695307f75e9e4e32365caf378ed394fcecc831a3c47b443172188f4d18338fa75000000000000000000000000000000000f52675fb4d112d1d39ff953a253b22dfa0b73d972e756ea7fb673bf87aa992883c5baf32be6f50f880b03dcb740f06c0000000000000000000000000000000008b57726e17c873e12834dc291cff6bd95307f50e7b1d0caebd8c1eeb6eff4acc0520b135bc8e35a257133b7dc640db2",
+ "Name": "matter_fp2_to_g2_65",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000fbbd5a10eeb2f358f2b167f1985d4084c4b12accb1520d780ef1c52f6fa80e97aaf190e7a7b241ef96fe8289fc0a9600000000000000000000000000000000155687114e7aa786ba27aeada830fc705aed069c4e3a07e88d7f33923319f416ff3caf6533cbb36e5bbb1b93a191bfd0",
+ "Expected": "00000000000000000000000000000000061938df3365bf910884ccbd74d3cea7c30416bddc1a9b65e7723c15d89aa657da36a45fe10ed50bfa0c2769bb98aa2b0000000000000000000000000000000007b3981054255715826cf8f247210521ac681305aad3928b69804117fc143c5101383eab7017127c8452a79003a857d60000000000000000000000000000000004c745113480fd87212ed3ff30ba43c8716b32e62c1f0091bde53bd4a8fa8fe6bbcf0904144f4791ed1bf12dffa1f17a000000000000000000000000000000001237ba297c7f69e5e240846a12d86c8276a9a6ceb4af977edadc7ebfba3ad3f4ecc0b875da0ea578c83fc3b91f9f31a5",
+ "Name": "matter_fp2_to_g2_66",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000115edef357ccc3432226d9bad796a42b1a278d9c8adfdddc5a0f8a36d32ea1787183877f8b7dfab71424cdd10b63441a0000000000000000000000000000000014b369ce61abe60d942346e049644b95a0fda96316446b2fe7ee427641af52fdd2a654bf125ff6c8c7f3dec98f6cbfb9",
+ "Expected": "000000000000000000000000000000000a0cc3e328b4cfd01afe53dbf971ad78fc74d951050d76210e4c84438109622f0531747e762e185e3d7ecb9faa7c3255000000000000000000000000000000000622ad6092caa727d069b8921f4124d5996f3019705a908ef95d23092c5bb148873a22c227aa25ebee361d4184cc38a10000000000000000000000000000000002938d2ff50cffaab8c056c2844c50013f5bcdbb4f91b3f823836edabb39ba17ed1b8b5862301efad04bd2f5d5bf599b00000000000000000000000000000000072e96136afebbf8c06a37cf9b20c85ef8cb3f7f99d5c71b05a187c193711e5b76f52863c7ef080a1b64b2120ab2ed84",
+ "Name": "matter_fp2_to_g2_67",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d22b7b36ac66b10adb4570f8e7521ed76de2df2a7b94b2d0b9ee4514cdff6fa7c74854d16e7e70f054a91df93c7ebaf0000000000000000000000000000000016867c9cba66dd9f1d0332d31c4e46f8e393eeeeb19af7e6e01effb29ad999b3086b599ee4b371de557d4fafd5da3794",
+ "Expected": "00000000000000000000000000000000142ceeefa9fceb903b25d4dc68f6755833d7529752db0f125f7f65f2b7aeea8c90e599ac409576e82f7b9d6f83c43aa0000000000000000000000000000000001664acd89b482aed04ef40bd4d1ff9f39c80d7738771e2b3ca731af01aa230d865869cb05d83992e94ad99549fd0b8550000000000000000000000000000000013d6ace9b492c014d9a7504b5abe442e3bba13b1ada454aa53177990ec44f616e091f1382d36db87b7e794c11570a9bf00000000000000000000000000000000081b7a8a2906435f8a9242f573225ea62c5429e903bebda9fe9973a18ed2682185d72aaa6584b9848d1cc45ac907dd27",
+ "Name": "matter_fp2_to_g2_68",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000db9258e1257e659e60bf8569ea90c8247a53a1d1eb958481623447a38d0f1f1686c3e40c8f15bd06cf5be9c02485452000000000000000000000000000000000517c87f3df032ff08d960f524939e66f7fa69b4168b0f2507baf7d7231a70dc5690a02d317b26f219365ac3255bee78",
+ "Expected": "000000000000000000000000000000001182e4230f0c360c07913349f89f8436c01841c9615348a0d7057336c7483342024b0369ae52f39d4582f9885f552b5d000000000000000000000000000000000d15433ed130163a85f8ba87468c906aba88ef8610fcc1a8d6b3308cda29907acca351fd7fb19799184f1ad91c751b5e00000000000000000000000000000000111089005c4c5370863b0ea6b629197a865f978f71becb741f50f9b4e49b13162ca63c29aa26287faa9c923f57f4ad4c000000000000000000000000000000000dce405ed2a79ad433123105ad01a26ee85d1ba4e5f3b4e0339fea787058c06e9a6b10f5ec8f6eeb85b211e18b6ea076",
+ "Name": "matter_fp2_to_g2_69",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000b6573c743989fc8613d4ea09c2e500ce965b50cf0c8975ff703116464082efff4b42828c8337809f6938d7cdd3f66e000000000000000000000000000000000896d316629c80ce6e5f240535863b9e064728665c0815f39b21675c236f6995e7dfff1e4aec9ad05861e2122469ea56",
+ "Expected": "000000000000000000000000000000001694cb615d2994a903a13645ad44a63395320f286503902b6009e7c795dc8f024260e0c45bedd864edc9fcb9d1ca6bc1000000000000000000000000000000000f20538af015bd6d213f90fb1a1ebde4d9e2ab2defaf80d791a1f70af2ca7ea1598d43e9eef1cc982f468cf15d223c9d00000000000000000000000000000000046c62bec4c6876a67f5fe68107d677db8fa4d59ac0cb7afe6e706864c6e94744bedac6b34a68e8ebf89c231307b86d3000000000000000000000000000000001839f3b8a6dd8fe8028247670fe5b491bb43ea8fda53116dca87f97da96573a5e701a703fb5fa7bca457ef88a827e061",
+ "Name": "matter_fp2_to_g2_70",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011fd2ccf6883b78fe19cfe7beded503cdbe1cd5dc9ee452aa6b329d2237c2529df6774334b132cfeaa616f20335f88680000000000000000000000000000000009eacceef036ec500e7676f54af703016fac93d69ed19c8943b64ffed2db498b19cd255a0a3437b568eade0f497c7b17",
+ "Expected": "0000000000000000000000000000000009d8725eb8757828a94969ebf40545a62835686897d4504a66484a3078b2f15e39fe918d8dc01bc7560dcb005a7a0dbb000000000000000000000000000000000954a6cc9b2dedca1cf280f72fd0625184b8f83b78ee1ffcaf0f9178ce97900d759e4a74b914c3ddc32f84c3f4c3a8d60000000000000000000000000000000014121b83d2a06390ce7359e570e1593d5ff097cb0e44c38bc74171fbd8a8da0dfffcc2bcb95fb2d80a55933f696a86cb0000000000000000000000000000000016f71d24256de70618a02b0f016c6f31a21d2cc42855886ba30176584a028c2e12367be19b834bf41356cdab21223314",
+ "Name": "matter_fp2_to_g2_71",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004a851380536054f6b69ef7581b57dfd753d1e6201069bd1218ae5766aada087b4b08f65d43b3ce0215640e8d34633310000000000000000000000000000000013579671b64f2d9a2c3ac2737cf95c2148acce3dcecb3db6d019730010c50d1c0504ba4ed42d93771ba296b0b07487d7",
+ "Expected": "000000000000000000000000000000000cd47f0982904ccaf4f3cdaa37091a08e67a5f04af09033b864631300bb6c2aacbad105eca6ddf68a643976fb555d3d80000000000000000000000000000000012332ddb0e91f0ef9e085f21634c6d69576e60d3d24732a0c91a560906791f60f79d09ac0ebf448bd39f047b1dd428450000000000000000000000000000000000a756a869b3cbc5624f0e08019170beda35fd2642a79108b284a503942f8267b75868636302e5a12b4f1505331b15f9000000000000000000000000000000000f60724f6c8200edff41f3299ca003e9ea03b97b01a3e8c63763bdf67b9f7677331a7144915312458c40d041be97b3c8",
+ "Name": "matter_fp2_to_g2_72",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000021dc1dedded9b0dd90afa9ab7fa8f9c33930fe4ae68185ea4cce9ed97ce4cc9ff93f96377b11f8d42b02e759a10b06200000000000000000000000000000000034c963fda3bb80043d6d7887661ad59b3c31c88c958b451a8e11684770c132205db6655ad7cbd604ecc3225b0c128b0",
+ "Expected": "00000000000000000000000000000000095cd509e53f10b1ee18b2120e2d18f0905a202a992a9c62480beb6588275fc8b5b151e6abf17a12b6d9cd03a8b37a59000000000000000000000000000000001723bf1a3d79935eb4b39f7feaa1e05cd8f3e7a32e2c406625053d8d8fde33eefec231ee00adb00b0acac16a83dc77fb0000000000000000000000000000000004af528e886dad3f9fa7232605936bc22a6a22622828367791920ec9d31cdb2f290e37f5fc79efaeaf96c86b3f6e39220000000000000000000000000000000015bada14a84fdb09b77397cd2e27836f9f88854924af0cafc6f9125d32be848c8325a3eee1a26de8be8eb80b601f1ad5",
+ "Name": "matter_fp2_to_g2_73",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003e8d1be04f8dbe5c7e1c7553cde8355ae16d26c819dea92fb543cbd9fe9e726359e1e4be0483a7720343f34c6a3fb9200000000000000000000000000000000062bc5fdae812802bdea09e4130c3d9bf80c7518138b116a4b6a302c155b97226a6ccc8a3ace18744e7adece08781f72",
+ "Expected": "000000000000000000000000000000000d8f14042f36bb377655b63dbc37c50e0eb5775d4e4399972a6758cdfa9751cb4b733745ed1a47fe5f2cc434efc5af81000000000000000000000000000000001384016829d028f823e6d062898c042a461bca13ae4627c983d9b5c9e8b4ffff7eb25daa1c52b39e309b9c1e7e4f2e920000000000000000000000000000000004f7904d491a0c2018b1361a9cfec4fc829e607402859fd9b9ded60adcee51e9b522d302f9064130a4eed1327f49bb4f000000000000000000000000000000000ef4fe949fca569b31fc57ae7d0166ea53318c5712311076e052c2967144116f5490fdf56f26adf64aa01beb4f6cd214",
+ "Name": "matter_fp2_to_g2_74",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000014b922157b19ed9debd9ae95cd9435f7980b8d4ea33fd29f99d5e7fb1a96f6d99ae13f7f86239c4bc286c3927d3522a000000000000000000000000000000000f6d4badf78d9115d93783a59ec9576fcfd87a2c29e1c506b6f7e313e71723811a36d64b37650fb6f7b460105a7e13f1",
+ "Expected": "000000000000000000000000000000000f20b3a6505784681331208b573d3a241706692db71b5daf4e9c80adb1fa9bb87023d7ba7f9c65158653c735dee9dfdd000000000000000000000000000000000f7f357407ca6cc5c5fae4b84509d71b2f4de9af226cb4038b4820c0541d4999b7396608efd2f322a00a768129f9800400000000000000000000000000000000138dcc1b9d978adb5eee6356980cec5d18cfbfbf18cf6fd14f4119a563f473f5027af06342e84ea858223ed63d1a16af00000000000000000000000000000000012b63f0d2e8ea361d55aa617a99e066b5feef3af1930b83d2a48b527e0ef304ceadf7cba1415db80c54fdcbbcf66d14",
+ "Name": "matter_fp2_to_g2_75",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000005a54ee5e3dc05c38ade7a42c71baf5a1467938f97c0cdf0742441cd339f22542b1ca6cd215d385b3fd6ba74ec996a4d00000000000000000000000000000000051c6f0ce621e8e27e5017628690fb68f0fea27d67726a0a77b0caf9f524936e123ff096168ff2079b9990c07fa80354",
+ "Expected": "0000000000000000000000000000000015ff2aa94f802d8f9c60ddcb43aee598239cf3ab7f90f8289a487b673f6065f8d9bc92bd4cd28df4a7b0d3bb78fad243000000000000000000000000000000000884b5d4ca3c8abea737cfca05878528890b6cee9bbac0bf027df5d4e0add431829caddf4c1e001818581ce08686eeed0000000000000000000000000000000019b91a7738fde9760240b335457955e963030848e85717858f22dc33ba5a4721156cfdd7341aa86d10d268e2fc9a1d26000000000000000000000000000000000af85e60161795906f3cf705f5e8cb8c15083a90836eac78445c6bc27ffbfc8c2df3009b436989b46b271dd8d1dbc282",
+ "Name": "matter_fp2_to_g2_76",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000094e958d9b7dac39fa4f0143a333b2ccee09046cd23e6a1c0712470a3c2e61d2f8b85aeca37350f71d7ec75aea2b3b6b00000000000000000000000000000000080743cdb5e359e8b8ad3485d53ea286669ad66d841945296edf80dde77b20a158e2c1529dfc33a1fbecf177d75a0c69",
+ "Expected": "0000000000000000000000000000000001bd1fe6a6c373cfdc2bfd488b0c942492b77d55b2560824edef3a91c711ee336bc1366690be40949d04edd39ad48a7500000000000000000000000000000000161476946a5687113c74a34284f49b0658e323fae57aba88b039eae584d6ef28adca669fb083a2fe8f0ef664eb5b957d0000000000000000000000000000000007aead870ae09a04cf9c9fa49d0888f7010782cdc5a0ade4c1340ff15d99cb39b7412d66d4147b95601fcf5a39c39bca00000000000000000000000000000000095cce83dbfec12973e27627bfb2d93fa9a027a2c2af4259a0879d6bda055d74559fc93fb3b4f6b0088f702af29a7643",
+ "Name": "matter_fp2_to_g2_77",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000dec04526dbf7666d2c29db5de1ef0b3da85380a171d871a57ae3df364d2754fceabf9d4d2a3da1ecd94e377abc78430000000000000000000000000000000000d19875fe988ffbd0cf1e9bfefc7019579962ffa3a585ee232615e4a5fce0a07bce0537b203ea00010a90ec05d5b8de7",
+ "Expected": "00000000000000000000000000000000133cdf684c3ff1cdaf07ff787b57a66c215eef06acc2aec4d726a086480e7b2a5dead2cb357d99e298df32d4c6f5029b0000000000000000000000000000000019cd65b830fb17880f40e104ed63a7d49b0fbad8eead7502f18f1b9f85f3f6ba6c275b8a242effc61a7a5d770a4fdaa700000000000000000000000000000000039aeacd163862e476b17a22c76042d7896a04f158489ae71afdd35d27106a3ec276baf5c08e3eed4b3f0a79c3c458d200000000000000000000000000000000125a9bd770c1fea2155a581211bd71d55eb1966645cc892a05d32cf1e4e5b23278ea2fb1336bba7f2c887debe4a93b52",
+ "Name": "matter_fp2_to_g2_78",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000016dd03f0df71b183e42cc29c665f18d57637b65f05df85aed9a0f7b8aa37f7913f6606c10f24a7a8c570f485905583a00000000000000000000000000000000161e62d8be678a114fd4a99a6caeb9481f5eaef145571152fe8a6ed77a34c06a1b6ff66044102d19a94abcaaeb254e73",
+ "Expected": "0000000000000000000000000000000007843268081f61ad2b3f6653336a99086381bb4da4c23b7d59b9c7827f2d4c196d136508c8a1f3d2f939e8c9799b95e10000000000000000000000000000000000e2c57ad95f762115d8230320810a4ea9978e26ca17decd6af4c112789608967a92fafe3fb3e79539d75d1c0bae97740000000000000000000000000000000010951c9839db9dd6ca5ef95bd1b1b9cf60bfd97cf88129fca23b24f19c9d5c71486dffb762e92f23d2a9e9d462556f620000000000000000000000000000000013d35c17b3763fc5db46ac8c44aef996f3f876c49f5278b7c97e844f23ac49f2d50b3af080322d30ead873af7b4257e1",
+ "Name": "matter_fp2_to_g2_79",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000036efffcb0c6f42109bf9b8b7421e32fa3f855373345341e6000eccaca135ef3b2e1c0151bddbd46ae92185acb847d74000000000000000000000000000000000edbd7a40f3e688eaff5e29800159b8d799df07e81f65d59011e84329b4689a28a15ce11537fb560df705be26bf14b1e",
+ "Expected": "0000000000000000000000000000000001aa1919a50b5bad62b839d672d5a11ad345fcc61f75eccc42990e113deb8a486423d1b27e7c81536d8a5799986b9408000000000000000000000000000000001879295d2f7bb3923ec61c063ee4f96d7d7cf7786259e2f4cbc3ccffe7e114af264b3527a5e06dcfad50ec1e2a9c1ae0000000000000000000000000000000001042632662e406c95f3fd44a6d956e526907147e7e6d4219c1c4b28a31e479974d00d4ad6e683f6a834d3d4a20830f4b000000000000000000000000000000000a29ea98ec25e7827bcb349ccdb2a57926809f3cce44d5ff6cd636460278c8103b0db78fa580e9edd4ecd0bdb21018ff",
+ "Name": "matter_fp2_to_g2_80",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000974c7d17cbf91947ad435b30ad2b639671a43d67da6a4edc7f8bdc11fe817d4d42f687dd642a2be89c81bc36e8df592000000000000000000000000000000000efeeb85860877abdabae35672a77ca9d2cf0ed18ed209fb905b591a841c900ed06d2c32c56bed5f7efd469d369b05b8",
+ "Expected": "000000000000000000000000000000000c67498c6751cc27d871b8711c4739398c501a5bfb688d7e1a73dc7db5c47c3e28b633078cb83745bf5b0d5d2dde3ce2000000000000000000000000000000000c205c03305422bd44082715b90e0a0ec178003d6f5e14a0d13bb0f2c38f2270816b884b4870b75db44ab080f88a35e2000000000000000000000000000000000257f378935772d326710ec6efeb22f8c9b6b549c8a4c0205b75740047d750d73da4e71aaa8ff33b9bd8ab7621b08e62000000000000000000000000000000000c386a15f09c849be9f449a59e1332a1e7f16a9394c8de198c01399a05b0f963921c4c57d49916407ae0d202af8da32a",
+ "Name": "matter_fp2_to_g2_81",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015333364f4d0d173ef35e447fc189b9d65ef71b9fc4ecba25fb6c8c1bfe8467f26bb9c55ef10bb34125d714b94aa1df1000000000000000000000000000000000cbba9d8ac191032f03c0746f13108962130c9e2c01d47f01174a4c4d3daa7631268f7dcc08dfda317bd249fb6e73e8a",
+ "Expected": "000000000000000000000000000000000864da537fd94a9ff1bdae733f01e145dc97a894733d0811cd67c2648ba61d0b187241f9ec69d8c011f514894a05a608000000000000000000000000000000000a53ea4ff9c0ff71541ee21127a33daff2b39e74301946a86e51dc7834717e7d8784cf92fa5845bc0613b6b869003f58000000000000000000000000000000000582f5a1fcef3067dfcdfabc6af33871114538abcb02fcad761cb496020c7b423fc52f0075916f160fbe03574df97ea4000000000000000000000000000000001244ede8ba0dc09aacdc5d9f886e59bf963a25885dbbe2c3d1f611bfae82debc556ec4c94f0606492c7b8c7bf976ec34",
+ "Name": "matter_fp2_to_g2_82",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000781e980c167c982c2fc8d0baa3907bc5499eafca675ae20a10b25063c9088fd06f6769df505e5900bcaf99e266c052c00000000000000000000000000000000183c12798438ea92db75d5bf76cf29d320fab3653e4131989205f2817aebcb1b13f161864c084fd13a11459d7d5ccd92",
+ "Expected": "0000000000000000000000000000000016c334aec0e19934665596f0ae37eb398f1d6f0d0c9f08189f1ccc219230395124a9da03858bdba13ec5366da54228af000000000000000000000000000000000b156ea34ae7b5c252dd90997f1c693773a463c26935a69bcc0599b95bde9e6aa31649c48b6ee4ec1f0a56b19273a5170000000000000000000000000000000014b2d69e02418844effcbc0d564b2721deae2872cd1f27f61d544fc0ebd5cadc77c6777ec944ef0500db181a5443618e0000000000000000000000000000000004f0d48a25c1eb81233f385af17ab6abf554e1285b669eeb5e884c64d5815fd5fa1350bb361997cf2e317f7c5e9cd19a",
+ "Name": "matter_fp2_to_g2_83",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000879133a3c0e50c90abf1a6ac75bbeca1121c865ef39e9224ddb160eb725e0850a34aaf9014e42174966773e40e4c99a0000000000000000000000000000000004c66f8f5bd462cb27e9f5e1d93e322bd97582b9e81d07b2877103420262e4cfe6d0e3bc07f9f160701fd754793eae33",
+ "Expected": "0000000000000000000000000000000003c0d6b721cee4e5fdc6a02095674a58075f81b1d28163f81d5b258c82634297009e6bfc8193969e23e196cf7a99ad6c0000000000000000000000000000000013229818411c8e55e50a63df6983150c1d5ead828711131d9c81841850ed76e4712954d3225eb6d7fffd3cb9924f7497000000000000000000000000000000000f42d6e4d5a28dbfda87c806cb0b1bbabb745e63e655c3c6be50411da4dcdc745ae50f71d56e88db8454d40375e325810000000000000000000000000000000000f663ab791b48f76d358e66e8cd8fa40848dff2bbec758ce1d7b3fe02d1f6b3f123cef644d4fd86d6a77b8155feae58",
+ "Name": "matter_fp2_to_g2_84",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a7e855324ef471b8fefb31967cec84d57953407ba555b672fa59364b303030cb02b6c77933cc63fcd1b8c107b263554000000000000000000000000000000000b50c3f7cebdcf538820113acdb017fcd5d41a4fd679af8dfde7b0c330e3576ca79d09eedc724a93a3f5c90d141e7524",
+ "Expected": "00000000000000000000000000000000197865f685e78a8842fa79ddc728d507e9f31b31666d1952a46f6422c97c83fba3087be70e3bb588260556014523f74000000000000000000000000000000000131f5d85ad3beaabd129d5a5675d90ea911ebd02cddb5ddc7a8be28c33061430d684d123d5c516785d21ebf756c99195000000000000000000000000000000000c7a14948f3aa29f845e5ca9877db9f0477af376eaeb45324c21e6f99e738aeec96b89af4df942bffbabbf50172d8e5b000000000000000000000000000000000ed4aea3cb585b0d36972f9ad6943172ca7375b44d1d6e80e0bf97a0b25d74deca4d35ce865c8747f1c7a2771a37c667",
+ "Name": "matter_fp2_to_g2_85",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001706830efca18d3e75ea0f1ca8af23a816017ceeb045694cdbad6d3d9aa5a9ddb123f5097a226a217166de3a82038393000000000000000000000000000000000402132ac383a2fcb17fe73398273ef0c2f2d0d6edabc78f31080d3ecbf7c249ffeef28bb8b37a6ef2a7d726c070dc41",
+ "Expected": "000000000000000000000000000000000a795c2affaaecab6cd2cfd6c8fab6e35cdd646e9cfa7b5e02400ef4abf839a69924ea80152eca7810a5041d1bf58ee800000000000000000000000000000000121426bb945d6f6b385c98a5247b7dadaebd3375dd8b2bff7aa77fddfbe603de89e77baf0e8f36a924c707c53d29a1450000000000000000000000000000000007a6fcb486634186f001c8b99874f0a07a37f1ff4b30599d2f570f1bb4ff290b816547f6ce8b3c1ed33e57630a1d57ab000000000000000000000000000000000fa65924a8f17414eb7dcc54f2a4134568484e91533dd21fd33cbcc37a920f2804516a64f1986e9d887ca189179d07c8",
+ "Name": "matter_fp2_to_g2_86",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024beda2b950efcee233435f0c748e33aa928f54ff29d3db217d7e32b1aac5f4ed11705da4fb8fd38481382486e4aef7000000000000000000000000000000000c85283ad6e35a72d07b74775df1a4660113d50b51426451f454a575adf9cbf9d7be3f521649f6c367c4f4c74b67ff6b",
+ "Expected": "00000000000000000000000000000000049d9ac43e31faa3d02f8255d207b82e4b27e8a9a61ba45fc4f9ad8048e5f89b58d25d98253aabe29334e0dc09d1cd6b000000000000000000000000000000001544f90a0baea38b48d89bcb337cf5a80faaa79334733b7e6126f55358a7e498aeb61419065b9434cab9d10fe8e7fd9f00000000000000000000000000000000139bdd668462a1b5d3ef1299d47aa91ed141ccbeba5b08a8ee31b023aa78c16514a97ba08abf5c8bb1abbd85b3fe87350000000000000000000000000000000005c7dbb8a22403a96aee634cfc67ee6f1069cd61a1e1831e8faa9d7e1aa5e4f7623f51f2e5b739f7fcf3b4ba77c82ff1",
+ "Name": "matter_fp2_to_g2_87",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000cb18f477abe58af92116101c3f52ad4f6074ed92a08c3adcc6660b555df9cff09dd8b34e032ed81e868a62bda50378d0000000000000000000000000000000013c4ab1558dc250c3b5d0f0fae3db62b8df969bb41e9ecc24c10e1e51cb399f1368bed7375a9b9ad9c7653c868eecfe3",
+ "Expected": "000000000000000000000000000000000b8b8bf2b25c2386e5f3be4bdb387d8005cf055e68ab9a5606f17dbedc4fbd7a11314fd646d08bbd6e394485d4f56f5f00000000000000000000000000000000173a45d766682f82ec2d69aed1d80ede2477c276ddaa8fb97f5f4d0515b2c2e370c615cd81c1e361f95db855c9b1b6e200000000000000000000000000000000115868a9187a0465a9309054e865ef224ec3c88a5eafbcc25f9a912ee3b19084757a90b72a4038ba71b10f59fe2f93100000000000000000000000000000000006c5476eb8aa1a471d289af52c7d1df55f6bb1ad53d7eaba6bdc2a97fcb24ec480f9d8e12079d366f2213194c861f016",
+ "Name": "matter_fp2_to_g2_88",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000188f650fdc51b970d16c0637ad5e97aade93c7f1398751439484ec6cc56613814908e51cfa7f68da9d980bb9dac47a400000000000000000000000000000000081834f86f1310135a2cb03265f37d9b7c9459bb149bc54b5a61319a7cde36c6a2a0fb49f8f1fb9d80f07b84f799119f",
+ "Expected": "0000000000000000000000000000000016e8fea4d09831146fc35bcad28e441f2c02e4d17838e04dc7cf909b2133297a13f07ee927722f3d78e36721d6848e3400000000000000000000000000000000114dee8b3a47269e9ada05ee015a874d1cbdfff4acdf5310642f829efd08f78dd6110e1c7a514e7d76aff52046f4ed140000000000000000000000000000000017b9d23f7a865a3ca61197d841fd9195805a9e883d79dc7d36e82f504e6689ade0e84c70a5c5c516fac3e3c643942e160000000000000000000000000000000001ab82b2a0986dec3211507b8adca351829b0a13f25e281f98f54d9e0e32280ea4c638dcb74280eb747a0d9af43b6b74",
+ "Name": "matter_fp2_to_g2_89",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006f66eb49f95f51ec90df86254580f0ae57862bdd8b5f2759ace63c5f14f8c5a762207f744bb82a8962f8c4fa410dfdb0000000000000000000000000000000004e02a80628c30ce336eab890fa37a227f77357a60be72cb87cc2b7442d2163d395fdc59350624ca1322bfe8619a2efd",
+ "Expected": "0000000000000000000000000000000006bc2ae646a603a1f4524b445cdeb99914e4ed19cd0676d511764b828bfe126e81cad2cb566655f04de1a302c14d70bc00000000000000000000000000000000023bd509aabfa41385e90cd4b1cbbfa45d066c4defab56993aaa386dc5b7707b1a3a7d444b8bd295a30d0b8f4bdc572e0000000000000000000000000000000006f82e60e18cc958375cce6f465db461ff46ed9d15cfcc01a3aff455d54c77ebba5a654c2ec788b6ed8ac53c39defdd3000000000000000000000000000000000896fbe6492c4c297f8b6d60295a7f2565734d69eea67b2675211a203fec043f0d181b1348bea425a068b7bc12676ed0",
+ "Name": "matter_fp2_to_g2_90",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001451bcd19495cea3a19393b77760f688fbf17b107dc131c88cbb503eee2a804e2978d6e8a4720d144083d28be73371d70000000000000000000000000000000017db715e8680a0e82e18b513f2c9c7ea136cefe8add71aac6baba146e3e33a498d025c7e0808ced306c915eb02900c61",
+ "Expected": "0000000000000000000000000000000008604a06a198c3e11458de920176842221667d024f9c155892485a37ff56252be1dc629a6fd580fa41f5e598a23f3651000000000000000000000000000000000e008eed25eafeaa67f27e89e1f81b469724a4b00f08dc4ae672aa1587b19dc615330e3fce0fbd98d7526bc2c4afe69e0000000000000000000000000000000015bc1e4ea5ae2a7fde6d5e5c3e58f6ff5df5bcb125ab402f10edd09087bde39fa27dfcdce7d04fd18ce399729e155fae0000000000000000000000000000000006684e9be8bf9fa4badda842a1d8840f0820d9a797e482c64f4004a18cd63986f19abfc93f6bf068d38eb1e491cabbe6",
+ "Name": "matter_fp2_to_g2_91",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013a6e129d4dd4aa93cff5489ee879763e2a2231939e609d2d72f07e630b37d09f3057a36fd5cdfc9c81675c996f8ba0f000000000000000000000000000000000e8d7ad082e8f9a718fc2ea712853ed9ab4e8b1a8ca9988f77c70fc759f1fe2d4bd73696e539f130be13b2862efbdf77",
+ "Expected": "000000000000000000000000000000000f15c3d0b40735babb2e38a2471773faa16b2fa307c3a573ef4cfa5a5559574b2d26cf88b19dee204b77f6e11a1b927c000000000000000000000000000000000d224445f3d31d381bb29c4fdc8130174f5bcb957f451c92f4a652cc3d2b5df985017133a944849b5228a88f99bec771000000000000000000000000000000001338b48bc1fa229f251bcd4828654baec9d149f090b19596ad3b444eacc7bc583f97d9cfc40d5611fdcf89cc9a88e33b000000000000000000000000000000000c30dd2aa51f6577d57175edb3ccc1b324717bc195eb0073c1dff4e5b0d77cf5e41ec233527b3936994e86303f91b172",
+ "Name": "matter_fp2_to_g2_92",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003379bc10acda5ed1014e2bba1e30cf83b72fe69259eb35476a031b8a898e0183bc32ee853a85fb3d738424208fc880900000000000000000000000000000000175a2e5a44ed62744fbbab9581ea7283470bff12436dfc414ad80b4070f895de3786022cbaed55bdbbc4f68db7460548",
+ "Expected": "000000000000000000000000000000001735e1f2fe905839fd6534c95b95322f8cc86a4c482f1ad7691b9b9bb8f55015b4faaa1f243786aa33b5874817cd09c80000000000000000000000000000000013f1a27931ac513145f2601e009cf637ba4bdb18a7604f89534fa3ec8488f5b6eab9963c5d753fdd34cbe7d2f8eb8a5900000000000000000000000000000000092d8f800e7a4bf6f9a25ddd7f64fc403db53b1695ae59c15f229458f347a8e7c2ebc415af2d3849282b670c5cf6f8600000000000000000000000000000000019d22d694e559c55db63521e7b60a1a2342c3cce868d70951e5ed32ec0f5efaeab0e78b21359110f6e769776b745938a",
+ "Name": "matter_fp2_to_g2_93",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b384a9db472c38a5d246da56059b7630f002b5f4663abce7c5f6e896222a1ca1ac02883a1ec95a4ef09bcfab7d0652a000000000000000000000000000000000de09ef45aafa56936e446e18ef9ff97ca8b81c295d35cf7b72416ebd80586d0fc479d86c23295ac54a23489af045ebc",
+ "Expected": "000000000000000000000000000000000d7dc499e5213120b3ccc173c83d3c15dde9e13ef57238cad84889243b35c8e69eea2ac7ef7560051dcd7402b46b733e00000000000000000000000000000000063ad31c17eb17d39cb4b33e45a0b0e951becc11b685b10cb45cff268b6dca40b780f7e1532be91903372c413a11b5be00000000000000000000000000000000140da959456cbd34e041409350d6106ff65ce6dd2ac3149f04959b16eb83dd0456ca11e5990daf4a1e5c23d3f30a6c4b00000000000000000000000000000000195d07ab127d49baf89fcf5eea1f5e4cffea1a577a5c864c0e637fbdfa10182adc1d5d4ebb871949300193e45ae0fbdd",
+ "Name": "matter_fp2_to_g2_94",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014df33e7d3ef2c339b958fee667097ccf146556261f7db4b0b0a3c29897b73a0ca249866cff1461488012bc16df43b0d00000000000000000000000000000000099dda253a43b8cfac580306267d9dfeb2c129ac1818fee43c6df5e582f5fa726ba73e1a2ef6a9e011a387c393529678",
+ "Expected": "0000000000000000000000000000000013ec1ef25b303fe2f10a0bbe9bd77a4b2a055e176c2870c99e63b4baf2b313a835459263351dfbc25c22ea32946d8956000000000000000000000000000000000cb1c3292a2e0c9b1c1ff43cbf7595f39c00fd413b54782681fe75a6f5f231d13912f8d598dd8aaae8159de083dccd8e0000000000000000000000000000000005385f2d4bb6d94d67b2a3bacd3aae31da282707672252c0ab1a12fc85d8e9b9eb75454eb145937542099b860f9d6dce000000000000000000000000000000000e59506f7733a38a7e1da4ea5958de4755b52a9307ba2e5813131b33b86f0e401f97594d9674ff1667068a1ec3c9b145",
+ "Name": "matter_fp2_to_g2_95",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000011c89c8d7e83155a308b2e517a23f05a4a55353332292b44b0a891b6f730fd126bd0b97eb87f0fbdb6c82779791d022f000000000000000000000000000000000da6f02450955bf26e236ec63aaf80a018ac34fd8784bb24a22a1fc5e8bd686244a923009a10cb38b1422534d0997afd",
+ "Expected": "000000000000000000000000000000000f4392a41fb3e58dea97b97fd22e2fe6436c3f9bbcd944585a76a5f1a8f98ea4ee21639208d765b6c3a7d08f8cd3f3f00000000000000000000000000000000002c3d62794996dbb881b665eece98926f41a42c21539125fda6070d9f69e29e0557c886b42e4bcd97b14134d6e9d1d710000000000000000000000000000000004b93f315822aa1be8250c2e736727d390ae3a862c4c7dda452817f70f01c73e6f344df1b0f05f03bd574edecc70902e000000000000000000000000000000000731403981fd6243d00c23d0a42a759016f7907548847743f18421f51b1e72cea92f0c5580328babd4ae3e15bc9c56de",
+ "Name": "matter_fp2_to_g2_96",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015bb227b5c9ccfb8390edcd158b04a69a88a3b99a10ae90e548182751a16448df25493061afde2c9790a0e75e6f409a20000000000000000000000000000000001d7b609155bf3939192eee9642032e6fb10f57d53916674c60211a37b4a7662759899a9569e2dc730febd23f747a7a3",
+ "Expected": "000000000000000000000000000000000b35c6294b70336217eb9334ff1f1bde9d892d109e947de7f4f5681b3830ed00ad1b89ccd7cbad88ce1586449140697d00000000000000000000000000000000032691e5f4597c06496e9e37907041ddcadd18ca8ce64a8b400b1e2e8d63acce5533231edb66b69807fa2dc026c1d2be000000000000000000000000000000000773ccd132cb215cd98aa17d7fc432e0577b08d8faaa35199000d46fdeeb954e8652566384fa0cc5bcd1724942f7075b00000000000000000000000000000000112e951db3694944fc82fb980547cd8b7f2e5ec6fd2051b6aff2573797bd6a28437848ea0627054af1960ad1de0981e5",
+ "Name": "matter_fp2_to_g2_97",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000017599d71686e817cf58b78dd7586d5b359999b32b0dec2d67e33fb6388411418ecfaa2670a2cc9dce3dadaed0fb3364000000000000000000000000000000001773995b540be9ffbfd276a92c0494e4eae296d094f9f7eca975cf4f73ae05e92bd64ea71ac47bba534044f4072a6591",
+ "Expected": "0000000000000000000000000000000018f2eace212eacabd44ff01d886543410ef72b4d27f8d25cb080dbe4b1d4b2b4e57e4dd40723d15789d9b5104b088d9b00000000000000000000000000000000098e9e9b302876ce85ba486609fd028f357314149ce8b530778e6de586ab057fe59648d8c8ae80fe619c4c605b90784a0000000000000000000000000000000016d20a8ca43d37518c8a0f47566ba61a7aade9ea2cdd4a0907ff0ed862c6b7c64815d50397eebec262a05c6010cfaa790000000000000000000000000000000005a70c2fce25acdc4a95fc2bdedb007d71f24b0b5714fa14910ef590215d25442e91a66b6bfea5f7777f0c6d202eff32",
+ "Name": "matter_fp2_to_g2_98",
+ "Gas": 110000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f470603a402bc134db1b389fd187460f9eb2dd001a2e99f730af386508c62f0e911d831a2562da84bce11d39f2ff13f000000000000000000000000000000000d8c45f4ab20642d0cba9764126e0818b7d731a6ba29ed234d9d6309a5e8ddfbd85193f1fa8b7cfeed3d31b23b904ee9",
+ "Expected": "0000000000000000000000000000000012e74d5a0c005a86ca148e9eff8e34a00bfa8b6e6aadf633d65cd09bb29917e0ceb0d5c9d9650c162d7fe4aa274526850000000000000000000000000000000005f09101a2088712619f9c096403b66855a12f9016c55aef6047372fba933f02d9d59db1a86df7be57978021e245782100000000000000000000000000000000136975b37fe400d1d217a2b496c1552b39be4e9e71dd7ad482f5f0836d271d02959fdb698dda3d0530587fb86e0db1dd0000000000000000000000000000000000bad0aabd9309e92e2dd752f4dd73be07c0de2c5ddd57916b9ffa065d7440d03d44e7c042075cda694414a9fb639bb7",
+ "Name": "matter_fp2_to_g2_99",
+ "Gas": 110000,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/blsPairing.json b/x/evm/core/vm/testdata/precompiles/blsPairing.json
new file mode 100644
index 00000000..138b1394
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/blsPairing.json
@@ -0,0 +1,702 @@
+[
+ {
+ "Input": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d2800000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e8490000000000000000000000000000000006e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb9090000000000000000000000000000000017d81038f7d60bee9110d9c0d6d1102fe2d998c957f28e31ec284cc04134df8e47e8f82ff3af2e60a6d9688a4563477c00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "bls_pairing_e(2*G1,3*G2)=e(6*G1,G2)",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d2800000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e8490000000000000000000000000000000010e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc0000000000000000000000000000000016ba437edcc6551e30c10512367494bfb6b01cc6681e8a4c3cd2501832ab5c4abc40b4578b85cbaffbf0bcd70d67c6e200000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_pairing_e(2*G1,3*G2)=e(5*G1,G2)",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a550000000000000000000000000000000004523f5a3915fc57ee889cdb057e3e76109112d125217546ccfe26810c99b130d1b27820595ad61c7527dc5bbb132a9000000000000000000000000000000000186a1da343cacf1815b9c8b6c807f536249dbfdb59d77bf4920ad2198a0d83ada21f7c39de6f06a5599f22571cab288d000000000000000000000000000000000ba1ec44f95121bd622932b84bbb4b3d279f69c494ee44db68e3165c86b627ba5e397ee197313fb5b775972798997332000000000000000000000000000000000783e7493e9fb106fa0d085e7c03eb816468d12c65d9b77643ed07c02583d491f4db5db44e565d50d8ccaa9ad8f7f8e80000000000000000000000000000000010a6a5fd90cd5f4fb6545814f5df065b001074bb3f29f649dd2612815df3a19a320f7754dd3d458e48e7fb1b4953978f000000000000000000000000000000000345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c00000000000000000000000000000000083d3baf25e42f2845d8fa594dda2e0f40a4d670dda40f30da0aff0d81c87ac3d687fe84eca72f34c7c755a045668cf100000000000000000000000000000000129c4945fe62538d2806fff056adac24f3bba8e17e42d82122affe6ad2123d68784348a79755f194fde3b3d448924032000000000000000000000000000000000528590e82f409ea8ce953f0c59d15080185dc6e3219b69fcaa3a2c8fc9d0b9e0bc1e75ec6c52638e6eaa4584005b5380000000000000000000000000000000018dc3e893f74729d27dd44f45a5a4f433dcd09a3b485e9d1c2bd0eb5e0e4c9024d928ddc426fdecae931e89885ee4db4000000000000000000000000000000000d6ee02e1fc7e52a8e1ef17e753065882c6fcc14da61da7ffe955fe84a9d2af9ba57562c69db3088652931bf124b0d5300000000000000000000000000000000051f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e000000000000000000000000000000000b6a63ac48b7d7666ccfcf1e7de0097c5e6e1aacd03507d23fb975d8daec42857b3a471bf3fc471425b63864e045f4df00000000000000000000000000000000131747485cce9a5c32837a964b8c0689ff70cb4702c6520f2220ab95192d73ae9508c5b998ffb0be40520926846ce3f100000000000000000000000000000000101e147f8bd7682b47b3a6cc0c552c26ce90b9ce0daef21f7f634b3360483afa14a11e6745e7de01a35c65b396a1a12700000000000000000000000000000000090ca61ed16c4c1e80acfef736eea2db0d7425d9110cb53e6c4a2aa3f8a59ee6c60bdce8df5825011066d44bef84d29600000000000000000000000000000000028207394adcbf30250ac21a8f1db6283580bc5e39159930552e5edb25e6215c66b6450296edc80dbc3a2acd125dab160000000000000000000000000000000019bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3000000000000000000000000000000000adb3250ba142db6a748a85e4e401fa0490dd10f27068d161bd47cb562cc189b3194ab53a998e48a48c65e071bb541170000000000000000000000000000000016cfabbe60d1e55723a0ff72cf802f2d1cf13ed131e17729adc88522a657f320a336078a9399c8e61a3bbde3d52fd3640000000000000000000000000000000009aa9a3c2a6d49d286aa593c6ff644f1786fa9ae471bdb3fe70b150a9ed7584eaa886ac057c30005c3642f65ad5581cc0000000000000000000000000000000001d417894c0cce924955a795b188b27951f8438a5485404b921a42fa79dea03c10e29d0390df2f34d7be13f360a7fada00000000000000000000000000000000189b0b3a04e6c613899d51231dbf0cba6a8a8f507ebed99d24fba7ebac6c97a8859ffde88e6d95c1a9d6b4f0a8f3c417000000000000000000000000000000000d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a414950835820000000000000000000000000000000009d0d1f706f1a85a98f3efaf5c35a41c9182afc129285cf2db3212f6ea0da586ca539bc66181f2ccb228485dd8aff0a70000000000000000000000000000000016cad7807d761f2c0c6ff11e786a9ed296442de8acc50f72a87139b9f1eb7c168e1c2f0b2a1ad7f9579e1e922d0eb309000000000000000000000000000000000d3577c713fcbc0648ca8fbdda0a0bf83c726a6205ee04d2d34cacff92b58725ca3c9766206e22d0791cb232fa8a9bc3000000000000000000000000000000000f5ea1957be1b9ca8956ba5f6b1c37ea72e2529f80d7a1c61df01afcc2df6f99ced81ac0052bd0e1e83f09d76ad8d33b000000000000000000000000000000000aabced4e2b9e4a473e72bf2b1cc0ce7ab13de533107df2205ed9e2bb50fa0217e6a13abcd12fce1bda1ccf84dac237a00000000000000000000000000000000073eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086000000000000000000000000000000001825bacd18f695351f843521ebeada20352c3c3965626f98bc4c68e6ff7c4eed38b48f328204bbb9cd461511d24ebfb3000000000000000000000000000000000029ea93c2f1eb48b195815571ea0148198ff1b19462618cab08d037646b592ecab5a66b4bc660ffd02d1b996ca377da000000000000000000000000000000000bb319a4550c981ee89e3c7e6dcc434283454847792807940f72fd2dbf3625b092e0a0c03e581fd9bd9cf74f95ccef15000000000000000000000000000000000abb072b8d9011e81c9f5b23ba86fdb6399c878aa4eadee45fb2486afe594dffc53be643598a23e5428894a36f5ac3ce0000000000000000000000000000000005d04aa0b644faae17d4c76a14aa680c69fdfc6b59fee3ef45641f566165fced60cbbda4ca096e132bb6f58ab4516686000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436000000000000000000000000000000001065f2a2d29a997343765f239c99a018490eced40ac42fc93217dfe20d8b43ee2215f65166aff483b3dc042c5a43b196000000000000000000000000000000000766e4c66f4a442ff1f61a7a4d197d2b47dd226d0e7822a9b065108cfc643cd3f3d5ae59ed2ce4cde13fd9260bb5b7cc0000000000000000000000000000000012251cc6abbabeb7bbe1fdd63eaee10832a748fff24f7e3fdccaea87facb6e99f2e0407a38f27f90450a471b873104620000000000000000000000000000000011181e08c8fba91271adfee9d31681f8412ab7a3f754f7ba4709024c0ad2287e32dd455d71a296b4838072a8ab9d96f2000000000000000000000000000000001252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada0000000000000000000000000000000002a1bc189e36902d1a49b9965eca3cb818ab5c26dffca63ca9af032870f7bbc615ac65f21bed27bd77dd65f2e90f53580000000000000000000000000000000005a7445f55add1ed5c143424ceef3d594280e316c9441a8e68c3ad97377141d015bf878bdfcf0df9fbcd0529f4e8100800000000000000000000000000000000192b52ba08ed509fc84d5775a7182498fd1ff80941d673c53470c9c9f1192f9c0057d68a1dfee0c68fe5df3625cc43bf000000000000000000000000000000000d3fcaf2f727e0eb32c65da9b910dc681b948dda874d0db6f6ed3f063430fbf073385a9a14c2dd78568726124e2b3ea8000000000000000000000000000000001943ce22cdb2387bd5796950dc95d1ace4012ab9bb4afb46223760230c1709e075f1ae76d6b3f2e947ba6b16d458ccd1000000000000000000000000000000001271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4000000000000000000000000000000001407ffc2c1a2fe3b00d1f91e1f4febcda31004f7c301075c9031c55dd3dfa8104b156a6a3b7017fccd27f81c2af222ef000000000000000000000000000000000a29e38da2d42fd4712052800c7c8dd6e94fd9f506e946068aaac799d60b94c2d7515769ffdd32ea95d3910330ec47de000000000000000000000000000000000c60dae92451206390e30b5daa7151d63624dee496753c87dd54eadc92dc9602081fae02a1a53bac97e984a571923a5d00000000000000000000000000000000085f4fda4c72328895f20c683cb49603a37ff2c43d62f66602506dad5b8d1daebfbac7a7db3f50ccf4dfff277deb105c0000000000000000000000000000000005674d005457e0fe1f0fd978d63996c5f3d29f9149ee4eb04c464742dd329ccaef5e5f6b896d986ddfc9f1b2a3aec13100000000000000000000000000000000071bc66d6e2d244afc4a5ce4da1dce3d0c22c303ba61310fdf57843bbd97763ef496833dfa99d14be084bb1a039bb2da0000000000000000000000000000000012c22e047b0af8e2f4bf3bd3633ef0f8264004ca8ea5677a468857a1762f815235a479e53f4ad4741ffda3fb855021c900000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "bls_pairing_10paircheckstrue",
+ "Gas": 345000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a550000000000000000000000000000000004523f5a3915fc57ee889cdb057e3e76109112d125217546ccfe26810c99b130d1b27820595ad61c7527dc5bbb132a9000000000000000000000000000000000186a1da343cacf1815b9c8b6c807f536249dbfdb59d77bf4920ad2198a0d83ada21f7c39de6f06a5599f22571cab288d000000000000000000000000000000000ba1ec44f95121bd622932b84bbb4b3d279f69c494ee44db68e3165c86b627ba5e397ee197313fb5b775972798997332000000000000000000000000000000000783e7493e9fb106fa0d085e7c03eb816468d12c65d9b77643ed07c02583d491f4db5db44e565d50d8ccaa9ad8f7f8e80000000000000000000000000000000010a6a5fd90cd5f4fb6545814f5df065b001074bb3f29f649dd2612815df3a19a320f7754dd3d458e48e7fb1b4953978f000000000000000000000000000000000345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c00000000000000000000000000000000083d3baf25e42f2845d8fa594dda2e0f40a4d670dda40f30da0aff0d81c87ac3d687fe84eca72f34c7c755a045668cf100000000000000000000000000000000129c4945fe62538d2806fff056adac24f3bba8e17e42d82122affe6ad2123d68784348a79755f194fde3b3d448924032000000000000000000000000000000000528590e82f409ea8ce953f0c59d15080185dc6e3219b69fcaa3a2c8fc9d0b9e0bc1e75ec6c52638e6eaa4584005b5380000000000000000000000000000000018dc3e893f74729d27dd44f45a5a4f433dcd09a3b485e9d1c2bd0eb5e0e4c9024d928ddc426fdecae931e89885ee4db4000000000000000000000000000000000d6ee02e1fc7e52a8e1ef17e753065882c6fcc14da61da7ffe955fe84a9d2af9ba57562c69db3088652931bf124b0d5300000000000000000000000000000000051f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e000000000000000000000000000000000b6a63ac48b7d7666ccfcf1e7de0097c5e6e1aacd03507d23fb975d8daec42857b3a471bf3fc471425b63864e045f4df00000000000000000000000000000000131747485cce9a5c32837a964b8c0689ff70cb4702c6520f2220ab95192d73ae9508c5b998ffb0be40520926846ce3f100000000000000000000000000000000101e147f8bd7682b47b3a6cc0c552c26ce90b9ce0daef21f7f634b3360483afa14a11e6745e7de01a35c65b396a1a12700000000000000000000000000000000090ca61ed16c4c1e80acfef736eea2db0d7425d9110cb53e6c4a2aa3f8a59ee6c60bdce8df5825011066d44bef84d29600000000000000000000000000000000028207394adcbf30250ac21a8f1db6283580bc5e39159930552e5edb25e6215c66b6450296edc80dbc3a2acd125dab160000000000000000000000000000000019bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3000000000000000000000000000000000adb3250ba142db6a748a85e4e401fa0490dd10f27068d161bd47cb562cc189b3194ab53a998e48a48c65e071bb541170000000000000000000000000000000016cfabbe60d1e55723a0ff72cf802f2d1cf13ed131e17729adc88522a657f320a336078a9399c8e61a3bbde3d52fd3640000000000000000000000000000000009aa9a3c2a6d49d286aa593c6ff644f1786fa9ae471bdb3fe70b150a9ed7584eaa886ac057c30005c3642f65ad5581cc0000000000000000000000000000000001d417894c0cce924955a795b188b27951f8438a5485404b921a42fa79dea03c10e29d0390df2f34d7be13f360a7fada00000000000000000000000000000000189b0b3a04e6c613899d51231dbf0cba6a8a8f507ebed99d24fba7ebac6c97a8859ffde88e6d95c1a9d6b4f0a8f3c417000000000000000000000000000000000d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a414950835820000000000000000000000000000000009d0d1f706f1a85a98f3efaf5c35a41c9182afc129285cf2db3212f6ea0da586ca539bc66181f2ccb228485dd8aff0a70000000000000000000000000000000016cad7807d761f2c0c6ff11e786a9ed296442de8acc50f72a87139b9f1eb7c168e1c2f0b2a1ad7f9579e1e922d0eb309000000000000000000000000000000000d3577c713fcbc0648ca8fbdda0a0bf83c726a6205ee04d2d34cacff92b58725ca3c9766206e22d0791cb232fa8a9bc3000000000000000000000000000000000f5ea1957be1b9ca8956ba5f6b1c37ea72e2529f80d7a1c61df01afcc2df6f99ced81ac0052bd0e1e83f09d76ad8d33b000000000000000000000000000000000aabced4e2b9e4a473e72bf2b1cc0ce7ab13de533107df2205ed9e2bb50fa0217e6a13abcd12fce1bda1ccf84dac237a00000000000000000000000000000000073eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086000000000000000000000000000000001825bacd18f695351f843521ebeada20352c3c3965626f98bc4c68e6ff7c4eed38b48f328204bbb9cd461511d24ebfb3000000000000000000000000000000000029ea93c2f1eb48b195815571ea0148198ff1b19462618cab08d037646b592ecab5a66b4bc660ffd02d1b996ca377da000000000000000000000000000000000bb319a4550c981ee89e3c7e6dcc434283454847792807940f72fd2dbf3625b092e0a0c03e581fd9bd9cf74f95ccef15000000000000000000000000000000000abb072b8d9011e81c9f5b23ba86fdb6399c878aa4eadee45fb2486afe594dffc53be643598a23e5428894a36f5ac3ce0000000000000000000000000000000005d04aa0b644faae17d4c76a14aa680c69fdfc6b59fee3ef45641f566165fced60cbbda4ca096e132bb6f58ab4516686000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436000000000000000000000000000000001065f2a2d29a997343765f239c99a018490eced40ac42fc93217dfe20d8b43ee2215f65166aff483b3dc042c5a43b196000000000000000000000000000000000766e4c66f4a442ff1f61a7a4d197d2b47dd226d0e7822a9b065108cfc643cd3f3d5ae59ed2ce4cde13fd9260bb5b7cc0000000000000000000000000000000012251cc6abbabeb7bbe1fdd63eaee10832a748fff24f7e3fdccaea87facb6e99f2e0407a38f27f90450a471b873104620000000000000000000000000000000011181e08c8fba91271adfee9d31681f8412ab7a3f754f7ba4709024c0ad2287e32dd455d71a296b4838072a8ab9d96f2000000000000000000000000000000001252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada0000000000000000000000000000000002a1bc189e36902d1a49b9965eca3cb818ab5c26dffca63ca9af032870f7bbc615ac65f21bed27bd77dd65f2e90f53580000000000000000000000000000000005a7445f55add1ed5c143424ceef3d594280e316c9441a8e68c3ad97377141d015bf878bdfcf0df9fbcd0529f4e8100800000000000000000000000000000000192b52ba08ed509fc84d5775a7182498fd1ff80941d673c53470c9c9f1192f9c0057d68a1dfee0c68fe5df3625cc43bf000000000000000000000000000000000d3fcaf2f727e0eb32c65da9b910dc681b948dda874d0db6f6ed3f063430fbf073385a9a14c2dd78568726124e2b3ea8000000000000000000000000000000001943ce22cdb2387bd5796950dc95d1ace4012ab9bb4afb46223760230c1709e075f1ae76d6b3f2e947ba6b16d458ccd1000000000000000000000000000000001271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4000000000000000000000000000000001407ffc2c1a2fe3b00d1f91e1f4febcda31004f7c301075c9031c55dd3dfa8104b156a6a3b7017fccd27f81c2af222ef000000000000000000000000000000000a29e38da2d42fd4712052800c7c8dd6e94fd9f506e946068aaac799d60b94c2d7515769ffdd32ea95d3910330ec47de000000000000000000000000000000000c60dae92451206390e30b5daa7151d63624dee496753c87dd54eadc92dc9602081fae02a1a53bac97e984a571923a5d00000000000000000000000000000000085f4fda4c72328895f20c683cb49603a37ff2c43d62f66602506dad5b8d1daebfbac7a7db3f50ccf4dfff277deb105c0000000000000000000000000000000005674d005457e0fe1f0fd978d63996c5f3d29f9149ee4eb04c464742dd329ccaef5e5f6b896d986ddfc9f1b2a3aec13100000000000000000000000000000000071bc66d6e2d244afc4a5ce4da1dce3d0c22c303ba61310fdf57843bbd97763ef496833dfa99d14be084bb1a039bb2da0000000000000000000000000000000012c22e047b0af8e2f4bf3bd3633ef0f8264004ca8ea5677a468857a1762f815235a479e53f4ad4741ffda3fb855021c900000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "bls_pairing_10pairchecksfalse",
+ "Gas": 345000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992fee0000000000000000000000000000000017c9fcf0504e62d3553b2f089b64574150aa5117bd3d2e89a8c1ed59bb7f70fb83215975ef31976e757abf60a75a1d9f0000000000000000000000000000000008f5a53d704298fe0cfc955e020442874fe87d5c729c7126abbdcbed355eef6c8f07277bee6d49d56c4ebaf334848624000000000000000000000000000000001302dcc50c6ce4c28086f8e1b43f9f65543cf598be440123816765ab6bc93f62bceda80045fbcad8598d4f32d03ee8fa000000000000000000000000000000000bbb4eb37628d60b035a3e0c45c0ea8c4abef5a6ddc5625e0560097ef9caab208221062e81cd77ef72162923a1906a40",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_0",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed200000000000000000000000000000000192fa5d8732ff9f38e0b1cf12eadfd2608f0c7a39aced7746837833ae253bb57ef9c0d98a4b69eeb2950901917e99d1e0000000000000000000000000000000009aeb10c372b5ef1010675c6a4762fda33636489c23b581c75220589afbc0cc46249f921eea02dd1b761e036ffdbae220000000000000000000000000000000002d225447600d49f932b9dd3ca1e6959697aa603e74d8666681a2dca8160c3857668ae074440366619eb8920256c4e4a00000000000000000000000000000000174882cdd3551e0ce6178861ff83e195fecbcffd53a67b6f10b4431e423e28a480327febe70276036f60bb9c99cf7633",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_1",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f000000000000000000000000000000000a69d6d9f79e19b38e6bf5a245dc820bddbdfe038d50932f76d0e4629d759f8ca6d573fcfc39256305daedf452f9fdf40000000000000000000000000000000015f5949369e58487afcecf8018775d1b0a73e913bf77e13d2e5a843bbbeba7d1978ca27ae8bfc87d30f567dd396b980e00000000000000000000000000000000182198bb38a0353b8db25389e56ab0d8679a1bda008a65dad77e4c95bc6804f6311eb16c761e1a5e2a5f87cfada49fa4000000000000000000000000000000000eb5483959e98c30e71db52615f63521378b156f142d46f3bb285b94aef39d80feacec335b797c5a68dc17ba89d43e0f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_2",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e4000000000000000000000000000000000286f09f931c07507ba4aafb7d43befe0b1d25b27ecc9199b19a9dc20bc7ec0329479ef224e00dece67ec0d61f1ca5ae0000000000000000000000000000000014e6ed154b5552be5c463b730b2134f83e0071dcdadfaa68e6c7c7f6e17dabb7daf06e409177bc4b38cfdb8248157618000000000000000000000000000000000f145e998dc6eb0c2b2be87db62949c7bfa63e8b01c8634248010fd623cfaec5d6c6c193331440957d333bf0c988b7b10000000000000000000000000000000002a1ab3eea343cfdea5779f64b3bddbf0769aded60e54a7507338f044310ba239430663394f110e560594d6042a99f1c",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_3",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d3000000000000000000000000000000000d1007ca90451229d3780d66d3aed7c9d8fc82e9d45549e8586600e38eb6763f3c466e2f6ba6ba1dafd8f00cc452dda20000000000000000000000000000000001d017d920a262b6d6597bab532f83270f41526409510e80278d1c3595ceabb9ceba8ae32b1817297ff78ea7a0d252e8000000000000000000000000000000000935b7a59d2e51bbb2f9b54ccb06ebee9d189fa82f0e97d10c8020badb3de7fe15731b5895faed8cad92ae76e2e1b649000000000000000000000000000000000792dadd48a20040ad43facedc109747411895180813349d41d0e5b389176bfb15895d41665be8d1afa80835ef818eca",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_4",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f9000000000000000000000000000000000095353ad699b89ac82ca7ef631775b2b3a6e3ed8dd320440cdb929baa428e63cb902a83857cc0e2621470544c69e84aa000000000000000000000000000000000892559ade1060b0eef2cbc1c74de62a7ff076a3621e5f0f159672a549f1201f2ffb3ac12c8b12cb86ae3e386c33e219000000000000000000000000000000000750df4632a7126ddb08658a4001f949b9764d9cc43a9393cc55d8fdbb15d4a1186dd87a6433d111888a7804540ad9fc0000000000000000000000000000000017554bd444665df044b91b0b2614017bbfcd7acc7f8c5a16cea2861235578ce2b27dcced9fba234999fa478cd3f6e42d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_5",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1b00000000000000000000000000000000175dadb6ee656ec6aebf8d0e5edaee3f119c74e0ea64e374be9e8ab9fd3d085fceeedf4ed8de676ebe9065d83b0542ad0000000000000000000000000000000005cd6a875329c23e4918976cf997e93e403957acfc999f8159a630d21ab6f1762925c063784237262bedc82402ad81bb0000000000000000000000000000000003274bcb8db35e50164d136c2a98b5a6d2fb5f9767d0ee11c1358bf7ca5ed96d9122f8c1051ba3c658cc89777d03dfa5000000000000000000000000000000000380a240443dff85b6542f75db28b87c39e278cdb8d9627efbbc63b229e6ce783f6fb0114c8e91c2fd6ea71c95bb99a4",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_6",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442a000000000000000000000000000000000834cf1b4149d100c41b1bca0495e455002eb6596bddcb94ae48d0c65957e8b313372f8e0d6e57504664b266f38293150000000000000000000000000000000000de2875fbd14760bac4c2cc7d3f239177efe9f7f61f767be420d44f24c9fb863efd60dcd732986db8c5b72470617ea60000000000000000000000000000000000bc9535ebf11c2dcc8c7d3bcd09d7d14035635fccb5fddb7df29ce8855e79f99809781d6ffbbcb33d1227314609abee00000000000000000000000000000000039bbfb4d969d702255e3be7f255a97529a19687ce38cb70637c37894d4102591feef428b0afe8c9ef50310ae3b83091",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_7",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795000000000000000000000000000000000fc09c241899fa6e8cc3b31830e9c9f2777d2bc6758260c9f6af5fce56c9dc1a8daedb5bcb7d7669005ccf6bfacf71050000000000000000000000000000000018e95921a76bc37308e2f10afb36a812b622afe19c8db84465ab8b3293c7d371948ee0578dbb025eed7ed60686109aa0000000000000000000000000000000001558cdfbac6ea2c4c1f4b9a2e809b19e9f4ba47b78d2b18185ed8c97c2f9c2990beadc78b85c123b4c3c08d5c5b3bbef000000000000000000000000000000000ea4dfdd12b9a4b9a3172671a6eafed7508af296813ec5700b697d9239ae484bcf7ab630e5b6830d6d95675be5174bb2",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_8",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a1900000000000000000000000000000000000b36d8fb9bd156f618ab8049d41dfe0698218764c0abb10e12fae43c8810b8e2a5201364e2778f6f433b199bb8f9a6800000000000000000000000000000000000707eb15411b63722b4308c0ed4288320078d2463ae659ad4fb3f9ef8124f379df92d64e077403e50727388adb59ac00000000000000000000000000000000158e1249d5b91614924acb23899c6bae408697dec0982c10d0459746499f4e6739afb9d5129568106ed1a1caefeaa9640000000000000000000000000000000019e841562e4aa75321143f8ce1e5ec6158fa5cb8b98c839a486188260c18ee8a7600930f23aa39eac2eb520d6a0fba90",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_9",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac94300000000000000000000000000000000186a9661d6fb539e8687ac214301b2d7623caedd76f4055089befba6ef2c96263d810921ad7783d229f82783c9def424000000000000000000000000000000000447f3e20caa1f99fbaccab7bde2bd37fe77cea691ebf2b9499f95bbbb77afe72b7039eb0c05970b61360fcf8ade73730000000000000000000000000000000005e11f828eda86c10a1d7929def547ac06885da278afae59c5d95453caf0a2d8ed186fa7c6d0a7ab6e9142cfa4b338190000000000000000000000000000000003d954e61b6ab71042b19e804efccd4956b56662f27f70a9255cec0c464b86c0e83721ad3785dec62dd4a9dd3d6d5d53",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_10",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e0000000000000000000000000000000002b94534aa0ba923bda34cbe92b3cd7a3e263741b120240ff5bdb8b718f094d3867e3fcabeab4a7be39c8f8c4fdd10d900000000000000000000000000000000048711cf6a82534d64d072355cb8fe647808e7e8b2d9ac9ed52eb7fe121647a721dd1234c71ecd163d91701eb7331cac00000000000000000000000000000000141ef2e23a1ecc7ef2ed3ea915492e79cfffe60b5e0de8441e878bd0653843d79c724e3c5ebe2321361df99f8932ddc200000000000000000000000000000000085513b4009f29b3e00a91c2c4be418368560802ba4194cbd2f4fa3d72a55fcae547014434514a8b2a8fe3e0b28d2773",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_11",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276b0000000000000000000000000000000009143507a24313ee33401955fc46562c9b20c9917df3b40ccbd7ed43b1349d4551cfd98a4976d6fec5fc289460c8d89900000000000000000000000000000000060566b79df5cc975e669da8ca3a7fa91bf3f5c9fb871c3d62f4a3e79dbc341b89d38b588e5414bc385d5e3cbf3ab9310000000000000000000000000000000016bf40b8cc4c01a87aafae0c4439b623a51ba9a383756a550b69d627d6f45209f0d87e4f9be9edff35c986f7b9c49e3f000000000000000000000000000000001842d9172bce51a164fbdbdb108d0faae07e4642f21c80e40ac31e737657472ae3dfe552b65349629c210a068c4afc0e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_12",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a5787681000000000000000000000000000000000ab19bbddd661e9db8fe4cb307ecebdc5e03efbb95c5b44716c7075bd60efcfc67de0bfd7c46ad989a613946c90a4c1000000000000000000000000000000000120800e7f344cda816299fa37f603ade06beb3b10907f5af896d6b4e42f7f865b756f14164db84411c56cb2ea81f60be000000000000000000000000000000000f688ddd257e66362af1437b6922d3397a7c3dd6dea6bca8ebd6375e75bf2de40bc287cbf3434388191e56b92949c83b0000000000000000000000000000000005252465784aff8c1c707da58b5808c69583bf852d68f96912bc53f8dae4536b09ccbbd25a49d9e744118992b92b6792",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_13",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f768000000000000000000000000000000000e3165efe00f69aee84ac56d2161f07c017abfaadeaad34f8c96799d68bae0e6f9b557bbf9137e7826f49f29c58d1ef9000000000000000000000000000000000de0dce7ea371ad60f21f2cb61cb582b5072408a7efc91edf05b36a1a3b58fd9e6cf808d75157eedccc8f1c93a8ae07d0000000000000000000000000000000016d911943d80427385ebac1d1b293914a9e4dd9db06c1d6a758192d63c8fc9368e02eae7fb0e3a7859408f215cfa76ca0000000000000000000000000000000007bfdc6afb8acec625e50ecbc08a5cdb7862b795866323679885ba5cba3fd51f181078e03fe35e96e6383c077eed1bf5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_14",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931d000000000000000000000000000000000a68dccbe3452731f075580fe6102b8ee5265007ee19c56d95bcb096a3a6ac444f4145b980f41afcb0a865853b279bc600000000000000000000000000000000164767ea55a9038ac2dd254d8c8a4970dba93dacdf5416aecaa407914719cab165e7a32784b2c41652a86358737d831f000000000000000000000000000000000da9441fbc6578c85fdeca49082c9ebbf183de894d67c65158380ee56132d3cdb44b100d72b6d3b82688defb75d2aa390000000000000000000000000000000017d570e4f6e46550679d5d12c347414da207060f594620e2f8db66df8e0b06c912290b207a268e782d4b45db19a199db",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_15",
+ "Gas": 138000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d500000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd8000000000000000000000000000000000118cd94e36ab177de95f52f180fdbdc584b8d30436eb882980306fa0625f07a1f7ad3b4c38a921c53d14aa9a6ba5b8d600000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_16",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debe0000000000000000000000000000000001c2d8d353d5983f22a5313ddd58fdc0d9c994b2915dbc87a9b65b7b98ff00b62e140a27dc322d42b3ad190c1b3728dd0000000000000000000000000000000010412f3625947b38bb380a6ed059f1677b7a7afcb91517837c563dadd0e285b95740a200ddff6570d4d92bb636b625bb0000000000000000000000000000000015f4f9a480a57bd1b2388532ab045a1ba93d2f6589a3022c585fe06a1d611165c99d70be06251812405c9c37d6e9f7730000000000000000000000000000000001a78e6c5062a6634a56e9853ff5afacb2e7cf31fd0ea5f0d8c8ac6174c88133cf2f63450ec4590544c9a0e37daac1f900000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a6700000000000000000000000000000000018c690fc5571f69793ec3c82915ac9513726ec891312f4f11dd3ba0ee95cc98b50d925099b0642e58a106e8456bbcbed0000000000000000000000000000000001c2d8d353d5983f22a5313ddd58fdc0d9c994b2915dbc87a9b65b7b98ff00b62e140a27dc322d42b3ad190c1b3728dd0000000000000000000000000000000010412f3625947b38bb380a6ed059f1677b7a7afcb91517837c563dadd0e285b95740a200ddff6570d4d92bb636b625bb0000000000000000000000000000000015f4f9a480a57bd1b2388532ab045a1ba93d2f6589a3022c585fe06a1d611165c99d70be06251812405c9c37d6e9f7730000000000000000000000000000000001a78e6c5062a6634a56e9853ff5afacb2e7cf31fd0ea5f0d8c8ac6174c88133cf2f63450ec4590544c9a0e37daac1f9",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_17",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb6000000000000000000000000000000000818e567aea83eaf3142984bb736b443743659626c407987b604a30c79756081fa6ae6beeb2e6c652dbfe9cf62d44e3900000000000000000000000000000000193f0317305fde1046acda2c9491e376aa67244f68ef6495845d049e1293082af91f880be935d9d8ad0e25ad918caae200000000000000000000000000000000109224b8178be58ea4e4a194ca66bef9d14f6fc2c625d25feaa4f32e0f4d72d91024d96839bc96e6a624c5ad6221bd94000000000000000000000000000000000e42decf8a987efaeb4ede37236b637e61249bf6245679be7fd4d633e2d814ed4748b73890ad3c4fcbcfb4960cb67ae70000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e88000000000000000000000000000000001129c94e0c06f51f1f808a62e42a5449dd159289c14a09c4cc382c91bcfe878b6f3555767c310de1b1c275eb3d17bcf5000000000000000000000000000000000818e567aea83eaf3142984bb736b443743659626c407987b604a30c79756081fa6ae6beeb2e6c652dbfe9cf62d44e3900000000000000000000000000000000193f0317305fde1046acda2c9491e376aa67244f68ef6495845d049e1293082af91f880be935d9d8ad0e25ad918caae200000000000000000000000000000000109224b8178be58ea4e4a194ca66bef9d14f6fc2c625d25feaa4f32e0f4d72d91024d96839bc96e6a624c5ad6221bd94000000000000000000000000000000000e42decf8a987efaeb4ede37236b637e61249bf6245679be7fd4d633e2d814ed4748b73890ad3c4fcbcfb4960cb67ae7",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_18",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154b000000000000000000000000000000000ca0d865f8c8ce0a476f7a6edb3ce4bd5e6c3a8d905d8fb5a10e66542f4325a9963c2f8d96f804f4d295f8993b5204df0000000000000000000000000000000005a966f6254f0ef4f93f082a97abe07db56f00c2ade047d2f0027edef6f00a0dfecaa24d50faa778fa29087302211f7e00000000000000000000000000000000121c51da366557c09af1bbd927521da88dfab3e2e9a95b6effb0a968795486f281f0c887e37f51837557b9e3808987130000000000000000000000000000000001a5524975400b1e88f3fff8dd34dadf5d75564cfc0026df31ee9c2c1d48b0f69a48e1e4a48cc4b7db61f023a79157800000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000f46a7dee0cb471ddef3a50670a5bfc443b8455877f1ff602b21faff1eff07fc6bf27930ca2159f01479359548339560000000000000000000000000000000000ca0d865f8c8ce0a476f7a6edb3ce4bd5e6c3a8d905d8fb5a10e66542f4325a9963c2f8d96f804f4d295f8993b5204df0000000000000000000000000000000005a966f6254f0ef4f93f082a97abe07db56f00c2ade047d2f0027edef6f00a0dfecaa24d50faa778fa29087302211f7e00000000000000000000000000000000121c51da366557c09af1bbd927521da88dfab3e2e9a95b6effb0a968795486f281f0c887e37f51837557b9e3808987130000000000000000000000000000000001a5524975400b1e88f3fff8dd34dadf5d75564cfc0026df31ee9c2c1d48b0f69a48e1e4a48cc4b7db61f023a7915780",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_19",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af0000000000000000000000000000000002b51851ef3b44481d13f42e5111fa4fec04be0bf6acc7e59dec3a8c8113e5bb7b604c6dbdc5e8eddc2a1ffb81bc2baf0000000000000000000000000000000018ddb483ae75402852b7f285277ff7308ff78a3364cca8b0e0e1fa9182de275fd55c1e8ec3dbde180379c4280787ba8000000000000000000000000000000000170539890c89a4f91acd59efd413b5d1059f0c8fd8718e8f722e865dd106a4eb02e6fb0cd71b34ebc4b94375b52e4dd60000000000000000000000000000000001c2e9392f5d4b75efc5ff10fe97f37e2671cad7e4710765866e92aec99b0130e6ff1314502d069fb7b5f86bfce4300e0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b090000000000000000000000000000000011dbce34af6cb14d3e4d49f2482e1b058609f25dca79e2ca48e289ace9d1c8db177b7bc35daad79aa5fdac77728bd5fc0000000000000000000000000000000002b51851ef3b44481d13f42e5111fa4fec04be0bf6acc7e59dec3a8c8113e5bb7b604c6dbdc5e8eddc2a1ffb81bc2baf0000000000000000000000000000000018ddb483ae75402852b7f285277ff7308ff78a3364cca8b0e0e1fa9182de275fd55c1e8ec3dbde180379c4280787ba8000000000000000000000000000000000170539890c89a4f91acd59efd413b5d1059f0c8fd8718e8f722e865dd106a4eb02e6fb0cd71b34ebc4b94375b52e4dd60000000000000000000000000000000001c2e9392f5d4b75efc5ff10fe97f37e2671cad7e4710765866e92aec99b0130e6ff1314502d069fb7b5f86bfce4300e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_20",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719290000000000000000000000000000000011bbc566a10eadf16009c1d2655cfae6adfb0f56f5e55b31dc000414be1b4cee9a0b9f7d9eab4c6829037c327914d5640000000000000000000000000000000009b28329096d8644dfcba6e92477eafff29f7477da4581ce76d1493f03034d7f5d3acaadbe42c76a83ca51db79d456d10000000000000000000000000000000019f75a303fdede5d97f3e521b03ef6b9d7c008d770b59ce3ac38900b340895e008342701ad1b41830b9c010936f4ff1700000000000000000000000000000000161aa1853edbb56fa3bd685c9c6b88e466dfa3c4f194f6774b4d9b1f30b016993bd0d65e8e9d6dea6caa196ff735bd6700000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000108248cdc6f503c7bad30eac875d92a75feccbdbe7b5394f8557a92bb12a796430a2c60ca23c6ecd259e5b01e53891820000000000000000000000000000000011bbc566a10eadf16009c1d2655cfae6adfb0f56f5e55b31dc000414be1b4cee9a0b9f7d9eab4c6829037c327914d5640000000000000000000000000000000009b28329096d8644dfcba6e92477eafff29f7477da4581ce76d1493f03034d7f5d3acaadbe42c76a83ca51db79d456d10000000000000000000000000000000019f75a303fdede5d97f3e521b03ef6b9d7c008d770b59ce3ac38900b340895e008342701ad1b41830b9c010936f4ff1700000000000000000000000000000000161aa1853edbb56fa3bd685c9c6b88e466dfa3c4f194f6774b4d9b1f30b016993bd0d65e8e9d6dea6caa196ff735bd67",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_21",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac000000000000000000000000000000000ae7289aa9bf20c4a9c807f2b3ac32f0db24e9a0a360c92e5ce4f8253f0e3e7853f771597c8141d705062bef12d4fea80000000000000000000000000000000001d2f610d79110f93145faad2e34f3408316b1dc3a72852e811b324577d9037035e24af25002ddd100cd9283b70ddcad0000000000000000000000000000000012947315d5c0ec670619125eed0de3dd259a008baee4379b82accf2391e70a2bdad264cda04c3bc1b5394a62559fa0ef000000000000000000000000000000001239e687c4d3417c3c9b655035f8d8a649c255f9a8e6f03b785eed0d416a1cd6ef7c8b45563acb4616af24f64dbccac4000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed30250000000000000000000000000000000006f1fe4d98675ffc62d4d5dd0af9968faca4d0ef425d56fa31b80aea892820e270f6da17aec9eb83c6cc9f84289ecbff000000000000000000000000000000000ae7289aa9bf20c4a9c807f2b3ac32f0db24e9a0a360c92e5ce4f8253f0e3e7853f771597c8141d705062bef12d4fea80000000000000000000000000000000001d2f610d79110f93145faad2e34f3408316b1dc3a72852e811b324577d9037035e24af25002ddd100cd9283b70ddcad0000000000000000000000000000000012947315d5c0ec670619125eed0de3dd259a008baee4379b82accf2391e70a2bdad264cda04c3bc1b5394a62559fa0ef000000000000000000000000000000001239e687c4d3417c3c9b655035f8d8a649c255f9a8e6f03b785eed0d416a1cd6ef7c8b45563acb4616af24f64dbccac4",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_22",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff32000000000000000000000000000000001179ee329771b5913d07818e70f6ce5a58d74ea0b573eaa1bd3d97e45d3eeb27fcc7d37dba127af7a38354cb6ff48f7c000000000000000000000000000000000c898abe6eb76ef99f5143cfb8d840a918bcc9096ce25caa45d0bf5d20814cb01b024f1fd2cbecb6bef65d9456070dd90000000000000000000000000000000008e2a4fd746e86f90484f9b9b7b47b6afe5833762e515ccb276c554f00df88dd9aa0fb792c5f419dda0465cfed838e7c0000000000000000000000000000000012b5e6f7070c0045ade96f548ed6428c5030fa20c6f6f37a42fde9dbb5cd01def0fd8585bf8aeef913e7d42b9ef22efa0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e705800000000000000000000000000000000091ce9e6c4bab3ad3d275cf5888387646c3d9bb53ace7bd0c118fce3e44fcd96241b58e5af53978272f56d04b7d7ab79000000000000000000000000000000001179ee329771b5913d07818e70f6ce5a58d74ea0b573eaa1bd3d97e45d3eeb27fcc7d37dba127af7a38354cb6ff48f7c000000000000000000000000000000000c898abe6eb76ef99f5143cfb8d840a918bcc9096ce25caa45d0bf5d20814cb01b024f1fd2cbecb6bef65d9456070dd90000000000000000000000000000000008e2a4fd746e86f90484f9b9b7b47b6afe5833762e515ccb276c554f00df88dd9aa0fb792c5f419dda0465cfed838e7c0000000000000000000000000000000012b5e6f7070c0045ade96f548ed6428c5030fa20c6f6f37a42fde9dbb5cd01def0fd8585bf8aeef913e7d42b9ef22efa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_23",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f2000000000000000000000000000000000fe2e61bc8e9085d2b472a6791d4851762d6401fd3e7d3f3ba61620dc70b773f2102df1c9d6f1462144662fb2f15359700000000000000000000000000000000031f160cde626ca11f67613884a977fb5d3248d78ddbf23e50e52c3ba4090268c1f6cd8156fa41d848a482a0ca39eb04000000000000000000000000000000000eb61ba51124be7f3ee9be1488aa83cbd2333aa7e09ae67fef63c890534cb37ca7de3d16046b984e72db21e1f5c57a8a0000000000000000000000000000000006bf6f5d65aa7d19613141018ac8bf5d1e6fe494a9f30da215a2313a0241779006bce33a776aeedae5de5ea6ee5a9b9e0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000b4322c2fb5d5dd2c65b45f74ca75002c97444d8d4e5680d0369d32d180c93b294e30ef42f21ac274f77ad89633ab1b9000000000000000000000000000000000fe2e61bc8e9085d2b472a6791d4851762d6401fd3e7d3f3ba61620dc70b773f2102df1c9d6f1462144662fb2f15359700000000000000000000000000000000031f160cde626ca11f67613884a977fb5d3248d78ddbf23e50e52c3ba4090268c1f6cd8156fa41d848a482a0ca39eb04000000000000000000000000000000000eb61ba51124be7f3ee9be1488aa83cbd2333aa7e09ae67fef63c890534cb37ca7de3d16046b984e72db21e1f5c57a8a0000000000000000000000000000000006bf6f5d65aa7d19613141018ac8bf5d1e6fe494a9f30da215a2313a0241779006bce33a776aeedae5de5ea6ee5a9b9e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_24",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c200000000000000000000000000000000196044a5cdbc5300ee837dca745a44379070e9297697f5db28df4a37307cc740abed45cc778a3f4e3b8c9890ab6c3c70000000000000000000000000000000001176f5de6a3577ad67863bd3d9152ab9e8184964c6ac276e95946788f5a76394047580077c0971d874a40d510eb0443e00000000000000000000000000000000147dd55dff69213c5760e8d22b700dd7a9c7c33c434a3be95bd5281b97b464fb934a3dff7c23f3e59c5d8d26faa426bf0000000000000000000000000000000019efcf03ddb0934b0f0dba3569809d5b48b863d50d3be4973b504244414e1e1db56adff51d33265ce102b320c552781f000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b100000000000000000000000000000000081162fe2e65a642993ba283df9bc8d60bfe495b2dc5623f0467c87bc7570980be2654c8cc8838fb362c677f3a3cb1e900000000000000000000000000000000196044a5cdbc5300ee837dca745a44379070e9297697f5db28df4a37307cc740abed45cc778a3f4e3b8c9890ab6c3c70000000000000000000000000000000001176f5de6a3577ad67863bd3d9152ab9e8184964c6ac276e95946788f5a76394047580077c0971d874a40d510eb0443e00000000000000000000000000000000147dd55dff69213c5760e8d22b700dd7a9c7c33c434a3be95bd5281b97b464fb934a3dff7c23f3e59c5d8d26faa426bf0000000000000000000000000000000019efcf03ddb0934b0f0dba3569809d5b48b863d50d3be4973b504244414e1e1db56adff51d33265ce102b320c552781f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_25",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd10000000000000000000000000000000005d8edbabf37a47a539d84393bb2747d0a35a52b80a7c99616c910479306e204e5db1f0fa3fe69f35af3164c7e5726b50000000000000000000000000000000005015082d6975649fbc172035da04f8aeb6d0dd88fdfac3fbd68ec925dc199413ed670488dc6588f9bd34c4ff527f149000000000000000000000000000000001312d53088ca58dfc325772b8dc0e1b20cebf7b2d5b6b4c560759987b44060bf4a59a68d1a5623bbb3cc5b0bc3986b810000000000000000000000000000000012110cd462c6fabf04f67d652639d19640c46f51aadd6c4f9a6dd7806cffb6192d95c198f4c8284151feaa2e2a0dbc1f00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e272839000000000000000000000000000000001324e51f295ea95adedc9730dac2e1ab6d85838840e3955103d76677ce9a7359215f8d954286950bed1be3bbfebabeda0000000000000000000000000000000005d8edbabf37a47a539d84393bb2747d0a35a52b80a7c99616c910479306e204e5db1f0fa3fe69f35af3164c7e5726b50000000000000000000000000000000005015082d6975649fbc172035da04f8aeb6d0dd88fdfac3fbd68ec925dc199413ed670488dc6588f9bd34c4ff527f149000000000000000000000000000000001312d53088ca58dfc325772b8dc0e1b20cebf7b2d5b6b4c560759987b44060bf4a59a68d1a5623bbb3cc5b0bc3986b810000000000000000000000000000000012110cd462c6fabf04f67d652639d19640c46f51aadd6c4f9a6dd7806cffb6192d95c198f4c8284151feaa2e2a0dbc1f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_26",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc00000000000000000000000000000000117fd5016ddb779a6979d2bffe18032d9a5cdc5a6c7feeaa412381983d49ab894cb067f671163ccbe6225c3d85219db6000000000000000000000000000000000dcf01077dcce35c283bea662f4e4d16f871717eb78e630d9f95a200cc104fe67b0d69d95f6704d9812b46c92b1bc9de00000000000000000000000000000000121f212cd7251697ef6a7e3aa93eb0d7d0157cf1247d4411430c36c7277bf8acfccc4ed8590b5e8d0f760e0e4ed7e95a0000000000000000000000000000000007d22d78b486f575e01e21e1239cbedc4628ba7e01ecf4a3459bd78a9716e2969f26ea3f2449685f60397e1ab2aa7352000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b00000000000000000000000000000000132d85236d655190323279a01acc8cbc6fb736d951e3999589f0559cb61ea93e2e1c526ed08ef08046c3d7a40d7cfdaf00000000000000000000000000000000117fd5016ddb779a6979d2bffe18032d9a5cdc5a6c7feeaa412381983d49ab894cb067f671163ccbe6225c3d85219db6000000000000000000000000000000000dcf01077dcce35c283bea662f4e4d16f871717eb78e630d9f95a200cc104fe67b0d69d95f6704d9812b46c92b1bc9de00000000000000000000000000000000121f212cd7251697ef6a7e3aa93eb0d7d0157cf1247d4411430c36c7277bf8acfccc4ed8590b5e8d0f760e0e4ed7e95a0000000000000000000000000000000007d22d78b486f575e01e21e1239cbedc4628ba7e01ecf4a3459bd78a9716e2969f26ea3f2449685f60397e1ab2aa7352",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_27",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da0000000000000000000000000000000000224cbea61c5136987d8dbc8deafa78ae002255c031bb54335bcf99e56a57768aa127506fca1761e8b835e67e88bb4dd0000000000000000000000000000000018cbf072b544df760c051d394ff68ad2dd5a8c731377fa2a5f61e61481ad5b42645704a2d083c7d45ed4774e5448141e000000000000000000000000000000000740b8b7d7bce78a51809713656c94cf98de72887676050f65f74c57cbe574278dd3634c44e057ea95babcc3d230e3c40000000000000000000000000000000006696058a191c7012a4ee7c973c2005ac51af02a85cbb60e3164809a583b4431dda2b59e1c9ceeb652b3ac7021d116a60000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000a4ec4acf91be994fe45f08dbeb2bbd053275861d11a486693fd6e5bfa3736134396f6b1c3ad146642f2e972ba609d0b000000000000000000000000000000000224cbea61c5136987d8dbc8deafa78ae002255c031bb54335bcf99e56a57768aa127506fca1761e8b835e67e88bb4dd0000000000000000000000000000000018cbf072b544df760c051d394ff68ad2dd5a8c731377fa2a5f61e61481ad5b42645704a2d083c7d45ed4774e5448141e000000000000000000000000000000000740b8b7d7bce78a51809713656c94cf98de72887676050f65f74c57cbe574278dd3634c44e057ea95babcc3d230e3c40000000000000000000000000000000006696058a191c7012a4ee7c973c2005ac51af02a85cbb60e3164809a583b4431dda2b59e1c9ceeb652b3ac7021d116a6",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_28",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e053000000000000000000000000000000001522e0a4ccd607f117fc6fc8f9abcd704e9850d96adb95d9bfaab210b76bfb2c5dc75163b922bd7a886541250bc1d8630000000000000000000000000000000018a6e4327d633108a292a51abed43e95230e951e4476dc385ceea9c72ed528bf3e06c42d10cefbd4aa75b134936e4747000000000000000000000000000000001198587188e793ad2ec2fa0fa1d0da9b61ed48444fe6722e523aeac270f17f73f56b1e726ab811bb54a6e42e506d70a20000000000000000000000000000000004bedd94182e0f16c71223ac3d68ab327d28ee0ccdcd2c2db07faf69e1babe3fbf3ba09c28b146eca7ab047b592947030000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe9760000000000000000000000000000000011dc30871a7a9b33e2882f6b24ccd192aad215edfc6c6bd9acd064dff4a43f41b4c212068875e896daf127547bbeca58000000000000000000000000000000001522e0a4ccd607f117fc6fc8f9abcd704e9850d96adb95d9bfaab210b76bfb2c5dc75163b922bd7a886541250bc1d8630000000000000000000000000000000018a6e4327d633108a292a51abed43e95230e951e4476dc385ceea9c72ed528bf3e06c42d10cefbd4aa75b134936e4747000000000000000000000000000000001198587188e793ad2ec2fa0fa1d0da9b61ed48444fe6722e523aeac270f17f73f56b1e726ab811bb54a6e42e506d70a20000000000000000000000000000000004bedd94182e0f16c71223ac3d68ab327d28ee0ccdcd2c2db07faf69e1babe3fbf3ba09c28b146eca7ab047b59294703",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_29",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265e00000000000000000000000000000000148b7dfc21521d79ff817c7a0305f1048851e283be13c07d5c04d28b571d48172838399ba539529e8d037ffd1f7295580000000000000000000000000000000003015abea326c15098f5205a8b2d3cd74d72dac59d60671ca6ef8c9c714ea61ffdacd46d1024b5b4f7e6b3b569fabaf20000000000000000000000000000000011f0c512fe7dc2dd8abdc1d22c2ecd2e7d1b84f8950ab90fc93bf54badf7bb9a9bad8c355d52a5efb110dca891e4cc3d0000000000000000000000000000000019774010814d1d94caf3ecda3ef4f5c5986e966eaf187c32a8a5a4a59452af0849690cf71338193f2d8435819160bcfb00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000dd1137e592119c134103b9e29e4f14b48387a767d4effae44f807e5b579e7f9c2f60105495f070d0a6ab2410f62844d00000000000000000000000000000000148b7dfc21521d79ff817c7a0305f1048851e283be13c07d5c04d28b571d48172838399ba539529e8d037ffd1f7295580000000000000000000000000000000003015abea326c15098f5205a8b2d3cd74d72dac59d60671ca6ef8c9c714ea61ffdacd46d1024b5b4f7e6b3b569fabaf20000000000000000000000000000000011f0c512fe7dc2dd8abdc1d22c2ecd2e7d1b84f8950ab90fc93bf54badf7bb9a9bad8c355d52a5efb110dca891e4cc3d0000000000000000000000000000000019774010814d1d94caf3ecda3ef4f5c5986e966eaf187c32a8a5a4a59452af0849690cf71338193f2d8435819160bcfb",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_30",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc8000000000000000000000000000000000805892f21889cab3cfe62226eaff6a8d3586d4396692b379efc7e90b0eaad4c9afbdf0f56b30f0c07ae0bc4013343b30000000000000000000000000000000007853f0e75c8dee034c2444299da58c98f22de367a90550dbc635fb52c9a8f61ccc100f70f10208944e48d09507fdce100000000000000000000000000000000064afd6b3ef7ff7ec34f1fa330877b42958a46a7698c6d21adf73bfdfcab7793b312e21e5988652e655f2d42edb8a673000000000000000000000000000000000ea8a2217c3dbcc0f6e562de9cb2f334c896577d0b3a7108d96b1aba2d705dbf531e870d4023cec2c0533455013242330000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad62420000000000000000000000000000000016ad3b981f689f51f46e3e5e166986e4e71655dcc1e928327751ffdcfff8934caec5cc37327b3320202c4efbcfda6ae3000000000000000000000000000000000805892f21889cab3cfe62226eaff6a8d3586d4396692b379efc7e90b0eaad4c9afbdf0f56b30f0c07ae0bc4013343b30000000000000000000000000000000007853f0e75c8dee034c2444299da58c98f22de367a90550dbc635fb52c9a8f61ccc100f70f10208944e48d09507fdce100000000000000000000000000000000064afd6b3ef7ff7ec34f1fa330877b42958a46a7698c6d21adf73bfdfcab7793b312e21e5988652e655f2d42edb8a673000000000000000000000000000000000ea8a2217c3dbcc0f6e562de9cb2f334c896577d0b3a7108d96b1aba2d705dbf531e870d4023cec2c053345501324233",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_31",
+ "Gas": 161000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff170000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f0000000000000000000000000000000004c56d3ee9931f7582d7eebeb598d1be208e3b333ab976dc7bb271969fa1d6caf8f467eb7cbee4af5d30e5c66d00a4e2000000000000000000000000000000000de29857dae126c0acbe966da6f50342837ef5dd9994ad929d75814f6f33f77e5b33690945bf6e980031ddd90ebc76ce00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000cbcd06a1c576af16d0d77ff8bcc3669a486d044cc7b85db03661a92f4c5c44a28d028521dfcfc292d8ecd05aed6ab940000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f0000000000000000000000000000000004c56d3ee9931f7582d7eebeb598d1be208e3b333ab976dc7bb271969fa1d6caf8f467eb7cbee4af5d30e5c66d00a4e2000000000000000000000000000000000de29857dae126c0acbe966da6f50342837ef5dd9994ad929d75814f6f33f77e5b33690945bf6e980031ddd90ebc76ce00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff170000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f00000000000000000000000000000000153ba4ab4fecc724c843b8f78db2db1943e91051b8cb9be2eb7e610a570f1f5925b7981334951b505cce1a3992ff05c9000000000000000000000000000000000c1e79925e9ebfd99e5d11489c56a994e0f855a759f0652cc9bb5151877cfea5c37896f56b949167b9cd2226f14333dd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_32",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3f000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000e751ccbd475fe7eda1c62df626c1d37e8ae6853cc9b2109beef3e8c6f26d41a5e4e0a91bbc3371c7ab6ba780b5db41600000000000000000000000000000000184097644c9b44d543ebc0934825610590cc9f8b17ed08e9c06592bf85591d2702b18cf48a70b378926057e541eb8ac50000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c81292925400000000000000000000000000000000065d3d4be1589a6f00c85c208c44916a35349a096b09219704b4c31861ef58e6b4ea5be57a175b429e482b1038718d6c000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000e751ccbd475fe7eda1c62df626c1d37e8ae6853cc9b2109beef3e8c6f26d41a5e4e0a91bbc3371c7ab6ba780b5db41600000000000000000000000000000000184097644c9b44d543ebc0934825610590cc9f8b17ed08e9c06592bf85591d2702b18cf48a70b378926057e541eb8ac50000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3f000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000b8bf51e6509e81b70ff44d6e0df8f9f7bc8e33126e9f1b5a8419414878a2209c05df56cf590c8e33f484587f4a1f6950000000000000000000000000000000001c07a85ece4a1c5072fe722fb264bd1d3aaabf9db9809d5a6cb3fe17157d8fd1bfa730a26e34c87279ea81abe141fe6",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_33",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9af000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000001869606dde1688e5ae9f1c466c5897fce7794f3735234b5af1ad3617f0688529499bbdc9f0b911840a3d99fd9c49150d00000000000000000000000000000000001bfd33df4a6059608ada794e03d7456e78317145eb4d5677c00d482ac4cf470053d33583cf602feb67b6f972c9973900000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda00000000000000000000000000000000055caff20f9f3f2ea27c64caeb6bb1880f326c64eb6ed6ee7d15da7bfeb16518f76a75f061cd347f7322e0cec634f0fc000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000001869606dde1688e5ae9f1c466c5897fce7794f3735234b5af1ad3617f0688529499bbdc9f0b911840a3d99fd9c49150d00000000000000000000000000000000001bfd33df4a6059608ada794e03d7456e78317145eb4d5677c00d482ac4cf470053d33583cf602feb67b6f972c9973900000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9af000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000000197b17c5b695db49c7c8b6fd6f314da7cfdfc4dbe61c76475839c89064870fad5104234c09aee7bafc1660263b6959e0000000000000000000000000000000019e514b65a358640ea90cd3cf547d591f5ff1a13ad99c568ef70c558cbec26dd1e582cc92d849fcfce9749068d361372",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_34",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c30000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa520000000000000000000000000000000002c536dd2f05f4a7eaa33fd884262b22a2ab2a88e7b63cb08ebb67fc0f143da7d6b18dd394c424161f7cf703acdc82f50000000000000000000000000000000002d1d9ff74e20ea9b03c478784f57e7a58a21ca2b1e552319f33305f367f5ae4daf8138505f953db4f86c0ec1d96d5f0000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000003c0c619be1382199bee84862a0ac6bf4c891d22f722b6af5bfef0edd1ed8c7e9af5efb5d3fc546801f3e019329ae4e80000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa520000000000000000000000000000000002c536dd2f05f4a7eaa33fd884262b22a2ab2a88e7b63cb08ebb67fc0f143da7d6b18dd394c424161f7cf703acdc82f50000000000000000000000000000000002d1d9ff74e20ea9b03c478784f57e7a58a21ca2b1e552319f33305f367f5ae4daf8138505f953db4f86c0ec1d96d5f0000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c30000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa5200000000000000000000000000000000173bdb0d0a79f1f2607867ddbf2581b4c1cc20fc0bced60ed8756aa4e79cb87c47fa722b1c8fdbe99a8208fc532327b600000000000000000000000000000000172f37eac49dd7f09adf602ebe562e5d0bd52ee2419fc08dc7fda241c0319b3f43b3ec79ab5aac246a783f13e268d4bb",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_35",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec350000000000000000000000000000000018db123e05404eea8707f9356f417c3966312b9e41765a6fd8449879ddc4c9850c38434481b235a5bc35db1b8ee86d43000000000000000000000000000000000b4162715717e9065a3849a9294cfe39b351e57ab5a6790f3e725ad9fbf0e4b9d6a3554e872af9c37df33bb896dada5c0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a030000000000000000000000000000000014c22dcacf2e21ff447c94d81067c626b1217e58b7dc98aacab2ea3fc00b1c5e66f660d19f1c69b16571e49d13c8e1d0000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec350000000000000000000000000000000018db123e05404eea8707f9356f417c3966312b9e41765a6fd8449879ddc4c9850c38434481b235a5bc35db1b8ee86d43000000000000000000000000000000000b4162715717e9065a3849a9294cfe39b351e57ab5a6790f3e725ad9fbf0e4b9d6a3554e872af9c37df33bb896dada5c0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec35000000000000000000000000000000000125ffac343f97afc413ae80d40a309dfe461fe6b20eb84f8eec3a2718ec2c9f1273bcba2fa1ca59fdc924e471173d68000000000000000000000000000000000ebfaf78e267fd93f0e35e0d19feae9db125660a3dde99b028be77c6fac0116a4808aab02a29063c3c0bc4476924d04f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_36",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218080000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000f6adad0a3bab3610165be2fadb1b020f25488a0af3d418b7d7cf1165812e17aefcbc23308ebcd31d22ba4ca5773dd87000000000000000000000000000000001657ff792e3d89d5d35767bd0cc788411b0420665a5e0704f4d2399b9d9a5ad3c027ee030fdf495e5a6e2a4c69d0571200000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000010338047b7c67c122ffb13466935623ef2338b32bbf5452f78f7abe9a13a16824c11f5520c9dac256b9d257da88d92a30000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000f6adad0a3bab3610165be2fadb1b020f25488a0af3d418b7d7cf1165812e17aefcbc23308ebcd31d22ba4ca5773dd87000000000000000000000000000000001657ff792e3d89d5d35767bd0cc788411b0420665a5e0704f4d2399b9d9a5ad3c027ee030fdf495e5a6e2a4c69d0571200000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218080000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000a96371995c5333949b5e9869599fcb67222c2e44447d133e9b3e18a9e9e14a92ee03dcba86832cde7d35b35a88bcd240000000000000000000000000000000003a912710b425cc477c43ff93684249649732b1e99270bba725e990559169b505e8411fba174b6a15f90d5b3962f5399",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_37",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c0000000000000000000000000000000004cb55008ccb5b2b8ece69fac7283f5a9ef9e622e2a0e42bed5bdd77faa550882643afc1759b1a327c4f2277e13a3d4f000000000000000000000000000000001690dee40c6c824dc2588fc47dbf93f68ac250b9357e1112db72ded905ed7b101b5f877bdc42d56afb5b6202403a91c4000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000008418a39124b40643dddcd6afe1dbdf930303bca65226c2fee1b95de6e080e25451f8b4f2b2b7c4633e1de6a5a7d47cb000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c0000000000000000000000000000000004cb55008ccb5b2b8ece69fac7283f5a9ef9e622e2a0e42bed5bdd77faa550882643afc1759b1a327c4f2277e13a3d4f000000000000000000000000000000001690dee40c6c824dc2588fc47dbf93f68ac250b9357e1112db72ded905ed7b101b5f877bdc42d56afb5b6202403a91c4000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c000000000000000000000000000000001535bce9acb48b6ebc4d3dbb7c236d7cc57d656210e42e9379d4f528fc0ba59bf868503d3bb8e5cd3dafdd881ec56d5c00000000000000000000000000000000037033062d13644c88c317f1c58c18e0d9b4facbbe0701ac8bbdf3c7f0c37b14034c7882d5112a94bea39dfdbfc518e7",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_38",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcb00000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000017078538092ace26cc88b94360871fc9a6bb9992172158ef3a16467919955083accf8d55d48c7ec462a743dbbca7b448000000000000000000000000000000000289b703157a02fc1d687a5aa595495be8bbb3eb0d70554728255a44b7820e0ee82d984d5493c800f1d9d8ca0c9381dc0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000ada13f88a645bc6082c6321e0cf2b7ac45c633fe2f0cb36aeb187fe2e50e7510df2a86b98979e8551636e94488c8ce000000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000017078538092ace26cc88b94360871fc9a6bb9992172158ef3a16467919955083accf8d55d48c7ec462a743dbbca7b448000000000000000000000000000000000289b703157a02fc1d687a5aa595495be8bbb3eb0d70554728255a44b7820e0ee82d984d5493c800f1d9d8ca0c9381dc0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcb00000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000002f98cb2305518737e92ee72e2c48d0dbdbbb1f2dc63b9d02d1a8c27dd1ba5a071dc72a8dcc7813b5757bc244357f6630000000000000000000000000000000017775ae72405e39e2db32d5b9db6637b7bbb9799e614bd783f0b785c3f2ee815367e67b15cc037fec8252735f36c28cf",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_39",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6300000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b600000000000000000000000000000000048b3e4ba3e2d1e0dbf5955101cf038dc22e87b0855a57b631ef119d1bd19d56c38a1d72376284c8598e866b6dba37530000000000000000000000000000000007c0b98cda33be53cf4ef29d0500ff5e7a3c2df6f83dfc1c36211d7f9c696b77dfa6571169cf7935d2fb5a6463cceac6000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a3700000000000000000000000000000000162e49ebd1b50c7837336509e48ace0e7856f00ec45a76b96d1dd88eea300a8118357cafabf32ee2d06b601def523e4800000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b600000000000000000000000000000000048b3e4ba3e2d1e0dbf5955101cf038dc22e87b0855a57b631ef119d1bd19d56c38a1d72376284c8598e866b6dba37530000000000000000000000000000000007c0b98cda33be53cf4ef29d0500ff5e7a3c2df6f83dfc1c36211d7f9c696b77dfa6571169cf7935d2fb5a6463cceac6000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6300000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b6000000000000000000000000000000001575d39e959d14b96f261265417ca949a248c3d46e2abb093541c103dadf58cd5b21e28c79f17b376070799492457358000000000000000000000000000000001240585d5f4c28467bccb5193e4aad78ea3b1d8dfb4716a3310fb5215a478aac3f05a8ed478486c9e703a59b9c32bfe5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_40",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba000000000000000000000000000000001172684b21c4dfe02a55e13b57bbf105c954daec849d4c6df5276b02872c004fdf09d24f4eef366bc82eb72fe91bf70d000000000000000000000000000000001151aeb9441c5a8fabe80867b5c791420645241eae1400bbcc064d75bedd39de2ef585138fe9f65725efa1b1e5888d0300000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000efe47bf2b11dd10608a309c8aaefdbcbc2bb5e6adceef375371cface8f79668e2b7c2ce9990063a3b53e419e80e2a79000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba000000000000000000000000000000001172684b21c4dfe02a55e13b57bbf105c954daec849d4c6df5276b02872c004fdf09d24f4eef366bc82eb72fe91bf70d000000000000000000000000000000001151aeb9441c5a8fabe80867b5c791420645241eae1400bbcc064d75bedd39de2ef585138fe9f65725efa1b1e5888d0300000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba00000000000000000000000000000000088ea99f17bb06ba20c5c67aeb8fbbd19b2270986ee7c6517209679e6f84f5d43fa22daf6264c993f1d048d016e3b39e0000000000000000000000000000000008af6330f5638c0a9f339f4e8d841b955e322766457112039b2a852b37d3bc45efb67aeb216a09a8940f5e4e1a771da8",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_41",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f000000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e000000000000000000000000000000001995b9d697bded656236430e78726f0f6ef963db9a5a24d455c12db38aeab0f8629e5dc2d04920156f2a057d69613096000000000000000000000000000000001119b13caf82c18fadcb65c9c166914bfd822534bb9def3feae6c9e572c97c84e97fab3b345cf59358436a404075493d000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c1872290000000000000000000000000000000001099fe889d8f5ddcad09328997c7c3098ef4b4d74ab1d9f6fcbc33a03cafb59c7b28931da67950d1389fbcedca3fb5bb00000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e000000000000000000000000000000001995b9d697bded656236430e78726f0f6ef963db9a5a24d455c12db38aeab0f8629e5dc2d04920156f2a057d69613096000000000000000000000000000000001119b13caf82c18fadcb65c9c166914bfd822534bb9def3feae6c9e572c97c84e97fab3b345cf59358436a404075493d000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f000000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e00000000000000000000000000000000006b5813a1c1f934e8e564a7cad93dc7f57de7a9592aedeb116fa4ed6bc6452bbc0da23be10adfea4ad4fa82969e7a150000000000000000000000000000000008e760ad89fd250a9d5041ec81e51b8b66f5265037e7237f7c4a08bb83e7799f352c54c37cf70a6c61bb95bfbf8a616e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_42",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5e0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000001bca57e985906695e14882f2aaeef75de5009e8717eb59962e978aa11e9d0a4d9a9e203df774cb1e993b1c6ecd6048c000000000000000000000000000000000695b11cc32740c91546eb7d554ca8b1f3afc942ad977345031be8b94b78b57a87ab049ca2d3676e039efccbf24d0c47000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a9000000000000000000000000000000001750d2e78525453f113b76f18abf2334de9755c03786fbc9233cda2364d57ed493f4fe6c2b565f4d82ff8113e9b63c4d0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000001bca57e985906695e14882f2aaeef75de5009e8717eb59962e978aa11e9d0a4d9a9e203df774cb1e993b1c6ecd6048c000000000000000000000000000000000695b11cc32740c91546eb7d554ca8b1f3afc942ad977345031be8b94b78b57a87ab049ca2d3676e039efccbf24d0c47000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5e0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000018446c6ba126e030ed071f87189cbd618627419c82065d26044759f6e4c7257f45021dfad1dcb34dd06b4e391329a61f00000000000000000000000000000000136b60cd7658a5d135d4bc38edff042570c7824245ed9f7a6414e9e7ab3840a99700fb620e809891b66003340db29e64",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_43",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb8776600000000000000000000000000000000135b3db43511dbd8b3bd5a91880d6da1a2bd1383000e0d6f0a521bf88a5836a3b5f7cb9c0c02aa861a1c2d339f3c11f20000000000000000000000000000000000e1337271bd3302a1cab762161ccfbf2a18b7800e6efe58cf897d4adbfe4cb3bf14f4b59307fffc548179bda70c18bf000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb0000000000000000000000000000000001a28b7856a22db6e79ac4165e60addbb7dfe1f19d815032bc68fea905bd0d7709c2dafc65fe51493c964de678a30d32000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb8776600000000000000000000000000000000135b3db43511dbd8b3bd5a91880d6da1a2bd1383000e0d6f0a521bf88a5836a3b5f7cb9c0c02aa861a1c2d339f3c11f20000000000000000000000000000000000e1337271bd3302a1cab762161ccfbf2a18b7800e6efe58cf897d4adbfe4cb3bf14f4b59307fffc548179bda70c18bf000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb877660000000000000000000000000000000006a5d436046e0ac1975e4d24bb3e3f35c1ba3801f37705505cdeb6a86c58bf8068b43462a55155799fe2d2cc60c398b900000000000000000000000000000000191fde77c7c2b397a950f0542d2edd183a5e9404e516146697a755561ab2a9705f970b491e4c0003657d864258f391ec",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_44",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e82000000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df70000000000000000000000000000000012c5b00376a1dd31378ec44f2dc8e321e17185d903cfc5c15345a01c33f2f151b21b938d31816550594a7a1e7216c5b00000000000000000000000000000000013d79f825c44775c68e90932d0496a5cae53f04a1edb19f8abeb5948a3dd325dfec4a8b6f58c7fbca9cf3c09b909d8b2000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e270000000000000000000000000000000007c17aaf82c2aa6bf01695157bcd0c2b34734dfbd572b0abe79c8dd3eef7ce6eb9c5e7de55b36ddf87f05e55ba9ac28b00000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df70000000000000000000000000000000012c5b00376a1dd31378ec44f2dc8e321e17185d903cfc5c15345a01c33f2f151b21b938d31816550594a7a1e7216c5b00000000000000000000000000000000013d79f825c44775c68e90932d0496a5cae53f04a1edb19f8abeb5948a3dd325dfec4a8b6f58c7fbca9cf3c09b909d8b2000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e82000000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df700000000000000000000000000000000073b61e6c2de0969138ce3671582c9b58305c5abefb54cfe13eb3284c2be04d26c906c717fd29aaf60b485e18de8e4fb0000000000000000000000000000000006297267dd3b6f3de2329e837302427ab6235b3ad4a9f8c6bb45795852d3c3c61fe75747bbc78043102fc3f646f5d1f9",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_45",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b811580000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c743900000000000000000000000000000000101e143b838c8a3f5f80fb1412081091b875230f1e2f9cf374d4bcd595392f6daa9552dbb6d5834e27b1b3dafe061ed300000000000000000000000000000000072463400b3e875395a1cdd31d73d51396e34347cd86d9f6f43f42253b3cdb24b89ed7434b1522af95ba1ee2d29ed1bb000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000017147eda83f35d0b6c8894317da5b2e991818479674d7dd1aef6bfaebacbb61ad4b2a17ce7e799939f8c2004af4799530000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c743900000000000000000000000000000000101e143b838c8a3f5f80fb1412081091b875230f1e2f9cf374d4bcd595392f6daa9552dbb6d5834e27b1b3dafe061ed300000000000000000000000000000000072463400b3e875395a1cdd31d73d51396e34347cd86d9f6f43f42253b3cdb24b89ed7434b1522af95ba1ee2d29ed1bb000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b811580000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c74390000000000000000000000000000000009e2fdaeb5f35c5aeb9aaca231439c45ac022875d55575cbf25c15cb6177c6b67416ad22fa7e7cb1924d4c2501f98bd80000000000000000000000000000000012dcaeaa2e415f46b579d9e325d7d7c3cd94083d25fe38c872f1907bbb741aff660d28bb663edd502444e11d2d60d8f0",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_46",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000eb731bc99cdadf7f2280385c7e17d72d34bcbdbdc725d5bc94e841036115e8cb95df08084221696f9be479821fbdd7400000000000000000000000000000000143ba7d3f66445249d9a81a6949f24ff40e7c4d270fa044a8b80200a4369b07806c5497a0ef9e9dbb87b9e63694623ee0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f10000000000000000000000000000000016c1c9ca735535f801c58a9e35a80ce122d20abb327b44db4dea31b899982c4e136a2430c51cf3a31adc5611621f9dde000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000eb731bc99cdadf7f2280385c7e17d72d34bcbdbdc725d5bc94e841036115e8cb95df08084221696f9be479821fbdd7400000000000000000000000000000000143ba7d3f66445249d9a81a6949f24ff40e7c4d270fa044a8b80200a4369b07806c5497a0ef9e9dbb87b9e63694623ee0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000b49e02d9fb238a258f3a4307b6a2f64912b7fa91712b5639de24e90c09f9797654e0f7e2d31e968c040b867de03cd370000000000000000000000000000000005c56a16431ba175ad81260faeac87d8238f86b2828b0e74dbb0b296b34745ac17e6b684a25a16240183619c96b986bd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_47",
+ "Gas": 184000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe90000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000068edef3169c58920509ed4e7069229bd8038a45d2ce5773451cc18b396d2838c9539ecb52298a27eebd714afacb907c0000000000000000000000000000000004c5346765a62f2d2e700aadccf747acb3322c250435ce2cf358c08f1e286427cabace052327c4b30135c8482c5c0eb90000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be100000000000000000000000000000000084486ebc81878331aab7d6f53ca3c773fda7b181b56a93e5ee0bfa189afbb7fd7a05c5bea35ec1054c0e1ddc2e2dac20000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000068edef3169c58920509ed4e7069229bd8038a45d2ce5773451cc18b396d2838c9539ecb52298a27eebd714afacb907c0000000000000000000000000000000004c5346765a62f2d2e700aadccf747acb3322c250435ce2cf358c08f1e286427cabace052327c4b30135c8482c5c0eb90000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe90000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000137232f722e38e084611ba67d2e28a3b8c73c13f20b6bb4c22141115bd43cdeb555861335f2a75d7cb418eb505341a2f00000000000000000000000000000000153bdd82d3d9b76d1cab9d087654652ab1451f5fef4f449273d81211d88891fc53f131f98e2c3b4cb8c937b7d3a39bf20000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be100000000000000000000000000000000084486ebc81878331aab7d6f53ca3c773fda7b181b56a93e5ee0bfa189afbb7fd7a05c5bea35ec1054c0e1ddc2e2dac20000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000137232f722e38e084611ba67d2e28a3b8c73c13f20b6bb4c22141115bd43cdeb555861335f2a75d7cb418eb505341a2f00000000000000000000000000000000153bdd82d3d9b76d1cab9d087654652ab1451f5fef4f449273d81211d88891fc53f131f98e2c3b4cb8c937b7d3a39bf2",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_48",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193a000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000f6fdc4e5dceb555c9eb4c912fedbfb3cb1b842345f73ded02cfaf8d397c4378809721094aa4a4113a368e0787effeb500000000000000000000000000000000143ac06258c579c11c05569669a2a10babc63ecc86f85c91791d8ea48af700a2067c5f13d2700b8d5cf59bcca8fbf7c600000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000a5b95d6031e92578f6b5de5b8873e87486fd818214be93814753dcf6665229758248a6529892265fcc2b2ba45f89171000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000f6fdc4e5dceb555c9eb4c912fedbfb3cb1b842345f73ded02cfaf8d397c4378809721094aa4a4113a368e0787effeb500000000000000000000000000000000143ac06258c579c11c05569669a2a10babc63ecc86f85c91791d8ea48af700a2067c5f13d2700b8d5cf59bcca8fbf7c600000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193a000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000a91359bdbb1314481305b25135ded23995bc761ad8dd4d264612313bd34b2ab9e14def566af5bee7fc871f8780fabf60000000000000000000000000000000005c65187e0ba6cd92f16511fd9a90bcbb8b10cb86c8cb62dee1343fc6bb9f582182fa0eadee3f4725d0964335703b2e500000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000a5b95d6031e92578f6b5de5b8873e87486fd818214be93814753dcf6665229758248a6529892265fcc2b2ba45f89171000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000a91359bdbb1314481305b25135ded23995bc761ad8dd4d264612313bd34b2ab9e14def566af5bee7fc871f8780fabf60000000000000000000000000000000005c65187e0ba6cd92f16511fd9a90bcbb8b10cb86c8cb62dee1343fc6bb9f582182fa0eadee3f4725d0964335703b2e5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_49",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc500000000000000000000000000000000192f3e8ae2588f9223de77f5e872115f1edec96d6a0f403a47879410c2562e79853c9a706e423b83fbf3154234edb6f80000000000000000000000000000000015084258d58fd1a07bbdb2e90df5a56ae15a787037eff4fe55f660e45f04820c6fc8982303b5e82074cf0cdcbde61307000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b60000000000000000000000000000000002a534a7e1432aa317f782a581f974d23ec75420611165d0486ecd377660fa7c2e8235f829c64501d1b9bf3131e87289000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc500000000000000000000000000000000192f3e8ae2588f9223de77f5e872115f1edec96d6a0f403a47879410c2562e79853c9a706e423b83fbf3154234edb6f80000000000000000000000000000000015084258d58fd1a07bbdb2e90df5a56ae15a787037eff4fe55f660e45f04820c6fc8982303b5e82074cf0cdcbde61307000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc50000000000000000000000000000000000d1d35f57275708273d2fc05ad99b78459882178975d2851fa93e90345ac7aa996f658e4311c47bbe0beabdcb11f3b30000000000000000000000000000000004f8cf9163f014f9cf5df4cd3556076c831cd314bb951dc1113a71bc97ac7417aee367dbad9e17df452ff323421997a4000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b60000000000000000000000000000000002a534a7e1432aa317f782a581f974d23ec75420611165d0486ecd377660fa7c2e8235f829c64501d1b9bf3131e87289000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc50000000000000000000000000000000000d1d35f57275708273d2fc05ad99b78459882178975d2851fa93e90345ac7aa996f658e4311c47bbe0beabdcb11f3b30000000000000000000000000000000004f8cf9163f014f9cf5df4cd3556076c831cd314bb951dc1113a71bc97ac7417aee367dbad9e17df452ff323421997a4",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_50",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10c000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f000000000000000000000000000000000477b55bd7fff14e0d1807bfc21edb9481be01c12abb1460d78b1aafe42953730167e32e694c2ddfb0d442e8cea57d460000000000000000000000000000000004b884c6ea36f189dbc3c0e9cf88f08baf5d868579998f63b752e61fcce3cf2c901bb9b51959d3597c4ef53cff41fc260000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000d4197b85280f1a5e4cfdd6a7acce516b34a5e12cf55081a858a2ad517d12733aa294a2ca1adf81bc9bf22922fbfd99f000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f000000000000000000000000000000000477b55bd7fff14e0d1807bfc21edb9481be01c12abb1460d78b1aafe42953730167e32e694c2ddfb0d442e8cea57d460000000000000000000000000000000004b884c6ea36f189dbc3c0e9cf88f08baf5d868579998f63b752e61fcce3cf2c901bb9b51959d3597c4ef53cff41fc260000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10c000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f0000000000000000000000000000000015895c8e617ff54c3e039ff6812cd142e2b949c3c8c9fe5e8fa5b7f11287a2b11d441cd04807d220092abd17315a2d650000000000000000000000000000000015488d234f48f5106f57e6cc73c2bc4bb519c4ff79eb835bafddec8129cd26f78e90464997fa2ca63db00ac300bdae850000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000d4197b85280f1a5e4cfdd6a7acce516b34a5e12cf55081a858a2ad517d12733aa294a2ca1adf81bc9bf22922fbfd99f000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f0000000000000000000000000000000015895c8e617ff54c3e039ff6812cd142e2b949c3c8c9fe5e8fa5b7f11287a2b11d441cd04807d220092abd17315a2d650000000000000000000000000000000015488d234f48f5106f57e6cc73c2bc4bb519c4ff79eb835bafddec8129cd26f78e90464997fa2ca63db00ac300bdae85",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_51",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bf00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac800000000000000000000000000000000183b7b917aaaa94f0ea9959273ed4701102346be2a9d72531bd18fef908ecb0579a6ac10ed42a91f1147fc3a05b2e81900000000000000000000000000000000070983b1582a97d9797782e4f960a298aaa8ec509720495acdbf176d8ecb9ec9e041c2b5ed6b7dfb46fdeaae3fb341500000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa00000000000000000000000000000000145688bf2f7a76a4341564a725a16dd5009b4a5174d766e6bf337a8bcbb11c797b82173d92aa796da6b168e734be90ec00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac800000000000000000000000000000000183b7b917aaaa94f0ea9959273ed4701102346be2a9d72531bd18fef908ecb0579a6ac10ed42a91f1147fc3a05b2e81900000000000000000000000000000000070983b1582a97d9797782e4f960a298aaa8ec509720495acdbf176d8ecb9ec9e041c2b5ed6b7dfb46fdeaae3fb341500000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bf00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac80000000000000000000000000000000001c59658bed53d4b3c721223cf5e65d6545404c6c8e7a06c4b5f42b166222b1ea50553edc41156e0a8b703c5fa4cc2920000000000000000000000000000000012f78e38e1554ec0d1a424d149eb0a3eb9ce5f345c64c9649971bb3367e5575a3e6a3d48c3e8820473011551c04c695b0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa00000000000000000000000000000000145688bf2f7a76a4341564a725a16dd5009b4a5174d766e6bf337a8bcbb11c797b82173d92aa796da6b168e734be90ec00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac80000000000000000000000000000000001c59658bed53d4b3c721223cf5e65d6545404c6c8e7a06c4b5f42b166222b1ea50553edc41156e0a8b703c5fa4cc2920000000000000000000000000000000012f78e38e1554ec0d1a424d149eb0a3eb9ce5f345c64c9649971bb3367e5575a3e6a3d48c3e8820473011551c04c695b",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_52",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b2000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b0000000000000000000000000000000010f7bf9f6711ba723bb71a004a90109ee22be6643d56d410da18103ef44a1b3d50f10c4b94222c7f05fd3c28acbdc8ee00000000000000000000000000000000007af41f09e6d0adcb1935d6a93ea1f6156fa0157a63f265a3a7ceffe82f6635b8511e7e8f21e8f3be7a73513ff597b10000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a030000000000000000000000000000000003942eae34fd3104cead334a2cbb2131eaa10b59d07949479331a8f4cc66761cd5d23eb8a861ae618f3a2e01b25080f9000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b0000000000000000000000000000000010f7bf9f6711ba723bb71a004a90109ee22be6643d56d410da18103ef44a1b3d50f10c4b94222c7f05fd3c28acbdc8ee00000000000000000000000000000000007af41f09e6d0adcb1935d6a93ea1f6156fa0157a63f265a3a7ceffe82f6635b8511e7e8f21e8f3be7a73513ff597b10000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b2000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b000000000000000000000000000000000909524ad26e2c280f648db5f8bb9c38824b6520b62e3eae8d18c2620266dae6cdbaf3b31d31d380b401c3d75341e1bd0000000000000000000000000000000019861dcb2f9915ec800271df9a0d0ae14f07ab6f79212059c38903a10e818fee665ae1802232170bfb848caec00a12fa0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a030000000000000000000000000000000003942eae34fd3104cead334a2cbb2131eaa10b59d07949479331a8f4cc66761cd5d23eb8a861ae618f3a2e01b25080f9000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b000000000000000000000000000000000909524ad26e2c280f648db5f8bb9c38824b6520b62e3eae8d18c2620266dae6cdbaf3b31d31d380b401c3d75341e1bd0000000000000000000000000000000019861dcb2f9915ec800271df9a0d0ae14f07ab6f79212059c38903a10e818fee665ae1802232170bfb848caec00a12fa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_53",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b0000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a0000000000000000000000000000000003a6cc74cc398f38d535b4341faa37c968daf2009c3f05ace1f938b33bbe4002d81d18d30c2c856b21afe7a22b83c37a000000000000000000000000000000000452d1b2da6392f9df1bfd35e4575c565333703b2f83f56e0a88a0c8195968c5321296b07f6750584e23597304a5472e00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f60463000000000000000000000000000000000575bd953fc6600f5b48faea1032cf2b6615bf34cc9c526fdcc5042a292812d35fef2884bf51e017eb24c174b2bc20a00000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a0000000000000000000000000000000003a6cc74cc398f38d535b4341faa37c968daf2009c3f05ace1f938b33bbe4002d81d18d30c2c856b21afe7a22b83c37a000000000000000000000000000000000452d1b2da6392f9df1bfd35e4575c565333703b2f83f56e0a88a0c8195968c5321296b07f6750584e23597304a5472e00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b0000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a00000000000000000000000000000000165a45756d46576175e5f38223a1750dfb9c598457460d12853799edbaf2b621468ee72ba5277a94984f185dd47be7310000000000000000000000000000000015ae40375f1c53a06bffaa805ef450811143db49c4011d515ca831d8dd578d5eec99694e31ecafa76bdba68cfb5a637d00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f60463000000000000000000000000000000000575bd953fc6600f5b48faea1032cf2b6615bf34cc9c526fdcc5042a292812d35fef2884bf51e017eb24c174b2bc20a00000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a00000000000000000000000000000000165a45756d46576175e5f38223a1750dfb9c598457460d12853799edbaf2b621468ee72ba5277a94984f185dd47be7310000000000000000000000000000000015ae40375f1c53a06bffaa805ef450811143db49c4011d515ca831d8dd578d5eec99694e31ecafa76bdba68cfb5a637d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_54",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751a0000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf780000000000000000000000000000000007a9cf48dbe005c5c59b2c731cf4117e5fadc9cb2cd8f486f1ed58b2909092ee8f36d88b8f719db94715641b418ab4240000000000000000000000000000000004ba40d4766b91bf8da1cc2526f62791a1b5f6fc24ffc54b522dd30cde2d29a6a6f81e8429d518710843d43705f3b4e60000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a000000000000000000000000000000000032e4fbb8dab462ff0352c2d3925b0e97ca662189129928ccc1714364e4f01d8b026887d808342091ad442b6e11635910000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf780000000000000000000000000000000007a9cf48dbe005c5c59b2c731cf4117e5fadc9cb2cd8f486f1ed58b2909092ee8f36d88b8f719db94715641b418ab4240000000000000000000000000000000004ba40d4766b91bf8da1cc2526f62791a1b5f6fc24ffc54b522dd30cde2d29a6a6f81e8429d518710843d43705f3b4e60000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751a0000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf7800000000000000000000000000000000125742a15d9fe0d485807b4326579b5904c981b9c6ac1e38754379ee662063358f75277321e2624672e99be4be74f687000000000000000000000000000000001546d115c31454dabd79db911c558545c2c15488ce854d741502ff941883cc7d77b3e17a877ee78eb1bb2bc8fa0bf5c50000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a000000000000000000000000000000000032e4fbb8dab462ff0352c2d3925b0e97ca662189129928ccc1714364e4f01d8b026887d808342091ad442b6e11635910000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf7800000000000000000000000000000000125742a15d9fe0d485807b4326579b5904c981b9c6ac1e38754379ee662063358f75277321e2624672e99be4be74f687000000000000000000000000000000001546d115c31454dabd79db911c558545c2c15488ce854d741502ff941883cc7d77b3e17a877ee78eb1bb2bc8fa0bf5c5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_55",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df910000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c7952820000000000000000000000000000000008ceb842a17953578013ceee519a28ef1b37f73e13564def5ffe08a64dc53aa680784e26138176c89269477ee003d16700000000000000000000000000000000159791b6f2c26ed611ca40bfbd2059c15cfec9d073a84254ad9b509ef786d62d17fdc67ab13092cf0b7b3482866f4c320000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000ae6134f1fec83a52e5358db260eb9dc6b918f7a803aae5715854ebee2b9bbecea9ab0d955f2e13e2c47a96b234ecb1a0000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c7952820000000000000000000000000000000008ceb842a17953578013ceee519a28ef1b37f73e13564def5ffe08a64dc53aa680784e26138176c89269477ee003d16700000000000000000000000000000000159791b6f2c26ed611ca40bfbd2059c15cfec9d073a84254ad9b509ef786d62d17fdc67ab13092cf0b7b3482866f4c320000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df910000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c79528200000000000000000000000000000000113259a798069342cb07d8c7f1b183e8493f5446e02ec4d00732c9faa8ebbb7d9e33b1d89dd289372795b8811ffbd944000000000000000000000000000000000469803346bd77c4395166f6862b5316077881b47fdcd06ab9958201ff2a1ff706ae398400236d30ae83cb7d79905e790000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000ae6134f1fec83a52e5358db260eb9dc6b918f7a803aae5715854ebee2b9bbecea9ab0d955f2e13e2c47a96b234ecb1a0000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c79528200000000000000000000000000000000113259a798069342cb07d8c7f1b183e8493f5446e02ec4d00732c9faa8ebbb7d9e33b1d89dd289372795b8811ffbd944000000000000000000000000000000000469803346bd77c4395166f6862b5316077881b47fdcd06ab9958201ff2a1ff706ae398400236d30ae83cb7d79905e79",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_56",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c04000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf000000000000000000000000000000001272c63693873e1dabe2c2739310f627d3d9b5bcaa615402c3849ffd8dfe72b40fea4a068064655f2c8f46f074e6518d0000000000000000000000000000000000161a8e5e1de10938e5bce241ae73d76173022127822d744b23e656095c28f2f8d142ceb48b72a1dbc36b6143f8af95000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000000d9bd58946a4d26e3f97e5fe96e574d6f93562c0fb0c187c0c586208fe9a4d9383d3ca22b272ff3eb7e624ad7fb9ea7000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf000000000000000000000000000000001272c63693873e1dabe2c2739310f627d3d9b5bcaa615402c3849ffd8dfe72b40fea4a068064655f2c8f46f074e6518d0000000000000000000000000000000000161a8e5e1de10938e5bce241ae73d76173022127822d744b23e656095c28f2f8d142ceb48b72a1dbc36b6143f8af95000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c04000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf00000000000000000000000000000000078e4bb3a5f8a87c9f38e542b03ab6af909d95c84923bebca3ac32a368b283700ec1b5f830ef9aa08d6fb90f8b19591e0000000000000000000000000000000019eaf75bdb6205911235ead4019d390003044963cc02e54b1c0cec4aed54cd3125dabd2ffcc88d5dde3b949ebc06fb16000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000000d9bd58946a4d26e3f97e5fe96e574d6f93562c0fb0c187c0c586208fe9a4d9383d3ca22b272ff3eb7e624ad7fb9ea7000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf00000000000000000000000000000000078e4bb3a5f8a87c9f38e542b03ab6af909d95c84923bebca3ac32a368b283700ec1b5f830ef9aa08d6fb90f8b19591e0000000000000000000000000000000019eaf75bdb6205911235ead4019d390003044963cc02e54b1c0cec4aed54cd3125dabd2ffcc88d5dde3b949ebc06fb16",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_57",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e2946000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a220000000000000000000000000000000018a236ea02b1971d6e193a6eb92e1298956679d86864042fb6a0c36dd91c0e385944d779dedd0149fa8a1b3d6a07949d00000000000000000000000000000000048eac7d116b5a7906bce070e2b51ee7c4c493f1415abdb6fd2d35676036d3b741d14b7135419645a6906018e9d3f150000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000f77a58fb4b4165bf86d30b6349b84780d72b24e8eddce16c73a1f5a06de0638045a64978eb9c477d806f1955e818165000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a220000000000000000000000000000000018a236ea02b1971d6e193a6eb92e1298956679d86864042fb6a0c36dd91c0e385944d779dedd0149fa8a1b3d6a07949d00000000000000000000000000000000048eac7d116b5a7906bce070e2b51ee7c4c493f1415abdb6fd2d35676036d3b741d14b7135419645a6906018e9d3f150000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e2946000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a2200000000000000000000000000000000015edb0036ce4f7cdd026d478a1d9a3ecf10d1ac8b210e8fb0900f331d94e7ebc5672884d276feb5bf74e4c295f8160e000000000000000000000000000000001572656d28148c21445ec74560968def9fb2b793b22a55086a039d39967a226cdcdab48d7c1269ba136e9fe7162bb95b000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000f77a58fb4b4165bf86d30b6349b84780d72b24e8eddce16c73a1f5a06de0638045a64978eb9c477d806f1955e818165000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a2200000000000000000000000000000000015edb0036ce4f7cdd026d478a1d9a3ecf10d1ac8b210e8fb0900f331d94e7ebc5672884d276feb5bf74e4c295f8160e000000000000000000000000000000001572656d28148c21445ec74560968def9fb2b793b22a55086a039d39967a226cdcdab48d7c1269ba136e9fe7162bb95b",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_58",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d318400000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c95384000000000000000000000000000000000003c96c6f20d7ac31ee7ca77d11e8d25ea78cdf13e5f4d317752320e059e19196f14c15b5a18ca712f3a7cc6f09be6d4000000000000000000000000000000000ebd71f61fcddf1652675f577bbaeec26b892dd954965b057ffb431d6e37cc5425a2a42a0059482c2bd75adb2a120b0b000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000018bc060c3f6be35b724dee72bcda5cc376dc1f35561f7e70c9fe11eda256edd30aca8c19018433483186beb5b9b2792700000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c95384000000000000000000000000000000000003c96c6f20d7ac31ee7ca77d11e8d25ea78cdf13e5f4d317752320e059e19196f14c15b5a18ca712f3a7cc6f09be6d4000000000000000000000000000000000ebd71f61fcddf1652675f577bbaeec26b892dd954965b057ffb431d6e37cc5425a2a42a0059482c2bd75adb2a120b0b000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d318400000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c9538400000000000000000000000000000000019c47b2347726bd72c33dd3e722d1fb179fe7d93b525c58defdea092f112dd0aaf973ea3573b358e8ac483390f63c3d7000000000000000000000000000000000b439ff419b20783f8b4485ec790be14f8ee1dab9eeeb7b9e7358f83887929cff9095bd4b0fab7d38e27a524d5ed9fa0000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000018bc060c3f6be35b724dee72bcda5cc376dc1f35561f7e70c9fe11eda256edd30aca8c19018433483186beb5b9b2792700000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c9538400000000000000000000000000000000019c47b2347726bd72c33dd3e722d1fb179fe7d93b525c58defdea092f112dd0aaf973ea3573b358e8ac483390f63c3d7000000000000000000000000000000000b439ff419b20783f8b4485ec790be14f8ee1dab9eeeb7b9e7358f83887929cff9095bd4b0fab7d38e27a524d5ed9fa0",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_59",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae920000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e4000000000000000000000000000000000174ffb89d7715866562d9882acb81ce40758644ca3e0decd546c8f5c349b24fce88214956e7540fac36bcfc105cf34a0000000000000000000000000000000003e06c5f607ccf1e2991828034fcdf91106295e7174b4dca21926169451ee58e737d535af45073e2378206e03c81c421000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f3555650000000000000000000000000000000007f7dc55c90fa181c55c9b83b7736ee84b3f19d960318e75661dd22c0546d62f4c9e07b915f9295a3c9fe6a62c84fc190000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e4000000000000000000000000000000000174ffb89d7715866562d9882acb81ce40758644ca3e0decd546c8f5c349b24fce88214956e7540fac36bcfc105cf34a0000000000000000000000000000000003e06c5f607ccf1e2991828034fcdf91106295e7174b4dca21926169451ee58e737d535af45073e2378206e03c81c421000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae920000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e400000000000000000000000000000000188c12319c08d113e5b8ce2e18802b092401c540294704d291ea09ab336743d45023deb55a6cabf00dc84303efa2b761000000000000000000000000000000001620a58ad903177c218a25360e4ecd465414b59ddc39c4f5459e7137b1921095ab2eaca3bd038c1d827cf91fc37de68a000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f3555650000000000000000000000000000000007f7dc55c90fa181c55c9b83b7736ee84b3f19d960318e75661dd22c0546d62f4c9e07b915f9295a3c9fe6a62c84fc190000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e400000000000000000000000000000000188c12319c08d113e5b8ce2e18802b092401c540294704d291ea09ab336743d45023deb55a6cabf00dc84303efa2b761000000000000000000000000000000001620a58ad903177c218a25360e4ecd465414b59ddc39c4f5459e7137b1921095ab2eaca3bd038c1d827cf91fc37de68a",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_60",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b1700000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000b15d92f2301075ab0e3215aa72cf9b130bc8e1bcd9fa36375c4b9d7da430ae3e2b24f417336d8729f44542ee7f561d300000000000000000000000000000000197d90090501e8cdea28eb7963231f1a7b5f716cc3a086acb6e7626600d6544132cac943e8d5cefb5daf0a2f8d4006290000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce0000000000000000000000000000000005b1ce5cb2ae0e9175f2bd557d7869233d65008e0f47c52914fa44c4a6234b70eed236bc5499bb0412d0cbb61c98f93b0000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000b15d92f2301075ab0e3215aa72cf9b130bc8e1bcd9fa36375c4b9d7da430ae3e2b24f417336d8729f44542ee7f561d300000000000000000000000000000000197d90090501e8cdea28eb7963231f1a7b5f716cc3a086acb6e7626600d6544132cac943e8d5cefb5daf0a2f8d4006290000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b1700000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000eeb38bb167edf3f9a38865b9c1eb32633babd6925e56f5bf16c18c91c6deb403bf9b0bd3e1d278d1abaabd1180a48d800000000000000000000000000000000008381e1347dfdcc60f2bc3ce0288dbce917da182fe48c12b049703af5daa1e2ebe136bac87e31045c4ff5d072bfa4820000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce0000000000000000000000000000000005b1ce5cb2ae0e9175f2bd557d7869233d65008e0f47c52914fa44c4a6234b70eed236bc5499bb0412d0cbb61c98f93b0000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000eeb38bb167edf3f9a38865b9c1eb32633babd6925e56f5bf16c18c91c6deb403bf9b0bd3e1d278d1abaabd1180a48d800000000000000000000000000000000008381e1347dfdcc60f2bc3ce0288dbce917da182fe48c12b049703af5daa1e2ebe136bac87e31045c4ff5d072bfa482",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_61",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ec0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf2300000000000000000000000000000000005c35f3372f1ec9845bd04ea722fbed2be1388abf59e622dd3dafb4b3af49bc5fba9e20235e7e58973fedf4b8b720691000000000000000000000000000000001111d18d621070509805d306a31c109701288fd55d4c0644349deb080c6591b6e852b4f7e009b80019513de7f2fce17d00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d0000000000000000000000000000000007efcb9da7b7ff0f4a1d92489ad76c59158bcc42c5c7a93067772a6d9ef1d3b6df9360d0fc1214e7dec02aaaf7b118bf0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf2300000000000000000000000000000000005c35f3372f1ec9845bd04ea722fbed2be1388abf59e622dd3dafb4b3af49bc5fba9e20235e7e58973fedf4b8b720691000000000000000000000000000000001111d18d621070509805d306a31c109701288fd55d4c0644349deb080c6591b6e852b4f7e009b80019513de7f2fce17d00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ec0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf23000000000000000000000000000000000143db2b6c68dfa02055ea2cbd11bee04a663c2d8fde6b0919355d755bbbc5a5e23021dfc7b6c1a76460020b4748da41a0000000000000000000000000000000008ef405cd76f7649b315d4afa02f9c40634ebbaf96390c7b3292e798ea4b646d36594b06d14a47ffa0adc2180d02c92e00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d0000000000000000000000000000000007efcb9da7b7ff0f4a1d92489ad76c59158bcc42c5c7a93067772a6d9ef1d3b6df9360d0fc1214e7dec02aaaf7b118bf0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf23000000000000000000000000000000000143db2b6c68dfa02055ea2cbd11bee04a663c2d8fde6b0919355d755bbbc5a5e23021dfc7b6c1a76460020b4748da41a0000000000000000000000000000000008ef405cd76f7649b315d4afa02f9c40634ebbaf96390c7b3292e798ea4b646d36594b06d14a47ffa0adc2180d02c92e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_62",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000000e7e532ee4b892af39f8a3db7a05cc77a6eb0b3d977c17076bac4a52d5ba003a0ac1f902a4257791a45370eb88426a70000000000000000000000000000000016a556050e4905fa74b5061e3874f05cc7a6c5b049bd3bb7c34adef5a77c393239a600542a4401c3e61978ee6515a30e0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000eb29e948adc9e1816c67a7865517fbc91610b2eb30da1d8a1e15c5f62e71a1fd1f40d4d59b23bea7edeba79829010e6000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000000e7e532ee4b892af39f8a3db7a05cc77a6eb0b3d977c17076bac4a52d5ba003a0ac1f902a4257791a45370eb88426a70000000000000000000000000000000016a556050e4905fa74b5061e3874f05cc7a6c5b049bd3bb7c34adef5a77c393239a600542a4401c3e61978ee6515a30e0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000019192cb74b345d6f577c1d788bab500fea089ad11a0d514ef0760dfbc95556207dffe06e8711a8869fb9c8f1477b840400000000000000000000000000000000035bbbe52b36e09fd666a1980ad6bc7a9cd085d4a9c7d707a3e5f3ab4f34bcf1e505ffaa870ffe3bd3e587119aea079d0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000eb29e948adc9e1816c67a7865517fbc91610b2eb30da1d8a1e15c5f62e71a1fd1f40d4d59b23bea7edeba79829010e6000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000019192cb74b345d6f577c1d788bab500fea089ad11a0d514ef0760dfbc95556207dffe06e8711a8869fb9c8f1477b840400000000000000000000000000000000035bbbe52b36e09fd666a1980ad6bc7a9cd085d4a9c7d707a3e5f3ab4f34bcf1e505ffaa870ffe3bd3e587119aea079d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_63",
+ "Gas": 207000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d0000000000000000000000000000000002f2e4467cdc15f1e57d75d6f5c172637df589590863bb437cc5166314e6362b7cd0d7499176b94529979849624cb432000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d29000000000000000000000000000000000264dd2fa407109abaf47d89c3d64542fd6d470579dfe0a98cc73f2fa3f6252bb9356ba39f3c92c1a6343c72d9cc4e5a000000000000000000000000000000000c34a091319b052226395b96f20fa37deb11b766b4b46811fa24799e5b5bfb20813a956524b7be7ea941b63a1c9a5a2c000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d0000000000000000000000000000000002f2e4467cdc15f1e57d75d6f5c172637df589590863bb437cc5166314e6362b7cd0d7499176b94529979849624cb432000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d29000000000000000000000000000000000264dd2fa407109abaf47d89c3d64542fd6d470579dfe0a98cc73f2fa3f6252bb9356ba39f3c92c1a6343c72d9cc4e5a000000000000000000000000000000000c34a091319b052226395b96f20fa37deb11b766b4b46811fa24799e5b5bfb20813a956524b7be7ea941b63a1c9a5a2c000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_64",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000cab5ed8dc53e9c891df449bd199776adbfc193fc8d6bebf9716610fd4db6def608df059bf29fe43dbf1bf0aa52c1b7f0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c8530000000000000000000000000000000003bdbb702a5d2d8a5b2d10ed605627c1413eff588ac82966ca516dd7c2dc617b46a612308182759201efb7e6c6e1d8b2000000000000000000000000000000000bb2d13f201626fb4a2d6c1dfa03fe41a4fbb60b35d623d640cd430b8fb84afd3ff0b371714aaca303bcd4d3d548827e000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000cab5ed8dc53e9c891df449bd199776adbfc193fc8d6bebf9716610fd4db6def608df059bf29fe43dbf1bf0aa52c1b7f0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c8530000000000000000000000000000000003bdbb702a5d2d8a5b2d10ed605627c1413eff588ac82966ca516dd7c2dc617b46a612308182759201efb7e6c6e1d8b2000000000000000000000000000000000bb2d13f201626fb4a2d6c1dfa03fe41a4fbb60b35d623d640cd430b8fb84afd3ff0b371714aaca303bcd4d3d548827e000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_65",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f700000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf1000000000000000000000000000000001528dcaae381eb764333992e28ed557034ba5413c5b64df40ef3150d2771e5d1cd8c211ca22075c7436e2582960ab3b400000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f700000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000fd913e00fb884cc217475cb69e1fafc298d5c38ee3bd5fbf68fa9c777b79f5ec111aff51fa0184023fec7c9cc881bf0000000000000000000000000000000000c45786b44e8dc531f1eb777adb0e146a963e46ab65d49a8ce9978607e5aa5c58b2880b8018a9ac97add3ca5c2e65beb000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf1000000000000000000000000000000001528dcaae381eb764333992e28ed557034ba5413c5b64df40ef3150d2771e5d1cd8c211ca22075c7436e2582960ab3b400000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000fd913e00fb884cc217475cb69e1fafc298d5c38ee3bd5fbf68fa9c777b79f5ec111aff51fa0184023fec7c9cc881bf0000000000000000000000000000000000c45786b44e8dc531f1eb777adb0e146a963e46ab65d49a8ce9978607e5aa5c58b2880b8018a9ac97add3ca5c2e65beb000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f700000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_66",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d200000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec275080000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c5100000000000000000000000000000000010ee94e9470765ac32b5648f1cd7d745a793dbd46dc95fa32db86929eec385e50cb35755120480be0956a2a342a46d900000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec275080000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d200000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000b4d1c17ec6597484ae95466d3ca0656f8226c5127b4068f46fcaef6a77d9418d75f25cc92c1b7fd03c825514cbbaa640000000000000000000000000000000003110cf859c0d28c6ad8c2c0d0481a4d0d09bb2000aab784939e9f819a6dc3a7a18190293cfd2a106149b5c1a13d35a30000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c5100000000000000000000000000000000010ee94e9470765ac32b5648f1cd7d745a793dbd46dc95fa32db86929eec385e50cb35755120480be0956a2a342a46d900000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000b4d1c17ec6597484ae95466d3ca0656f8226c5127b4068f46fcaef6a77d9418d75f25cc92c1b7fd03c825514cbbaa640000000000000000000000000000000003110cf859c0d28c6ad8c2c0d0481a4d0d09bb2000aab784939e9f819a6dc3a7a18190293cfd2a106149b5c1a13d35a30000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d200000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec27508",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_67",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab0000000000000000000000000000000004acd0ba7577ffe37bdeeaf5810b5a8a4a6b51c3c02bec4e0c6f0cfb4f12283120d283c12ecb7e4be7063fefb37a578c0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d00000000000000000000000000000000175da48b3c4c64d6eb26b45475ca7240a0923333b1bf7a6ef37c758ddceb0291da8085580f004814972d4afad7ececab000000000000000000000000000000000a8cb418c0192fdb509c33a79feb88c60226ee228a62a2c1be2b8c1ab9a0f711d11c15eae9f030491dcf70ed47e2678c0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab0000000000000000000000000000000004acd0ba7577ffe37bdeeaf5810b5a8a4a6b51c3c02bec4e0c6f0cfb4f12283120d283c12ecb7e4be7063fefb37a578c0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d00000000000000000000000000000000175da48b3c4c64d6eb26b45475ca7240a0923333b1bf7a6ef37c758ddceb0291da8085580f004814972d4afad7ececab000000000000000000000000000000000a8cb418c0192fdb509c33a79feb88c60226ee228a62a2c1be2b8c1ab9a0f711d11c15eae9f030491dcf70ed47e2678c0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_68",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e7879000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e20000000000000000000000000000000012ee6884c9d68bdabe8f4aa92aa613129993aad6a7aafffef1922c910cbd3f8b4ae8a810c59a0b9de0a79d4e5db13232000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e7879000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000001669360d7591ed2362569fc05c4912fcd7ffe60dd26f533087b3099eb6603336863793d2b976bbff0edf4765066dc66c0000000000000000000000000000000006653bf1218a486d94578b5d40ff9a09b4e22325ba3d5abcff3d64652440d68ed5f69e3a215003a1db10c01843704f5000000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e20000000000000000000000000000000012ee6884c9d68bdabe8f4aa92aa613129993aad6a7aafffef1922c910cbd3f8b4ae8a810c59a0b9de0a79d4e5db13232000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000001669360d7591ed2362569fc05c4912fcd7ffe60dd26f533087b3099eb6603336863793d2b976bbff0edf4765066dc66c0000000000000000000000000000000006653bf1218a486d94578b5d40ff9a09b4e22325ba3d5abcff3d64652440d68ed5f69e3a215003a1db10c01843704f5000000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e7879000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_69",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e5590000000000000000000000000000000006abf7ef1d5e3484992225b5a59791a68cc7e1e0f8aaf2415a9f759f2dff53f62aecf23e0443fdf37bb3775be9f5c981000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b000000000000000000000000000000000082385363502637bd8d030855032ee447fdfd7f0bc1eb14c5f00be2f5a7f30867483a066590a5fa22229e16c2dc00ec0000000000000000000000000000000009aa4ff672d1afdc24d89aa21616fbef5d0eef0b60307c7e193085e89db01dca0666b4201544d9aec8614ca14c22641e000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e5590000000000000000000000000000000006abf7ef1d5e3484992225b5a59791a68cc7e1e0f8aaf2415a9f759f2dff53f62aecf23e0443fdf37bb3775be9f5c981000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b000000000000000000000000000000000082385363502637bd8d030855032ee447fdfd7f0bc1eb14c5f00be2f5a7f30867483a066590a5fa22229e16c2dc00ec0000000000000000000000000000000009aa4ff672d1afdc24d89aa21616fbef5d0eef0b60307c7e193085e89db01dca0666b4201544d9aec8614ca14c22641e000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_70",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf9250000000000000000000000000000000001b7a86c4142843a854dd0937bdbfd833a34fb15303d753e3f41eaf19f4fd9a6af785804d5ae2c3b99044cc13e6ca4b60000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f00000000000000000000000000000000118871ec2ef96fd3a5b465133902c6f108eea08781ff754f1776dc029889a958b56943ad041d3a98a5f8fad5530e0cb2000000000000000000000000000000000d8b09f53d16443f4c1b0272d95999130c034720b02c3874a80a014f170c65c87538e22f0025d5c08da9e3532f0ac62c0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf9250000000000000000000000000000000001b7a86c4142843a854dd0937bdbfd833a34fb15303d753e3f41eaf19f4fd9a6af785804d5ae2c3b99044cc13e6ca4b60000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f00000000000000000000000000000000118871ec2ef96fd3a5b465133902c6f108eea08781ff754f1776dc029889a958b56943ad041d3a98a5f8fad5530e0cb2000000000000000000000000000000000d8b09f53d16443f4c1b0272d95999130c034720b02c3874a80a014f170c65c87538e22f0025d5c08da9e3532f0ac62c0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_71",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567300000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000008151a15a13daeee49a82737118d488005fa7ed1869bc458f8af88e7341e0a48b5d8f129f6eb071fb07c11887f4d543800000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567300000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000efb08850063e94f4ce935ef65928deaabafa580a1c0a8e92b7f59efc09adf240f5363caedf8a212170e8d39120cbf74000000000000000000000000000000000838486201e313e21e62bbde270d9804a45b41a70e1c072804f4ca2a2f5ba6d151f15cc19958f0f2c6cd337a8b6c69de000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000008151a15a13daeee49a82737118d488005fa7ed1869bc458f8af88e7341e0a48b5d8f129f6eb071fb07c11887f4d543800000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000efb08850063e94f4ce935ef65928deaabafa580a1c0a8e92b7f59efc09adf240f5363caedf8a212170e8d39120cbf74000000000000000000000000000000000838486201e313e21e62bbde270d9804a45b41a70e1c072804f4ca2a2f5ba6d151f15cc19958f0f2c6cd337a8b6c69de000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567300000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_72",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a07060000000000000000000000000000000000876cf6553b21053e0d7a4449cd137fd946f2de0f7032f535f54914a8ae7da5afbe765bdfa3a0cdea0a50e1ed43bce800000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000afb70d8856591b980a2e4144357f4cb75fb367f5319786fb7fa2b656f9ed8facbdfb0b26346349986342ed4f34fae4900000000000000000000000000000000012670f096c4b225332cc181df91d6317c27071668f04226f807b0e17506fed0001c11613598926e38fce506ba02c6c8000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a07060000000000000000000000000000000000876cf6553b21053e0d7a4449cd137fd946f2de0f7032f535f54914a8ae7da5afbe765bdfa3a0cdea0a50e1ed43bce800000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000afb70d8856591b980a2e4144357f4cb75fb367f5319786fb7fa2b656f9ed8facbdfb0b26346349986342ed4f34fae4900000000000000000000000000000000012670f096c4b225332cc181df91d6317c27071668f04226f807b0e17506fed0001c11613598926e38fce506ba02c6c8000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_73",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c2000000000000000000000000000000001093356407cff41779ce8f3d53dfe7a04edc8ce7192ddfeeb4329c38152cf1875d0df9ffeced95f1c7fae7d124649f21000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a903505000000000000000000000000000000000227280838fae5023ab2dcb23f6470b056dd6c87acf848e339d5164981a6abcbfb3c7084235f0749b2f5a4957f17cc62000000000000000000000000000000000b43329a7230c0dc0ee61c43a13e90ce24df40a52a415a2740cb3faa64cfe21058aaae5ea8f69364cd72d2cd6543fe9e00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c2000000000000000000000000000000001093356407cff41779ce8f3d53dfe7a04edc8ce7192ddfeeb4329c38152cf1875d0df9ffeced95f1c7fae7d124649f21000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a903505000000000000000000000000000000000227280838fae5023ab2dcb23f6470b056dd6c87acf848e339d5164981a6abcbfb3c7084235f0749b2f5a4957f17cc62000000000000000000000000000000000b43329a7230c0dc0ee61c43a13e90ce24df40a52a415a2740cb3faa64cfe21058aaae5ea8f69364cd72d2cd6543fe9e00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_74",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa300000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e0000000000000000000000000000000007007c89288b69f16870dc857a02cd071db8178e578fd2b78fcd5edb5050dcded107a1c1c0071d45e4c4af364bc9400800000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa300000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000018034dc4ccb64f0700b5e12b89d531cd9ccc7a399c1f36d08bbe277ccd8dd970eb00606d6e12bca68291897a817637d200000000000000000000000000000000069e1dd2b22d8ce5ce1e0969e35e07abcfd97f8f3b6d8fa724a0feb9ea78b603391caea3172f50aa222f5fc82bdb18e5000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e0000000000000000000000000000000007007c89288b69f16870dc857a02cd071db8178e578fd2b78fcd5edb5050dcded107a1c1c0071d45e4c4af364bc9400800000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000018034dc4ccb64f0700b5e12b89d531cd9ccc7a399c1f36d08bbe277ccd8dd970eb00606d6e12bca68291897a817637d200000000000000000000000000000000069e1dd2b22d8ce5ce1e0969e35e07abcfd97f8f3b6d8fa724a0feb9ea78b603391caea3172f50aa222f5fc82bdb18e5000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa300000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_75",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000a76ccda2ca736ce935b4b88e08bbf183f69e2b3f5a471662a5de571976e7d4264021db88b919c896bbbb8128732c3e3000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000009060f4c03cbefb8f46332a22d5a2be92b167e493cca773121c9bcb485ff3c100df3404737bb08bae60a9dacc4a5c83f00000000000000000000000000000000058eac9c9eddd5f62da6c450254602ebf94e246b3f1a6c5fd27a26cbe1f1f02da4d1176190537db9e264c7e4f28058ed0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000a76ccda2ca736ce935b4b88e08bbf183f69e2b3f5a471662a5de571976e7d4264021db88b919c896bbbb8128732c3e3000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000009060f4c03cbefb8f46332a22d5a2be92b167e493cca773121c9bcb485ff3c100df3404737bb08bae60a9dacc4a5c83f00000000000000000000000000000000058eac9c9eddd5f62da6c450254602ebf94e246b3f1a6c5fd27a26cbe1f1f02da4d1176190537db9e264c7e4f28058ed0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_76",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb21100000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c00000000000000000000000000000000124a601a06d5094945ec8528c5457ea3f8ca710137b6ad48ee7ad93db53c056059dbc8b02d9edf5e2786c575a0bff89a00000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb21100000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d70000000000000000000000000000000014e04221744944c56495e2cb7789acc9f3cb7456d78c44872d593343fcaa575103fc4ea96e61c4729f0887454fa57d6a000000000000000000000000000000000231121026adca019380e499e795165f297bce1b30c633afb6c00329e21b5872d5545b887bef49a43b2ceb284b72710f000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c00000000000000000000000000000000124a601a06d5094945ec8528c5457ea3f8ca710137b6ad48ee7ad93db53c056059dbc8b02d9edf5e2786c575a0bff89a00000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d70000000000000000000000000000000014e04221744944c56495e2cb7789acc9f3cb7456d78c44872d593343fcaa575103fc4ea96e61c4729f0887454fa57d6a000000000000000000000000000000000231121026adca019380e499e795165f297bce1b30c633afb6c00329e21b5872d5545b887bef49a43b2ceb284b72710f000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb21100000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_77",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a00000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c04200000000000000000000000000000000001b8c085fd1f34fb273da7d651602b326fef7c357c2fb7845f4c17ce95152042af9e51e7d7699b50f3605bacab563a100000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a00000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000012098b001cb819309d0b45df8a37854967f88cfa823a69f262fe9a40c564bad8e8a6be94d3f7939ed38305c6fd2d93b6000000000000000000000000000000000099b6e094a1b1eb0ead2e7117f3f9bbf72db98409ef1234c8b3b60fea1048f9e97e3c61fd568ccca1da89f6a484bbe8000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c04200000000000000000000000000000000001b8c085fd1f34fb273da7d651602b326fef7c357c2fb7845f4c17ce95152042af9e51e7d7699b50f3605bacab563a100000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000012098b001cb819309d0b45df8a37854967f88cfa823a69f262fe9a40c564bad8e8a6be94d3f7939ed38305c6fd2d93b6000000000000000000000000000000000099b6e094a1b1eb0ead2e7117f3f9bbf72db98409ef1234c8b3b60fea1048f9e97e3c61fd568ccca1da89f6a484bbe8000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a00000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_78",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a880000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000c8bd020743550a6d27f0052d0037547db204e3fd752abf6758d899a3793fd3cd50c3073df6258c20a2f8e4797cbab700000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a880000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000a42cfd1e09bd5fdf93d4ffec5a6b312a27dfb7b5e5238dc590158156b613c2d15de1e5a1a4ef2f6751e766874ea788d00000000000000000000000000000000000c87de488d68a3ef74410fe4c892cf62d25fb7d9ef6cbf3cb093184803e12066e86020225e3b9899decf8dbe6a20230000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000c8bd020743550a6d27f0052d0037547db204e3fd752abf6758d899a3793fd3cd50c3073df6258c20a2f8e4797cbab700000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000a42cfd1e09bd5fdf93d4ffec5a6b312a27dfb7b5e5238dc590158156b613c2d15de1e5a1a4ef2f6751e766874ea788d00000000000000000000000000000000000c87de488d68a3ef74410fe4c892cf62d25fb7d9ef6cbf3cb093184803e12066e86020225e3b9899decf8dbe6a20230000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a88",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "matter_pairing_79",
+ "Gas": 230000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb9630000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb9630000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb9630000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb963",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_80",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_81",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_82",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_83",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_84",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_85",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_86",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_87",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_88",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_89",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e60000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e60000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e60000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e6",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_90",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_91",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_92",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_93",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a70000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a70000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a70000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a7",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_94",
+ "Gas": 299000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "matter_pairing_95",
+ "Gas": 299000,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/bn256Add.json b/x/evm/core/vm/testdata/precompiles/bn256Add.json
new file mode 100644
index 00000000..b6fcd550
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/bn256Add.json
@@ -0,0 +1,114 @@
+[
+ {
+ "Input": "18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7",
+ "Expected": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915",
+ "Name": "chfast1",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91518b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266",
+ "Expected": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204",
+ "Name": "chfast2",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "cdetrio1",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "cdetrio2",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "cdetrio3",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "cdetrio4",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "cdetrio5",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Name": "cdetrio6",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Name": "cdetrio7",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Name": "cdetrio8",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Gas": 150,
+ "Name": "cdetrio9",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Gas": 150,
+ "Name": "cdetrio10",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ "Expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4",
+ "Name": "cdetrio11",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4",
+ "Name": "cdetrio12",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98",
+ "Expected": "15bf2bb17880144b5d1cd2b1f46eff9d617bffd1ca57c37fb5a49bd84e53cf66049c797f9ce0d17083deb32b5e36f2ea2a212ee036598dd7624c168993d1355f",
+ "Name": "cdetrio13",
+ "Gas": 150,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "cdetrio14",
+ "Gas": 150,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/bn256Pairing.json b/x/evm/core/vm/testdata/precompiles/bn256Pairing.json
new file mode 100644
index 00000000..3fbed6b8
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/bn256Pairing.json
@@ -0,0 +1,100 @@
+[
+ {
+ "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "jeff1",
+ "Gas": 113000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "jeff2",
+ "Gas": 113000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "jeff3",
+ "Gas": 113000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "jeff4",
+ "Gas": 147000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "jeff5",
+ "Gas": 147000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "jeff6",
+ "Gas": 113000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "empty_data",
+ "Gas": 45000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "one_point",
+ "Gas": 79000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "two_point_match_2",
+ "Gas": 113000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "two_point_match_3",
+ "Gas": 113000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "two_point_match_4",
+ "Gas": 113000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "ten_point_match_1",
+ "Gas": 385000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "ten_point_match_2",
+ "Gas": 385000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "ten_point_match_3",
+ "Gas": 113000,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/bn256ScalarMul.json b/x/evm/core/vm/testdata/precompiles/bn256ScalarMul.json
new file mode 100644
index 00000000..2a28f630
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/bn256ScalarMul.json
@@ -0,0 +1,128 @@
+[
+ {
+ "Input": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2",
+ "Expected": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc",
+ "Name": "chfast1",
+ "Gas": 6000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46",
+ "Expected": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e",
+ "Name": "chfast2",
+ "Gas": 6000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3",
+ "Expected": "14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27",
+ "Name": "chfast3",
+ "Gas": 6000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11",
+ "Name": "cdetrio1",
+ "Gas": 6000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000",
+ "Expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451",
+ "Name": "cdetrio2",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000100000000000000000000000000000000",
+ "Expected": "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b",
+ "Name": "cdetrio3",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000009",
+ "Expected": "1dbad7d39dbc56379f78fac1bca147dc8e66de1b9d183c7b167351bfe0aeab742cd757d51289cd8dbd0acf9e673ad67d0f0a89f912af47ed1be53664f5692575",
+ "Name": "cdetrio4",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000001",
+ "Expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6",
+ "Name": "cdetrio5",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "29e587aadd7c06722aabba753017c093f70ba7eb1f1c0104ec0564e7e3e21f6022b1143f6a41008e7755c71c3d00b6b915d386de21783ef590486d8afa8453b1",
+ "Name": "cdetrio6",
+ "Gas": 6000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000",
+ "Expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb",
+ "Name": "cdetrio7",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000100000000000000000000000000000000",
+ "Expected": "221a3577763877920d0d14a91cd59b9479f83b87a653bb41f82a3f6f120cea7c2752c7f64cdd7f0e494bff7b60419f242210f2026ed2ec70f89f78a4c56a1f15",
+ "Name": "cdetrio8",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000009",
+ "Expected": "228e687a379ba154554040f8821f4e41ee2be287c201aa9c3bc02c9dd12f1e691e0fd6ee672d04cfd924ed8fdc7ba5f2d06c53c1edc30f65f2af5a5b97f0a76a",
+ "Name": "cdetrio9",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000001",
+ "Expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c",
+ "Name": "cdetrio10",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "00a1a234d08efaa2616607e31eca1980128b00b415c845ff25bba3afcb81dc00242077290ed33906aeb8e42fd98c41bcb9057ba03421af3f2d08cfc441186024",
+ "Name": "cdetrio11",
+ "Gas": 6000,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d9830644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000",
+ "Expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b8692929ee761a352600f54921df9bf472e66217e7bb0cee9032e00acc86b3c8bfaf",
+ "Name": "cdetrio12",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000100000000000000000000000000000000",
+ "Expected": "1071b63011e8c222c5a771dfa03c2e11aac9666dd097f2c620852c3951a4376a2f46fe2f73e1cf310a168d56baa5575a8319389d7bfa6b29ee2d908305791434",
+ "Name": "cdetrio13",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000009",
+ "Expected": "19f75b9dd68c080a688774a6213f131e3052bd353a304a189d7a2ee367e3c2582612f545fb9fc89fde80fd81c68fc7dcb27fea5fc124eeda69433cf5c46d2d7f",
+ "Name": "cdetrio14",
+ "Gas": 6000,
+ "NoBenchmark": true
+ },
+ {
+ "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000001",
+ "Expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98",
+ "Name": "cdetrio15",
+ "Gas": 6000,
+ "NoBenchmark": true
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/ecRecover.json b/x/evm/core/vm/testdata/precompiles/ecRecover.json
new file mode 100644
index 00000000..4911d615
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/ecRecover.json
@@ -0,0 +1,37 @@
+[
+ {
+ "Input": "a8b53bdf3306a35a7103ab5504a0c9b492295564b6202b1942a84ef300107281000000000000000000000000000000000000000000000000000000000000001b307835653165303366353363653138623737326363623030393366663731663366353366356337356237346463623331613835616138623838393262346538621122334455667788991011121314151617181920212223242526272829303132",
+ "Expected": "",
+ "Gas": 3000,
+ "Name": "CallEcrecoverUnrecoverableKey",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ "Expected": "000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "Gas": 3000,
+ "Name": "ValidKey",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c100000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ "Expected": "",
+ "Gas": 3000,
+ "Name": "InvalidHighV-bits-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ "Expected": "",
+ "Gas": 3000,
+ "Name": "InvalidHighV-bits-2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000011c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ "Expected": "",
+ "Gas": 3000,
+ "Name": "InvalidHighV-bits-3",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blake2f.json b/x/evm/core/vm/testdata/precompiles/fail-blake2f.json
new file mode 100644
index 00000000..70835aa5
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blake2f.json
@@ -0,0 +1,22 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "vector 0: empty input"
+ },
+ {
+ "Input": "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ "ExpectedError": "invalid input length",
+ "Name": "vector 1: less than 213 bytes input"
+ },
+ {
+ "Input": "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
+ "ExpectedError": "invalid input length",
+ "Name": "vector 2: more than 213 bytes input"
+ },
+ {
+ "Input": "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002",
+ "ExpectedError": "invalid final flag",
+ "Name": "vector 3: malformed final block indicator flag"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsG1Add.json b/x/evm/core/vm/testdata/precompiles/fail-blsG1Add.json
new file mode 100644
index 00000000..e58ec0e9
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsG1Add.json
@@ -0,0 +1,32 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1add_empty_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1add_short_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1add_large_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000108b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_g1add_violate_top_bytes"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_g1add_invalid_field_element"
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_g1add_point_not_on_curve"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsG1Mul.json b/x/evm/core/vm/testdata/precompiles/fail-blsG1Mul.json
new file mode 100644
index 00000000..acb8228a
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsG1Mul.json
@@ -0,0 +1,32 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1mul_empty_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1mul_short_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1mul_large_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000108b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_g1mul_violate_top_bytes"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_g1mul_invalid_field_element"
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_g1mul_point_not_on_curve"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsG1MultiExp.json b/x/evm/core/vm/testdata/precompiles/fail-blsG1MultiExp.json
new file mode 100644
index 00000000..2cd28bd3
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsG1MultiExp.json
@@ -0,0 +1,32 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1multiexp_empty_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1multiexp_short_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g1multiexp_large_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_g1multiexp_invalid_field_element"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000108b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_g1multiexp_violate_top_bytes"
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_g1multiexp_point_not_on_curve"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsG2Add.json b/x/evm/core/vm/testdata/precompiles/fail-blsG2Add.json
new file mode 100644
index 00000000..b1fe9d5b
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsG2Add.json
@@ -0,0 +1,32 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2add_empty_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828010000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2add_short_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2add_large_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_g2add_violate_top_bytes"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_g2add_invalid_field_element"
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_g2add_point_not_on_curve"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsG2Mul.json b/x/evm/core/vm/testdata/precompiles/fail-blsG2Mul.json
new file mode 100644
index 00000000..c2f0b89c
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsG2Mul.json
@@ -0,0 +1,32 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2mul_empty_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828010000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2mul_short_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2mul_large_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_g2mul_violate_top_bytes"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_g2mul_invalid_field_element"
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_g2mul_point_not_on_curve"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsG2MultiExp.json b/x/evm/core/vm/testdata/precompiles/fail-blsG2MultiExp.json
new file mode 100644
index 00000000..437f8dfc
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsG2MultiExp.json
@@ -0,0 +1,32 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2multiexp_empty_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828010000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2multiexp_short_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_g2multiexp_large_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_g2multiexp_violate_top_bytes"
+ },
+ {
+ "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_g2multiexp_invalid_field_element"
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_g2multiexp_point_not_on_curve"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsMapG1.json b/x/evm/core/vm/testdata/precompiles/fail-blsMapG1.json
new file mode 100644
index 00000000..8550269f
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsMapG1.json
@@ -0,0 +1,22 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_mapg1_empty_input"
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_mapg1_short_input"
+ },
+ {
+ "Input": "00000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_mapg1_top_bytes"
+ },
+ {
+ "Input": "000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_mapg1_invalid_fq_element"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsMapG2.json b/x/evm/core/vm/testdata/precompiles/fail-blsMapG2.json
new file mode 100644
index 00000000..397a608b
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsMapG2.json
@@ -0,0 +1,22 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_mapg2_empty_input"
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_mapg2_short_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_mapg2_top_bytes"
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_mapg2_invalid_fq_element"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/fail-blsPairing.json b/x/evm/core/vm/testdata/precompiles/fail-blsPairing.json
new file mode 100644
index 00000000..084e5563
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/fail-blsPairing.json
@@ -0,0 +1,42 @@
+[
+ {
+ "Input": "",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_pairing_empty_input"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "invalid input length",
+ "Name": "bls_pairing_extra_data"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac",
+ "ExpectedError": "must be less than modulus",
+ "Name": "bls_pairing_invalid_field_element"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "invalid field element top bytes",
+ "Name": "bls_pairing_top_bytes"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_pairing_g1_not_on_curve"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "ExpectedError": "point is not on curve",
+ "Name": "bls_pairing_g2_not_on_curve"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000a989badd40d6212b33cffc3f3763e9bc760f988c9926b26da9dd85e928483446346b8ed00e1de5d5ea93e354abe706c00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ "ExpectedError": "g1 point is not on correct subgroup",
+ "Name": "bls_pairing_g1_not_in_correct_subgroup"
+ },
+ {
+ "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013a59858b6809fca4d9a3b6539246a70051a3c88899964a42bc9a69cf9acdd9dd387cfa9086b894185b9a46a402be730000000000000000000000000000000002d27e0ec3356299a346a09ad7dc4ef68a483c3aed53f9139d2f929a3eecebf72082e5e58c6da24ee32e03040c406d4f",
+ "ExpectedError": "g2 point is not on correct subgroup",
+ "Name": "bls_pairing_g2_not_in_correct_subgroup"
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/modexp.json b/x/evm/core/vm/testdata/precompiles/modexp.json
new file mode 100644
index 00000000..4550eb91
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/modexp.json
@@ -0,0 +1,121 @@
+[
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "eip_example1",
+ "Gas": 13056,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "eip_example2",
+ "Gas": 13056,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
+ "Expected": "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc",
+ "Name": "nagydani-1-square",
+ "Gas": 204,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
+ "Expected": "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec",
+ "Name": "nagydani-1-qube",
+ "Gas": 204,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
+ "Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2",
+ "Name": "nagydani-1-pow0x10001",
+ "Gas": 3276,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
+ "Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70",
+ "Name": "nagydani-2-square",
+ "Gas": 665,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
+ "Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f",
+ "Name": "nagydani-2-qube",
+ "Gas": 665,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
+ "Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2",
+ "Name": "nagydani-2-pow0x10001",
+ "Gas": 10649,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
+ "Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8",
+ "Name": "nagydani-3-square",
+ "Gas": 1894,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
+ "Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e",
+ "Name": "nagydani-3-qube",
+ "Gas": 1894,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
+ "Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76",
+ "Name": "nagydani-3-pow0x10001",
+ "Gas": 30310,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
+ "Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10",
+ "Name": "nagydani-4-square",
+ "Gas": 5580,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
+ "Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc",
+ "Name": "nagydani-4-qube",
+ "Gas": 5580,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
+ "Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963",
+ "Name": "nagydani-4-pow0x10001",
+ "Gas": 89292,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
+ "Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb",
+ "Name": "nagydani-5-square",
+ "Gas": 17868,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
+ "Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f",
+ "Name": "nagydani-5-qube",
+ "Gas": 17868,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
+ "Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500",
+ "Name": "nagydani-5-pow0x10001",
+ "Gas": 285900,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/precompiles/modexp_eip2565.json b/x/evm/core/vm/testdata/precompiles/modexp_eip2565.json
new file mode 100644
index 00000000..c5544143
--- /dev/null
+++ b/x/evm/core/vm/testdata/precompiles/modexp_eip2565.json
@@ -0,0 +1,121 @@
+[
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Name": "eip_example1",
+ "Gas": 1360,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
+ "Name": "eip_example2",
+ "Gas": 1360,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
+ "Expected": "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc",
+ "Name": "nagydani-1-square",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
+ "Expected": "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec",
+ "Name": "nagydani-1-qube",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
+ "Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2",
+ "Name": "nagydani-1-pow0x10001",
+ "Gas": 341,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
+ "Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70",
+ "Name": "nagydani-2-square",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
+ "Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f",
+ "Name": "nagydani-2-qube",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
+ "Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2",
+ "Name": "nagydani-2-pow0x10001",
+ "Gas": 1365,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
+ "Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8",
+ "Name": "nagydani-3-square",
+ "Gas": 341,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
+ "Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e",
+ "Name": "nagydani-3-qube",
+ "Gas": 341,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
+ "Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76",
+ "Name": "nagydani-3-pow0x10001",
+ "Gas": 5461,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
+ "Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10",
+ "Name": "nagydani-4-square",
+ "Gas": 1365,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
+ "Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc",
+ "Name": "nagydani-4-qube",
+ "Gas": 1365,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
+ "Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963",
+ "Name": "nagydani-4-pow0x10001",
+ "Gas": 21845,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
+ "Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb",
+ "Name": "nagydani-5-square",
+ "Gas": 5461,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
+ "Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f",
+ "Name": "nagydani-5-qube",
+ "Gas": 5461,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
+ "Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500",
+ "Name": "nagydani-5-pow0x10001",
+ "Gas": 87381,
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_add.json b/x/evm/core/vm/testdata/testcases_add.json
new file mode 100644
index 00000000..c03ae96a
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_add.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"000000000000000000000000000000000000000000000000000000000000000a"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_and.json b/x/evm/core/vm/testdata/testcases_and.json
new file mode 100644
index 00000000..aba5f246
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_and.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_byte.json b/x/evm/core/vm/testdata/testcases_byte.json
new file mode 100644
index 00000000..88d7c7d8
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_byte.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"000000000000000000000000000000000000000000000000000000000000007f"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"000000000000000000000000000000000000000000000000000000000000007f"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000080"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000080"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_div.json b/x/evm/core/vm/testdata/testcases_div.json
new file mode 100644
index 00000000..b1f9c7fb
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_div.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"3333333333333333333333333333333333333333333333333333333333333332"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"3333333333333333333333333333333333333333333333333333333333333333"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_eq.json b/x/evm/core/vm/testdata/testcases_eq.json
new file mode 100644
index 00000000..937eadb0
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_eq.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_exp.json b/x/evm/core/vm/testdata/testcases_exp.json
new file mode 100644
index 00000000..61818357
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_exp.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000c35"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3cb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c29"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c29"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccd"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"3333333333333333333333333333333333333333333333333333333333333333"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"58cd20afa2f05a708ede54b48d3ae685db76b3bb83cf2cf95d4e8fb00bcbe61d"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"a732df505d0fa58f7121ab4b72c5197a24894c447c30d306a2b1704ff43419e3"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccd"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"3333333333333333333333333333333333333333333333333333333333333333"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_gt.json b/x/evm/core/vm/testdata/testcases_gt.json
new file mode 100644
index 00000000..637bd3f6
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_gt.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_lt.json b/x/evm/core/vm/testdata/testcases_lt.json
new file mode 100644
index 00000000..55252a4d
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_lt.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_mod.json b/x/evm/core/vm/testdata/testcases_mod.json
new file mode 100644
index 00000000..192503f2
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_mod.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_mul.json b/x/evm/core/vm/testdata/testcases_mul.json
new file mode 100644
index 00000000..dc44c253
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_mul.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000019"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"800000000000000000000000000000000000000000000000000000000000000a"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"800000000000000000000000000000000000000000000000000000000000000a"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000019"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_or.json b/x/evm/core/vm/testdata/testcases_or.json
new file mode 100644
index 00000000..bfa561b5
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_or.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_sar.json b/x/evm/core/vm/testdata/testcases_sar.json
new file mode 100644
index 00000000..c93abbd6
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_sar.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"c000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fc00000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"c000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fc00000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_sdiv.json b/x/evm/core/vm/testdata/testcases_sdiv.json
new file mode 100644
index 00000000..18cb666a
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_sdiv.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_sgt.json b/x/evm/core/vm/testdata/testcases_sgt.json
new file mode 100644
index 00000000..aa581a65
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_sgt.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_shl.json b/x/evm/core/vm/testdata/testcases_shl.json
new file mode 100644
index 00000000..65e9c07b
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_shl.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000020"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"000000000000000000000000000000000000000000000000000000000000000a"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000a0"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000020"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_shr.json b/x/evm/core/vm/testdata/testcases_shr.json
new file mode 100644
index 00000000..a3849135
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_shr.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"4000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0400000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"4000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0400000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_signext.json b/x/evm/core/vm/testdata/testcases_signext.json
new file mode 100644
index 00000000..bdadd400
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_signext.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_slt.json b/x/evm/core/vm/testdata/testcases_slt.json
new file mode 100644
index 00000000..4369b96f
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_slt.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_smod.json b/x/evm/core/vm/testdata/testcases_smod.json
new file mode 100644
index 00000000..980e0341
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_smod.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_sub.json b/x/evm/core/vm/testdata/testcases_sub.json
new file mode 100644
index 00000000..b3881a5a
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_sub.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000007"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"000000000000000000000000000000000000000000000000000000000000000a"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/core/vm/testdata/testcases_xor.json b/x/evm/core/vm/testdata/testcases_xor.json
new file mode 100644
index 00000000..4cc2dddd
--- /dev/null
+++ b/x/evm/core/vm/testdata/testcases_xor.json
@@ -0,0 +1 @@
+[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}]
\ No newline at end of file
diff --git a/x/evm/genesis.go b/x/evm/genesis.go
new file mode 100644
index 00000000..54ca4c61
--- /dev/null
+++ b/x/evm/genesis.go
@@ -0,0 +1,85 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package evm
+
+import (
+ "fmt"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+
+ "github.com/evmos/evmos/v19/x/evm/keeper"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// InitGenesis initializes genesis state based on exported genesis
+func InitGenesis(
+ ctx sdk.Context,
+ k *keeper.Keeper,
+ accountKeeper types.AccountKeeper,
+ data types.GenesisState,
+) []abci.ValidatorUpdate {
+ k.WithChainID(ctx)
+
+ err := k.SetParams(ctx, data.Params)
+ if err != nil {
+ panic(fmt.Errorf("error setting params %s", err))
+ }
+
+ // ensure evm module account is set
+ if addr := accountKeeper.GetModuleAddress(types.ModuleName); addr == nil {
+ panic("the EVM module account has not been set")
+ }
+
+ for _, account := range data.Accounts {
+ address := common.HexToAddress(account.Address)
+ accAddress := sdk.AccAddress(address.Bytes())
+
+ // check that the account is actually found in the account keeper
+ acc := accountKeeper.GetAccount(ctx, accAddress)
+ if acc == nil {
+ panic(fmt.Errorf("account not found for address %s", account.Address))
+ }
+
+ code := common.Hex2Bytes(account.Code)
+ codeHash := crypto.Keccak256Hash(code).Bytes()
+
+ if !types.IsEmptyCodeHash(codeHash) {
+ k.SetCodeHash(ctx, address.Bytes(), codeHash)
+ }
+
+ if len(code) != 0 {
+ k.SetCode(ctx, codeHash, code)
+ }
+
+ for _, storage := range account.Storage {
+ k.SetState(ctx, address, common.HexToHash(storage.Key), common.HexToHash(storage.Value).Bytes())
+ }
+ }
+
+ return []abci.ValidatorUpdate{}
+}
+
+// ExportGenesis exports genesis state of the EVM module
+func ExportGenesis(ctx sdk.Context, k *keeper.Keeper) *types.GenesisState {
+ var ethGenAccounts []types.GenesisAccount
+ k.IterateContracts(ctx, func(address common.Address, codeHash common.Hash) (stop bool) {
+ storage := k.GetAccountStorage(ctx, address)
+
+ genAccount := types.GenesisAccount{
+ Address: address.String(),
+ Code: common.Bytes2Hex(k.GetCode(ctx, codeHash)),
+ Storage: storage,
+ }
+
+ ethGenAccounts = append(ethGenAccounts, genAccount)
+ return false
+ })
+
+ return &types.GenesisState{
+ Accounts: ethGenAccounts,
+ Params: k.GetParams(ctx),
+ }
+}
diff --git a/x/evm/genesis_test.go b/x/evm/genesis_test.go
new file mode 100644
index 00000000..f627b800
--- /dev/null
+++ b/x/evm/genesis_test.go
@@ -0,0 +1,243 @@
+package evm_test
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/contracts"
+ "github.com/evmos/evmos/v19/crypto/ethsecp256k1"
+ testfactory "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ testhandler "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ testnetwork "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ "github.com/evmos/evmos/v19/x/evm"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+ "github.com/stretchr/testify/require"
+)
+
+type GenesisTestSuite struct {
+ keyring testkeyring.Keyring
+ network *testnetwork.UnitTestNetwork
+ handler testhandler.Handler
+ factory testfactory.TxFactory
+}
+
+func SetupTest() *GenesisTestSuite {
+ keyring := testkeyring.New(1)
+ network := testnetwork.NewUnitTestNetwork(
+ testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ handler := testhandler.NewIntegrationHandler(network)
+ factory := testfactory.New(network, handler)
+
+ return &GenesisTestSuite{
+ keyring: keyring,
+ network: network,
+ handler: handler,
+ factory: factory,
+ }
+}
+
+func TestInitGenesis(t *testing.T) {
+ privkey, err := ethsecp256k1.GenerateKey()
+ require.NoError(t, err, "failed to generate private key")
+
+ address := common.HexToAddress(privkey.PubKey().Address().String())
+
+ var vmdb *statedb.StateDB
+
+ testCases := []struct {
+ name string
+ malleate func(*testnetwork.UnitTestNetwork)
+ genState *types.GenesisState
+ code common.Hash
+ expPanic bool
+ }{
+ {
+ name: "default",
+ malleate: func(_ *testnetwork.UnitTestNetwork) {},
+ genState: types.DefaultGenesisState(),
+ expPanic: false,
+ },
+ {
+ name: "valid account",
+ malleate: func(_ *testnetwork.UnitTestNetwork) {
+ vmdb.AddBalance(address, big.NewInt(1))
+ },
+ genState: &types.GenesisState{
+ Params: types.DefaultParams(),
+ Accounts: []types.GenesisAccount{
+ {
+ Address: address.String(),
+ Storage: types.Storage{
+ {Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()},
+ },
+ },
+ },
+ },
+ expPanic: false,
+ },
+ {
+ name: "account not found",
+ malleate: func(_ *testnetwork.UnitTestNetwork) {},
+ genState: &types.GenesisState{
+ Params: types.DefaultParams(),
+ Accounts: []types.GenesisAccount{
+ {
+ Address: address.String(),
+ },
+ },
+ },
+ expPanic: true,
+ },
+ {
+ name: "ignore empty account code checking",
+ malleate: func(network *testnetwork.UnitTestNetwork) {
+ ctx := network.GetContext()
+ acc := network.App.AccountKeeper.NewAccountWithAddress(ctx, address.Bytes())
+ network.App.AccountKeeper.SetAccount(ctx, acc)
+ },
+ genState: &types.GenesisState{
+ Params: types.DefaultParams(),
+ Accounts: []types.GenesisAccount{
+ {
+ Address: address.String(),
+ Code: "",
+ },
+ },
+ },
+ expPanic: false,
+ },
+ {
+ name: "valid account with code",
+ malleate: func(network *testnetwork.UnitTestNetwork) {
+ ctx := network.GetContext()
+ acc := network.App.AccountKeeper.NewAccountWithAddress(ctx, address.Bytes())
+ network.App.AccountKeeper.SetAccount(ctx, acc)
+ },
+ genState: &types.GenesisState{
+ Params: types.DefaultParams(),
+ Accounts: []types.GenesisAccount{
+ {
+ Address: address.String(),
+ Code: "1234",
+ },
+ },
+ },
+ expPanic: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ ts := SetupTest()
+ ctx := ts.network.GetContext()
+
+ vmdb = statedb.New(
+ ctx,
+ ts.network.App.EvmKeeper,
+ statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())),
+ )
+
+ tc.malleate(ts.network)
+ err := vmdb.Commit()
+ require.NoError(t, err, "failed to commit to state db")
+
+ if tc.expPanic {
+ require.Panics(t, func() {
+ _ = evm.InitGenesis(
+ ts.network.GetContext(),
+ ts.network.App.EvmKeeper,
+ ts.network.App.AccountKeeper,
+ *tc.genState,
+ )
+ })
+ } else {
+ require.NotPanics(t, func() {
+ _ = evm.InitGenesis(
+ ctx,
+ ts.network.App.EvmKeeper,
+ ts.network.App.AccountKeeper,
+ *tc.genState,
+ )
+ })
+
+ // If the initialization has not panicked we're checking the state
+ for _, account := range tc.genState.Accounts {
+ acc := ts.network.App.AccountKeeper.GetAccount(ctx, common.HexToAddress(account.Address).Bytes())
+ require.NotNil(t, acc, "account not found in account keeper")
+
+ expHash := crypto.Keccak256Hash(common.Hex2Bytes(account.Code))
+ if account.Code == "" {
+ expHash = common.BytesToHash(types.EmptyCodeHash)
+ }
+
+ require.Equal(t,
+ expHash.String(),
+ ts.network.App.EvmKeeper.GetCodeHash(
+ ts.network.GetContext(),
+ common.HexToAddress(account.Address),
+ ).String(),
+ "code hash mismatch",
+ )
+
+ require.Equal(t,
+ account.Code,
+ common.Bytes2Hex(
+ ts.network.App.EvmKeeper.GetCode(
+ ts.network.GetContext(),
+ expHash,
+ ),
+ ),
+ "code mismatch",
+ )
+
+ for _, storage := range account.Storage {
+ key := common.HexToHash(storage.Key)
+ value := common.HexToHash(storage.Value)
+ require.Equal(t, value, vmdb.GetState(common.HexToAddress(account.Address), key), "storage mismatch")
+ }
+ }
+ }
+ })
+ }
+}
+
+func TestExportGenesis(t *testing.T) {
+ ts := SetupTest()
+
+ contractAddr, err := ts.factory.DeployContract(
+ ts.keyring.GetPrivKey(0),
+ types.EvmTxArgs{},
+ testfactory.ContractDeploymentData{
+ Contract: contracts.ERC20MinterBurnerDecimalsContract,
+ ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)},
+ },
+ )
+ require.NoError(t, err, "failed to deploy contract")
+ require.NoError(t, ts.network.NextBlock(), "failed to advance block")
+
+ contractAddr2, err := ts.factory.DeployContract(
+ ts.keyring.GetPrivKey(0),
+ types.EvmTxArgs{},
+ testfactory.ContractDeploymentData{
+ Contract: contracts.ERC20MinterBurnerDecimalsContract,
+ ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)},
+ },
+ )
+ require.NoError(t, err, "failed to deploy contract")
+ require.NoError(t, ts.network.NextBlock(), "failed to advance block")
+
+ genState := evm.ExportGenesis(ts.network.GetContext(), ts.network.App.EvmKeeper)
+ require.Len(t, genState.Accounts, 2, "expected only one smart contract in the exported genesis")
+
+ genAddresses := make([]string, 0, len(genState.Accounts))
+ for _, acc := range genState.Accounts {
+ genAddresses = append(genAddresses, acc.Address)
+ }
+ require.Contains(t, genAddresses, contractAddr.Hex(), "expected contract 1 address in exported genesis")
+ require.Contains(t, genAddresses, contractAddr2.Hex(), "expected contract 2 address in exported genesis")
+}
diff --git a/x/evm/keeper/abci.go b/x/evm/keeper/abci.go
new file mode 100644
index 00000000..df9e2979
--- /dev/null
+++ b/x/evm/keeper/abci.go
@@ -0,0 +1,29 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ abci "github.com/cometbft/cometbft/abci/types"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+)
+
+// BeginBlock sets the sdk Context and EIP155 chain id to the Keeper.
+func (k *Keeper) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
+ k.WithChainID(ctx)
+}
+
+// EndBlock also retrieves the bloom filter value from the transient store and commits it to the
+// KVStore. The EVM end block logic doesn't update the validator set, thus it returns
+// an empty slice.
+func (k *Keeper) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
+ // Gas costs are handled within msg handler so costs should be ignored
+ infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
+
+ bloom := ethtypes.BytesToBloom(k.GetBlockBloomTransient(infCtx).Bytes())
+ k.EmitBlockBloomEvent(infCtx, bloom)
+
+ return []abci.ValidatorUpdate{}
+}
diff --git a/x/evm/keeper/abci_test.go b/x/evm/keeper/abci_test.go
new file mode 100644
index 00000000..e52cfb16
--- /dev/null
+++ b/x/evm/keeper/abci_test.go
@@ -0,0 +1,18 @@
+package keeper_test
+
+import (
+ "github.com/cometbft/cometbft/abci/types"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *KeeperTestSuite) TestEndBlock() {
+ em := suite.ctx.EventManager()
+ suite.Require().Equal(0, len(em.Events()))
+
+ res := suite.app.EvmKeeper.EndBlock(suite.ctx, types.RequestEndBlock{})
+ suite.Require().Equal([]types.ValidatorUpdate{}, res)
+
+ // should emit 1 EventTypeBlockBloom event on EndBlock
+ suite.Require().Equal(1, len(em.Events()))
+ suite.Require().Equal(evmtypes.EventTypeBlockBloom, em.Events()[0].Type)
+}
diff --git a/x/evm/keeper/benchmark_test.go b/x/evm/keeper/benchmark_test.go
new file mode 100644
index 00000000..eeb276de
--- /dev/null
+++ b/x/evm/keeper/benchmark_test.go
@@ -0,0 +1,207 @@
+package keeper_test
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/evmos/evmos/v19/x/evm/keeper/testdata"
+
+ sdkmath "cosmossdk.io/math"
+ "github.com/stretchr/testify/require"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
+ "github.com/ethereum/go-ethereum/common"
+
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ evmostypes "github.com/evmos/evmos/v19/types"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func SetupContract(b *testing.B) (*KeeperTestSuite, common.Address) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+
+ amt := sdk.Coins{evmostypes.NewEvmosCoinInt64(1000000000000000000)}
+ err := suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, amt)
+ require.NoError(b, err)
+ err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, suite.address.Bytes(), amt)
+ require.NoError(b, err)
+
+ contractAddr := suite.DeployTestContract(b, suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Commit()
+
+ return &suite, contractAddr
+}
+
+func SetupTestMessageCall(b *testing.B) (*KeeperTestSuite, common.Address) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+
+ amt := sdk.Coins{evmostypes.NewEvmosCoinInt64(1000000000000000000)}
+ err := suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, amt)
+ require.NoError(b, err)
+ err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, suite.address.Bytes(), amt)
+ require.NoError(b, err)
+
+ contractAddr := suite.DeployTestMessageCall(b)
+ suite.Commit()
+
+ return &suite, contractAddr
+}
+
+type TxBuilder func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx
+
+func DoBenchmark(b *testing.B, txBuilder TxBuilder) {
+ suite, contractAddr := SetupContract(b)
+
+ msg := txBuilder(suite, contractAddr)
+ msg.From = suite.address.Hex()
+ err := msg.Sign(ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()), suite.signer)
+ require.NoError(b, err)
+
+ b.ResetTimer()
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ ctx, _ := suite.ctx.CacheContext()
+
+ // deduct fee first
+ txData, err := types.UnpackTxData(msg.Data)
+ require.NoError(b, err)
+
+ fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(txData.Fee()))}
+ err = authante.DeductFees(suite.app.BankKeeper, suite.ctx, suite.app.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees)
+ require.NoError(b, err)
+
+ rsp, err := suite.app.EvmKeeper.EthereumTx(sdk.WrapSDKContext(ctx), msg)
+ require.NoError(b, err)
+ require.False(b, rsp.Failed())
+ }
+}
+
+func BenchmarkTokenTransfer(b *testing.B) {
+ erc20Contract, err := testdata.LoadERC20Contract()
+ require.NoError(b, err, "failed to load erc20 contract")
+
+ DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx {
+ input, err := erc20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
+ require.NoError(b, err)
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+ ethTxParams := &types.EvmTxArgs{
+ ChainID: suite.app.EvmKeeper.ChainID(),
+ Nonce: nonce,
+ To: &contract,
+ Amount: big.NewInt(0),
+ GasLimit: 410000,
+ GasPrice: big.NewInt(1),
+ Input: input,
+ }
+ return types.NewTx(ethTxParams)
+ })
+}
+
+func BenchmarkEmitLogs(b *testing.B) {
+ erc20Contract, err := testdata.LoadERC20Contract()
+ require.NoError(b, err, "failed to load erc20 contract")
+
+ DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx {
+ input, err := erc20Contract.ABI.Pack("benchmarkLogs", big.NewInt(1000))
+ require.NoError(b, err)
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+ ethTxParams := &types.EvmTxArgs{
+ ChainID: suite.app.EvmKeeper.ChainID(),
+ Nonce: nonce,
+ To: &contract,
+ Amount: big.NewInt(0),
+ GasLimit: 4100000,
+ GasPrice: big.NewInt(1),
+ Input: input,
+ }
+ return types.NewTx(ethTxParams)
+ })
+}
+
+func BenchmarkTokenTransferFrom(b *testing.B) {
+ erc20Contract, err := testdata.LoadERC20Contract()
+ require.NoError(b, err)
+
+ DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx {
+ input, err := erc20Contract.ABI.Pack("transferFrom", suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(0))
+ require.NoError(b, err)
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+ ethTxParams := &types.EvmTxArgs{
+ ChainID: suite.app.EvmKeeper.ChainID(),
+ Nonce: nonce,
+ To: &contract,
+ Amount: big.NewInt(0),
+ GasLimit: 410000,
+ GasPrice: big.NewInt(1),
+ Input: input,
+ }
+ return types.NewTx(ethTxParams)
+ })
+}
+
+func BenchmarkTokenMint(b *testing.B) {
+ erc20Contract, err := testdata.LoadERC20Contract()
+ require.NoError(b, err, "failed to load erc20 contract")
+
+ DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx {
+ input, err := erc20Contract.ABI.Pack("mint", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
+ require.NoError(b, err)
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+ ethTxParams := &types.EvmTxArgs{
+ ChainID: suite.app.EvmKeeper.ChainID(),
+ Nonce: nonce,
+ To: &contract,
+ Amount: big.NewInt(0),
+ GasLimit: 410000,
+ GasPrice: big.NewInt(1),
+ Input: input,
+ }
+ return types.NewTx(ethTxParams)
+ })
+}
+
+func BenchmarkMessageCall(b *testing.B) {
+ suite, contract := SetupTestMessageCall(b)
+
+ messageCallContract, err := testdata.LoadMessageCallContract()
+ require.NoError(b, err, "failed to load message call contract")
+
+ input, err := messageCallContract.ABI.Pack("benchmarkMessageCall", big.NewInt(10000))
+ require.NoError(b, err)
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+ ethTxParams := &types.EvmTxArgs{
+ ChainID: suite.app.EvmKeeper.ChainID(),
+ Nonce: nonce,
+ To: &contract,
+ Amount: big.NewInt(0),
+ GasLimit: 25000000,
+ GasPrice: big.NewInt(1),
+ Input: input,
+ }
+ msg := types.NewTx(ethTxParams)
+
+ msg.From = suite.address.Hex()
+ err = msg.Sign(ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()), suite.signer)
+ require.NoError(b, err)
+
+ b.ResetTimer()
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ ctx, _ := suite.ctx.CacheContext()
+
+ // deduct fee first
+ txData, err := types.UnpackTxData(msg.Data)
+ require.NoError(b, err)
+
+ fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(txData.Fee()))}
+ err = authante.DeductFees(suite.app.BankKeeper, suite.ctx, suite.app.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees)
+ require.NoError(b, err)
+
+ rsp, err := suite.app.EvmKeeper.EthereumTx(sdk.WrapSDKContext(ctx), msg)
+ require.NoError(b, err)
+ require.False(b, rsp.Failed())
+ }
+}
diff --git a/x/evm/keeper/block_proposer.go b/x/evm/keeper/block_proposer.go
new file mode 100644
index 00000000..a0e9cb17
--- /dev/null
+++ b/x/evm/keeper/block_proposer.go
@@ -0,0 +1,33 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// GetCoinbaseAddress returns the block proposer's validator operator address.
+func (k Keeper) GetCoinbaseAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) (common.Address, error) {
+ validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, GetProposerAddress(ctx, proposerAddress))
+ if !found {
+ return common.Address{}, errorsmod.Wrapf(
+ stakingtypes.ErrNoValidatorFound,
+ "failed to retrieve validator from block proposer address %s",
+ proposerAddress.String(),
+ )
+ }
+
+ coinbase := common.BytesToAddress(validator.GetOperator())
+ return coinbase, nil
+}
+
+// GetProposerAddress returns current block proposer's address when provided proposer address is empty.
+func GetProposerAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) sdk.ConsAddress {
+ if len(proposerAddress) == 0 {
+ proposerAddress = ctx.BlockHeader().ProposerAddress
+ }
+ return proposerAddress
+}
diff --git a/x/evm/keeper/call_evm.go b/x/evm/keeper/call_evm.go
new file mode 100644
index 00000000..24110f7d
--- /dev/null
+++ b/x/evm/keeper/call_evm.go
@@ -0,0 +1,102 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "encoding/json"
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/server/config"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// CallEVM performs a smart contract method call using given args
+func (k Keeper) CallEVM(
+ ctx sdk.Context,
+ abi abi.ABI,
+ from, contract common.Address,
+ commit bool,
+ method string,
+ args ...interface{},
+) (*types.MsgEthereumTxResponse, error) {
+ data, err := abi.Pack(method, args...)
+ if err != nil {
+ return nil, errorsmod.Wrap(
+ types.ErrABIPack,
+ errorsmod.Wrap(err, "failed to create transaction data").Error(),
+ )
+ }
+
+ resp, err := k.CallEVMWithData(ctx, from, &contract, data, commit)
+ if err != nil {
+ return nil, errorsmod.Wrapf(err, "contract call failed: method '%s', contract '%s'", method, contract)
+ }
+ return resp, nil
+}
+
+// CallEVMWithData performs a smart contract method call using contract data
+func (k Keeper) CallEVMWithData(
+ ctx sdk.Context,
+ from common.Address,
+ contract *common.Address,
+ data []byte,
+ commit bool,
+) (*types.MsgEthereumTxResponse, error) {
+ nonce, err := k.accountKeeper.GetSequence(ctx, from.Bytes())
+ if err != nil {
+ return nil, err
+ }
+
+ gasCap := config.DefaultGasCap
+ if commit {
+ args, err := json.Marshal(types.TransactionArgs{
+ From: &from,
+ To: contract,
+ Data: (*hexutil.Bytes)(&data),
+ })
+ if err != nil {
+ return nil, errorsmod.Wrapf(errortypes.ErrJSONMarshal, "failed to marshal tx args: %s", err.Error())
+ }
+
+ gasRes, err := k.EstimateGasInternal(sdk.WrapSDKContext(ctx), &types.EthCallRequest{
+ Args: args,
+ GasCap: config.DefaultGasCap,
+ }, types.Internal)
+ if err != nil {
+ return nil, err
+ }
+ gasCap = gasRes.Gas
+ }
+
+ msg := ethtypes.NewMessage(
+ from,
+ contract,
+ nonce,
+ big.NewInt(0), // amount
+ gasCap, // gasLimit
+ big.NewInt(0), // gasFeeCap
+ big.NewInt(0), // gasTipCap
+ big.NewInt(0), // gasPrice
+ data,
+ ethtypes.AccessList{}, // AccessList
+ !commit, // isFake
+ )
+
+ res, err := k.ApplyMessage(ctx, msg, types.NewNoOpTracer(), commit)
+ if err != nil {
+ return nil, err
+ }
+
+ if res.Failed() {
+ return nil, errorsmod.Wrap(types.ErrVMExecution, res.VmError)
+ }
+
+ return res, nil
+}
diff --git a/x/evm/keeper/call_evm_test.go b/x/evm/keeper/call_evm_test.go
new file mode 100644
index 00000000..6d8fd7c6
--- /dev/null
+++ b/x/evm/keeper/call_evm_test.go
@@ -0,0 +1,161 @@
+package keeper_test
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/contracts"
+ "github.com/evmos/evmos/v19/testutil"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/erc20/types"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+const erc20Decimals = uint8(18)
+
+// DeployContract deploys the ERC20MinterBurnerDecimalsContract.
+func (suite *KeeperTestSuite) DeployContract(name, symbol string, decimals uint8) (common.Address, error) {
+ suite.Commit()
+ addr, err := testutil.DeployContract(
+ suite.ctx,
+ suite.app,
+ suite.priv,
+ suite.queryClient,
+ contracts.ERC20MinterBurnerDecimalsContract,
+ name, symbol, decimals,
+ )
+ suite.Commit()
+ return addr, err
+}
+
+func (suite *KeeperTestSuite) TestCallEVM() {
+ testCases := []struct {
+ name string
+ method string
+ expPass bool
+ }{
+ {
+ "unknown method",
+ "",
+ false,
+ },
+ {
+ "pass",
+ "balanceOf",
+ true,
+ },
+ }
+ for _, tc := range testCases {
+ suite.SetupTest() // reset
+
+ erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI
+ contract, err := suite.DeployContract("coin", "token", erc20Decimals)
+ suite.Require().NoError(err)
+ account := utiltx.GenerateAddress()
+
+ res, err := suite.app.EvmKeeper.CallEVM(suite.ctx, erc20, types.ModuleAddress, contract, true, tc.method, account)
+ if tc.expPass {
+ suite.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name)
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ }
+}
+
+func (suite *KeeperTestSuite) TestCallEVMWithData() {
+ erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI
+ testCases := []struct {
+ name string
+ from common.Address
+ malleate func() ([]byte, *common.Address)
+ expPass bool
+ }{
+ {
+ "unknown method",
+ types.ModuleAddress,
+ func() ([]byte, *common.Address) {
+ contract, err := suite.DeployContract("coin", "token", erc20Decimals)
+ suite.Require().NoError(err)
+ account := utiltx.GenerateAddress()
+ data, _ := erc20.Pack("", account)
+ return data, &contract
+ },
+ false,
+ },
+ {
+ "pass",
+ types.ModuleAddress,
+ func() ([]byte, *common.Address) {
+ contract, err := suite.DeployContract("coin", "token", erc20Decimals)
+ suite.Require().NoError(err)
+ account := utiltx.GenerateAddress()
+ data, _ := erc20.Pack("balanceOf", account)
+ return data, &contract
+ },
+ true,
+ },
+ {
+ "fail empty data",
+ types.ModuleAddress,
+ func() ([]byte, *common.Address) {
+ contract, err := suite.DeployContract("coin", "token", erc20Decimals)
+ suite.Require().NoError(err)
+ return []byte{}, &contract
+ },
+ false,
+ },
+
+ {
+ "fail empty sender",
+ common.Address{},
+ func() ([]byte, *common.Address) {
+ contract, err := suite.DeployContract("coin", "token", erc20Decimals)
+ suite.Require().NoError(err)
+ return []byte{}, &contract
+ },
+ false,
+ },
+ {
+ "deploy",
+ types.ModuleAddress,
+ func() ([]byte, *common.Address) {
+ ctorArgs, _ := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack("", "test", "test", uint8(18))
+ data := append(contracts.ERC20MinterBurnerDecimalsContract.Bin, ctorArgs...) //nolint:gocritic
+ return data, nil
+ },
+ true,
+ },
+ {
+ "fail deploy",
+ types.ModuleAddress,
+ func() ([]byte, *common.Address) {
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ params.AccessControl.Create = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypeRestricted,
+ }
+ _ = suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ ctorArgs, _ := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack("", "test", "test", uint8(18))
+ data := append(contracts.ERC20MinterBurnerDecimalsContract.Bin, ctorArgs...) //nolint:gocritic
+ return data, nil
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.SetupTest() // reset
+
+ data, contract := tc.malleate()
+
+ res, err := suite.app.EvmKeeper.CallEVMWithData(suite.ctx, tc.from, contract, data, true)
+ if tc.expPass {
+ suite.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name)
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
diff --git a/x/evm/keeper/config.go b/x/evm/keeper/config.go
new file mode 100644
index 00000000..0fd55855
--- /dev/null
+++ b/x/evm/keeper/config.go
@@ -0,0 +1,66 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// EVMConfig creates the EVMConfig based on current state
+func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, chainID *big.Int) (*statedb.EVMConfig, error) {
+ params := k.GetParams(ctx)
+ ethCfg := params.ChainConfig.EthereumConfig(chainID)
+
+ // get the coinbase address from the block proposer
+ coinbase, err := k.GetCoinbaseAddress(ctx, proposerAddress)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to obtain coinbase address")
+ }
+
+ baseFee := k.GetBaseFee(ctx, ethCfg)
+ return &statedb.EVMConfig{
+ Params: params,
+ ChainConfig: ethCfg,
+ CoinBase: coinbase,
+ BaseFee: baseFee,
+ }, nil
+}
+
+// TxConfig loads `TxConfig` from current transient storage
+func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) statedb.TxConfig {
+ return statedb.NewTxConfig(
+ common.BytesToHash(ctx.HeaderHash()), // BlockHash
+ txHash, // TxHash
+ uint(k.GetTxIndexTransient(ctx)), // TxIndex
+ uint(k.GetLogSizeTransient(ctx)), // LogIndex
+ )
+}
+
+// VMConfig creates an EVM configuration from the debug setting and the extra EIPs enabled on the
+// module parameters. The config generated uses the default JumpTable from the EVM.
+func (k Keeper) VMConfig(ctx sdk.Context, _ core.Message, cfg *statedb.EVMConfig, tracer vm.EVMLogger) vm.Config {
+ noBaseFee := true
+ if types.IsLondon(cfg.ChainConfig, ctx.BlockHeight()) {
+ noBaseFee = k.feeMarketKeeper.GetParams(ctx).NoBaseFee
+ }
+
+ var debug bool
+ if _, ok := tracer.(types.NoOpTracer); !ok {
+ debug = true
+ }
+
+ return vm.Config{
+ Debug: debug,
+ Tracer: tracer,
+ NoBaseFee: noBaseFee,
+ ExtraEips: cfg.Params.EIPs(),
+ }
+}
diff --git a/x/evm/keeper/fees.go b/x/evm/keeper/fees.go
new file mode 100644
index 00000000..101a3e4c
--- /dev/null
+++ b/x/evm/keeper/fees.go
@@ -0,0 +1,115 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ errorsmod "cosmossdk.io/errors"
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+ authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// CheckSenderBalance validates that the tx cost value is positive and that the
+// sender has enough funds to pay for the fees and value of the transaction.
+func CheckSenderBalance(
+ balance sdkmath.Int,
+ txData types.TxData,
+) error {
+ cost := txData.Cost()
+
+ if cost.Sign() < 0 {
+ return errorsmod.Wrapf(
+ errortypes.ErrInvalidCoins,
+ "tx cost (%s) is negative and invalid", cost,
+ )
+ }
+
+ if balance.IsNegative() || balance.BigInt().Cmp(cost) < 0 {
+ return errorsmod.Wrapf(
+ errortypes.ErrInsufficientFunds,
+ "sender balance < tx cost (%s < %s)", balance, txData.Cost(),
+ )
+ }
+ return nil
+}
+
+// DeductTxCostsFromUserBalance deducts the fees from the user balance. Returns an
+// error if the specified sender address does not exist or the account balance is not sufficient.
+func (k *Keeper) DeductTxCostsFromUserBalance(
+ ctx sdk.Context,
+ fees sdk.Coins,
+ from common.Address,
+) error {
+ // fetch sender account
+ signerAcc, err := authante.GetSignerAcc(ctx, k.accountKeeper, from.Bytes())
+ if err != nil {
+ return errorsmod.Wrapf(err, "account not found for sender %s", from)
+ }
+
+ // deduct the full gas cost from the user balance
+ if err := authante.DeductFees(k.bankKeeper, ctx, signerAcc, fees); err != nil {
+ return errorsmod.Wrapf(err, "failed to deduct full gas cost %s from the user %s balance", fees, from)
+ }
+
+ return nil
+}
+
+// VerifyFee is used to return the fee for the given transaction data in sdk.Coins. It checks that the
+// gas limit is not reached, the gas limit is higher than the intrinsic gas and that the
+// base fee is higher than the gas fee cap.
+func VerifyFee(
+ txData types.TxData,
+ denom string,
+ baseFee *big.Int,
+ homestead, istanbul, isCheckTx bool,
+) (sdk.Coins, error) {
+ isContractCreation := txData.GetTo() == nil
+
+ gasLimit := txData.GetGas()
+
+ var accessList ethtypes.AccessList
+ if txData.GetAccessList() != nil {
+ accessList = txData.GetAccessList()
+ }
+
+ intrinsicGas, err := core.IntrinsicGas(txData.GetData(), accessList, isContractCreation, homestead, istanbul)
+ if err != nil {
+ return nil, errorsmod.Wrapf(
+ err,
+ "failed to retrieve intrinsic gas, contract creation = %t; homestead = %t, istanbul = %t",
+ isContractCreation, homestead, istanbul,
+ )
+ }
+
+ // intrinsic gas verification during CheckTx
+ if isCheckTx && gasLimit < intrinsicGas {
+ return nil, errorsmod.Wrapf(
+ errortypes.ErrOutOfGas,
+ "gas limit too low: %d (gas limit) < %d (intrinsic gas)", gasLimit, intrinsicGas,
+ )
+ }
+
+ if baseFee != nil && txData.GetGasFeeCap().Cmp(baseFee) < 0 {
+ return nil, errorsmod.Wrapf(errortypes.ErrInsufficientFee,
+ "the tx gasfeecap is lower than the tx baseFee: %s (gasfeecap), %s (basefee) ",
+ txData.GetGasFeeCap(),
+ baseFee)
+ }
+
+ feeAmt := txData.EffectiveFee(baseFee)
+ if feeAmt.Sign() == 0 {
+ // zero fee, no need to deduct
+ return sdk.Coins{}, nil
+ }
+
+ return sdk.Coins{{Denom: denom, Amount: sdkmath.NewIntFromBigInt(feeAmt)}}, nil
+}
diff --git a/x/evm/keeper/fees_test.go b/x/evm/keeper/fees_test.go
new file mode 100644
index 00000000..fffaf320
--- /dev/null
+++ b/x/evm/keeper/fees_test.go
@@ -0,0 +1,539 @@
+package keeper_test
+
+import (
+ "math/big"
+
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ ethparams "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/keeper"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *KeeperTestSuite) TestCheckSenderBalance() {
+ hundredInt := sdkmath.NewInt(100)
+ zeroInt := sdkmath.ZeroInt()
+ oneInt := sdkmath.OneInt()
+ fiveInt := sdkmath.NewInt(5)
+ fiftyInt := sdkmath.NewInt(50)
+ negInt := sdkmath.NewInt(-10)
+
+ testCases := []struct {
+ name string
+ to string
+ gasLimit uint64
+ gasPrice *sdkmath.Int
+ gasFeeCap *big.Int
+ gasTipCap *big.Int
+ cost *sdkmath.Int
+ from string
+ accessList *ethtypes.AccessList
+ expectPass bool
+ enableFeemarket bool
+ }{
+ {
+ name: "Enough balance",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ },
+ {
+ name: "Equal balance",
+ to: suite.address.String(),
+ gasLimit: 99,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ },
+ {
+ name: "negative cost",
+ to: suite.address.String(),
+ gasLimit: 1,
+ gasPrice: &oneInt,
+ cost: &negInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ },
+ {
+ name: "Higher gas limit, not enough balance",
+ to: suite.address.String(),
+ gasLimit: 100,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ },
+ {
+ name: "Higher gas price, enough balance",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasPrice: &fiveInt,
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ },
+ {
+ name: "Higher gas price, not enough balance",
+ to: suite.address.String(),
+ gasLimit: 20,
+ gasPrice: &fiveInt,
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ },
+ {
+ name: "Higher cost, enough balance",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasPrice: &fiveInt,
+ cost: &fiftyInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ },
+ {
+ name: "Higher cost, not enough balance",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasPrice: &fiveInt,
+ cost: &hundredInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ },
+ {
+ name: "Enough balance w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasFeeCap: big.NewInt(1),
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ enableFeemarket: true,
+ },
+ {
+ name: "Equal balance w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 99,
+ gasFeeCap: big.NewInt(1),
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ enableFeemarket: true,
+ },
+ {
+ name: "negative cost w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 1,
+ gasFeeCap: big.NewInt(1),
+ cost: &negInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ enableFeemarket: true,
+ },
+ {
+ name: "Higher gas limit, not enough balance w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 100,
+ gasFeeCap: big.NewInt(1),
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ enableFeemarket: true,
+ },
+ {
+ name: "Higher gas price, enough balance w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasFeeCap: big.NewInt(5),
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ enableFeemarket: true,
+ },
+ {
+ name: "Higher gas price, not enough balance w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 20,
+ gasFeeCap: big.NewInt(5),
+ cost: &oneInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ enableFeemarket: true,
+ },
+ {
+ name: "Higher cost, enough balance w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasFeeCap: big.NewInt(5),
+ cost: &fiftyInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: true,
+ enableFeemarket: true,
+ },
+ {
+ name: "Higher cost, not enough balance w/ enableFeemarket",
+ to: suite.address.String(),
+ gasLimit: 10,
+ gasFeeCap: big.NewInt(5),
+ cost: &hundredInt,
+ from: suite.address.String(),
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ enableFeemarket: true,
+ },
+ }
+
+ vmdb := suite.StateDB()
+ vmdb.AddBalance(suite.address, hundredInt.BigInt())
+ balance := vmdb.GetBalance(suite.address)
+ suite.Require().Equal(balance, hundredInt.BigInt())
+ err := vmdb.Commit()
+ suite.Require().NoError(err, "Unexpected error while committing to vmdb: %d", err)
+
+ for i, tc := range testCases {
+ suite.Run(tc.name, func() {
+ to := common.HexToAddress(tc.from)
+
+ var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
+ if tc.cost != nil {
+ amount = tc.cost.BigInt()
+ }
+
+ if tc.enableFeemarket {
+ gasFeeCap = tc.gasFeeCap
+ if tc.gasTipCap == nil {
+ gasTipCap = oneInt.BigInt()
+ } else {
+ gasTipCap = tc.gasTipCap
+ }
+ } else if tc.gasPrice != nil {
+ gasPrice = tc.gasPrice.BigInt()
+ }
+
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: zeroInt.BigInt(),
+ Nonce: 1,
+ To: &to,
+ Amount: amount,
+ GasLimit: tc.gasLimit,
+ GasPrice: gasPrice,
+ GasFeeCap: gasFeeCap,
+ GasTipCap: gasTipCap,
+ Accesses: tc.accessList,
+ }
+ tx := evmtypes.NewTx(ethTxParams)
+ tx.From = tc.from
+
+ txData, _ := evmtypes.UnpackTxData(tx.Data)
+
+ acct := suite.app.EvmKeeper.GetAccountOrEmpty(suite.ctx, suite.address)
+ err := keeper.CheckSenderBalance(
+ sdkmath.NewIntFromBigInt(acct.Balance),
+ txData,
+ )
+
+ if tc.expectPass {
+ suite.Require().NoError(err, "valid test %d failed", i)
+ } else {
+ suite.Require().Error(err, "invalid test %d passed", i)
+ }
+ })
+ }
+}
+
+// TestVerifyFeeAndDeductTxCostsFromUserBalance is a test method for both the VerifyFee
+// function and the DeductTxCostsFromUserBalance method.
+//
+// NOTE: This method combines testing for both functions, because these used to be
+// in one function and share a lot of the same setup.
+// In practice, the two tested functions will also be sequentially executed.
+func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() {
+ hundredInt := sdkmath.NewInt(100)
+ zeroInt := sdkmath.ZeroInt()
+ oneInt := sdkmath.NewInt(1)
+ fiveInt := sdkmath.NewInt(5)
+ fiftyInt := sdkmath.NewInt(50)
+
+ // should be enough to cover all test cases
+ initBalance := sdkmath.NewInt((ethparams.InitialBaseFee + 10) * 105)
+
+ testCases := []struct {
+ name string
+ gasLimit uint64
+ gasPrice *sdkmath.Int
+ gasFeeCap *big.Int
+ gasTipCap *big.Int
+ cost *sdkmath.Int
+ accessList *ethtypes.AccessList
+ expectPassVerify bool
+ expectPassDeduct bool
+ enableFeemarket bool
+ from string
+ malleate func()
+ }{
+ {
+ name: "Enough balance",
+ gasLimit: 10,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "Equal balance",
+ gasLimit: 100,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "Higher gas limit, not enough balance",
+ gasLimit: 105,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: false,
+ from: suite.address.String(),
+ },
+ {
+ name: "Higher gas price, enough balance",
+ gasLimit: 20,
+ gasPrice: &fiveInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "Higher gas price, not enough balance",
+ gasLimit: 20,
+ gasPrice: &fiftyInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: false,
+ from: suite.address.String(),
+ },
+ // This case is expected to be true because the fees can be deducted, but the tx
+ // execution is going to fail because there is no more balance to pay the cost
+ {
+ name: "Higher cost, enough balance",
+ gasLimit: 100,
+ gasPrice: &oneInt,
+ cost: &fiftyInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ from: suite.address.String(),
+ },
+ // testcases with enableFeemarket enabled.
+ {
+ name: "Invalid gasFeeCap w/ enableFeemarket",
+ gasLimit: 10,
+ gasFeeCap: big.NewInt(1),
+ gasTipCap: big.NewInt(1),
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: false,
+ expectPassDeduct: true,
+ enableFeemarket: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "empty tip fee is valid to deduct",
+ gasLimit: 10,
+ gasFeeCap: big.NewInt(ethparams.InitialBaseFee),
+ gasTipCap: big.NewInt(1),
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ enableFeemarket: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "effectiveTip equal to gasTipCap",
+ gasLimit: 100,
+ gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 2),
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ enableFeemarket: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "effectiveTip equal to (gasFeeCap - baseFee)",
+ gasLimit: 105,
+ gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 1),
+ gasTipCap: big.NewInt(2),
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ enableFeemarket: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "Invalid from address",
+ gasLimit: 10,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: true,
+ expectPassDeduct: false,
+ from: "abcdef",
+ },
+ {
+ name: "Enough balance - with access list",
+ gasLimit: 10,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{
+ ethtypes.AccessTuple{
+ Address: suite.address,
+ StorageKeys: []common.Hash{},
+ },
+ },
+ expectPassVerify: true,
+ expectPassDeduct: true,
+ from: suite.address.String(),
+ },
+ {
+ name: "gasLimit < intrinsicGas during IsCheckTx",
+ gasLimit: 1,
+ gasPrice: &oneInt,
+ cost: &oneInt,
+ accessList: ðtypes.AccessList{},
+ expectPassVerify: false,
+ expectPassDeduct: true,
+ from: suite.address.String(),
+ malleate: func() {
+ suite.ctx = suite.ctx.WithIsCheckTx(true)
+ },
+ },
+ }
+
+ for i, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.enableFeemarket = tc.enableFeemarket
+ suite.SetupTest()
+ vmdb := suite.StateDB()
+
+ if tc.malleate != nil {
+ tc.malleate()
+ }
+ var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
+ if tc.cost != nil {
+ amount = tc.cost.BigInt()
+ }
+
+ if suite.enableFeemarket {
+ if tc.gasFeeCap != nil {
+ gasFeeCap = tc.gasFeeCap
+ }
+ if tc.gasTipCap == nil {
+ gasTipCap = oneInt.BigInt()
+ } else {
+ gasTipCap = tc.gasTipCap
+ }
+ vmdb.AddBalance(suite.address, initBalance.BigInt())
+ balance := vmdb.GetBalance(suite.address)
+ suite.Require().Equal(balance, initBalance.BigInt())
+ } else {
+ if tc.gasPrice != nil {
+ gasPrice = tc.gasPrice.BigInt()
+ }
+
+ vmdb.AddBalance(suite.address, hundredInt.BigInt())
+ balance := vmdb.GetBalance(suite.address)
+ suite.Require().Equal(balance, hundredInt.BigInt())
+ }
+ err := vmdb.Commit()
+ suite.Require().NoError(err, "Unexpected error while committing to vmdb: %d", err)
+
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: zeroInt.BigInt(),
+ Nonce: 1,
+ To: &suite.address,
+ Amount: amount,
+ GasLimit: tc.gasLimit,
+ GasPrice: gasPrice,
+ GasFeeCap: gasFeeCap,
+ GasTipCap: gasTipCap,
+ Accesses: tc.accessList,
+ }
+ tx := evmtypes.NewTx(ethTxParams)
+ tx.From = tc.from
+
+ txData, _ := evmtypes.UnpackTxData(tx.Data)
+
+ evmParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ ethCfg := evmParams.GetChainConfig().EthereumConfig(nil)
+ baseFee := suite.app.EvmKeeper.GetBaseFee(suite.ctx, ethCfg)
+ priority := evmtypes.GetTxPriority(txData, baseFee)
+
+ fees, err := keeper.VerifyFee(txData, evmtypes.DefaultEVMDenom, baseFee, false, false, suite.ctx.IsCheckTx())
+ if tc.expectPassVerify {
+ suite.Require().NoError(err, "valid test %d failed - '%s'", i, tc.name)
+ if tc.enableFeemarket {
+ baseFee := suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx)
+ suite.Require().Equal(
+ fees,
+ sdk.NewCoins(
+ sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewIntFromBigInt(txData.EffectiveFee(baseFee))),
+ ),
+ "valid test %d failed, fee value is wrong - '%s'", i, tc.name,
+ )
+ suite.Require().Equal(int64(0), priority)
+ } else {
+ suite.Require().Equal(
+ fees,
+ sdk.NewCoins(
+ sdk.NewCoin(evmtypes.DefaultEVMDenom, tc.gasPrice.Mul(sdkmath.NewIntFromUint64(tc.gasLimit))),
+ ),
+ "valid test %d failed, fee value is wrong - '%s'", i, tc.name,
+ )
+ }
+ } else {
+ suite.Require().Error(err, "invalid test %d passed - '%s'", i, tc.name)
+ suite.Require().Nil(fees, "invalid test %d passed. fees value must be nil - '%s'", i, tc.name)
+ }
+
+ err = suite.app.EvmKeeper.DeductTxCostsFromUserBalance(suite.ctx, fees, common.HexToAddress(tx.From))
+ if tc.expectPassDeduct {
+ suite.Require().NoError(err, "valid test %d failed - '%s'", i, tc.name)
+ } else {
+ suite.Require().Error(err, "invalid test %d passed - '%s'", i, tc.name)
+ }
+ })
+ }
+ suite.enableFeemarket = false // reset flag
+}
diff --git a/x/evm/keeper/gas.go b/x/evm/keeper/gas.go
new file mode 100644
index 00000000..59cacb93
--- /dev/null
+++ b/x/evm/keeper/gas.go
@@ -0,0 +1,77 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/params"
+
+ errorsmod "cosmossdk.io/errors"
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// GetEthIntrinsicGas returns the intrinsic gas cost for the transaction
+func (k *Keeper) GetEthIntrinsicGas(ctx sdk.Context, msg core.Message, cfg *params.ChainConfig, isContractCreation bool) (uint64, error) {
+ height := big.NewInt(ctx.BlockHeight())
+ homestead := cfg.IsHomestead(height)
+ istanbul := cfg.IsIstanbul(height)
+
+ return core.IntrinsicGas(msg.Data(), msg.AccessList(), isContractCreation, homestead, istanbul)
+}
+
+// RefundGas transfers the leftover gas to the sender of the message, caped to half of the total gas
+// consumed in the transaction. Additionally, the function sets the total gas consumed to the value
+// returned by the EVM execution, thus ignoring the previous intrinsic gas consumed during in the
+// AnteHandler.
+func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas uint64, denom string) error {
+ // Return EVM tokens for remaining gas, exchanged at the original rate.
+ remaining := new(big.Int).Mul(new(big.Int).SetUint64(leftoverGas), msg.GasPrice())
+
+ switch remaining.Sign() {
+ case -1:
+ // negative refund errors
+ return errorsmod.Wrapf(types.ErrInvalidRefund, "refunded amount value cannot be negative %d", remaining.Int64())
+ case 1:
+ // positive amount refund
+ refundedCoins := sdk.Coins{sdk.NewCoin(denom, sdkmath.NewIntFromBigInt(remaining))}
+
+ // refund to sender from the fee collector module account, which is the escrow account in charge of collecting tx fees
+
+ err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, msg.From().Bytes(), refundedCoins)
+ if err != nil {
+ err = errorsmod.Wrapf(errortypes.ErrInsufficientFunds, "fee collector account failed to refund fees: %s", err.Error())
+ return errorsmod.Wrapf(err, "failed to refund %d leftover gas (%s)", leftoverGas, refundedCoins.String())
+ }
+ default:
+ // no refund, consume gas and update the tx gas meter
+ }
+
+ return nil
+}
+
+// ResetGasMeterAndConsumeGas reset first the gas meter consumed value to zero and set it back to the new value
+// 'gasUsed'
+func (k *Keeper) ResetGasMeterAndConsumeGas(ctx sdk.Context, gasUsed uint64) {
+ // reset the gas count
+ ctx.GasMeter().RefundGas(ctx.GasMeter().GasConsumed(), "reset the gas count")
+ ctx.GasMeter().ConsumeGas(gasUsed, "apply evm transaction")
+}
+
+// GasToRefund calculates the amount of gas the state machine should refund to the sender. It is
+// capped by the refund quotient value.
+// Note: do not pass 0 to refundQuotient
+func GasToRefund(availableRefund, gasConsumed, refundQuotient uint64) uint64 {
+ // Apply refund counter
+ refund := gasConsumed / refundQuotient
+ if refund > availableRefund {
+ return availableRefund
+ }
+ return refund
+}
diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go
new file mode 100644
index 00000000..f1dfd131
--- /dev/null
+++ b/x/evm/keeper/grpc_query.go
@@ -0,0 +1,702 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math/big"
+ "time"
+
+ "github.com/evmos/evmos/v19/x/evm/core/logger"
+ "github.com/evmos/evmos/v19/x/evm/core/tracers"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ ethparams "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ evmostypes "github.com/evmos/evmos/v19/types"
+ evmante "github.com/evmos/evmos/v19/x/evm/ante"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+var _ types.QueryServer = Keeper{}
+
+const (
+ defaultTraceTimeout = 5 * time.Second
+)
+
+// Account implements the Query/Account gRPC method
+func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*types.QueryAccountResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if err := evmostypes.ValidateAddress(req.Address); err != nil {
+ return nil, status.Error(
+ codes.InvalidArgument, err.Error(),
+ )
+ }
+
+ addr := common.HexToAddress(req.Address)
+
+ ctx := sdk.UnwrapSDKContext(c)
+ acct := k.GetAccountOrEmpty(ctx, addr)
+
+ return &types.QueryAccountResponse{
+ Balance: acct.Balance.String(),
+ CodeHash: common.BytesToHash(acct.CodeHash).Hex(),
+ Nonce: acct.Nonce,
+ }, nil
+}
+
+func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRequest) (*types.QueryCosmosAccountResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if err := evmostypes.ValidateAddress(req.Address); err != nil {
+ return nil, status.Error(
+ codes.InvalidArgument, err.Error(),
+ )
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+
+ ethAddr := common.HexToAddress(req.Address)
+ cosmosAddr := sdk.AccAddress(ethAddr.Bytes())
+
+ account := k.accountKeeper.GetAccount(ctx, cosmosAddr)
+ res := types.QueryCosmosAccountResponse{
+ CosmosAddress: cosmosAddr.String(),
+ }
+
+ if account != nil {
+ res.Sequence = account.GetSequence()
+ res.AccountNumber = account.GetAccountNumber()
+ }
+
+ return &res, nil
+}
+
+// ValidatorAccount implements the Query/Balance gRPC method
+func (k Keeper) ValidatorAccount(c context.Context, req *types.QueryValidatorAccountRequest) (*types.QueryValidatorAccountResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ consAddr, err := sdk.ConsAddressFromBech32(req.ConsAddress)
+ if err != nil {
+ return nil, status.Error(
+ codes.InvalidArgument, err.Error(),
+ )
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+
+ validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
+ if !found {
+ return nil, fmt.Errorf("validator not found for %s", consAddr.String())
+ }
+
+ accAddr := sdk.AccAddress(validator.GetOperator())
+
+ res := types.QueryValidatorAccountResponse{
+ AccountAddress: accAddr.String(),
+ }
+
+ account := k.accountKeeper.GetAccount(ctx, accAddr)
+ if account != nil {
+ res.Sequence = account.GetSequence()
+ res.AccountNumber = account.GetAccountNumber()
+ }
+
+ return &res, nil
+}
+
+// Balance implements the Query/Balance gRPC method
+func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if err := evmostypes.ValidateAddress(req.Address); err != nil {
+ return nil, status.Error(
+ codes.InvalidArgument,
+ types.ErrZeroAddress.Error(),
+ )
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+
+ balanceInt := k.GetBalance(ctx, common.HexToAddress(req.Address))
+
+ return &types.QueryBalanceResponse{
+ Balance: balanceInt.String(),
+ }, nil
+}
+
+// Storage implements the Query/Storage gRPC method
+func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*types.QueryStorageResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if err := evmostypes.ValidateAddress(req.Address); err != nil {
+ return nil, status.Error(
+ codes.InvalidArgument,
+ types.ErrZeroAddress.Error(),
+ )
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+
+ address := common.HexToAddress(req.Address)
+ key := common.HexToHash(req.Key)
+
+ state := k.GetState(ctx, address, key)
+ stateHex := state.Hex()
+
+ return &types.QueryStorageResponse{
+ Value: stateHex,
+ }, nil
+}
+
+// Code implements the Query/Code gRPC method
+func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.QueryCodeResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if err := evmostypes.ValidateAddress(req.Address); err != nil {
+ return nil, status.Error(
+ codes.InvalidArgument,
+ types.ErrZeroAddress.Error(),
+ )
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+
+ address := common.HexToAddress(req.Address)
+ acct := k.GetAccountWithoutBalance(ctx, address)
+
+ var code []byte
+ if acct != nil && acct.IsContract() {
+ code = k.GetCode(ctx, common.BytesToHash(acct.CodeHash))
+ }
+
+ return &types.QueryCodeResponse{
+ Code: code,
+ }, nil
+}
+
+// Params implements the Query/Params gRPC method
+func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
+ ctx := sdk.UnwrapSDKContext(c)
+ params := k.GetParams(ctx)
+
+ return &types.QueryParamsResponse{
+ Params: params,
+ }, nil
+}
+
+// EthCall implements eth_call rpc api.
+func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.MsgEthereumTxResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+
+ var args types.TransactionArgs
+ err := json.Unmarshal(req.Args, &args)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+ chainID, err := getChainID(ctx, req.ChainId)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+ cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
+ if err != nil {
+ return nil, status.Error(codes.Internal, err.Error())
+ }
+
+ // ApplyMessageWithConfig expect correct nonce set in msg
+ nonce := k.GetNonce(ctx, args.GetFrom())
+ args.Nonce = (*hexutil.Uint64)(&nonce)
+
+ msg, err := args.ToMessage(req.GasCap, cfg.BaseFee)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+
+ txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))
+
+ // pass false to not commit StateDB
+ res, err := k.ApplyMessageWithConfig(ctx, msg, nil, false, cfg, txConfig)
+ if err != nil {
+ return nil, status.Error(codes.Internal, err.Error())
+ }
+
+ return res, nil
+}
+
+// EstimateGas implements eth_estimateGas rpc api.
+func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*types.EstimateGasResponse, error) {
+ return k.EstimateGasInternal(c, req, types.RPC)
+}
+
+// EstimateGasInternal returns the gas estimation for the corresponding request.
+// This function is called from the RPC client (eth_estimateGas) and internally
+// by the CallEVMWithData function in the x/erc20 module keeper.
+// When called from the RPC client, we need to reset the gas meter before
+// simulating the transaction to have
+// an accurate gas estimation for EVM extensions transactions.
+func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest, fromType types.CallType) (*types.EstimateGasResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+ chainID, err := getChainID(ctx, req.ChainId)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+
+ if req.GasCap < ethparams.TxGas {
+ return nil, status.Errorf(codes.InvalidArgument, "gas cap cannot be lower than %d", ethparams.TxGas)
+ }
+
+ var args types.TransactionArgs
+ err = json.Unmarshal(req.Args, &args)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+
+ // Binary search the gas requirement, as it may be higher than the amount used
+ var (
+ lo = ethparams.TxGas - 1
+ hi uint64
+ gasCap uint64
+ )
+
+ // Determine the highest gas limit can be used during the estimation.
+ if args.Gas != nil && uint64(*args.Gas) >= ethparams.TxGas {
+ hi = uint64(*args.Gas)
+ } else {
+ // Query block gas limit
+ params := ctx.ConsensusParams()
+ if params != nil && params.Block != nil && params.Block.MaxGas > 0 {
+ hi = uint64(params.Block.MaxGas)
+ } else {
+ hi = req.GasCap
+ }
+ }
+
+ // TODO: Recap the highest gas limit with account's available balance.
+
+ // Recap the highest gas allowance with specified gascap.
+ if req.GasCap != 0 && hi > req.GasCap {
+ hi = req.GasCap
+ }
+
+ gasCap = hi
+ cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
+ if err != nil {
+ return nil, status.Error(codes.Internal, "failed to load evm config")
+ }
+
+ // ApplyMessageWithConfig expect correct nonce set in msg
+ nonce := k.GetNonce(ctx, args.GetFrom())
+ args.Nonce = (*hexutil.Uint64)(&nonce)
+
+ txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))
+
+ // convert the tx args to an ethereum message
+ msg, err := args.ToMessage(req.GasCap, cfg.BaseFee)
+ if err != nil {
+ return nil, status.Error(codes.Internal, err.Error())
+ }
+
+ // NOTE: the errors from the executable below should be consistent with go-ethereum,
+ // so we don't wrap them with the gRPC status code
+
+ // Create a helper to check if a gas allowance results in an executable transaction
+ executable := func(gas uint64) (vmError bool, rsp *types.MsgEthereumTxResponse, err error) {
+ // update the message with the new gas value
+ msg = ethtypes.NewMessage(
+ msg.From(),
+ msg.To(),
+ msg.Nonce(),
+ msg.Value(),
+ gas,
+ msg.GasPrice(),
+ msg.GasFeeCap(),
+ msg.GasTipCap(),
+ msg.Data(),
+ msg.AccessList(),
+ msg.IsFake(),
+ )
+
+ tmpCtx := ctx
+ if fromType == types.RPC {
+ tmpCtx, _ = ctx.CacheContext()
+
+ acct := k.GetAccount(tmpCtx, msg.From())
+
+ from := msg.From()
+ if acct == nil {
+ acc := k.accountKeeper.NewAccountWithAddress(tmpCtx, from[:])
+ k.accountKeeper.SetAccount(tmpCtx, acc)
+ acct = statedb.NewEmptyAccount()
+ }
+ // When submitting a transaction, the `EthIncrementSenderSequence` ante handler increases the account nonce
+ acct.Nonce = nonce + 1
+ err = k.SetAccount(tmpCtx, from, *acct)
+ if err != nil {
+ return true, nil, err
+ }
+ // resetting the gasMeter after increasing the sequence to have an accurate gas estimation on EVM extensions transactions
+ gasMeter := evmostypes.NewInfiniteGasMeterWithLimit(msg.Gas())
+ tmpCtx = evmante.BuildEvmExecutionCtx(tmpCtx).WithGasMeter(gasMeter)
+ }
+ // pass false to not commit StateDB
+ rsp, err = k.ApplyMessageWithConfig(tmpCtx, msg, nil, false, cfg, txConfig)
+ if err != nil {
+ if errors.Is(err, core.ErrIntrinsicGas) {
+ return true, nil, nil // Special case, raise gas limit
+ }
+ return true, nil, err // Bail out
+ }
+ return len(rsp.VmError) > 0, rsp, nil
+ }
+
+ // Execute the binary search and hone in on an executable gas limit
+ hi, err = types.BinSearch(lo, hi, executable)
+ if err != nil {
+ return nil, err
+ }
+
+ // Reject the transaction as invalid if it still fails at the highest allowance
+ if hi == gasCap {
+ failed, result, err := executable(hi)
+ if err != nil {
+ return nil, err
+ }
+
+ if failed {
+ if result != nil && result.VmError != vm.ErrOutOfGas.Error() {
+ if result.VmError == vm.ErrExecutionReverted.Error() {
+ return nil, types.NewExecErrorWithReason(result.Ret)
+ }
+ return nil, errors.New(result.VmError)
+ }
+ // Otherwise, the specified gas cap is too low
+ return nil, fmt.Errorf("gas required exceeds allowance (%d)", gasCap)
+ }
+ }
+ return &types.EstimateGasResponse{Gas: hi}, nil
+}
+
+// TraceTx configures a new tracer according to the provided configuration, and
+// executes the given message in the provided environment. The return value will
+// be tracer dependent.
+func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*types.QueryTraceTxResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if req.TraceConfig != nil && req.TraceConfig.Limit < 0 {
+ return nil, status.Errorf(codes.InvalidArgument, "output limit cannot be negative, got %d", req.TraceConfig.Limit)
+ }
+
+ // get the context of block beginning
+ contextHeight := req.BlockNumber
+ if contextHeight < 1 {
+ // 0 is a special value in `ContextWithHeight`
+ contextHeight = 1
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+ ctx = ctx.WithBlockHeight(contextHeight)
+ ctx = ctx.WithBlockTime(req.BlockTime)
+ ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash))
+
+ // to get the base fee we only need the block max gas in the consensus params
+ ctx = ctx.WithConsensusParams(&tmproto.ConsensusParams{
+ Block: &tmproto.BlockParams{MaxGas: req.BlockMaxGas},
+ })
+
+ chainID, err := getChainID(ctx, req.ChainId)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+ cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "failed to load evm config: %s", err.Error())
+ }
+
+ // compute and use base fee of the height that is being traced
+ baseFee := k.feeMarketKeeper.CalculateBaseFee(ctx)
+ if baseFee != nil {
+ cfg.BaseFee = baseFee
+ }
+
+ signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
+
+ txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))
+
+ // gas used at this point corresponds to GetProposerAddress & CalculateBaseFee
+ // need to reset gas meter per transaction to be consistent with tx execution
+ // and avoid stacking the gas used of every predecessor in the same gas meter
+
+ for i, tx := range req.Predecessors {
+ ethTx := tx.AsTransaction()
+ msg, err := ethTx.AsMessage(signer, cfg.BaseFee)
+ if err != nil {
+ continue
+ }
+ txConfig.TxHash = ethTx.Hash()
+ txConfig.TxIndex = uint(i)
+ // reset gas meter for each transaction
+ ctx = evmante.BuildEvmExecutionCtx(ctx).
+ WithGasMeter(evmostypes.NewInfiniteGasMeterWithLimit(msg.Gas()))
+ rsp, err := k.ApplyMessageWithConfig(ctx, msg, types.NewNoOpTracer(), true, cfg, txConfig)
+ if err != nil {
+ continue
+ }
+ txConfig.LogIndex += uint(len(rsp.Logs))
+ }
+
+ tx := req.Msg.AsTransaction()
+ txConfig.TxHash = tx.Hash()
+ if len(req.Predecessors) > 0 {
+ txConfig.TxIndex++
+ }
+
+ var tracerConfig json.RawMessage
+ if req.TraceConfig != nil && req.TraceConfig.TracerJsonConfig != "" {
+ // ignore error. default to no traceConfig
+ _ = json.Unmarshal([]byte(req.TraceConfig.TracerJsonConfig), &tracerConfig)
+ }
+
+ result, _, err := k.traceTx(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false, tracerConfig)
+ if err != nil {
+ // error will be returned with detail status from traceTx
+ return nil, err
+ }
+
+ resultData, err := json.Marshal(result)
+ if err != nil {
+ return nil, status.Error(codes.Internal, err.Error())
+ }
+
+ return &types.QueryTraceTxResponse{
+ Data: resultData,
+ }, nil
+}
+
+// TraceBlock configures a new tracer according to the provided configuration, and
+// executes the given message in the provided environment for all the transactions in the queried block.
+// The return value will be tracer dependent.
+func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) (*types.QueryTraceBlockResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if req.TraceConfig != nil && req.TraceConfig.Limit < 0 {
+ return nil, status.Errorf(codes.InvalidArgument, "output limit cannot be negative, got %d", req.TraceConfig.Limit)
+ }
+
+ // get the context of block beginning
+ contextHeight := req.BlockNumber
+ if contextHeight < 1 {
+ // 0 is a special value in `ContextWithHeight`
+ contextHeight = 1
+ }
+
+ ctx := sdk.UnwrapSDKContext(c)
+ ctx = ctx.WithBlockHeight(contextHeight)
+ ctx = ctx.WithBlockTime(req.BlockTime)
+ ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash))
+
+ // to get the base fee we only need the block max gas in the consensus params
+ ctx = ctx.WithConsensusParams(&tmproto.ConsensusParams{
+ Block: &tmproto.BlockParams{MaxGas: req.BlockMaxGas},
+ })
+
+ chainID, err := getChainID(ctx, req.ChainId)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, err.Error())
+ }
+
+ cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
+ if err != nil {
+ return nil, status.Error(codes.Internal, "failed to load evm config")
+ }
+
+ // compute and use base fee of height that is being traced
+ baseFee := k.feeMarketKeeper.CalculateBaseFee(ctx)
+ if baseFee != nil {
+ cfg.BaseFee = baseFee
+ }
+
+ signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
+ txsLength := len(req.Txs)
+ results := make([]*types.TxTraceResult, 0, txsLength)
+
+ txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))
+
+ for i, tx := range req.Txs {
+ result := types.TxTraceResult{}
+ 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)
+ if err != nil {
+ result.Error = err.Error()
+ } else {
+ txConfig.LogIndex = logIndex
+ result.Result = traceResult
+ }
+ results = append(results, &result)
+ }
+
+ resultData, err := json.Marshal(results)
+ if err != nil {
+ return nil, status.Error(codes.Internal, err.Error())
+ }
+
+ return &types.QueryTraceBlockResponse{
+ Data: resultData,
+ }, nil
+}
+
+// traceTx do trace on one transaction, it returns a tuple: (traceResult, nextLogIndex, error).
+func (k *Keeper) traceTx(
+ ctx sdk.Context,
+ cfg *statedb.EVMConfig,
+ txConfig statedb.TxConfig,
+ signer ethtypes.Signer,
+ tx *ethtypes.Transaction,
+ traceConfig *types.TraceConfig,
+ commitMessage bool,
+ tracerJSONConfig json.RawMessage,
+) (*interface{}, uint, error) {
+ // Assemble the structured logger or the JavaScript tracer
+ var (
+ tracer tracers.Tracer
+ overrides *ethparams.ChainConfig
+ err error
+ timeout = defaultTraceTimeout
+ )
+ msg, err := tx.AsMessage(signer, cfg.BaseFee)
+ if err != nil {
+ return nil, 0, status.Error(codes.Internal, err.Error())
+ }
+
+ if traceConfig == nil {
+ traceConfig = &types.TraceConfig{}
+ }
+
+ if traceConfig.Overrides != nil {
+ overrides = traceConfig.Overrides.EthereumConfig(cfg.ChainConfig.ChainID)
+ }
+
+ logConfig := logger.Config{
+ EnableMemory: traceConfig.EnableMemory,
+ DisableStorage: traceConfig.DisableStorage,
+ DisableStack: traceConfig.DisableStack,
+ EnableReturnData: traceConfig.EnableReturnData,
+ Debug: traceConfig.Debug,
+ Limit: int(traceConfig.Limit),
+ Overrides: overrides,
+ }
+
+ tracer = logger.NewStructLogger(&logConfig)
+
+ tCtx := &tracers.Context{
+ BlockHash: txConfig.BlockHash,
+ TxIndex: int(txConfig.TxIndex),
+ TxHash: txConfig.TxHash,
+ }
+
+ if traceConfig.Tracer != "" {
+ if tracer, err = tracers.New(traceConfig.Tracer, tCtx, tracerJSONConfig); err != nil {
+ return nil, 0, status.Error(codes.Internal, err.Error())
+ }
+ }
+
+ // Define a meaningful timeout of a single transaction trace
+ if traceConfig.Timeout != "" {
+ if timeout, err = time.ParseDuration(traceConfig.Timeout); err != nil {
+ return nil, 0, status.Errorf(codes.InvalidArgument, "timeout value: %s", err.Error())
+ }
+ }
+
+ // Handle timeouts and RPC cancellations
+ deadlineCtx, cancel := context.WithTimeout(ctx.Context(), timeout)
+ defer cancel()
+
+ go func() {
+ <-deadlineCtx.Done()
+ if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
+ tracer.Stop(errors.New("execution timeout"))
+ }
+ }()
+
+ // Build EVM execution context
+ ctx = evmante.BuildEvmExecutionCtx(ctx).
+ WithGasMeter(evmostypes.NewInfiniteGasMeterWithLimit(msg.Gas()))
+ res, err := k.ApplyMessageWithConfig(ctx, msg, tracer, commitMessage, cfg, txConfig)
+ if err != nil {
+ return nil, 0, status.Error(codes.Internal, err.Error())
+ }
+
+ var result interface{}
+ result, err = tracer.GetResult()
+ if err != nil {
+ return nil, 0, status.Error(codes.Internal, err.Error())
+ }
+
+ return &result, txConfig.LogIndex + uint(len(res.Logs)), nil
+}
+
+// BaseFee implements the Query/BaseFee gRPC method
+func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types.QueryBaseFeeResponse, error) {
+ ctx := sdk.UnwrapSDKContext(c)
+
+ params := k.GetParams(ctx)
+ ethCfg := params.ChainConfig.EthereumConfig(k.eip155ChainID)
+ baseFee := k.GetBaseFee(ctx, ethCfg)
+
+ res := &types.QueryBaseFeeResponse{}
+ if baseFee != nil {
+ aux := sdkmath.NewIntFromBigInt(baseFee)
+ res.BaseFee = &aux
+ }
+
+ return res, nil
+}
+
+// getChainID parse chainID from current context if not provided
+func getChainID(ctx sdk.Context, chainID int64) (*big.Int, error) {
+ if chainID == 0 {
+ return evmostypes.ParseChainID(ctx.ChainID())
+ }
+ return big.NewInt(chainID), nil
+}
diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go
new file mode 100644
index 00000000..bd4f6d4c
--- /dev/null
+++ b/x/evm/keeper/grpc_query_test.go
@@ -0,0 +1,1497 @@
+package keeper_test
+
+import (
+ "encoding/json"
+ "fmt"
+ "math/big"
+
+ "github.com/evmos/evmos/v19/x/evm/keeper/testdata"
+
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto"
+ ethparams "github.com/ethereum/go-ethereum/params"
+ ethlogger "github.com/evmos/evmos/v19/x/evm/core/logger"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ "github.com/evmos/evmos/v19/server/config"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// Not valid Ethereum address
+const invalidAddress = "0x0000"
+
+// expGasConsumed is the gas consumed in traceTx setup (GetProposerAddr + CalculateBaseFee)
+const expGasConsumed = 7475
+
+// expGasConsumedWithFeeMkt is the gas consumed in traceTx setup (GetProposerAddr + CalculateBaseFee) with enabled feemarket
+const expGasConsumedWithFeeMkt = 7469
+
+func (suite *KeeperTestSuite) TestQueryAccount() {
+ var (
+ req *types.QueryAccountRequest
+ expAccount *types.QueryAccountResponse
+ )
+
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "invalid address",
+ func() {
+ expAccount = &types.QueryAccountResponse{
+ Balance: "0",
+ CodeHash: common.BytesToHash(crypto.Keccak256(nil)).Hex(),
+ Nonce: 0,
+ }
+ req = &types.QueryAccountRequest{
+ Address: invalidAddress,
+ }
+ },
+ false,
+ },
+ {
+ "success",
+ func() {
+ amt := sdk.Coins{sdk.NewInt64Coin(types.DefaultEVMDenom, 100)}
+ err := suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, amt)
+ suite.Require().NoError(err)
+ err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, suite.address.Bytes(), amt)
+ suite.Require().NoError(err)
+
+ expAccount = &types.QueryAccountResponse{
+ Balance: "100",
+ CodeHash: common.BytesToHash(crypto.Keccak256(nil)).Hex(),
+ Nonce: 0,
+ }
+ req = &types.QueryAccountRequest{
+ Address: suite.address.String(),
+ }
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ tc.malleate()
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ res, err := suite.queryClient.Account(ctx, req)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().NotNil(res)
+
+ suite.Require().Equal(expAccount, res)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryCosmosAccount() {
+ var (
+ req *types.QueryCosmosAccountRequest
+ expAccount *types.QueryCosmosAccountResponse
+ )
+
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "invalid address",
+ func() {
+ expAccount = &types.QueryCosmosAccountResponse{
+ CosmosAddress: sdk.AccAddress(common.Address{}.Bytes()).String(),
+ }
+ req = &types.QueryCosmosAccountRequest{
+ Address: invalidAddress,
+ }
+ },
+ false,
+ },
+ {
+ "success",
+ func() {
+ expAccount = &types.QueryCosmosAccountResponse{
+ CosmosAddress: sdk.AccAddress(suite.address.Bytes()).String(),
+ Sequence: 0,
+ AccountNumber: 0,
+ }
+ req = &types.QueryCosmosAccountRequest{
+ Address: suite.address.String(),
+ }
+ },
+ true,
+ },
+ {
+ "success with seq and account number",
+ func() {
+ acc := suite.app.AccountKeeper.GetAccount(suite.ctx, suite.address.Bytes())
+ suite.Require().NoError(acc.SetSequence(10))
+ suite.Require().NoError(acc.SetAccountNumber(1))
+ suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
+
+ expAccount = &types.QueryCosmosAccountResponse{
+ CosmosAddress: sdk.AccAddress(suite.address.Bytes()).String(),
+ Sequence: 10,
+ AccountNumber: 1,
+ }
+ req = &types.QueryCosmosAccountRequest{
+ Address: suite.address.String(),
+ }
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ tc.malleate()
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ res, err := suite.queryClient.CosmosAccount(ctx, req)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().NotNil(res)
+
+ suite.Require().Equal(expAccount, res)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryBalance() {
+ var (
+ req *types.QueryBalanceRequest
+ expBalance string
+ )
+
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "invalid address",
+ func() {
+ expBalance = "0"
+ req = &types.QueryBalanceRequest{
+ Address: invalidAddress,
+ }
+ },
+ false,
+ },
+ {
+ "success",
+ func() {
+ amt := sdk.Coins{sdk.NewInt64Coin(types.DefaultEVMDenom, 100)}
+ err := suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, amt)
+ suite.Require().NoError(err)
+ err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, suite.address.Bytes(), amt)
+ suite.Require().NoError(err)
+
+ expBalance = "100"
+ req = &types.QueryBalanceRequest{
+ Address: suite.address.String(),
+ }
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ tc.malleate()
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ res, err := suite.queryClient.Balance(ctx, req)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().NotNil(res)
+
+ suite.Require().Equal(expBalance, res.Balance)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryStorage() {
+ var (
+ req *types.QueryStorageRequest
+ expValue string
+ )
+
+ testCases := []struct {
+ msg string
+ malleate func(vm.StateDB)
+ expPass bool
+ }{
+ {
+ "invalid address",
+ func(vm.StateDB) {
+ req = &types.QueryStorageRequest{
+ Address: invalidAddress,
+ }
+ },
+ false,
+ },
+ {
+ "success",
+ func(vmdb vm.StateDB) {
+ key := common.BytesToHash([]byte("key"))
+ value := common.BytesToHash([]byte("value"))
+ expValue = value.String()
+ vmdb.SetState(suite.address, key, value)
+ req = &types.QueryStorageRequest{
+ Address: suite.address.String(),
+ Key: key.String(),
+ }
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+ suite.Require().NoError(vmdb.Commit())
+
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ res, err := suite.queryClient.Storage(ctx, req)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().NotNil(res)
+
+ suite.Require().Equal(expValue, res.Value)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryCode() {
+ var (
+ req *types.QueryCodeRequest
+ expCode []byte
+ )
+
+ testCases := []struct {
+ msg string
+ malleate func(vm.StateDB)
+ expPass bool
+ }{
+ {
+ "invalid address",
+ func(vm.StateDB) {
+ req = &types.QueryCodeRequest{
+ Address: invalidAddress,
+ }
+ exp := &types.QueryCodeResponse{}
+ expCode = exp.Code
+ },
+ false,
+ },
+ {
+ "success",
+ func(vmdb vm.StateDB) {
+ expCode = []byte("code")
+ vmdb.SetCode(suite.address, expCode)
+
+ req = &types.QueryCodeRequest{
+ Address: suite.address.String(),
+ }
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+ suite.Require().NoError(vmdb.Commit())
+
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ res, err := suite.queryClient.Code(ctx, req)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().NotNil(res)
+
+ suite.Require().Equal(expCode, res.Code)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryTxLogs() {
+ var expLogs []*types.Log
+ txHash := common.BytesToHash([]byte("tx_hash"))
+ txIndex := uint(1)
+ logIndex := uint(1)
+
+ testCases := []struct {
+ msg string
+ malleate func(vm.StateDB)
+ }{
+ {
+ "empty logs",
+ func(vm.StateDB) {
+ expLogs = nil
+ },
+ },
+ {
+ "success",
+ func(vmdb vm.StateDB) {
+ expLogs = []*types.Log{
+ {
+ Address: suite.address.String(),
+ Topics: []string{common.BytesToHash([]byte("topic")).String()},
+ Data: []byte("data"),
+ BlockNumber: 1,
+ TxHash: txHash.String(),
+ TxIndex: uint64(txIndex),
+ BlockHash: common.BytesToHash(suite.ctx.HeaderHash()).Hex(),
+ Index: uint64(logIndex),
+ Removed: false,
+ },
+ }
+
+ for _, log := range types.LogsToEthereum(expLogs) {
+ vmdb.AddLog(log)
+ }
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ vmdb := statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes()), txHash, txIndex, logIndex))
+ tc.malleate(vmdb)
+ suite.Require().NoError(vmdb.Commit())
+
+ logs := vmdb.Logs()
+ suite.Require().Equal(expLogs, types.NewLogsFromEth(logs))
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryParams() {
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ expParams := types.DefaultParams()
+
+ res, err := suite.queryClient.Params(ctx, &types.QueryParamsRequest{})
+ suite.Require().NoError(err)
+ suite.Require().Equal(expParams, res.Params)
+}
+
+func (suite *KeeperTestSuite) TestQueryValidatorAccount() {
+ var (
+ req *types.QueryValidatorAccountRequest
+ expAccount *types.QueryValidatorAccountResponse
+ )
+
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "invalid address",
+ func() {
+ expAccount = &types.QueryValidatorAccountResponse{
+ AccountAddress: sdk.AccAddress(common.Address{}.Bytes()).String(),
+ }
+ req = &types.QueryValidatorAccountRequest{
+ ConsAddress: "",
+ }
+ },
+ false,
+ },
+ {
+ "success",
+ func() {
+ expAccount = &types.QueryValidatorAccountResponse{
+ AccountAddress: sdk.AccAddress(suite.address.Bytes()).String(),
+ Sequence: 0,
+ AccountNumber: 0,
+ }
+ req = &types.QueryValidatorAccountRequest{
+ ConsAddress: suite.consAddress.String(),
+ }
+ },
+ true,
+ },
+ {
+ "success with seq and account number",
+ func() {
+ acc := suite.app.AccountKeeper.GetAccount(suite.ctx, suite.address.Bytes())
+ suite.Require().NoError(acc.SetSequence(10))
+ suite.Require().NoError(acc.SetAccountNumber(1))
+ suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
+
+ expAccount = &types.QueryValidatorAccountResponse{
+ AccountAddress: sdk.AccAddress(suite.address.Bytes()).String(),
+ Sequence: 10,
+ AccountNumber: 1,
+ }
+ req = &types.QueryValidatorAccountRequest{
+ ConsAddress: suite.consAddress.String(),
+ }
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ tc.malleate()
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ res, err := suite.queryClient.ValidatorAccount(ctx, req)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().NotNil(res)
+
+ suite.Require().Equal(expAccount, res)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestEstimateGas() {
+ gasHelper := hexutil.Uint64(20000)
+ higherGas := hexutil.Uint64(25000)
+ hexBigInt := hexutil.Big(*big.NewInt(1))
+
+ erc20Contract, err := testdata.LoadERC20Contract()
+ suite.Require().NoError(err, "failed to load erc20 contract")
+
+ var (
+ args interface{}
+ gasCap uint64
+ )
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ expGas uint64
+ enableFeemarket bool
+ }{
+ // should success, because transfer value is zero
+ {
+ "default args - special case for ErrIntrinsicGas on contract creation, raise gas limit",
+ func() {
+ args = types.TransactionArgs{}
+ },
+ true,
+ ethparams.TxGasContractCreation,
+ false,
+ },
+ // should success, because transfer value is zero
+ {
+ "default args with 'to' address",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}}
+ },
+ true,
+ ethparams.TxGas,
+ false,
+ },
+ // should fail, because the default From address(zero address) don't have fund
+ {
+ "not enough balance",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))}
+ },
+ false,
+ 0,
+ false,
+ },
+ // should success, enough balance now
+ {
+ "enough balance",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))}
+ }, false, 0, false,
+ },
+ // should success, because gas limit lower than 21000 is ignored
+ {
+ "gas exceed allowance",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper}
+ },
+ true,
+ ethparams.TxGas,
+ false,
+ },
+ // should fail, invalid gas cap
+ {
+ "gas exceed global allowance",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}}
+ gasCap = 20000
+ },
+ false,
+ 0,
+ false,
+ },
+ // estimate gas of an erc20 contract deployment, the exact gas number is checked with geth
+ {
+ "contract deployment",
+ func() {
+ ctorArgs, err := erc20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Require().NoError(err)
+
+ data := erc20Contract.Bin
+ data = append(data, ctorArgs...)
+ args = types.TransactionArgs{
+ From: &suite.address,
+ Data: (*hexutil.Bytes)(&data),
+ }
+ },
+ true,
+ 1186778,
+ false,
+ },
+ // estimate gas of an erc20 transfer, the exact gas number is checked with geth
+ {
+ "erc20 transfer",
+ func() {
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Commit()
+ transferData, err := erc20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
+ suite.Require().NoError(err)
+ args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)}
+ },
+ true,
+ 51880,
+ false,
+ },
+ // repeated tests with enableFeemarket
+ {
+ "default args w/ enableFeemarket",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}}
+ },
+ true,
+ ethparams.TxGas,
+ true,
+ },
+ {
+ "not enough balance w/ enableFeemarket",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))}
+ },
+ false,
+ 0,
+ true,
+ },
+ {
+ "enough balance w/ enableFeemarket",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))}
+ },
+ false,
+ 0,
+ true,
+ },
+ {
+ "gas exceed allowance w/ enableFeemarket",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper}
+ },
+ true,
+ ethparams.TxGas,
+ true,
+ },
+ {
+ "gas exceed global allowance w/ enableFeemarket",
+ func() {
+ args = types.TransactionArgs{To: &common.Address{}}
+ gasCap = 20000
+ },
+ false,
+ 0,
+ true,
+ },
+ {
+ "contract deployment w/ enableFeemarket",
+ func() {
+ ctorArgs, err := erc20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Require().NoError(err)
+ data := erc20Contract.Bin
+ data = append(data, ctorArgs...)
+ args = types.TransactionArgs{
+ From: &suite.address,
+ Data: (*hexutil.Bytes)(&data),
+ }
+ },
+ true,
+ 1186778,
+ true,
+ },
+ {
+ "erc20 transfer w/ enableFeemarket",
+ func() {
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Commit()
+ transferData, err := erc20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
+ suite.Require().NoError(err)
+ args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)}
+ },
+ true,
+ 51880,
+ true,
+ },
+ {
+ "contract creation but 'create' param disabled",
+ func() {
+ ctorArgs, err := erc20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Require().NoError(err)
+ data := erc20Contract.Bin
+ data = append(data, ctorArgs...)
+ args = types.TransactionArgs{
+ From: &suite.address,
+ Data: (*hexutil.Bytes)(&data),
+ }
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ params.AccessControl = types.AccessControl{
+ Create: types.AccessControlType{
+ AccessType: types.AccessTypeRestricted,
+ },
+ }
+ err = suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ },
+ false,
+ 0,
+ false,
+ },
+ {
+ "specified gas in args higher than ethparams.TxGas (21,000)",
+ func() {
+ args = types.TransactionArgs{
+ To: &common.Address{},
+ Gas: &higherGas,
+ }
+ },
+ true,
+ ethparams.TxGas,
+ false,
+ },
+ {
+ "specified gas in args higher than request gasCap",
+ func() {
+ gasCap = 22_000
+ args = types.TransactionArgs{
+ To: &common.Address{},
+ Gas: &higherGas,
+ }
+ },
+ true,
+ ethparams.TxGas,
+ false,
+ },
+ {
+ "invalid args - specified both gasPrice and maxFeePerGas",
+ func() {
+ args = types.TransactionArgs{
+ To: &common.Address{},
+ GasPrice: &hexBigInt,
+ MaxFeePerGas: &hexBigInt,
+ }
+ },
+ false,
+ 0,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.enableFeemarket = tc.enableFeemarket
+ suite.SetupTest()
+ gasCap = 25_000_000
+ tc.malleate()
+
+ args, err := json.Marshal(&args)
+ suite.Require().NoError(err)
+ req := types.EthCallRequest{
+ Args: args,
+ GasCap: gasCap,
+ ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
+ }
+
+ rsp, err := suite.queryClient.EstimateGas(sdk.WrapSDKContext(suite.ctx), &req)
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().Equal(int64(tc.expGas), int64(rsp.Gas))
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ suite.enableFeemarket = false // reset flag
+}
+
+func (suite *KeeperTestSuite) TestTraceTx() {
+ // TODO deploy contract that triggers internal transactions
+ var (
+ txMsg *types.MsgEthereumTx
+ traceConfig *types.TraceConfig
+ predecessors []*types.MsgEthereumTx
+ chainID *sdkmath.Int
+ )
+
+ erc20Contract, err := testdata.LoadERC20Contract()
+ suite.Require().NoError(err, "failed to load erc20 contract")
+
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ traceResponse string
+ enableFeemarket bool
+ expFinalGas uint64
+ }{
+ {
+ msg: "default trace",
+ malleate: func() {
+ traceConfig = nil
+ predecessors = []*types.MsgEthereumTx{}
+ },
+ expPass: true,
+ traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "default trace with filtered response",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ }
+ predecessors = []*types.MsgEthereumTx{}
+ },
+ expPass: true,
+ traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
+ enableFeemarket: false,
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "javascript tracer",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}",
+ }
+ predecessors = []*types.MsgEthereumTx{}
+ },
+ expPass: true,
+ traceResponse: "[]",
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "default trace with enableFeemarket",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ }
+ predecessors = []*types.MsgEthereumTx{}
+ },
+ expPass: true,
+ traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
+ enableFeemarket: true,
+ expFinalGas: expGasConsumedWithFeeMkt,
+ },
+ {
+ msg: "javascript tracer with enableFeemarket",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}",
+ }
+ predecessors = []*types.MsgEthereumTx{}
+ },
+ expPass: true,
+ traceResponse: "[]",
+ enableFeemarket: true,
+ expFinalGas: expGasConsumedWithFeeMkt,
+ },
+ {
+ msg: "default tracer with predecessors",
+ malleate: func() {
+ traceConfig = nil
+
+ // increase nonce to avoid address collision
+ vmdb := suite.StateDB()
+ vmdb.SetNonce(suite.address, vmdb.GetNonce(suite.address)+1)
+ suite.Require().NoError(vmdb.Commit())
+
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Commit()
+ // Generate token transfer transaction
+ firstTx := suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
+ txMsg = suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
+ suite.Commit()
+
+ predecessors = append(predecessors, firstTx)
+ },
+ expPass: true,
+ traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
+ enableFeemarket: false,
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "invalid trace config - Negative Limit",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ Limit: -1,
+ }
+ },
+ expPass: false,
+ expFinalGas: 0,
+ },
+ {
+ msg: "invalid trace config - Invalid Tracer",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ Tracer: "invalid_tracer",
+ }
+ },
+ expPass: false,
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "invalid trace config - Invalid Timeout",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ Timeout: "wrong_time",
+ }
+ },
+ expPass: false,
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "default tracer with contract creation tx as predecessor but 'create' param disabled",
+ malleate: func() {
+ traceConfig = nil
+
+ // increase nonce to avoid address collision
+ vmdb := suite.StateDB()
+ vmdb.SetNonce(suite.address, vmdb.GetNonce(suite.address)+1)
+ suite.Require().NoError(vmdb.Commit())
+
+ chainID := suite.app.EvmKeeper.ChainID()
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+ data := erc20Contract.Bin
+ ethTxParams := &types.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ GasLimit: ethparams.TxGasContractCreation,
+ Input: data,
+ }
+ contractTx := types.NewTx(ethTxParams)
+
+ predecessors = append(predecessors, contractTx)
+ suite.Commit()
+
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ params.AccessControl = types.AccessControl{
+ Create: types.AccessControlType{
+ AccessType: types.AccessTypeRestricted,
+ },
+ }
+ err := suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ },
+ expPass: true,
+ traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
+ expFinalGas: 27140, // gas consumed in traceTx setup (GetProposerAddr + CalculateBaseFee) + gas consumed in malleate func
+ },
+ {
+ msg: "invalid chain id",
+ malleate: func() {
+ traceConfig = nil
+ predecessors = []*types.MsgEthereumTx{}
+ tmp := sdkmath.NewInt(1)
+ chainID = &tmp
+ },
+ expPass: false,
+ expFinalGas: expGasConsumed,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.enableFeemarket = tc.enableFeemarket
+ suite.SetupTest()
+ // Deploy contract
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Commit()
+ // Generate token transfer transaction
+ txMsg = suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
+ suite.Commit()
+
+ tc.malleate()
+ traceReq := types.QueryTraceTxRequest{
+ Msg: txMsg,
+ TraceConfig: traceConfig,
+ Predecessors: predecessors,
+ }
+
+ if chainID != nil {
+ traceReq.ChainId = chainID.Int64()
+ }
+ res, err := suite.queryClient.TraceTx(sdk.WrapSDKContext(suite.ctx), &traceReq)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ // if data is too big, slice the result
+ if len(res.Data) > 150 {
+ suite.Require().Equal(tc.traceResponse, string(res.Data[:150]))
+ } else {
+ suite.Require().Equal(tc.traceResponse, string(res.Data))
+ }
+ if traceConfig == nil || traceConfig.Tracer == "" {
+ var result ethlogger.ExecutionResult
+ suite.Require().NoError(json.Unmarshal(res.Data, &result))
+ suite.Require().Positive(result.Gas)
+ }
+ } else {
+ suite.Require().Error(err)
+ }
+ suite.Require().Equal(int(tc.expFinalGas), int(suite.ctx.GasMeter().GasConsumed()), "expected different gas consumption")
+ // Reset for next test case
+ chainID = nil
+ })
+ }
+
+ suite.enableFeemarket = false // reset flag
+}
+
+func (suite *KeeperTestSuite) TestTraceBlock() {
+ var (
+ txs []*types.MsgEthereumTx
+ traceConfig *types.TraceConfig
+ chainID *sdkmath.Int
+ )
+
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ traceResponse string
+ enableFeemarket bool
+ expFinalGas uint64
+ }{
+ {
+ msg: "default trace",
+ malleate: func() {
+ traceConfig = nil
+ },
+ expPass: true,
+ traceResponse: "[{\"result\":{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PU",
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "filtered trace",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ }
+ },
+ expPass: true,
+ traceResponse: "[{\"result\":{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PU",
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "javascript tracer",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}",
+ }
+ },
+ expPass: true,
+ traceResponse: "[{\"result\":[]}]",
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "default trace with enableFeemarket and filtered return",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ }
+ },
+ expPass: true,
+ traceResponse: "[{\"result\":{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PU",
+ enableFeemarket: true,
+ expFinalGas: expGasConsumedWithFeeMkt,
+ },
+ {
+ msg: "javascript tracer with enableFeemarket",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}",
+ }
+ },
+ expPass: true,
+ traceResponse: "[{\"result\":[]}]",
+ enableFeemarket: true,
+ expFinalGas: expGasConsumedWithFeeMkt,
+ },
+ {
+ msg: "tracer with multiple transactions",
+ malleate: func() {
+ traceConfig = nil
+
+ // increase nonce to avoid address collision
+ vmdb := suite.StateDB()
+ vmdb.SetNonce(suite.address, vmdb.GetNonce(suite.address)+1)
+ suite.Require().NoError(vmdb.Commit())
+
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Commit()
+ // create multiple transactions in the same block
+ firstTx := suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
+ secondTx := suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
+ suite.Commit()
+ // overwrite txs to include only the ones on new block
+ txs = append([]*types.MsgEthereumTx{}, firstTx, secondTx)
+ },
+ expPass: true,
+ traceResponse: "[{\"result\":{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PU",
+ enableFeemarket: false,
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "invalid trace config - Negative Limit",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ Limit: -1,
+ }
+ },
+ expPass: false,
+ expFinalGas: 0,
+ },
+ {
+ msg: "invalid trace config - Invalid Tracer",
+ malleate: func() {
+ traceConfig = &types.TraceConfig{
+ DisableStack: true,
+ DisableStorage: true,
+ EnableMemory: false,
+ Tracer: "invalid_tracer",
+ }
+ },
+ expPass: true,
+ traceResponse: "[{\"error\":\"rpc error: code = Internal desc = tracer not found\"}]",
+ expFinalGas: expGasConsumed,
+ },
+ {
+ msg: "invalid chain id",
+ malleate: func() {
+ traceConfig = nil
+ tmp := sdkmath.NewInt(1)
+ chainID = &tmp
+ },
+ expPass: true,
+ traceResponse: "[{\"error\":\"rpc error: code = Internal desc = invalid chain id for signer\"}]",
+ expFinalGas: expGasConsumed,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ txs = []*types.MsgEthereumTx{}
+ suite.enableFeemarket = tc.enableFeemarket
+ suite.SetupTest()
+ // Deploy contract
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
+ suite.Commit()
+ // Generate token transfer transaction
+ txMsg := suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
+ suite.Commit()
+
+ txs = append(txs, txMsg)
+
+ tc.malleate()
+ traceReq := types.QueryTraceBlockRequest{
+ Txs: txs,
+ TraceConfig: traceConfig,
+ }
+
+ if chainID != nil {
+ traceReq.ChainId = chainID.Int64()
+ }
+
+ res, err := suite.queryClient.TraceBlock(sdk.WrapSDKContext(suite.ctx), &traceReq)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ // if data is too big, slice the result
+ if len(res.Data) > 150 {
+ suite.Require().Equal(tc.traceResponse, string(res.Data[:150]))
+ } else {
+ suite.Require().Equal(tc.traceResponse, string(res.Data))
+ }
+ } else {
+ suite.Require().Error(err)
+ }
+ suite.Require().Equal(int64(tc.expFinalGas), int64(suite.ctx.GasMeter().GasConsumed()), "expected different gas consumption")
+ // Reset for next case
+ chainID = nil
+ })
+ }
+
+ suite.enableFeemarket = false // reset flag
+}
+
+func (suite *KeeperTestSuite) TestNonceInQuery() {
+ address := utiltx.GenerateAddress()
+ suite.Require().Equal(uint64(0), suite.app.EvmKeeper.GetNonce(suite.ctx, address))
+ supply := sdkmath.NewIntWithDecimal(1000, 18).BigInt()
+
+ // occupy nonce 0
+ _ = suite.DeployTestContract(suite.T(), address, supply)
+
+ erc20Contract, err := testdata.LoadERC20Contract()
+ suite.Require().NoError(err, "failed to load erc20 contract")
+
+ // do an EthCall/EstimateGas with nonce 0
+ ctorArgs, err := erc20Contract.ABI.Pack("", address, supply)
+ suite.Require().NoError(err)
+
+ data := erc20Contract.Bin
+ data = append(data, ctorArgs...)
+ args, err := json.Marshal(&types.TransactionArgs{
+ From: &address,
+ Data: (*hexutil.Bytes)(&data),
+ })
+ suite.Require().NoError(err)
+ proposerAddress := suite.ctx.BlockHeader().ProposerAddress
+ _, err = suite.queryClient.EstimateGas(sdk.WrapSDKContext(suite.ctx), &types.EthCallRequest{
+ Args: args,
+ GasCap: config.DefaultGasCap,
+ ProposerAddress: proposerAddress,
+ })
+ suite.Require().NoError(err)
+
+ _, err = suite.queryClient.EthCall(sdk.WrapSDKContext(suite.ctx), &types.EthCallRequest{
+ Args: args,
+ GasCap: config.DefaultGasCap,
+ ProposerAddress: proposerAddress,
+ })
+ suite.Require().NoError(err)
+}
+
+func (suite *KeeperTestSuite) TestQueryBaseFee() {
+ var (
+ aux sdkmath.Int
+ expRes *types.QueryBaseFeeResponse
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ enableFeemarket bool
+ enableLondonHF bool
+ }{
+ {
+ "pass - default Base Fee",
+ func() {
+ initialBaseFee := sdkmath.NewInt(ethparams.InitialBaseFee)
+ expRes = &types.QueryBaseFeeResponse{BaseFee: &initialBaseFee}
+ },
+ true, true, true,
+ },
+ {
+ "pass - non-nil Base Fee",
+ func() {
+ baseFee := sdkmath.OneInt().BigInt()
+ suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, baseFee)
+
+ aux = sdkmath.NewIntFromBigInt(baseFee)
+ expRes = &types.QueryBaseFeeResponse{BaseFee: &aux}
+ },
+ true, true, true,
+ },
+ {
+ "pass - nil Base Fee when london hard-fork not activated",
+ func() {
+ baseFee := sdkmath.OneInt().BigInt()
+ suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, baseFee)
+
+ expRes = &types.QueryBaseFeeResponse{}
+ },
+ true, true, false,
+ },
+ {
+ "pass - zero Base Fee when feemarket not activated",
+ func() {
+ baseFee := sdkmath.ZeroInt()
+ expRes = &types.QueryBaseFeeResponse{BaseFee: &baseFee}
+ },
+ true, false, true,
+ },
+ }
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.enableFeemarket = tc.enableFeemarket
+ suite.enableLondonHF = tc.enableLondonHF
+ suite.SetupTest()
+
+ tc.malleate()
+
+ res, err := suite.queryClient.BaseFee(suite.ctx.Context(), &types.QueryBaseFeeRequest{})
+ if tc.expPass {
+ suite.Require().NotNil(res)
+ suite.Require().Equal(expRes, res, tc.name)
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ suite.enableFeemarket = false
+ suite.enableLondonHF = true
+}
+
+func (suite *KeeperTestSuite) TestEthCall() {
+ var req *types.EthCallRequest
+
+ address := utiltx.GenerateAddress()
+ suite.Require().Equal(uint64(0), suite.app.EvmKeeper.GetNonce(suite.ctx, address))
+ supply := sdkmath.NewIntWithDecimal(1000, 18).BigInt()
+
+ hexBigInt := hexutil.Big(*big.NewInt(1))
+
+ erc20Contract, err := testdata.LoadERC20Contract()
+ suite.Require().NoError(err, "failed to load erc20 contract")
+
+ ctorArgs, err := erc20Contract.ABI.Pack("", address, supply)
+ suite.Require().NoError(err)
+
+ data := erc20Contract.Bin
+ data = append(data, ctorArgs...)
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expVMError bool
+ }{
+ {
+ "invalid args",
+ func() {
+ req = &types.EthCallRequest{Args: []byte("invalid args"), GasCap: config.DefaultGasCap}
+ },
+ false,
+ },
+ {
+ "invalid args - specified both gasPrice and maxFeePerGas",
+ func() {
+ args, err := json.Marshal(&types.TransactionArgs{
+ From: &address,
+ Data: (*hexutil.Bytes)(&data),
+ GasPrice: &hexBigInt,
+ MaxFeePerGas: &hexBigInt,
+ })
+
+ suite.Require().NoError(err)
+ req = &types.EthCallRequest{Args: args, GasCap: config.DefaultGasCap}
+ },
+ false,
+ },
+ {
+ "set param AccessControl - no Access",
+ func() {
+ args, err := json.Marshal(&types.TransactionArgs{
+ From: &address,
+ Data: (*hexutil.Bytes)(&data),
+ })
+
+ suite.Require().NoError(err)
+ req = &types.EthCallRequest{Args: args, GasCap: config.DefaultGasCap}
+
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ params.AccessControl = types.AccessControl{
+ Create: types.AccessControlType{
+ AccessType: types.AccessTypeRestricted,
+ },
+ }
+ err = suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "set param AccessControl = non whitelist",
+ func() {
+ args, err := json.Marshal(&types.TransactionArgs{
+ From: &address,
+ Data: (*hexutil.Bytes)(&data),
+ })
+
+ suite.Require().NoError(err)
+ req = &types.EthCallRequest{Args: args, GasCap: config.DefaultGasCap}
+
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ params.AccessControl = types.AccessControl{
+ Create: types.AccessControlType{
+ AccessType: types.AccessTypePermissioned,
+ },
+ }
+ err = suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ }
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ tc.malleate()
+
+ res, err := suite.queryClient.EthCall(suite.ctx, req)
+ if tc.expVMError {
+ suite.Require().NotNil(res)
+ suite.Require().Contains(res.VmError, "does not have permission to deploy contracts")
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestEmptyRequest() {
+ k := suite.app.EvmKeeper
+
+ testCases := []struct {
+ name string
+ queryFunc func() (interface{}, error)
+ }{
+ {
+ "Account method",
+ func() (interface{}, error) {
+ return k.Account(suite.ctx, nil)
+ },
+ },
+ {
+ "CosmosAccount method",
+ func() (interface{}, error) {
+ return k.CosmosAccount(suite.ctx, nil)
+ },
+ },
+ {
+ "ValidatorAccount method",
+ func() (interface{}, error) {
+ return k.ValidatorAccount(suite.ctx, nil)
+ },
+ },
+ {
+ "Balance method",
+ func() (interface{}, error) {
+ return k.Balance(suite.ctx, nil)
+ },
+ },
+ {
+ "Storage method",
+ func() (interface{}, error) {
+ return k.Storage(suite.ctx, nil)
+ },
+ },
+ {
+ "Code method",
+ func() (interface{}, error) {
+ return k.Code(suite.ctx, nil)
+ },
+ },
+ {
+ "EthCall method",
+ func() (interface{}, error) {
+ return k.EthCall(suite.ctx, nil)
+ },
+ },
+ {
+ "EstimateGas method",
+ func() (interface{}, error) {
+ return k.EstimateGas(suite.ctx, nil)
+ },
+ },
+ {
+ "TraceTx method",
+ func() (interface{}, error) {
+ return k.TraceTx(suite.ctx, nil)
+ },
+ },
+ {
+ "TraceBlock method",
+ func() (interface{}, error) {
+ return k.TraceBlock(suite.ctx, nil)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.SetupTest()
+ _, err := tc.queryFunc()
+ suite.Require().Error(err)
+ })
+ }
+}
diff --git a/x/evm/keeper/integration_test.go b/x/evm/keeper/integration_test.go
new file mode 100644
index 00000000..b7de68e1
--- /dev/null
+++ b/x/evm/keeper/integration_test.go
@@ -0,0 +1,654 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper_test
+
+import (
+ "math/big"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "cosmossdk.io/math"
+ abcitypes "github.com/cometbft/cometbft/abci/types"
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/contracts"
+ "github.com/evmos/evmos/v19/precompiles/staking"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ integrationutils "github.com/evmos/evmos/v19/testutil/integration/evmos/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+type IntegrationTestSuite struct {
+ network network.Network
+ factory factory.TxFactory
+ grpcHandler grpc.Handler
+ keyring testkeyring.Keyring
+}
+
+// This test suite is meant to test the EVM module in the context of the EVMOS.
+// It uses the integration test framework to spin up a local EVMOS network and
+// perform transactions on it.
+// The test suite focus on testing how the MsgEthereumTx message is handled under the
+// different params configuration of the module while testing the different Tx types
+// Ethereum supports (LegacyTx, AccessListTx, DynamicFeeTx) and the different types of
+// transactions (transfer, contract deployment, contract call).
+// Note that more in depth testing of the EVM and solidity execution is done through the
+// hardhat and the nix setup.
+var _ = Describe("Handling a MsgEthereumTx message", Label("EVM"), Ordered, func() {
+ var s *IntegrationTestSuite
+
+ BeforeAll(func() {
+ keyring := testkeyring.New(4)
+ integrationNetwork := network.New(
+ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ grpcHandler := grpc.NewIntegrationHandler(integrationNetwork)
+ txFactory := factory.New(integrationNetwork, grpcHandler)
+ s = &IntegrationTestSuite{
+ network: integrationNetwork,
+ factory: txFactory,
+ grpcHandler: grpcHandler,
+ keyring: keyring,
+ }
+ })
+
+ AfterEach(func() {
+ // Start each test with a fresh block
+ err := s.network.NextBlock()
+ Expect(err).To(BeNil())
+ })
+
+ When("the params have default values", Ordered, func() {
+ BeforeAll(func() {
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ err := s.network.UpdateEvmParams(defaultParams)
+ Expect(err).To(BeNil())
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+ })
+
+ DescribeTable("Executes a transfer transaction", func(getTxArgs func() evmtypes.EvmTxArgs) {
+ senderKey := s.keyring.GetKey(0)
+ receiverKey := s.keyring.GetKey(1)
+ denom := s.network.GetDenom()
+
+ senderPrevBalanceResponse, err := s.grpcHandler.GetBalance(senderKey.AccAddr, denom)
+ Expect(err).To(BeNil())
+ senderPrevBalance := senderPrevBalanceResponse.GetBalance().Amount
+
+ receiverPrevBalanceResponse, err := s.grpcHandler.GetBalance(receiverKey.AccAddr, denom)
+ Expect(err).To(BeNil())
+ receiverPrevBalance := receiverPrevBalanceResponse.GetBalance().Amount
+
+ transferAmount := int64(1000)
+
+ // Taking custom args from the table entry
+ txArgs := getTxArgs()
+ txArgs.Amount = big.NewInt(transferAmount)
+ txArgs.To = &receiverKey.Addr
+
+ res, err := s.factory.ExecuteEthTx(senderKey.Priv, txArgs)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+
+ // Check sender balance after transaction
+ senderBalanceResultBeforeFees := senderPrevBalance.Sub(math.NewInt(transferAmount))
+ senderAfterBalance, err := s.grpcHandler.GetBalance(senderKey.AccAddr, denom)
+ Expect(err).To(BeNil())
+ Expect(senderAfterBalance.GetBalance().Amount.LTE(senderBalanceResultBeforeFees)).To(BeTrue())
+
+ // Check receiver balance after transaction
+ receiverBalanceResult := receiverPrevBalance.Add(math.NewInt(transferAmount))
+ receverAfterBalanceResponse, err := s.grpcHandler.GetBalance(receiverKey.AccAddr, denom)
+ Expect(err).To(BeNil())
+ Expect(receverAfterBalanceResponse.GetBalance().Amount).To(Equal(receiverBalanceResult))
+ },
+ Entry("as a DynamicFeeTx", func() evmtypes.EvmTxArgs { return evmtypes.EvmTxArgs{} }),
+ Entry("as an AccessListTx",
+ func() evmtypes.EvmTxArgs {
+ return evmtypes.EvmTxArgs{
+ Accesses: ðtypes.AccessList{{
+ Address: s.keyring.GetAddr(1),
+ StorageKeys: []common.Hash{{0}},
+ }},
+ }
+ },
+ ),
+ Entry("as a LegacyTx", func() evmtypes.EvmTxArgs {
+ return evmtypes.EvmTxArgs{
+ GasPrice: big.NewInt(1e9),
+ }
+ }),
+ )
+
+ DescribeTable("Executes a contract deployment", func(getTxArgs func() evmtypes.EvmTxArgs) {
+ // Deploy contract
+ senderPriv := s.keyring.GetPrivKey(0)
+ constructorArgs := []interface{}{"coin", "token", uint8(18)}
+ compiledContract := contracts.ERC20MinterBurnerDecimalsContract
+
+ txArgs := getTxArgs()
+ contractAddr, err := s.factory.DeployContract(
+ senderPriv,
+ txArgs,
+ factory.ContractDeploymentData{
+ Contract: compiledContract,
+ ConstructorArgs: constructorArgs,
+ },
+ )
+ Expect(err).To(BeNil())
+ Expect(contractAddr).ToNot(Equal(common.Address{}))
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+
+ // Check contract account got created correctly
+ contractBechAddr := sdktypes.AccAddress(contractAddr.Bytes()).String()
+ contractAccount, err := s.grpcHandler.GetAccount(contractBechAddr)
+ Expect(err).To(BeNil())
+ Expect(contractAccount).ToNot(BeNil(), "expected account to be retrievable via auth query")
+
+ ethAccountRes, err := s.grpcHandler.GetEvmAccount(contractAddr)
+ Expect(err).To(BeNil(), "expected no error retrieving account from the state db")
+ Expect(ethAccountRes.CodeHash).ToNot(Equal(common.BytesToHash(evmtypes.EmptyCodeHash).Hex()),
+ "expected code hash not to be the empty code hash",
+ )
+ },
+ Entry("as a DynamicFeeTx", func() evmtypes.EvmTxArgs { return evmtypes.EvmTxArgs{} }),
+ Entry("as an AccessListTx",
+ func() evmtypes.EvmTxArgs {
+ return evmtypes.EvmTxArgs{
+ Accesses: ðtypes.AccessList{{
+ Address: s.keyring.GetAddr(1),
+ StorageKeys: []common.Hash{{0}},
+ }},
+ }
+ },
+ ),
+ Entry("as a LegacyTx", func() evmtypes.EvmTxArgs {
+ return evmtypes.EvmTxArgs{
+ GasPrice: big.NewInt(1e9),
+ }
+ }),
+ )
+
+ Context("With a predeployed ERC20MinterBurnerDecimalsContract", func() {
+ var contractAddr common.Address
+
+ BeforeEach(func() {
+ // Deploy contract
+ senderPriv := s.keyring.GetPrivKey(0)
+ constructorArgs := []interface{}{"coin", "token", uint8(18)}
+ compiledContract := contracts.ERC20MinterBurnerDecimalsContract
+
+ var err error // Avoid shadowing
+ contractAddr, err = s.factory.DeployContract(
+ senderPriv,
+ evmtypes.EvmTxArgs{}, // Default values
+ factory.ContractDeploymentData{
+ Contract: compiledContract,
+ ConstructorArgs: constructorArgs,
+ },
+ )
+ Expect(err).To(BeNil())
+ Expect(contractAddr).ToNot(Equal(common.Address{}))
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+ })
+
+ DescribeTable("Executes a contract call", func(getTxArgs func() evmtypes.EvmTxArgs) {
+ senderPriv := s.keyring.GetPrivKey(0)
+ compiledContract := contracts.ERC20MinterBurnerDecimalsContract
+ recipientKey := s.keyring.GetKey(1)
+
+ // Execute contract call
+ mintTxArgs := getTxArgs()
+ mintTxArgs.To = &contractAddr
+
+ amountToMint := big.NewInt(1e18)
+ mintArgs := factory.CallArgs{
+ ContractABI: compiledContract.ABI,
+ MethodName: "mint",
+ Args: []interface{}{recipientKey.Addr, amountToMint},
+ }
+ mintResponse, err := s.factory.ExecuteContractCall(senderPriv, mintTxArgs, mintArgs)
+ Expect(err).To(BeNil())
+ Expect(mintResponse.IsOK()).To(Equal(true), "transaction should have succeeded", mintResponse.GetLog())
+
+ err = checkMintTopics(mintResponse)
+ Expect(err).To(BeNil())
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+
+ totalSupplyTxArgs := evmtypes.EvmTxArgs{
+ To: &contractAddr,
+ }
+ totalSupplyArgs := factory.CallArgs{
+ ContractABI: compiledContract.ABI,
+ MethodName: "totalSupply",
+ Args: []interface{}{},
+ }
+ totalSupplyRes, err := s.factory.ExecuteContractCall(senderPriv, totalSupplyTxArgs, totalSupplyArgs)
+ Expect(err).To(BeNil())
+ Expect(totalSupplyRes.IsOK()).To(Equal(true), "transaction should have succeeded", totalSupplyRes.GetLog())
+
+ var totalSupplyResponse *big.Int
+ err = integrationutils.DecodeContractCallResponse(&totalSupplyResponse, totalSupplyArgs, totalSupplyRes)
+ Expect(err).To(BeNil())
+ Expect(totalSupplyResponse).To(Equal(amountToMint))
+ },
+ Entry("as a DynamicFeeTx", func() evmtypes.EvmTxArgs { return evmtypes.EvmTxArgs{} }),
+ Entry("as an AccessListTx",
+ func() evmtypes.EvmTxArgs {
+ return evmtypes.EvmTxArgs{
+ Accesses: ðtypes.AccessList{{
+ Address: s.keyring.GetAddr(1),
+ StorageKeys: []common.Hash{{0}},
+ }},
+ }
+ },
+ ),
+ Entry("as a LegacyTx", func() evmtypes.EvmTxArgs {
+ return evmtypes.EvmTxArgs{
+ GasPrice: big.NewInt(1e9),
+ }
+ }),
+ )
+ })
+
+ It("should fail when ChainID is wrong", func() {
+ senderPriv := s.keyring.GetPrivKey(0)
+ receiver := s.keyring.GetKey(1)
+ txArgs := evmtypes.EvmTxArgs{
+ To: &receiver.Addr,
+ Amount: big.NewInt(1000),
+ ChainID: big.NewInt(1),
+ }
+
+ res, err := s.factory.ExecuteEthTx(senderPriv, txArgs)
+ Expect(err).NotTo(BeNil())
+ Expect(err.Error()).To(ContainSubstring("invalid chain id"))
+ // Transaction fails before being broadcasted
+ Expect(res).To(Equal(abcitypes.ResponseDeliverTx{}))
+ })
+ })
+
+ DescribeTable("Performs transfer and contract call", func(getTestParams func() evmtypes.Params, transferParams, contractCallParams PermissionsTableTest) {
+ params := getTestParams()
+ err := s.network.UpdateEvmParams(params)
+ Expect(err).To(BeNil())
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+
+ signer := s.keyring.GetKey(transferParams.SignerIndex)
+ receiver := s.keyring.GetKey(1)
+ txArgs := evmtypes.EvmTxArgs{
+ To: &receiver.Addr,
+ Amount: big.NewInt(1000),
+ // Hard coded gas limit to avoid failure on gas estimation because
+ // of the param
+ GasLimit: 100000,
+ }
+ res, err := s.factory.ExecuteEthTx(signer.Priv, txArgs)
+ if transferParams.ExpFail {
+ Expect(err).NotTo(BeNil())
+ Expect(err.Error()).To(ContainSubstring("does not have permission to perform a call"))
+ } else {
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ }
+
+ senderKey := s.keyring.GetKey(contractCallParams.SignerIndex)
+ contractAddress := common.HexToAddress(evmtypes.StakingPrecompileAddress)
+ validatorAddress := s.network.GetValidators()[1].OperatorAddress
+ contractABI, err := staking.LoadABI()
+ Expect(err).To(BeNil())
+
+ // If grpc query fails, that means there were no previous delegations
+ prevDelegation := big.NewInt(0)
+ prevDelegationRes, err := s.grpcHandler.GetDelegation(senderKey.AccAddr.String(), validatorAddress)
+ if err == nil {
+ prevDelegation = prevDelegationRes.DelegationResponse.Balance.Amount.BigInt()
+ }
+
+ amountToDelegate := big.NewInt(200)
+ totalSupplyTxArgs := evmtypes.EvmTxArgs{
+ To: &contractAddress,
+ }
+
+ // Perform a delegate transaction to the staking precompile
+ delegateArgs := factory.CallArgs{
+ ContractABI: contractABI,
+ MethodName: staking.DelegateMethod,
+ Args: []interface{}{senderKey.Addr, validatorAddress, amountToDelegate},
+ }
+ delegateResponse, err := s.factory.ExecuteContractCall(senderKey.Priv, totalSupplyTxArgs, delegateArgs)
+ if contractCallParams.ExpFail {
+ Expect(err).NotTo(BeNil())
+ Expect(err.Error()).To(ContainSubstring("does not have permission to perform a call"))
+ } else {
+ Expect(err).To(BeNil())
+ Expect(delegateResponse.IsOK()).To(Equal(true), "transaction should have succeeded", delegateResponse.GetLog())
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+
+ // Perform query to check the delegation was successful
+ queryDelegationArgs := factory.CallArgs{
+ ContractABI: contractABI,
+ MethodName: staking.DelegationMethod,
+ Args: []interface{}{senderKey.Addr, validatorAddress},
+ }
+ queryDelegationResponse, err := s.factory.ExecuteContractCall(senderKey.Priv, totalSupplyTxArgs, queryDelegationArgs)
+ Expect(err).To(BeNil())
+ Expect(queryDelegationResponse.IsOK()).To(Equal(true), "transaction should have succeeded", queryDelegationResponse.GetLog())
+
+ // Make sure the delegation amount is correct
+ var delegationOutput staking.DelegationOutput
+ err = integrationutils.DecodeContractCallResponse(&delegationOutput, queryDelegationArgs, queryDelegationResponse)
+ Expect(err).To(BeNil())
+
+ expectedDelegationAmt := amountToDelegate.Add(amountToDelegate, prevDelegation)
+ Expect(delegationOutput.Balance.Amount.String()).To(Equal(expectedDelegationAmt.String()))
+ }
+ },
+ // Entry("transfer and call fail with CALL permission policy set to restricted", func() evmtypes.Params {
+ // // Set params to default values
+ // defaultParams := evmtypes.DefaultParams()
+ // defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ // AccessType: evmtypes.AccessTypeRestricted,
+ // }
+ // return defaultParams
+ // },
+ // OpcodeTestTable{ExpFail: true, SignerIndex: 0},
+ // OpcodeTestTable{ExpFail: true, SignerIndex: 0},
+ // ),
+ Entry("transfer and call succeed with CALL permission policy set to default and CREATE permission policy set to restricted", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Create = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypeRestricted,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ ),
+ Entry("transfer and call are successful with CALL permission policy set to permissionless and address not blocked", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissionless,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ ),
+ Entry("transfer fails with signer blocked and call succeeds with signer NOT blocked permission policy set to permissionless", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissionless,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: true, SignerIndex: 1},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ ),
+ Entry("transfer succeeds with signer NOT blocked and call fails with signer blocked permission policy set to permissionless", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissionless,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: true, SignerIndex: 1},
+ ),
+ Entry("transfer and call succeeds with CALL permission policy set to permissioned and signer whitelisted on both", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissioned,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 1},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 1},
+ ),
+ Entry("transfer and call fails with CALL permission policy set to permissioned and signer not whitelisted on both", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissioned,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: true, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: true, SignerIndex: 0},
+ ),
+ )
+
+ DescribeTable("Performs contract deployment and contract call with AccessControl", func(getTestParams func() evmtypes.Params, createParams, callParams PermissionsTableTest) {
+ params := getTestParams()
+ err := s.network.UpdateEvmParams(params)
+ Expect(err).To(BeNil())
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+
+ createSigner := s.keyring.GetPrivKey(createParams.SignerIndex)
+ constructorArgs := []interface{}{"coin", "token", uint8(18)}
+ compiledContract := contracts.ERC20MinterBurnerDecimalsContract
+
+ contractAddr, err := s.factory.DeployContract(
+ createSigner,
+ evmtypes.EvmTxArgs{}, // Default values
+ factory.ContractDeploymentData{
+ Contract: compiledContract,
+ ConstructorArgs: constructorArgs,
+ },
+ )
+ if createParams.ExpFail {
+ Expect(err).NotTo(BeNil())
+ Expect(err.Error()).To(ContainSubstring("does not have permission to deploy contracts"))
+ // If contract deployment is expected to fail, we can skip the rest of the test
+ return
+ }
+
+ Expect(err).To(BeNil())
+ Expect(contractAddr).ToNot(Equal(common.Address{}))
+
+ err = s.network.NextBlock()
+ Expect(err).To(BeNil())
+
+ callSigner := s.keyring.GetPrivKey(callParams.SignerIndex)
+ totalSupplyTxArgs := evmtypes.EvmTxArgs{
+ To: &contractAddr,
+ }
+ totalSupplyArgs := factory.CallArgs{
+ ContractABI: compiledContract.ABI,
+ MethodName: "totalSupply",
+ Args: []interface{}{},
+ }
+ res, err := s.factory.ExecuteContractCall(callSigner, totalSupplyTxArgs, totalSupplyArgs)
+ if callParams.ExpFail {
+ Expect(err).NotTo(BeNil())
+ Expect(err.Error()).To(ContainSubstring("does not have permission to perform a call"))
+ } else {
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ }
+ },
+ Entry("Create and call is successful with create permission policy set to permissionless and address not blocked ", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Create = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissionless,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ ),
+ Entry("Create fails with create permission policy set to permissionless and signer is blocked ", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Create = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissionless,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: true, SignerIndex: 1},
+ PermissionsTableTest{}, // Call should not be executed
+ ),
+ Entry("Create and call is successful with call permission policy set to permissionless and address not blocked ", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissionless,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ ),
+ Entry("Create is successful and call fails with call permission policy set to permissionless and address blocked ", func() evmtypes.Params {
+ blockedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissionless,
+ AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: true, SignerIndex: 1},
+ ),
+ Entry("Create fails create permission policy set to restricted", func() evmtypes.Params {
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Create = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypeRestricted,
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: true, SignerIndex: 0},
+ PermissionsTableTest{}, // Call should not be executed
+ ),
+ Entry("Create succeeds and call fails when call permission policy set to restricted", func() evmtypes.Params {
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypeRestricted,
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: true, SignerIndex: 0},
+ ),
+ Entry("Create and call are successful with create permission policy set to permissioned and signer whitelisted", func() evmtypes.Params {
+ whitelistedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Create = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissioned,
+ AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 1},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ ),
+ Entry("Create fails with create permission policy set to permissioned and signer NOT whitelisted", func() evmtypes.Params {
+ whitelistedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Create = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissioned,
+ AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: true, SignerIndex: 0},
+ PermissionsTableTest{},
+ ),
+ Entry("Create and call are successful with call permission policy set to permissioned and signer whitelisted", func() evmtypes.Params {
+ whitelistedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissioned,
+ AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: false, SignerIndex: 1},
+ ),
+ Entry("Create succeeds and call fails with call permission policy set to permissioned and signer NOT whitelisted", func() evmtypes.Params {
+ whitelistedSignerIndex := 1
+ // Set params to default values
+ defaultParams := evmtypes.DefaultParams()
+ defaultParams.AccessControl.Call = evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypePermissioned,
+ AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()},
+ }
+ return defaultParams
+ },
+ PermissionsTableTest{ExpFail: false, SignerIndex: 0},
+ PermissionsTableTest{ExpFail: true, SignerIndex: 0},
+ ),
+ )
+})
+
+type PermissionsTableTest struct {
+ ExpFail bool
+ SignerIndex int
+}
+
+func checkMintTopics(res abcitypes.ResponseDeliverTx) error {
+ // Check contract call response has the expected topics for a mint
+ // call within an ERC20 contract
+ expectedTopics := []string{
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x0000000000000000000000000000000000000000000000000000000000000000",
+ }
+ return integrationutils.CheckTxTopics(res, expectedTopics)
+}
diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go
new file mode 100644
index 00000000..60a57e7e
--- /dev/null
+++ b/x/evm/keeper/keeper.go
@@ -0,0 +1,352 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ "github.com/cometbft/cometbft/libs/log"
+ "github.com/cosmos/cosmos-sdk/codec"
+ "github.com/cosmos/cosmos-sdk/store/prefix"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ evmostypes "github.com/evmos/evmos/v19/types"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// Keeper grants access to the EVM module state and implements the go-ethereum StateDB interface.
+type Keeper struct {
+ // Protobuf codec
+ cdc codec.BinaryCodec
+ // Store key required for the EVM Prefix KVStore. It is required by:
+ // - storing account's Storage State
+ // - storing account's Code
+ // - storing transaction Logs
+ // - storing Bloom filters by block height. Needed for the Web3 API.
+ storeKey storetypes.StoreKey
+
+ // key to access the transient store, which is reset on every block during Commit
+ transientKey storetypes.StoreKey
+
+ // the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account.
+ authority sdk.AccAddress
+
+ // access to account state
+ accountKeeper types.AccountKeeper
+ // update balance and accounting operations with coins
+ bankKeeper types.BankKeeper
+ // access historical headers for EVM state transition execution
+ stakingKeeper types.StakingKeeper
+ // fetch EIP1559 base fee and parameters
+ feeMarketKeeper types.FeeMarketKeeper
+ // erc20Keeper interface needed to instantiate erc20 precompiles
+ erc20Keeper types.Erc20Keeper
+
+ // chain ID number obtained from the context's chain id
+ eip155ChainID *big.Int
+
+ // Tracer used to collect execution traces from the EVM transaction execution
+ tracer string
+
+ // Legacy subspace
+ ss paramstypes.Subspace
+
+ // precompiles defines the map of all available precompiled smart contracts.
+ // Some these precompiled contracts might not be active depending on the EVM
+ // parameters.
+ precompiles map[common.Address]vm.PrecompiledContract
+}
+
+// NewKeeper generates new evm module keeper
+func NewKeeper(
+ cdc codec.BinaryCodec,
+ storeKey, transientKey storetypes.StoreKey,
+ authority sdk.AccAddress,
+ ak types.AccountKeeper,
+ bankKeeper types.BankKeeper,
+ sk types.StakingKeeper,
+ fmk types.FeeMarketKeeper,
+ erc20Keeper types.Erc20Keeper,
+ tracer string,
+ ss paramstypes.Subspace,
+) *Keeper {
+ // ensure evm module account is set
+ if addr := ak.GetModuleAddress(types.ModuleName); addr == nil {
+ panic("the EVM module account has not been set")
+ }
+
+ // ensure the authority account is correct
+ if err := sdk.VerifyAddressFormat(authority); err != nil {
+ panic(err)
+ }
+
+ // NOTE: we pass in the parameter space to the CommitStateDB in order to use custom denominations for the EVM operations
+ return &Keeper{
+ cdc: cdc,
+ authority: authority,
+ accountKeeper: ak,
+ bankKeeper: bankKeeper,
+ stakingKeeper: sk,
+ feeMarketKeeper: fmk,
+ storeKey: storeKey,
+ transientKey: transientKey,
+ tracer: tracer,
+ erc20Keeper: erc20Keeper,
+ ss: ss,
+ }
+}
+
+// Logger returns a module-specific logger.
+func (k Keeper) Logger(ctx sdk.Context) log.Logger {
+ return ctx.Logger().With("module", types.ModuleName)
+}
+
+// WithChainID sets the chain id to the local variable in the keeper
+func (k *Keeper) WithChainID(ctx sdk.Context) {
+ chainID, err := evmostypes.ParseChainID(ctx.ChainID())
+ if err != nil {
+ panic(err)
+ }
+
+ if k.eip155ChainID != nil && k.eip155ChainID.Cmp(chainID) != 0 {
+ panic("chain id already set")
+ }
+
+ k.eip155ChainID = chainID
+}
+
+// ChainID returns the EIP155 chain ID for the EVM context
+func (k Keeper) ChainID() *big.Int {
+ return k.eip155ChainID
+}
+
+// ----------------------------------------------------------------------------
+// Block Bloom
+// Required by Web3 API.
+// ----------------------------------------------------------------------------
+
+// EmitBlockBloomEvent emit block bloom events
+func (k Keeper) EmitBlockBloomEvent(ctx sdk.Context, bloom ethtypes.Bloom) {
+ ctx.EventManager().EmitEvent(
+ sdk.NewEvent(
+ types.EventTypeBlockBloom,
+ sdk.NewAttribute(types.AttributeKeyEthereumBloom, string(bloom.Bytes())),
+ ),
+ )
+}
+
+// GetAuthority returns the x/evm module authority address
+func (k Keeper) GetAuthority() sdk.AccAddress {
+ return k.authority
+}
+
+// GetBlockBloomTransient returns bloom bytes for the current block height
+func (k Keeper) GetBlockBloomTransient(ctx sdk.Context) *big.Int {
+ store := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientBloom)
+ heightBz := sdk.Uint64ToBigEndian(uint64(ctx.BlockHeight()))
+ bz := store.Get(heightBz)
+ if len(bz) == 0 {
+ return big.NewInt(0)
+ }
+
+ return new(big.Int).SetBytes(bz)
+}
+
+// SetBlockBloomTransient sets the given bloom bytes to the transient store. This value is reset on
+// every block.
+func (k Keeper) SetBlockBloomTransient(ctx sdk.Context, bloom *big.Int) {
+ store := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientBloom)
+ heightBz := sdk.Uint64ToBigEndian(uint64(ctx.BlockHeight()))
+ store.Set(heightBz, bloom.Bytes())
+}
+
+// ----------------------------------------------------------------------------
+// Tx
+// ----------------------------------------------------------------------------
+
+// SetTxIndexTransient set the index of processing transaction
+func (k Keeper) SetTxIndexTransient(ctx sdk.Context, index uint64) {
+ store := ctx.TransientStore(k.transientKey)
+ store.Set(types.KeyPrefixTransientTxIndex, sdk.Uint64ToBigEndian(index))
+}
+
+// GetTxIndexTransient returns EVM transaction index on the current block.
+func (k Keeper) GetTxIndexTransient(ctx sdk.Context) uint64 {
+ store := ctx.TransientStore(k.transientKey)
+ bz := store.Get(types.KeyPrefixTransientTxIndex)
+ if len(bz) == 0 {
+ return 0
+ }
+
+ return sdk.BigEndianToUint64(bz)
+}
+
+// ----------------------------------------------------------------------------
+// Log
+// ----------------------------------------------------------------------------
+
+// GetLogSizeTransient returns EVM log index on the current block.
+func (k Keeper) GetLogSizeTransient(ctx sdk.Context) uint64 {
+ store := ctx.TransientStore(k.transientKey)
+ bz := store.Get(types.KeyPrefixTransientLogSize)
+ if len(bz) == 0 {
+ return 0
+ }
+
+ return sdk.BigEndianToUint64(bz)
+}
+
+// SetLogSizeTransient fetches the current EVM log index from the transient store, increases its
+// value by one and then sets the new index back to the transient store.
+func (k Keeper) SetLogSizeTransient(ctx sdk.Context, logSize uint64) {
+ store := ctx.TransientStore(k.transientKey)
+ store.Set(types.KeyPrefixTransientLogSize, sdk.Uint64ToBigEndian(logSize))
+}
+
+// ----------------------------------------------------------------------------
+// Storage
+// ----------------------------------------------------------------------------
+
+// GetAccountStorage return state storage associated with an account
+func (k Keeper) GetAccountStorage(ctx sdk.Context, address common.Address) types.Storage {
+ storage := types.Storage{}
+
+ k.ForEachStorage(ctx, address, func(key, value common.Hash) bool {
+ storage = append(storage, types.NewState(key, value))
+ return true
+ })
+
+ return storage
+}
+
+// ----------------------------------------------------------------------------
+// Account
+// ----------------------------------------------------------------------------
+
+// Tracer return a default vm.Tracer based on current keeper state
+func (k Keeper) Tracer(ctx sdk.Context, msg core.Message, ethCfg *params.ChainConfig) vm.EVMLogger {
+ return types.NewTracer(k.tracer, msg, ethCfg, ctx.BlockHeight())
+}
+
+// GetAccountWithoutBalance load nonce and codehash without balance,
+// more efficient in cases where balance is not needed.
+func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *statedb.Account {
+ cosmosAddr := sdk.AccAddress(addr.Bytes())
+ acct := k.accountKeeper.GetAccount(ctx, cosmosAddr)
+ if acct == nil {
+ return nil
+ }
+
+ codeHashBz := k.GetCodeHash(ctx, addr).Bytes()
+
+ return &statedb.Account{
+ Nonce: acct.GetSequence(),
+ CodeHash: codeHashBz,
+ }
+}
+
+// GetAccountOrEmpty returns empty account if not exist
+func (k *Keeper) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) statedb.Account {
+ acct := k.GetAccount(ctx, addr)
+ if acct != nil {
+ return *acct
+ }
+
+ // empty account
+ return statedb.Account{
+ Balance: new(big.Int),
+ CodeHash: types.EmptyCodeHash,
+ }
+}
+
+// GetNonce returns the sequence number of an account, returns 0 if not exists.
+func (k *Keeper) GetNonce(ctx sdk.Context, addr common.Address) uint64 {
+ cosmosAddr := sdk.AccAddress(addr.Bytes())
+ acct := k.accountKeeper.GetAccount(ctx, cosmosAddr)
+ if acct == nil {
+ return 0
+ }
+
+ return acct.GetSequence()
+}
+
+// GetBalance load account's balance of gas token
+func (k *Keeper) GetBalance(ctx sdk.Context, addr common.Address) *big.Int {
+ cosmosAddr := sdk.AccAddress(addr.Bytes())
+ evmParams := k.GetParams(ctx)
+ evmDenom := evmParams.GetEvmDenom()
+ // if node is pruned, params is empty. Return invalid value
+ if evmDenom == "" {
+ return big.NewInt(-1)
+ }
+ coin := k.bankKeeper.GetBalance(ctx, cosmosAddr, evmDenom)
+ return coin.Amount.BigInt()
+}
+
+// GetBaseFee returns current base fee, return values:
+// - `nil`: london hardfork not enabled.
+// - `0`: london hardfork enabled but feemarket is not enabled.
+// - `n`: both london hardfork and feemarket are enabled.
+func (k Keeper) GetBaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int {
+ return k.getBaseFee(ctx, types.IsLondon(ethCfg, ctx.BlockHeight()))
+}
+
+func (k Keeper) getBaseFee(ctx sdk.Context, london bool) *big.Int {
+ if !london {
+ return nil
+ }
+ baseFee := k.feeMarketKeeper.GetBaseFee(ctx)
+ if baseFee == nil {
+ // return 0 if feemarket not enabled.
+ baseFee = big.NewInt(0)
+ }
+ return baseFee
+}
+
+// GetMinGasMultiplier returns the MinGasMultiplier param from the fee market module
+func (k Keeper) GetMinGasMultiplier(ctx sdk.Context) math.LegacyDec {
+ return k.feeMarketKeeper.GetParams(ctx).MinGasMultiplier
+}
+
+// ResetTransientGasUsed reset gas used to prepare for execution of current cosmos tx, called in ante handler.
+func (k Keeper) ResetTransientGasUsed(ctx sdk.Context) {
+ store := ctx.TransientStore(k.transientKey)
+ store.Delete(types.KeyPrefixTransientGasUsed)
+}
+
+// GetTransientGasUsed returns the gas used by current cosmos tx.
+func (k Keeper) GetTransientGasUsed(ctx sdk.Context) uint64 {
+ store := ctx.TransientStore(k.transientKey)
+ bz := store.Get(types.KeyPrefixTransientGasUsed)
+ if len(bz) == 0 {
+ return 0
+ }
+ return sdk.BigEndianToUint64(bz)
+}
+
+// SetTransientGasUsed sets the gas used by current cosmos tx.
+func (k Keeper) SetTransientGasUsed(ctx sdk.Context, gasUsed uint64) {
+ store := ctx.TransientStore(k.transientKey)
+ bz := sdk.Uint64ToBigEndian(gasUsed)
+ store.Set(types.KeyPrefixTransientGasUsed, bz)
+}
+
+// AddTransientGasUsed accumulate gas used by each eth msgs included in current cosmos tx.
+func (k Keeper) AddTransientGasUsed(ctx sdk.Context, gasUsed uint64) (uint64, error) {
+ result := k.GetTransientGasUsed(ctx) + gasUsed
+ if result < gasUsed {
+ return 0, errorsmod.Wrap(types.ErrGasOverflow, "transient gas used")
+ }
+ k.SetTransientGasUsed(ctx, result)
+ return result, nil
+}
diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go
new file mode 100644
index 00000000..8e6d9d47
--- /dev/null
+++ b/x/evm/keeper/keeper_test.go
@@ -0,0 +1,194 @@
+package keeper_test
+
+import (
+ "fmt"
+ "math/big"
+
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/keeper"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+)
+
+func (suite *KeeperTestSuite) TestWithChainID() {
+ testCases := []struct {
+ name string
+ chainID string
+ expChainID int64
+ expPanic bool
+ }{
+ {
+ "fail - chainID is empty",
+ "",
+ 0,
+ true,
+ },
+ {
+ "success - Evmos mainnet chain ID",
+ "evmos_9001-2",
+ 9001,
+ false,
+ },
+ {
+ "success - Evmos testnet chain ID",
+ "evmos_9000-4",
+ 9000,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ keeper := keeper.Keeper{}
+ ctx := suite.ctx.WithChainID(tc.chainID)
+
+ if tc.expPanic {
+ suite.Require().Panics(func() {
+ keeper.WithChainID(ctx)
+ })
+ } else {
+ suite.Require().NotPanics(func() {
+ keeper.WithChainID(ctx)
+ suite.Require().Equal(tc.expChainID, keeper.ChainID().Int64())
+ })
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestBaseFee() {
+ testCases := []struct {
+ name string
+ enableLondonHF bool
+ enableFeemarket bool
+ expectBaseFee *big.Int
+ }{
+ {"not enable london HF, not enable feemarket", false, false, nil},
+ {"enable london HF, not enable feemarket", true, false, big.NewInt(0)},
+ {"enable london HF, enable feemarket", true, true, big.NewInt(1000000000)},
+ {"not enable london HF, enable feemarket", false, true, nil},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.enableFeemarket = tc.enableFeemarket
+ suite.enableLondonHF = tc.enableLondonHF
+ suite.SetupTest()
+ suite.app.EvmKeeper.BeginBlock(suite.ctx, abci.RequestBeginBlock{})
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ baseFee := suite.app.EvmKeeper.GetBaseFee(suite.ctx, ethCfg)
+ suite.Require().Equal(tc.expectBaseFee, baseFee)
+ })
+ }
+ suite.enableFeemarket = false
+ suite.enableLondonHF = true
+}
+
+func (suite *KeeperTestSuite) TestGetAccountStorage() {
+ testCases := []struct {
+ name string
+ malleate func() common.Address
+ }{
+ {
+ name: "Only accounts that are not a contract (no storage)",
+ malleate: nil,
+ },
+ {
+ name: "One contract (with storage) and other EOAs",
+ malleate: func() common.Address {
+ supply := big.NewInt(100)
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, supply)
+ return contractAddr
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+
+ var contractAddr common.Address
+ if tc.malleate != nil {
+ contractAddr = tc.malleate()
+ }
+
+ i := 0
+ suite.app.AccountKeeper.IterateAccounts(suite.ctx, func(account authtypes.AccountI) bool {
+ acc, ok := account.(*authtypes.BaseAccount)
+ if !ok {
+ // Ignore e.g. module accounts
+ return false
+ }
+
+ address, err := utils.Bech32ToHexAddr(acc.Address)
+ if err != nil {
+ // NOTE: we panic in the test to see any potential problems
+ // instead of skipping to the next account
+ panic(fmt.Sprintf("failed to convert %s to hex address", err))
+ }
+
+ storage := suite.app.EvmKeeper.GetAccountStorage(suite.ctx, address)
+
+ if address == contractAddr {
+ suite.Require().NotEqual(0, len(storage),
+ "expected account %d to have non-zero amount of storage slots, got %d",
+ i, len(storage),
+ )
+ } else {
+ suite.Require().Len(storage, 0,
+ "expected account %d to have %d storage slots, got %d",
+ i, 0, len(storage),
+ )
+ }
+
+ i++
+ return false
+ })
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestGetAccountOrEmpty() {
+ empty := statedb.Account{
+ Balance: new(big.Int),
+ CodeHash: evmtypes.EmptyCodeHash,
+ }
+
+ supply := big.NewInt(100)
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, supply)
+
+ testCases := []struct {
+ name string
+ addr common.Address
+ expEmpty bool
+ }{
+ {
+ "unexisting account - get empty",
+ common.Address{},
+ true,
+ },
+ {
+ "existing contract account",
+ contractAddr,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ res := suite.app.EvmKeeper.GetAccountOrEmpty(suite.ctx, tc.addr)
+ if tc.expEmpty {
+ suite.Require().Equal(empty, res)
+ } else {
+ suite.Require().NotEqual(empty, res)
+ }
+ })
+ }
+}
diff --git a/x/evm/keeper/migrations.go b/x/evm/keeper/migrations.go
new file mode 100644
index 00000000..86ea49a9
--- /dev/null
+++ b/x/evm/keeper/migrations.go
@@ -0,0 +1,28 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ v7 "github.com/evmos/evmos/v19/x/evm/migrations/v7"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// Migrator is a struct for handling in-place store migrations.
+type Migrator struct {
+ keeper Keeper
+ legacySubspace types.Subspace
+}
+
+// NewMigrator returns a new Migrator instance.
+func NewMigrator(keeper Keeper, legacySubspace types.Subspace) Migrator {
+ return Migrator{
+ keeper: keeper,
+ legacySubspace: legacySubspace,
+ }
+}
+
+// Migrate6to7 migrates the store from consensus version 6 to 7.
+func (m Migrator) Migrate6to7(ctx sdk.Context) error {
+ return v7.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc)
+}
diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go
new file mode 100644
index 00000000..c3d30010
--- /dev/null
+++ b/x/evm/keeper/msg_server.go
@@ -0,0 +1,149 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "strconv"
+
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+
+ tmbytes "github.com/cometbft/cometbft/libs/bytes"
+ tmtypes "github.com/cometbft/cometbft/types"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ "github.com/armon/go-metrics"
+ "github.com/cosmos/cosmos-sdk/telemetry"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+var _ types.MsgServer = &Keeper{}
+
+// EthereumTx implements the gRPC MsgServer interface. It receives a transaction which is then
+// executed (i.e applied) against the go-ethereum EVM. The provided SDK Context is set to the Keeper
+// so that it can implements and call the StateDB methods without receiving it as a function
+// parameter.
+func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) {
+ ctx := sdk.UnwrapSDKContext(goCtx)
+
+ sender := msg.From
+ tx := msg.AsTransaction()
+ txIndex := k.GetTxIndexTransient(ctx)
+
+ labels := []metrics.Label{
+ telemetry.NewLabel("tx_type", fmt.Sprintf("%d", tx.Type())),
+ }
+ if tx.To() == nil {
+ labels = append(labels, telemetry.NewLabel("execution", "create"))
+ } else {
+ labels = append(labels, telemetry.NewLabel("execution", "call"))
+ }
+
+ response, err := k.ApplyTransaction(ctx, tx)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to apply transaction")
+ }
+
+ defer func() {
+ telemetry.IncrCounterWithLabels(
+ []string{"tx", "msg", "ethereum_tx", "total"},
+ 1,
+ labels,
+ )
+
+ if response.GasUsed != 0 {
+ telemetry.IncrCounterWithLabels(
+ []string{"tx", "msg", "ethereum_tx", "gas_used", "total"},
+ float32(response.GasUsed),
+ labels,
+ )
+
+ // Observe which users define a gas limit >> gas used. Note, that
+ // gas_limit and gas_used are always > 0
+ gasLimit := math.LegacyNewDec(int64(tx.Gas()))
+ gasRatio, err := gasLimit.QuoInt64(int64(response.GasUsed)).Float64()
+ if err == nil {
+ telemetry.SetGaugeWithLabels(
+ []string{"tx", "msg", "ethereum_tx", "gas_limit", "per", "gas_used"},
+ float32(gasRatio),
+ labels,
+ )
+ }
+ }
+ }()
+
+ attrs := []sdk.Attribute{
+ sdk.NewAttribute(sdk.AttributeKeyAmount, tx.Value().String()),
+ // add event for ethereum transaction hash format
+ sdk.NewAttribute(types.AttributeKeyEthereumTxHash, response.Hash),
+ // add event for index of valid ethereum tx
+ sdk.NewAttribute(types.AttributeKeyTxIndex, strconv.FormatUint(txIndex, 10)),
+ // add event for eth tx gas used, we can't get it from cosmos tx result when it contains multiple eth tx msgs.
+ sdk.NewAttribute(types.AttributeKeyTxGasUsed, strconv.FormatUint(response.GasUsed, 10)),
+ }
+
+ if len(ctx.TxBytes()) > 0 {
+ // add event for tendermint transaction hash format
+ hash := tmbytes.HexBytes(tmtypes.Tx(ctx.TxBytes()).Hash())
+ attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyTxHash, hash.String()))
+ }
+
+ if to := tx.To(); to != nil {
+ attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyRecipient, to.Hex()))
+ }
+
+ if response.Failed() {
+ attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyEthereumTxFailed, response.VmError))
+ }
+
+ txLogAttrs := make([]sdk.Attribute, len(response.Logs))
+ for i, log := range response.Logs {
+ value, err := json.Marshal(log)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to encode log")
+ }
+ txLogAttrs[i] = sdk.NewAttribute(types.AttributeKeyTxLog, string(value))
+ }
+
+ // emit events
+ ctx.EventManager().EmitEvents(sdk.Events{
+ sdk.NewEvent(
+ types.EventTypeEthereumTx,
+ attrs...,
+ ),
+ sdk.NewEvent(
+ types.EventTypeTxLog,
+ txLogAttrs...,
+ ),
+ sdk.NewEvent(
+ sdk.EventTypeMessage,
+ sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
+ sdk.NewAttribute(sdk.AttributeKeySender, sender),
+ sdk.NewAttribute(types.AttributeKeyTxType, fmt.Sprintf("%d", tx.Type())),
+ ),
+ })
+
+ return response, nil
+}
+
+// UpdateParams implements the gRPC MsgServer interface. When an UpdateParams
+// proposal passes, it updates the module parameters. The update can only be
+// performed if the requested authority is the Cosmos SDK governance module
+// account.
+func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
+ if k.authority.String() != req.Authority {
+ return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority, expected %s, got %s", k.authority.String(), req.Authority)
+ }
+
+ ctx := sdk.UnwrapSDKContext(goCtx)
+ if err := k.SetParams(ctx, req.Params); err != nil {
+ return nil, err
+ }
+
+ return &types.MsgUpdateParamsResponse{}, nil
+}
diff --git a/x/evm/keeper/msg_server_test.go b/x/evm/keeper/msg_server_test.go
new file mode 100644
index 00000000..0311379a
--- /dev/null
+++ b/x/evm/keeper/msg_server_test.go
@@ -0,0 +1,111 @@
+package keeper_test
+
+import (
+ "math/big"
+
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *KeeperTestSuite) TestEthereumTx() {
+ var (
+ err error
+ msg *types.MsgEthereumTx
+ signer ethtypes.Signer
+ vmdb *statedb.StateDB
+ expectedGasUsed uint64
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expErr bool
+ }{
+ {
+ "Deploy contract tx - insufficient gas",
+ func() {
+ msg, err = suite.createContractMsgTx(
+ vmdb.GetNonce(suite.address),
+ signer,
+ big.NewInt(1),
+ )
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "Transfer funds tx",
+ func() {
+ msg, _, err = newEthMsgTx(
+ vmdb.GetNonce(suite.address),
+ suite.address,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ nil,
+ nil,
+ )
+ suite.Require().NoError(err)
+ expectedGasUsed = params.TxGas
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ signer = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+ vmdb = suite.StateDB()
+
+ tc.malleate()
+ res, err := suite.app.EvmKeeper.EthereumTx(suite.ctx, msg)
+ if tc.expErr {
+ suite.Require().Error(err)
+ return
+ }
+ suite.Require().NoError(err)
+ suite.Require().Equal(expectedGasUsed, res.GasUsed)
+ suite.Require().False(res.Failed())
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestUpdateParams() {
+ testCases := []struct {
+ name string
+ request *types.MsgUpdateParams
+ expectErr bool
+ }{
+ {
+ name: "fail - invalid authority",
+ request: &types.MsgUpdateParams{Authority: "foobar"},
+ expectErr: true,
+ },
+ {
+ name: "pass - valid Update msg",
+ request: &types.MsgUpdateParams{
+ Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
+ Params: types.DefaultParams(),
+ },
+ expectErr: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ suite.Run("MsgUpdateParams", func() {
+ _, err := suite.app.EvmKeeper.UpdateParams(suite.ctx, tc.request)
+ if tc.expectErr {
+ suite.Require().Error(err)
+ } else {
+ suite.Require().NoError(err)
+ }
+ })
+ }
+}
diff --git a/x/evm/keeper/params.go b/x/evm/keeper/params.go
new file mode 100644
index 00000000..6721c549
--- /dev/null
+++ b/x/evm/keeper/params.go
@@ -0,0 +1,100 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "fmt"
+ "slices"
+ "sort"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// GetParams returns the total set of evm parameters.
+func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
+ store := ctx.KVStore(k.storeKey)
+ bz := store.Get(types.KeyPrefixParams)
+ if len(bz) == 0 {
+ return k.GetLegacyParams(ctx)
+ }
+ k.cdc.MustUnmarshal(bz, ¶ms)
+ return
+}
+
+// SetParams sets the EVM params each in their individual key for better get performance
+func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error {
+ // NOTE: We need to sort the precompiles in order to enable searching with binary search
+ // in params.IsActivePrecompile.
+ slices.Sort(params.ActiveStaticPrecompiles)
+
+ if err := params.Validate(); err != nil {
+ return err
+ }
+
+ store := ctx.KVStore(k.storeKey)
+ bz, err := k.cdc.Marshal(¶ms)
+ if err != nil {
+ return err
+ }
+
+ store.Set(types.KeyPrefixParams, bz)
+ return nil
+}
+
+// GetLegacyParams returns param set for version before migrate
+func (k Keeper) GetLegacyParams(ctx sdk.Context) types.Params {
+ var params types.Params
+ k.ss.GetParamSetIfExists(ctx, ¶ms)
+ return params
+}
+
+// EnableStaticPrecompiles appends the addresses of the given Precompiles to the list
+// of active static precompiles.
+func (k Keeper) EnableStaticPrecompiles(ctx sdk.Context, addresses ...common.Address) error {
+ params := k.GetParams(ctx)
+ activePrecompiles := params.ActiveStaticPrecompiles
+
+ // Append and sort the new precompiles
+ updatedPrecompiles, err := appendPrecompiles(activePrecompiles, addresses...)
+ if err != nil {
+ return err
+ }
+
+ params.ActiveStaticPrecompiles = updatedPrecompiles
+ return k.SetParams(ctx, params)
+}
+
+func appendPrecompiles(existingPrecompiles []string, addresses ...common.Address) ([]string, error) {
+ // check for duplicates
+ hexAddresses := make([]string, len(addresses))
+ for i := range addresses {
+ addrHex := addresses[i].Hex()
+ if slices.Contains(existingPrecompiles, addrHex) {
+ return nil, fmt.Errorf("precompile already registered: %s", addrHex)
+ }
+ hexAddresses[i] = addrHex
+ }
+
+ existingLength := len(existingPrecompiles)
+ updatedPrecompiles := make([]string, existingLength+len(hexAddresses))
+ copy(updatedPrecompiles, existingPrecompiles)
+ copy(updatedPrecompiles[existingLength:], hexAddresses)
+
+ utils.SortSlice(updatedPrecompiles)
+ return updatedPrecompiles, nil
+}
+
+// EnableEIPs enables the given EIPs in the EVM parameters.
+func (k Keeper) EnableEIPs(ctx sdk.Context, eips ...string) error {
+ evmParams := k.GetParams(ctx)
+ evmParams.ExtraEIPs = append(evmParams.ExtraEIPs, eips...)
+
+ sort.Slice(evmParams.ExtraEIPs, func(i, j int) bool {
+ return evmParams.ExtraEIPs[i] < evmParams.ExtraEIPs[j]
+ })
+
+ return k.SetParams(ctx, evmParams)
+}
diff --git a/x/evm/keeper/params_benchmark_test.go b/x/evm/keeper/params_benchmark_test.go
new file mode 100644
index 00000000..a93fe2a8
--- /dev/null
+++ b/x/evm/keeper/params_benchmark_test.go
@@ -0,0 +1,30 @@
+package keeper_test
+
+import (
+ "testing"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func BenchmarkSetParams(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ params := types.DefaultParams()
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _ = suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ }
+}
+
+func BenchmarkGetParams(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _ = suite.app.EvmKeeper.GetParams(suite.ctx)
+ }
+}
diff --git a/x/evm/keeper/params_test.go b/x/evm/keeper/params_test.go
new file mode 100644
index 00000000..c894e40a
--- /dev/null
+++ b/x/evm/keeper/params_test.go
@@ -0,0 +1,137 @@
+package keeper_test
+
+import (
+ "reflect"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *KeeperTestSuite) TestParams() {
+ params := types.DefaultParams()
+
+ testCases := []struct {
+ name string
+ paramsFun func() interface{}
+ getFun func() interface{}
+ expected bool
+ }{
+ {
+ "success - Checks if the default params are set correctly",
+ func() interface{} {
+ return types.DefaultParams()
+ },
+ func() interface{} {
+ return suite.app.EvmKeeper.GetParams(suite.ctx)
+ },
+ true,
+ },
+ {
+ "success - EvmDenom param is set to \"inj\" and can be retrieved correctly",
+ func() interface{} {
+ params.EvmDenom = "inj"
+ err := suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ return params.EvmDenom
+ },
+ func() interface{} {
+ evmParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ return evmParams.GetEvmDenom()
+ },
+ true,
+ },
+ {
+ "success - Check Access Control Create param is set to restricted and can be retrieved correctly",
+ func() interface{} {
+ params.AccessControl = types.AccessControl{
+ Create: types.AccessControlType{
+ AccessType: types.AccessTypeRestricted,
+ },
+ }
+ err := suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ return types.AccessTypeRestricted
+ },
+ func() interface{} {
+ evmParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ return evmParams.GetAccessControl().Create.AccessType
+ },
+ true,
+ },
+ {
+ "success - Check Access control param is set to restricted and can be retrieved correctly",
+ func() interface{} {
+ params.AccessControl = types.AccessControl{
+ Call: types.AccessControlType{
+ AccessType: types.AccessTypeRestricted,
+ },
+ }
+ err := suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ return types.AccessTypeRestricted
+ },
+ func() interface{} {
+ evmParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ return evmParams.GetAccessControl().Call.AccessType
+ },
+ true,
+ },
+ {
+ "success - Check AllowUnprotectedTxs param is set to false and can be retrieved correctly",
+ func() interface{} {
+ params.AllowUnprotectedTxs = false
+ err := suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ return params.AllowUnprotectedTxs
+ },
+ func() interface{} {
+ evmParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ return evmParams.GetAllowUnprotectedTxs()
+ },
+ true,
+ },
+ {
+ "success - Check ChainConfig param is set to the default value and can be retrieved correctly",
+ func() interface{} {
+ params.ChainConfig = types.DefaultChainConfig()
+ err := suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ return params.ChainConfig
+ },
+ func() interface{} {
+ evmParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ return evmParams.GetChainConfig()
+ },
+ true,
+ },
+ {
+ name: "success - Active precompiles are sorted when setting params",
+ paramsFun: func() interface{} {
+ params.ActiveStaticPrecompiles = []string{
+ "0x0000000000000000000000000000000000000801",
+ "0x0000000000000000000000000000000000000800",
+ }
+ err := suite.app.EvmKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err, "expected no error when setting params")
+
+ // NOTE: return sorted slice here because the precompiles should be sorted when setting the params
+ return []string{
+ "0x0000000000000000000000000000000000000800",
+ "0x0000000000000000000000000000000000000801",
+ }
+ },
+ getFun: func() interface{} {
+ evmParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ return evmParams.GetActiveStaticPrecompiles()
+ },
+ expected: true,
+ },
+ }
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+
+ outcome := reflect.DeepEqual(tc.paramsFun(), tc.getFun())
+ suite.Require().Equal(tc.expected, outcome)
+ })
+ }
+}
diff --git a/x/evm/keeper/precompiles.go b/x/evm/keeper/precompiles.go
new file mode 100644
index 00000000..b47bd9fa
--- /dev/null
+++ b/x/evm/keeper/precompiles.go
@@ -0,0 +1,65 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package keeper
+
+import (
+ sdktypes "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+type Precompiles struct {
+ Map map[common.Address]vm.PrecompiledContract
+ Addresses []common.Address
+}
+
+// GetPrecompileInstance returns the address and instance of the static or dynamic precompile associated with the
+// given address, or return nil if not found.
+func (k *Keeper) GetPrecompileInstance(
+ ctx sdktypes.Context,
+ address common.Address,
+) (*Precompiles, bool, error) {
+ params := k.GetParams(ctx)
+ // Get the precompile from the static precompiles
+ if precompile, found, err := k.GetStaticPrecompileInstance(¶ms, address); err != nil {
+ return nil, false, err
+ } else if found {
+ addressMap := make(map[common.Address]vm.PrecompiledContract)
+ addressMap[address] = precompile
+ return &Precompiles{
+ Map: addressMap,
+ Addresses: []common.Address{precompile.Address()},
+ }, found, nil
+ }
+
+ // Get the precompile from the dynamic precompiles
+ precompile, found, err := k.erc20Keeper.GetERC20PrecompileInstance(ctx, address)
+ if err != nil || !found {
+ return nil, false, err
+ }
+ addressMap := make(map[common.Address]vm.PrecompiledContract)
+ addressMap[address] = precompile
+ return &Precompiles{
+ Map: addressMap,
+ Addresses: []common.Address{precompile.Address()},
+ }, found, nil
+}
+
+// GetPrecompilesCallHook returns a closure that can be used to instantiate the EVM with a specific
+// precompile instance.
+func (k *Keeper) GetPrecompilesCallHook(ctx sdktypes.Context) types.CallHook {
+ return func(evm *vm.EVM, _ common.Address, recipient common.Address) error {
+ // Check if the recipient is a precompile contract and if so, load the precompile instance
+ precompiles, found, err := k.GetPrecompileInstance(ctx, recipient)
+ if err != nil {
+ return err
+ }
+
+ if found {
+ evm.WithPrecompiles(precompiles.Map, precompiles.Addresses)
+ }
+ return nil
+ }
+}
diff --git a/x/evm/keeper/setup_test.go b/x/evm/keeper/setup_test.go
new file mode 100644
index 00000000..0541386d
--- /dev/null
+++ b/x/evm/keeper/setup_test.go
@@ -0,0 +1,200 @@
+package keeper_test
+
+import (
+ "math"
+ "testing"
+ "time"
+
+ sdkmath "cosmossdk.io/math"
+ "cosmossdk.io/simapp"
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/cometbft/cometbft/crypto/tmhash"
+ tmjson "github.com/cometbft/cometbft/libs/json"
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/codec"
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/crypto/ethsecp256k1"
+ "github.com/evmos/evmos/v19/encoding"
+ "github.com/evmos/evmos/v19/testutil"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
+ "github.com/stretchr/testify/require"
+ "github.com/stretchr/testify/suite"
+)
+
+type KeeperTestSuite struct {
+ suite.Suite
+
+ ctx sdk.Context
+ app *app.Evmos
+ priv cryptotypes.PrivKey
+ queryClient evmtypes.QueryClient
+ address common.Address
+ consAddress sdk.ConsAddress
+
+ // for generate test tx
+ clientCtx client.Context
+ ethSigner ethtypes.Signer
+
+ appCodec codec.Codec
+ signer keyring.Signer
+
+ enableFeemarket bool
+ enableLondonHF bool
+ mintFeeCollector bool
+ denom string
+}
+
+type UnitTestSuite struct {
+ suite.Suite
+}
+
+var s *KeeperTestSuite
+
+func TestKeeperTestSuite(t *testing.T) {
+ s = new(KeeperTestSuite)
+ s.enableFeemarket = false
+ s.enableLondonHF = true
+ suite.Run(t, s)
+
+ // Run UnitTestSuite
+ unitTestSuite := new(UnitTestSuite)
+ suite.Run(t, unitTestSuite)
+}
+
+func (suite *KeeperTestSuite) SetupTest() {
+ checkTx := false
+ chainID := utils.TestnetChainID + "-1"
+ suite.app = app.Setup(checkTx, nil, chainID)
+ suite.SetupApp(checkTx, chainID)
+}
+
+func (suite *KeeperTestSuite) SetupTestWithT(t require.TestingT) {
+ checkTx := false
+ chainID := utils.TestnetChainID + "-1"
+ suite.app = app.Setup(checkTx, nil, chainID)
+ suite.SetupAppWithT(checkTx, t, chainID)
+}
+
+func (suite *KeeperTestSuite) SetupApp(checkTx bool, chainID string) {
+ suite.SetupAppWithT(checkTx, suite.T(), chainID)
+}
+
+// SetupApp setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
+func (suite *KeeperTestSuite) SetupAppWithT(checkTx bool, t require.TestingT, chainID string) {
+ // account key, use a constant account to keep unit test deterministic.
+ ecdsaPriv, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ require.NoError(t, err)
+ priv := ðsecp256k1.PrivKey{
+ Key: crypto.FromECDSA(ecdsaPriv),
+ }
+ suite.priv = priv
+ suite.address = common.BytesToAddress(priv.PubKey().Address().Bytes())
+ suite.signer = utiltx.NewSigner(priv)
+
+ // consensus key
+ priv, err = ethsecp256k1.GenerateKey()
+ require.NoError(t, err)
+ suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())
+
+ suite.app = app.EthSetup(checkTx, func(app *app.Evmos, genesis simapp.GenesisState) simapp.GenesisState {
+ feemarketGenesis := feemarkettypes.DefaultGenesisState()
+ if suite.enableFeemarket {
+ feemarketGenesis.Params.EnableHeight = 1
+ feemarketGenesis.Params.NoBaseFee = false
+ } else {
+ feemarketGenesis.Params.NoBaseFee = true
+ }
+ genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
+ if !suite.enableLondonHF {
+ evmGenesis := evmtypes.DefaultGenesisState()
+ maxInt := sdkmath.NewInt(math.MaxInt64)
+ evmGenesis.Params.ChainConfig.LondonBlock = &maxInt
+ evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
+ evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
+ evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
+ evmGenesis.Params.ChainConfig.ShanghaiBlock = &maxInt
+ evmGenesis.Params.ChainConfig.CancunBlock = &maxInt
+ genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
+ }
+ return genesis
+ })
+
+ if suite.mintFeeCollector {
+ // mint some coin to fee collector
+ coins := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(int64(params.TxGas)-1)))
+ genesisState := app.NewTestGenesisState(suite.app.AppCodec())
+ balances := []banktypes.Balance{
+ {
+ Address: suite.app.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName).String(),
+ Coins: coins,
+ },
+ }
+ var bankGenesis banktypes.GenesisState
+ suite.app.AppCodec().MustUnmarshalJSON(genesisState[banktypes.ModuleName], &bankGenesis)
+ // Update balances and total supply
+ bankGenesis.Balances = append(bankGenesis.Balances, balances...)
+ bankGenesis.Supply = bankGenesis.Supply.Add(coins...)
+ genesisState[banktypes.ModuleName] = suite.app.AppCodec().MustMarshalJSON(&bankGenesis)
+
+ // we marshal the genesisState of all module to a byte array
+ stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
+ require.NoError(t, err)
+
+ // Initialize the chain
+ suite.app.InitChain(
+ abci.RequestInitChain{
+ ChainId: chainID,
+ Validators: []abci.ValidatorUpdate{},
+ ConsensusParams: app.DefaultConsensusParams,
+ AppStateBytes: stateBytes,
+ },
+ )
+ }
+
+ header := testutil.NewHeader(
+ 1, time.Now().UTC(), chainID, suite.consAddress,
+ tmhash.Sum([]byte("app")), tmhash.Sum([]byte("validators")),
+ )
+ suite.ctx = suite.app.NewContext(checkTx, header)
+
+ queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
+ evmtypes.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
+ suite.queryClient = evmtypes.NewQueryClient(queryHelper)
+
+ acc := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0)
+ suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
+
+ valAddr := sdk.ValAddress(suite.address.Bytes())
+ validator, err := stakingtypes.NewValidator(valAddr, priv.PubKey(), stakingtypes.Description{})
+ require.NoError(t, err)
+ err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
+ require.NoError(t, err)
+ err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
+ require.NoError(t, err)
+ suite.app.StakingKeeper.SetValidator(suite.ctx, validator)
+
+ stakingParams := stakingtypes.DefaultParams()
+ stakingParams.BondDenom = utils.BaseDenom
+ err = suite.app.StakingKeeper.SetParams(suite.ctx, stakingParams)
+ require.NoError(t, err)
+
+ encodingConfig := encoding.MakeConfig(app.ModuleBasics)
+ suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
+ suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+ suite.appCodec = encodingConfig.Codec
+ suite.denom = evmtypes.DefaultEVMDenom
+}
diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go
new file mode 100644
index 00000000..80d0e62b
--- /dev/null
+++ b/x/evm/keeper/state_transition.go
@@ -0,0 +1,382 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ tmtypes "github.com/cometbft/cometbft/types"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ evmostypes "github.com/evmos/evmos/v19/types"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ evmoscore "github.com/evmos/evmos/v19/x/evm/core/core"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// NewEVM generates a go-ethereum VM from the provided Message fields and the chain parameters
+// (ChainConfig and module Params). It additionally sets the validator operator address as the
+// coinbase address to make it available for the COINBASE opcode, even though there is no
+// beneficiary of the coinbase transaction (since we're not mining).
+//
+// NOTE: the RANDOM opcode is currently not supported since it requires
+// RANDAO implementation. See https://github.com/evmos/ethermint/pull/1520#pullrequestreview-1200504697
+// for more information.
+
+func (k *Keeper) NewEVM(
+ ctx sdk.Context,
+ msg core.Message,
+ cfg *statedb.EVMConfig,
+ tracer vm.EVMLogger,
+ stateDB vm.StateDB,
+) *vm.EVM {
+ blockCtx := vm.BlockContext{
+ CanTransfer: evmoscore.CanTransfer,
+ Transfer: evmoscore.Transfer,
+ GetHash: k.GetHashFn(ctx),
+ Coinbase: cfg.CoinBase,
+ GasLimit: evmostypes.BlockGasLimit(ctx),
+ BlockNumber: big.NewInt(ctx.BlockHeight()),
+ Time: big.NewInt(ctx.BlockHeader().Time.Unix()),
+ Difficulty: big.NewInt(0), // unused. Only required in PoW context
+ BaseFee: cfg.BaseFee,
+ Random: nil, // not supported
+ }
+
+ txCtx := evmoscore.NewEVMTxContext(msg)
+ if tracer == nil {
+ tracer = k.Tracer(ctx, msg, cfg.ChainConfig)
+ }
+ vmConfig := k.VMConfig(ctx, msg, cfg, tracer)
+
+ signer := msg.From()
+ accessControl := types.NewRestrictedPermissionPolicy(&cfg.Params.AccessControl, signer)
+
+ // Set hooks for the EVM opcodes
+ evmHooks := types.NewDefaultOpCodesHooks()
+ evmHooks.AddCreateHooks(
+ accessControl.GetCreateHook(signer),
+ )
+ evmHooks.AddCallHooks(
+ accessControl.GetCallHook(signer),
+ k.GetPrecompilesCallHook(ctx),
+ )
+ return vm.NewEVMWithHooks(evmHooks, blockCtx, txCtx, stateDB, cfg.ChainConfig, vmConfig)
+}
+
+// GetHashFn implements vm.GetHashFunc for Ethermint. It handles 3 cases:
+// 1. The requested height matches the current height from context (and thus same epoch number)
+// 2. The requested height is from an previous height from the same chain epoch
+// 3. The requested height is from a height greater than the latest one
+func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc {
+ return func(height uint64) common.Hash {
+ h, err := evmostypes.SafeInt64(height)
+ if err != nil {
+ k.Logger(ctx).Error("failed to cast height to int64", "error", err)
+ return common.Hash{}
+ }
+
+ switch {
+ case ctx.BlockHeight() == h:
+ // Case 1: The requested height matches the one from the context so we can retrieve the header
+ // hash directly from the context.
+ // Note: The headerHash is only set at begin block, it will be nil in case of a query context
+ headerHash := ctx.HeaderHash()
+ if len(headerHash) != 0 {
+ return common.BytesToHash(headerHash)
+ }
+
+ // only recompute the hash if not set (eg: checkTxState)
+ contextBlockHeader := ctx.BlockHeader()
+ header, err := tmtypes.HeaderFromProto(&contextBlockHeader)
+ if err != nil {
+ k.Logger(ctx).Error("failed to cast tendermint header from proto", "error", err)
+ return common.Hash{}
+ }
+
+ headerHash = header.Hash()
+ return common.BytesToHash(headerHash)
+
+ case ctx.BlockHeight() > h:
+ // Case 2: if the chain is not the current height we need to retrieve the hash from the store for the
+ // current chain epoch. This only applies if the current height is greater than the requested height.
+ histInfo, found := k.stakingKeeper.GetHistoricalInfo(ctx, h)
+ if !found {
+ k.Logger(ctx).Debug("historical info not found", "height", h)
+ return common.Hash{}
+ }
+
+ header, err := tmtypes.HeaderFromProto(&histInfo.Header)
+ if err != nil {
+ k.Logger(ctx).Error("failed to cast tendermint header from proto", "error", err)
+ return common.Hash{}
+ }
+
+ return common.BytesToHash(header.Hash())
+ default:
+ // Case 3: heights greater than the current one returns an empty hash.
+ return common.Hash{}
+ }
+ }
+}
+
+// ApplyTransaction runs and attempts to perform a state transition with the given transaction (i.e Message), that will
+// only be persisted (committed) to the underlying KVStore if the transaction does not fail.
+//
+// # Gas tracking
+//
+// Ethereum consumes gas according to the EVM opcodes instead of general reads and writes to store. Because of this, the
+// state transition needs to ignore the SDK gas consumption mechanism defined by the GasKVStore and instead consume the
+// amount of gas used by the VM execution. The amount of gas used is tracked by the EVM and returned in the execution
+// result.
+//
+// Prior to the execution, the starting tx gas meter is saved and replaced with an infinite gas meter in a new context
+// in order to ignore the SDK gas consumption config values (read, write, has, delete).
+// After the execution, the gas used from the message execution will be added to the starting gas consumed, taking into
+// consideration the amount of gas returned. Finally, the context is updated with the EVM gas consumed value prior to
+// returning.
+//
+// For relevant discussion see: https://github.com/cosmos/cosmos-sdk/discussions/9072
+func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*types.MsgEthereumTxResponse, error) {
+ var bloom *big.Int
+
+ cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress), k.eip155ChainID)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to load evm config")
+ }
+ txConfig := k.TxConfig(ctx, tx.Hash())
+
+ // get the signer according to the chain rules from the config and block height
+ signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
+ msg, err := tx.AsMessage(signer, cfg.BaseFee)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to return ethereum transaction as core message")
+ }
+
+ // Create a cache context to revert state. The cache context is only committed when both tx and hooks executed successfully.
+ // Didn't use `Snapshot` because the context stack has exponential complexity on certain operations,
+ // thus restricted to be used only inside `ApplyMessage`.
+ tmpCtx, commit := ctx.CacheContext()
+
+ // pass true to commit the StateDB
+ res, err := k.ApplyMessageWithConfig(tmpCtx, msg, nil, true, cfg, txConfig)
+ if err != nil {
+ // when a transaction contains multiple msg, as long as one of the msg fails
+ // all gas will be deducted. so is not msg.Gas()
+ k.ResetGasMeterAndConsumeGas(tmpCtx, tmpCtx.GasMeter().Limit())
+ return nil, errorsmod.Wrap(err, "failed to apply ethereum core message")
+ }
+
+ logs := types.LogsToEthereum(res.Logs)
+
+ // Compute block bloom filter
+ if len(logs) > 0 {
+ bloom = k.GetBlockBloomTransient(ctx)
+ bloom.Or(bloom, big.NewInt(0).SetBytes(ethtypes.LogsBloom(logs)))
+ }
+
+ if !res.Failed() {
+ commit()
+ }
+
+ // refund gas in order to match the Ethereum gas consumption instead of the default SDK one.
+ if err = k.RefundGas(ctx, msg, msg.Gas()-res.GasUsed, cfg.Params.EvmDenom); err != nil {
+ return nil, errorsmod.Wrapf(err, "failed to refund gas leftover gas to sender %s", msg.From())
+ }
+
+ if len(logs) > 0 {
+ // Update transient block bloom filter
+ k.SetBlockBloomTransient(ctx, bloom)
+ k.SetLogSizeTransient(ctx, uint64(txConfig.LogIndex)+uint64(len(logs)))
+ }
+
+ k.SetTxIndexTransient(ctx, uint64(txConfig.TxIndex)+1)
+
+ totalGasUsed, err := k.AddTransientGasUsed(ctx, res.GasUsed)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to add transient gas used")
+ }
+
+ // reset the gas meter for current cosmos transaction
+ k.ResetGasMeterAndConsumeGas(ctx, totalGasUsed)
+ return res, nil
+}
+
+// ApplyMessage calls ApplyMessageWithConfig with an empty TxConfig.
+func (k *Keeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool) (*types.MsgEthereumTxResponse, error) {
+ cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress), k.eip155ChainID)
+ if err != nil {
+ return nil, errorsmod.Wrap(err, "failed to load evm config")
+ }
+
+ txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))
+ return k.ApplyMessageWithConfig(ctx, msg, tracer, commit, cfg, txConfig)
+}
+
+// ApplyMessageWithConfig computes the new state by applying the given message against the existing state.
+// If the message fails, the VM execution error with the reason will be returned to the client
+// and the transaction won't be committed to the store.
+//
+// # Reverted state
+//
+// The snapshot and rollback are supported by the `statedb.StateDB`.
+//
+// # Different Callers
+//
+// It's called in three scenarios:
+// 1. `ApplyTransaction`, in the transaction processing flow.
+// 2. `EthCall/EthEstimateGas` grpc query handler.
+// 3. Called by other native modules directly.
+//
+// # Prechecks and Preprocessing
+//
+// All relevant state transition prechecks for the MsgEthereumTx are performed on the AnteHandler,
+// prior to running the transaction against the state. The prechecks run are the following:
+//
+// 1. the nonce of the message caller is correct
+// 2. caller has enough balance to cover transaction fee(gaslimit * gasprice)
+// 3. the amount of gas required is available in the block
+// 4. the purchased gas is enough to cover intrinsic usage
+// 5. there is no overflow when calculating intrinsic gas
+// 6. caller has enough balance to cover asset transfer for **topmost** call
+//
+// The preprocessing steps performed by the AnteHandler are:
+//
+// 1. set up the initial access list (iff fork > Berlin)
+//
+// # Tracer parameter
+//
+// It should be a `vm.Tracer` object or nil, if pass `nil`, it'll create a default one based on keeper options.
+//
+// # Commit parameter
+//
+// If commit is true, the `StateDB` will be committed, otherwise discarded.
+func (k *Keeper) ApplyMessageWithConfig(
+ ctx sdk.Context,
+ msg core.Message,
+ tracer vm.EVMLogger,
+ commit bool,
+ cfg *statedb.EVMConfig,
+ txConfig statedb.TxConfig,
+) (*types.MsgEthereumTxResponse, error) {
+ var (
+ ret []byte // return bytes from evm execution
+ vmErr error // vm errors do not effect consensus and are therefore not assigned to err
+ )
+
+ stateDB := statedb.New(ctx, k, txConfig)
+ evm := k.NewEVM(ctx, msg, cfg, tracer, stateDB)
+
+ leftoverGas := msg.Gas()
+
+ // Allow the tracer captures the tx level events, mainly the gas consumption.
+ vmCfg := evm.Config
+ if vmCfg.Debug {
+ vmCfg.Tracer.CaptureTxStart(leftoverGas)
+ defer func() {
+ vmCfg.Tracer.CaptureTxEnd(leftoverGas)
+ }()
+ }
+
+ sender := vm.AccountRef(msg.From())
+ contractCreation := msg.To() == nil
+ isLondon := cfg.ChainConfig.IsLondon(evm.Context.BlockNumber)
+
+ intrinsicGas, err := k.GetEthIntrinsicGas(ctx, msg, cfg.ChainConfig, contractCreation)
+ if err != nil {
+ // should have already been checked on Ante Handler
+ return nil, errorsmod.Wrap(err, "intrinsic gas failed")
+ }
+
+ // Should check again even if it is checked on Ante Handler, because eth_call don't go through Ante Handler.
+ if leftoverGas < intrinsicGas {
+ // eth_estimateGas will check for this exact error
+ return nil, errorsmod.Wrap(core.ErrIntrinsicGas, "apply message")
+ }
+ leftoverGas -= intrinsicGas
+
+ // access list preparation is moved from ante handler to here, because it's needed when `ApplyMessage` is called
+ // under contexts where ante handlers are not run, for example `eth_call` and `eth_estimateGas`.
+ if rules := cfg.ChainConfig.Rules(big.NewInt(ctx.BlockHeight()), cfg.ChainConfig.MergeNetsplitBlock != nil); rules.IsBerlin {
+ stateDB.PrepareAccessList(msg.From(), msg.To(), evm.ActivePrecompiles(rules), msg.AccessList())
+ }
+
+ if contractCreation {
+ // take over the nonce management from evm:
+ // - reset sender's nonce to msg.Nonce() before calling evm.
+ // - increase sender's nonce by one no matter the result.
+ stateDB.SetNonce(sender.Address(), msg.Nonce())
+ ret, _, leftoverGas, vmErr = evm.Create(sender, msg.Data(), leftoverGas, msg.Value())
+ stateDB.SetNonce(sender.Address(), msg.Nonce()+1)
+ } else {
+ ret, leftoverGas, vmErr = evm.Call(sender, *msg.To(), msg.Data(), leftoverGas, msg.Value())
+ }
+
+ refundQuotient := params.RefundQuotient
+
+ // After EIP-3529: refunds are capped to gasUsed / 5
+ if isLondon {
+ refundQuotient = params.RefundQuotientEIP3529
+ }
+
+ // calculate gas refund
+ if msg.Gas() < leftoverGas {
+ return nil, errorsmod.Wrap(types.ErrGasOverflow, "apply message")
+ }
+ // refund gas
+ temporaryGasUsed := msg.Gas() - leftoverGas
+ refund := GasToRefund(stateDB.GetRefund(), temporaryGasUsed, refundQuotient)
+
+ // update leftoverGas and temporaryGasUsed with refund amount
+ leftoverGas += refund
+ temporaryGasUsed -= refund
+
+ // EVM execution error needs to be available for the JSON-RPC client
+ var vmError string
+ if vmErr != nil {
+ vmError = vmErr.Error()
+ }
+
+ // The dirty states in `StateDB` is either committed or discarded after return
+ if commit {
+ if err := stateDB.Commit(); err != nil {
+ return nil, errorsmod.Wrap(err, "failed to commit stateDB")
+ }
+ }
+
+ // calculate a minimum amount of gas to be charged to sender if GasLimit
+ // is considerably higher than GasUsed to stay more aligned with Tendermint gas mechanics
+ // for more info https://github.com/evmos/ethermint/issues/1085
+ gasLimit := math.LegacyNewDec(int64(msg.Gas()))
+ minGasMultiplier := k.GetMinGasMultiplier(ctx)
+ minimumGasUsed := gasLimit.Mul(minGasMultiplier)
+
+ if !minimumGasUsed.TruncateInt().IsUint64() {
+ return nil, errorsmod.Wrapf(types.ErrGasOverflow, "minimumGasUsed(%s) is not a uint64", minimumGasUsed.TruncateInt().String())
+ }
+
+ if msg.Gas() < leftoverGas {
+ return nil, errorsmod.Wrapf(types.ErrGasOverflow, "message gas limit < leftover gas (%d < %d)", msg.Gas(), leftoverGas)
+ }
+
+ gasUsed := math.LegacyMaxDec(minimumGasUsed, math.LegacyNewDec(int64(temporaryGasUsed))).TruncateInt().Uint64()
+ // reset leftoverGas, to be used by the tracer
+ leftoverGas = msg.Gas() - gasUsed
+
+ return &types.MsgEthereumTxResponse{
+ GasUsed: gasUsed,
+ VmError: vmError,
+ Ret: ret,
+ Logs: types.NewLogsFromEth(stateDB.Logs()),
+ Hash: txConfig.TxHash.Hex(),
+ }, nil
+}
diff --git a/x/evm/keeper/state_transition_benchmark_test.go b/x/evm/keeper/state_transition_benchmark_test.go
new file mode 100644
index 00000000..4a46db8b
--- /dev/null
+++ b/x/evm/keeper/state_transition_benchmark_test.go
@@ -0,0 +1,346 @@
+package keeper_test
+
+import (
+ "errors"
+ "math/big"
+ "testing"
+
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ "github.com/stretchr/testify/require"
+)
+
+var templateAccessListTx = ðtypes.AccessListTx{
+ GasPrice: big.NewInt(1),
+ Gas: 21000,
+ To: &common.Address{},
+ Value: big.NewInt(0),
+ Data: []byte{},
+}
+
+var templateLegacyTx = ðtypes.LegacyTx{
+ GasPrice: big.NewInt(1),
+ Gas: 21000,
+ To: &common.Address{},
+ Value: big.NewInt(0),
+ Data: []byte{},
+}
+
+var templateDynamicFeeTx = ðtypes.DynamicFeeTx{
+ GasFeeCap: big.NewInt(10),
+ GasTipCap: big.NewInt(2),
+ Gas: 21000,
+ To: &common.Address{},
+ Value: big.NewInt(0),
+ Data: []byte{},
+}
+
+func newSignedEthTx(
+ txData ethtypes.TxData,
+ nonce uint64,
+ addr sdk.Address,
+ krSigner keyring.Signer,
+ ethSigner ethtypes.Signer,
+) (*ethtypes.Transaction, error) {
+ var ethTx *ethtypes.Transaction
+ switch txData := txData.(type) {
+ case *ethtypes.AccessListTx:
+ txData.Nonce = nonce
+ ethTx = ethtypes.NewTx(txData)
+ case *ethtypes.LegacyTx:
+ txData.Nonce = nonce
+ ethTx = ethtypes.NewTx(txData)
+ case *ethtypes.DynamicFeeTx:
+ txData.Nonce = nonce
+ ethTx = ethtypes.NewTx(txData)
+ default:
+ return nil, errors.New("unknown transaction type")
+ }
+
+ sig, _, err := krSigner.SignByAddress(addr, ethTx.Hash().Bytes())
+ if err != nil {
+ return nil, err
+ }
+
+ ethTx, err = ethTx.WithSignature(ethSigner, sig)
+ if err != nil {
+ return nil, err
+ }
+
+ return ethTx, nil
+}
+
+func newEthMsgTx(
+ nonce uint64,
+ address common.Address,
+ krSigner keyring.Signer,
+ ethSigner ethtypes.Signer,
+ txType byte,
+ data []byte,
+ accessList ethtypes.AccessList,
+) (*evmtypes.MsgEthereumTx, *big.Int, error) {
+ var (
+ ethTx *ethtypes.Transaction
+ baseFee *big.Int
+ )
+ switch txType {
+ case ethtypes.LegacyTxType:
+ templateLegacyTx.Nonce = nonce
+ if data != nil {
+ templateLegacyTx.Data = data
+ }
+ ethTx = ethtypes.NewTx(templateLegacyTx)
+ case ethtypes.AccessListTxType:
+ templateAccessListTx.Nonce = nonce
+ if data != nil {
+ templateAccessListTx.Data = data
+ } else {
+ templateAccessListTx.Data = []byte{}
+ }
+
+ templateAccessListTx.AccessList = accessList
+ ethTx = ethtypes.NewTx(templateAccessListTx)
+ case ethtypes.DynamicFeeTxType:
+ templateDynamicFeeTx.Nonce = nonce
+
+ if data != nil {
+ templateAccessListTx.Data = data
+ } else {
+ templateAccessListTx.Data = []byte{}
+ }
+ templateAccessListTx.AccessList = accessList
+ ethTx = ethtypes.NewTx(templateDynamicFeeTx)
+ baseFee = big.NewInt(3)
+ default:
+ return nil, baseFee, errors.New("unsupported tx type")
+ }
+
+ msg := &evmtypes.MsgEthereumTx{}
+ err := msg.FromEthereumTx(ethTx)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ msg.From = address.Hex()
+
+ return msg, baseFee, msg.Sign(ethSigner, krSigner)
+}
+
+func newNativeMessage(
+ nonce uint64,
+ blockHeight int64,
+ address common.Address,
+ cfg *params.ChainConfig,
+ krSigner keyring.Signer,
+ ethSigner ethtypes.Signer,
+ txType byte,
+ data []byte,
+ accessList ethtypes.AccessList,
+) (core.Message, error) {
+ msgSigner := ethtypes.MakeSigner(cfg, big.NewInt(blockHeight))
+
+ msg, baseFee, err := newEthMsgTx(nonce, address, krSigner, ethSigner, txType, data, accessList)
+ if err != nil {
+ return nil, err
+ }
+
+ m, err := msg.AsMessage(msgSigner, baseFee)
+ if err != nil {
+ return nil, err
+ }
+
+ return m, nil
+}
+
+func BenchmarkApplyTransaction(b *testing.B) {
+ suite := KeeperTestSuite{enableLondonHF: true}
+ suite.SetupTestWithT(b)
+
+ ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ tx, err := newSignedEthTx(templateAccessListTx,
+ suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address),
+ sdk.AccAddress(suite.address.Bytes()),
+ suite.signer,
+ ethSigner,
+ )
+ require.NoError(b, err)
+
+ b.StartTimer()
+ resp, err := suite.app.EvmKeeper.ApplyTransaction(suite.ctx, tx)
+ b.StopTimer()
+
+ require.NoError(b, err)
+ require.False(b, resp.Failed())
+ }
+}
+
+func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) {
+ suite := KeeperTestSuite{enableLondonHF: true}
+ suite.SetupTestWithT(b)
+
+ ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ tx, err := newSignedEthTx(templateLegacyTx,
+ suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address),
+ sdk.AccAddress(suite.address.Bytes()),
+ suite.signer,
+ ethSigner,
+ )
+ require.NoError(b, err)
+
+ b.StartTimer()
+ resp, err := suite.app.EvmKeeper.ApplyTransaction(suite.ctx, tx)
+ b.StopTimer()
+
+ require.NoError(b, err)
+ require.False(b, resp.Failed())
+ }
+}
+
+func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) {
+ suite := KeeperTestSuite{enableFeemarket: true, enableLondonHF: true}
+ suite.SetupTestWithT(b)
+
+ ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ tx, err := newSignedEthTx(templateDynamicFeeTx,
+ suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address),
+ sdk.AccAddress(suite.address.Bytes()),
+ suite.signer,
+ ethSigner,
+ )
+ require.NoError(b, err)
+
+ b.StartTimer()
+ resp, err := suite.app.EvmKeeper.ApplyTransaction(suite.ctx, tx)
+ b.StopTimer()
+
+ require.NoError(b, err)
+ require.False(b, resp.Failed())
+ }
+}
+
+//nolint:all
+func BenchmarkApplyMessage(b *testing.B) {
+ suite := KeeperTestSuite{enableLondonHF: true}
+ suite.SetupTestWithT(b)
+
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+
+ m, err := newNativeMessage(
+ suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ ethCfg,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ nil,
+ nil,
+ )
+ require.NoError(b, err)
+
+ b.StartTimer()
+ resp, err := suite.app.EvmKeeper.ApplyMessage(suite.ctx, m, nil, true)
+ b.StopTimer()
+
+ require.NoError(b, err)
+ require.False(b, resp.Failed())
+ }
+}
+
+//nolint:all
+func BenchmarkApplyMessageWithLegacyTx(b *testing.B) {
+ suite := KeeperTestSuite{enableLondonHF: true}
+ suite.SetupTestWithT(b)
+
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+
+ m, err := newNativeMessage(
+ suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ ethCfg,
+ suite.signer,
+ signer,
+ ethtypes.LegacyTxType,
+ nil,
+ nil,
+ )
+ require.NoError(b, err)
+
+ b.StartTimer()
+ resp, err := suite.app.EvmKeeper.ApplyMessage(suite.ctx, m, nil, true)
+ b.StopTimer()
+
+ require.NoError(b, err)
+ require.False(b, resp.Failed())
+ }
+}
+
+func BenchmarkApplyMessageWithDynamicFeeTx(b *testing.B) {
+ suite := KeeperTestSuite{enableFeemarket: true, enableLondonHF: true}
+ suite.SetupTestWithT(b)
+
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+
+ m, err := newNativeMessage(
+ suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ ethCfg,
+ suite.signer,
+ signer,
+ ethtypes.DynamicFeeTxType,
+ nil,
+ nil,
+ )
+ require.NoError(b, err)
+
+ b.StartTimer()
+ resp, err := suite.app.EvmKeeper.ApplyMessage(suite.ctx, m, nil, true)
+ b.StopTimer()
+
+ require.NoError(b, err)
+ require.False(b, resp.Failed())
+ }
+}
diff --git a/x/evm/keeper/state_transition_test.go b/x/evm/keeper/state_transition_test.go
new file mode 100644
index 00000000..b9a7975b
--- /dev/null
+++ b/x/evm/keeper/state_transition_test.go
@@ -0,0 +1,765 @@
+package keeper_test
+
+import (
+ "fmt"
+ "math"
+ "math/big"
+
+ sdkmath "cosmossdk.io/math"
+ "github.com/cometbft/cometbft/crypto/tmhash"
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+ tmtypes "github.com/cometbft/cometbft/types"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/evm/keeper"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *KeeperTestSuite) TestGetHashFn() {
+ header := suite.ctx.BlockHeader()
+ h, _ := tmtypes.HeaderFromProto(&header)
+ hash := h.Hash()
+
+ testCases := []struct {
+ msg string
+ height uint64
+ malleate func()
+ expHash common.Hash
+ }{
+ {
+ "case 1.1: context hash cached",
+ uint64(suite.ctx.BlockHeight()),
+ func() {
+ suite.ctx = suite.ctx.WithHeaderHash(tmhash.Sum([]byte("header")))
+ },
+ common.BytesToHash(tmhash.Sum([]byte("header"))),
+ },
+ {
+ "case 1.2: failed to cast Tendermint header",
+ uint64(suite.ctx.BlockHeight()),
+ func() {
+ header := tmproto.Header{}
+ header.Height = suite.ctx.BlockHeight()
+ suite.ctx = suite.ctx.WithBlockHeader(header)
+ },
+ common.Hash{},
+ },
+ {
+ "case 1.3: hash calculated from Tendermint header",
+ uint64(suite.ctx.BlockHeight()),
+ func() {
+ suite.ctx = suite.ctx.WithBlockHeader(header)
+ },
+ common.BytesToHash(hash),
+ },
+ {
+ "case 2.1: height lower than current one, hist info not found",
+ 1,
+ func() {
+ suite.ctx = suite.ctx.WithBlockHeight(10)
+ },
+ common.Hash{},
+ },
+ {
+ "case 2.2: height lower than current one, invalid hist info header",
+ 1,
+ func() {
+ suite.app.StakingKeeper.SetHistoricalInfo(suite.ctx, 1, &stakingtypes.HistoricalInfo{})
+ suite.ctx = suite.ctx.WithBlockHeight(10)
+ },
+ common.Hash{},
+ },
+ {
+ "case 2.3: height lower than current one, calculated from hist info header",
+ 1,
+ func() {
+ histInfo := &stakingtypes.HistoricalInfo{
+ Header: header,
+ }
+ suite.app.StakingKeeper.SetHistoricalInfo(suite.ctx, 1, histInfo)
+ suite.ctx = suite.ctx.WithBlockHeight(10)
+ },
+ common.BytesToHash(hash),
+ },
+ {
+ "case 3: height greater than current one",
+ 200,
+ func() {},
+ common.Hash{},
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ tc.malleate()
+
+ hash := suite.app.EvmKeeper.GetHashFn(suite.ctx)(tc.height)
+ suite.Require().Equal(tc.expHash, hash)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestGetCoinbaseAddress() {
+ valOpAddr := utiltx.GenerateAddress()
+
+ testCases := []struct {
+ msg string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "validator not found",
+ func() {
+ header := suite.ctx.BlockHeader()
+ header.ProposerAddress = []byte{}
+ suite.ctx = suite.ctx.WithBlockHeader(header)
+ },
+ false,
+ },
+ {
+ "success",
+ func() {
+ valConsAddr, privkey := utiltx.NewAddrKey()
+
+ pkAny, err := codectypes.NewAnyWithValue(privkey.PubKey())
+ suite.Require().NoError(err)
+
+ validator := stakingtypes.Validator{
+ OperatorAddress: sdk.ValAddress(valOpAddr.Bytes()).String(),
+ ConsensusPubkey: pkAny,
+ }
+
+ suite.app.StakingKeeper.SetValidator(suite.ctx, validator)
+ err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
+ suite.Require().NoError(err)
+
+ header := suite.ctx.BlockHeader()
+ header.ProposerAddress = valConsAddr.Bytes()
+ suite.ctx = suite.ctx.WithBlockHeader(header)
+
+ _, found := suite.app.StakingKeeper.GetValidatorByConsAddr(suite.ctx, valConsAddr.Bytes())
+ suite.Require().True(found)
+
+ suite.Require().NotEmpty(suite.ctx.BlockHeader().ProposerAddress)
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.SetupTest() // reset
+
+ tc.malleate()
+ proposerAddress := suite.ctx.BlockHeader().ProposerAddress
+ coinbase, err := suite.app.EvmKeeper.GetCoinbaseAddress(suite.ctx, sdk.ConsAddress(proposerAddress))
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().Equal(valOpAddr, coinbase)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestGetEthIntrinsicGas() {
+ testCases := []struct {
+ name string
+ data []byte
+ accessList ethtypes.AccessList
+ height int64
+ isContractCreation bool
+ noError bool
+ expGas uint64
+ }{
+ {
+ "no data, no accesslist, not contract creation, not homestead, not istanbul",
+ nil,
+ nil,
+ 1,
+ false,
+ true,
+ params.TxGas,
+ },
+ {
+ "with one zero data, no accesslist, not contract creation, not homestead, not istanbul",
+ []byte{0},
+ nil,
+ 1,
+ false,
+ true,
+ params.TxGas + params.TxDataZeroGas*1,
+ },
+ {
+ "with one non zero data, no accesslist, not contract creation, not homestead, not istanbul",
+ []byte{1},
+ nil,
+ 1,
+ true,
+ true,
+ params.TxGas + params.TxDataNonZeroGasFrontier*1,
+ },
+ {
+ "no data, one accesslist, not contract creation, not homestead, not istanbul",
+ nil,
+ []ethtypes.AccessTuple{
+ {},
+ },
+ 1,
+ false,
+ true,
+ params.TxGas + params.TxAccessListAddressGas,
+ },
+ {
+ "no data, one accesslist with one storageKey, not contract creation, not homestead, not istanbul",
+ nil,
+ []ethtypes.AccessTuple{
+ {StorageKeys: make([]common.Hash, 1)},
+ },
+ 1,
+ false,
+ true,
+ params.TxGas + params.TxAccessListAddressGas + params.TxAccessListStorageKeyGas*1,
+ },
+ {
+ "no data, no accesslist, is contract creation, is homestead, not istanbul",
+ nil,
+ nil,
+ 2,
+ true,
+ true,
+ params.TxGasContractCreation,
+ },
+ {
+ "with one zero data, no accesslist, not contract creation, is homestead, is istanbul",
+ []byte{1},
+ nil,
+ 3,
+ false,
+ true,
+ params.TxGas + params.TxDataNonZeroGasEIP2028*1,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.SetupTest() // reset
+
+ params := suite.app.EvmKeeper.GetParams(suite.ctx)
+ ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ ethCfg.HomesteadBlock = big.NewInt(2)
+ ethCfg.IstanbulBlock = big.NewInt(3)
+ signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+
+ suite.ctx = suite.ctx.WithBlockHeight(tc.height)
+
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+ m, err := newNativeMessage(
+ nonce,
+ suite.ctx.BlockHeight(),
+ suite.address,
+ ethCfg,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ tc.data,
+ tc.accessList,
+ )
+ suite.Require().NoError(err)
+
+ gas, err := suite.app.EvmKeeper.GetEthIntrinsicGas(suite.ctx, m, ethCfg, tc.isContractCreation)
+ if tc.noError {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+
+ suite.Require().Equal(tc.expGas, gas)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestGasToRefund() {
+ testCases := []struct {
+ name string
+ gasconsumed uint64
+ refundQuotient uint64
+ expGasRefund uint64
+ expPanic bool
+ }{
+ {
+ "gas refund 5",
+ 5,
+ 1,
+ 5,
+ false,
+ },
+ {
+ "gas refund 10",
+ 10,
+ 1,
+ 10,
+ false,
+ },
+ {
+ "gas refund availableRefund",
+ 11,
+ 1,
+ 10,
+ false,
+ },
+ {
+ "gas refund quotient 0",
+ 11,
+ 0,
+ 0,
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.mintFeeCollector = true
+ suite.SetupTest() // reset
+ vmdb := suite.StateDB()
+ vmdb.AddRefund(10)
+
+ if tc.expPanic {
+ panicF := func() {
+ //nolint:staticcheck
+ keeper.GasToRefund(vmdb.GetRefund(), tc.gasconsumed, tc.refundQuotient)
+ }
+ suite.Require().Panics(panicF)
+ } else {
+ gr := keeper.GasToRefund(vmdb.GetRefund(), tc.gasconsumed, tc.refundQuotient)
+ suite.Require().Equal(tc.expGasRefund, gr)
+ }
+ })
+ }
+ suite.mintFeeCollector = false
+}
+
+func (suite *KeeperTestSuite) TestRefundGas() {
+ var (
+ m core.Message
+ err error
+ )
+
+ testCases := []struct {
+ name string
+ leftoverGas uint64
+ refundQuotient uint64
+ noError bool
+ expGasRefund uint64
+ malleate func()
+ }{
+ {
+ name: "leftoverGas more than tx gas limit",
+ leftoverGas: params.TxGas + 1,
+ refundQuotient: params.RefundQuotient,
+ noError: false,
+ expGasRefund: params.TxGas + 1,
+ },
+ {
+ name: "leftoverGas equal to tx gas limit, insufficient fee collector account",
+ leftoverGas: params.TxGas,
+ refundQuotient: params.RefundQuotient,
+ noError: true,
+ expGasRefund: 0,
+ },
+ {
+ name: "leftoverGas less than to tx gas limit",
+ leftoverGas: params.TxGas - 1,
+ refundQuotient: params.RefundQuotient,
+ noError: true,
+ expGasRefund: 0,
+ },
+ {
+ name: "no leftoverGas, refund half used gas ",
+ leftoverGas: 0,
+ refundQuotient: params.RefundQuotient,
+ noError: true,
+ expGasRefund: params.TxGas / params.RefundQuotient,
+ },
+ {
+ name: "invalid Gas value in msg",
+ leftoverGas: 0,
+ refundQuotient: params.RefundQuotient,
+ noError: false,
+ expGasRefund: params.TxGas,
+ malleate: func() {
+ keeperParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ m, err = suite.createContractGethMsg(
+ suite.StateDB().GetNonce(suite.address),
+ ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()),
+ keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID()),
+ big.NewInt(-100),
+ )
+ suite.Require().NoError(err)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.mintFeeCollector = true
+ suite.SetupTest() // reset
+
+ keeperParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ ethCfg := keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+ vmdb := suite.StateDB()
+
+ m, err = newNativeMessage(
+ vmdb.GetNonce(suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ ethCfg,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ nil,
+ nil,
+ )
+ suite.Require().NoError(err)
+
+ vmdb.AddRefund(params.TxGas)
+
+ if tc.leftoverGas > m.Gas() {
+ return
+ }
+
+ if tc.malleate != nil {
+ tc.malleate()
+ }
+
+ gasUsed := m.Gas() - tc.leftoverGas
+ refund := keeper.GasToRefund(vmdb.GetRefund(), gasUsed, tc.refundQuotient)
+ suite.Require().Equal(tc.expGasRefund, refund)
+
+ err = suite.app.EvmKeeper.RefundGas(suite.ctx, m, refund, evmtypes.DefaultEVMDenom)
+ if tc.noError {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ suite.mintFeeCollector = false
+}
+
+func (suite *KeeperTestSuite) TestResetGasMeterAndConsumeGas() {
+ testCases := []struct {
+ name string
+ gasConsumed uint64
+ gasUsed uint64
+ expPanic bool
+ }{
+ {
+ "gas consumed 5, used 5",
+ 5,
+ 5,
+ false,
+ },
+ {
+ "gas consumed 5, used 10",
+ 5,
+ 10,
+ false,
+ },
+ {
+ "gas consumed 10, used 10",
+ 10,
+ 10,
+ false,
+ },
+ {
+ "gas consumed 11, used 10, NegativeGasConsumed panic",
+ 11,
+ 10,
+ true,
+ },
+ {
+ "gas consumed 1, used 10, overflow panic",
+ 1,
+ math.MaxUint64,
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.SetupTest() // reset
+
+ panicF := func() {
+ gm := storetypes.NewGasMeter(10)
+ gm.ConsumeGas(tc.gasConsumed, "")
+ ctx := suite.ctx.WithGasMeter(gm)
+ suite.app.EvmKeeper.ResetGasMeterAndConsumeGas(ctx, tc.gasUsed)
+ }
+
+ if tc.expPanic {
+ suite.Require().Panics(panicF)
+ } else {
+ suite.Require().NotPanics(panicF)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestEVMConfig() {
+ proposerAddress := suite.ctx.BlockHeader().ProposerAddress
+ cfg, err := suite.app.EvmKeeper.EVMConfig(suite.ctx, proposerAddress, big.NewInt(9000))
+ suite.Require().NoError(err)
+ suite.Require().Equal(evmtypes.DefaultParams(), cfg.Params)
+ // london hardfork is enabled by default
+ suite.Require().Equal(big.NewInt(0), cfg.BaseFee)
+ suite.Require().Equal(suite.address, cfg.CoinBase)
+ suite.Require().Equal(evmtypes.DefaultParams().ChainConfig.EthereumConfig(big.NewInt(9000)), cfg.ChainConfig)
+}
+
+func (suite *KeeperTestSuite) TestContractDeployment() {
+ contractAddress := suite.DeployTestContract(suite.T(), suite.address, big.NewInt(10000000000000))
+ db := suite.StateDB()
+ suite.Require().Greater(db.GetCodeSize(contractAddress), 0)
+}
+
+func (suite *KeeperTestSuite) TestApplyMessage() {
+ expectedGasUsed := params.TxGas
+ var msg core.Message
+
+ proposerAddress := suite.ctx.BlockHeader().ProposerAddress
+ config, err := suite.app.EvmKeeper.EVMConfig(suite.ctx, proposerAddress, big.NewInt(9000))
+ suite.Require().NoError(err)
+
+ keeperParams := suite.app.EvmKeeper.GetParams(suite.ctx)
+ chainCfg := keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+ tracer := suite.app.EvmKeeper.Tracer(suite.ctx, msg, config.ChainConfig)
+ vmdb := suite.StateDB()
+
+ msg, err = newNativeMessage(
+ vmdb.GetNonce(suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ chainCfg,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ nil,
+ nil,
+ )
+ suite.Require().NoError(err)
+
+ res, err := suite.app.EvmKeeper.ApplyMessage(suite.ctx, msg, tracer, true)
+
+ suite.Require().NoError(err)
+ suite.Require().Equal(expectedGasUsed, res.GasUsed)
+ suite.Require().False(res.Failed())
+}
+
+func (suite *KeeperTestSuite) TestApplyMessageWithConfig() {
+ var (
+ msg core.Message
+ err error
+ expectedGasUsed uint64
+ config *statedb.EVMConfig
+ keeperParams evmtypes.Params
+ signer ethtypes.Signer
+ vmdb *statedb.StateDB
+ txConfig statedb.TxConfig
+ chainCfg *params.ChainConfig
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expErr bool
+ expVMErr bool
+ }{
+ {
+ "message applied ok",
+ func() {
+ msg, err = newNativeMessage(
+ vmdb.GetNonce(suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ chainCfg,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ nil,
+ nil,
+ )
+ suite.Require().NoError(err)
+ },
+ false,
+ false,
+ },
+ {
+ "call contract tx with config param EnableCall = false",
+ func() {
+ config.Params.AccessControl = evmtypes.AccessControl{
+ Call: evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypeRestricted,
+ },
+ }
+ msg, err = newNativeMessage(
+ vmdb.GetNonce(suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ chainCfg,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ nil,
+ nil,
+ )
+ suite.Require().NoError(err)
+ },
+ false,
+ true,
+ },
+ {
+ "create contract tx with config param EnableCreate = false",
+ func() {
+ msg, err = suite.createContractGethMsg(vmdb.GetNonce(suite.address), signer, chainCfg, big.NewInt(2))
+ suite.Require().NoError(err)
+ config.Params.AccessControl = evmtypes.AccessControl{
+ Create: evmtypes.AccessControlType{
+ AccessType: evmtypes.AccessTypeRestricted,
+ },
+ }
+ },
+ false,
+ true,
+ },
+ {
+ "fix panic when minimumGasUsed is not uint64",
+ func() {
+ msg, err = newNativeMessage(
+ vmdb.GetNonce(suite.address),
+ suite.ctx.BlockHeight(),
+ suite.address,
+ chainCfg,
+ suite.signer,
+ signer,
+ ethtypes.AccessListTxType,
+ nil,
+ nil,
+ )
+ suite.Require().NoError(err)
+ params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
+ params.MinGasMultiplier = sdkmath.LegacyNewDec(math.MaxInt64).MulInt64(100)
+ err = suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ },
+ true,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.SetupTest()
+ expectedGasUsed = params.TxGas
+
+ proposerAddress := suite.ctx.BlockHeader().ProposerAddress
+ config, err = suite.app.EvmKeeper.EVMConfig(suite.ctx, proposerAddress, big.NewInt(9000))
+ suite.Require().NoError(err)
+
+ keeperParams = suite.app.EvmKeeper.GetParams(suite.ctx)
+ chainCfg = keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
+ signer = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+ vmdb = suite.StateDB()
+ txConfig = suite.app.EvmKeeper.TxConfig(suite.ctx, common.Hash{})
+
+ tc.malleate()
+ res, err := suite.app.EvmKeeper.ApplyMessageWithConfig(suite.ctx, msg, nil, true, config, txConfig)
+
+ if tc.expErr {
+ suite.Require().Error(err)
+ return
+ }
+
+ if tc.expVMErr {
+ suite.Require().NotEmpty(res.VmError)
+ return
+ }
+
+ suite.Require().NoError(err)
+ suite.Require().False(res.Failed())
+ suite.Require().Equal(expectedGasUsed, res.GasUsed)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) createContractGethMsg(nonce uint64, signer ethtypes.Signer, cfg *params.ChainConfig, gasPrice *big.Int) (core.Message, error) {
+ ethMsg, err := suite.createContractMsgTx(nonce, signer, gasPrice)
+ if err != nil {
+ return nil, err
+ }
+
+ msgSigner := ethtypes.MakeSigner(cfg, big.NewInt(suite.ctx.BlockHeight()))
+ return ethMsg.AsMessage(msgSigner, nil)
+}
+
+func (suite *KeeperTestSuite) createContractMsgTx(nonce uint64, signer ethtypes.Signer, gasPrice *big.Int) (*evmtypes.MsgEthereumTx, error) {
+ contractCreateTx := ðtypes.AccessListTx{
+ GasPrice: gasPrice,
+ Gas: params.TxGasContractCreation + 1000, // account for data length
+ To: nil,
+ Data: []byte("contract_data"),
+ Nonce: nonce,
+ }
+ ethTx := ethtypes.NewTx(contractCreateTx)
+ ethMsg := &evmtypes.MsgEthereumTx{}
+ err := ethMsg.FromEthereumTx(ethTx)
+ suite.Require().NoError(err)
+ ethMsg.From = suite.address.Hex()
+
+ return ethMsg, ethMsg.Sign(signer, suite.signer)
+}
+
+func (suite *KeeperTestSuite) TestGetProposerAddress() {
+ var a sdk.ConsAddress
+ address := sdk.ConsAddress(suite.address.Bytes())
+ proposerAddress := sdk.ConsAddress(suite.ctx.BlockHeader().ProposerAddress)
+ testCases := []struct {
+ msg string
+ adr sdk.ConsAddress
+ expAdr sdk.ConsAddress
+ }{
+ {
+ "proposer address provided",
+ address,
+ address,
+ },
+ {
+ "nil proposer address provided",
+ nil,
+ proposerAddress,
+ },
+ {
+ "typed nil proposer address provided",
+ a,
+ proposerAddress,
+ },
+ }
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+ suite.Require().Equal(tc.expAdr, keeper.GetProposerAddress(suite.ctx, tc.adr))
+ })
+ }
+}
diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go
new file mode 100644
index 00000000..891f75d8
--- /dev/null
+++ b/x/evm/keeper/statedb.go
@@ -0,0 +1,290 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package keeper
+
+import (
+ "errors"
+ "math/big"
+
+ sdkmath "cosmossdk.io/math"
+ "github.com/cosmos/cosmos-sdk/store/prefix"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+var _ statedb.Keeper = &Keeper{}
+
+// ----------------------------------------------------------------------------
+// StateDB Keeper implementation
+// ----------------------------------------------------------------------------
+
+// GetAccount returns nil if account is not exist
+func (k *Keeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account {
+ acct := k.GetAccountWithoutBalance(ctx, addr)
+ if acct == nil {
+ return nil
+ }
+
+ acct.Balance = k.GetBalance(ctx, addr)
+ return acct
+}
+
+// GetState loads contract state from database.
+func (k *Keeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
+
+ value := store.Get(key.Bytes())
+ if len(value) == 0 {
+ return common.Hash{}
+ }
+
+ return common.BytesToHash(value)
+}
+
+// GetFastState loads contract state from database.
+func (k *Keeper) GetFastState(ctx sdk.Context, addr common.Address, key common.Hash) []byte {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
+
+ return store.Get(key.Bytes())
+}
+
+// GetCodeHash loads the code hash from the database for the given contract address.
+func (k *Keeper) GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash)
+ bz := store.Get(addr.Bytes())
+ if len(bz) == 0 {
+ return common.BytesToHash(types.EmptyCodeHash)
+ }
+
+ return common.BytesToHash(bz)
+}
+
+// IterateContracts iterates over all smart contract addresses in the EVM keeper and
+// performs a callback function.
+//
+// The iteration is stopped when the callback function returns true.
+func (k Keeper) IterateContracts(ctx sdk.Context, cb func(addr common.Address, codeHash common.Hash) (stop bool)) {
+ store := ctx.KVStore(k.storeKey)
+ iterator := sdk.KVStorePrefixIterator(store, types.KeyPrefixCodeHash)
+
+ defer iterator.Close()
+ for ; iterator.Valid(); iterator.Next() {
+ addr := common.BytesToAddress(iterator.Key())
+ codeHash := common.BytesToHash(iterator.Value())
+
+ if cb(addr, codeHash) {
+ break
+ }
+ }
+}
+
+// GetCode loads contract code from database, implements `statedb.Keeper` interface.
+func (k *Keeper) GetCode(ctx sdk.Context, codeHash common.Hash) []byte {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode)
+ return store.Get(codeHash.Bytes())
+}
+
+// ForEachStorage iterate contract storage, callback return false to break early
+func (k *Keeper) ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) {
+ store := ctx.KVStore(k.storeKey)
+ prefix := types.AddressStoragePrefix(addr)
+
+ iterator := storetypes.KVStorePrefixIterator(store, prefix)
+ defer iterator.Close()
+
+ for ; iterator.Valid(); iterator.Next() {
+ key := common.BytesToHash(iterator.Key())
+ value := common.BytesToHash(iterator.Value())
+
+ // check if iteration stops
+ if !cb(key, value) {
+ return
+ }
+ }
+}
+
+// SetBalance update account's balance, compare with current balance first, then decide to mint or burn.
+func (k *Keeper) SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int) error {
+ cosmosAddr := sdk.AccAddress(addr.Bytes())
+
+ params := k.GetParams(ctx)
+ coin := k.bankKeeper.GetBalance(ctx, cosmosAddr, params.EvmDenom)
+ balance := coin.Amount.BigInt()
+ delta := new(big.Int).Sub(amount, balance)
+ switch delta.Sign() {
+ case 1:
+ // mint
+ coins := sdk.NewCoins(sdk.NewCoin(params.EvmDenom, sdkmath.NewIntFromBigInt(delta)))
+ if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil {
+ return err
+ }
+ if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, cosmosAddr, coins); err != nil {
+ return err
+ }
+ case -1:
+ // burn
+ coins := sdk.NewCoins(sdk.NewCoin(params.EvmDenom, sdkmath.NewIntFromBigInt(new(big.Int).Neg(delta))))
+ if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, cosmosAddr, types.ModuleName, coins); err != nil {
+ return err
+ }
+ if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, coins); err != nil {
+ return err
+ }
+ default:
+ // not changed
+ }
+ return nil
+}
+
+// SetAccount updates nonce/balance/codeHash together.
+func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account statedb.Account) error {
+ // update account
+ acct := k.accountKeeper.GetAccount(ctx, addr.Bytes())
+ if acct == nil {
+ acct = k.accountKeeper.NewAccountWithAddress(ctx, addr.Bytes())
+ }
+
+ if err := acct.SetSequence(account.Nonce); err != nil {
+ return err
+ }
+
+ if types.IsEmptyCodeHash(account.CodeHash) {
+ k.DeleteCodeHash(ctx, addr)
+ } else {
+ k.SetCodeHash(ctx, addr.Bytes(), account.CodeHash)
+ }
+ k.accountKeeper.SetAccount(ctx, acct)
+
+ if err := k.SetBalance(ctx, addr, account.Balance); err != nil {
+ return err
+ }
+
+ k.Logger(ctx).Debug(
+ "account updated",
+ "ethereum-address", addr.Hex(),
+ "nonce", account.Nonce,
+ "codeHash", common.BytesToHash(account.CodeHash).Hex(),
+ "balance", account.Balance,
+ )
+ return nil
+}
+
+// SetState update contract storage.
+func (k *Keeper) SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
+ store.Set(key.Bytes(), value)
+
+ k.Logger(ctx).Debug(
+ "state updated",
+ "ethereum-address", addr.Hex(),
+ "key", key.Hex(),
+ )
+}
+
+// DeleteState deletes the entry for the given key in the contract storage
+// at the defined contract address.
+func (k *Keeper) DeleteState(ctx sdk.Context, addr common.Address, key common.Hash) {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
+ store.Delete(key.Bytes())
+
+ k.Logger(ctx).Debug(
+ "state deleted",
+ "ethereum-address", addr.Hex(),
+ "key", key.Hex(),
+ )
+}
+
+// SetCodeHash sets the code hash for the given contract address.
+func (k *Keeper) SetCodeHash(ctx sdk.Context, addrBytes, hashBytes []byte) {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash)
+ store.Set(addrBytes, hashBytes)
+
+ k.Logger(ctx).Debug(
+ "code hash updated",
+ "address", common.BytesToAddress(addrBytes).Hex(),
+ "code hash", common.BytesToHash(hashBytes).Hex(),
+ )
+}
+
+// DeleteCodeHash deletes the code hash for the given contract address from the store.
+func (k *Keeper) DeleteCodeHash(ctx sdk.Context, addr common.Address) {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash)
+ store.Delete(addr.Bytes())
+
+ k.Logger(ctx).Debug(
+ "code hash deleted",
+ "address", addr.Hex(),
+ )
+}
+
+// SetCode sets the given contract code bytes for the corresponding code hash bytes key
+// in the code store.
+func (k *Keeper) SetCode(ctx sdk.Context, codeHash, code []byte) {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode)
+ store.Set(codeHash, code)
+
+ k.Logger(ctx).Debug(
+ "code updated",
+ "code-hash", common.BytesToHash(codeHash).Hex(),
+ )
+}
+
+// DeleteCode deletes the contract code for the given code hash bytes in
+// the corresponding store.
+func (k *Keeper) DeleteCode(ctx sdk.Context, codeHash []byte) {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode)
+ store.Delete(codeHash)
+
+ k.Logger(ctx).Debug(
+ "code deleted",
+ "code-hash", common.BytesToHash(codeHash).Hex(),
+ )
+}
+
+// DeleteAccount handles contract's suicide call:
+// - clear balance
+// - remove code
+// - remove states
+// - remove the code hash
+// - remove auth account
+func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error {
+ cosmosAddr := sdk.AccAddress(addr.Bytes())
+ acct := k.accountKeeper.GetAccount(ctx, cosmosAddr)
+ if acct == nil {
+ return nil
+ }
+
+ // NOTE: only Ethereum contracts can be self-destructed
+ if !k.IsContract(ctx, addr) {
+ return errors.New("only smart contracts can be self-destructed")
+ }
+
+ // clear balance
+ if err := k.SetBalance(ctx, addr, new(big.Int)); err != nil {
+ return err
+ }
+
+ // clear storage
+ k.ForEachStorage(ctx, addr, func(key, _ common.Hash) bool {
+ k.DeleteState(ctx, addr, key)
+ return true
+ })
+
+ // clear code hash
+ k.DeleteCodeHash(ctx, addr)
+
+ // remove auth account
+ k.accountKeeper.RemoveAccount(ctx, acct)
+
+ k.Logger(ctx).Debug(
+ "account suicided",
+ "ethereum-address", addr.Hex(),
+ "cosmos-address", cosmosAddr.String(),
+ )
+
+ return nil
+}
diff --git a/x/evm/keeper/statedb_benchmark_test.go b/x/evm/keeper/statedb_benchmark_test.go
new file mode 100644
index 00000000..28aa7ccd
--- /dev/null
+++ b/x/evm/keeper/statedb_benchmark_test.go
@@ -0,0 +1,193 @@
+package keeper_test
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+)
+
+func BenchmarkCreateAccountNew(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ addr := utiltx.GenerateAddress()
+ b.StartTimer()
+ vmdb.CreateAccount(addr)
+ }
+}
+
+func BenchmarkCreateAccountExisting(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.CreateAccount(suite.address)
+ }
+}
+
+func BenchmarkAddBalance(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ amt := big.NewInt(10)
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.AddBalance(suite.address, amt)
+ }
+}
+
+func BenchmarkSetCode(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ hash := crypto.Keccak256Hash([]byte("code")).Bytes()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.SetCode(suite.address, hash)
+ }
+}
+
+func BenchmarkSetState(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ hash := crypto.Keccak256Hash([]byte("topic")).Bytes()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.SetCode(suite.address, hash)
+ }
+}
+
+func BenchmarkAddLog(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ topic := crypto.Keccak256Hash([]byte("topic"))
+ txHash := crypto.Keccak256Hash([]byte("tx_hash"))
+ blockHash := crypto.Keccak256Hash([]byte("block_hash"))
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.AddLog(ðtypes.Log{
+ Address: suite.address,
+ Topics: []common.Hash{topic},
+ Data: []byte("data"),
+ BlockNumber: 1,
+ TxHash: txHash,
+ TxIndex: 1,
+ BlockHash: blockHash,
+ Index: 1,
+ Removed: false,
+ })
+ }
+}
+
+func BenchmarkSnapshot(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ target := vmdb.Snapshot()
+ require.Equal(b, i, target)
+ }
+
+ for i := b.N - 1; i >= 0; i-- {
+ require.NotPanics(b, func() {
+ vmdb.RevertToSnapshot(i)
+ })
+ }
+}
+
+func BenchmarkSubBalance(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ amt := big.NewInt(10)
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.SubBalance(suite.address, amt)
+ }
+}
+
+func BenchmarkSetNonce(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.SetNonce(suite.address, 1)
+ }
+}
+
+func BenchmarkAddRefund(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ vmdb.AddRefund(1)
+ }
+}
+
+func BenchmarkSuicide(b *testing.B) {
+ suite := KeeperTestSuite{}
+ suite.SetupTestWithT(b)
+ vmdb := suite.StateDB()
+
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ addr := utiltx.GenerateAddress()
+ vmdb.CreateAccount(addr)
+ b.StartTimer()
+
+ vmdb.Suicide(addr)
+ }
+}
diff --git a/x/evm/keeper/statedb_test.go b/x/evm/keeper/statedb_test.go
new file mode 100644
index 00000000..10849a1d
--- /dev/null
+++ b/x/evm/keeper/statedb_test.go
@@ -0,0 +1,1060 @@
+package keeper_test
+
+import (
+ "fmt"
+ "math/big"
+ "testing"
+
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/store/prefix"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
+ authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/contracts"
+ testfactory "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ testhandler "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ testnetwork "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+ "github.com/stretchr/testify/require"
+)
+
+func (suite *KeeperTestSuite) TestCreateAccount() {
+ testCases := []struct {
+ name string
+ addr common.Address
+ malleate func(vm.StateDB, common.Address)
+ callback func(vm.StateDB, common.Address)
+ }{
+ {
+ "reset account (keep balance)",
+ suite.address,
+ func(vmdb vm.StateDB, addr common.Address) {
+ vmdb.AddBalance(addr, big.NewInt(100))
+ suite.Require().NotZero(vmdb.GetBalance(addr).Int64())
+ },
+ func(vmdb vm.StateDB, addr common.Address) {
+ suite.Require().Equal(vmdb.GetBalance(addr).Int64(), int64(100))
+ },
+ },
+ {
+ "create account",
+ utiltx.GenerateAddress(),
+ func(vmdb vm.StateDB, addr common.Address) {
+ suite.Require().False(vmdb.Exist(addr))
+ },
+ func(vmdb vm.StateDB, addr common.Address) {
+ suite.Require().True(vmdb.Exist(addr))
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb, tc.addr)
+ vmdb.CreateAccount(tc.addr)
+ tc.callback(vmdb, tc.addr)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestAddBalance() {
+ testCases := []struct {
+ name string
+ amount *big.Int
+ isNoOp bool
+ }{
+ {
+ "positive amount",
+ big.NewInt(100),
+ false,
+ },
+ {
+ "zero amount",
+ big.NewInt(0),
+ true,
+ },
+ {
+ "negative amount",
+ big.NewInt(-1),
+ false, // seems to be consistent with go-ethereum's implementation
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ prev := vmdb.GetBalance(suite.address)
+ vmdb.AddBalance(suite.address, tc.amount)
+ post := vmdb.GetBalance(suite.address)
+
+ if tc.isNoOp {
+ suite.Require().Equal(prev.Int64(), post.Int64())
+ } else {
+ suite.Require().Equal(new(big.Int).Add(prev, tc.amount).Int64(), post.Int64())
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestSubBalance() {
+ testCases := []struct {
+ name string
+ amount *big.Int
+ malleate func(vm.StateDB)
+ isNoOp bool
+ }{
+ {
+ "positive amount, below zero",
+ big.NewInt(100),
+ func(vm.StateDB) {},
+ false,
+ },
+ {
+ "positive amount, above zero",
+ big.NewInt(50),
+ func(vmdb vm.StateDB) {
+ vmdb.AddBalance(suite.address, big.NewInt(100))
+ },
+ false,
+ },
+ {
+ "zero amount",
+ big.NewInt(0),
+ func(vm.StateDB) {},
+ true,
+ },
+ {
+ "negative amount",
+ big.NewInt(-1),
+ func(vm.StateDB) {},
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+
+ prev := vmdb.GetBalance(suite.address)
+ vmdb.SubBalance(suite.address, tc.amount)
+ post := vmdb.GetBalance(suite.address)
+
+ if tc.isNoOp {
+ suite.Require().Equal(prev.Int64(), post.Int64())
+ } else {
+ suite.Require().Equal(new(big.Int).Sub(prev, tc.amount).Int64(), post.Int64())
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestGetNonce() {
+ testCases := []struct {
+ name string
+ address common.Address
+ expectedNonce uint64
+ malleate func(vm.StateDB)
+ }{
+ {
+ "account not found",
+ utiltx.GenerateAddress(),
+ 0,
+ func(vm.StateDB) {},
+ },
+ {
+ "existing account",
+ suite.address,
+ 1,
+ func(vmdb vm.StateDB) {
+ vmdb.SetNonce(suite.address, 1)
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+
+ nonce := vmdb.GetNonce(tc.address)
+ suite.Require().Equal(tc.expectedNonce, nonce)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestSetNonce() {
+ testCases := []struct {
+ name string
+ address common.Address
+ nonce uint64
+ malleate func()
+ }{
+ {
+ "new account",
+ utiltx.GenerateAddress(),
+ 10,
+ func() {},
+ },
+ {
+ "existing account",
+ suite.address,
+ 99,
+ func() {},
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ vmdb.SetNonce(tc.address, tc.nonce)
+ nonce := vmdb.GetNonce(tc.address)
+ suite.Require().Equal(tc.nonce, nonce)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestGetCodeHash() {
+ addr := utiltx.GenerateAddress()
+ baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
+ suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
+
+ testCases := []struct {
+ name string
+ address common.Address
+ expHash common.Hash
+ malleate func(vm.StateDB)
+ }{
+ {
+ "account not found",
+ utiltx.GenerateAddress(),
+ common.Hash{},
+ func(vm.StateDB) {},
+ },
+ {
+ "account is not a smart contract",
+ addr,
+ common.BytesToHash(types.EmptyCodeHash),
+ func(vm.StateDB) {},
+ },
+ {
+ "existing account",
+ suite.address,
+ crypto.Keccak256Hash([]byte("codeHash")),
+ func(vmdb vm.StateDB) {
+ vmdb.SetCode(suite.address, []byte("codeHash"))
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+
+ hash := vmdb.GetCodeHash(tc.address)
+ suite.Require().Equal(tc.expHash, hash)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestSetCode() {
+ addr := utiltx.GenerateAddress()
+ baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
+ suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
+
+ testCases := []struct {
+ name string
+ address common.Address
+ code []byte
+ isNoOp bool
+ }{
+ {
+ "account not found",
+ utiltx.GenerateAddress(),
+ []byte("code"),
+ false,
+ },
+ {
+ "account not a smart contract",
+ addr,
+ nil,
+ true,
+ },
+ {
+ "existing account",
+ suite.address,
+ []byte("code"),
+ false,
+ },
+ {
+ "existing account, code deleted from store",
+ suite.address,
+ nil,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ prev := vmdb.GetCode(tc.address)
+ vmdb.SetCode(tc.address, tc.code)
+ post := vmdb.GetCode(tc.address)
+
+ if tc.isNoOp {
+ suite.Require().Equal(prev, post)
+ } else {
+ suite.Require().Equal(tc.code, post)
+ }
+
+ suite.Require().Equal(len(post), vmdb.GetCodeSize(tc.address))
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestKeeperSetOrDeleteCode() {
+ addr := utiltx.GenerateAddress()
+ baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
+ suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
+
+ testCases := []struct {
+ name string
+ codeHash []byte
+ code []byte
+ }{
+ {
+ "set code",
+ []byte("codeHash"),
+ []byte("this is the code"),
+ },
+ {
+ "delete code",
+ []byte("codeHash"),
+ nil,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ if len(tc.code) == 0 {
+ suite.app.EvmKeeper.DeleteCode(suite.ctx, tc.codeHash)
+ } else {
+ suite.app.EvmKeeper.SetCode(suite.ctx, tc.codeHash, tc.code)
+ }
+ key := suite.app.GetKey(types.StoreKey)
+ store := prefix.NewStore(suite.ctx.KVStore(key), types.KeyPrefixCode)
+ code := store.Get(tc.codeHash)
+
+ suite.Require().Equal(tc.code, code)
+ })
+ }
+}
+
+func TestIterateContracts(t *testing.T) {
+ keyring := testkeyring.New(1)
+ network := testnetwork.NewUnitTestNetwork(
+ testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ handler := testhandler.NewIntegrationHandler(network)
+ factory := testfactory.New(network, handler)
+
+ contractAddr, err := factory.DeployContract(
+ keyring.GetPrivKey(0),
+ types.EvmTxArgs{},
+ testfactory.ContractDeploymentData{
+ Contract: contracts.ERC20MinterBurnerDecimalsContract,
+ ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)},
+ },
+ )
+ require.NoError(t, err, "failed to deploy contract")
+ require.NoError(t, network.NextBlock(), "failed to advance block")
+
+ contractAddr2, err := factory.DeployContract(
+ keyring.GetPrivKey(0),
+ types.EvmTxArgs{},
+ testfactory.ContractDeploymentData{
+ Contract: contracts.ERC20MinterBurnerDecimalsContract,
+ ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)},
+ },
+ )
+ require.NoError(t, err, "failed to deploy contract")
+ require.NoError(t, network.NextBlock(), "failed to advance block")
+
+ var (
+ foundAddrs []common.Address
+ foundHashes []common.Hash
+ )
+
+ network.App.EvmKeeper.IterateContracts(network.GetContext(), func(addr common.Address, codeHash common.Hash) bool {
+ foundAddrs = append(foundAddrs, addr)
+ foundHashes = append(foundHashes, codeHash)
+ return false
+ })
+
+ require.Len(t, foundAddrs, 2, "expected 2 contracts to be found when iterating")
+ require.Contains(t, foundAddrs, contractAddr, "expected contract 1 to be found when iterating")
+ require.Contains(t, foundAddrs, contractAddr2, "expected contract 2 to be found when iterating")
+ require.Equal(t, foundHashes[0], foundHashes[1], "expected both contracts to have the same code hash")
+ require.NotEqual(t, types.EmptyCodeHash, foundHashes[0], "expected store code hash not to be the keccak256 of empty code")
+}
+
+func (suite *KeeperTestSuite) TestRefund() {
+ testCases := []struct {
+ name string
+ malleate func(vm.StateDB)
+ expRefund uint64
+ expPanic bool
+ }{
+ {
+ "success - add and subtract refund",
+ func(vmdb vm.StateDB) {
+ vmdb.AddRefund(11)
+ },
+ 1,
+ false,
+ },
+ {
+ "fail - subtract amount > current refund",
+ func(vm.StateDB) {
+ },
+ 0,
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+
+ if tc.expPanic {
+ suite.Require().Panics(func() { vmdb.SubRefund(10) })
+ } else {
+ vmdb.SubRefund(10)
+ suite.Require().Equal(tc.expRefund, vmdb.GetRefund())
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestState() {
+ testCases := []struct {
+ name string
+ key, value common.Hash
+ }{
+ {
+ "set state - delete from store",
+ common.BytesToHash([]byte("key")),
+ common.Hash{},
+ },
+ {
+ "set state - update value",
+ common.BytesToHash([]byte("key")),
+ common.BytesToHash([]byte("value")),
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ vmdb.SetState(suite.address, tc.key, tc.value)
+ value := vmdb.GetState(suite.address, tc.key)
+ suite.Require().Equal(tc.value, value)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestCommittedState() {
+ key := common.BytesToHash([]byte("key"))
+ value1 := common.BytesToHash([]byte("value1"))
+ value2 := common.BytesToHash([]byte("value2"))
+
+ vmdb := suite.StateDB()
+ vmdb.SetState(suite.address, key, value1)
+ err := vmdb.Commit()
+ suite.Require().NoError(err)
+
+ vmdb = suite.StateDB()
+ vmdb.SetState(suite.address, key, value2)
+ tmp := vmdb.GetState(suite.address, key)
+ suite.Require().Equal(value2, tmp)
+ tmp = vmdb.GetCommittedState(suite.address, key)
+ suite.Require().Equal(value1, tmp)
+ err = vmdb.Commit()
+ suite.Require().NoError(err)
+
+ vmdb = suite.StateDB()
+ tmp = vmdb.GetCommittedState(suite.address, key)
+ suite.Require().Equal(value2, tmp)
+}
+
+func (suite *KeeperTestSuite) TestSetAndGetCodeHash() {
+ suite.SetupTest()
+}
+
+func (suite *KeeperTestSuite) TestSuicide() {
+ suite.SetupTest()
+
+ // Generate addresses for testing
+ addr1 := utiltx.GenerateAddress()
+ addr2 := utiltx.GenerateAddress()
+
+ // Set the code in the code storage
+ code := []byte("code1")
+ codeHashBz := crypto.Keccak256(code)
+ suite.app.EvmKeeper.SetCodeHash(s.ctx, addr1.Bytes(), codeHashBz)
+ suite.app.EvmKeeper.SetCodeHash(s.ctx, addr2.Bytes(), codeHashBz)
+
+ // NOTE: we're instantiating the StateDB here to have the context already contain the
+ db := suite.StateDB()
+
+ // Add code to account
+ db.SetCode(addr1, code)
+
+ suite.Require().Equal(code, db.GetCode(addr1))
+ // Add state to account
+ for i := 0; i < 5; i++ {
+ db.SetState(addr1, common.BytesToHash([]byte(fmt.Sprintf("key%d", i))), common.BytesToHash([]byte(fmt.Sprintf("value%d", i))))
+ }
+
+ suite.Require().NoError(db.Commit())
+ db = suite.StateDB()
+
+ // Add code and state to account 2
+ db.SetCode(addr2, code)
+ suite.Require().Equal(code, db.GetCode(addr2))
+
+ for i := 0; i < 5; i++ {
+ db.SetState(addr2, common.BytesToHash([]byte(fmt.Sprintf("key%d", i))), common.BytesToHash([]byte(fmt.Sprintf("value%d", i))))
+ }
+
+ // Call Suicide
+ suite.Require().Equal(true, db.Suicide(addr1))
+
+ // Check suicided is marked
+ suite.Require().Equal(true, db.HasSuicided(addr1))
+
+ // Commit state
+ suite.Require().NoError(db.Commit())
+ db = suite.StateDB()
+
+ // Check code is deleted
+ suite.Require().Nil(db.GetCode(addr1))
+
+ // Check state is deleted
+ var storage types.Storage
+ suite.app.EvmKeeper.ForEachStorage(suite.ctx, addr1, func(key, value common.Hash) bool {
+ storage = append(storage, types.NewState(key, value))
+ return true
+ })
+ suite.Require().Equal(0, len(storage))
+
+ // Check account is deleted
+ suite.Require().Equal(common.Hash{}, db.GetCodeHash(addr1))
+
+ // Check code is still present in addr2 and suicided is false
+ suite.Require().NotNil(db.GetCode(addr2))
+ suite.Require().Equal(false, db.HasSuicided(addr2))
+}
+
+func (suite *KeeperTestSuite) TestExist() {
+ testCases := []struct {
+ name string
+ address common.Address
+ malleate func(vm.StateDB)
+ exists bool
+ }{
+ {"success, account exists", suite.address, func(vm.StateDB) {}, true},
+ {"success, has suicided", suite.address, func(vmdb vm.StateDB) {
+ vmdb.Suicide(suite.address)
+ }, true},
+ {"success, account doesn't exist", utiltx.GenerateAddress(), func(vm.StateDB) {}, false},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+
+ suite.Require().Equal(tc.exists, vmdb.Exist(tc.address))
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestEmpty() {
+ testCases := []struct {
+ name string
+ address common.Address
+ malleate func(vm.StateDB)
+ empty bool
+ }{
+ {"empty, account exists", suite.address, func(vm.StateDB) {}, true},
+ {
+ "not empty, positive balance",
+ suite.address,
+ func(vmdb vm.StateDB) { vmdb.AddBalance(suite.address, big.NewInt(100)) },
+ false,
+ },
+ {"empty, account doesn't exist", utiltx.GenerateAddress(), func(vm.StateDB) {}, true},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+
+ suite.Require().Equal(tc.empty, vmdb.Empty(tc.address))
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestSnapshot() {
+ key := common.BytesToHash([]byte("key"))
+ value1 := common.BytesToHash([]byte("value1"))
+ value2 := common.BytesToHash([]byte("value2"))
+
+ testCases := []struct {
+ name string
+ malleate func(vm.StateDB)
+ }{
+ {"simple revert", func(vmdb vm.StateDB) {
+ revision := vmdb.Snapshot()
+ suite.Require().Zero(revision)
+
+ vmdb.SetState(suite.address, key, value1)
+ suite.Require().Equal(value1, vmdb.GetState(suite.address, key))
+
+ vmdb.RevertToSnapshot(revision)
+
+ // reverted
+ suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.address, key))
+ }},
+ {"nested snapshot/revert", func(vmdb vm.StateDB) {
+ revision1 := vmdb.Snapshot()
+ suite.Require().Zero(revision1)
+
+ vmdb.SetState(suite.address, key, value1)
+
+ revision2 := vmdb.Snapshot()
+
+ vmdb.SetState(suite.address, key, value2)
+ suite.Require().Equal(value2, vmdb.GetState(suite.address, key))
+
+ vmdb.RevertToSnapshot(revision2)
+ suite.Require().Equal(value1, vmdb.GetState(suite.address, key))
+
+ vmdb.RevertToSnapshot(revision1)
+ suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.address, key))
+ }},
+ {"jump revert", func(vmdb vm.StateDB) {
+ revision1 := vmdb.Snapshot()
+ vmdb.SetState(suite.address, key, value1)
+ vmdb.Snapshot()
+ vmdb.SetState(suite.address, key, value2)
+ vmdb.RevertToSnapshot(revision1)
+ suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.address, key))
+ }},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ vmdb := suite.StateDB()
+ tc.malleate(vmdb)
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) CreateTestTx(msg *types.MsgEthereumTx, priv cryptotypes.PrivKey) authsigning.Tx {
+ option, err := codectypes.NewAnyWithValue(&types.ExtensionOptionsEthereumTx{})
+ suite.Require().NoError(err)
+
+ txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
+ builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder)
+ suite.Require().True(ok)
+
+ builder.SetExtensionOptions(option)
+
+ err = msg.Sign(suite.ethSigner, utiltx.NewSigner(priv))
+ suite.Require().NoError(err)
+
+ err = txBuilder.SetMsgs(msg)
+ suite.Require().NoError(err)
+
+ return txBuilder.GetTx()
+}
+
+func (suite *KeeperTestSuite) TestAddLog() {
+ addr, privKey := utiltx.NewAddrKey()
+ ethTxParams := &types.EvmTxArgs{
+ ChainID: big.NewInt(1),
+ Nonce: 0,
+ To: &suite.address,
+ Amount: big.NewInt(1),
+ GasLimit: 100000,
+ GasPrice: big.NewInt(1),
+ Input: []byte("test"),
+ }
+ msg := types.NewTx(ethTxParams)
+ msg.From = addr.Hex()
+
+ tx := suite.CreateTestTx(msg, privKey)
+ msg, _ = tx.GetMsgs()[0].(*types.MsgEthereumTx)
+ txHash := msg.AsTransaction().Hash()
+
+ ethTx2Params := &types.EvmTxArgs{
+ ChainID: big.NewInt(1),
+ Nonce: 2,
+ To: &suite.address,
+ Amount: big.NewInt(1),
+ GasLimit: 100000,
+ GasPrice: big.NewInt(1),
+ Input: []byte("test"),
+ }
+ msg2 := types.NewTx(ethTx2Params)
+ msg2.From = addr.Hex()
+
+ ethTx3Params := &types.EvmTxArgs{
+ ChainID: big.NewInt(9000),
+ Nonce: 0,
+ To: &suite.address,
+ Amount: big.NewInt(1),
+ GasLimit: 100000,
+ GasFeeCap: big.NewInt(1),
+ GasTipCap: big.NewInt(1),
+ Input: []byte("test"),
+ }
+ msg3 := types.NewTx(ethTx3Params)
+ msg3.From = addr.Hex()
+
+ tx3 := suite.CreateTestTx(msg3, privKey)
+ msg3, _ = tx3.GetMsgs()[0].(*types.MsgEthereumTx)
+ txHash3 := msg3.AsTransaction().Hash()
+
+ ethTx4Params := &types.EvmTxArgs{
+ ChainID: big.NewInt(1),
+ Nonce: 1,
+ To: &suite.address,
+ Amount: big.NewInt(1),
+ GasLimit: 100000,
+ GasFeeCap: big.NewInt(1),
+ GasTipCap: big.NewInt(1),
+ Input: []byte("test"),
+ }
+ msg4 := types.NewTx(ethTx4Params)
+ msg4.From = addr.Hex()
+
+ testCases := []struct {
+ name string
+ hash common.Hash
+ log, expLog *ethtypes.Log // pre and post populating log fields
+ malleate func(vm.StateDB)
+ }{
+ {
+ "tx hash from message",
+ txHash,
+ ðtypes.Log{
+ Address: addr,
+ Topics: make([]common.Hash, 0),
+ },
+ ðtypes.Log{
+ Address: addr,
+ TxHash: txHash,
+ Topics: make([]common.Hash, 0),
+ },
+ func(vm.StateDB) {},
+ },
+ {
+ "dynamicfee tx hash from message",
+ txHash3,
+ ðtypes.Log{
+ Address: addr,
+ Topics: make([]common.Hash, 0),
+ },
+ ðtypes.Log{
+ Address: addr,
+ TxHash: txHash3,
+ Topics: make([]common.Hash, 0),
+ },
+ func(vm.StateDB) {},
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ vmdb := statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewTxConfig(
+ common.BytesToHash(suite.ctx.HeaderHash().Bytes()),
+ tc.hash,
+ 0, 0,
+ ))
+ tc.malleate(vmdb)
+
+ vmdb.AddLog(tc.log)
+ logs := vmdb.Logs()
+ suite.Require().Equal(1, len(logs))
+ suite.Require().Equal(tc.expLog, logs[0])
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestPrepareAccessList() {
+ dest := utiltx.GenerateAddress()
+ precompiles := []common.Address{utiltx.GenerateAddress(), utiltx.GenerateAddress()}
+ accesses := ethtypes.AccessList{
+ {Address: utiltx.GenerateAddress(), StorageKeys: []common.Hash{common.BytesToHash([]byte("key"))}},
+ {Address: utiltx.GenerateAddress(), StorageKeys: []common.Hash{common.BytesToHash([]byte("key1"))}},
+ }
+
+ vmdb := suite.StateDB()
+ vmdb.PrepareAccessList(suite.address, &dest, precompiles, accesses)
+
+ suite.Require().True(vmdb.AddressInAccessList(suite.address))
+ suite.Require().True(vmdb.AddressInAccessList(dest))
+
+ for _, precompile := range precompiles {
+ suite.Require().True(vmdb.AddressInAccessList(precompile))
+ }
+
+ for _, access := range accesses {
+ for _, key := range access.StorageKeys {
+ addrOK, slotOK := vmdb.SlotInAccessList(access.Address, key)
+ suite.Require().True(addrOK, access.Address.Hex())
+ suite.Require().True(slotOK, key.Hex())
+ }
+ }
+}
+
+func (suite *KeeperTestSuite) TestAddAddressToAccessList() {
+ testCases := []struct {
+ name string
+ addr common.Address
+ }{
+ {"new address", suite.address},
+ {"existing address", suite.address},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ vmdb.AddAddressToAccessList(tc.addr)
+ addrOk := vmdb.AddressInAccessList(tc.addr)
+ suite.Require().True(addrOk, tc.addr.Hex())
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) AddSlotToAccessList() {
+ testCases := []struct {
+ name string
+ addr common.Address
+ slot common.Hash
+ }{
+ {"new address and slot (1)", utiltx.GenerateAddress(), common.BytesToHash([]byte("hash"))},
+ {"new address and slot (2)", suite.address, common.Hash{}},
+ {"existing address and slot", suite.address, common.Hash{}},
+ {"existing address, new slot", suite.address, common.BytesToHash([]byte("hash"))},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ vmdb := suite.StateDB()
+ vmdb.AddSlotToAccessList(tc.addr, tc.slot)
+ addrOk, slotOk := vmdb.SlotInAccessList(tc.addr, tc.slot)
+ suite.Require().True(addrOk, tc.addr.Hex())
+ suite.Require().True(slotOk, tc.slot.Hex())
+ })
+ }
+}
+
+// FIXME skip for now
+// func (suite *KeeperTestSuite) _TestForEachStorage() {
+// var storage types.Storage
+//
+// testCase := []struct {
+// name string
+// malleate func(vm.StateDB)
+// callback func(key, value common.Hash) (stop bool)
+// expValues []common.Hash
+// }{
+// {
+// "aggregate state",
+// func(vmdb vm.StateDB) {
+// for i := 0; i < 5; i++ {
+// vmdb.SetState(suite.address, common.BytesToHash([]byte(fmt.Sprintf("key%d", i))), common.BytesToHash([]byte(fmt.Sprintf("value%d", i))))
+// }
+// },
+// func(key, value common.Hash) bool {
+// storage = append(storage, types.NewState(key, value))
+// return true
+// },
+// []common.Hash{
+// common.BytesToHash([]byte("value0")),
+// common.BytesToHash([]byte("value1")),
+// common.BytesToHash([]byte("value2")),
+// common.BytesToHash([]byte("value3")),
+// common.BytesToHash([]byte("value4")),
+// },
+// },
+// {
+// "filter state",
+// func(vmdb vm.StateDB) {
+// vmdb.SetState(suite.address, common.BytesToHash([]byte("key")), common.BytesToHash([]byte("value")))
+// vmdb.SetState(suite.address, common.BytesToHash([]byte("filterkey")), common.BytesToHash([]byte("filtervalue")))
+// },
+// func(key, value common.Hash) bool {
+// if value == common.BytesToHash([]byte("filtervalue")) {
+// storage = append(storage, types.NewState(key, value))
+// return false
+// }
+// return true
+// },
+// []common.Hash{
+// common.BytesToHash([]byte("filtervalue")),
+// },
+// },
+// }
+//
+// for _, tc := range testCase {
+// suite.Run(tc.name, func() {
+// suite.SetupTest() // reset
+// vmdb := suite.StateDB()
+// tc.malleate(vmdb)
+//
+// err := vmdb.ForEachStorage(suite.address, tc.callback)
+// suite.Require().NoError(err)
+// suite.Require().Equal(len(tc.expValues), len(storage), fmt.Sprintf("Expected values:\n%v\nStorage Values\n%v", tc.expValues, storage))
+//
+// vals := make([]common.Hash, len(storage))
+// for i := range storage {
+// vals[i] = common.HexToHash(storage[i].Value)
+// }
+//
+// // TODO: not sure why Equals fails
+// suite.Require().ElementsMatch(tc.expValues, vals)
+// })
+// storage = types.Storage{}
+// }
+// }
+
+func (suite *KeeperTestSuite) TestSetBalance() {
+ amount := big.NewInt(-10)
+
+ testCases := []struct {
+ name string
+ addr common.Address
+ malleate func()
+ expErr bool
+ }{
+ {
+ "address without funds - invalid amount",
+ suite.address,
+ func() {},
+ true,
+ },
+ {
+ "mint to address",
+ suite.address,
+ func() {
+ amount = big.NewInt(100)
+ },
+ false,
+ },
+ {
+ "burn from address",
+ suite.address,
+ func() {
+ amount = big.NewInt(60)
+ },
+ false,
+ },
+ {
+ "address with funds - invalid amount",
+ suite.address,
+ func() {
+ amount = big.NewInt(-10)
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ tc.malleate()
+ err := suite.app.EvmKeeper.SetBalance(suite.ctx, tc.addr, amount)
+ if tc.expErr {
+ suite.Require().Error(err)
+ } else {
+ balance := suite.app.EvmKeeper.GetBalance(suite.ctx, tc.addr)
+ suite.Require().NoError(err)
+ suite.Require().Equal(amount, balance)
+ }
+ })
+ }
+}
+
+func (suite *KeeperTestSuite) TestDeleteAccount() {
+ suite.SetupTest()
+
+ supply := big.NewInt(100)
+ contractAddr := suite.DeployTestContract(suite.T(), suite.address, supply)
+
+ testCases := []struct {
+ name string
+ addr common.Address
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "remove address",
+ addr: suite.address,
+ errContains: "only smart contracts can be self-destructed",
+ },
+ {
+ name: "remove unexistent address - returns nil error",
+ addr: common.HexToAddress("unexistent_address"),
+ expPass: true,
+ },
+ {
+ name: "remove deployed contract",
+ addr: contractAddr,
+ expPass: true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+
+ err := suite.app.EvmKeeper.DeleteAccount(suite.ctx, tc.addr)
+ if tc.expPass {
+ suite.Require().NoError(err, "expected deleting account to succeed")
+
+ acc := suite.app.EvmKeeper.GetAccount(suite.ctx, tc.addr)
+ suite.Require().Nil(acc, "expected no account to be found after deleting")
+
+ balance := suite.app.EvmKeeper.GetBalance(suite.ctx, tc.addr)
+ suite.Require().Equal(new(big.Int), balance, "expected balance to be zero after deleting account")
+ } else {
+ suite.Require().ErrorContains(err, tc.errContains, "expected error to contain message")
+
+ acc := suite.app.EvmKeeper.GetAccount(suite.ctx, tc.addr)
+ suite.Require().NotNil(acc, "expected account to still be found after failing to delete")
+ }
+ })
+ }
+}
diff --git a/x/evm/keeper/static_precompiles.go b/x/evm/keeper/static_precompiles.go
new file mode 100644
index 00000000..7da53ee1
--- /dev/null
+++ b/x/evm/keeper/static_precompiles.go
@@ -0,0 +1,137 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package keeper
+
+import (
+ "fmt"
+ "slices"
+
+ authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
+ bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
+ distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
+ channelkeeper "github.com/cosmos/ibc-go/v7/modules/core/04-channel/keeper"
+ "github.com/ethereum/go-ethereum/common"
+ bankprecompile "github.com/evmos/evmos/v19/precompiles/bank"
+ "github.com/evmos/evmos/v19/precompiles/bech32"
+ distprecompile "github.com/evmos/evmos/v19/precompiles/distribution"
+ ics20precompile "github.com/evmos/evmos/v19/precompiles/ics20"
+ "github.com/evmos/evmos/v19/precompiles/p256"
+ stakingprecompile "github.com/evmos/evmos/v19/precompiles/staking"
+ vestingprecompile "github.com/evmos/evmos/v19/precompiles/vesting"
+ erc20Keeper "github.com/evmos/evmos/v19/x/erc20/keeper"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/types"
+ transferkeeper "github.com/evmos/evmos/v19/x/ibc/transfer/keeper"
+ stakingkeeper "github.com/evmos/evmos/v19/x/staking/keeper"
+ vestingkeeper "github.com/evmos/evmos/v19/x/vesting/keeper"
+ "golang.org/x/exp/maps"
+)
+
+const bech32PrecompileBaseGas = 6_000
+
+// AvailableStaticPrecompiles returns the list of all available static precompiled contracts.
+// NOTE: this should only be used during initialization of the Keeper.
+func NewAvailableStaticPrecompiles(
+ stakingKeeper stakingkeeper.Keeper,
+ distributionKeeper distributionkeeper.Keeper,
+ bankKeeper bankkeeper.Keeper,
+ erc20Keeper erc20Keeper.Keeper,
+ vestingKeeper vestingkeeper.Keeper,
+ authzKeeper authzkeeper.Keeper,
+ transferKeeper transferkeeper.Keeper,
+ channelKeeper channelkeeper.Keeper,
+) map[common.Address]vm.PrecompiledContract {
+ // Clone the mapping from the latest EVM fork.
+ precompiles := maps.Clone(vm.PrecompiledContractsBerlin)
+
+ // secp256r1 precompile as per EIP-7212
+ p256Precompile := &p256.Precompile{}
+
+ bech32Precompile, err := bech32.NewPrecompile(bech32PrecompileBaseGas)
+ if err != nil {
+ panic(fmt.Errorf("failed to instantiate bech32 precompile: %w", err))
+ }
+
+ stakingPrecompile, err := stakingprecompile.NewPrecompile(stakingKeeper, authzKeeper)
+ if err != nil {
+ panic(fmt.Errorf("failed to instantiate staking precompile: %w", err))
+ }
+
+ distributionPrecompile, err := distprecompile.NewPrecompile(
+ distributionKeeper,
+ stakingKeeper,
+ authzKeeper,
+ )
+ if err != nil {
+ panic(fmt.Errorf("failed to instantiate distribution precompile: %w", err))
+ }
+
+ ibcTransferPrecompile, err := ics20precompile.NewPrecompile(
+ stakingKeeper,
+ transferKeeper,
+ channelKeeper,
+ authzKeeper,
+ )
+ if err != nil {
+ panic(fmt.Errorf("failed to instantiate ICS20 precompile: %w", err))
+ }
+
+ vestingPrecompile, err := vestingprecompile.NewPrecompile(vestingKeeper, authzKeeper)
+ if err != nil {
+ panic(fmt.Errorf("failed to instantiate vesting precompile: %w", err))
+ }
+
+ bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, erc20Keeper)
+ if err != nil {
+ panic(fmt.Errorf("failed to instantiate bank precompile: %w", err))
+ }
+
+ // Stateless precompiles
+ precompiles[bech32Precompile.Address()] = bech32Precompile
+ precompiles[p256Precompile.Address()] = p256Precompile
+
+ // Stateful precompiles
+ precompiles[stakingPrecompile.Address()] = stakingPrecompile
+ precompiles[distributionPrecompile.Address()] = distributionPrecompile
+ precompiles[ibcTransferPrecompile.Address()] = ibcTransferPrecompile
+ precompiles[vestingPrecompile.Address()] = vestingPrecompile
+ precompiles[bankPrecompile.Address()] = bankPrecompile
+ return precompiles
+}
+
+// WithStaticPrecompiles sets the available static precompiled contracts.
+func (k *Keeper) WithStaticPrecompiles(precompiles map[common.Address]vm.PrecompiledContract) *Keeper {
+ if k.precompiles != nil {
+ panic("available precompiles map already set")
+ }
+
+ if len(precompiles) == 0 {
+ panic("empty precompiled contract map")
+ }
+
+ k.precompiles = precompiles
+ return k
+}
+
+// GetStaticPrecompileInstance returns the instance of the given static precompile address.
+func (k *Keeper) GetStaticPrecompileInstance(params *types.Params, address common.Address) (vm.PrecompiledContract, bool, error) {
+ if k.IsAvailableStaticPrecompile(params, address) {
+ precompile, found := k.precompiles[address]
+ // If the precompile is within params but not found in the precompiles map it means we have memory
+ // corruption.
+ if !found {
+ panic(fmt.Errorf("precompiled contract not stored in memory: %s", address))
+ }
+ return precompile, true, nil
+ }
+ return nil, false, nil
+}
+
+// IsAvailablePrecompile returns true if the given static precompile address is contained in the
+// EVM keeper's available precompiles map.
+// This function assumes that the Berlin precompiles cannot be disabled.
+func (k Keeper) IsAvailableStaticPrecompile(params *types.Params, address common.Address) bool {
+ return slices.Contains(params.ActiveStaticPrecompiles, address.String()) ||
+ slices.Contains(vm.PrecompiledAddressesBerlin, address)
+}
diff --git a/x/evm/keeper/testdata/ERC20Contract.json b/x/evm/keeper/testdata/ERC20Contract.json
new file mode 100644
index 00000000..50764e3d
--- /dev/null
+++ b/x/evm/keeper/testdata/ERC20Contract.json
@@ -0,0 +1,4 @@
+{
+ "abi": "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initialAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"initialBalance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"TestLog\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"benchmarkLogs\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ "bin": "608060405234801561001057600080fd5b506040516114543803806114548339818101604052604081101561003357600080fd5b810190808051906020019092919080519060200190929190505050806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508060028190555050506113ab806100a96000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80636618846311610066578063661884631461022957806370a082311461028f578063a9059cbb146102e7578063d73dd6231461034d578063dd62ed3e146103b35761009e565b8063095ea7b3146100a357806318160ddd1461010957806323b872dd1461012757806340c10f19146101ad57806357807d7f146101fb575b600080fd5b6100ef600480360360408110156100b957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061042b565b604051808215151515815260200191505060405180910390f35b61011161051d565b6040518082815260200191505060405180910390f35b6101936004803603606081101561013d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610527565b604051808215151515815260200191505060405180910390f35b6101f9600480360360408110156101c357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506108dc565b005b6102276004803603602081101561021157600080fd5b810190808035906020019092919050505061098e565b005b6102756004803603604081101561023f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610a18565b604051808215151515815260200191505060405180910390f35b6102d1600480360360208110156102a557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ca8565b6040518082815260200191505060405180910390f35b610333600480360360408110156102fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610cf0565b604051808215151515815260200191505060405180910390f35b6103996004803603604081101561036357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f0c565b604051808215151515815260200191505060405180910390f35b610415600480360360408110156103c957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611108565b6040518082815260200191505060405180910390f35b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b6000600254905090565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111561057457600080fd5b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211156105fd57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561063757600080fd5b610688826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461118f90919063ffffffff16565b6000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061071b826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461128390919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506107ec82600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461118f90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b61092d816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461128390919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109848160025461128390919063ffffffff16565b6002819055505050565b60008090505b81811015610a14577fb2abdf6dca7f5665e93ea2262744f2159b5c45ff1a9dacadb090ceb00c2a302f3382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a18080600101915050610994565b5050565b600080600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050808310610b28576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610bbc565b610b3b838261118f90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a3600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115610d3d57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610d7757600080fd5b610dc8826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461118f90919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610e5b826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461128390919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000610f9d82600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461128390919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f57000000000000000000000000000081525090611271576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561123657808201518184015260208101905061121b565b50505050905090810190601f1680156112635780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600082840390508091505092915050565b6000808284019050838110156040518060400160405280601181526020017f4d4154485f4144445f4f564552464c4f570000000000000000000000000000008152509061136b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611330578082015181840152602081019050611315565b50505050905090810190601f16801561135d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50809150509291505056fea265627a7a723158201835ad3fdb84f43ad0d79c6875a0f5521dc5110fc373c9f0597547aff6d9971764736f6c63430005110032"
+}
diff --git a/x/evm/keeper/testdata/TestMessageCall.json b/x/evm/keeper/testdata/TestMessageCall.json
new file mode 100644
index 00000000..616ae16a
--- /dev/null
+++ b/x/evm/keeper/testdata/TestMessageCall.json
@@ -0,0 +1,4 @@
+{
+ "abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"iterations\",\"type\":\"uint256\"}],\"name\":\"benchmarkMessageCall\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ "bin": "608060405234801561001057600080fd5b5060405161001d9061007e565b604051809103906000f080158015610039573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061008a565b60dd8061021483390190565b61017b806100996000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806376e489f014610030575b600080fd5b61005c6004803603602081101561004657600080fd5b8101908080359060200190929190505050610072565b6040518082815260200191505060405180910390f35b6000806000905060008090505b8381101561013c576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f8a8fd6d6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156100f057600080fd5b505af1158015610104573d6000803e3d6000fd5b505050506040513d602081101561011a57600080fd5b810190808051906020019092919050505082019150808060010191505061007f565b508091505091905056fea265627a7a723158203bb5ea1d2b128eb07e834f8b4cab93aab73270ef20cb80c1d5e0e2ee4f10b7c264736f6c634300051100326080604052348015600f57600080fd5b5060bf8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063f8a8fd6d14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b60007f1440c4dd67b4344ea1905ec0318995133b550f168b4ee959a0da6b503d7d2414602a6040518082815260200191505060405180910390a1602a90509056fea265627a7a723158209236549244199cceaef9525385c8b6fccaf6390440ece080e2046d9f4a0035f564736f6c63430005110032"
+}
diff --git a/x/evm/keeper/testdata/contracts.go b/x/evm/keeper/testdata/contracts.go
new file mode 100644
index 00000000..e787fa6a
--- /dev/null
+++ b/x/evm/keeper/testdata/contracts.go
@@ -0,0 +1,17 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package testdata
+
+import (
+ contractutils "github.com/evmos/evmos/v19/contracts/utils"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func LoadERC20Contract() (evmtypes.CompiledContract, error) {
+ return contractutils.LegacyLoadContractFromJSONFile("ERC20Contract.json")
+}
+
+func LoadMessageCallContract() (evmtypes.CompiledContract, error) {
+ return contractutils.LegacyLoadContractFromJSONFile("MessageCallContract.json")
+}
diff --git a/x/evm/keeper/utils.go b/x/evm/keeper/utils.go
new file mode 100644
index 00000000..3e2ec918
--- /dev/null
+++ b/x/evm/keeper/utils.go
@@ -0,0 +1,17 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package keeper
+
+import (
+ "github.com/cosmos/cosmos-sdk/store/prefix"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// IsContract determines if the given address is a smart contract.
+func (k *Keeper) IsContract(ctx sdk.Context, addr common.Address) bool {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash)
+ return store.Has(addr.Bytes())
+}
diff --git a/x/evm/keeper/utils_test.go b/x/evm/keeper/utils_test.go
new file mode 100644
index 00000000..89e42f7a
--- /dev/null
+++ b/x/evm/keeper/utils_test.go
@@ -0,0 +1,208 @@
+package keeper_test
+
+import (
+ "encoding/json"
+ "math/big"
+ "time"
+
+ "github.com/evmos/evmos/v19/x/evm/keeper/testdata"
+
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/server/config"
+ "github.com/evmos/evmos/v19/testutil"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ "github.com/stretchr/testify/require"
+)
+
+func (suite *KeeperTestSuite) EvmDenom() string {
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ rsp, _ := suite.queryClient.Params(ctx, &evmtypes.QueryParamsRequest{})
+ return rsp.Params.EvmDenom
+}
+
+// Commit and begin new block
+func (suite *KeeperTestSuite) Commit() {
+ var err error
+ suite.ctx, err = testutil.CommitAndCreateNewCtx(suite.ctx, suite.app, 0*time.Second, nil)
+ suite.Require().NoError(err)
+
+ queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
+ evmtypes.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
+ suite.queryClient = evmtypes.NewQueryClient(queryHelper)
+}
+
+func (suite *KeeperTestSuite) StateDB() *statedb.StateDB {
+ return statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes())))
+}
+
+// DeployTestContract deploy a test erc20 contract and returns the contract address
+func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, owner common.Address, supply *big.Int) common.Address {
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ chainID := suite.app.EvmKeeper.ChainID()
+
+ erc20Contract, err := testdata.LoadERC20Contract()
+ require.NoError(t, err, "failed to load contract")
+
+ ctorArgs, err := erc20Contract.ABI.Pack("", owner, supply)
+ require.NoError(t, err)
+
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+
+ data := erc20Contract.Bin
+ data = append(data, ctorArgs...)
+ args, err := json.Marshal(&evmtypes.TransactionArgs{
+ From: &suite.address,
+ Data: (*hexutil.Bytes)(&data),
+ })
+ require.NoError(t, err)
+ res, err := suite.queryClient.EstimateGas(ctx, &evmtypes.EthCallRequest{
+ Args: args,
+ GasCap: config.DefaultGasCap,
+ ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
+ })
+ require.NoError(t, err)
+
+ var erc20DeployTx *evmtypes.MsgEthereumTx
+ if suite.enableFeemarket {
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ GasLimit: res.Gas,
+ GasFeeCap: suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx),
+ GasTipCap: big.NewInt(1),
+ Input: data,
+ Accesses: ðtypes.AccessList{},
+ }
+ erc20DeployTx = evmtypes.NewTx(ethTxParams)
+ } else {
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ GasLimit: res.Gas,
+ Input: data,
+ }
+ erc20DeployTx = evmtypes.NewTx(ethTxParams)
+ }
+
+ erc20DeployTx.From = suite.address.Hex()
+ err = erc20DeployTx.Sign(ethtypes.LatestSignerForChainID(chainID), suite.signer)
+ require.NoError(t, err)
+ rsp, err := suite.app.EvmKeeper.EthereumTx(ctx, erc20DeployTx)
+ require.NoError(t, err)
+ require.Empty(t, rsp.VmError)
+ return crypto.CreateAddress(suite.address, nonce)
+}
+
+func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAddr, from, to common.Address, amount *big.Int) *evmtypes.MsgEthereumTx {
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ chainID := suite.app.EvmKeeper.ChainID()
+
+ erc20Contract, err := testdata.LoadERC20Contract()
+ require.NoError(t, err, "failed to load contract")
+
+ transferData, err := erc20Contract.ABI.Pack("transfer", to, amount)
+ require.NoError(t, err)
+ args, err := json.Marshal(&evmtypes.TransactionArgs{To: &contractAddr, From: &from, Data: (*hexutil.Bytes)(&transferData)})
+ require.NoError(t, err)
+ res, err := suite.queryClient.EstimateGas(ctx, &evmtypes.EthCallRequest{
+ Args: args,
+ GasCap: 25_000_000,
+ ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
+ })
+ require.NoError(t, err)
+
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+
+ var ercTransferTx *evmtypes.MsgEthereumTx
+ if suite.enableFeemarket {
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ To: &contractAddr,
+ GasLimit: res.Gas,
+ GasFeeCap: suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx),
+ GasTipCap: big.NewInt(1),
+ Input: transferData,
+ Accesses: ðtypes.AccessList{},
+ }
+ ercTransferTx = evmtypes.NewTx(ethTxParams)
+ } else {
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ To: &contractAddr,
+ GasLimit: res.Gas,
+ Input: transferData,
+ }
+ ercTransferTx = evmtypes.NewTx(ethTxParams)
+ }
+
+ ercTransferTx.From = suite.address.Hex()
+ err = ercTransferTx.Sign(ethtypes.LatestSignerForChainID(chainID), suite.signer)
+ require.NoError(t, err)
+ rsp, err := suite.app.EvmKeeper.EthereumTx(ctx, ercTransferTx)
+ require.NoError(t, err)
+ require.Empty(t, rsp.VmError)
+ return ercTransferTx
+}
+
+// DeployTestMessageCall deploy a test erc20 contract and returns the contract address
+func (suite *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.Address {
+ ctx := sdk.WrapSDKContext(suite.ctx)
+ chainID := suite.app.EvmKeeper.ChainID()
+
+ testMessageCallContract, err := testdata.LoadMessageCallContract()
+ require.NoError(t, err, "failed to load contract")
+
+ data := testMessageCallContract.Bin
+ args, err := json.Marshal(&evmtypes.TransactionArgs{
+ From: &suite.address,
+ Data: (*hexutil.Bytes)(&data),
+ })
+ require.NoError(t, err)
+
+ res, err := suite.queryClient.EstimateGas(ctx, &evmtypes.EthCallRequest{
+ Args: args,
+ GasCap: config.DefaultGasCap,
+ ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
+ })
+ require.NoError(t, err)
+
+ nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
+
+ var erc20DeployTx *evmtypes.MsgEthereumTx
+ if suite.enableFeemarket {
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ GasLimit: res.Gas,
+ Input: data,
+ GasFeeCap: suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx),
+ Accesses: ðtypes.AccessList{},
+ GasTipCap: big.NewInt(1),
+ }
+ erc20DeployTx = evmtypes.NewTx(ethTxParams)
+ } else {
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ GasLimit: res.Gas,
+ Input: data,
+ }
+ erc20DeployTx = evmtypes.NewTx(ethTxParams)
+ }
+
+ erc20DeployTx.From = suite.address.Hex()
+ err = erc20DeployTx.Sign(ethtypes.LatestSignerForChainID(chainID), suite.signer)
+ require.NoError(t, err)
+ rsp, err := suite.app.EvmKeeper.EthereumTx(ctx, erc20DeployTx)
+ require.NoError(t, err)
+ require.Empty(t, rsp.VmError)
+ return crypto.CreateAddress(suite.address, nonce)
+}
diff --git a/x/evm/migrations/v7/migrate.go b/x/evm/migrations/v7/migrate.go
new file mode 100644
index 00000000..9f6bc9ed
--- /dev/null
+++ b/x/evm/migrations/v7/migrate.go
@@ -0,0 +1,82 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package v7
+
+import (
+ "fmt"
+
+ "github.com/cosmos/cosmos-sdk/codec"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ v6types "github.com/evmos/evmos/v19/x/evm/migrations/v7/types"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// MigrateStore migrates the x/evm module state from the consensus version 6 to
+// version 7. Specifically, it changes the type of the Params ExtraEIPs from
+// []int64 to []string and introduces the access control.
+func MigrateStore(
+ ctx sdk.Context,
+ storeKey storetypes.StoreKey,
+ cdc codec.BinaryCodec,
+) error {
+ var (
+ paramsV6 v6types.V6Params
+ params types.Params
+ )
+
+ store := ctx.KVStore(storeKey)
+
+ paramsV6Bz := store.Get(types.KeyPrefixParams)
+ cdc.MustUnmarshal(paramsV6Bz, ¶msV6)
+
+ params.EvmDenom = paramsV6.EvmDenom
+ params.ChainConfig = types.ChainConfig{
+ HomesteadBlock: paramsV6.ChainConfig.HomesteadBlock,
+ DAOForkBlock: paramsV6.ChainConfig.DAOForkBlock,
+ DAOForkSupport: paramsV6.ChainConfig.DAOForkSupport,
+ EIP150Block: paramsV6.ChainConfig.EIP150Block,
+ EIP150Hash: paramsV6.ChainConfig.EIP150Hash,
+ EIP155Block: paramsV6.ChainConfig.EIP155Block,
+ EIP158Block: paramsV6.ChainConfig.EIP158Block,
+ ByzantiumBlock: paramsV6.ChainConfig.ByzantiumBlock,
+ ConstantinopleBlock: paramsV6.ChainConfig.ConstantinopleBlock,
+ PetersburgBlock: paramsV6.ChainConfig.PetersburgBlock,
+ IstanbulBlock: paramsV6.ChainConfig.IstanbulBlock,
+ MuirGlacierBlock: paramsV6.ChainConfig.MuirGlacierBlock,
+ BerlinBlock: paramsV6.ChainConfig.BerlinBlock,
+ LondonBlock: paramsV6.ChainConfig.LondonBlock,
+ ArrowGlacierBlock: paramsV6.ChainConfig.ArrowGlacierBlock,
+ GrayGlacierBlock: paramsV6.ChainConfig.GrayGlacierBlock,
+ MergeNetsplitBlock: paramsV6.ChainConfig.MergeNetsplitBlock,
+ ShanghaiBlock: paramsV6.ChainConfig.ShanghaiBlock,
+ CancunBlock: paramsV6.ChainConfig.CancunBlock,
+ }
+ params.AllowUnprotectedTxs = paramsV6.AllowUnprotectedTxs
+ params.ActiveStaticPrecompiles = paramsV6.ActivePrecompiles
+ params.EVMChannels = paramsV6.EVMChannels
+
+ // set the default access control configuration
+ params.AccessControl = types.DefaultAccessControl
+
+ // Migrate old ExtraEIPs from int64 to string. Since no Evmos EIPs have been
+ // created before and activators contains only `ethereum_XXXX` activations,
+ // all values will be prefixed with `ethereum_`.
+ params.ExtraEIPs = make([]string, 0, len(paramsV6.ExtraEIPs))
+ for _, eip := range paramsV6.ExtraEIPs {
+ eipName := fmt.Sprintf("ethereum_%d", eip)
+ params.ExtraEIPs = append(params.ExtraEIPs, eipName)
+ }
+
+ if err := params.Validate(); err != nil {
+ return err
+ }
+
+ bz := cdc.MustMarshal(¶ms)
+
+ store.Set(types.KeyPrefixParams, bz)
+
+ return nil
+}
diff --git a/x/evm/migrations/v7/migrate_test.go b/x/evm/migrations/v7/migrate_test.go
new file mode 100644
index 00000000..e191ea26
--- /dev/null
+++ b/x/evm/migrations/v7/migrate_test.go
@@ -0,0 +1,63 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package v7_test
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/cosmos/cosmos-sdk/testutil"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/stretchr/testify/require"
+
+ "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/encoding"
+ v7 "github.com/evmos/evmos/v19/x/evm/migrations/v7"
+ v6types "github.com/evmos/evmos/v19/x/evm/migrations/v7/types"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func TestMigrate(t *testing.T) {
+ encCfg := encoding.MakeConfig(app.ModuleBasics)
+ cdc := encCfg.Codec
+
+ // Initialize the store
+ storeKey := sdk.NewKVStoreKey(types.ModuleName)
+ tKey := sdk.NewTransientStoreKey("transient_storekey")
+ ctx := testutil.DefaultContext(storeKey, tKey)
+ kvStore := ctx.KVStore(storeKey)
+
+ chainConfig := types.DefaultChainConfig()
+ bz, err := json.Marshal(chainConfig)
+ require.NoError(t, err)
+ var chainCfgV6 v6types.V6ChainConfig
+ err = json.Unmarshal(bz, &chainCfgV6)
+ require.NoError(t, err)
+
+ // Create a pre migration environment with default params.
+ paramsV6 := v6types.V6Params{
+ EvmDenom: types.DefaultEVMDenom,
+ ChainConfig: chainCfgV6,
+ ExtraEIPs: v6types.DefaultExtraEIPs,
+ AllowUnprotectedTxs: types.DefaultAllowUnprotectedTxs,
+ ActivePrecompiles: types.DefaultStaticPrecompiles,
+ EVMChannels: types.DefaultEVMChannels,
+ }
+ paramsV6Bz := cdc.MustMarshal(¶msV6)
+ kvStore.Set(types.KeyPrefixParams, paramsV6Bz)
+
+ err = v7.MigrateStore(ctx, storeKey, cdc)
+ require.NoError(t, err)
+
+ paramsBz := kvStore.Get(types.KeyPrefixParams)
+ var params types.Params
+ cdc.MustUnmarshal(paramsBz, ¶ms)
+
+ require.Equal(t, types.DefaultEVMDenom, params.EvmDenom)
+ require.False(t, params.AllowUnprotectedTxs)
+ require.Equal(t, chainConfig, params.ChainConfig)
+ require.Equal(t, types.DefaultExtraEIPs, params.ExtraEIPs)
+ require.Equal(t, types.DefaultEVMChannels, params.EVMChannels)
+ require.Equal(t, types.DefaultAccessControl, params.AccessControl)
+}
diff --git a/x/evm/migrations/v7/types/evm.pb.go b/x/evm/migrations/v7/types/evm.pb.go
new file mode 100644
index 00000000..b8bd3cbc
--- /dev/null
+++ b/x/evm/migrations/v7/types/evm.pb.go
@@ -0,0 +1,4703 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/evm/v1/evm.proto
+
+package types
+
+import (
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ cosmossdk_io_math "cosmossdk.io/math"
+
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ proto "github.com/cosmos/gogoproto/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = proto.Marshal
+ _ = fmt.Errorf
+ _ = math.Inf
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// V6AccessType defines the types of permissions for the operations
+type V6AccessType int32
+
+const (
+ // ACCESS_TYPE_PERMISSIONLESS does not restrict the operation to anyone
+ AccessTypePermissionless V6AccessType = 0
+ // ACCESS_TYPE_RESTRICTED restrict the operation to anyone
+ AccessTypeRestricted V6AccessType = 1
+ // ACCESS_TYPE_PERMISSIONED only allows the operation for specific addresses
+ AccessTypePermissioned V6AccessType = 2
+)
+
+var V6AccessType_name = map[int32]string{
+ 0: "ACCESS_TYPE_PERMISSIONLESS",
+ 1: "ACCESS_TYPE_RESTRICTED",
+ 2: "ACCESS_TYPE_PERMISSIONED",
+}
+
+var V6AccessType_value = map[string]int32{
+ "ACCESS_TYPE_PERMISSIONLESS": 0,
+ "ACCESS_TYPE_RESTRICTED": 1,
+ "ACCESS_TYPE_PERMISSIONED": 2,
+}
+
+func (x V6AccessType) String() string {
+ return proto.EnumName(V6AccessType_name, int32(x))
+}
+
+func (V6AccessType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{0}
+}
+
+// V6Params defines the EVM module parameters
+type V6Params struct {
+ // evm_denom represents the token denomination used to run the EVM state
+ // transitions.
+ EvmDenom string `protobuf:"bytes,1,opt,name=evm_denom,json=evmDenom,proto3" json:"evm_denom,omitempty" yaml:"evm_denom"`
+ // extra_eips defines the additional EIPs for the vm.Config
+ ExtraEIPs []int64 `protobuf:"varint,4,rep,packed,name=extra_eips,json=extraEips,proto3" json:"extra_eips,omitempty" yaml:"extra_eips"`
+ // chain_config defines the EVM chain configuration parameters
+ ChainConfig V6ChainConfig `protobuf:"bytes,5,opt,name=chain_config,json=chainConfig,proto3" json:"chain_config" yaml:"chain_config"`
+ // allow_unprotected_txs defines if replay-protected (i.e non EIP155
+ // signed) transactions can be executed on the state machine.
+ AllowUnprotectedTxs bool `protobuf:"varint,6,opt,name=allow_unprotected_txs,json=allowUnprotectedTxs,proto3" json:"allow_unprotected_txs,omitempty"`
+ // active_precompiles defines the slice of hex addresses of the precompiled
+ // contracts that are active
+ ActivePrecompiles []string `protobuf:"bytes,7,rep,name=active_precompiles,json=activePrecompiles,proto3" json:"active_precompiles,omitempty"`
+ // evm_channels is the list of channel identifiers from EVM compatible chains
+ EVMChannels []string `protobuf:"bytes,8,rep,name=evm_channels,json=evmChannels,proto3" json:"evm_channels,omitempty"`
+ // access_control defines the permission policy of the EVM
+ AccessControl V6AccessControl `protobuf:"bytes,9,opt,name=access_control,json=accessControl,proto3" json:"access_control"`
+}
+
+func (m *V6Params) Reset() { *m = V6Params{} }
+func (m *V6Params) String() string { return proto.CompactTextString(m) }
+func (*V6Params) ProtoMessage() {}
+func (*V6Params) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{0}
+}
+
+func (m *V6Params) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Params.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6Params) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Params.Merge(m, src)
+}
+
+func (m *V6Params) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6Params) XXX_DiscardUnknown() {
+ xxx_messageInfo_Params.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Params proto.InternalMessageInfo
+
+func (m *V6Params) GetEvmDenom() string {
+ if m != nil {
+ return m.EvmDenom
+ }
+ return ""
+}
+
+func (m *V6Params) GetExtraEIPs() []int64 {
+ if m != nil {
+ return m.ExtraEIPs
+ }
+ return nil
+}
+
+func (m *V6Params) GetChainConfig() V6ChainConfig {
+ if m != nil {
+ return m.ChainConfig
+ }
+ return V6ChainConfig{}
+}
+
+func (m *V6Params) GetAllowUnprotectedTxs() bool {
+ if m != nil {
+ return m.AllowUnprotectedTxs
+ }
+ return false
+}
+
+func (m *V6Params) GetActivePrecompiles() []string {
+ if m != nil {
+ return m.ActivePrecompiles
+ }
+ return nil
+}
+
+func (m *V6Params) GetEVMChannels() []string {
+ if m != nil {
+ return m.EVMChannels
+ }
+ return nil
+}
+
+func (m *V6Params) GetAccessControl() V6AccessControl {
+ if m != nil {
+ return m.AccessControl
+ }
+ return V6AccessControl{}
+}
+
+// V6AccessControl defines the permission policy of the EVM
+// for creating and calling contracts
+type V6AccessControl struct {
+ // create defines the permission policy for creating contracts
+ Create V6AccessControlType `protobuf:"bytes,1,opt,name=create,proto3" json:"create"`
+ // call defines the permission policy for calling contracts
+ Call V6AccessControlType `protobuf:"bytes,2,opt,name=call,proto3" json:"call"`
+}
+
+func (m *V6AccessControl) Reset() { *m = V6AccessControl{} }
+func (m *V6AccessControl) String() string { return proto.CompactTextString(m) }
+func (*V6AccessControl) ProtoMessage() {}
+func (*V6AccessControl) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{1}
+}
+
+func (m *V6AccessControl) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6AccessControl) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_AccessControl.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6AccessControl) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccessControl.Merge(m, src)
+}
+
+func (m *V6AccessControl) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6AccessControl) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccessControl.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccessControl proto.InternalMessageInfo
+
+func (m *V6AccessControl) GetCreate() V6AccessControlType {
+ if m != nil {
+ return m.Create
+ }
+ return V6AccessControlType{}
+}
+
+func (m *V6AccessControl) GetCall() V6AccessControlType {
+ if m != nil {
+ return m.Call
+ }
+ return V6AccessControlType{}
+}
+
+// V6AccessControlType defines the permission type for policies
+type V6AccessControlType struct {
+ // access_type defines which type of permission is required for the operation
+ AccessType V6AccessType `protobuf:"varint,1,opt,name=access_type,json=accessType,proto3,enum=ethermint.evm.v1.AccessType" json:"access_type,omitempty" yaml:"access_type"`
+ // access_control_list defines defines different things depending on the AccessType:
+ // - ACCESS_TYPE_PERMISSIONLESS: list of addresses that are blocked from performing the operation
+ // - ACCESS_TYPE_RESTRICTED: ignored
+ // - ACCESS_TYPE_PERMISSIONED: list of addresses that are allowed to perform the operation
+ AccessControlList []string `protobuf:"bytes,2,rep,name=access_control_list,json=accessControlList,proto3" json:"access_control_list,omitempty" yaml:"access_control_list"`
+}
+
+func (m *V6AccessControlType) Reset() { *m = V6AccessControlType{} }
+func (m *V6AccessControlType) String() string { return proto.CompactTextString(m) }
+func (*V6AccessControlType) ProtoMessage() {}
+func (*V6AccessControlType) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{2}
+}
+
+func (m *V6AccessControlType) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6AccessControlType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_AccessControlType.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6AccessControlType) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccessControlType.Merge(m, src)
+}
+
+func (m *V6AccessControlType) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6AccessControlType) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccessControlType.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccessControlType proto.InternalMessageInfo
+
+func (m *V6AccessControlType) GetAccessType() V6AccessType {
+ if m != nil {
+ return m.AccessType
+ }
+ return AccessTypePermissionless
+}
+
+func (m *V6AccessControlType) GetAccessControlList() []string {
+ if m != nil {
+ return m.AccessControlList
+ }
+ return nil
+}
+
+// V6ChainConfig defines the Ethereum V6ChainConfig parameters using *sdk.Int values
+// instead of *big.Int.
+type V6ChainConfig struct {
+ // homestead_block switch (nil no fork, 0 = already homestead)
+ HomesteadBlock *cosmossdk_io_math.Int `protobuf:"bytes,1,opt,name=homestead_block,json=homesteadBlock,proto3,customtype=cosmossdk.io/math.Int" json:"homestead_block,omitempty" yaml:"homestead_block"`
+ // dao_fork_block corresponds to TheDAO hard-fork switch block (nil no fork)
+ DAOForkBlock *cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=dao_fork_block,json=daoForkBlock,proto3,customtype=cosmossdk.io/math.Int" json:"dao_fork_block,omitempty" yaml:"dao_fork_block"`
+ // dao_fork_support defines whether the nodes supports or opposes the DAO hard-fork
+ DAOForkSupport bool `protobuf:"varint,3,opt,name=dao_fork_support,json=daoForkSupport,proto3" json:"dao_fork_support,omitempty" yaml:"dao_fork_support"`
+ // eip150_block: EIP150 implements the Gas price changes
+ // (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no fork)
+ EIP150Block *cosmossdk_io_math.Int `protobuf:"bytes,4,opt,name=eip150_block,json=eip150Block,proto3,customtype=cosmossdk.io/math.Int" json:"eip150_block,omitempty" yaml:"eip150_block"`
+ // eip150_hash: EIP150 HF hash (needed for header only clients as only gas pricing changed)
+ EIP150Hash string `protobuf:"bytes,5,opt,name=eip150_hash,json=eip150Hash,proto3" json:"eip150_hash,omitempty" yaml:"byzantium_block"`
+ // eip155_block: EIP155Block HF block
+ EIP155Block *cosmossdk_io_math.Int `protobuf:"bytes,6,opt,name=eip155_block,json=eip155Block,proto3,customtype=cosmossdk.io/math.Int" json:"eip155_block,omitempty" yaml:"eip155_block"`
+ // eip158_block: EIP158 HF block
+ EIP158Block *cosmossdk_io_math.Int `protobuf:"bytes,7,opt,name=eip158_block,json=eip158Block,proto3,customtype=cosmossdk.io/math.Int" json:"eip158_block,omitempty" yaml:"eip158_block"`
+ // byzantium_block: Byzantium switch block (nil no fork, 0 = already on byzantium)
+ ByzantiumBlock *cosmossdk_io_math.Int `protobuf:"bytes,8,opt,name=byzantium_block,json=byzantiumBlock,proto3,customtype=cosmossdk.io/math.Int" json:"byzantium_block,omitempty" yaml:"byzantium_block"`
+ // constantinople_block: Constantinople switch block (nil no fork, 0 = already activated)
+ ConstantinopleBlock *cosmossdk_io_math.Int `protobuf:"bytes,9,opt,name=constantinople_block,json=constantinopleBlock,proto3,customtype=cosmossdk.io/math.Int" json:"constantinople_block,omitempty" yaml:"constantinople_block"`
+ // petersburg_block: Petersburg switch block (nil same as Constantinople)
+ PetersburgBlock *cosmossdk_io_math.Int `protobuf:"bytes,10,opt,name=petersburg_block,json=petersburgBlock,proto3,customtype=cosmossdk.io/math.Int" json:"petersburg_block,omitempty" yaml:"petersburg_block"`
+ // istanbul_block: Istanbul switch block (nil no fork, 0 = already on istanbul)
+ IstanbulBlock *cosmossdk_io_math.Int `protobuf:"bytes,11,opt,name=istanbul_block,json=istanbulBlock,proto3,customtype=cosmossdk.io/math.Int" json:"istanbul_block,omitempty" yaml:"istanbul_block"`
+ // muir_glacier_block: Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated)
+ MuirGlacierBlock *cosmossdk_io_math.Int `protobuf:"bytes,12,opt,name=muir_glacier_block,json=muirGlacierBlock,proto3,customtype=cosmossdk.io/math.Int" json:"muir_glacier_block,omitempty" yaml:"muir_glacier_block"`
+ // berlin_block: Berlin switch block (nil = no fork, 0 = already on berlin)
+ BerlinBlock *cosmossdk_io_math.Int `protobuf:"bytes,13,opt,name=berlin_block,json=berlinBlock,proto3,customtype=cosmossdk.io/math.Int" json:"berlin_block,omitempty" yaml:"berlin_block"`
+ // london_block: London switch block (nil = no fork, 0 = already on london)
+ LondonBlock *cosmossdk_io_math.Int `protobuf:"bytes,17,opt,name=london_block,json=londonBlock,proto3,customtype=cosmossdk.io/math.Int" json:"london_block,omitempty" yaml:"london_block"`
+ // arrow_glacier_block: Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
+ ArrowGlacierBlock *cosmossdk_io_math.Int `protobuf:"bytes,18,opt,name=arrow_glacier_block,json=arrowGlacierBlock,proto3,customtype=cosmossdk.io/math.Int" json:"arrow_glacier_block,omitempty" yaml:"arrow_glacier_block"`
+ // gray_glacier_block: EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
+ GrayGlacierBlock *cosmossdk_io_math.Int `protobuf:"bytes,20,opt,name=gray_glacier_block,json=grayGlacierBlock,proto3,customtype=cosmossdk.io/math.Int" json:"gray_glacier_block,omitempty" yaml:"gray_glacier_block"`
+ // merge_netsplit_block: Virtual fork after The Merge to use as a network splitter
+ MergeNetsplitBlock *cosmossdk_io_math.Int `protobuf:"bytes,21,opt,name=merge_netsplit_block,json=mergeNetsplitBlock,proto3,customtype=cosmossdk.io/math.Int" json:"merge_netsplit_block,omitempty" yaml:"merge_netsplit_block"`
+ // shanghai_block switch block (nil = no fork, 0 = already on shanghai)
+ ShanghaiBlock *cosmossdk_io_math.Int `protobuf:"bytes,22,opt,name=shanghai_block,json=shanghaiBlock,proto3,customtype=cosmossdk.io/math.Int" json:"shanghai_block,omitempty" yaml:"shanghai_block"`
+ // cancun_block switch block (nil = no fork, 0 = already on cancun)
+ CancunBlock *cosmossdk_io_math.Int `protobuf:"bytes,23,opt,name=cancun_block,json=cancunBlock,proto3,customtype=cosmossdk.io/math.Int" json:"cancun_block,omitempty" yaml:"cancun_block"`
+}
+
+func (m *V6ChainConfig) Reset() { *m = V6ChainConfig{} }
+func (m *V6ChainConfig) String() string { return proto.CompactTextString(m) }
+func (*V6ChainConfig) ProtoMessage() {}
+func (*V6ChainConfig) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{3}
+}
+
+func (m *V6ChainConfig) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6ChainConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ChainConfig.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6ChainConfig) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ChainConfig.Merge(m, src)
+}
+
+func (m *V6ChainConfig) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6ChainConfig) XXX_DiscardUnknown() {
+ xxx_messageInfo_ChainConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ChainConfig proto.InternalMessageInfo
+
+func (m *V6ChainConfig) GetDAOForkSupport() bool {
+ if m != nil {
+ return m.DAOForkSupport
+ }
+ return false
+}
+
+func (m *V6ChainConfig) GetEIP150Hash() string {
+ if m != nil {
+ return m.EIP150Hash
+ }
+ return ""
+}
+
+// V6State represents a single Storage key value pair item.
+type V6State struct {
+ // key is the stored key
+ Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // value is the stored value for the given key
+ Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *V6State) Reset() { *m = V6State{} }
+func (m *V6State) String() string { return proto.CompactTextString(m) }
+func (*V6State) ProtoMessage() {}
+func (*V6State) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{4}
+}
+
+func (m *V6State) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6State) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_State.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6State) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_State.Merge(m, src)
+}
+
+func (m *V6State) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6State) XXX_DiscardUnknown() {
+ xxx_messageInfo_State.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_State proto.InternalMessageInfo
+
+func (m *V6State) GetKey() string {
+ if m != nil {
+ return m.Key
+ }
+ return ""
+}
+
+func (m *V6State) GetValue() string {
+ if m != nil {
+ return m.Value
+ }
+ return ""
+}
+
+// V6TransactionLogs define the logs generated from a transaction execution
+// with a given hash. It it used for import/export data as transactions are not
+// persisted on blockchain state after an upgrade.
+type V6TransactionLogs struct {
+ // hash of the transaction
+ Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
+ // logs is an array of Logs for the given transaction hash
+ Logs []*V6Log `protobuf:"bytes,2,rep,name=logs,proto3" json:"logs,omitempty"`
+}
+
+func (m *V6TransactionLogs) Reset() { *m = V6TransactionLogs{} }
+func (m *V6TransactionLogs) String() string { return proto.CompactTextString(m) }
+func (*V6TransactionLogs) ProtoMessage() {}
+func (*V6TransactionLogs) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{5}
+}
+
+func (m *V6TransactionLogs) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6TransactionLogs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_TransactionLogs.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6TransactionLogs) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TransactionLogs.Merge(m, src)
+}
+
+func (m *V6TransactionLogs) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6TransactionLogs) XXX_DiscardUnknown() {
+ xxx_messageInfo_TransactionLogs.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TransactionLogs proto.InternalMessageInfo
+
+func (m *V6TransactionLogs) GetHash() string {
+ if m != nil {
+ return m.Hash
+ }
+ return ""
+}
+
+func (m *V6TransactionLogs) GetLogs() []*V6Log {
+ if m != nil {
+ return m.Logs
+ }
+ return nil
+}
+
+// V6Log represents an protobuf compatible Ethereum V6Log that defines a contract
+// log event. These events are generated by the LOG opcode and stored/indexed by
+// the node.
+//
+// NOTE: address, topics and data are consensus fields. The rest of the fields
+// are derived, i.e. filled in by the nodes, but not secured by consensus.
+type V6Log struct {
+ // address of the contract that generated the event
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ // topics is a list of topics provided by the contract.
+ Topics []string `protobuf:"bytes,2,rep,name=topics,proto3" json:"topics,omitempty"`
+ // data which is supplied by the contract, usually ABI-encoded
+ Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
+ // block_number of the block in which the transaction was included
+ BlockNumber uint64 `protobuf:"varint,4,opt,name=block_number,json=blockNumber,proto3" json:"blockNumber"`
+ // tx_hash is the transaction hash
+ TxHash string `protobuf:"bytes,5,opt,name=tx_hash,json=txHash,proto3" json:"transactionHash"`
+ // tx_index of the transaction in the block
+ TxIndex uint64 `protobuf:"varint,6,opt,name=tx_index,json=txIndex,proto3" json:"transactionIndex"`
+ // block_hash of the block in which the transaction was included
+ BlockHash string `protobuf:"bytes,7,opt,name=block_hash,json=blockHash,proto3" json:"blockHash"`
+ // index of the log in the block
+ Index uint64 `protobuf:"varint,8,opt,name=index,proto3" json:"logIndex"`
+ // removed is true if this log was reverted due to a chain
+ // reorganisation. You must pay attention to this field if you receive logs
+ // through a filter query.
+ Removed bool `protobuf:"varint,9,opt,name=removed,proto3" json:"removed,omitempty"`
+}
+
+func (m *V6Log) Reset() { *m = V6Log{} }
+func (m *V6Log) String() string { return proto.CompactTextString(m) }
+func (*V6Log) ProtoMessage() {}
+func (*V6Log) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{6}
+}
+
+func (m *V6Log) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6Log) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Log.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6Log) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Log.Merge(m, src)
+}
+
+func (m *V6Log) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6Log) XXX_DiscardUnknown() {
+ xxx_messageInfo_Log.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Log proto.InternalMessageInfo
+
+func (m *V6Log) GetAddress() string {
+ if m != nil {
+ return m.Address
+ }
+ return ""
+}
+
+func (m *V6Log) GetTopics() []string {
+ if m != nil {
+ return m.Topics
+ }
+ return nil
+}
+
+func (m *V6Log) GetData() []byte {
+ if m != nil {
+ return m.Data
+ }
+ return nil
+}
+
+func (m *V6Log) GetBlockNumber() uint64 {
+ if m != nil {
+ return m.BlockNumber
+ }
+ return 0
+}
+
+func (m *V6Log) GetTxHash() string {
+ if m != nil {
+ return m.TxHash
+ }
+ return ""
+}
+
+func (m *V6Log) GetTxIndex() uint64 {
+ if m != nil {
+ return m.TxIndex
+ }
+ return 0
+}
+
+func (m *V6Log) GetBlockHash() string {
+ if m != nil {
+ return m.BlockHash
+ }
+ return ""
+}
+
+func (m *V6Log) GetIndex() uint64 {
+ if m != nil {
+ return m.Index
+ }
+ return 0
+}
+
+func (m *V6Log) GetRemoved() bool {
+ if m != nil {
+ return m.Removed
+ }
+ return false
+}
+
+// V6TxResult stores results of Tx execution.
+type V6TxResult struct {
+ // contract_address contains the ethereum address of the created contract (if
+ // any). If the state transition is an evm.Call, the contract address will be
+ // empty.
+ ContractAddress string `protobuf:"bytes,1,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty" yaml:"contract_address"`
+ // bloom represents the bloom filter bytes
+ Bloom []byte `protobuf:"bytes,2,opt,name=bloom,proto3" json:"bloom,omitempty"`
+ // tx_logs contains the transaction hash and the proto-compatible ethereum
+ // logs.
+ TxLogs V6TransactionLogs `protobuf:"bytes,3,opt,name=tx_logs,json=txLogs,proto3" json:"tx_logs" yaml:"tx_logs"`
+ // ret defines the bytes from the execution.
+ Ret []byte `protobuf:"bytes,4,opt,name=ret,proto3" json:"ret,omitempty"`
+ // reverted flag is set to true when the call has been reverted
+ Reverted bool `protobuf:"varint,5,opt,name=reverted,proto3" json:"reverted,omitempty"`
+ // gas_used notes the amount of gas consumed while execution
+ GasUsed uint64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
+}
+
+func (m *V6TxResult) Reset() { *m = V6TxResult{} }
+func (m *V6TxResult) String() string { return proto.CompactTextString(m) }
+func (*V6TxResult) ProtoMessage() {}
+func (*V6TxResult) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{7}
+}
+
+func (m *V6TxResult) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6TxResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_TxResult.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6TxResult) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TxResult.Merge(m, src)
+}
+
+func (m *V6TxResult) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6TxResult) XXX_DiscardUnknown() {
+ xxx_messageInfo_TxResult.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TxResult proto.InternalMessageInfo
+
+// V6AccessTuple is the element type of an access list.
+type V6AccessTuple struct {
+ // address is a hex formatted ethereum address
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ // storage_keys are hex formatted hashes of the storage keys
+ StorageKeys []string `protobuf:"bytes,2,rep,name=storage_keys,json=storageKeys,proto3" json:"storageKeys"`
+}
+
+func (m *V6AccessTuple) Reset() { *m = V6AccessTuple{} }
+func (m *V6AccessTuple) String() string { return proto.CompactTextString(m) }
+func (*V6AccessTuple) ProtoMessage() {}
+func (*V6AccessTuple) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{8}
+}
+
+func (m *V6AccessTuple) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6AccessTuple) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_AccessTuple.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6AccessTuple) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccessTuple.Merge(m, src)
+}
+
+func (m *V6AccessTuple) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6AccessTuple) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccessTuple.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccessTuple proto.InternalMessageInfo
+
+// V6TraceConfig holds extra parameters to trace functions.
+type V6TraceConfig struct {
+ // tracer is a custom javascript tracer
+ Tracer string `protobuf:"bytes,1,opt,name=tracer,proto3" json:"tracer,omitempty"`
+ // timeout overrides the default timeout of 5 seconds for JavaScript-based tracing
+ // calls
+ Timeout string `protobuf:"bytes,2,opt,name=timeout,proto3" json:"timeout,omitempty"`
+ // reexec defines the number of blocks the tracer is willing to go back
+ Reexec uint64 `protobuf:"varint,3,opt,name=reexec,proto3" json:"reexec,omitempty"`
+ // disable_stack switches stack capture
+ DisableStack bool `protobuf:"varint,5,opt,name=disable_stack,json=disableStack,proto3" json:"disableStack"`
+ // disable_storage switches storage capture
+ DisableStorage bool `protobuf:"varint,6,opt,name=disable_storage,json=disableStorage,proto3" json:"disableStorage"`
+ // debug can be used to print output during capture end
+ Debug bool `protobuf:"varint,8,opt,name=debug,proto3" json:"debug,omitempty"`
+ // limit defines the maximum length of output, but zero means unlimited
+ Limit int32 `protobuf:"varint,9,opt,name=limit,proto3" json:"limit,omitempty"`
+ // overrides can be used to execute a trace using future fork rules
+ Overrides *V6ChainConfig `protobuf:"bytes,10,opt,name=overrides,proto3" json:"overrides,omitempty"`
+ // enable_memory switches memory capture
+ EnableMemory bool `protobuf:"varint,11,opt,name=enable_memory,json=enableMemory,proto3" json:"enableMemory"`
+ // enable_return_data switches the capture of return data
+ EnableReturnData bool `protobuf:"varint,12,opt,name=enable_return_data,json=enableReturnData,proto3" json:"enableReturnData"`
+ // tracer_json_config configures the tracer using a JSON string
+ TracerJsonConfig string `protobuf:"bytes,13,opt,name=tracer_json_config,json=tracerJsonConfig,proto3" json:"tracerConfig"`
+}
+
+func (m *V6TraceConfig) Reset() { *m = V6TraceConfig{} }
+func (m *V6TraceConfig) String() string { return proto.CompactTextString(m) }
+func (*V6TraceConfig) ProtoMessage() {}
+func (*V6TraceConfig) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{9}
+}
+
+func (m *V6TraceConfig) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *V6TraceConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_TraceConfig.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *V6TraceConfig) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TraceConfig.Merge(m, src)
+}
+
+func (m *V6TraceConfig) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *V6TraceConfig) XXX_DiscardUnknown() {
+ xxx_messageInfo_TraceConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TraceConfig proto.InternalMessageInfo
+
+func (m *V6TraceConfig) GetTracer() string {
+ if m != nil {
+ return m.Tracer
+ }
+ return ""
+}
+
+func (m *V6TraceConfig) GetTimeout() string {
+ if m != nil {
+ return m.Timeout
+ }
+ return ""
+}
+
+func (m *V6TraceConfig) GetReexec() uint64 {
+ if m != nil {
+ return m.Reexec
+ }
+ return 0
+}
+
+func (m *V6TraceConfig) GetDisableStack() bool {
+ if m != nil {
+ return m.DisableStack
+ }
+ return false
+}
+
+func (m *V6TraceConfig) GetDisableStorage() bool {
+ if m != nil {
+ return m.DisableStorage
+ }
+ return false
+}
+
+func (m *V6TraceConfig) GetDebug() bool {
+ if m != nil {
+ return m.Debug
+ }
+ return false
+}
+
+func (m *V6TraceConfig) GetLimit() int32 {
+ if m != nil {
+ return m.Limit
+ }
+ return 0
+}
+
+func (m *V6TraceConfig) GetOverrides() *V6ChainConfig {
+ if m != nil {
+ return m.Overrides
+ }
+ return nil
+}
+
+func (m *V6TraceConfig) GetEnableMemory() bool {
+ if m != nil {
+ return m.EnableMemory
+ }
+ return false
+}
+
+func (m *V6TraceConfig) GetEnableReturnData() bool {
+ if m != nil {
+ return m.EnableReturnData
+ }
+ return false
+}
+
+func (m *V6TraceConfig) GetTracerJsonConfig() string {
+ if m != nil {
+ return m.TracerJsonConfig
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterEnum("ethermint.evm.v1.V6AccessType", V6AccessType_name, V6AccessType_value)
+ proto.RegisterType((*V6Params)(nil), "ethermint.evm.v1.V6Params")
+ proto.RegisterType((*V6AccessControl)(nil), "ethermint.evm.v1.V6AccessControl")
+ proto.RegisterType((*V6AccessControlType)(nil), "ethermint.evm.v1.V6AccessControlType")
+ proto.RegisterType((*V6ChainConfig)(nil), "ethermint.evm.v1.V6ChainConfig")
+ proto.RegisterType((*V6State)(nil), "ethermint.evm.v1.V6State")
+ proto.RegisterType((*V6TransactionLogs)(nil), "ethermint.evm.v1.V6TransactionLogs")
+ proto.RegisterType((*V6Log)(nil), "ethermint.evm.v1.V6Log")
+ proto.RegisterType((*V6TxResult)(nil), "ethermint.evm.v1.V6TxResult")
+ proto.RegisterType((*V6AccessTuple)(nil), "ethermint.evm.v1.V6AccessTuple")
+ proto.RegisterType((*V6TraceConfig)(nil), "ethermint.evm.v1.V6TraceConfig")
+}
+
+func init() { proto.RegisterFile("ethermint/evm/v1/evm.proto", fileDescriptor_d21ecc92c8c8583e) }
+
+var fileDescriptor_d21ecc92c8c8583e = []byte{
+ // 1884 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0xdd, 0x4f, 0x2b, 0xc7,
+ 0x15, 0xc7, 0x78, 0x81, 0xf5, 0xd8, 0xd8, 0xcb, 0x60, 0x88, 0xe3, 0xa4, 0x2c, 0xdd, 0x56, 0x15,
+ 0xad, 0x12, 0xb8, 0x70, 0x43, 0x8b, 0x92, 0x7e, 0x61, 0x70, 0x5a, 0x28, 0xf7, 0x06, 0x8d, 0x49,
+ 0xab, 0x54, 0x8d, 0x56, 0xe3, 0xdd, 0x89, 0xbd, 0x61, 0x77, 0xc7, 0xda, 0x19, 0xfb, 0xda, 0xfd,
+ 0x0b, 0xa2, 0xdb, 0x97, 0xf6, 0x0f, 0xb8, 0x52, 0xa4, 0xfe, 0x23, 0x7d, 0x8c, 0xfa, 0x94, 0xc7,
+ 0xaa, 0x52, 0xb7, 0x95, 0xef, 0x1b, 0x8f, 0xbc, 0x57, 0xaa, 0xe6, 0xc3, 0x9f, 0x10, 0x42, 0x5f,
+ 0x60, 0xce, 0xd7, 0xef, 0x77, 0xce, 0x99, 0xb3, 0x3b, 0xb3, 0x06, 0x55, 0xc2, 0xdb, 0x24, 0x89,
+ 0x82, 0x98, 0xef, 0x91, 0x5e, 0xb4, 0xd7, 0xdb, 0x17, 0xff, 0x76, 0x3b, 0x09, 0xe5, 0x14, 0x5a,
+ 0x63, 0xdb, 0xae, 0x50, 0xf6, 0xf6, 0xab, 0xe5, 0x16, 0x6d, 0x51, 0x69, 0xdc, 0x13, 0x2b, 0xe5,
+ 0xe7, 0xfc, 0x3b, 0x0b, 0x96, 0x2f, 0x71, 0x82, 0x23, 0x06, 0xf7, 0x41, 0x8e, 0xf4, 0x22, 0xd7,
+ 0x27, 0x31, 0x8d, 0x2a, 0x99, 0xed, 0xcc, 0x4e, 0xae, 0x56, 0xbe, 0x4d, 0x6d, 0x6b, 0x80, 0xa3,
+ 0xf0, 0x7d, 0x67, 0x6c, 0x72, 0x90, 0x49, 0x7a, 0xd1, 0xa9, 0x58, 0xc2, 0x63, 0x00, 0x48, 0x9f,
+ 0x27, 0xd8, 0x25, 0x41, 0x87, 0x55, 0x8c, 0xed, 0xec, 0x4e, 0xb6, 0xe6, 0x0c, 0x53, 0x3b, 0x57,
+ 0x17, 0xda, 0xfa, 0xd9, 0x25, 0xbb, 0x4d, 0xed, 0x35, 0x0d, 0x30, 0x76, 0x74, 0x50, 0x4e, 0x0a,
+ 0xf5, 0xa0, 0xc3, 0xe0, 0xa7, 0xa0, 0xe0, 0xb5, 0x71, 0x10, 0xbb, 0x1e, 0x8d, 0x3f, 0x0b, 0x5a,
+ 0x95, 0xa5, 0xed, 0xcc, 0x4e, 0xfe, 0xe0, 0x3b, 0xbb, 0xf3, 0xf9, 0xef, 0x9e, 0x08, 0xaf, 0x13,
+ 0xe9, 0x54, 0x7b, 0xeb, 0xab, 0xd4, 0x5e, 0xb8, 0x4d, 0xed, 0x75, 0x05, 0x3d, 0x0d, 0xe0, 0xa0,
+ 0xbc, 0x37, 0xf1, 0x84, 0x07, 0x60, 0x03, 0x87, 0x21, 0x7d, 0xe1, 0x76, 0x63, 0x51, 0x30, 0xf1,
+ 0x38, 0xf1, 0x5d, 0xde, 0x67, 0x95, 0xe5, 0xed, 0xcc, 0x8e, 0x89, 0xd6, 0xa5, 0xf1, 0xe3, 0x89,
+ 0xed, 0xaa, 0xcf, 0xe0, 0xbb, 0x00, 0x62, 0x8f, 0x07, 0x3d, 0xe2, 0x76, 0x12, 0xe2, 0xd1, 0xa8,
+ 0x13, 0x84, 0x84, 0x55, 0x56, 0xb6, 0xb3, 0x3b, 0x39, 0xb4, 0xa6, 0x2c, 0x97, 0x13, 0x03, 0x3c,
+ 0x00, 0x05, 0xd1, 0x1c, 0xaf, 0x8d, 0xe3, 0x98, 0x84, 0xac, 0x62, 0x0a, 0xc7, 0x5a, 0x69, 0x98,
+ 0xda, 0xf9, 0xfa, 0x6f, 0x9f, 0x9d, 0x68, 0x35, 0xca, 0x93, 0x5e, 0x34, 0x12, 0xe0, 0xa7, 0xa0,
+ 0x88, 0x3d, 0x8f, 0x30, 0x26, 0xb2, 0xe6, 0x09, 0x0d, 0x2b, 0x39, 0x59, 0xb7, 0x7d, 0xb7, 0xee,
+ 0x63, 0xe9, 0x77, 0xa2, 0xdc, 0x6a, 0x1b, 0xa2, 0xf2, 0x61, 0x6a, 0xaf, 0xce, 0xa8, 0xd1, 0x2a,
+ 0x9e, 0x16, 0xcf, 0x0d, 0x73, 0xd1, 0xca, 0x9e, 0x1b, 0x66, 0xd6, 0x32, 0x9c, 0xbf, 0x64, 0xc0,
+ 0xac, 0x33, 0x3c, 0x06, 0xcb, 0x5e, 0x42, 0x30, 0x27, 0x72, 0x97, 0xf3, 0x07, 0xdf, 0xfb, 0x16,
+ 0xd2, 0xab, 0x41, 0x87, 0xd4, 0x0c, 0x41, 0x8c, 0x74, 0x20, 0xfc, 0x19, 0x30, 0x3c, 0x1c, 0x86,
+ 0x95, 0xc5, 0xff, 0x17, 0x40, 0x86, 0x39, 0xff, 0xca, 0x80, 0xb5, 0x3b, 0x1e, 0xd0, 0x03, 0x79,
+ 0xdd, 0x14, 0x3e, 0xe8, 0xa8, 0xe4, 0x8a, 0x07, 0x6f, 0x7f, 0x13, 0xb6, 0x04, 0xfd, 0xfe, 0x30,
+ 0xb5, 0xc1, 0x44, 0xbe, 0x4d, 0x6d, 0xa8, 0x46, 0x62, 0x0a, 0xc8, 0x41, 0x00, 0x8f, 0x3d, 0xa0,
+ 0x07, 0xd6, 0x67, 0x3b, 0xef, 0x86, 0x01, 0xe3, 0x95, 0x45, 0xb9, 0x69, 0x4f, 0x87, 0xa9, 0x3d,
+ 0x9b, 0xd8, 0x45, 0xc0, 0xf8, 0x6d, 0x6a, 0x57, 0x67, 0x50, 0xa7, 0x23, 0x1d, 0x31, 0x12, 0x73,
+ 0x01, 0xce, 0x7f, 0x8b, 0x20, 0x3f, 0x35, 0xaf, 0xf0, 0x0f, 0xa0, 0xd4, 0xa6, 0x11, 0x61, 0x9c,
+ 0x60, 0xdf, 0x6d, 0x86, 0xd4, 0xbb, 0xd6, 0x0f, 0xd8, 0xd3, 0x7f, 0xa6, 0xf6, 0x86, 0x47, 0x59,
+ 0x44, 0x19, 0xf3, 0xaf, 0x77, 0x03, 0xba, 0x17, 0x61, 0xde, 0xde, 0x3d, 0x8b, 0x05, 0xe9, 0xa6,
+ 0x22, 0x9d, 0x8b, 0x74, 0x50, 0x71, 0xac, 0xa9, 0x09, 0x05, 0x6c, 0x83, 0xa2, 0x8f, 0xa9, 0xfb,
+ 0x19, 0x4d, 0xae, 0x35, 0xf8, 0xa2, 0x04, 0xaf, 0x7d, 0x23, 0xf8, 0x30, 0xb5, 0x0b, 0xa7, 0xc7,
+ 0x1f, 0x7d, 0x48, 0x93, 0x6b, 0x09, 0x71, 0x9b, 0xda, 0x1b, 0x8a, 0x6c, 0x16, 0xc8, 0x41, 0x05,
+ 0x1f, 0xd3, 0xb1, 0x1b, 0xfc, 0x1d, 0xb0, 0xc6, 0x0e, 0xac, 0xdb, 0xe9, 0xd0, 0x84, 0x57, 0xb2,
+ 0xe2, 0x41, 0xaa, 0xbd, 0x3b, 0x4c, 0xed, 0xa2, 0x86, 0x6c, 0x28, 0xcb, 0x6d, 0x6a, 0xbf, 0x31,
+ 0x07, 0xaa, 0x63, 0x1c, 0x54, 0xd4, 0xb0, 0xda, 0x15, 0x36, 0x41, 0x81, 0x04, 0x9d, 0xfd, 0xc3,
+ 0x27, 0xba, 0x00, 0x43, 0x16, 0xf0, 0x8b, 0x87, 0x0a, 0xc8, 0xd7, 0xcf, 0x2e, 0xf7, 0x0f, 0x9f,
+ 0x8c, 0xf2, 0xd7, 0xaf, 0x82, 0x69, 0x14, 0x07, 0xe5, 0x95, 0xa8, 0x92, 0x3f, 0x03, 0x5a, 0x74,
+ 0xdb, 0x98, 0xb5, 0xe5, 0x8b, 0x26, 0x57, 0xdb, 0x11, 0x03, 0xa4, 0x90, 0x7e, 0x8d, 0x59, 0x7b,
+ 0xd2, 0xf5, 0xe6, 0xe0, 0x8f, 0x38, 0xe6, 0x41, 0x37, 0x1a, 0x61, 0x01, 0x15, 0x2c, 0xbc, 0xc6,
+ 0xe9, 0x1e, 0xea, 0x74, 0x97, 0x1f, 0x9b, 0xee, 0xe1, 0x7d, 0xe9, 0x1e, 0xce, 0xa6, 0xab, 0x7c,
+ 0xc6, 0x1c, 0x47, 0x9a, 0x63, 0xe5, 0xb1, 0x1c, 0x47, 0xf7, 0x71, 0x1c, 0xcd, 0x72, 0x28, 0x1f,
+ 0x31, 0x97, 0x73, 0x75, 0x56, 0xcc, 0x47, 0xcf, 0xe5, 0x9d, 0x0e, 0x15, 0xc7, 0x1a, 0x85, 0x7e,
+ 0x0d, 0xca, 0x1e, 0x8d, 0x19, 0x17, 0xba, 0x98, 0x76, 0x42, 0xa2, 0x29, 0x72, 0x92, 0xe2, 0xe8,
+ 0x21, 0x8a, 0xb7, 0xf4, 0x8b, 0xfd, 0x9e, 0x70, 0x07, 0xad, 0xcf, 0xaa, 0x15, 0x99, 0x0b, 0xac,
+ 0x0e, 0xe1, 0x24, 0x61, 0xcd, 0x6e, 0xd2, 0xd2, 0x44, 0x40, 0x12, 0xbd, 0xf7, 0x10, 0x91, 0x9e,
+ 0xd0, 0xf9, 0x50, 0x07, 0x95, 0x26, 0x2a, 0x45, 0xf0, 0x09, 0x28, 0x06, 0x82, 0xb5, 0xd9, 0x0d,
+ 0x35, 0x7c, 0x5e, 0xc2, 0x1f, 0x3c, 0x04, 0xaf, 0x9f, 0xaa, 0xd9, 0x40, 0x07, 0xad, 0x8e, 0x14,
+ 0x0a, 0xda, 0x07, 0x30, 0xea, 0x06, 0x89, 0xdb, 0x0a, 0xb1, 0x17, 0x90, 0x44, 0xc3, 0x17, 0x24,
+ 0xfc, 0x8f, 0x1f, 0x82, 0x7f, 0x53, 0xc1, 0xdf, 0x0d, 0x76, 0x90, 0x25, 0x94, 0xbf, 0x52, 0x3a,
+ 0xc5, 0xd2, 0x00, 0x85, 0x26, 0x49, 0xc2, 0x20, 0xd6, 0xf8, 0xab, 0x12, 0xff, 0xc9, 0x43, 0xf8,
+ 0x7a, 0x82, 0xa6, 0xc3, 0x1c, 0x94, 0x57, 0xe2, 0x18, 0x34, 0xa4, 0xb1, 0x4f, 0x47, 0xa0, 0x6b,
+ 0x8f, 0x06, 0x9d, 0x0e, 0x73, 0x50, 0x5e, 0x89, 0x0a, 0xb4, 0x05, 0xd6, 0x71, 0x92, 0xd0, 0x17,
+ 0x73, 0x0d, 0x81, 0x12, 0xfb, 0x27, 0x0f, 0x61, 0x8f, 0xde, 0xd3, 0x77, 0xa3, 0xc5, 0x7b, 0x5a,
+ 0x68, 0x67, 0x5a, 0xe2, 0x03, 0xd8, 0x4a, 0xf0, 0x60, 0x8e, 0xa7, 0xfc, 0xe8, 0xc6, 0xdf, 0x0d,
+ 0x76, 0x90, 0x25, 0x94, 0x33, 0x2c, 0x9f, 0x83, 0x72, 0x44, 0x92, 0x16, 0x71, 0x63, 0xc2, 0x59,
+ 0x27, 0x0c, 0xb8, 0xe6, 0xd9, 0x78, 0xf4, 0x73, 0x70, 0x5f, 0xb8, 0x83, 0xa0, 0x54, 0x3f, 0xd7,
+ 0xda, 0xf1, 0x94, 0xb2, 0x36, 0x8e, 0x5b, 0x6d, 0x1c, 0x68, 0x96, 0xcd, 0x47, 0x4f, 0xe9, 0x6c,
+ 0xa0, 0x83, 0x56, 0x47, 0x8a, 0xf1, 0x56, 0x7b, 0x38, 0xf6, 0xba, 0xa3, 0xad, 0x7e, 0xe3, 0xd1,
+ 0x5b, 0x3d, 0x1d, 0x26, 0xee, 0x67, 0x52, 0x94, 0xa0, 0xe7, 0x86, 0x59, 0xb4, 0x4a, 0xe7, 0x86,
+ 0x59, 0xb2, 0xac, 0x73, 0xc3, 0xb4, 0xac, 0xb5, 0x73, 0xc3, 0x5c, 0xb7, 0xca, 0x68, 0x75, 0x40,
+ 0x43, 0xea, 0xf6, 0x9e, 0xaa, 0x20, 0x94, 0x27, 0x2f, 0x30, 0xd3, 0x2f, 0x1a, 0x54, 0xf4, 0x30,
+ 0xc7, 0xe1, 0x80, 0xe9, 0x46, 0x20, 0x4b, 0xb5, 0x67, 0xea, 0xd8, 0xda, 0x03, 0x4b, 0x0d, 0x2e,
+ 0xee, 0x29, 0x16, 0xc8, 0x5e, 0x93, 0x81, 0x3a, 0x6c, 0x91, 0x58, 0xc2, 0x32, 0x58, 0xea, 0xe1,
+ 0xb0, 0x4b, 0xd4, 0x19, 0x89, 0x94, 0xe0, 0x5c, 0x82, 0xd2, 0x55, 0x82, 0x63, 0x26, 0x6e, 0x77,
+ 0x34, 0xbe, 0xa0, 0x2d, 0x06, 0x21, 0x30, 0xe4, 0x39, 0xa1, 0x62, 0xe5, 0x1a, 0xfe, 0x10, 0x18,
+ 0x21, 0x6d, 0x31, 0x79, 0x5b, 0xc8, 0x1f, 0x6c, 0xdc, 0xbd, 0x9a, 0x5c, 0xd0, 0x16, 0x92, 0x2e,
+ 0xce, 0xdf, 0x17, 0x41, 0xf6, 0x82, 0xb6, 0x60, 0x05, 0xac, 0x60, 0xdf, 0x4f, 0x08, 0x63, 0x1a,
+ 0x69, 0x24, 0xc2, 0x4d, 0xb0, 0xcc, 0x69, 0x27, 0xf0, 0x14, 0x5c, 0x0e, 0x69, 0x49, 0x10, 0xfb,
+ 0x98, 0x63, 0x79, 0xb0, 0x16, 0x90, 0x5c, 0x8b, 0x3b, 0xa6, 0xac, 0xcc, 0x8d, 0xbb, 0x51, 0x93,
+ 0x24, 0xf2, 0x7c, 0x34, 0x6a, 0xa5, 0x9b, 0xd4, 0xce, 0x4b, 0xfd, 0x73, 0xa9, 0x46, 0xd3, 0x02,
+ 0x7c, 0x07, 0xac, 0xf0, 0xfe, 0xf4, 0x59, 0xb7, 0x7e, 0x93, 0xda, 0x25, 0x3e, 0x29, 0x53, 0x1c,
+ 0x65, 0x68, 0x99, 0xf7, 0xe5, 0x91, 0xb6, 0x07, 0x4c, 0xde, 0x77, 0x83, 0xd8, 0x27, 0x7d, 0x79,
+ 0x9c, 0x19, 0xb5, 0xf2, 0x4d, 0x6a, 0x5b, 0x53, 0xee, 0x67, 0xc2, 0x86, 0x56, 0x78, 0x5f, 0x2e,
+ 0xe0, 0x3b, 0x00, 0xa8, 0x94, 0x24, 0x83, 0x3a, 0x9d, 0x56, 0x6f, 0x52, 0x3b, 0x27, 0xb5, 0x12,
+ 0x7b, 0xb2, 0x84, 0x0e, 0x58, 0x52, 0xd8, 0xa6, 0xc4, 0x2e, 0xdc, 0xa4, 0xb6, 0x19, 0xd2, 0x96,
+ 0xc2, 0x54, 0x26, 0xd1, 0xaa, 0x84, 0x44, 0xb4, 0x47, 0x7c, 0x79, 0x44, 0x98, 0x68, 0x24, 0x3a,
+ 0x7f, 0x5a, 0x04, 0xe6, 0x55, 0x1f, 0x11, 0xd6, 0x0d, 0x39, 0xfc, 0x10, 0x58, 0xf2, 0x02, 0x86,
+ 0x3d, 0xee, 0xce, 0xb4, 0xb6, 0xf6, 0xd6, 0xe4, 0x85, 0x3e, 0xef, 0xe1, 0xa0, 0xd2, 0x48, 0x75,
+ 0xac, 0xfb, 0x5f, 0x06, 0x4b, 0xcd, 0x90, 0xd2, 0x48, 0x4e, 0x42, 0x01, 0x29, 0x01, 0x22, 0xd9,
+ 0x35, 0xb9, 0xcb, 0x59, 0x79, 0xb9, 0xfd, 0xee, 0xdd, 0x5d, 0x9e, 0x1b, 0x95, 0xda, 0xa6, 0xfe,
+ 0x1c, 0x29, 0x2a, 0x6e, 0x1d, 0xef, 0x88, 0xde, 0xca, 0x51, 0xb2, 0x40, 0x36, 0x21, 0x5c, 0x6e,
+ 0x5a, 0x01, 0x89, 0x25, 0xac, 0x02, 0x33, 0x21, 0x3d, 0x92, 0x70, 0xe2, 0xcb, 0xcd, 0x31, 0xd1,
+ 0x58, 0x86, 0x6f, 0x02, 0xb3, 0x85, 0x99, 0xdb, 0x65, 0xc4, 0x57, 0x3b, 0x81, 0x56, 0x5a, 0x98,
+ 0x7d, 0xcc, 0x88, 0xff, 0xbe, 0xf1, 0xc5, 0x97, 0xf6, 0x82, 0x83, 0x41, 0x5e, 0x5f, 0x79, 0xbb,
+ 0x9d, 0x90, 0x3c, 0x30, 0x61, 0x07, 0xa0, 0xc0, 0x38, 0x4d, 0x70, 0x8b, 0xb8, 0xd7, 0x64, 0xa0,
+ 0xe7, 0x4c, 0x4d, 0x8d, 0xd6, 0xff, 0x86, 0x0c, 0x18, 0x9a, 0x16, 0x34, 0xc5, 0x97, 0x06, 0xc8,
+ 0x5f, 0x25, 0xd8, 0x23, 0xfa, 0x02, 0x2b, 0x66, 0x55, 0x88, 0x89, 0xa6, 0xd0, 0x92, 0xe0, 0xe6,
+ 0x41, 0x44, 0x68, 0x97, 0xeb, 0xe7, 0x69, 0x24, 0x8a, 0x88, 0x84, 0x90, 0x3e, 0xf1, 0x64, 0x1b,
+ 0x0d, 0xa4, 0x25, 0x78, 0x08, 0x56, 0xfd, 0x80, 0xe1, 0x66, 0x48, 0x5c, 0xc6, 0xb1, 0x77, 0xad,
+ 0xca, 0xaf, 0x59, 0x37, 0xa9, 0x5d, 0xd0, 0x86, 0x86, 0xd0, 0xa3, 0x19, 0x09, 0x7e, 0x00, 0x4a,
+ 0x93, 0x30, 0x99, 0xad, 0xfa, 0x82, 0xab, 0xc1, 0x9b, 0xd4, 0x2e, 0x8e, 0x5d, 0xa5, 0x05, 0xcd,
+ 0xc9, 0x62, 0xa7, 0x7d, 0xd2, 0xec, 0xb6, 0xe4, 0xf0, 0x99, 0x48, 0x09, 0x42, 0x1b, 0x06, 0x51,
+ 0xc0, 0xe5, 0xb0, 0x2d, 0x21, 0x25, 0xc0, 0x0f, 0x40, 0x8e, 0xf6, 0x48, 0x92, 0x04, 0x3e, 0x61,
+ 0xf2, 0x02, 0xf1, 0x6d, 0x1f, 0xa3, 0x68, 0xe2, 0x2f, 0x8a, 0x23, 0xb1, 0x4c, 0x32, 0x22, 0x11,
+ 0x4d, 0x06, 0xf2, 0x8a, 0xa0, 0x8b, 0x53, 0x86, 0x67, 0x52, 0x8f, 0x66, 0x24, 0x58, 0x03, 0x50,
+ 0x87, 0x25, 0x84, 0x77, 0x93, 0xd8, 0x95, 0xcf, 0x7f, 0x41, 0xc6, 0xca, 0xa7, 0x50, 0x59, 0x91,
+ 0x34, 0x9e, 0x62, 0x8e, 0xd1, 0x1d, 0x0d, 0xfc, 0x39, 0x80, 0x6a, 0x4f, 0xdc, 0xcf, 0x19, 0x1d,
+ 0x7f, 0x4d, 0xab, 0x33, 0x5e, 0xf2, 0x2b, 0xab, 0xce, 0xd9, 0x52, 0xd2, 0x39, 0xa3, 0xba, 0x8a,
+ 0x73, 0xc3, 0x34, 0xac, 0xa5, 0x73, 0xc3, 0x5c, 0xb1, 0xcc, 0x71, 0xff, 0x74, 0x15, 0x68, 0x7d,
+ 0x24, 0x4f, 0xa5, 0xf7, 0xa3, 0xbf, 0x65, 0xc0, 0xd4, 0x97, 0x17, 0xfc, 0x29, 0xa8, 0x1e, 0x9f,
+ 0x9c, 0xd4, 0x1b, 0x0d, 0xf7, 0xea, 0x93, 0xcb, 0xba, 0x7b, 0x59, 0x47, 0xcf, 0xce, 0x1a, 0x8d,
+ 0xb3, 0x8f, 0x9e, 0x5f, 0xd4, 0x1b, 0x0d, 0x6b, 0xa1, 0xfa, 0xf6, 0xcb, 0x57, 0xdb, 0x95, 0x89,
+ 0xff, 0xa5, 0xe8, 0x27, 0x63, 0x01, 0x8d, 0x43, 0x31, 0xa9, 0xef, 0x81, 0xcd, 0xe9, 0x68, 0x54,
+ 0x6f, 0x5c, 0xa1, 0xb3, 0x93, 0xab, 0xfa, 0xa9, 0x95, 0xa9, 0x56, 0x5e, 0xbe, 0xda, 0x2e, 0x4f,
+ 0x22, 0x11, 0x61, 0x3c, 0x09, 0xc4, 0xb7, 0x3a, 0x3c, 0x02, 0x95, 0xfb, 0x39, 0xeb, 0xa7, 0xd6,
+ 0x62, 0xb5, 0xfa, 0xf2, 0xd5, 0xf6, 0xe6, 0x7d, 0x8c, 0xc4, 0xaf, 0x1a, 0x5f, 0xfc, 0x75, 0x6b,
+ 0xa1, 0xf6, 0xcb, 0xaf, 0x86, 0x5b, 0x99, 0xaf, 0x87, 0x5b, 0x99, 0xff, 0x0c, 0xb7, 0x32, 0x7f,
+ 0x7e, 0xbd, 0xb5, 0xf0, 0xf5, 0xeb, 0xad, 0x85, 0x7f, 0xbc, 0xde, 0x5a, 0xf8, 0xfd, 0x0f, 0x5a,
+ 0x01, 0x6f, 0x77, 0x9b, 0xbb, 0x1e, 0x8d, 0xf6, 0x48, 0x2f, 0xa2, 0x4c, 0xff, 0xed, 0xed, 0x1f,
+ 0xed, 0xf5, 0xe5, 0xaf, 0x2d, 0xe2, 0xcb, 0x92, 0x35, 0x97, 0xe5, 0xaf, 0x28, 0x4f, 0xff, 0x17,
+ 0x00, 0x00, 0xff, 0xff, 0x97, 0xcf, 0xe9, 0x62, 0x8b, 0x11, 0x00, 0x00,
+}
+
+func (m *V6Params) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6Params) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.AccessControl.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x4a
+ if len(m.EVMChannels) > 0 {
+ for iNdEx := len(m.EVMChannels) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.EVMChannels[iNdEx])
+ copy(dAtA[i:], m.EVMChannels[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.EVMChannels[iNdEx])))
+ i--
+ dAtA[i] = 0x42
+ }
+ }
+ if len(m.ActivePrecompiles) > 0 {
+ for iNdEx := len(m.ActivePrecompiles) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.ActivePrecompiles[iNdEx])
+ copy(dAtA[i:], m.ActivePrecompiles[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.ActivePrecompiles[iNdEx])))
+ i--
+ dAtA[i] = 0x3a
+ }
+ }
+ if m.AllowUnprotectedTxs {
+ i--
+ if m.AllowUnprotectedTxs {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x30
+ }
+ {
+ size, err := m.ChainConfig.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x2a
+ if len(m.ExtraEIPs) > 0 {
+ dAtA4 := make([]byte, len(m.ExtraEIPs)*10)
+ var j3 int
+ for _, num1 := range m.ExtraEIPs {
+ num := uint64(num1)
+ for num >= 1<<7 {
+ dAtA4[j3] = uint8(uint64(num)&0x7f | 0x80)
+ num >>= 7
+ j3++
+ }
+ dAtA4[j3] = uint8(num)
+ j3++
+ }
+ i -= j3
+ copy(dAtA[i:], dAtA4[:j3])
+ i = encodeVarintEvm(dAtA, i, uint64(j3))
+ i--
+ dAtA[i] = 0x22
+ }
+ if len(m.EvmDenom) > 0 {
+ i -= len(m.EvmDenom)
+ copy(dAtA[i:], m.EvmDenom)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.EvmDenom)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6AccessControl) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6AccessControl) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6AccessControl) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Call.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ {
+ size, err := m.Create.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+}
+
+func (m *V6AccessControlType) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6AccessControlType) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6AccessControlType) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.AccessControlList) > 0 {
+ for iNdEx := len(m.AccessControlList) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.AccessControlList[iNdEx])
+ copy(dAtA[i:], m.AccessControlList[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.AccessControlList[iNdEx])))
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if m.AccessType != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.AccessType))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6ChainConfig) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6ChainConfig) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6ChainConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.CancunBlock != nil {
+ {
+ size := m.CancunBlock.Size()
+ i -= size
+ if _, err := m.CancunBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xba
+ }
+ if m.ShanghaiBlock != nil {
+ {
+ size := m.ShanghaiBlock.Size()
+ i -= size
+ if _, err := m.ShanghaiBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xb2
+ }
+ if m.MergeNetsplitBlock != nil {
+ {
+ size := m.MergeNetsplitBlock.Size()
+ i -= size
+ if _, err := m.MergeNetsplitBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xaa
+ }
+ if m.GrayGlacierBlock != nil {
+ {
+ size := m.GrayGlacierBlock.Size()
+ i -= size
+ if _, err := m.GrayGlacierBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xa2
+ }
+ if m.ArrowGlacierBlock != nil {
+ {
+ size := m.ArrowGlacierBlock.Size()
+ i -= size
+ if _, err := m.ArrowGlacierBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x92
+ }
+ if m.LondonBlock != nil {
+ {
+ size := m.LondonBlock.Size()
+ i -= size
+ if _, err := m.LondonBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x8a
+ }
+ if m.BerlinBlock != nil {
+ {
+ size := m.BerlinBlock.Size()
+ i -= size
+ if _, err := m.BerlinBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x6a
+ }
+ if m.MuirGlacierBlock != nil {
+ {
+ size := m.MuirGlacierBlock.Size()
+ i -= size
+ if _, err := m.MuirGlacierBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x62
+ }
+ if m.IstanbulBlock != nil {
+ {
+ size := m.IstanbulBlock.Size()
+ i -= size
+ if _, err := m.IstanbulBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x5a
+ }
+ if m.PetersburgBlock != nil {
+ {
+ size := m.PetersburgBlock.Size()
+ i -= size
+ if _, err := m.PetersburgBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x52
+ }
+ if m.ConstantinopleBlock != nil {
+ {
+ size := m.ConstantinopleBlock.Size()
+ i -= size
+ if _, err := m.ConstantinopleBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x4a
+ }
+ if m.ByzantiumBlock != nil {
+ {
+ size := m.ByzantiumBlock.Size()
+ i -= size
+ if _, err := m.ByzantiumBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x42
+ }
+ if m.EIP158Block != nil {
+ {
+ size := m.EIP158Block.Size()
+ i -= size
+ if _, err := m.EIP158Block.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x3a
+ }
+ if m.EIP155Block != nil {
+ {
+ size := m.EIP155Block.Size()
+ i -= size
+ if _, err := m.EIP155Block.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x32
+ }
+ if len(m.EIP150Hash) > 0 {
+ i -= len(m.EIP150Hash)
+ copy(dAtA[i:], m.EIP150Hash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.EIP150Hash)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if m.EIP150Block != nil {
+ {
+ size := m.EIP150Block.Size()
+ i -= size
+ if _, err := m.EIP150Block.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x22
+ }
+ if m.DAOForkSupport {
+ i--
+ if m.DAOForkSupport {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.DAOForkBlock != nil {
+ {
+ size := m.DAOForkBlock.Size()
+ i -= size
+ if _, err := m.DAOForkBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.HomesteadBlock != nil {
+ {
+ size := m.HomesteadBlock.Size()
+ i -= size
+ if _, err := m.HomesteadBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6State) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6State) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6State) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Value) > 0 {
+ i -= len(m.Value)
+ copy(dAtA[i:], m.Value)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Value)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Key) > 0 {
+ i -= len(m.Key)
+ copy(dAtA[i:], m.Key)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Key)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6TransactionLogs) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6TransactionLogs) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6TransactionLogs) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Logs) > 0 {
+ for iNdEx := len(m.Logs) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Logs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if len(m.Hash) > 0 {
+ i -= len(m.Hash)
+ copy(dAtA[i:], m.Hash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Hash)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6Log) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6Log) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6Log) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Removed {
+ i--
+ if m.Removed {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x48
+ }
+ if m.Index != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.Index))
+ i--
+ dAtA[i] = 0x40
+ }
+ if len(m.BlockHash) > 0 {
+ i -= len(m.BlockHash)
+ copy(dAtA[i:], m.BlockHash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.BlockHash)))
+ i--
+ dAtA[i] = 0x3a
+ }
+ if m.TxIndex != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.TxIndex))
+ i--
+ dAtA[i] = 0x30
+ }
+ if len(m.TxHash) > 0 {
+ i -= len(m.TxHash)
+ copy(dAtA[i:], m.TxHash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.TxHash)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if m.BlockNumber != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.BlockNumber))
+ i--
+ dAtA[i] = 0x20
+ }
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Topics) > 0 {
+ for iNdEx := len(m.Topics) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.Topics[iNdEx])
+ copy(dAtA[i:], m.Topics[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Topics[iNdEx])))
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6TxResult) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6TxResult) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6TxResult) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.GasUsed != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.GasUsed))
+ i--
+ dAtA[i] = 0x30
+ }
+ if m.Reverted {
+ i--
+ if m.Reverted {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x28
+ }
+ if len(m.Ret) > 0 {
+ i -= len(m.Ret)
+ copy(dAtA[i:], m.Ret)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Ret)))
+ i--
+ dAtA[i] = 0x22
+ }
+ {
+ size, err := m.TxLogs.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ if len(m.Bloom) > 0 {
+ i -= len(m.Bloom)
+ copy(dAtA[i:], m.Bloom)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Bloom)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.ContractAddress) > 0 {
+ i -= len(m.ContractAddress)
+ copy(dAtA[i:], m.ContractAddress)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.ContractAddress)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6AccessTuple) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6AccessTuple) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6AccessTuple) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.StorageKeys) > 0 {
+ for iNdEx := len(m.StorageKeys) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.StorageKeys[iNdEx])
+ copy(dAtA[i:], m.StorageKeys[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.StorageKeys[iNdEx])))
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *V6TraceConfig) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *V6TraceConfig) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *V6TraceConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.TracerJsonConfig) > 0 {
+ i -= len(m.TracerJsonConfig)
+ copy(dAtA[i:], m.TracerJsonConfig)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.TracerJsonConfig)))
+ i--
+ dAtA[i] = 0x6a
+ }
+ if m.EnableReturnData {
+ i--
+ if m.EnableReturnData {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x60
+ }
+ if m.EnableMemory {
+ i--
+ if m.EnableMemory {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x58
+ }
+ if m.Overrides != nil {
+ {
+ size, err := m.Overrides.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x52
+ }
+ if m.Limit != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.Limit))
+ i--
+ dAtA[i] = 0x48
+ }
+ if m.Debug {
+ i--
+ if m.Debug {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x40
+ }
+ if m.DisableStorage {
+ i--
+ if m.DisableStorage {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x30
+ }
+ if m.DisableStack {
+ i--
+ if m.DisableStack {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x28
+ }
+ if m.Reexec != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.Reexec))
+ i--
+ dAtA[i] = 0x18
+ }
+ if len(m.Timeout) > 0 {
+ i -= len(m.Timeout)
+ copy(dAtA[i:], m.Timeout)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Timeout)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Tracer) > 0 {
+ i -= len(m.Tracer)
+ copy(dAtA[i:], m.Tracer)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Tracer)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintEvm(dAtA []byte, offset int, v uint64) int {
+ offset -= sovEvm(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+
+func (m *V6Params) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.EvmDenom)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.ExtraEIPs) > 0 {
+ l = 0
+ for _, e := range m.ExtraEIPs {
+ l += sovEvm(uint64(e))
+ }
+ n += 1 + sovEvm(uint64(l)) + l
+ }
+ l = m.ChainConfig.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ if m.AllowUnprotectedTxs {
+ n += 2
+ }
+ if len(m.ActivePrecompiles) > 0 {
+ for _, s := range m.ActivePrecompiles {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ if len(m.EVMChannels) > 0 {
+ for _, s := range m.EVMChannels {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ l = m.AccessControl.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ return n
+}
+
+func (m *V6AccessControl) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = m.Create.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ l = m.Call.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ return n
+}
+
+func (m *V6AccessControlType) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.AccessType != 0 {
+ n += 1 + sovEvm(uint64(m.AccessType))
+ }
+ if len(m.AccessControlList) > 0 {
+ for _, s := range m.AccessControlList {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *V6ChainConfig) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.HomesteadBlock != nil {
+ l = m.HomesteadBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.DAOForkBlock != nil {
+ l = m.DAOForkBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.DAOForkSupport {
+ n += 2
+ }
+ if m.EIP150Block != nil {
+ l = m.EIP150Block.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.EIP150Hash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.EIP155Block != nil {
+ l = m.EIP155Block.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.EIP158Block != nil {
+ l = m.EIP158Block.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.ByzantiumBlock != nil {
+ l = m.ByzantiumBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.ConstantinopleBlock != nil {
+ l = m.ConstantinopleBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.PetersburgBlock != nil {
+ l = m.PetersburgBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.IstanbulBlock != nil {
+ l = m.IstanbulBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.MuirGlacierBlock != nil {
+ l = m.MuirGlacierBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.BerlinBlock != nil {
+ l = m.BerlinBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.LondonBlock != nil {
+ l = m.LondonBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.ArrowGlacierBlock != nil {
+ l = m.ArrowGlacierBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.GrayGlacierBlock != nil {
+ l = m.GrayGlacierBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.MergeNetsplitBlock != nil {
+ l = m.MergeNetsplitBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.ShanghaiBlock != nil {
+ l = m.ShanghaiBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.CancunBlock != nil {
+ l = m.CancunBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ return n
+}
+
+func (m *V6State) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ return n
+}
+
+func (m *V6TransactionLogs) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Hash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.Logs) > 0 {
+ for _, e := range m.Logs {
+ l = e.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *V6Log) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.Topics) > 0 {
+ for _, s := range m.Topics {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.BlockNumber != 0 {
+ n += 1 + sovEvm(uint64(m.BlockNumber))
+ }
+ l = len(m.TxHash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.TxIndex != 0 {
+ n += 1 + sovEvm(uint64(m.TxIndex))
+ }
+ l = len(m.BlockHash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.Index != 0 {
+ n += 1 + sovEvm(uint64(m.Index))
+ }
+ if m.Removed {
+ n += 2
+ }
+ return n
+}
+
+func (m *V6TxResult) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ContractAddress)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.Bloom)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = m.TxLogs.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ l = len(m.Ret)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.Reverted {
+ n += 2
+ }
+ if m.GasUsed != 0 {
+ n += 1 + sovEvm(uint64(m.GasUsed))
+ }
+ return n
+}
+
+func (m *V6AccessTuple) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.StorageKeys) > 0 {
+ for _, s := range m.StorageKeys {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *V6TraceConfig) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Tracer)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.Timeout)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.Reexec != 0 {
+ n += 1 + sovEvm(uint64(m.Reexec))
+ }
+ if m.DisableStack {
+ n += 2
+ }
+ if m.DisableStorage {
+ n += 2
+ }
+ if m.Debug {
+ n += 2
+ }
+ if m.Limit != 0 {
+ n += 1 + sovEvm(uint64(m.Limit))
+ }
+ if m.Overrides != nil {
+ l = m.Overrides.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.EnableMemory {
+ n += 2
+ }
+ if m.EnableReturnData {
+ n += 2
+ }
+ l = len(m.TracerJsonConfig)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ return n
+}
+
+func sovEvm(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+
+func sozEvm(x uint64) (n int) {
+ return sovEvm(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+func (m *V6Params) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Params: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EvmDenom", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EvmDenom = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 4:
+ if wireType == 0 {
+ var v int64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.ExtraEIPs = append(m.ExtraEIPs, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var elementCount int
+ var count int
+ for _, integer := range dAtA[iNdEx:postIndex] {
+ if integer < 128 {
+ count++
+ }
+ }
+ elementCount = count
+ if elementCount != 0 && len(m.ExtraEIPs) == 0 {
+ m.ExtraEIPs = make([]int64, 0, elementCount)
+ }
+ for iNdEx < postIndex {
+ var v int64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.ExtraEIPs = append(m.ExtraEIPs, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field ExtraEIPs", wireType)
+ }
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainConfig", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.ChainConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AllowUnprotectedTxs", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.AllowUnprotectedTxs = bool(v != 0)
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ActivePrecompiles", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ActivePrecompiles = append(m.ActivePrecompiles, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EVMChannels", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EVMChannels = append(m.EVMChannels, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccessControl", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.AccessControl.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6AccessControl) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AccessControl: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AccessControl: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Create", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Create.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Call", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Call.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6AccessControlType) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AccessControlType: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AccessControlType: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccessType", wireType)
+ }
+ m.AccessType = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.AccessType |= V6AccessType(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccessControlList", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.AccessControlList = append(m.AccessControlList, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6ChainConfig) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ChainConfig: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ChainConfig: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field HomesteadBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.HomesteadBlock = &v
+ if err := m.HomesteadBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DAOForkBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.DAOForkBlock = &v
+ if err := m.DAOForkBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DAOForkSupport", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.DAOForkSupport = bool(v != 0)
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP150Block", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.EIP150Block = &v
+ if err := m.EIP150Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP150Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EIP150Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP155Block", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.EIP155Block = &v
+ if err := m.EIP155Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP158Block", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.EIP158Block = &v
+ if err := m.EIP158Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ByzantiumBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ByzantiumBlock = &v
+ if err := m.ByzantiumBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ConstantinopleBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ConstantinopleBlock = &v
+ if err := m.ConstantinopleBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PetersburgBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.PetersburgBlock = &v
+ if err := m.PetersburgBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 11:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field IstanbulBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.IstanbulBlock = &v
+ if err := m.IstanbulBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 12:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MuirGlacierBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.MuirGlacierBlock = &v
+ if err := m.MuirGlacierBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 13:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BerlinBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.BerlinBlock = &v
+ if err := m.BerlinBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 17:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LondonBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.LondonBlock = &v
+ if err := m.LondonBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 18:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ArrowGlacierBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ArrowGlacierBlock = &v
+ if err := m.ArrowGlacierBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 20:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GrayGlacierBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.GrayGlacierBlock = &v
+ if err := m.GrayGlacierBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 21:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MergeNetsplitBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.MergeNetsplitBlock = &v
+ if err := m.MergeNetsplitBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 22:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ShanghaiBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ShanghaiBlock = &v
+ if err := m.ShanghaiBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 23:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CancunBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.CancunBlock = &v
+ if err := m.CancunBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6State) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: State: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: State: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6TransactionLogs) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TransactionLogs: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TransactionLogs: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Logs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Logs = append(m.Logs, &V6Log{})
+ if err := m.Logs[len(m.Logs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6Log) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Log: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Log: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Topics", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Topics = append(m.Topics, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockNumber", wireType)
+ }
+ m.BlockNumber = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BlockNumber |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.TxHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxIndex", wireType)
+ }
+ m.TxIndex = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TxIndex |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.BlockHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType)
+ }
+ m.Index = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Index |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Removed", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Removed = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6TxResult) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TxResult: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TxResult: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ContractAddress = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Bloom", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Bloom = append(m.Bloom[:0], dAtA[iNdEx:postIndex]...)
+ if m.Bloom == nil {
+ m.Bloom = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxLogs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.TxLogs.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Ret", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Ret = append(m.Ret[:0], dAtA[iNdEx:postIndex]...)
+ if m.Ret == nil {
+ m.Ret = []byte{}
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Reverted", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Reverted = bool(v != 0)
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType)
+ }
+ m.GasUsed = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GasUsed |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6AccessTuple) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AccessTuple: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AccessTuple: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field StorageKeys", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.StorageKeys = append(m.StorageKeys, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *V6TraceConfig) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TraceConfig: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TraceConfig: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Tracer", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Tracer = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timeout", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Timeout = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Reexec", wireType)
+ }
+ m.Reexec = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Reexec |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DisableStack", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.DisableStack = bool(v != 0)
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DisableStorage", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.DisableStorage = bool(v != 0)
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Debug", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Debug = bool(v != 0)
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType)
+ }
+ m.Limit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Limit |= int32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Overrides", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Overrides == nil {
+ m.Overrides = &V6ChainConfig{}
+ }
+ if err := m.Overrides.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 11:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EnableMemory", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.EnableMemory = bool(v != 0)
+ case 12:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EnableReturnData", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.EnableReturnData = bool(v != 0)
+ case 13:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TracerJsonConfig", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.TracerJsonConfig = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func skipEvm(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthEvm
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupEvm
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthEvm
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthEvm = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowEvm = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupEvm = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/evm/migrations/v7/types/params.go b/x/evm/migrations/v7/types/params.go
new file mode 100644
index 00000000..32c26230
--- /dev/null
+++ b/x/evm/migrations/v7/types/params.go
@@ -0,0 +1,6 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package types
+
+var DefaultExtraEIPs = []int64{3855}
diff --git a/x/evm/module.go b/x/evm/module.go
new file mode 100644
index 00000000..b5a00001
--- /dev/null
+++ b/x/evm/module.go
@@ -0,0 +1,180 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package evm
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+
+ "github.com/gorilla/mux"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/spf13/cobra"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/codec"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/module"
+ simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
+
+ "github.com/evmos/evmos/v19/x/evm/client/cli"
+ "github.com/evmos/evmos/v19/x/evm/keeper"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// consensusVersion defines the current x/evm module consensus version.
+const consensusVersion = 7
+
+var (
+ _ module.AppModule = AppModule{}
+ _ module.AppModuleBasic = AppModuleBasic{}
+ _ module.EndBlockAppModule = AppModule{}
+ _ module.BeginBlockAppModule = AppModule{}
+)
+
+// AppModuleBasic defines the basic application module used by the evm module.
+type AppModuleBasic struct{}
+
+// Name returns the evm module's name.
+func (AppModuleBasic) Name() string {
+ return types.ModuleName
+}
+
+// RegisterLegacyAminoCodec registers the module's types with the given codec.
+func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
+ types.RegisterLegacyAminoCodec(cdc)
+}
+
+// ConsensusVersion returns the consensus state-breaking version for the module.
+func (AppModuleBasic) ConsensusVersion() uint64 {
+ return consensusVersion
+}
+
+// DefaultGenesis returns default genesis state as raw bytes for the evm
+// module.
+func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
+ return cdc.MustMarshalJSON(types.DefaultGenesisState())
+}
+
+// ValidateGenesis is the validation check of the Genesis
+func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error {
+ var genesisState types.GenesisState
+ if err := cdc.UnmarshalJSON(bz, &genesisState); err != nil {
+ return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
+ }
+
+ return genesisState.Validate()
+}
+
+// RegisterRESTRoutes performs a no-op as the EVM module doesn't expose REST
+// endpoints
+func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {
+}
+
+func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) {
+ if err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(c)); err != nil {
+ panic(err)
+ }
+}
+
+// GetTxCmd returns the root tx command for the evm module.
+func (AppModuleBasic) GetTxCmd() *cobra.Command {
+ return cli.GetTxCmd()
+}
+
+// GetQueryCmd returns no root query command for the evm module.
+func (AppModuleBasic) GetQueryCmd() *cobra.Command {
+ return cli.GetQueryCmd()
+}
+
+// RegisterInterfaces registers interfaces and implementations of the evm module.
+func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
+ types.RegisterInterfaces(registry)
+}
+
+// ____________________________________________________________________________
+
+// AppModule implements an application module for the evm module.
+type AppModule struct {
+ AppModuleBasic
+ keeper *keeper.Keeper
+ ak types.AccountKeeper
+ // legacySubspace is used solely for migration of x/params managed parameters
+ legacySubspace types.Subspace
+}
+
+// NewAppModule creates a new AppModule object
+func NewAppModule(k *keeper.Keeper, ak types.AccountKeeper, ss types.Subspace) AppModule {
+ return AppModule{
+ AppModuleBasic: AppModuleBasic{},
+ keeper: k,
+ ak: ak,
+ legacySubspace: ss,
+ }
+}
+
+// Name returns the evm module's name.
+func (AppModule) Name() string {
+ return types.ModuleName
+}
+
+// RegisterInvariants interface for registering invariants. Performs a no-op
+// as the evm module doesn't expose invariants.
+func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {
+}
+
+// RegisterServices registers a GRPC query service to respond to the
+// module-specific GRPC queries.
+func (am AppModule) RegisterServices(cfg module.Configurator) {
+ types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
+ types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
+
+ m := keeper.NewMigrator(*am.keeper, am.legacySubspace)
+
+ if err := cfg.RegisterMigration(types.ModuleName, 6, m.Migrate6to7); err != nil {
+ panic(err)
+ }
+}
+
+// BeginBlock returns the begin block for the evm module.
+func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
+ am.keeper.BeginBlock(ctx, req)
+}
+
+// EndBlock returns the end blocker for the evm module. It returns no validator
+// updates.
+func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate {
+ return am.keeper.EndBlock(ctx, req)
+}
+
+// InitGenesis performs genesis initialization for the evm module. It returns
+// no validator updates.
+func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
+ var genesisState types.GenesisState
+ cdc.MustUnmarshalJSON(data, &genesisState)
+ InitGenesis(ctx, am.keeper, am.ak, genesisState)
+ return []abci.ValidatorUpdate{}
+}
+
+// ExportGenesis returns the exported genesis state as raw bytes for the evm
+// module.
+func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
+ gs := ExportGenesis(ctx, am.keeper)
+ return cdc.MustMarshalJSON(gs)
+}
+
+// RegisterStoreDecoder registers a decoder for evm module's types
+func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {
+}
+
+// GenerateGenesisState creates a randomized GenState of the evm module.
+func (AppModule) GenerateGenesisState(_ *module.SimulationState) {
+}
+
+// WeightedOperations returns the all the evm module operations with their respective weights.
+func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation {
+ return nil
+}
diff --git a/x/evm/statedb/access_list.go b/x/evm/statedb/access_list.go
new file mode 100644
index 00000000..4513a916
--- /dev/null
+++ b/x/evm/statedb/access_list.go
@@ -0,0 +1,118 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package statedb
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+)
+
+type accessList struct {
+ addresses map[common.Address]int
+ slots []map[common.Hash]struct{}
+}
+
+// ContainsAddress returns true if the address is in the access list.
+func (al *accessList) ContainsAddress(address common.Address) bool {
+ _, ok := al.addresses[address]
+ return ok
+}
+
+// Contains checks if a slot within an account is present in the access list, returning
+// separate flags for the presence of the account and the slot respectively.
+func (al *accessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) {
+ idx, ok := al.addresses[address]
+ if !ok {
+ // no such address (and hence zero slots)
+ return false, false
+ }
+ if idx == -1 {
+ // address yes, but no slots
+ return true, false
+ }
+ _, slotPresent = al.slots[idx][slot]
+ return true, slotPresent
+}
+
+// newAccessList creates a new accessList.
+func newAccessList() *accessList {
+ return &accessList{
+ addresses: make(map[common.Address]int),
+ }
+}
+
+// AddAddress adds an address to the access list, and returns 'true' if the operation
+// caused a change (addr was not previously in the list).
+func (al *accessList) AddAddress(address common.Address) bool {
+ if _, present := al.addresses[address]; present {
+ return false
+ }
+ al.addresses[address] = -1
+ return true
+}
+
+// AddSlot adds the specified (addr, slot) combo to the access list.
+// Return values are:
+// - address added
+// - slot added
+// For any 'true' value returned, a corresponding journal entry must be made.
+func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) {
+ idx, addrPresent := al.addresses[address]
+ if !addrPresent || idx == -1 {
+ // Address not present, or addr present but no slots there
+ al.addresses[address] = len(al.slots)
+ slotmap := map[common.Hash]struct{}{slot: {}}
+ al.slots = append(al.slots, slotmap)
+ return !addrPresent, true
+ }
+ // There is already an (address,slot) mapping
+ slotmap := al.slots[idx]
+ if _, ok := slotmap[slot]; !ok {
+ slotmap[slot] = struct{}{}
+ // Journal add slot change
+ return false, true
+ }
+ // No changes required
+ return false, false
+}
+
+// DeleteSlot removes an (address, slot)-tuple from the access list.
+// This operation needs to be performed in the same order as the addition happened.
+// This method is meant to be used by the journal, which maintains ordering of
+// operations.
+func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) {
+ idx, addrOk := al.addresses[address]
+ if !addrOk {
+ panic("reverting slot change, address not present in list")
+ }
+ slotmap := al.slots[idx]
+ delete(slotmap, slot)
+ // If that was the last (first) slot, remove it
+ // Since additions and rollbacks are always performed in order,
+ // we can delete the item without worrying about screwing up later indices
+ if len(slotmap) == 0 {
+ al.slots = al.slots[:idx]
+ al.addresses[address] = -1
+ }
+}
+
+// DeleteAddress removes an address from the access list. This operation
+// needs to be performed in the same order as the addition happened.
+// This method is meant to be used by the journal, which maintains ordering of
+// operations.
+func (al *accessList) DeleteAddress(address common.Address) {
+ delete(al.addresses, address)
+}
diff --git a/x/evm/statedb/config.go b/x/evm/statedb/config.go
new file mode 100644
index 00000000..bf8fab23
--- /dev/null
+++ b/x/evm/statedb/config.go
@@ -0,0 +1,49 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package statedb
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// TxConfig encapulates the readonly information of current tx for `StateDB`.
+type TxConfig struct {
+ BlockHash common.Hash // hash of current block
+ TxHash common.Hash // hash of current tx
+ TxIndex uint // the index of current transaction
+ LogIndex uint // the index of next log within current block
+}
+
+// NewTxConfig returns a TxConfig
+func NewTxConfig(bhash, thash common.Hash, txIndex, logIndex uint) TxConfig {
+ return TxConfig{
+ BlockHash: bhash,
+ TxHash: thash,
+ TxIndex: txIndex,
+ LogIndex: logIndex,
+ }
+}
+
+// NewEmptyTxConfig construct an empty TxConfig,
+// used in context where there's no transaction, e.g. `eth_call`/`eth_estimateGas`.
+func NewEmptyTxConfig(bhash common.Hash) TxConfig {
+ return TxConfig{
+ BlockHash: bhash,
+ TxHash: common.Hash{},
+ TxIndex: 0,
+ LogIndex: 0,
+ }
+}
+
+// EVMConfig encapsulates common parameters needed to create an EVM to execute a message
+// It's mainly to reduce the number of method parameters
+type EVMConfig struct {
+ Params types.Params
+ ChainConfig *params.ChainConfig
+ CoinBase common.Address
+ BaseFee *big.Int
+}
diff --git a/x/evm/statedb/integration_test.go b/x/evm/statedb/integration_test.go
new file mode 100644
index 00000000..443ca55e
--- /dev/null
+++ b/x/evm/statedb/integration_test.go
@@ -0,0 +1,338 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package statedb_test
+
+import (
+ "math/big"
+ "testing"
+
+ "cosmossdk.io/math"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/contracts"
+ stakingprecompile "github.com/evmos/evmos/v19/precompiles/staking"
+ testcontracts "github.com/evmos/evmos/v19/precompiles/testutil/contracts"
+ testfactory "github.com/evmos/evmos/v19/testutil/integration/evmos/factory"
+ "github.com/evmos/evmos/v19/testutil/integration/evmos/grpc"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ testnetwork "github.com/evmos/evmos/v19/testutil/integration/evmos/network"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ //nolint:revive // okay to use dot imports for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // okay to use dot imports for Ginkgo
+ . "github.com/onsi/gomega"
+)
+
+func TestNestedEVMExtensionCall(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Nested EVM Extension Call Test Suite")
+}
+
+type testCase struct {
+ method string
+ expDelegation bool
+ expSenderERC20Balance *big.Int
+ expContractERC20Balance *big.Int
+}
+
+// This test is a demonstration of the flash loan exploit that was reported.
+// This happens when interacting with EVM extensions in smart contract methods,
+// where a resulting state change has the same value as the original state value.
+//
+// Before the fix, this would result in state changes not being persisted after the EVM extension call,
+// therefore leaving the loaned funds in the contract.
+var _ = Describe("testing the flash loan exploit", Ordered, func() {
+ var (
+ keyring testkeyring.Keyring
+ // NOTE: we need to use the unit test network here because we need it to instantiate the staking precompile correctly
+ network *testnetwork.UnitTestNetwork
+ handler grpc.Handler
+ factory testfactory.TxFactory
+
+ deployer testkeyring.Key
+
+ erc20Addr common.Address
+ flashLoanAddr common.Address
+ flashLoanContract evmtypes.CompiledContract
+
+ validatorToDelegateTo string
+
+ delegatedAmountPre math.Int
+
+ stakingPrecompile *stakingprecompile.Precompile
+ )
+
+ mintAmount := big.NewInt(2e18)
+ delegateAmount := big.NewInt(1e18)
+
+ BeforeAll(func() {
+ keyring = testkeyring.New(2)
+ network = testnetwork.NewUnitTestNetwork(
+ testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...),
+ )
+ handler = grpc.NewIntegrationHandler(network)
+ factory = testfactory.New(network, handler)
+
+ deployer = keyring.GetKey(0)
+
+ var err error
+ stakingPrecompile, err = stakingprecompile.NewPrecompile(network.App.StakingKeeper, network.App.AuthzKeeper)
+ Expect(err).ToNot(HaveOccurred(), "failed to create staking precompile")
+
+ // Load the flash loan contract from the compiled JSON data.
+ flashLoanContract, err = testcontracts.LoadFlashLoanContract()
+ Expect(err).ToNot(HaveOccurred(), "failed to load flash loan contract")
+ })
+
+ BeforeEach(func() {
+ valsRes, err := handler.GetBondedValidators()
+ Expect(err).ToNot(HaveOccurred(), "failed to get bonded validators")
+
+ validatorToDelegateTo = valsRes.Validators[0].OperatorAddress
+ qRes, err := handler.GetDelegation(deployer.AccAddr.String(), validatorToDelegateTo)
+ Expect(err).ToNot(HaveOccurred(), "failed to get delegation")
+ delegatedAmountPre = qRes.DelegationResponse.Balance.Amount
+
+ // Deploy an ERC-20 token contract.
+ erc20Addr, err = factory.DeployContract(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{},
+ testfactory.ContractDeploymentData{
+ Contract: contracts.ERC20MinterBurnerDecimalsContract,
+ ConstructorArgs: []interface{}{"TestToken", "TT", uint8(18)},
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC-20 contract")
+
+ // Mint some tokens to the deployer.
+ _, err = factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &erc20Addr},
+ testfactory.CallArgs{
+ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ MethodName: "mint",
+ Args: []interface{}{
+ deployer.Addr, mintAmount,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to mint tokens")
+
+ // Check the balance of the deployer on the ERC20 contract.
+ res, err := factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &erc20Addr},
+ testfactory.CallArgs{
+ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ MethodName: "balanceOf",
+ Args: []interface{}{
+ deployer.Addr,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+
+ ethRes, err := evmtypes.DecodeTxResponse(res.Data)
+ Expect(err).ToNot(HaveOccurred(), "failed to decode balance of tx response")
+
+ unpacked, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack(
+ "balanceOf",
+ ethRes.Ret,
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balance")
+
+ balance, ok := unpacked[0].(*big.Int)
+ Expect(ok).To(BeTrue(), "failed to convert balance to big.Int")
+ Expect(balance.String()).To(Equal(mintAmount.String()), "balance is not correct")
+
+ // Deploy the flash loan contract.
+ flashLoanAddr, err = factory.DeployContract(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{},
+ testfactory.ContractDeploymentData{
+ Contract: flashLoanContract,
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to deploy flash loan contract")
+
+ // Approve the flash loan contract to spend tokens. This is required because
+ // the contract will get funds from the caller to perform actions.
+ _, err = factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &erc20Addr},
+ testfactory.CallArgs{
+ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ MethodName: "approve",
+ Args: []interface{}{
+ flashLoanAddr, mintAmount,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to approve flash loan contract")
+
+ // Check the allowance.
+ res, err = factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &erc20Addr},
+ testfactory.CallArgs{
+ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ MethodName: "allowance",
+ Args: []interface{}{
+ deployer.Addr, flashLoanAddr,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to get allowance")
+
+ ethRes, err = evmtypes.DecodeTxResponse(res.Data)
+ Expect(err).ToNot(HaveOccurred(), "failed to decode allowance tx response")
+
+ unpacked, err = contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack(
+ "allowance",
+ ethRes.Ret,
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack allowance")
+
+ var allowance *big.Int
+ allowance, ok = unpacked[0].(*big.Int)
+ Expect(ok).To(BeTrue(), "failed to convert allowance to big.Int")
+ Expect(allowance.String()).To(Equal(mintAmount.String()), "allowance is not correct")
+
+ // Approve the flash loan contract to delegate tokens on behalf of user.
+ precompileAddr := stakingPrecompile.Address()
+
+ _, err = factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &precompileAddr},
+ testfactory.CallArgs{
+ ContractABI: stakingPrecompile.ABI,
+ MethodName: "approve",
+ Args: []interface{}{
+ flashLoanAddr, delegateAmount, []string{stakingprecompile.DelegateMsg},
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to approve flash loan contract")
+
+ // Check the allowance.
+ res, err = factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &precompileAddr},
+ testfactory.CallArgs{
+ ContractABI: stakingPrecompile.ABI,
+ MethodName: "allowance",
+ Args: []interface{}{
+ deployer.Addr, flashLoanAddr, stakingprecompile.DelegateMsg,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to get allowance")
+
+ ethRes, err = evmtypes.DecodeTxResponse(res.Data)
+ Expect(err).ToNot(HaveOccurred(), "failed to decode allowance tx response")
+
+ err = stakingPrecompile.UnpackIntoInterface(&allowance, "allowance", ethRes.Ret)
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack allowance")
+ })
+
+ DescribeTable("call the flashLoan contract", func(tc testCase) {
+ _, err := factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{
+ To: &flashLoanAddr,
+ GasPrice: big.NewInt(900_000_000),
+ GasLimit: 400_000,
+ },
+ testfactory.CallArgs{
+ ContractABI: flashLoanContract.ABI,
+ MethodName: tc.method,
+ Args: []interface{}{
+ erc20Addr,
+ validatorToDelegateTo,
+ delegateAmount,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to execute flash loan")
+
+ delRes, err := handler.GetDelegation(deployer.AccAddr.String(), validatorToDelegateTo)
+ Expect(err).ToNot(HaveOccurred(), "failed to get delegation")
+ delAmtPost := delRes.DelegationResponse.Balance.Amount
+ if tc.expDelegation {
+ Expect(delAmtPost).To(Equal(
+ delegatedAmountPre.Add(math.NewIntFromBigInt(delegateAmount))),
+ "delegated amount is not correct",
+ )
+ } else {
+ Expect(delAmtPost).To(Equal(delegatedAmountPre))
+ }
+
+ // Check the ERC20 token balance of the deployer.
+ res, err := factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &erc20Addr},
+ testfactory.CallArgs{
+ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ MethodName: "balanceOf",
+ Args: []interface{}{
+ deployer.Addr,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+
+ ethRes, err := evmtypes.DecodeTxResponse(res.Data)
+ Expect(err).ToNot(HaveOccurred(), "failed to decode balance of tx response")
+
+ unpacked, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack(
+ "balanceOf",
+ ethRes.Ret,
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balance")
+
+ balance, ok := unpacked[0].(*big.Int)
+ Expect(ok).To(BeTrue(), "failed to convert balance to big.Int")
+ Expect(balance.String()).To(Equal(tc.expSenderERC20Balance.String()), "balance is not correct")
+
+ // Check FlashLoan smart contract ERC20 token balance.
+ res, err = factory.ExecuteContractCall(
+ deployer.Priv,
+ evmtypes.EvmTxArgs{To: &erc20Addr},
+ testfactory.CallArgs{
+ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI,
+ MethodName: "balanceOf",
+ Args: []interface{}{
+ flashLoanAddr,
+ },
+ },
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to get balance")
+
+ ethRes, err = evmtypes.DecodeTxResponse(res.Data)
+ Expect(err).ToNot(HaveOccurred(), "failed to decode balance of tx response")
+
+ unpacked, err = contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack(
+ "balanceOf",
+ ethRes.Ret,
+ )
+ Expect(err).ToNot(HaveOccurred(), "failed to unpack balance")
+
+ balance, ok = unpacked[0].(*big.Int)
+ Expect(ok).To(BeTrue(), "failed to convert balance to big.Int")
+ Expect(balance.String()).To(Equal(tc.expContractERC20Balance.String()), "balance is not correct")
+ },
+ Entry("flasLoan method & expect delegation", testCase{
+ method: "flashLoan",
+ expDelegation: true,
+ expSenderERC20Balance: mintAmount,
+ expContractERC20Balance: big.NewInt(0),
+ }),
+ Entry("flashLoanWithRevert method - delegation reverted", testCase{
+ method: "flashLoanWithRevert",
+ expDelegation: false,
+ expSenderERC20Balance: delegateAmount,
+ expContractERC20Balance: delegateAmount,
+ }),
+ )
+})
diff --git a/x/evm/statedb/interfaces.go b/x/evm/statedb/interfaces.go
new file mode 100644
index 00000000..7839abdd
--- /dev/null
+++ b/x/evm/statedb/interfaces.go
@@ -0,0 +1,37 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package statedb
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// ExtStateDB defines an extension to the interface provided by the go-ethereum
+// codebase to support additional state transition functionalities. In particular
+// it supports appending a new entry to the state journal through
+// AppendJournalEntry so that the state can be reverted after running
+// stateful precompiled contracts.
+type ExtStateDB interface {
+ vm.StateDB
+ AppendJournalEntry(JournalEntry)
+}
+
+// Keeper provide underlying storage of StateDB
+type Keeper interface {
+ // Read methods
+ GetAccount(ctx sdk.Context, addr common.Address) *Account
+ GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash
+ GetCode(ctx sdk.Context, codeHash common.Hash) []byte
+ // the callback returns false to break early
+ ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool)
+
+ // Write methods, only called by `StateDB.Commit()`
+ SetAccount(ctx sdk.Context, addr common.Address, account Account) error
+ DeleteState(ctx sdk.Context, addr common.Address, key common.Hash)
+ SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte)
+ DeleteCode(ctx sdk.Context, codeHash []byte)
+ SetCode(ctx sdk.Context, codeHash []byte, code []byte)
+ DeleteAccount(ctx sdk.Context, addr common.Address) error
+}
diff --git a/x/evm/statedb/journal.go b/x/evm/statedb/journal.go
new file mode 100644
index 00000000..615b4627
--- /dev/null
+++ b/x/evm/statedb/journal.go
@@ -0,0 +1,278 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package statedb
+
+import (
+ "bytes"
+ "math/big"
+ "sort"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+// JournalEntry is a modification entry in the state change journal that can be
+// Reverted on demand.
+type JournalEntry interface {
+ // Revert undoes the changes introduced by this journal entry.
+ Revert(*StateDB)
+
+ // Dirtied returns the Ethereum address modified by this journal entry.
+ Dirtied() *common.Address
+}
+
+// journal contains the list of state modifications applied since the last state
+// commit. These are tracked to be able to be reverted in the case of an execution
+// exception or request for reversal.
+type journal struct {
+ entries []JournalEntry // Current changes tracked by the journal
+ dirties map[common.Address]int // Dirty accounts and the number of changes
+}
+
+// newJournal creates a new initialized journal.
+func newJournal() *journal {
+ return &journal{
+ dirties: make(map[common.Address]int),
+ }
+}
+
+// sortedDirties sort the dirty addresses for deterministic iteration
+func (j *journal) sortedDirties() []common.Address {
+ keys := make([]common.Address, 0, len(j.dirties))
+ for k := range j.dirties {
+ keys = append(keys, k)
+ }
+ sort.Slice(keys, func(i, j int) bool {
+ return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) < 0
+ })
+ return keys
+}
+
+// append inserts a new modification entry to the end of the change journal.
+func (j *journal) append(entry JournalEntry) {
+ j.entries = append(j.entries, entry)
+ if addr := entry.Dirtied(); addr != nil {
+ j.dirties[*addr]++
+ }
+}
+
+// Revert undoes a batch of journalled modifications along with any Reverted
+// dirty handling too.
+func (j *journal) Revert(statedb *StateDB, snapshot int) {
+ for i := len(j.entries) - 1; i >= snapshot; i-- {
+ // Undo the changes made by the operation
+ j.entries[i].Revert(statedb)
+
+ // Drop any dirty tracking induced by the change
+ if addr := j.entries[i].Dirtied(); addr != nil {
+ if j.dirties[*addr]--; j.dirties[*addr] == 0 {
+ delete(j.dirties, *addr)
+ }
+ }
+ }
+ j.entries = j.entries[:snapshot]
+}
+
+// length returns the current number of entries in the journal.
+func (j *journal) length() int {
+ return len(j.entries)
+}
+
+type (
+ // Changes to the account trie.
+ createObjectChange struct {
+ account *common.Address
+ }
+ resetObjectChange struct {
+ prev *stateObject
+ }
+ suicideChange struct {
+ account *common.Address
+ prev bool // whether account had already suicided
+ prevbalance *big.Int
+ }
+
+ // Changes to individual accounts.
+ balanceChange struct {
+ account *common.Address
+ prev *big.Int
+ }
+ nonceChange struct {
+ account *common.Address
+ prev uint64
+ }
+ storageChange struct {
+ account *common.Address
+ key, prevalue common.Hash
+ }
+ codeChange struct {
+ account *common.Address
+ prevcode, prevhash []byte
+ }
+
+ // Changes to other state values.
+ refundChange struct {
+ prev uint64
+ }
+ addLogChange struct{}
+
+ // Changes to the access list
+ accessListAddAccountChange struct {
+ address *common.Address
+ }
+ accessListAddSlotChange struct {
+ address *common.Address
+ slot *common.Hash
+ }
+ precompileCallChange struct {
+ multiStore sdk.CacheMultiStore
+ events sdk.Events
+ }
+)
+
+var (
+ _ JournalEntry = createObjectChange{}
+ _ JournalEntry = resetObjectChange{}
+ _ JournalEntry = suicideChange{}
+ _ JournalEntry = balanceChange{}
+ _ JournalEntry = nonceChange{}
+ _ JournalEntry = storageChange{}
+ _ JournalEntry = codeChange{}
+ _ JournalEntry = refundChange{}
+ _ JournalEntry = addLogChange{}
+ _ JournalEntry = accessListAddAccountChange{}
+ _ JournalEntry = accessListAddSlotChange{}
+ _ JournalEntry = precompileCallChange{}
+)
+
+func (pc precompileCallChange) Revert(s *StateDB) {
+ // rollback multi store from cache ctx to the previous
+ // state stored in the snapshot
+ s.cacheCtx = s.cacheCtx.WithMultiStore(pc.multiStore)
+ s.writeCache = func() {
+ // rollback the events to the ones snapshot
+ // on the snapshot
+ s.ctx.EventManager().EmitEvents(pc.events)
+ pc.multiStore.Write()
+ }
+}
+
+func (pc precompileCallChange) Dirtied() *common.Address {
+ return nil
+}
+
+func (ch createObjectChange) Revert(s *StateDB) {
+ delete(s.stateObjects, *ch.account)
+}
+
+func (ch createObjectChange) Dirtied() *common.Address {
+ return ch.account
+}
+
+func (ch resetObjectChange) Revert(s *StateDB) {
+ s.setStateObject(ch.prev)
+}
+
+func (ch resetObjectChange) Dirtied() *common.Address {
+ return nil
+}
+
+func (ch suicideChange) Revert(s *StateDB) {
+ obj := s.getStateObject(*ch.account)
+ if obj != nil {
+ obj.suicided = ch.prev
+ obj.setBalance(ch.prevbalance)
+ }
+}
+
+func (ch suicideChange) Dirtied() *common.Address {
+ return ch.account
+}
+
+func (ch balanceChange) Revert(s *StateDB) {
+ s.getStateObject(*ch.account).setBalance(ch.prev)
+}
+
+func (ch balanceChange) Dirtied() *common.Address {
+ return ch.account
+}
+
+func (ch nonceChange) Revert(s *StateDB) {
+ s.getStateObject(*ch.account).setNonce(ch.prev)
+}
+
+func (ch nonceChange) Dirtied() *common.Address {
+ return ch.account
+}
+
+func (ch codeChange) Revert(s *StateDB) {
+ s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
+}
+
+func (ch codeChange) Dirtied() *common.Address {
+ return ch.account
+}
+
+func (ch storageChange) Revert(s *StateDB) {
+ s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
+}
+
+func (ch storageChange) Dirtied() *common.Address {
+ return ch.account
+}
+
+func (ch refundChange) Revert(s *StateDB) {
+ s.refund = ch.prev
+}
+
+func (ch refundChange) Dirtied() *common.Address {
+ return nil
+}
+
+func (ch addLogChange) Revert(s *StateDB) {
+ s.logs = s.logs[:len(s.logs)-1]
+}
+
+func (ch addLogChange) Dirtied() *common.Address {
+ return nil
+}
+
+func (ch accessListAddAccountChange) Revert(s *StateDB) {
+ /*
+ One important invariant here, is that whenever a (addr, slot) is added, if the
+ addr is not already present, the add causes two journal entries:
+ - one for the address,
+ - one for the (address,slot)
+ Therefore, when unrolling the change, we can always blindly delete the
+ (addr) at this point, since no storage adds can remain when come upon
+ a single (addr) change.
+ */
+ s.accessList.DeleteAddress(*ch.address)
+}
+
+func (ch accessListAddAccountChange) Dirtied() *common.Address {
+ return nil
+}
+
+func (ch accessListAddSlotChange) Revert(s *StateDB) {
+ s.accessList.DeleteSlot(*ch.address, *ch.slot)
+}
+
+func (ch accessListAddSlotChange) Dirtied() *common.Address {
+ return nil
+}
diff --git a/x/evm/statedb/mock_test.go b/x/evm/statedb/mock_test.go
new file mode 100644
index 00000000..4f411e6a
--- /dev/null
+++ b/x/evm/statedb/mock_test.go
@@ -0,0 +1,115 @@
+package statedb_test
+
+import (
+ "errors"
+ "maps"
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+var (
+ _ statedb.Keeper = &MockKeeper{}
+ errAddress common.Address = common.BigToAddress(big.NewInt(100))
+ emptyCodeHash = crypto.Keccak256(nil)
+)
+
+type MockAcount struct {
+ account statedb.Account
+ states statedb.Storage
+}
+
+type MockKeeper struct {
+ accounts map[common.Address]MockAcount
+ codes map[common.Hash][]byte
+}
+
+func NewMockKeeper() *MockKeeper {
+ return &MockKeeper{
+ accounts: make(map[common.Address]MockAcount),
+ codes: make(map[common.Hash][]byte),
+ }
+}
+
+func (k MockKeeper) GetAccount(_ sdk.Context, addr common.Address) *statedb.Account {
+ acct, ok := k.accounts[addr]
+ if !ok {
+ return nil
+ }
+ return &acct.account
+}
+
+func (k MockKeeper) GetState(_ sdk.Context, addr common.Address, key common.Hash) common.Hash {
+ return k.accounts[addr].states[key]
+}
+
+func (k MockKeeper) GetCode(_ sdk.Context, codeHash common.Hash) []byte {
+ return k.codes[codeHash]
+}
+
+func (k MockKeeper) ForEachStorage(_ sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) {
+ if acct, ok := k.accounts[addr]; ok {
+ for k, v := range acct.states {
+ if !cb(k, v) {
+ return
+ }
+ }
+ }
+}
+
+func (k MockKeeper) SetAccount(_ sdk.Context, addr common.Address, account statedb.Account) error {
+ if addr == errAddress {
+ return errors.New("mock db error")
+ }
+ acct, exists := k.accounts[addr]
+ if exists {
+ // update
+ acct.account = account
+ k.accounts[addr] = acct
+ } else {
+ k.accounts[addr] = MockAcount{account: account, states: make(statedb.Storage)}
+ }
+ return nil
+}
+
+func (k MockKeeper) SetState(_ sdk.Context, addr common.Address, key common.Hash, value []byte) {
+ if acct, ok := k.accounts[addr]; ok {
+ acct.states[key] = common.BytesToHash(value)
+ }
+}
+
+func (k MockKeeper) DeleteState(_ sdk.Context, addr common.Address, key common.Hash) {
+ if acct, ok := k.accounts[addr]; ok {
+ delete(acct.states, key)
+ }
+}
+
+func (k MockKeeper) SetCode(_ sdk.Context, codeHash []byte, code []byte) {
+ k.codes[common.BytesToHash(codeHash)] = code
+}
+
+func (k MockKeeper) DeleteCode(_ sdk.Context, codeHash []byte) {
+ delete(k.codes, common.BytesToHash(codeHash))
+}
+
+func (k MockKeeper) DeleteAccount(_ sdk.Context, addr common.Address) error {
+ if addr == errAddress {
+ return errors.New("mock db error")
+ }
+ old := k.accounts[addr]
+ delete(k.accounts, addr)
+ if !types.IsEmptyCodeHash(old.account.CodeHash) {
+ delete(k.codes, common.BytesToHash(old.account.CodeHash))
+ }
+ return nil
+}
+
+func (k MockKeeper) Clone() *MockKeeper {
+ accounts := maps.Clone(k.accounts)
+ codes := maps.Clone(k.codes)
+ return &MockKeeper{accounts, codes}
+}
diff --git a/x/evm/statedb/state_object.go b/x/evm/statedb/state_object.go
new file mode 100644
index 00000000..51a0b258
--- /dev/null
+++ b/x/evm/statedb/state_object.go
@@ -0,0 +1,253 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package statedb
+
+import (
+ "bytes"
+ "math/big"
+ "sort"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// Account is the Ethereum consensus representation of accounts.
+// These objects are stored in the storage of auth module.
+type Account struct {
+ Nonce uint64
+ Balance *big.Int
+ CodeHash []byte
+}
+
+// NewEmptyAccount returns an empty account.
+func NewEmptyAccount() *Account {
+ return &Account{
+ Balance: new(big.Int),
+ CodeHash: types.EmptyCodeHash,
+ }
+}
+
+// IsContract returns if the account contains contract code.
+func (acct Account) IsContract() bool {
+ return !types.IsEmptyCodeHash(acct.CodeHash)
+}
+
+// Storage represents in-memory cache/buffer of contract storage.
+type Storage map[common.Hash]common.Hash
+
+// SortedKeys sort the keys for deterministic iteration
+func (s Storage) SortedKeys() []common.Hash {
+ keys := make([]common.Hash, 0, len(s))
+ for k := range s {
+ keys = append(keys, k)
+ }
+ sort.Slice(keys, func(i, j int) bool {
+ return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) < 0
+ })
+ return keys
+}
+
+// stateObject is the state of an account
+type stateObject struct {
+ db *StateDB
+
+ account Account
+ code []byte
+
+ // state storage
+ originStorage Storage
+ dirtyStorage Storage
+
+ address common.Address
+
+ // flags
+ dirtyCode bool
+ suicided bool
+}
+
+// newObject creates a state object.
+func newObject(db *StateDB, address common.Address, account Account) *stateObject {
+ if account.Balance == nil {
+ account.Balance = new(big.Int)
+ }
+
+ if account.CodeHash == nil {
+ account.CodeHash = types.EmptyCodeHash
+ }
+
+ return &stateObject{
+ db: db,
+ address: address,
+ account: account,
+ originStorage: make(Storage),
+ dirtyStorage: make(Storage),
+ }
+}
+
+// empty returns whether the account is considered empty.
+func (s *stateObject) empty() bool {
+ return s.account.Nonce == 0 &&
+ s.account.Balance.Sign() == 0 &&
+ types.IsEmptyCodeHash(s.account.CodeHash)
+}
+
+func (s *stateObject) markSuicided() {
+ s.suicided = true
+}
+
+// AddBalance adds amount to s's balance.
+// It is used to add funds to the destination account of a transfer.
+func (s *stateObject) AddBalance(amount *big.Int) {
+ if amount.Sign() == 0 {
+ return
+ }
+ s.SetBalance(new(big.Int).Add(s.Balance(), amount))
+}
+
+// SubBalance removes amount from s's balance.
+// It is used to remove funds from the origin account of a transfer.
+func (s *stateObject) SubBalance(amount *big.Int) {
+ if amount.Sign() == 0 {
+ return
+ }
+ s.SetBalance(new(big.Int).Sub(s.Balance(), amount))
+}
+
+// SetBalance update account balance.
+func (s *stateObject) SetBalance(amount *big.Int) {
+ s.db.journal.append(balanceChange{
+ account: &s.address,
+ prev: new(big.Int).Set(s.account.Balance),
+ })
+ s.setBalance(amount)
+}
+
+// AddPrecompileFn appends to the journal an entry
+// with a snapshot of the multi-store and events
+// previous to the precompile call
+func (s *stateObject) AddPrecompileFn(cms sdk.CacheMultiStore, events sdk.Events) {
+ s.db.journal.append(precompileCallChange{
+ multiStore: cms,
+ events: events,
+ })
+}
+
+func (s *stateObject) setBalance(amount *big.Int) {
+ s.account.Balance = amount
+}
+
+//
+// Attribute accessors
+//
+
+// Returns the address of the contract/account
+func (s *stateObject) Address() common.Address {
+ return s.address
+}
+
+// Code returns the contract code associated with this object, if any.
+func (s *stateObject) Code() []byte {
+ if s.code != nil {
+ return s.code
+ }
+
+ if types.IsEmptyCodeHash(s.CodeHash()) {
+ return nil
+ }
+
+ code := s.db.keeper.GetCode(s.db.ctx, common.BytesToHash(s.CodeHash()))
+ s.code = code
+
+ return code
+}
+
+// CodeSize returns the size of the contract code associated with this object,
+// or zero if none.
+func (s *stateObject) CodeSize() int {
+ return len(s.Code())
+}
+
+// SetCode set contract code to account
+func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
+ prevcode := s.Code()
+ s.db.journal.append(codeChange{
+ account: &s.address,
+ prevhash: s.CodeHash(),
+ prevcode: prevcode,
+ })
+ s.setCode(codeHash, code)
+}
+
+func (s *stateObject) setCode(codeHash common.Hash, code []byte) {
+ s.code = code
+ s.account.CodeHash = codeHash[:]
+ s.dirtyCode = true
+}
+
+// SetCode set nonce to account
+func (s *stateObject) SetNonce(nonce uint64) {
+ s.db.journal.append(nonceChange{
+ account: &s.address,
+ prev: s.account.Nonce,
+ })
+ s.setNonce(nonce)
+}
+
+func (s *stateObject) setNonce(nonce uint64) {
+ s.account.Nonce = nonce
+}
+
+// CodeHash returns the code hash of account
+func (s *stateObject) CodeHash() []byte {
+ return s.account.CodeHash
+}
+
+// Balance returns the balance of account
+func (s *stateObject) Balance() *big.Int {
+ return s.account.Balance
+}
+
+// Nonce returns the nonce of account
+func (s *stateObject) Nonce() uint64 {
+ return s.account.Nonce
+}
+
+// GetCommittedState query the committed state
+func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
+ if value, cached := s.originStorage[key]; cached {
+ return value
+ }
+ // If no live objects are available, load it from keeper
+ value := s.db.keeper.GetState(s.db.ctx, s.Address(), key)
+ s.originStorage[key] = value
+ return value
+}
+
+// GetState query the current state (including dirty state)
+func (s *stateObject) GetState(key common.Hash) common.Hash {
+ if value, dirty := s.dirtyStorage[key]; dirty {
+ return value
+ }
+ return s.GetCommittedState(key)
+}
+
+// SetState sets the contract state
+func (s *stateObject) SetState(key common.Hash, value common.Hash) {
+ // If the new value is the same as old, don't set
+ prev := s.GetState(key)
+ if prev == value {
+ return
+ }
+ // New value is different, update and journal the change
+ s.db.journal.append(storageChange{
+ account: &s.address,
+ key: key,
+ prevalue: prev,
+ })
+ s.setState(key, value)
+}
+
+func (s *stateObject) setState(key, value common.Hash) {
+ s.dirtyStorage[key] = value
+}
diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go
new file mode 100644
index 00000000..6e46b224
--- /dev/null
+++ b/x/evm/statedb/statedb.go
@@ -0,0 +1,555 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package statedb
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+ "sort"
+
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+// revision is the identifier of a version of state.
+// it consists of an auto-increment id and a journal index.
+// it's safer to use than using journal index alone.
+type revision struct {
+ id int
+ journalIndex int
+}
+
+var _ vm.StateDB = &StateDB{}
+
+// StateDB structs within the ethereum protocol are used to store anything
+// within the merkle trie. StateDBs take care of caching and storing
+// nested states. It's the general query interface to retrieve:
+// * Contracts
+// * Accounts
+type StateDB struct {
+ keeper Keeper
+ ctx sdk.Context
+ // cacheCtx is used on precompile calls. It allows to commit the current journal
+ // entries to get the updated state in for the precompile call.
+ cacheCtx sdk.Context
+ // writeCache function contains all the changes related to precompile calls.
+ writeCache func()
+
+ // Journal of state modifications. This is the backbone of
+ // Snapshot and RevertToSnapshot.
+ journal *journal
+ validRevisions []revision
+ nextRevisionID int
+
+ stateObjects map[common.Address]*stateObject
+
+ txConfig TxConfig
+
+ // The refund counter, also used by state transitioning.
+ refund uint64
+
+ // Per-transaction logs
+ logs []*ethtypes.Log
+
+ // Per-transaction access list
+ accessList *accessList
+
+ // The count of calls to precompiles
+ precompileCallsCounter uint8
+}
+
+// New creates a new state from a given trie.
+func New(ctx sdk.Context, keeper Keeper, txConfig TxConfig) *StateDB {
+ return &StateDB{
+ keeper: keeper,
+ ctx: ctx,
+ stateObjects: make(map[common.Address]*stateObject),
+ journal: newJournal(),
+ accessList: newAccessList(),
+
+ txConfig: txConfig,
+ }
+}
+
+// Keeper returns the underlying `Keeper`
+func (s *StateDB) Keeper() Keeper {
+ return s.keeper
+}
+
+// GetContext returns the transaction Context.
+func (s *StateDB) GetContext() sdk.Context {
+ return s.ctx
+}
+
+// GetCacheContext returns the stateDB CacheContext.
+func (s *StateDB) GetCacheContext() (sdk.Context, error) {
+ if s.writeCache == nil {
+ err := s.cache()
+ if err != nil {
+ return s.ctx, err
+ }
+ }
+ return s.cacheCtx, nil
+}
+
+// MultiStoreSnapshot returns a copy of the stateDB CacheMultiStore.
+func (s *StateDB) MultiStoreSnapshot() sdk.CacheMultiStore {
+ if s.writeCache == nil {
+ err := s.cache()
+ if err != nil {
+ return s.ctx.MultiStore().CacheMultiStore()
+ }
+ }
+ // the cacheCtx multi store is already a CacheMultiStore
+ // so we need to pass a copy of the current state of it
+ cms := s.cacheCtx.MultiStore().(sdk.CacheMultiStore)
+ snapshot := cms.Copy()
+
+ return snapshot
+}
+
+// cache creates the stateDB cache context
+func (s *StateDB) cache() error {
+ if s.ctx.MultiStore() == nil {
+ return errors.New("ctx has no multi store")
+ }
+ s.cacheCtx, s.writeCache = s.ctx.CacheContext()
+ return nil
+}
+
+// AddLog adds a log, called by evm.
+func (s *StateDB) AddLog(log *ethtypes.Log) {
+ s.journal.append(addLogChange{})
+
+ log.TxHash = s.txConfig.TxHash
+ log.BlockHash = s.txConfig.BlockHash
+ log.TxIndex = s.txConfig.TxIndex
+ log.Index = s.txConfig.LogIndex + uint(len(s.logs))
+ s.logs = append(s.logs, log)
+}
+
+// Logs returns the logs of current transaction.
+func (s *StateDB) Logs() []*ethtypes.Log {
+ return s.logs
+}
+
+// AddRefund adds gas to the refund counter
+func (s *StateDB) AddRefund(gas uint64) {
+ s.journal.append(refundChange{prev: s.refund})
+ s.refund += gas
+}
+
+// SubRefund removes gas from the refund counter.
+// This method will panic if the refund counter goes below zero
+func (s *StateDB) SubRefund(gas uint64) {
+ s.journal.append(refundChange{prev: s.refund})
+ if gas > s.refund {
+ panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund))
+ }
+ s.refund -= gas
+}
+
+// Exist reports whether the given account address exists in the state.
+// Notably this also returns true for suicided accounts.
+func (s *StateDB) Exist(addr common.Address) bool {
+ return s.getStateObject(addr) != nil
+}
+
+// Empty returns whether the state object is either non-existent
+// or empty according to the EIP161 specification (balance = nonce = code = 0)
+func (s *StateDB) Empty(addr common.Address) bool {
+ so := s.getStateObject(addr)
+ return so == nil || so.empty()
+}
+
+// GetBalance retrieves the balance from the given address or 0 if object not found
+func (s *StateDB) GetBalance(addr common.Address) *big.Int {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Balance()
+ }
+ return common.Big0
+}
+
+// GetNonce returns the nonce of account, 0 if not exists.
+func (s *StateDB) GetNonce(addr common.Address) uint64 {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Nonce()
+ }
+
+ return 0
+}
+
+// GetCode returns the code of account, nil if not exists.
+func (s *StateDB) GetCode(addr common.Address) []byte {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Code()
+ }
+ return nil
+}
+
+// GetCodeSize returns the code size of account.
+func (s *StateDB) GetCodeSize(addr common.Address) int {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.CodeSize()
+ }
+ return 0
+}
+
+// GetCodeHash returns the code hash of account.
+func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
+ stateObject := s.getStateObject(addr)
+ if stateObject == nil {
+ return common.Hash{}
+ }
+ return common.BytesToHash(stateObject.CodeHash())
+}
+
+// GetState retrieves a value from the given account's storage trie.
+func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.GetState(hash)
+ }
+ return common.Hash{}
+}
+
+// GetCommittedState retrieves a value from the given account's committed storage trie.
+func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.GetCommittedState(hash)
+ }
+ return common.Hash{}
+}
+
+// GetRefund returns the current value of the refund counter.
+func (s *StateDB) GetRefund() uint64 {
+ return s.refund
+}
+
+// HasSuicided returns if the contract is suicided in current transaction.
+func (s *StateDB) HasSuicided(addr common.Address) bool {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.suicided
+ }
+ return false
+}
+
+// AddPreimage records a SHA3 preimage seen by the VM.
+// AddPreimage performs a no-op since the EnablePreimageRecording flag is disabled
+// on the vm.Config during state transitions. No store trie preimages are written
+// to the database.
+func (s *StateDB) AddPreimage(_ common.Hash, _ []byte) {}
+
+// getStateObject retrieves a state object given by the address, returning nil if
+// the object is not found.
+func (s *StateDB) getStateObject(addr common.Address) *stateObject {
+ // Prefer live objects if any is available
+ if obj := s.stateObjects[addr]; obj != nil {
+ return obj
+ }
+ // If no live objects are available, load it from keeper
+ account := s.keeper.GetAccount(s.ctx, addr)
+ if account == nil {
+ return nil
+ }
+ // Insert into the live set
+ obj := newObject(s, addr, *account)
+ s.setStateObject(obj)
+ return obj
+}
+
+// getOrNewStateObject retrieves a state object or create a new state object if nil.
+func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
+ stateObject := s.getStateObject(addr)
+ if stateObject == nil {
+ stateObject, _ = s.createObject(addr)
+ }
+ return stateObject
+}
+
+// createObject creates a new state object. If there is an existing account with
+// the given address, it is overwritten and returned as the second return value.
+func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
+ prev = s.getStateObject(addr)
+
+ newobj = newObject(s, addr, Account{})
+ if prev == nil {
+ s.journal.append(createObjectChange{account: &addr})
+ } else {
+ s.journal.append(resetObjectChange{prev: prev})
+ }
+ s.setStateObject(newobj)
+ if prev != nil {
+ return newobj, prev
+ }
+ return newobj, nil
+}
+
+// CreateAccount explicitly creates a state object. If a state object with the address
+// already exists the balance is carried over to the new account.
+//
+// CreateAccount is called during the EVM CREATE operation. The situation might arise that
+// a contract does the following:
+//
+// 1. sends funds to sha(account ++ (nonce + 1))
+// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
+//
+// Carrying over the balance ensures that Ether doesn't disappear.
+func (s *StateDB) CreateAccount(addr common.Address) {
+ newObj, prev := s.createObject(addr)
+ if prev != nil {
+ newObj.setBalance(prev.account.Balance)
+ }
+}
+
+// ForEachStorage iterate the contract storage, the iteration order is not defined.
+func (s *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
+ so := s.getStateObject(addr)
+ if so == nil {
+ return nil
+ }
+ s.keeper.ForEachStorage(s.ctx, addr, func(key, value common.Hash) bool {
+ if value, dirty := so.dirtyStorage[key]; dirty {
+ return cb(key, value)
+ }
+ if len(value) > 0 {
+ return cb(key, value)
+ }
+ return true
+ })
+ return nil
+}
+
+func (s *StateDB) setStateObject(object *stateObject) {
+ s.stateObjects[object.Address()] = object
+}
+
+/*
+ * SETTERS
+ */
+
+// AddPrecompileFn adds a precompileCall journal entry
+// with a snapshot of the multi-store and events previous
+// to the precompile call.
+func (s *StateDB) AddPrecompileFn(addr common.Address, cms sdk.CacheMultiStore, events sdk.Events) error {
+ stateObject := s.getOrNewStateObject(addr)
+ if stateObject == nil {
+ return fmt.Errorf("could not add precompile call to address %s. State object not found", addr)
+ }
+ stateObject.AddPrecompileFn(cms, events)
+ s.precompileCallsCounter++
+ if s.precompileCallsCounter > types.MaxPrecompileCalls {
+ return fmt.Errorf("max calls to precompiles (%d) reached", types.MaxPrecompileCalls)
+ }
+ return nil
+}
+
+// AddBalance adds amount to the account associated with addr.
+func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
+ stateObject := s.getOrNewStateObject(addr)
+ if stateObject != nil {
+ stateObject.AddBalance(amount)
+ }
+}
+
+// SubBalance subtracts amount from the account associated with addr.
+func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
+ stateObject := s.getOrNewStateObject(addr)
+ if stateObject != nil {
+ stateObject.SubBalance(amount)
+ }
+}
+
+// SetNonce sets the nonce of account.
+func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
+ stateObject := s.getOrNewStateObject(addr)
+ if stateObject != nil {
+ stateObject.SetNonce(nonce)
+ }
+}
+
+// SetCode sets the code of account.
+func (s *StateDB) SetCode(addr common.Address, code []byte) {
+ stateObject := s.getOrNewStateObject(addr)
+ if stateObject != nil {
+ stateObject.SetCode(crypto.Keccak256Hash(code), code)
+ }
+}
+
+// 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)
+ }
+}
+
+// Suicide marks the given account as suicided.
+// This clears the account balance.
+//
+// The account's state object is still available until the state is committed,
+// getStateObject will return a non-nil account after Suicide.
+func (s *StateDB) Suicide(addr common.Address) bool {
+ stateObject := s.getStateObject(addr)
+ if stateObject == nil {
+ return false
+ }
+ s.journal.append(suicideChange{
+ account: &addr,
+ prev: stateObject.suicided,
+ prevbalance: new(big.Int).Set(stateObject.Balance()),
+ })
+ stateObject.markSuicided()
+ stateObject.account.Balance = new(big.Int)
+
+ return true
+}
+
+// PrepareAccessList handles the preparatory steps for executing a state transition with
+// regards to both EIP-2929 and EIP-2930:
+//
+// - Add sender to access list (2929)
+// - Add destination to access list (2929)
+// - Add precompiles to access list (2929)
+// - Add the contents of the optional tx access list (2930)
+//
+// This method should only be called if Yolov3/Berlin/2929+2930 is applicable at the current number.
+func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list ethtypes.AccessList) {
+ s.AddAddressToAccessList(sender)
+ if dst != nil {
+ s.AddAddressToAccessList(*dst)
+ // If it's a create-tx, the destination will be added inside evm.create
+ }
+ for _, addr := range precompiles {
+ s.AddAddressToAccessList(addr)
+ }
+ for _, el := range list {
+ s.AddAddressToAccessList(el.Address)
+ for _, key := range el.StorageKeys {
+ s.AddSlotToAccessList(el.Address, key)
+ }
+ }
+}
+
+// AddAddressToAccessList adds the given address to the access list
+func (s *StateDB) AddAddressToAccessList(addr common.Address) {
+ if s.accessList.AddAddress(addr) {
+ s.journal.append(accessListAddAccountChange{&addr})
+ }
+}
+
+// AddSlotToAccessList adds the given (address, slot)-tuple to the access list
+func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
+ addrMod, slotMod := s.accessList.AddSlot(addr, slot)
+ if addrMod {
+ // In practice, this should not happen, since there is no way to enter the
+ // scope of 'address' without having the 'address' become already added
+ // to the access list (via call-variant, create, etc).
+ // Better safe than sorry, though
+ s.journal.append(accessListAddAccountChange{&addr})
+ }
+ if slotMod {
+ s.journal.append(accessListAddSlotChange{
+ address: &addr,
+ slot: &slot,
+ })
+ }
+}
+
+// AddressInAccessList returns true if the given address is in the access list.
+func (s *StateDB) AddressInAccessList(addr common.Address) bool {
+ return s.accessList.ContainsAddress(addr)
+}
+
+// SlotInAccessList returns true if the given (address, slot)-tuple is in the access list.
+func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) {
+ return s.accessList.Contains(addr, slot)
+}
+
+// Snapshot returns an identifier for the current revision of the state.
+func (s *StateDB) Snapshot() int {
+ id := s.nextRevisionID
+ s.nextRevisionID++
+ s.validRevisions = append(s.validRevisions, revision{id, s.journal.length()})
+ return id
+}
+
+// RevertToSnapshot reverts all state changes made since the given revision.
+func (s *StateDB) RevertToSnapshot(revid int) {
+ // Find the snapshot in the stack of valid snapshots.
+ idx := sort.Search(len(s.validRevisions), func(i int) bool {
+ return s.validRevisions[i].id >= revid
+ })
+ if idx == len(s.validRevisions) || s.validRevisions[idx].id != revid {
+ panic(fmt.Errorf("revision id %v cannot be reverted", revid))
+ }
+ snapshot := s.validRevisions[idx].journalIndex
+
+ // Replay the journal to undo changes and remove invalidated snapshots
+ s.journal.Revert(s, snapshot)
+ s.validRevisions = s.validRevisions[:idx]
+}
+
+// Commit writes the dirty states to keeper
+// the StateDB object should be discarded after committed.
+func (s *StateDB) Commit() error {
+ // writeCache func will exist only when there's a call to a precompile.
+ // It applies all the store updates preformed by precompile calls.
+ if s.writeCache != nil {
+ s.writeCache()
+ }
+ return s.commitWithCtx(s.ctx)
+}
+
+// CommitWithCacheCtx writes the dirty states to keeper using the cacheCtx.
+// This function is used before any precompile call to make sure the cacheCtx
+// is updated with the latest changes within the tx (StateDB's journal entries).
+func (s *StateDB) CommitWithCacheCtx() error {
+ return s.commitWithCtx(s.cacheCtx)
+}
+
+// commitWithCtx writes the dirty states to keeper
+// using the provided context
+func (s *StateDB) commitWithCtx(ctx sdk.Context) error {
+ for _, addr := range s.journal.sortedDirties() {
+ obj := s.stateObjects[addr]
+ if obj.suicided {
+ if err := s.keeper.DeleteAccount(ctx, obj.Address()); err != nil {
+ return errorsmod.Wrapf(err, "failed to delete account %s", obj.Address())
+ }
+ } else {
+ if obj.code != nil && obj.dirtyCode {
+ if len(obj.code) == 0 {
+ s.keeper.DeleteCode(ctx, obj.CodeHash())
+ } else {
+ s.keeper.SetCode(ctx, obj.CodeHash(), obj.code)
+ }
+ }
+ if err := s.keeper.SetAccount(ctx, obj.Address(), obj.account); err != nil {
+ return errorsmod.Wrap(err, "failed to set account")
+ }
+
+ for _, key := range obj.dirtyStorage.SortedKeys() {
+ valueBytes := obj.dirtyStorage[key].Bytes()
+ if len(valueBytes) == 0 {
+ s.keeper.DeleteState(ctx, obj.Address(), key)
+ } else {
+ s.keeper.SetState(ctx, obj.Address(), key, valueBytes)
+ }
+ }
+ }
+ }
+ return nil
+}
diff --git a/x/evm/statedb/statedb_test.go b/x/evm/statedb/statedb_test.go
new file mode 100644
index 00000000..2ad01b55
--- /dev/null
+++ b/x/evm/statedb/statedb_test.go
@@ -0,0 +1,587 @@
+package statedb_test
+
+import (
+ "math/big"
+ "testing"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+ "github.com/evmos/evmos/v19/x/evm/statedb"
+ "github.com/stretchr/testify/suite"
+)
+
+var (
+ address common.Address = common.BigToAddress(big.NewInt(101))
+ address2 common.Address = common.BigToAddress(big.NewInt(102))
+ address3 common.Address = common.BigToAddress(big.NewInt(103))
+ blockHash common.Hash = common.BigToHash(big.NewInt(9999))
+ emptyTxConfig statedb.TxConfig = statedb.NewEmptyTxConfig(blockHash)
+)
+
+type StateDBTestSuite struct {
+ suite.Suite
+}
+
+func (suite *StateDBTestSuite) TestAccount() {
+ key1 := common.BigToHash(big.NewInt(1))
+ value1 := common.BigToHash(big.NewInt(2))
+ key2 := common.BigToHash(big.NewInt(3))
+ value2 := common.BigToHash(big.NewInt(4))
+ testCases := []struct {
+ name string
+ malleate func(*statedb.StateDB)
+ }{
+ {"non-exist account", func(db *statedb.StateDB) {
+ suite.Require().Equal(false, db.Exist(address))
+ suite.Require().Equal(true, db.Empty(address))
+ suite.Require().Equal(big.NewInt(0), db.GetBalance(address))
+ suite.Require().Equal([]byte(nil), db.GetCode(address))
+ suite.Require().Equal(common.Hash{}, db.GetCodeHash(address))
+ suite.Require().Equal(uint64(0), db.GetNonce(address))
+ }},
+ {"empty account", func(db *statedb.StateDB) {
+ db.CreateAccount(address)
+ suite.Require().NoError(db.Commit())
+
+ keeper := db.Keeper().(*MockKeeper)
+ acct := keeper.accounts[address]
+ suite.Require().Equal(statedb.NewEmptyAccount(), &acct.account)
+ suite.Require().Empty(acct.states)
+ suite.Require().False(acct.account.IsContract())
+
+ db = statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ suite.Require().Equal(true, db.Exist(address))
+ suite.Require().Equal(true, db.Empty(address))
+ suite.Require().Equal(big.NewInt(0), db.GetBalance(address))
+ suite.Require().Equal([]byte(nil), db.GetCode(address))
+ suite.Require().Equal(common.BytesToHash(emptyCodeHash), db.GetCodeHash(address))
+ suite.Require().Equal(uint64(0), db.GetNonce(address))
+ }},
+ {"suicide", func(db *statedb.StateDB) {
+ // non-exist account.
+ suite.Require().False(db.Suicide(address))
+ suite.Require().False(db.HasSuicided(address))
+
+ // create a contract account
+ db.CreateAccount(address)
+ db.SetCode(address, []byte("hello world"))
+ db.AddBalance(address, big.NewInt(100))
+ db.SetState(address, key1, value1)
+ db.SetState(address, key2, value2)
+ suite.Require().NoError(db.Commit())
+
+ // suicide
+ db = statedb.New(sdk.Context{}, db.Keeper(), emptyTxConfig)
+ suite.Require().False(db.HasSuicided(address))
+ suite.Require().True(db.Suicide(address))
+
+ // check dirty state
+ suite.Require().True(db.HasSuicided(address))
+ // balance is cleared
+ suite.Require().Equal(big.NewInt(0), db.GetBalance(address))
+ // but code and state are still accessible in dirty state
+ suite.Require().Equal(value1, db.GetState(address, key1))
+ suite.Require().Equal([]byte("hello world"), db.GetCode(address))
+
+ suite.Require().NoError(db.Commit())
+
+ // not accessible from StateDB anymore
+ db = statedb.New(sdk.Context{}, db.Keeper(), emptyTxConfig)
+ suite.Require().False(db.Exist(address))
+
+ // and cleared in keeper too
+ keeper := db.Keeper().(*MockKeeper)
+ suite.Require().Empty(keeper.accounts)
+ suite.Require().Empty(keeper.codes)
+ }},
+ }
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ keeper := NewMockKeeper()
+ db := statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ tc.malleate(db)
+ })
+ }
+}
+
+func (suite *StateDBTestSuite) TestAccountOverride() {
+ keeper := NewMockKeeper()
+ db := statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ // test balance carry over when overwritten
+ amount := big.NewInt(1)
+
+ // init an EOA account, account overridden only happens on EOA account.
+ db.AddBalance(address, amount)
+ db.SetNonce(address, 1)
+
+ // override
+ db.CreateAccount(address)
+
+ // check balance is not lost
+ suite.Require().Equal(amount, db.GetBalance(address))
+ // but nonce is reset
+ suite.Require().Equal(uint64(0), db.GetNonce(address))
+}
+
+func (suite *StateDBTestSuite) TestDBError() {
+ testCases := []struct {
+ name string
+ malleate func(vm.StateDB)
+ }{
+ {"set account", func(db vm.StateDB) {
+ db.SetNonce(errAddress, 1)
+ }},
+ {"delete account", func(db vm.StateDB) {
+ db.SetNonce(errAddress, 1)
+ suite.Require().True(db.Suicide(errAddress))
+ }},
+ }
+ for _, tc := range testCases {
+ db := statedb.New(sdk.Context{}, NewMockKeeper(), emptyTxConfig)
+ tc.malleate(db)
+ suite.Require().Error(db.Commit())
+ }
+}
+
+func (suite *StateDBTestSuite) TestBalance() {
+ // NOTE: no need to test overflow/underflow, that is guaranteed by evm implementation.
+ testCases := []struct {
+ name string
+ malleate func(*statedb.StateDB)
+ expBalance *big.Int
+ }{
+ {"add balance", func(db *statedb.StateDB) {
+ db.AddBalance(address, big.NewInt(10))
+ }, big.NewInt(10)},
+ {"sub balance", func(db *statedb.StateDB) {
+ db.AddBalance(address, big.NewInt(10))
+ // get dirty balance
+ suite.Require().Equal(big.NewInt(10), db.GetBalance(address))
+ db.SubBalance(address, big.NewInt(2))
+ }, big.NewInt(8)},
+ {"add zero balance", func(db *statedb.StateDB) {
+ db.AddBalance(address, big.NewInt(0))
+ }, big.NewInt(0)},
+ {"sub zero balance", func(db *statedb.StateDB) {
+ db.SubBalance(address, big.NewInt(0))
+ }, big.NewInt(0)},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ keeper := NewMockKeeper()
+ db := statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ tc.malleate(db)
+
+ // check dirty state
+ suite.Require().Equal(tc.expBalance, db.GetBalance(address))
+ suite.Require().NoError(db.Commit())
+ // check committed balance too
+ suite.Require().Equal(tc.expBalance, keeper.accounts[address].account.Balance)
+ })
+ }
+}
+
+func (suite *StateDBTestSuite) TestState() {
+ key1 := common.BigToHash(big.NewInt(1))
+ value1 := common.BigToHash(big.NewInt(1))
+ testCases := []struct {
+ name string
+ malleate func(*statedb.StateDB)
+ expStates statedb.Storage
+ }{
+ {"empty state", func(_ *statedb.StateDB) {
+ }, nil},
+ {"set empty value", func(db *statedb.StateDB) {
+ db.SetState(address, key1, common.Hash{})
+ }, statedb.Storage{}},
+ {"set state even if same as original value (due to possible reverts within precompile calls)", func(db *statedb.StateDB) {
+ db.SetState(address, key1, value1)
+ db.SetState(address, key1, common.Hash{})
+ }, statedb.Storage{
+ key1: common.Hash{},
+ }},
+ {"set state", func(db *statedb.StateDB) {
+ // check empty initial state
+ suite.Require().Equal(common.Hash{}, db.GetState(address, key1))
+ suite.Require().Equal(common.Hash{}, db.GetCommittedState(address, key1))
+
+ // set state
+ db.SetState(address, key1, value1)
+ // query dirty state
+ suite.Require().Equal(value1, db.GetState(address, key1))
+ // check committed state is still not exist
+ suite.Require().Equal(common.Hash{}, db.GetCommittedState(address, key1))
+
+ // set same value again, should be noop
+ db.SetState(address, key1, value1)
+ suite.Require().Equal(value1, db.GetState(address, key1))
+ }, statedb.Storage{
+ key1: value1,
+ }},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ keeper := NewMockKeeper()
+ db := statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ tc.malleate(db)
+ suite.Require().NoError(db.Commit())
+
+ // check committed states in keeper
+ suite.Require().Equal(tc.expStates, keeper.accounts[address].states)
+
+ // check ForEachStorage
+ db = statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ collected := CollectContractStorage(db)
+ if len(tc.expStates) > 0 {
+ suite.Require().Equal(tc.expStates, collected)
+ } else {
+ suite.Require().Empty(collected)
+ }
+ })
+ }
+}
+
+func (suite *StateDBTestSuite) TestCode() {
+ code := []byte("hello world")
+ codeHash := crypto.Keccak256Hash(code)
+
+ testCases := []struct {
+ name string
+ malleate func(vm.StateDB)
+ expCode []byte
+ expCodeHash common.Hash
+ }{
+ {"non-exist account", func(vm.StateDB) {}, nil, common.Hash{}},
+ {"empty account", func(db vm.StateDB) {
+ db.CreateAccount(address)
+ }, nil, common.BytesToHash(emptyCodeHash)},
+ {"set code", func(db vm.StateDB) {
+ db.SetCode(address, code)
+ }, code, codeHash},
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ keeper := NewMockKeeper()
+ db := statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ tc.malleate(db)
+
+ // check dirty state
+ suite.Require().Equal(tc.expCode, db.GetCode(address))
+ suite.Require().Equal(len(tc.expCode), db.GetCodeSize(address))
+ suite.Require().Equal(tc.expCodeHash, db.GetCodeHash(address))
+
+ suite.Require().NoError(db.Commit())
+
+ // check again
+ db = statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ suite.Require().Equal(tc.expCode, db.GetCode(address))
+ suite.Require().Equal(len(tc.expCode), db.GetCodeSize(address))
+ suite.Require().Equal(tc.expCodeHash, db.GetCodeHash(address))
+ })
+ }
+}
+
+func (suite *StateDBTestSuite) TestRevertSnapshot() {
+ v1 := common.BigToHash(big.NewInt(1))
+ v2 := common.BigToHash(big.NewInt(2))
+ v3 := common.BigToHash(big.NewInt(3))
+ testCases := []struct {
+ name string
+ malleate func(vm.StateDB)
+ }{
+ {"set state", func(db vm.StateDB) {
+ db.SetState(address, v1, v3)
+ }},
+ {"set nonce", func(db vm.StateDB) {
+ db.SetNonce(address, 10)
+ }},
+ {"change balance", func(db vm.StateDB) {
+ db.AddBalance(address, big.NewInt(10))
+ db.SubBalance(address, big.NewInt(5))
+ }},
+ {"override account", func(db vm.StateDB) {
+ db.CreateAccount(address)
+ }},
+ {"set code", func(db vm.StateDB) {
+ db.SetCode(address, []byte("hello world"))
+ }},
+ {"suicide", func(db vm.StateDB) {
+ db.SetState(address, v1, v2)
+ db.SetCode(address, []byte("hello world"))
+ suite.Require().True(db.Suicide(address))
+ }},
+ {"add log", func(db vm.StateDB) {
+ db.AddLog(ðtypes.Log{
+ Address: address,
+ })
+ }},
+ {"add refund", func(db vm.StateDB) {
+ db.AddRefund(10)
+ db.SubRefund(5)
+ }},
+ {"access list", func(db vm.StateDB) {
+ db.AddAddressToAccessList(address)
+ db.AddSlotToAccessList(address, v1)
+ }},
+ }
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ ctx := sdk.Context{}
+ keeper := NewMockKeeper()
+
+ {
+ // do some arbitrary changes to the storage
+ db := statedb.New(ctx, keeper, emptyTxConfig)
+ db.SetNonce(address, 1)
+ db.AddBalance(address, big.NewInt(100))
+ db.SetCode(address, []byte("hello world"))
+ db.SetState(address, v1, v2)
+ db.SetNonce(address2, 1)
+ suite.Require().NoError(db.Commit())
+ }
+
+ originalKeeper := keeper.Clone()
+
+ // run test
+ db := statedb.New(ctx, keeper, emptyTxConfig)
+ rev := db.Snapshot()
+ tc.malleate(db)
+ db.RevertToSnapshot(rev)
+
+ // check empty states after revert
+ suite.Require().Zero(db.GetRefund())
+ suite.Require().Empty(db.Logs())
+
+ suite.Require().NoError(db.Commit())
+
+ // check keeper should stay the same
+ suite.Require().Equal(originalKeeper, keeper)
+ })
+ }
+}
+
+func (suite *StateDBTestSuite) TestNestedSnapshot() {
+ key := common.BigToHash(big.NewInt(1))
+ value1 := common.BigToHash(big.NewInt(1))
+ value2 := common.BigToHash(big.NewInt(2))
+
+ db := statedb.New(sdk.Context{}, NewMockKeeper(), emptyTxConfig)
+
+ rev1 := db.Snapshot()
+ db.SetState(address, key, value1)
+
+ rev2 := db.Snapshot()
+ db.SetState(address, key, value2)
+ suite.Require().Equal(value2, db.GetState(address, key))
+
+ db.RevertToSnapshot(rev2)
+ suite.Require().Equal(value1, db.GetState(address, key))
+
+ db.RevertToSnapshot(rev1)
+ suite.Require().Equal(common.Hash{}, db.GetState(address, key))
+}
+
+func (suite *StateDBTestSuite) TestInvalidSnapshotId() {
+ db := statedb.New(sdk.Context{}, NewMockKeeper(), emptyTxConfig)
+ suite.Require().Panics(func() {
+ db.RevertToSnapshot(1)
+ })
+}
+
+func (suite *StateDBTestSuite) TestAccessList() {
+ value1 := common.BigToHash(big.NewInt(1))
+ value2 := common.BigToHash(big.NewInt(2))
+
+ testCases := []struct {
+ name string
+ malleate func(vm.StateDB)
+ }{
+ {"add address", func(db vm.StateDB) {
+ suite.Require().False(db.AddressInAccessList(address))
+ db.AddAddressToAccessList(address)
+ suite.Require().True(db.AddressInAccessList(address))
+
+ addrPresent, slotPresent := db.SlotInAccessList(address, value1)
+ suite.Require().True(addrPresent)
+ suite.Require().False(slotPresent)
+
+ // add again, should be no-op
+ db.AddAddressToAccessList(address)
+ suite.Require().True(db.AddressInAccessList(address))
+ }},
+ {"add slot", func(db vm.StateDB) {
+ addrPresent, slotPresent := db.SlotInAccessList(address, value1)
+ suite.Require().False(addrPresent)
+ suite.Require().False(slotPresent)
+ db.AddSlotToAccessList(address, value1)
+ addrPresent, slotPresent = db.SlotInAccessList(address, value1)
+ suite.Require().True(addrPresent)
+ suite.Require().True(slotPresent)
+
+ // add another slot
+ db.AddSlotToAccessList(address, value2)
+ addrPresent, slotPresent = db.SlotInAccessList(address, value2)
+ suite.Require().True(addrPresent)
+ suite.Require().True(slotPresent)
+
+ // add again, should be noop
+ db.AddSlotToAccessList(address, value2)
+ addrPresent, slotPresent = db.SlotInAccessList(address, value2)
+ suite.Require().True(addrPresent)
+ suite.Require().True(slotPresent)
+ }},
+ {"prepare access list", func(db vm.StateDB) {
+ al := ethtypes.AccessList{{
+ Address: address3,
+ StorageKeys: []common.Hash{value1},
+ }}
+
+ db.PrepareAccessList(address, &address2, vm.PrecompiledAddressesBerlin, al)
+
+ // check sender and dst
+ suite.Require().True(db.AddressInAccessList(address))
+ suite.Require().True(db.AddressInAccessList(address2))
+ // check precompiles
+ suite.Require().True(db.AddressInAccessList(common.BytesToAddress([]byte{1})))
+ // check AccessList
+ suite.Require().True(db.AddressInAccessList(address3))
+ addrPresent, slotPresent := db.SlotInAccessList(address3, value1)
+ suite.Require().True(addrPresent)
+ suite.Require().True(slotPresent)
+ addrPresent, slotPresent = db.SlotInAccessList(address3, value2)
+ suite.Require().True(addrPresent)
+ suite.Require().False(slotPresent)
+ }},
+ }
+
+ for _, tc := range testCases {
+ db := statedb.New(sdk.Context{}, NewMockKeeper(), emptyTxConfig)
+ tc.malleate(db)
+ }
+}
+
+func (suite *StateDBTestSuite) TestLog() {
+ txHash := common.BytesToHash([]byte("tx"))
+ // use a non-default tx config
+ txConfig := statedb.NewTxConfig(
+ blockHash,
+ txHash,
+ 1, 1,
+ )
+ db := statedb.New(sdk.Context{}, NewMockKeeper(), txConfig)
+ data := []byte("hello world")
+ db.AddLog(ðtypes.Log{
+ Address: address,
+ Topics: []common.Hash{},
+ Data: data,
+ BlockNumber: 1,
+ })
+ suite.Require().Equal(1, len(db.Logs()))
+ expecedLog := ðtypes.Log{
+ Address: address,
+ Topics: []common.Hash{},
+ Data: data,
+ BlockNumber: 1,
+ BlockHash: blockHash,
+ TxHash: txHash,
+ TxIndex: 1,
+ Index: 1,
+ }
+ suite.Require().Equal(expecedLog, db.Logs()[0])
+
+ db.AddLog(ðtypes.Log{
+ Address: address,
+ Topics: []common.Hash{},
+ Data: data,
+ BlockNumber: 1,
+ })
+ suite.Require().Equal(2, len(db.Logs()))
+ expecedLog.Index++
+ suite.Require().Equal(expecedLog, db.Logs()[1])
+}
+
+func (suite *StateDBTestSuite) TestRefund() {
+ testCases := []struct {
+ name string
+ malleate func(vm.StateDB)
+ expRefund uint64
+ expPanic bool
+ }{
+ {"add refund", func(db vm.StateDB) {
+ db.AddRefund(uint64(10))
+ }, 10, false},
+ {"sub refund", func(db vm.StateDB) {
+ db.AddRefund(uint64(10))
+ db.SubRefund(uint64(5))
+ }, 5, false},
+ {"negative refund counter", func(db vm.StateDB) {
+ db.AddRefund(uint64(5))
+ db.SubRefund(uint64(10))
+ }, 0, true},
+ }
+ for _, tc := range testCases {
+ db := statedb.New(sdk.Context{}, NewMockKeeper(), emptyTxConfig)
+ if !tc.expPanic {
+ tc.malleate(db)
+ suite.Require().Equal(tc.expRefund, db.GetRefund())
+ } else {
+ suite.Require().Panics(func() {
+ tc.malleate(db)
+ })
+ }
+ }
+}
+
+func (suite *StateDBTestSuite) TestIterateStorage() {
+ key1 := common.BigToHash(big.NewInt(1))
+ value1 := common.BigToHash(big.NewInt(2))
+ key2 := common.BigToHash(big.NewInt(3))
+ value2 := common.BigToHash(big.NewInt(4))
+
+ keeper := NewMockKeeper()
+ db := statedb.New(sdk.Context{}, keeper, emptyTxConfig)
+ db.SetState(address, key1, value1)
+ db.SetState(address, key2, value2)
+
+ // ForEachStorage only iterate committed state
+ suite.Require().Empty(CollectContractStorage(db))
+
+ suite.Require().NoError(db.Commit())
+
+ storage := CollectContractStorage(db)
+ suite.Require().Equal(2, len(storage))
+ suite.Require().Equal(keeper.accounts[address].states, storage)
+
+ // break early iteration
+ storage = make(statedb.Storage)
+ err := db.ForEachStorage(address, func(k, v common.Hash) bool {
+ storage[k] = v
+ // return false to break early
+ return false
+ })
+ suite.Require().NoError(err)
+ suite.Require().Equal(1, len(storage))
+}
+
+func CollectContractStorage(db vm.StateDB) statedb.Storage {
+ storage := make(statedb.Storage)
+ err := db.ForEachStorage(address, func(k, v common.Hash) bool {
+ storage[k] = v
+ return true
+ })
+ if err != nil {
+ return nil
+ }
+
+ return storage
+}
+
+func TestStateDBTestSuite(t *testing.T) {
+ suite.Run(t, &StateDBTestSuite{})
+}
diff --git a/x/evm/types/access_list.go b/x/evm/types/access_list.go
new file mode 100644
index 00000000..50de8b2a
--- /dev/null
+++ b/x/evm/types/access_list.go
@@ -0,0 +1,57 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+)
+
+// AccessList is an EIP-2930 access list that represents the slice of
+// the protobuf AccessTuples.
+type AccessList []AccessTuple
+
+// NewAccessList creates a new protobuf-compatible AccessList from an ethereum
+// core AccessList type
+func NewAccessList(ethAccessList *ethtypes.AccessList) AccessList {
+ if ethAccessList == nil {
+ return nil
+ }
+
+ al := AccessList{}
+ for _, tuple := range *ethAccessList {
+ storageKeys := make([]string, len(tuple.StorageKeys))
+
+ for i := range tuple.StorageKeys {
+ storageKeys[i] = tuple.StorageKeys[i].String()
+ }
+
+ al = append(al, AccessTuple{
+ Address: tuple.Address.String(),
+ StorageKeys: storageKeys,
+ })
+ }
+
+ return al
+}
+
+// ToEthAccessList is an utility function to convert the protobuf compatible
+// AccessList to eth core AccessList from go-ethereum
+func (al AccessList) ToEthAccessList() *ethtypes.AccessList {
+ var ethAccessList ethtypes.AccessList
+
+ for _, tuple := range al {
+ storageKeys := make([]common.Hash, len(tuple.StorageKeys))
+
+ for i := range tuple.StorageKeys {
+ storageKeys[i] = common.HexToHash(tuple.StorageKeys[i])
+ }
+
+ ethAccessList = append(ethAccessList, ethtypes.AccessTuple{
+ Address: common.HexToAddress(tuple.Address),
+ StorageKeys: storageKeys,
+ })
+ }
+
+ return ðAccessList
+}
diff --git a/x/evm/types/access_list_test.go b/x/evm/types/access_list_test.go
new file mode 100644
index 00000000..b4b57d3a
--- /dev/null
+++ b/x/evm/types/access_list_test.go
@@ -0,0 +1,39 @@
+package types_test
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *TxDataTestSuite) TestTestNewAccessList() {
+ testCases := []struct {
+ name string
+ ethAccessList *ethtypes.AccessList
+ expAl types.AccessList
+ }{
+ {
+ "ethAccessList is nil",
+ nil,
+ nil,
+ },
+ {
+ "non-empty ethAccessList",
+ ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ types.AccessList{{Address: suite.hexAddr, StorageKeys: []string{common.Hash{}.Hex()}}},
+ },
+ }
+ for _, tc := range testCases {
+ al := types.NewAccessList(tc.ethAccessList)
+
+ suite.Require().Equal(tc.expAl, al)
+ }
+}
+
+func (suite *TxDataTestSuite) TestAccessListToEthAccessList() {
+ ethAccessList := ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}}
+ al := types.NewAccessList(ðAccessList)
+ actual := al.ToEthAccessList()
+
+ suite.Require().Equal(ðAccessList, actual)
+}
diff --git a/x/evm/types/access_list_tx.go b/x/evm/types/access_list_tx.go
new file mode 100644
index 00000000..0cd291f5
--- /dev/null
+++ b/x/evm/types/access_list_tx.go
@@ -0,0 +1,251 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ sdkmath "cosmossdk.io/math"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ "github.com/evmos/evmos/v19/types"
+)
+
+func newAccessListTx(tx *ethtypes.Transaction) (*AccessListTx, error) {
+ txData := &AccessListTx{
+ Nonce: tx.Nonce(),
+ Data: tx.Data(),
+ GasLimit: tx.Gas(),
+ }
+
+ v, r, s := tx.RawSignatureValues()
+ if to := tx.To(); to != nil {
+ txData.To = to.Hex()
+ }
+
+ if tx.Value() != nil {
+ amountInt, err := types.SafeNewIntFromBigInt(tx.Value())
+ if err != nil {
+ return nil, err
+ }
+ txData.Amount = &amountInt
+ }
+
+ if tx.GasPrice() != nil {
+ gasPriceInt, err := types.SafeNewIntFromBigInt(tx.GasPrice())
+ if err != nil {
+ return nil, err
+ }
+ txData.GasPrice = &gasPriceInt
+ }
+
+ if tx.AccessList() != nil {
+ al := tx.AccessList()
+ txData.Accesses = NewAccessList(&al)
+ }
+
+ txData.SetSignatureValues(tx.ChainId(), v, r, s)
+ return txData, nil
+}
+
+// TxType returns the tx type
+func (tx *AccessListTx) TxType() uint8 {
+ return ethtypes.AccessListTxType
+}
+
+// Copy returns an instance with the same field values
+func (tx *AccessListTx) Copy() TxData {
+ return &AccessListTx{
+ ChainID: tx.ChainID,
+ Nonce: tx.Nonce,
+ GasPrice: tx.GasPrice,
+ GasLimit: tx.GasLimit,
+ To: tx.To,
+ Amount: tx.Amount,
+ Data: common.CopyBytes(tx.Data),
+ Accesses: tx.Accesses,
+ V: common.CopyBytes(tx.V),
+ R: common.CopyBytes(tx.R),
+ S: common.CopyBytes(tx.S),
+ }
+}
+
+// GetChainID returns the chain id field from the AccessListTx
+func (tx *AccessListTx) GetChainID() *big.Int {
+ if tx.ChainID == nil {
+ return nil
+ }
+
+ return tx.ChainID.BigInt()
+}
+
+// GetAccessList returns the AccessList field.
+func (tx *AccessListTx) GetAccessList() ethtypes.AccessList {
+ if tx.Accesses == nil {
+ return nil
+ }
+ return *tx.Accesses.ToEthAccessList()
+}
+
+// GetData returns the a copy of the input data bytes.
+func (tx *AccessListTx) GetData() []byte {
+ return common.CopyBytes(tx.Data)
+}
+
+// GetGas returns the gas limit.
+func (tx *AccessListTx) GetGas() uint64 {
+ return tx.GasLimit
+}
+
+// GetGasPrice returns the gas price field.
+func (tx *AccessListTx) GetGasPrice() *big.Int {
+ if tx.GasPrice == nil {
+ return nil
+ }
+ return tx.GasPrice.BigInt()
+}
+
+// GetGasTipCap returns the gas price field.
+func (tx *AccessListTx) GetGasTipCap() *big.Int {
+ return tx.GetGasPrice()
+}
+
+// GetGasFeeCap returns the gas price field.
+func (tx *AccessListTx) GetGasFeeCap() *big.Int {
+ return tx.GetGasPrice()
+}
+
+// GetValue returns the tx amount.
+func (tx *AccessListTx) GetValue() *big.Int {
+ if tx.Amount == nil {
+ return nil
+ }
+
+ return tx.Amount.BigInt()
+}
+
+// GetNonce returns the account sequence for the transaction.
+func (tx *AccessListTx) GetNonce() uint64 { return tx.Nonce }
+
+// GetTo returns the pointer to the recipient address.
+func (tx *AccessListTx) GetTo() *common.Address {
+ if tx.To == "" {
+ return nil
+ }
+ to := common.HexToAddress(tx.To)
+ return &to
+}
+
+// AsEthereumData returns an AccessListTx transaction tx from the proto-formatted
+// TxData defined on the Cosmos EVM.
+func (tx *AccessListTx) AsEthereumData() ethtypes.TxData {
+ v, r, s := tx.GetRawSignatureValues()
+ return ðtypes.AccessListTx{
+ ChainID: tx.GetChainID(),
+ Nonce: tx.GetNonce(),
+ GasPrice: tx.GetGasPrice(),
+ Gas: tx.GetGas(),
+ To: tx.GetTo(),
+ Value: tx.GetValue(),
+ Data: tx.GetData(),
+ AccessList: tx.GetAccessList(),
+ V: v,
+ R: r,
+ S: s,
+ }
+}
+
+// GetRawSignatureValues returns the V, R, S signature values of the transaction.
+// The return values should not be modified by the caller.
+func (tx *AccessListTx) GetRawSignatureValues() (v, r, s *big.Int) {
+ return rawSignatureValues(tx.V, tx.R, tx.S)
+}
+
+// SetSignatureValues sets the signature values to the transaction.
+func (tx *AccessListTx) SetSignatureValues(chainID, v, r, s *big.Int) {
+ if v != nil {
+ tx.V = v.Bytes()
+ }
+ if r != nil {
+ tx.R = r.Bytes()
+ }
+ if s != nil {
+ tx.S = s.Bytes()
+ }
+ if chainID != nil {
+ chainIDInt := sdkmath.NewIntFromBigInt(chainID)
+ tx.ChainID = &chainIDInt
+ }
+}
+
+// Validate performs a stateless validation of the tx fields.
+func (tx AccessListTx) Validate() error {
+ gasPrice := tx.GetGasPrice()
+ if gasPrice == nil {
+ return errorsmod.Wrap(ErrInvalidGasPrice, "cannot be nil")
+ }
+ if !types.IsValidInt256(gasPrice) {
+ return errorsmod.Wrap(ErrInvalidGasPrice, "out of bound")
+ }
+
+ if gasPrice.Sign() == -1 {
+ return errorsmod.Wrapf(ErrInvalidGasPrice, "gas price cannot be negative %s", gasPrice)
+ }
+
+ amount := tx.GetValue()
+ // Amount can be 0
+ if amount != nil && amount.Sign() == -1 {
+ return errorsmod.Wrapf(ErrInvalidAmount, "amount cannot be negative %s", amount)
+ }
+ if !types.IsValidInt256(amount) {
+ return errorsmod.Wrap(ErrInvalidAmount, "out of bound")
+ }
+
+ if !types.IsValidInt256(tx.Fee()) {
+ return errorsmod.Wrap(ErrInvalidGasFee, "out of bound")
+ }
+
+ if tx.To != "" {
+ if err := types.ValidateAddress(tx.To); err != nil {
+ return errorsmod.Wrap(err, "invalid to address")
+ }
+ }
+
+ if tx.GetChainID() == nil {
+ return errorsmod.Wrap(
+ errortypes.ErrInvalidChainID,
+ "chain ID must be present on AccessList txs",
+ )
+ }
+
+ return nil
+}
+
+// Fee returns gasprice * gaslimit.
+func (tx AccessListTx) Fee() *big.Int {
+ return fee(tx.GetGasPrice(), tx.GetGas())
+}
+
+// Cost returns amount + gasprice * gaslimit.
+func (tx AccessListTx) Cost() *big.Int {
+ return cost(tx.Fee(), tx.GetValue())
+}
+
+// EffectiveGasPrice is the same as GasPrice for AccessListTx
+func (tx AccessListTx) EffectiveGasPrice(_ *big.Int) *big.Int {
+ return tx.GetGasPrice()
+}
+
+// EffectiveFee is the same as Fee for AccessListTx
+func (tx AccessListTx) EffectiveFee(_ *big.Int) *big.Int {
+ return tx.Fee()
+}
+
+// EffectiveCost is the same as Cost for AccessListTx
+func (tx AccessListTx) EffectiveCost(_ *big.Int) *big.Int {
+ return tx.Cost()
+}
diff --git a/x/evm/types/access_list_tx_test.go b/x/evm/types/access_list_tx_test.go
new file mode 100644
index 00000000..1e6c04c4
--- /dev/null
+++ b/x/evm/types/access_list_tx_test.go
@@ -0,0 +1,168 @@
+package types_test
+
+import (
+ "math/big"
+
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *TxDataTestSuite) TestAccessListTxCopy() {
+ tx := &types.AccessListTx{}
+ txCopy := tx.Copy()
+
+ suite.Require().Equal(&types.AccessListTx{}, txCopy)
+}
+
+func (suite *TxDataTestSuite) TestAccessListTxGetGasTipCap() {
+ testCases := []struct {
+ name string
+ tx types.AccessListTx
+ exp *big.Int
+ }{
+ {
+ "non-empty gasPrice",
+ types.AccessListTx{
+ GasPrice: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasTipCap()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestAccessListTxGetGasFeeCap() {
+ testCases := []struct {
+ name string
+ tx types.AccessListTx
+ exp *big.Int
+ }{
+ {
+ "non-empty gasPrice",
+ types.AccessListTx{
+ GasPrice: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasFeeCap()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestEmptyAccessList() {
+ testCases := []struct {
+ name string
+ tx types.AccessListTx
+ }{
+ {
+ "empty access list tx",
+ types.AccessListTx{
+ Accesses: nil,
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actual := tc.tx.GetAccessList()
+
+ suite.Require().Nil(actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestAccessListTxCost() {
+ testCases := []struct {
+ name string
+ tx types.AccessListTx
+ exp *big.Int
+ }{
+ {
+ "non-empty access list tx",
+ types.AccessListTx{
+ GasPrice: &suite.sdkInt,
+ GasLimit: uint64(1),
+ Amount: &suite.sdkZeroInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.Cost()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestAccessListEffectiveGasPrice() {
+ testCases := []struct {
+ name string
+ tx types.AccessListTx
+ baseFee *big.Int
+ }{
+ {
+ "non-empty access list tx",
+ types.AccessListTx{
+ GasPrice: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveGasPrice(tc.baseFee)
+
+ suite.Require().Equal(tc.tx.GetGasPrice(), actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestAccessListTxEffectiveCost() {
+ testCases := []struct {
+ name string
+ tx types.AccessListTx
+ baseFee *big.Int
+ exp *big.Int
+ }{
+ {
+ "non-empty access list tx",
+ types.AccessListTx{
+ GasPrice: &suite.sdkInt,
+ GasLimit: uint64(1),
+ Amount: &suite.sdkZeroInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveCost(tc.baseFee)
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestAccessListTxType() {
+ testCases := []struct {
+ name string
+ tx types.AccessListTx
+ }{
+ {
+ "non-empty access list tx",
+ types.AccessListTx{},
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.TxType()
+
+ suite.Require().Equal(uint8(ethtypes.AccessListTxType), actual, tc.name)
+ }
+}
diff --git a/x/evm/types/call.go b/x/evm/types/call.go
new file mode 100644
index 00000000..53fa0896
--- /dev/null
+++ b/x/evm/types/call.go
@@ -0,0 +1,17 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+type CallType int
+
+const (
+ // RPC call type is used on requests to eth_estimateGas rpc API endpoint
+ RPC CallType = iota + 1
+ // Internal call type is used in case of smart contract methods calls
+ Internal
+)
+
+// MaxPrecompileCalls is the maximum number of precompile
+// calls within a transaction. We want to limit this because
+// for each precompile tx we're creating a cached context
+const MaxPrecompileCalls uint8 = 7
diff --git a/x/evm/types/chain_config.go b/x/evm/types/chain_config.go
new file mode 100644
index 00000000..1708c2c2
--- /dev/null
+++ b/x/evm/types/chain_config.go
@@ -0,0 +1,183 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math/big"
+ "strings"
+
+ sdkmath "cosmossdk.io/math"
+
+ errorsmod "cosmossdk.io/errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// EthereumConfig returns an Ethereum ChainConfig for EVM state transitions.
+// All the negative or nil values are converted to nil
+func (cc ChainConfig) EthereumConfig(chainID *big.Int) *params.ChainConfig {
+ return ¶ms.ChainConfig{
+ ChainID: chainID,
+ HomesteadBlock: getBlockValue(cc.HomesteadBlock),
+ DAOForkBlock: getBlockValue(cc.DAOForkBlock),
+ DAOForkSupport: cc.DAOForkSupport,
+ EIP150Block: getBlockValue(cc.EIP150Block),
+ EIP150Hash: common.HexToHash(cc.EIP150Hash),
+ EIP155Block: getBlockValue(cc.EIP155Block),
+ EIP158Block: getBlockValue(cc.EIP158Block),
+ ByzantiumBlock: getBlockValue(cc.ByzantiumBlock),
+ ConstantinopleBlock: getBlockValue(cc.ConstantinopleBlock),
+ PetersburgBlock: getBlockValue(cc.PetersburgBlock),
+ IstanbulBlock: getBlockValue(cc.IstanbulBlock),
+ MuirGlacierBlock: getBlockValue(cc.MuirGlacierBlock),
+ BerlinBlock: getBlockValue(cc.BerlinBlock),
+ LondonBlock: getBlockValue(cc.LondonBlock),
+ ArrowGlacierBlock: getBlockValue(cc.ArrowGlacierBlock),
+ GrayGlacierBlock: getBlockValue(cc.GrayGlacierBlock),
+ MergeNetsplitBlock: getBlockValue(cc.MergeNetsplitBlock),
+ ShanghaiBlock: getBlockValue(cc.ShanghaiBlock),
+ CancunBlock: getBlockValue(cc.CancunBlock),
+ TerminalTotalDifficulty: nil,
+ Ethash: nil,
+ Clique: nil,
+ }
+}
+
+// DefaultChainConfig returns default evm parameters.
+func DefaultChainConfig() ChainConfig {
+ homesteadBlock := sdkmath.ZeroInt()
+ daoForkBlock := sdkmath.ZeroInt()
+ eip150Block := sdkmath.ZeroInt()
+ eip155Block := sdkmath.ZeroInt()
+ eip158Block := sdkmath.ZeroInt()
+ byzantiumBlock := sdkmath.ZeroInt()
+ constantinopleBlock := sdkmath.ZeroInt()
+ petersburgBlock := sdkmath.ZeroInt()
+ istanbulBlock := sdkmath.ZeroInt()
+ muirGlacierBlock := sdkmath.ZeroInt()
+ berlinBlock := sdkmath.ZeroInt()
+ londonBlock := sdkmath.ZeroInt()
+ arrowGlacierBlock := sdkmath.ZeroInt()
+ grayGlacierBlock := sdkmath.ZeroInt()
+ mergeNetsplitBlock := sdkmath.ZeroInt()
+ shanghaiBlock := sdkmath.ZeroInt()
+ cancunBlock := sdkmath.ZeroInt()
+
+ return ChainConfig{
+ HomesteadBlock: &homesteadBlock,
+ DAOForkBlock: &daoForkBlock,
+ DAOForkSupport: true,
+ EIP150Block: &eip150Block,
+ EIP150Hash: common.Hash{}.String(),
+ EIP155Block: &eip155Block,
+ EIP158Block: &eip158Block,
+ ByzantiumBlock: &byzantiumBlock,
+ ConstantinopleBlock: &constantinopleBlock,
+ PetersburgBlock: &petersburgBlock,
+ IstanbulBlock: &istanbulBlock,
+ MuirGlacierBlock: &muirGlacierBlock,
+ BerlinBlock: &berlinBlock,
+ LondonBlock: &londonBlock,
+ ArrowGlacierBlock: &arrowGlacierBlock,
+ GrayGlacierBlock: &grayGlacierBlock,
+ MergeNetsplitBlock: &mergeNetsplitBlock,
+ ShanghaiBlock: &shanghaiBlock,
+ CancunBlock: &cancunBlock,
+ }
+}
+
+func getBlockValue(block *sdkmath.Int) *big.Int {
+ if block == nil || block.IsNegative() {
+ return nil
+ }
+
+ return block.BigInt()
+}
+
+// Validate performs a basic validation of the ChainConfig params. The function will return an error
+// if any of the block values is uninitialized (i.e nil) or if the EIP150Hash is an invalid hash.
+func (cc ChainConfig) Validate() error {
+ if err := validateBlock(cc.HomesteadBlock); err != nil {
+ return errorsmod.Wrap(err, "homesteadBlock")
+ }
+ if err := validateBlock(cc.DAOForkBlock); err != nil {
+ return errorsmod.Wrap(err, "daoForkBlock")
+ }
+ if err := validateBlock(cc.EIP150Block); err != nil {
+ return errorsmod.Wrap(err, "eip150Block")
+ }
+ if err := validateHash(cc.EIP150Hash); err != nil {
+ return err
+ }
+ if err := validateBlock(cc.EIP155Block); err != nil {
+ return errorsmod.Wrap(err, "eip155Block")
+ }
+ if err := validateBlock(cc.EIP158Block); err != nil {
+ return errorsmod.Wrap(err, "eip158Block")
+ }
+ if err := validateBlock(cc.ByzantiumBlock); err != nil {
+ return errorsmod.Wrap(err, "byzantiumBlock")
+ }
+ if err := validateBlock(cc.ConstantinopleBlock); err != nil {
+ return errorsmod.Wrap(err, "constantinopleBlock")
+ }
+ if err := validateBlock(cc.PetersburgBlock); err != nil {
+ return errorsmod.Wrap(err, "petersburgBlock")
+ }
+ if err := validateBlock(cc.IstanbulBlock); err != nil {
+ return errorsmod.Wrap(err, "istanbulBlock")
+ }
+ if err := validateBlock(cc.MuirGlacierBlock); err != nil {
+ return errorsmod.Wrap(err, "muirGlacierBlock")
+ }
+ if err := validateBlock(cc.BerlinBlock); err != nil {
+ return errorsmod.Wrap(err, "berlinBlock")
+ }
+ if err := validateBlock(cc.LondonBlock); err != nil {
+ return errorsmod.Wrap(err, "londonBlock")
+ }
+ if err := validateBlock(cc.ArrowGlacierBlock); err != nil {
+ return errorsmod.Wrap(err, "arrowGlacierBlock")
+ }
+ if err := validateBlock(cc.GrayGlacierBlock); err != nil {
+ return errorsmod.Wrap(err, "GrayGlacierBlock")
+ }
+ if err := validateBlock(cc.MergeNetsplitBlock); err != nil {
+ return errorsmod.Wrap(err, "MergeNetsplitBlock")
+ }
+ if err := validateBlock(cc.ShanghaiBlock); err != nil {
+ return errorsmod.Wrap(err, "ShanghaiBlock")
+ }
+ if err := validateBlock(cc.CancunBlock); err != nil {
+ return errorsmod.Wrap(err, "CancunBlock")
+ }
+ // NOTE: chain ID is not needed to check config order
+ if err := cc.EthereumConfig(nil).CheckConfigForkOrder(); err != nil {
+ return errorsmod.Wrap(err, "invalid config fork order")
+ }
+ return nil
+}
+
+func validateHash(hex string) error {
+ if hex != "" && strings.TrimSpace(hex) == "" {
+ return errorsmod.Wrap(ErrInvalidChainConfig, "hash cannot be blank")
+ }
+
+ return nil
+}
+
+func validateBlock(block *sdkmath.Int) error {
+ // nil value means that the fork has not yet been applied
+ if block == nil {
+ return nil
+ }
+
+ if block.IsNegative() {
+ return errorsmod.Wrapf(
+ ErrInvalidChainConfig, "block value cannot be negative: %s", block,
+ )
+ }
+
+ return nil
+}
diff --git a/x/evm/types/chain_config_test.go b/x/evm/types/chain_config_test.go
new file mode 100644
index 00000000..50457019
--- /dev/null
+++ b/x/evm/types/chain_config_test.go
@@ -0,0 +1,381 @@
+package types
+
+import (
+ "testing"
+
+ sdkmath "cosmossdk.io/math"
+ "github.com/stretchr/testify/require"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+var defaultEIP150Hash = common.Hash{}.String()
+
+func newIntPtr(i int64) *sdkmath.Int {
+ v := sdkmath.NewInt(i)
+ return &v
+}
+
+func TestChainConfigValidate(t *testing.T) {
+ testCases := []struct {
+ name string
+ config ChainConfig
+ expError bool
+ }{
+ {"default", DefaultChainConfig(), false},
+ {
+ "valid",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(0),
+ CancunBlock: newIntPtr(0),
+ ShanghaiBlock: newIntPtr(0),
+ },
+ false,
+ },
+ {
+ "valid with nil values",
+ ChainConfig{
+ HomesteadBlock: nil,
+ DAOForkBlock: nil,
+ EIP150Block: nil,
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: nil,
+ EIP158Block: nil,
+ ByzantiumBlock: nil,
+ ConstantinopleBlock: nil,
+ PetersburgBlock: nil,
+ IstanbulBlock: nil,
+ MuirGlacierBlock: nil,
+ BerlinBlock: nil,
+ LondonBlock: nil,
+ CancunBlock: nil,
+ ShanghaiBlock: nil,
+ },
+ false,
+ },
+ {
+ "empty",
+ ChainConfig{},
+ false,
+ },
+ {
+ "invalid HomesteadBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid DAOForkBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid EIP150Block",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid EIP150Hash",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: " ",
+ },
+ true,
+ },
+ {
+ "invalid EIP155Block",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid EIP158Block",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid ByzantiumBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid ConstantinopleBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid PetersburgBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid IstanbulBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid MuirGlacierBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid BerlinBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid LondonBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid ArrowGlacierBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(0),
+ ArrowGlacierBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid GrayGlacierBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(0),
+ ArrowGlacierBlock: newIntPtr(0),
+ GrayGlacierBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid MergeNetsplitBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(0),
+ ArrowGlacierBlock: newIntPtr(0),
+ GrayGlacierBlock: newIntPtr(0),
+ MergeNetsplitBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid fork order - skip HomesteadBlock",
+ ChainConfig{
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(0),
+ },
+ true,
+ },
+ {
+ "invalid ShanghaiBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(0),
+ ArrowGlacierBlock: newIntPtr(0),
+ GrayGlacierBlock: newIntPtr(0),
+ MergeNetsplitBlock: newIntPtr(0),
+ ShanghaiBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ {
+ "invalid CancunBlock",
+ ChainConfig{
+ HomesteadBlock: newIntPtr(0),
+ DAOForkBlock: newIntPtr(0),
+ EIP150Block: newIntPtr(0),
+ EIP150Hash: defaultEIP150Hash,
+ EIP155Block: newIntPtr(0),
+ EIP158Block: newIntPtr(0),
+ ByzantiumBlock: newIntPtr(0),
+ ConstantinopleBlock: newIntPtr(0),
+ PetersburgBlock: newIntPtr(0),
+ IstanbulBlock: newIntPtr(0),
+ MuirGlacierBlock: newIntPtr(0),
+ BerlinBlock: newIntPtr(0),
+ LondonBlock: newIntPtr(0),
+ ArrowGlacierBlock: newIntPtr(0),
+ GrayGlacierBlock: newIntPtr(0),
+ MergeNetsplitBlock: newIntPtr(0),
+ ShanghaiBlock: newIntPtr(0),
+ CancunBlock: newIntPtr(-1),
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ err := tc.config.Validate()
+
+ if tc.expError {
+ require.Error(t, err, tc.name)
+ } else {
+ require.NoError(t, err, tc.name)
+ }
+ }
+}
diff --git a/x/evm/types/codec.go b/x/evm/types/codec.go
new file mode 100644
index 00000000..394d24b5
--- /dev/null
+++ b/x/evm/types/codec.go
@@ -0,0 +1,94 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ errorsmod "cosmossdk.io/errors"
+ "github.com/cosmos/cosmos-sdk/codec"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/cosmos/cosmos-sdk/types/msgservice"
+ "github.com/cosmos/cosmos-sdk/types/tx"
+ proto "github.com/cosmos/gogoproto/proto"
+)
+
+var (
+ amino = codec.NewLegacyAmino()
+ // ModuleCdc references the global evm module codec. Note, the codec should
+ // ONLY be used in certain instances of tests and for JSON encoding.
+ ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
+
+ // AminoCdc is a amino codec created to support amino JSON compatible msgs.
+ AminoCdc = codec.NewAminoCodec(amino)
+)
+
+const (
+ // Amino names
+ updateParamsName = "ethermint/MsgUpdateParams"
+)
+
+// NOTE: This is required for the GetSignBytes function
+func init() {
+ RegisterLegacyAminoCodec(amino)
+ amino.Seal()
+}
+
+// RegisterInterfaces registers the client interfaces to protobuf Any.
+func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
+ registry.RegisterImplementations(
+ (*tx.TxExtensionOptionI)(nil),
+ &ExtensionOptionsEthereumTx{},
+ )
+ registry.RegisterImplementations(
+ (*sdk.Msg)(nil),
+ &MsgEthereumTx{},
+ &MsgUpdateParams{},
+ )
+ registry.RegisterInterface(
+ "ethermint.evm.v1.TxData",
+ (*TxData)(nil),
+ &DynamicFeeTx{},
+ &AccessListTx{},
+ &LegacyTx{},
+ )
+
+ msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
+}
+
+// PackTxData constructs a new Any packed with the given tx data value. It returns
+// an error if the client state can't be casted to a protobuf message or if the concrete
+// implementation is not registered to the protobuf codec.
+func PackTxData(txData TxData) (*codectypes.Any, error) {
+ msg, ok := txData.(proto.Message)
+ if !ok {
+ return nil, errorsmod.Wrapf(errortypes.ErrPackAny, "cannot proto marshal %T", txData)
+ }
+
+ anyTxData, err := codectypes.NewAnyWithValue(msg)
+ if err != nil {
+ return nil, errorsmod.Wrap(errortypes.ErrPackAny, err.Error())
+ }
+
+ return anyTxData, nil
+}
+
+// UnpackTxData unpacks an Any into a TxData. It returns an error if the
+// client state can't be unpacked into a TxData.
+func UnpackTxData(any *codectypes.Any) (TxData, error) {
+ if any == nil {
+ return nil, errorsmod.Wrap(errortypes.ErrUnpackAny, "protobuf Any message cannot be nil")
+ }
+
+ txData, ok := any.GetCachedValue().(TxData)
+ if !ok {
+ return nil, errorsmod.Wrapf(errortypes.ErrUnpackAny, "cannot unpack Any into TxData %T", any)
+ }
+
+ return txData, nil
+}
+
+// RegisterLegacyAminoCodec required for EIP-712
+func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
+ cdc.RegisterConcrete(&MsgUpdateParams{}, updateParamsName, nil)
+}
diff --git a/x/evm/types/codec_test.go b/x/evm/types/codec_test.go
new file mode 100644
index 00000000..7121f5b5
--- /dev/null
+++ b/x/evm/types/codec_test.go
@@ -0,0 +1,61 @@
+package types
+
+import (
+ "testing"
+
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ "github.com/stretchr/testify/require"
+)
+
+type caseAny struct {
+ name string
+ any *codectypes.Any
+ expPass bool
+}
+
+func TestPackTxData(t *testing.T) {
+ testCases := []struct {
+ name string
+ txData TxData
+ expPass bool
+ }{
+ {
+ "access list tx",
+ &AccessListTx{},
+ true,
+ },
+ {
+ "legacy tx",
+ &LegacyTx{},
+ true,
+ },
+ {
+ "nil",
+ nil,
+ false,
+ },
+ }
+
+ testCasesAny := []caseAny{}
+
+ for _, tc := range testCases {
+ txDataAny, err := PackTxData(tc.txData)
+ if tc.expPass {
+ require.NoError(t, err, tc.name)
+ } else {
+ require.Error(t, err, tc.name)
+ }
+
+ testCasesAny = append(testCasesAny, caseAny{tc.name, txDataAny, tc.expPass})
+ }
+
+ for i, tc := range testCasesAny {
+ cs, err := UnpackTxData(tc.any)
+ if tc.expPass {
+ require.NoError(t, err, tc.name)
+ require.Equal(t, testCases[i].txData, cs, tc.name)
+ } else {
+ require.Error(t, err, tc.name)
+ }
+ }
+}
diff --git a/x/evm/types/compiled_contract.go b/x/evm/types/compiled_contract.go
new file mode 100644
index 00000000..e36c1a74
--- /dev/null
+++ b/x/evm/types/compiled_contract.go
@@ -0,0 +1,93 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package types
+
+import (
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+)
+
+// HexString is a byte array that serializes to hex
+type HexString []byte
+
+// MarshalJSON serializes ByteArray to hex
+func (s HexString) MarshalJSON() ([]byte, error) {
+ return json.Marshal(fmt.Sprintf("%x", string(s)))
+}
+
+// UnmarshalJSON deserializes ByteArray to hex
+func (s *HexString) UnmarshalJSON(data []byte) error {
+ var x string
+ if err := json.Unmarshal(data, &x); err != nil {
+ return err
+ }
+ str, err := hex.DecodeString(x)
+ if err != nil {
+ return err
+ }
+ *s = str
+ return nil
+}
+
+// CompiledContract contains compiled bytecode and abi
+type CompiledContract struct {
+ ABI abi.ABI
+ Bin HexString
+}
+
+type jsonCompiledContract struct {
+ ABI string
+ Bin HexString
+}
+
+// MarshalJSON serializes ByteArray to hex
+func (s CompiledContract) MarshalJSON() ([]byte, error) {
+ abi1, err := json.Marshal(s.ABI)
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal(jsonCompiledContract{ABI: string(abi1), Bin: s.Bin})
+}
+
+// UnmarshalJSON deserializes ByteArray to hex
+func (s *CompiledContract) UnmarshalJSON(data []byte) error {
+ var x jsonCompiledContract
+ if err := json.Unmarshal(data, &x); err != nil {
+ return err
+ }
+
+ s.Bin = x.Bin
+ if err := json.Unmarshal([]byte(x.ABI), &s.ABI); err != nil {
+ return fmt.Errorf("failed to unmarshal ABI: %w", err)
+ }
+
+ return nil
+}
+
+// HardhatCompiledContract is a type used to unpack the compiled JSON data
+// which is generated by running `npx hardhat compile` for a given smart contract.
+type HardhatCompiledContract struct {
+ Format string `json:"_format"`
+ ContractName string `json:"contractName"`
+ SourceName string `json:"sourceName"`
+ ABI abi.ABI `json:"abi"`
+ Bytecode string `json:"bytecode"`
+}
+
+func (c HardhatCompiledContract) ToCompiledContract() (CompiledContract, error) {
+ strippedHex := strings.TrimPrefix(c.Bytecode, "0x")
+ hexBytes, err := hex.DecodeString(strippedHex)
+ if err != nil {
+ return CompiledContract{}, fmt.Errorf("failed to decode hex string: %w", err)
+ }
+
+ return CompiledContract{
+ ABI: c.ABI,
+ Bin: hexBytes,
+ }, nil
+}
diff --git a/x/evm/types/compiled_contract_test.go b/x/evm/types/compiled_contract_test.go
new file mode 100644
index 00000000..8f4a2b04
--- /dev/null
+++ b/x/evm/types/compiled_contract_test.go
@@ -0,0 +1,32 @@
+package types_test
+
+import (
+ "encoding/json"
+ "os"
+ "testing"
+
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+ "github.com/stretchr/testify/require"
+)
+
+func TestHardhatCompiledContract(t *testing.T) {
+ contents, err := os.ReadFile("testdata/SimpleContractHardhat.json")
+ require.NoError(t, err, "failed to read file")
+ require.NotEmpty(t, contents, "expected contents not to be empty")
+
+ var hardhatContract evmtypes.HardhatCompiledContract
+ err = json.Unmarshal(contents, &hardhatContract)
+ require.NoError(t, err, "failed to unmarshal contract")
+
+ require.Equal(t, hardhatContract.ContractName, "SimpleContract")
+ require.Contains(t,
+ hardhatContract.ABI.Methods,
+ "setValue",
+ "missing setValue method in contract ABI methods",
+ )
+
+ compiledContract, err := hardhatContract.ToCompiledContract()
+ require.NoError(t, err, "failed to convert hardhat contract to compiled contract type")
+ require.Equal(t, compiledContract.ABI, hardhatContract.ABI, "expected ABIs to be equal")
+ require.NotEmpty(t, compiledContract.Bin, "expected bin data not to be empty")
+}
diff --git a/x/evm/types/dynamic_fee_tx.go b/x/evm/types/dynamic_fee_tx.go
new file mode 100644
index 00000000..c98cbb95
--- /dev/null
+++ b/x/evm/types/dynamic_fee_tx.go
@@ -0,0 +1,283 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ sdkmath "cosmossdk.io/math"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ "github.com/evmos/evmos/v19/types"
+)
+
+func NewDynamicFeeTx(tx *ethtypes.Transaction) (*DynamicFeeTx, error) {
+ txData := &DynamicFeeTx{
+ Nonce: tx.Nonce(),
+ Data: tx.Data(),
+ GasLimit: tx.Gas(),
+ }
+
+ v, r, s := tx.RawSignatureValues()
+ if to := tx.To(); to != nil {
+ txData.To = to.Hex()
+ }
+
+ if tx.Value() != nil {
+ amountInt, err := types.SafeNewIntFromBigInt(tx.Value())
+ if err != nil {
+ return nil, err
+ }
+ txData.Amount = &amountInt
+ }
+
+ if tx.GasFeeCap() != nil {
+ gasFeeCapInt, err := types.SafeNewIntFromBigInt(tx.GasFeeCap())
+ if err != nil {
+ return nil, err
+ }
+ txData.GasFeeCap = &gasFeeCapInt
+ }
+
+ if tx.GasTipCap() != nil {
+ gasTipCapInt, err := types.SafeNewIntFromBigInt(tx.GasTipCap())
+ if err != nil {
+ return nil, err
+ }
+ txData.GasTipCap = &gasTipCapInt
+ }
+
+ if tx.AccessList() != nil {
+ al := tx.AccessList()
+ txData.Accesses = NewAccessList(&al)
+ }
+
+ txData.SetSignatureValues(tx.ChainId(), v, r, s)
+ return txData, nil
+}
+
+// TxType returns the tx type
+func (tx *DynamicFeeTx) TxType() uint8 {
+ return ethtypes.DynamicFeeTxType
+}
+
+// Copy returns an instance with the same field values
+func (tx *DynamicFeeTx) Copy() TxData {
+ return &DynamicFeeTx{
+ ChainID: tx.ChainID,
+ Nonce: tx.Nonce,
+ GasTipCap: tx.GasTipCap,
+ GasFeeCap: tx.GasFeeCap,
+ GasLimit: tx.GasLimit,
+ To: tx.To,
+ Amount: tx.Amount,
+ Data: common.CopyBytes(tx.Data),
+ Accesses: tx.Accesses,
+ V: common.CopyBytes(tx.V),
+ R: common.CopyBytes(tx.R),
+ S: common.CopyBytes(tx.S),
+ }
+}
+
+// GetChainID returns the chain id field from the DynamicFeeTx
+func (tx *DynamicFeeTx) GetChainID() *big.Int {
+ if tx.ChainID == nil {
+ return nil
+ }
+
+ return tx.ChainID.BigInt()
+}
+
+// GetAccessList returns the AccessList field.
+func (tx *DynamicFeeTx) GetAccessList() ethtypes.AccessList {
+ if tx.Accesses == nil {
+ return nil
+ }
+ return *tx.Accesses.ToEthAccessList()
+}
+
+// GetData returns the a copy of the input data bytes.
+func (tx *DynamicFeeTx) GetData() []byte {
+ return common.CopyBytes(tx.Data)
+}
+
+// GetGas returns the gas limit.
+func (tx *DynamicFeeTx) GetGas() uint64 {
+ return tx.GasLimit
+}
+
+// GetGasPrice returns the gas fee cap field.
+func (tx *DynamicFeeTx) GetGasPrice() *big.Int {
+ return tx.GetGasFeeCap()
+}
+
+// GetGasTipCap returns the gas tip cap field.
+func (tx *DynamicFeeTx) GetGasTipCap() *big.Int {
+ if tx.GasTipCap == nil {
+ return nil
+ }
+ return tx.GasTipCap.BigInt()
+}
+
+// GetGasFeeCap returns the gas fee cap field.
+func (tx *DynamicFeeTx) GetGasFeeCap() *big.Int {
+ if tx.GasFeeCap == nil {
+ return nil
+ }
+ return tx.GasFeeCap.BigInt()
+}
+
+// GetValue returns the tx amount.
+func (tx *DynamicFeeTx) GetValue() *big.Int {
+ if tx.Amount == nil {
+ return nil
+ }
+
+ return tx.Amount.BigInt()
+}
+
+// GetNonce returns the account sequence for the transaction.
+func (tx *DynamicFeeTx) GetNonce() uint64 { return tx.Nonce }
+
+// GetTo returns the pointer to the recipient address.
+func (tx *DynamicFeeTx) GetTo() *common.Address {
+ if tx.To == "" {
+ return nil
+ }
+ to := common.HexToAddress(tx.To)
+ return &to
+}
+
+// AsEthereumData returns an DynamicFeeTx transaction tx from the proto-formatted
+// TxData defined on the Cosmos EVM.
+func (tx *DynamicFeeTx) AsEthereumData() ethtypes.TxData {
+ v, r, s := tx.GetRawSignatureValues()
+ return ðtypes.DynamicFeeTx{
+ ChainID: tx.GetChainID(),
+ Nonce: tx.GetNonce(),
+ GasTipCap: tx.GetGasTipCap(),
+ GasFeeCap: tx.GetGasFeeCap(),
+ Gas: tx.GetGas(),
+ To: tx.GetTo(),
+ Value: tx.GetValue(),
+ Data: tx.GetData(),
+ AccessList: tx.GetAccessList(),
+ V: v,
+ R: r,
+ S: s,
+ }
+}
+
+// GetRawSignatureValues returns the V, R, S signature values of the transaction.
+// The return values should not be modified by the caller.
+func (tx *DynamicFeeTx) GetRawSignatureValues() (v, r, s *big.Int) {
+ return rawSignatureValues(tx.V, tx.R, tx.S)
+}
+
+// SetSignatureValues sets the signature values to the transaction.
+func (tx *DynamicFeeTx) SetSignatureValues(chainID, v, r, s *big.Int) {
+ if v != nil {
+ tx.V = v.Bytes()
+ }
+ if r != nil {
+ tx.R = r.Bytes()
+ }
+ if s != nil {
+ tx.S = s.Bytes()
+ }
+ if chainID != nil {
+ chainIDInt := sdkmath.NewIntFromBigInt(chainID)
+ tx.ChainID = &chainIDInt
+ }
+}
+
+// Validate performs a stateless validation of the tx fields.
+func (tx DynamicFeeTx) Validate() error {
+ if tx.GasTipCap == nil {
+ return errorsmod.Wrap(ErrInvalidGasCap, "gas tip cap cannot nil")
+ }
+
+ if tx.GasFeeCap == nil {
+ return errorsmod.Wrap(ErrInvalidGasCap, "gas fee cap cannot nil")
+ }
+
+ if tx.GasTipCap.IsNegative() {
+ return errorsmod.Wrapf(ErrInvalidGasCap, "gas tip cap cannot be negative %s", tx.GasTipCap)
+ }
+
+ if tx.GasFeeCap.IsNegative() {
+ return errorsmod.Wrapf(ErrInvalidGasCap, "gas fee cap cannot be negative %s", tx.GasFeeCap)
+ }
+
+ if !types.IsValidInt256(tx.GetGasTipCap()) {
+ return errorsmod.Wrap(ErrInvalidGasCap, "out of bound")
+ }
+
+ if !types.IsValidInt256(tx.GetGasFeeCap()) {
+ return errorsmod.Wrap(ErrInvalidGasCap, "out of bound")
+ }
+
+ if tx.GasFeeCap.LT(*tx.GasTipCap) {
+ return errorsmod.Wrapf(
+ ErrInvalidGasCap, "max priority fee per gas higher than max fee per gas (%s > %s)",
+ tx.GasTipCap, tx.GasFeeCap,
+ )
+ }
+
+ if !types.IsValidInt256(tx.Fee()) {
+ return errorsmod.Wrap(ErrInvalidGasFee, "out of bound")
+ }
+
+ amount := tx.GetValue()
+ // Amount can be 0
+ if amount != nil && amount.Sign() == -1 {
+ return errorsmod.Wrapf(ErrInvalidAmount, "amount cannot be negative %s", amount)
+ }
+ if !types.IsValidInt256(amount) {
+ return errorsmod.Wrap(ErrInvalidAmount, "out of bound")
+ }
+
+ if tx.To != "" {
+ if err := types.ValidateAddress(tx.To); err != nil {
+ return errorsmod.Wrap(err, "invalid to address")
+ }
+ }
+
+ if tx.GetChainID() == nil {
+ return errorsmod.Wrap(
+ errortypes.ErrInvalidChainID,
+ "chain ID must be present on DynamicFee txs",
+ )
+ }
+
+ return nil
+}
+
+// Fee returns gasprice * gaslimit.
+func (tx DynamicFeeTx) Fee() *big.Int {
+ return fee(tx.GetGasFeeCap(), tx.GasLimit)
+}
+
+// Cost returns amount + gasprice * gaslimit.
+func (tx DynamicFeeTx) Cost() *big.Int {
+ return cost(tx.Fee(), tx.GetValue())
+}
+
+// EffectiveGasPrice returns the effective gas price
+func (tx *DynamicFeeTx) EffectiveGasPrice(baseFee *big.Int) *big.Int {
+ return EffectiveGasPrice(baseFee, tx.GasFeeCap.BigInt(), tx.GasTipCap.BigInt())
+}
+
+// EffectiveFee returns effective_gasprice * gaslimit.
+func (tx DynamicFeeTx) EffectiveFee(baseFee *big.Int) *big.Int {
+ return fee(tx.EffectiveGasPrice(baseFee), tx.GasLimit)
+}
+
+// EffectiveCost returns amount + effective_gasprice * gaslimit.
+func (tx DynamicFeeTx) EffectiveCost(baseFee *big.Int) *big.Int {
+ return cost(tx.EffectiveFee(baseFee), tx.GetValue())
+}
diff --git a/x/evm/types/dynamic_fee_tx_test.go b/x/evm/types/dynamic_fee_tx_test.go
new file mode 100644
index 00000000..41767f0f
--- /dev/null
+++ b/x/evm/types/dynamic_fee_tx_test.go
@@ -0,0 +1,677 @@
+package types_test
+
+import (
+ "math/big"
+ "testing"
+
+ sdkmath "cosmossdk.io/math"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/evm/types"
+
+ "github.com/stretchr/testify/suite"
+)
+
+type TxDataTestSuite struct {
+ suite.Suite
+
+ sdkInt sdkmath.Int
+ uint64 uint64
+ hexUint64 hexutil.Uint64
+ bigInt *big.Int
+ hexBigInt hexutil.Big
+ overflowBigInt *big.Int
+ sdkZeroInt sdkmath.Int
+ sdkMinusOneInt sdkmath.Int
+ invalidAddr string
+ addr common.Address
+ hexAddr string
+ hexDataBytes hexutil.Bytes
+ hexInputBytes hexutil.Bytes
+}
+
+func (suite *TxDataTestSuite) SetupTest() {
+ suite.sdkInt = sdkmath.NewInt(9001)
+ suite.uint64 = suite.sdkInt.Uint64()
+ suite.hexUint64 = hexutil.Uint64(100)
+ suite.bigInt = big.NewInt(1)
+ suite.hexBigInt = hexutil.Big(*big.NewInt(1))
+ suite.overflowBigInt = big.NewInt(0).Exp(big.NewInt(10), big.NewInt(256), nil)
+ suite.sdkZeroInt = sdkmath.ZeroInt()
+ suite.sdkMinusOneInt = sdkmath.NewInt(-1)
+ suite.invalidAddr = "123456"
+ suite.addr = utiltx.GenerateAddress()
+ suite.hexAddr = suite.addr.Hex()
+ suite.hexDataBytes = hexutil.Bytes([]byte("data"))
+ suite.hexInputBytes = hexutil.Bytes([]byte("input"))
+}
+
+func TestTxDataTestSuite(t *testing.T) {
+ suite.Run(t, new(TxDataTestSuite))
+}
+
+func (suite *TxDataTestSuite) TestNewDynamicFeeTx() {
+ testCases := []struct {
+ name string
+ expError bool
+ tx *ethtypes.Transaction
+ }{
+ {
+ "non-empty tx",
+ false,
+ ethtypes.NewTx(ðtypes.DynamicFeeTx{
+ Nonce: 1,
+ Data: []byte("data"),
+ Gas: 100,
+ Value: big.NewInt(1),
+ AccessList: ethtypes.AccessList{},
+ To: &suite.addr,
+ V: suite.bigInt,
+ R: suite.bigInt,
+ S: suite.bigInt,
+ }),
+ },
+ {
+ "value out of bounds tx",
+ true,
+ ethtypes.NewTx(ðtypes.DynamicFeeTx{
+ Nonce: 1,
+ Data: []byte("data"),
+ Gas: 100,
+ Value: suite.overflowBigInt,
+ AccessList: ethtypes.AccessList{},
+ To: &suite.addr,
+ V: suite.bigInt,
+ R: suite.bigInt,
+ S: suite.bigInt,
+ }),
+ },
+ {
+ "gas fee cap out of bounds tx",
+ true,
+ ethtypes.NewTx(ðtypes.DynamicFeeTx{
+ Nonce: 1,
+ Data: []byte("data"),
+ Gas: 100,
+ GasFeeCap: suite.overflowBigInt,
+ Value: big.NewInt(1),
+ AccessList: ethtypes.AccessList{},
+ To: &suite.addr,
+ V: suite.bigInt,
+ R: suite.bigInt,
+ S: suite.bigInt,
+ }),
+ },
+ {
+ "gas tip cap out of bounds tx",
+ true,
+ ethtypes.NewTx(ðtypes.DynamicFeeTx{
+ Nonce: 1,
+ Data: []byte("data"),
+ Gas: 100,
+ GasTipCap: suite.overflowBigInt,
+ Value: big.NewInt(1),
+ AccessList: ethtypes.AccessList{},
+ To: &suite.addr,
+ V: suite.bigInt,
+ R: suite.bigInt,
+ S: suite.bigInt,
+ }),
+ },
+ }
+ for _, tc := range testCases {
+ tx, err := types.NewDynamicFeeTx(tc.tx)
+
+ if tc.expError {
+ suite.Require().Error(err)
+ } else {
+ suite.Require().NoError(err)
+ suite.Require().NotEmpty(tx)
+ suite.Require().Equal(uint8(2), tx.TxType())
+ }
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxAsEthereumData() {
+ feeConfig := ðtypes.DynamicFeeTx{
+ Nonce: 1,
+ Data: []byte("data"),
+ Gas: 100,
+ Value: big.NewInt(1),
+ AccessList: ethtypes.AccessList{},
+ To: &suite.addr,
+ V: suite.bigInt,
+ R: suite.bigInt,
+ S: suite.bigInt,
+ }
+
+ tx := ethtypes.NewTx(feeConfig)
+
+ dynamicFeeTx, err := types.NewDynamicFeeTx(tx)
+ suite.Require().NoError(err)
+
+ res := dynamicFeeTx.AsEthereumData()
+ resTx := ethtypes.NewTx(res)
+
+ suite.Require().Equal(feeConfig.Nonce, resTx.Nonce())
+ suite.Require().Equal(feeConfig.Data, resTx.Data())
+ suite.Require().Equal(feeConfig.Gas, resTx.Gas())
+ suite.Require().Equal(feeConfig.Value, resTx.Value())
+ suite.Require().Equal(feeConfig.AccessList, resTx.AccessList())
+ suite.Require().Equal(feeConfig.To, resTx.To())
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxCopy() {
+ tx := &types.DynamicFeeTx{}
+ txCopy := tx.Copy()
+
+ suite.Require().Equal(&types.DynamicFeeTx{}, txCopy)
+ // TODO: Test for different pointers
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetChainID() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp *big.Int
+ }{
+ {
+ "empty chainID",
+ types.DynamicFeeTx{
+ ChainID: nil,
+ },
+ nil,
+ },
+ {
+ "non-empty chainID",
+ types.DynamicFeeTx{
+ ChainID: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetChainID()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetAccessList() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp ethtypes.AccessList
+ }{
+ {
+ "empty accesses",
+ types.DynamicFeeTx{
+ Accesses: nil,
+ },
+ nil,
+ },
+ {
+ "nil",
+ types.DynamicFeeTx{
+ Accesses: types.NewAccessList(nil),
+ },
+ nil,
+ },
+ {
+ "non-empty accesses",
+ types.DynamicFeeTx{
+ Accesses: types.AccessList{
+ {
+ Address: suite.hexAddr,
+ StorageKeys: []string{},
+ },
+ },
+ },
+ ethtypes.AccessList{
+ {
+ Address: suite.addr,
+ StorageKeys: []common.Hash{},
+ },
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetAccessList()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetData() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ }{
+ {
+ "non-empty transaction",
+ types.DynamicFeeTx{
+ Data: nil,
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetData()
+
+ suite.Require().Equal(tc.tx.Data, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetGas() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp uint64
+ }{
+ {
+ "non-empty gas",
+ types.DynamicFeeTx{
+ GasLimit: suite.uint64,
+ },
+ suite.uint64,
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGas()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetGasPrice() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp *big.Int
+ }{
+ {
+ "non-empty gasFeeCap",
+ types.DynamicFeeTx{
+ GasFeeCap: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasPrice()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetGasTipCap() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp *big.Int
+ }{
+ {
+ "empty gasTipCap",
+ types.DynamicFeeTx{
+ GasTipCap: nil,
+ },
+ nil,
+ },
+ {
+ "non-empty gasTipCap",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasTipCap()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetGasFeeCap() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp *big.Int
+ }{
+ {
+ "empty gasFeeCap",
+ types.DynamicFeeTx{
+ GasFeeCap: nil,
+ },
+ nil,
+ },
+ {
+ "non-empty gasFeeCap",
+ types.DynamicFeeTx{
+ GasFeeCap: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasFeeCap()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetValue() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp *big.Int
+ }{
+ {
+ "empty amount",
+ types.DynamicFeeTx{
+ Amount: nil,
+ },
+ nil,
+ },
+ {
+ "non-empty amount",
+ types.DynamicFeeTx{
+ Amount: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetValue()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetNonce() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp uint64
+ }{
+ {
+ "non-empty nonce",
+ types.DynamicFeeTx{
+ Nonce: suite.uint64,
+ },
+ suite.uint64,
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetNonce()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxGetTo() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ exp *common.Address
+ }{
+ {
+ "empty suite.address",
+ types.DynamicFeeTx{
+ To: "",
+ },
+ nil,
+ },
+ {
+ "non-empty suite.address",
+ types.DynamicFeeTx{
+ To: suite.hexAddr,
+ },
+ &suite.addr,
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetTo()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxSetSignatureValues() {
+ testCases := []struct {
+ name string
+ chainID *big.Int
+ r *big.Int
+ v *big.Int
+ s *big.Int
+ }{
+ {
+ "empty values",
+ nil,
+ nil,
+ nil,
+ nil,
+ },
+ {
+ "non-empty values",
+ suite.bigInt,
+ suite.bigInt,
+ suite.bigInt,
+ suite.bigInt,
+ },
+ }
+
+ for _, tc := range testCases {
+ tx := &types.DynamicFeeTx{}
+ tx.SetSignatureValues(tc.chainID, tc.v, tc.r, tc.s)
+
+ v, r, s := tx.GetRawSignatureValues()
+ chainID := tx.GetChainID()
+
+ suite.Require().Equal(tc.v, v, tc.name)
+ suite.Require().Equal(tc.r, r, tc.name)
+ suite.Require().Equal(tc.s, s, tc.name)
+ suite.Require().Equal(tc.chainID, chainID, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxValidate() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ expError bool
+ }{
+ {
+ "empty",
+ types.DynamicFeeTx{},
+ true,
+ },
+ {
+ "gas tip cap is nil",
+ types.DynamicFeeTx{
+ GasTipCap: nil,
+ },
+ true,
+ },
+ {
+ "gas fee cap is nil",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkZeroInt,
+ },
+ true,
+ },
+ {
+ "gas tip cap is negative",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkMinusOneInt,
+ GasFeeCap: &suite.sdkZeroInt,
+ },
+ true,
+ },
+ {
+ "gas tip cap is negative",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkZeroInt,
+ GasFeeCap: &suite.sdkMinusOneInt,
+ },
+ true,
+ },
+ {
+ "gas fee cap < gas tip cap",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkZeroInt,
+ },
+ true,
+ },
+ {
+ "amount is negative",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkInt,
+ Amount: &suite.sdkMinusOneInt,
+ },
+ true,
+ },
+ {
+ "to suite.address is invalid",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkInt,
+ Amount: &suite.sdkInt,
+ To: suite.invalidAddr,
+ },
+ true,
+ },
+ {
+ "chain ID not present on AccessList txs",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkInt,
+ Amount: &suite.sdkInt,
+ To: suite.hexAddr,
+ ChainID: nil,
+ },
+ true,
+ },
+ {
+ "no errors",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkInt,
+ Amount: &suite.sdkInt,
+ To: suite.hexAddr,
+ ChainID: &suite.sdkInt,
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ err := tc.tx.Validate()
+
+ if tc.expError {
+ suite.Require().Error(err, tc.name)
+ continue
+ }
+
+ suite.Require().NoError(err, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxEffectiveGasPrice() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ baseFee *big.Int
+ exp *big.Int
+ }{
+ {
+ "non-empty dynamic fee tx",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveGasPrice(tc.baseFee)
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxEffectiveFee() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ baseFee *big.Int
+ exp *big.Int
+ }{
+ {
+ "non-empty dynamic fee tx",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkInt,
+ GasLimit: uint64(1),
+ },
+ (&suite.sdkInt).BigInt(),
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveFee(tc.baseFee)
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxEffectiveCost() {
+ testCases := []struct {
+ name string
+ tx types.DynamicFeeTx
+ baseFee *big.Int
+ exp *big.Int
+ }{
+ {
+ "non-empty dynamic fee tx",
+ types.DynamicFeeTx{
+ GasTipCap: &suite.sdkInt,
+ GasFeeCap: &suite.sdkInt,
+ GasLimit: uint64(1),
+ Amount: &suite.sdkZeroInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveCost(tc.baseFee)
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestDynamicFeeTxFeeCost() {
+ tx := &types.DynamicFeeTx{}
+ suite.Require().Panics(func() { tx.Fee() }, "should panic")
+ suite.Require().Panics(func() { tx.Cost() }, "should panic")
+}
diff --git a/x/evm/types/errors.go b/x/evm/types/errors.go
new file mode 100644
index 00000000..197b2ce8
--- /dev/null
+++ b/x/evm/types/errors.go
@@ -0,0 +1,124 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "errors"
+ "fmt"
+
+ errorsmod "cosmossdk.io/errors"
+ "github.com/ethereum/go-ethereum/common"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+)
+
+const (
+ codeErrInvalidState = uint32(iota) + 2 // NOTE: code 1 is reserved for internal errors
+ codeErrInvalidChainConfig
+ codeErrZeroAddress
+ codeErrCreateDisabled
+ codeErrCallDisabled
+ codeErrInvalidAmount
+ codeErrInvalidGasPrice
+ codeErrInvalidGasFee
+ codeErrVMExecution
+ codeErrInvalidRefund
+ codeErrInvalidGasCap
+ codeErrInvalidBaseFee
+ codeErrGasOverflow
+ codeErrInvalidAccount
+ codeErrInvalidGasLimit
+ codeErrInactivePrecompile
+ codeErrABIPack
+ codeErrABIUnpack
+)
+
+var (
+ // ErrInvalidState returns an error resulting from an invalid Storage State.
+ ErrInvalidState = errorsmod.Register(ModuleName, codeErrInvalidState, "invalid storage state")
+
+ // ErrInvalidChainConfig returns an error resulting from an invalid ChainConfig.
+ ErrInvalidChainConfig = errorsmod.Register(ModuleName, codeErrInvalidChainConfig, "invalid chain configuration")
+
+ // ErrZeroAddress returns an error resulting from an zero (empty) ethereum Address.
+ ErrZeroAddress = errorsmod.Register(ModuleName, codeErrZeroAddress, "invalid zero address")
+
+ // ErrCreateDisabled returns an error if the EnableCreate parameter is false.
+ ErrCreateDisabled = errorsmod.Register(ModuleName, codeErrCreateDisabled, "EVM Create operation is disabled")
+
+ // ErrCallDisabled returns an error if the EnableCall parameter is false.
+ ErrCallDisabled = errorsmod.Register(ModuleName, codeErrCallDisabled, "EVM Call operation is disabled")
+
+ // ErrInvalidAmount returns an error if a tx contains an invalid amount.
+ ErrInvalidAmount = errorsmod.Register(ModuleName, codeErrInvalidAmount, "invalid transaction amount")
+
+ // ErrInvalidGasPrice returns an error if an invalid gas price is provided to the tx.
+ ErrInvalidGasPrice = errorsmod.Register(ModuleName, codeErrInvalidGasPrice, "invalid gas price")
+
+ // ErrInvalidGasFee returns an error if the tx gas fee is out of bound.
+ ErrInvalidGasFee = errorsmod.Register(ModuleName, codeErrInvalidGasFee, "invalid gas fee")
+
+ // ErrVMExecution returns an error resulting from an error in EVM execution.
+ ErrVMExecution = errorsmod.Register(ModuleName, codeErrVMExecution, "evm transaction execution failed")
+
+ // ErrInvalidRefund returns an error if a the gas refund value is invalid.
+ ErrInvalidRefund = errorsmod.Register(ModuleName, codeErrInvalidRefund, "invalid gas refund amount")
+
+ // ErrInvalidGasCap returns an error if a the gas cap value is negative or invalid
+ ErrInvalidGasCap = errorsmod.Register(ModuleName, codeErrInvalidGasCap, "invalid gas cap")
+
+ // ErrInvalidBaseFee returns an error if a the base fee cap value is invalid
+ ErrInvalidBaseFee = errorsmod.Register(ModuleName, codeErrInvalidBaseFee, "invalid base fee")
+
+ // ErrGasOverflow returns an error if gas computation overlow/underflow
+ ErrGasOverflow = errorsmod.Register(ModuleName, codeErrGasOverflow, "gas computation overflow/underflow")
+
+ // ErrInvalidAccount returns an error if the account is not an EVM compatible account
+ ErrInvalidAccount = errorsmod.Register(ModuleName, codeErrInvalidAccount, "account type is not a valid ethereum account")
+
+ // ErrInvalidGasLimit returns an error if gas limit value is invalid
+ ErrInvalidGasLimit = errorsmod.Register(ModuleName, codeErrInvalidGasLimit, "invalid gas limit")
+
+ // ErrInactivePrecompile returns an error if a call is made to an inactive precompile
+ ErrInactivePrecompile = errorsmod.Register(ModuleName, codeErrInactivePrecompile, "precompile not enabled")
+
+ // ErrABIPack returns an error if the contract ABI packing fails
+ ErrABIPack = errorsmod.Register(ModuleName, codeErrABIPack, "contract ABI pack failed")
+
+ // ErrABIUnpack returns an error if the contract ABI unpacking fails
+ ErrABIUnpack = errorsmod.Register(ModuleName, codeErrABIUnpack, "contract ABI unpack failed")
+)
+
+// NewExecErrorWithReason unpacks the revert return bytes and returns a wrapped error
+// with the return reason.
+func NewExecErrorWithReason(revertReason []byte) *RevertError {
+ result := common.CopyBytes(revertReason)
+ reason, errUnpack := abi.UnpackRevert(result)
+ err := errors.New("execution reverted")
+ if errUnpack == nil {
+ err = fmt.Errorf("execution reverted: %v", reason)
+ }
+ return &RevertError{
+ error: err,
+ reason: hexutil.Encode(result),
+ }
+}
+
+// RevertError is an API error that encompass an EVM revert with JSON error
+// code and a binary data blob.
+type RevertError struct {
+ error
+ reason string // revert reason hex encoded
+}
+
+// ErrorCode returns the JSON error code for a revert.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *RevertError) ErrorCode() int {
+ return 3
+}
+
+// ErrorData returns the hex encoded revert reason.
+func (e *RevertError) ErrorData() interface{} {
+ return e.reason
+}
diff --git a/x/evm/types/events.go b/x/evm/types/events.go
new file mode 100644
index 00000000..8c300bf6
--- /dev/null
+++ b/x/evm/types/events.go
@@ -0,0 +1,26 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+// Evm module events
+const (
+ EventTypeEthereumTx = TypeMsgEthereumTx
+ EventTypeBlockBloom = "block_bloom"
+ EventTypeTxLog = "tx_log"
+
+ AttributeKeyContractAddress = "contract"
+ AttributeKeyRecipient = "recipient"
+ AttributeKeyTxHash = "txHash"
+ AttributeKeyEthereumTxHash = "ethereumTxHash"
+ AttributeKeyTxIndex = "txIndex"
+ AttributeKeyTxGasUsed = "txGasUsed"
+ AttributeKeyTxType = "txType"
+ AttributeKeyTxLog = "txLog"
+ // tx failed in eth vm execution
+ AttributeKeyEthereumTxFailed = "ethereumTxFailed"
+ AttributeValueCategory = ModuleName
+ AttributeKeyEthereumBloom = "bloom"
+
+ MetricKeyTransitionDB = "transition_db"
+ MetricKeyStaticCall = "static_call"
+)
diff --git a/x/evm/types/events.pb.go b/x/evm/types/events.pb.go
new file mode 100644
index 00000000..cd013e94
--- /dev/null
+++ b/x/evm/types/events.pb.go
@@ -0,0 +1,1265 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/evm/v1/events.proto
+
+package types
+
+import (
+ fmt "fmt"
+ proto "github.com/cosmos/gogoproto/proto"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// EventEthereumTx defines the event for an Ethereum transaction
+type EventEthereumTx struct {
+ // amount
+ Amount string `protobuf:"bytes,1,opt,name=amount,proto3" json:"amount,omitempty"`
+ // eth_hash is the Ethereum hash of the transaction
+ EthHash string `protobuf:"bytes,2,opt,name=eth_hash,json=ethHash,proto3" json:"eth_hash,omitempty"`
+ // index of the transaction in the block
+ Index string `protobuf:"bytes,3,opt,name=index,proto3" json:"index,omitempty"`
+ // gas_used is the amount of gas used by the transaction
+ GasUsed string `protobuf:"bytes,4,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
+ // hash is the Tendermint hash of the transaction
+ Hash string `protobuf:"bytes,5,opt,name=hash,proto3" json:"hash,omitempty"`
+ // recipient of the transaction
+ Recipient string `protobuf:"bytes,6,opt,name=recipient,proto3" json:"recipient,omitempty"`
+ // eth_tx_failed contains a VM error should it occur
+ EthTxFailed string `protobuf:"bytes,7,opt,name=eth_tx_failed,json=ethTxFailed,proto3" json:"eth_tx_failed,omitempty"`
+}
+
+func (m *EventEthereumTx) Reset() { *m = EventEthereumTx{} }
+func (m *EventEthereumTx) String() string { return proto.CompactTextString(m) }
+func (*EventEthereumTx) ProtoMessage() {}
+func (*EventEthereumTx) Descriptor() ([]byte, []int) {
+ return fileDescriptor_432e0d592184bde3, []int{0}
+}
+func (m *EventEthereumTx) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EventEthereumTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EventEthereumTx.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EventEthereumTx) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EventEthereumTx.Merge(m, src)
+}
+func (m *EventEthereumTx) XXX_Size() int {
+ return m.Size()
+}
+func (m *EventEthereumTx) XXX_DiscardUnknown() {
+ xxx_messageInfo_EventEthereumTx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EventEthereumTx proto.InternalMessageInfo
+
+func (m *EventEthereumTx) GetAmount() string {
+ if m != nil {
+ return m.Amount
+ }
+ return ""
+}
+
+func (m *EventEthereumTx) GetEthHash() string {
+ if m != nil {
+ return m.EthHash
+ }
+ return ""
+}
+
+func (m *EventEthereumTx) GetIndex() string {
+ if m != nil {
+ return m.Index
+ }
+ return ""
+}
+
+func (m *EventEthereumTx) GetGasUsed() string {
+ if m != nil {
+ return m.GasUsed
+ }
+ return ""
+}
+
+func (m *EventEthereumTx) GetHash() string {
+ if m != nil {
+ return m.Hash
+ }
+ return ""
+}
+
+func (m *EventEthereumTx) GetRecipient() string {
+ if m != nil {
+ return m.Recipient
+ }
+ return ""
+}
+
+func (m *EventEthereumTx) GetEthTxFailed() string {
+ if m != nil {
+ return m.EthTxFailed
+ }
+ return ""
+}
+
+// EventTxLog defines the event for an Ethereum transaction log
+type EventTxLog struct {
+ // tx_logs is an array of transaction logs
+ TxLogs []string `protobuf:"bytes,1,rep,name=tx_logs,json=txLogs,proto3" json:"tx_logs,omitempty"`
+}
+
+func (m *EventTxLog) Reset() { *m = EventTxLog{} }
+func (m *EventTxLog) String() string { return proto.CompactTextString(m) }
+func (*EventTxLog) ProtoMessage() {}
+func (*EventTxLog) Descriptor() ([]byte, []int) {
+ return fileDescriptor_432e0d592184bde3, []int{1}
+}
+func (m *EventTxLog) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EventTxLog) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EventTxLog.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EventTxLog) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EventTxLog.Merge(m, src)
+}
+func (m *EventTxLog) XXX_Size() int {
+ return m.Size()
+}
+func (m *EventTxLog) XXX_DiscardUnknown() {
+ xxx_messageInfo_EventTxLog.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EventTxLog proto.InternalMessageInfo
+
+func (m *EventTxLog) GetTxLogs() []string {
+ if m != nil {
+ return m.TxLogs
+ }
+ return nil
+}
+
+// EventMessage
+type EventMessage struct {
+ // module which emits the event
+ Module string `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"`
+ // sender of the message
+ Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"`
+ // tx_type is the type of the message
+ TxType string `protobuf:"bytes,3,opt,name=tx_type,json=txType,proto3" json:"tx_type,omitempty"`
+}
+
+func (m *EventMessage) Reset() { *m = EventMessage{} }
+func (m *EventMessage) String() string { return proto.CompactTextString(m) }
+func (*EventMessage) ProtoMessage() {}
+func (*EventMessage) Descriptor() ([]byte, []int) {
+ return fileDescriptor_432e0d592184bde3, []int{2}
+}
+func (m *EventMessage) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EventMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EventMessage.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EventMessage) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EventMessage.Merge(m, src)
+}
+func (m *EventMessage) XXX_Size() int {
+ return m.Size()
+}
+func (m *EventMessage) XXX_DiscardUnknown() {
+ xxx_messageInfo_EventMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EventMessage proto.InternalMessageInfo
+
+func (m *EventMessage) GetModule() string {
+ if m != nil {
+ return m.Module
+ }
+ return ""
+}
+
+func (m *EventMessage) GetSender() string {
+ if m != nil {
+ return m.Sender
+ }
+ return ""
+}
+
+func (m *EventMessage) GetTxType() string {
+ if m != nil {
+ return m.TxType
+ }
+ return ""
+}
+
+// EventBlockBloom defines an Ethereum block bloom filter event
+type EventBlockBloom struct {
+ // bloom is the bloom filter of the block
+ Bloom string `protobuf:"bytes,1,opt,name=bloom,proto3" json:"bloom,omitempty"`
+}
+
+func (m *EventBlockBloom) Reset() { *m = EventBlockBloom{} }
+func (m *EventBlockBloom) String() string { return proto.CompactTextString(m) }
+func (*EventBlockBloom) ProtoMessage() {}
+func (*EventBlockBloom) Descriptor() ([]byte, []int) {
+ return fileDescriptor_432e0d592184bde3, []int{3}
+}
+func (m *EventBlockBloom) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EventBlockBloom) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EventBlockBloom.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EventBlockBloom) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EventBlockBloom.Merge(m, src)
+}
+func (m *EventBlockBloom) XXX_Size() int {
+ return m.Size()
+}
+func (m *EventBlockBloom) XXX_DiscardUnknown() {
+ xxx_messageInfo_EventBlockBloom.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EventBlockBloom proto.InternalMessageInfo
+
+func (m *EventBlockBloom) GetBloom() string {
+ if m != nil {
+ return m.Bloom
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*EventEthereumTx)(nil), "ethermint.evm.v1.EventEthereumTx")
+ proto.RegisterType((*EventTxLog)(nil), "ethermint.evm.v1.EventTxLog")
+ proto.RegisterType((*EventMessage)(nil), "ethermint.evm.v1.EventMessage")
+ proto.RegisterType((*EventBlockBloom)(nil), "ethermint.evm.v1.EventBlockBloom")
+}
+
+func init() { proto.RegisterFile("ethermint/evm/v1/events.proto", fileDescriptor_432e0d592184bde3) }
+
+var fileDescriptor_432e0d592184bde3 = []byte{
+ // 365 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x51, 0x4d, 0x6b, 0xdb, 0x40,
+ 0x14, 0xb4, 0x6a, 0x5b, 0xae, 0xb7, 0x2d, 0x2d, 0x4b, 0x69, 0x55, 0x68, 0x85, 0x11, 0x34, 0xc9,
+ 0x49, 0xc2, 0xe4, 0x92, 0x63, 0x30, 0x38, 0xe4, 0x90, 0x5c, 0x82, 0x42, 0x20, 0x17, 0x21, 0x5b,
+ 0x2f, 0x5a, 0x11, 0xad, 0x56, 0x68, 0x9f, 0xc4, 0xfa, 0x5f, 0xe4, 0x67, 0x05, 0x72, 0xf1, 0x31,
+ 0xc7, 0x60, 0xff, 0x91, 0xb0, 0xab, 0x4d, 0x72, 0x59, 0x76, 0x66, 0xde, 0x07, 0xf3, 0x86, 0xfc,
+ 0x03, 0x64, 0xd0, 0xf0, 0xa2, 0xc2, 0x08, 0x3a, 0x1e, 0x75, 0xf3, 0x08, 0x3a, 0xa8, 0x50, 0x86,
+ 0x75, 0x23, 0x50, 0xd0, 0x1f, 0xef, 0x72, 0x08, 0x1d, 0x0f, 0xbb, 0x79, 0xf0, 0xe4, 0x90, 0xef,
+ 0x4b, 0x5d, 0xb2, 0xd4, 0x0a, 0xb4, 0x3c, 0x56, 0xf4, 0x17, 0x71, 0x53, 0x2e, 0xda, 0x0a, 0x3d,
+ 0x67, 0xe6, 0x1c, 0x4d, 0xaf, 0x2c, 0xa2, 0x7f, 0xc8, 0x67, 0x40, 0x96, 0xb0, 0x54, 0x32, 0xef,
+ 0x93, 0x51, 0x26, 0x80, 0xec, 0x3c, 0x95, 0x8c, 0xfe, 0x24, 0xe3, 0xa2, 0xca, 0x40, 0x79, 0x43,
+ 0xc3, 0xf7, 0x40, 0x37, 0xe4, 0xa9, 0x4c, 0x5a, 0x09, 0x99, 0x37, 0xea, 0x1b, 0xf2, 0x54, 0x5e,
+ 0x4b, 0xc8, 0x28, 0x25, 0x23, 0x33, 0x67, 0x6c, 0x68, 0xf3, 0xa7, 0x7f, 0xc9, 0xb4, 0x81, 0x75,
+ 0x51, 0x17, 0x50, 0xa1, 0xe7, 0x1a, 0xe1, 0x83, 0xa0, 0x01, 0xf9, 0xa6, 0xb7, 0xa3, 0x4a, 0xee,
+ 0xd2, 0xa2, 0x84, 0xcc, 0x9b, 0x98, 0x8a, 0x2f, 0x80, 0x2c, 0x56, 0x67, 0x86, 0x0a, 0xfe, 0x13,
+ 0x62, 0xcc, 0xc4, 0xea, 0x42, 0xe4, 0xf4, 0x37, 0x99, 0xa0, 0x4a, 0x4a, 0x91, 0x4b, 0xcf, 0x99,
+ 0x0d, 0xb5, 0x11, 0xd4, 0xbc, 0x0c, 0x6e, 0xc8, 0x57, 0x53, 0x76, 0x09, 0x52, 0xa6, 0x39, 0x68,
+ 0xc3, 0x5c, 0x64, 0x6d, 0x09, 0x6f, 0x86, 0x7b, 0xa4, 0x79, 0x09, 0x55, 0x06, 0x8d, 0xb5, 0x6b,
+ 0x91, 0x1d, 0x8c, 0x9b, 0x1a, 0xac, 0x5f, 0x17, 0x55, 0xbc, 0xa9, 0x21, 0x38, 0xb4, 0xc7, 0x5c,
+ 0x94, 0x62, 0x7d, 0xbf, 0x28, 0x85, 0xe0, 0xfa, 0x32, 0x2b, 0xfd, 0xb1, 0xa3, 0x7b, 0xb0, 0x38,
+ 0x7d, 0xdc, 0xf9, 0xce, 0x76, 0xe7, 0x3b, 0x2f, 0x3b, 0xdf, 0x79, 0xd8, 0xfb, 0x83, 0xed, 0xde,
+ 0x1f, 0x3c, 0xef, 0xfd, 0xc1, 0xed, 0x41, 0x5e, 0x20, 0x6b, 0x57, 0xe1, 0x5a, 0x70, 0x1d, 0xa1,
+ 0x90, 0xf6, 0xed, 0xe6, 0x27, 0x91, 0x32, 0xa1, 0xea, 0xbd, 0x72, 0xe5, 0x9a, 0x44, 0x8f, 0x5f,
+ 0x03, 0x00, 0x00, 0xff, 0xff, 0x28, 0x90, 0xca, 0xca, 0xf2, 0x01, 0x00, 0x00,
+}
+
+func (m *EventEthereumTx) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EventEthereumTx) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EventEthereumTx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.EthTxFailed) > 0 {
+ i -= len(m.EthTxFailed)
+ copy(dAtA[i:], m.EthTxFailed)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.EthTxFailed)))
+ i--
+ dAtA[i] = 0x3a
+ }
+ if len(m.Recipient) > 0 {
+ i -= len(m.Recipient)
+ copy(dAtA[i:], m.Recipient)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Recipient)))
+ i--
+ dAtA[i] = 0x32
+ }
+ if len(m.Hash) > 0 {
+ i -= len(m.Hash)
+ copy(dAtA[i:], m.Hash)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Hash)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if len(m.GasUsed) > 0 {
+ i -= len(m.GasUsed)
+ copy(dAtA[i:], m.GasUsed)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.GasUsed)))
+ i--
+ dAtA[i] = 0x22
+ }
+ if len(m.Index) > 0 {
+ i -= len(m.Index)
+ copy(dAtA[i:], m.Index)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Index)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.EthHash) > 0 {
+ i -= len(m.EthHash)
+ copy(dAtA[i:], m.EthHash)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.EthHash)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Amount) > 0 {
+ i -= len(m.Amount)
+ copy(dAtA[i:], m.Amount)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Amount)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *EventTxLog) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EventTxLog) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EventTxLog) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.TxLogs) > 0 {
+ for iNdEx := len(m.TxLogs) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.TxLogs[iNdEx])
+ copy(dAtA[i:], m.TxLogs[iNdEx])
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.TxLogs[iNdEx])))
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *EventMessage) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EventMessage) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EventMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.TxType) > 0 {
+ i -= len(m.TxType)
+ copy(dAtA[i:], m.TxType)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.TxType)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Sender) > 0 {
+ i -= len(m.Sender)
+ copy(dAtA[i:], m.Sender)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Sender)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Module) > 0 {
+ i -= len(m.Module)
+ copy(dAtA[i:], m.Module)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Module)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *EventBlockBloom) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EventBlockBloom) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EventBlockBloom) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Bloom) > 0 {
+ i -= len(m.Bloom)
+ copy(dAtA[i:], m.Bloom)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Bloom)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintEvents(dAtA []byte, offset int, v uint64) int {
+ offset -= sovEvents(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *EventEthereumTx) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Amount)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.EthHash)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.Index)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.GasUsed)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.Hash)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.Recipient)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.EthTxFailed)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ return n
+}
+
+func (m *EventTxLog) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.TxLogs) > 0 {
+ for _, s := range m.TxLogs {
+ l = len(s)
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *EventMessage) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Module)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.Sender)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.TxType)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ return n
+}
+
+func (m *EventBlockBloom) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Bloom)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ return n
+}
+
+func sovEvents(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozEvents(x uint64) (n int) {
+ return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *EventEthereumTx) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EventEthereumTx: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EventEthereumTx: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Amount = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EthHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EthHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Index = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.GasUsed = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Recipient", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Recipient = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EthTxFailed", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EthTxFailed = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvents(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *EventTxLog) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EventTxLog: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EventTxLog: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxLogs", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.TxLogs = append(m.TxLogs, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvents(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *EventMessage) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EventMessage: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EventMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Module", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Module = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Sender = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxType", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.TxType = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvents(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *EventBlockBloom) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EventBlockBloom: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EventBlockBloom: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Bloom", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Bloom = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvents(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipEvents(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthEvents
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupEvents
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthEvents
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthEvents = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowEvents = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupEvents = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/evm/types/evm.pb.go b/x/evm/types/evm.pb.go
new file mode 100644
index 00000000..c4717953
--- /dev/null
+++ b/x/evm/types/evm.pb.go
@@ -0,0 +1,4648 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/evm/v1/evm.proto
+
+package types
+
+import (
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ cosmossdk_io_math "cosmossdk.io/math"
+
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ proto "github.com/cosmos/gogoproto/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = proto.Marshal
+ _ = fmt.Errorf
+ _ = math.Inf
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// AccessType defines the types of permissions for the operations
+type AccessType int32
+
+const (
+ // ACCESS_TYPE_PERMISSIONLESS does not restrict the operation to anyone
+ AccessTypePermissionless AccessType = 0
+ // ACCESS_TYPE_RESTRICTED restrict the operation to anyone
+ AccessTypeRestricted AccessType = 1
+ // ACCESS_TYPE_PERMISSIONED only allows the operation for specific addresses
+ AccessTypePermissioned AccessType = 2
+)
+
+var AccessType_name = map[int32]string{
+ 0: "ACCESS_TYPE_PERMISSIONLESS",
+ 1: "ACCESS_TYPE_RESTRICTED",
+ 2: "ACCESS_TYPE_PERMISSIONED",
+}
+
+var AccessType_value = map[string]int32{
+ "ACCESS_TYPE_PERMISSIONLESS": 0,
+ "ACCESS_TYPE_RESTRICTED": 1,
+ "ACCESS_TYPE_PERMISSIONED": 2,
+}
+
+func (x AccessType) String() string {
+ return proto.EnumName(AccessType_name, int32(x))
+}
+
+func (AccessType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{0}
+}
+
+// Params defines the EVM module parameters
+type Params struct {
+ // evm_denom represents the token denomination used to run the EVM state
+ // transitions.
+ EvmDenom string `protobuf:"bytes,1,opt,name=evm_denom,json=evmDenom,proto3" json:"evm_denom,omitempty" yaml:"evm_denom"`
+ // extra_eips defines the additional EIPs for the vm.Config
+ ExtraEIPs []string `protobuf:"bytes,4,rep,name=extra_eips,json=extraEips,proto3" json:"extra_eips,omitempty" yaml:"extra_eips"`
+ // chain_config defines the EVM chain configuration parameters
+ ChainConfig ChainConfig `protobuf:"bytes,5,opt,name=chain_config,json=chainConfig,proto3" json:"chain_config" yaml:"chain_config"`
+ // allow_unprotected_txs defines if replay-protected (i.e non EIP155
+ // signed) transactions can be executed on the state machine.
+ AllowUnprotectedTxs bool `protobuf:"varint,6,opt,name=allow_unprotected_txs,json=allowUnprotectedTxs,proto3" json:"allow_unprotected_txs,omitempty"`
+ // evm_channels is the list of channel identifiers from EVM compatible chains
+ EVMChannels []string `protobuf:"bytes,8,rep,name=evm_channels,json=evmChannels,proto3" json:"evm_channels,omitempty"`
+ // access_control defines the permission policy of the EVM
+ AccessControl AccessControl `protobuf:"bytes,9,opt,name=access_control,json=accessControl,proto3" json:"access_control"`
+ // active_static_precompiles defines the slice of hex addresses of the precompiled
+ // contracts that are active
+ ActiveStaticPrecompiles []string `protobuf:"bytes,10,rep,name=active_static_precompiles,json=activeStaticPrecompiles,proto3" json:"active_static_precompiles,omitempty"`
+}
+
+func (m *Params) Reset() { *m = Params{} }
+func (m *Params) String() string { return proto.CompactTextString(m) }
+func (*Params) ProtoMessage() {}
+func (*Params) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{0}
+}
+
+func (m *Params) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Params.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *Params) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Params.Merge(m, src)
+}
+
+func (m *Params) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *Params) XXX_DiscardUnknown() {
+ xxx_messageInfo_Params.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Params proto.InternalMessageInfo
+
+func (m *Params) GetEvmDenom() string {
+ if m != nil {
+ return m.EvmDenom
+ }
+ return ""
+}
+
+func (m *Params) GetExtraEIPs() []string {
+ if m != nil {
+ return m.ExtraEIPs
+ }
+ return nil
+}
+
+func (m *Params) GetChainConfig() ChainConfig {
+ if m != nil {
+ return m.ChainConfig
+ }
+ return ChainConfig{}
+}
+
+func (m *Params) GetAllowUnprotectedTxs() bool {
+ if m != nil {
+ return m.AllowUnprotectedTxs
+ }
+ return false
+}
+
+func (m *Params) GetEVMChannels() []string {
+ if m != nil {
+ return m.EVMChannels
+ }
+ return nil
+}
+
+func (m *Params) GetAccessControl() AccessControl {
+ if m != nil {
+ return m.AccessControl
+ }
+ return AccessControl{}
+}
+
+func (m *Params) GetActiveStaticPrecompiles() []string {
+ if m != nil {
+ return m.ActiveStaticPrecompiles
+ }
+ return nil
+}
+
+// AccessControl defines the permission policy of the EVM
+// for creating and calling contracts
+type AccessControl struct {
+ // create defines the permission policy for creating contracts
+ Create AccessControlType `protobuf:"bytes,1,opt,name=create,proto3" json:"create"`
+ // call defines the permission policy for calling contracts
+ Call AccessControlType `protobuf:"bytes,2,opt,name=call,proto3" json:"call"`
+}
+
+func (m *AccessControl) Reset() { *m = AccessControl{} }
+func (m *AccessControl) String() string { return proto.CompactTextString(m) }
+func (*AccessControl) ProtoMessage() {}
+func (*AccessControl) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{1}
+}
+
+func (m *AccessControl) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *AccessControl) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_AccessControl.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *AccessControl) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccessControl.Merge(m, src)
+}
+
+func (m *AccessControl) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *AccessControl) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccessControl.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccessControl proto.InternalMessageInfo
+
+func (m *AccessControl) GetCreate() AccessControlType {
+ if m != nil {
+ return m.Create
+ }
+ return AccessControlType{}
+}
+
+func (m *AccessControl) GetCall() AccessControlType {
+ if m != nil {
+ return m.Call
+ }
+ return AccessControlType{}
+}
+
+// AccessControlType defines the permission type for policies
+type AccessControlType struct {
+ // access_type defines which type of permission is required for the operation
+ AccessType AccessType `protobuf:"varint,1,opt,name=access_type,json=accessType,proto3,enum=ethermint.evm.v1.AccessType" json:"access_type,omitempty" yaml:"access_type"`
+ // access_control_list defines defines different things depending on the AccessType:
+ // - ACCESS_TYPE_PERMISSIONLESS: list of addresses that are blocked from performing the operation
+ // - ACCESS_TYPE_RESTRICTED: ignored
+ // - ACCESS_TYPE_PERMISSIONED: list of addresses that are allowed to perform the operation
+ AccessControlList []string `protobuf:"bytes,2,rep,name=access_control_list,json=accessControlList,proto3" json:"access_control_list,omitempty" yaml:"access_control_list"`
+}
+
+func (m *AccessControlType) Reset() { *m = AccessControlType{} }
+func (m *AccessControlType) String() string { return proto.CompactTextString(m) }
+func (*AccessControlType) ProtoMessage() {}
+func (*AccessControlType) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{2}
+}
+
+func (m *AccessControlType) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *AccessControlType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_AccessControlType.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *AccessControlType) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccessControlType.Merge(m, src)
+}
+
+func (m *AccessControlType) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *AccessControlType) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccessControlType.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccessControlType proto.InternalMessageInfo
+
+func (m *AccessControlType) GetAccessType() AccessType {
+ if m != nil {
+ return m.AccessType
+ }
+ return AccessTypePermissionless
+}
+
+func (m *AccessControlType) GetAccessControlList() []string {
+ if m != nil {
+ return m.AccessControlList
+ }
+ return nil
+}
+
+// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
+// instead of *big.Int.
+type ChainConfig struct {
+ // homestead_block switch (nil no fork, 0 = already homestead)
+ HomesteadBlock *cosmossdk_io_math.Int `protobuf:"bytes,1,opt,name=homestead_block,json=homesteadBlock,proto3,customtype=cosmossdk.io/math.Int" json:"homestead_block,omitempty" yaml:"homestead_block"`
+ // dao_fork_block corresponds to TheDAO hard-fork switch block (nil no fork)
+ DAOForkBlock *cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=dao_fork_block,json=daoForkBlock,proto3,customtype=cosmossdk.io/math.Int" json:"dao_fork_block,omitempty" yaml:"dao_fork_block"`
+ // dao_fork_support defines whether the nodes supports or opposes the DAO hard-fork
+ DAOForkSupport bool `protobuf:"varint,3,opt,name=dao_fork_support,json=daoForkSupport,proto3" json:"dao_fork_support,omitempty" yaml:"dao_fork_support"`
+ // eip150_block: EIP150 implements the Gas price changes
+ // (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no fork)
+ EIP150Block *cosmossdk_io_math.Int `protobuf:"bytes,4,opt,name=eip150_block,json=eip150Block,proto3,customtype=cosmossdk.io/math.Int" json:"eip150_block,omitempty" yaml:"eip150_block"`
+ // eip150_hash: EIP150 HF hash (needed for header only clients as only gas pricing changed)
+ EIP150Hash string `protobuf:"bytes,5,opt,name=eip150_hash,json=eip150Hash,proto3" json:"eip150_hash,omitempty" yaml:"byzantium_block"`
+ // eip155_block: EIP155Block HF block
+ EIP155Block *cosmossdk_io_math.Int `protobuf:"bytes,6,opt,name=eip155_block,json=eip155Block,proto3,customtype=cosmossdk.io/math.Int" json:"eip155_block,omitempty" yaml:"eip155_block"`
+ // eip158_block: EIP158 HF block
+ EIP158Block *cosmossdk_io_math.Int `protobuf:"bytes,7,opt,name=eip158_block,json=eip158Block,proto3,customtype=cosmossdk.io/math.Int" json:"eip158_block,omitempty" yaml:"eip158_block"`
+ // byzantium_block: Byzantium switch block (nil no fork, 0 = already on byzantium)
+ ByzantiumBlock *cosmossdk_io_math.Int `protobuf:"bytes,8,opt,name=byzantium_block,json=byzantiumBlock,proto3,customtype=cosmossdk.io/math.Int" json:"byzantium_block,omitempty" yaml:"byzantium_block"`
+ // constantinople_block: Constantinople switch block (nil no fork, 0 = already activated)
+ ConstantinopleBlock *cosmossdk_io_math.Int `protobuf:"bytes,9,opt,name=constantinople_block,json=constantinopleBlock,proto3,customtype=cosmossdk.io/math.Int" json:"constantinople_block,omitempty" yaml:"constantinople_block"`
+ // petersburg_block: Petersburg switch block (nil same as Constantinople)
+ PetersburgBlock *cosmossdk_io_math.Int `protobuf:"bytes,10,opt,name=petersburg_block,json=petersburgBlock,proto3,customtype=cosmossdk.io/math.Int" json:"petersburg_block,omitempty" yaml:"petersburg_block"`
+ // istanbul_block: Istanbul switch block (nil no fork, 0 = already on istanbul)
+ IstanbulBlock *cosmossdk_io_math.Int `protobuf:"bytes,11,opt,name=istanbul_block,json=istanbulBlock,proto3,customtype=cosmossdk.io/math.Int" json:"istanbul_block,omitempty" yaml:"istanbul_block"`
+ // muir_glacier_block: Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated)
+ MuirGlacierBlock *cosmossdk_io_math.Int `protobuf:"bytes,12,opt,name=muir_glacier_block,json=muirGlacierBlock,proto3,customtype=cosmossdk.io/math.Int" json:"muir_glacier_block,omitempty" yaml:"muir_glacier_block"`
+ // berlin_block: Berlin switch block (nil = no fork, 0 = already on berlin)
+ BerlinBlock *cosmossdk_io_math.Int `protobuf:"bytes,13,opt,name=berlin_block,json=berlinBlock,proto3,customtype=cosmossdk.io/math.Int" json:"berlin_block,omitempty" yaml:"berlin_block"`
+ // london_block: London switch block (nil = no fork, 0 = already on london)
+ LondonBlock *cosmossdk_io_math.Int `protobuf:"bytes,17,opt,name=london_block,json=londonBlock,proto3,customtype=cosmossdk.io/math.Int" json:"london_block,omitempty" yaml:"london_block"`
+ // arrow_glacier_block: Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
+ ArrowGlacierBlock *cosmossdk_io_math.Int `protobuf:"bytes,18,opt,name=arrow_glacier_block,json=arrowGlacierBlock,proto3,customtype=cosmossdk.io/math.Int" json:"arrow_glacier_block,omitempty" yaml:"arrow_glacier_block"`
+ // gray_glacier_block: EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
+ GrayGlacierBlock *cosmossdk_io_math.Int `protobuf:"bytes,20,opt,name=gray_glacier_block,json=grayGlacierBlock,proto3,customtype=cosmossdk.io/math.Int" json:"gray_glacier_block,omitempty" yaml:"gray_glacier_block"`
+ // merge_netsplit_block: Virtual fork after The Merge to use as a network splitter
+ MergeNetsplitBlock *cosmossdk_io_math.Int `protobuf:"bytes,21,opt,name=merge_netsplit_block,json=mergeNetsplitBlock,proto3,customtype=cosmossdk.io/math.Int" json:"merge_netsplit_block,omitempty" yaml:"merge_netsplit_block"`
+ // shanghai_block switch block (nil = no fork, 0 = already on shanghai)
+ ShanghaiBlock *cosmossdk_io_math.Int `protobuf:"bytes,22,opt,name=shanghai_block,json=shanghaiBlock,proto3,customtype=cosmossdk.io/math.Int" json:"shanghai_block,omitempty" yaml:"shanghai_block"`
+ // cancun_block switch block (nil = no fork, 0 = already on cancun)
+ CancunBlock *cosmossdk_io_math.Int `protobuf:"bytes,23,opt,name=cancun_block,json=cancunBlock,proto3,customtype=cosmossdk.io/math.Int" json:"cancun_block,omitempty" yaml:"cancun_block"`
+}
+
+func (m *ChainConfig) Reset() { *m = ChainConfig{} }
+func (m *ChainConfig) String() string { return proto.CompactTextString(m) }
+func (*ChainConfig) ProtoMessage() {}
+func (*ChainConfig) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{3}
+}
+
+func (m *ChainConfig) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *ChainConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ChainConfig.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *ChainConfig) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ChainConfig.Merge(m, src)
+}
+
+func (m *ChainConfig) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *ChainConfig) XXX_DiscardUnknown() {
+ xxx_messageInfo_ChainConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ChainConfig proto.InternalMessageInfo
+
+func (m *ChainConfig) GetDAOForkSupport() bool {
+ if m != nil {
+ return m.DAOForkSupport
+ }
+ return false
+}
+
+func (m *ChainConfig) GetEIP150Hash() string {
+ if m != nil {
+ return m.EIP150Hash
+ }
+ return ""
+}
+
+// State represents a single Storage key value pair item.
+type State struct {
+ // key is the stored key
+ Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // value is the stored value for the given key
+ Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *State) Reset() { *m = State{} }
+func (m *State) String() string { return proto.CompactTextString(m) }
+func (*State) ProtoMessage() {}
+func (*State) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{4}
+}
+
+func (m *State) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *State) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_State.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *State) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_State.Merge(m, src)
+}
+
+func (m *State) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *State) XXX_DiscardUnknown() {
+ xxx_messageInfo_State.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_State proto.InternalMessageInfo
+
+func (m *State) GetKey() string {
+ if m != nil {
+ return m.Key
+ }
+ return ""
+}
+
+func (m *State) GetValue() string {
+ if m != nil {
+ return m.Value
+ }
+ return ""
+}
+
+// TransactionLogs define the logs generated from a transaction execution
+// with a given hash. It it used for import/export data as transactions are not
+// persisted on blockchain state after an upgrade.
+type TransactionLogs struct {
+ // hash of the transaction
+ Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
+ // logs is an array of Logs for the given transaction hash
+ Logs []*Log `protobuf:"bytes,2,rep,name=logs,proto3" json:"logs,omitempty"`
+}
+
+func (m *TransactionLogs) Reset() { *m = TransactionLogs{} }
+func (m *TransactionLogs) String() string { return proto.CompactTextString(m) }
+func (*TransactionLogs) ProtoMessage() {}
+func (*TransactionLogs) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{5}
+}
+
+func (m *TransactionLogs) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *TransactionLogs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_TransactionLogs.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *TransactionLogs) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TransactionLogs.Merge(m, src)
+}
+
+func (m *TransactionLogs) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *TransactionLogs) XXX_DiscardUnknown() {
+ xxx_messageInfo_TransactionLogs.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TransactionLogs proto.InternalMessageInfo
+
+func (m *TransactionLogs) GetHash() string {
+ if m != nil {
+ return m.Hash
+ }
+ return ""
+}
+
+func (m *TransactionLogs) GetLogs() []*Log {
+ if m != nil {
+ return m.Logs
+ }
+ return nil
+}
+
+// Log represents an protobuf compatible Ethereum Log that defines a contract
+// log event. These events are generated by the LOG opcode and stored/indexed by
+// the node.
+//
+// NOTE: address, topics and data are consensus fields. The rest of the fields
+// are derived, i.e. filled in by the nodes, but not secured by consensus.
+type Log struct {
+ // address of the contract that generated the event
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ // topics is a list of topics provided by the contract.
+ Topics []string `protobuf:"bytes,2,rep,name=topics,proto3" json:"topics,omitempty"`
+ // data which is supplied by the contract, usually ABI-encoded
+ Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
+ // block_number of the block in which the transaction was included
+ BlockNumber uint64 `protobuf:"varint,4,opt,name=block_number,json=blockNumber,proto3" json:"blockNumber"`
+ // tx_hash is the transaction hash
+ TxHash string `protobuf:"bytes,5,opt,name=tx_hash,json=txHash,proto3" json:"transactionHash"`
+ // tx_index of the transaction in the block
+ TxIndex uint64 `protobuf:"varint,6,opt,name=tx_index,json=txIndex,proto3" json:"transactionIndex"`
+ // block_hash of the block in which the transaction was included
+ BlockHash string `protobuf:"bytes,7,opt,name=block_hash,json=blockHash,proto3" json:"blockHash"`
+ // index of the log in the block
+ Index uint64 `protobuf:"varint,8,opt,name=index,proto3" json:"logIndex"`
+ // removed is true if this log was reverted due to a chain
+ // reorganisation. You must pay attention to this field if you receive logs
+ // through a filter query.
+ Removed bool `protobuf:"varint,9,opt,name=removed,proto3" json:"removed,omitempty"`
+}
+
+func (m *Log) Reset() { *m = Log{} }
+func (m *Log) String() string { return proto.CompactTextString(m) }
+func (*Log) ProtoMessage() {}
+func (*Log) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{6}
+}
+
+func (m *Log) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *Log) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Log.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *Log) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Log.Merge(m, src)
+}
+
+func (m *Log) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *Log) XXX_DiscardUnknown() {
+ xxx_messageInfo_Log.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Log proto.InternalMessageInfo
+
+func (m *Log) GetAddress() string {
+ if m != nil {
+ return m.Address
+ }
+ return ""
+}
+
+func (m *Log) GetTopics() []string {
+ if m != nil {
+ return m.Topics
+ }
+ return nil
+}
+
+func (m *Log) GetData() []byte {
+ if m != nil {
+ return m.Data
+ }
+ return nil
+}
+
+func (m *Log) GetBlockNumber() uint64 {
+ if m != nil {
+ return m.BlockNumber
+ }
+ return 0
+}
+
+func (m *Log) GetTxHash() string {
+ if m != nil {
+ return m.TxHash
+ }
+ return ""
+}
+
+func (m *Log) GetTxIndex() uint64 {
+ if m != nil {
+ return m.TxIndex
+ }
+ return 0
+}
+
+func (m *Log) GetBlockHash() string {
+ if m != nil {
+ return m.BlockHash
+ }
+ return ""
+}
+
+func (m *Log) GetIndex() uint64 {
+ if m != nil {
+ return m.Index
+ }
+ return 0
+}
+
+func (m *Log) GetRemoved() bool {
+ if m != nil {
+ return m.Removed
+ }
+ return false
+}
+
+// TxResult stores results of Tx execution.
+type TxResult struct {
+ // contract_address contains the ethereum address of the created contract (if
+ // any). If the state transition is an evm.Call, the contract address will be
+ // empty.
+ ContractAddress string `protobuf:"bytes,1,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty" yaml:"contract_address"`
+ // bloom represents the bloom filter bytes
+ Bloom []byte `protobuf:"bytes,2,opt,name=bloom,proto3" json:"bloom,omitempty"`
+ // tx_logs contains the transaction hash and the proto-compatible ethereum
+ // logs.
+ TxLogs TransactionLogs `protobuf:"bytes,3,opt,name=tx_logs,json=txLogs,proto3" json:"tx_logs" yaml:"tx_logs"`
+ // ret defines the bytes from the execution.
+ Ret []byte `protobuf:"bytes,4,opt,name=ret,proto3" json:"ret,omitempty"`
+ // reverted flag is set to true when the call has been reverted
+ Reverted bool `protobuf:"varint,5,opt,name=reverted,proto3" json:"reverted,omitempty"`
+ // gas_used notes the amount of gas consumed while execution
+ GasUsed uint64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
+}
+
+func (m *TxResult) Reset() { *m = TxResult{} }
+func (m *TxResult) String() string { return proto.CompactTextString(m) }
+func (*TxResult) ProtoMessage() {}
+func (*TxResult) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{7}
+}
+
+func (m *TxResult) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *TxResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_TxResult.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *TxResult) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TxResult.Merge(m, src)
+}
+
+func (m *TxResult) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *TxResult) XXX_DiscardUnknown() {
+ xxx_messageInfo_TxResult.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TxResult proto.InternalMessageInfo
+
+// AccessTuple is the element type of an access list.
+type AccessTuple struct {
+ // address is a hex formatted ethereum address
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ // storage_keys are hex formatted hashes of the storage keys
+ StorageKeys []string `protobuf:"bytes,2,rep,name=storage_keys,json=storageKeys,proto3" json:"storageKeys"`
+}
+
+func (m *AccessTuple) Reset() { *m = AccessTuple{} }
+func (m *AccessTuple) String() string { return proto.CompactTextString(m) }
+func (*AccessTuple) ProtoMessage() {}
+func (*AccessTuple) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{8}
+}
+
+func (m *AccessTuple) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *AccessTuple) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_AccessTuple.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *AccessTuple) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccessTuple.Merge(m, src)
+}
+
+func (m *AccessTuple) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *AccessTuple) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccessTuple.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccessTuple proto.InternalMessageInfo
+
+// TraceConfig holds extra parameters to trace functions.
+type TraceConfig struct {
+ // tracer is a custom javascript tracer
+ Tracer string `protobuf:"bytes,1,opt,name=tracer,proto3" json:"tracer,omitempty"`
+ // timeout overrides the default timeout of 5 seconds for JavaScript-based tracing
+ // calls
+ Timeout string `protobuf:"bytes,2,opt,name=timeout,proto3" json:"timeout,omitempty"`
+ // reexec defines the number of blocks the tracer is willing to go back
+ Reexec uint64 `protobuf:"varint,3,opt,name=reexec,proto3" json:"reexec,omitempty"`
+ // disable_stack switches stack capture
+ DisableStack bool `protobuf:"varint,5,opt,name=disable_stack,json=disableStack,proto3" json:"disableStack"`
+ // disable_storage switches storage capture
+ DisableStorage bool `protobuf:"varint,6,opt,name=disable_storage,json=disableStorage,proto3" json:"disableStorage"`
+ // debug can be used to print output during capture end
+ Debug bool `protobuf:"varint,8,opt,name=debug,proto3" json:"debug,omitempty"`
+ // limit defines the maximum length of output, but zero means unlimited
+ Limit int32 `protobuf:"varint,9,opt,name=limit,proto3" json:"limit,omitempty"`
+ // overrides can be used to execute a trace using future fork rules
+ Overrides *ChainConfig `protobuf:"bytes,10,opt,name=overrides,proto3" json:"overrides,omitempty"`
+ // enable_memory switches memory capture
+ EnableMemory bool `protobuf:"varint,11,opt,name=enable_memory,json=enableMemory,proto3" json:"enableMemory"`
+ // enable_return_data switches the capture of return data
+ EnableReturnData bool `protobuf:"varint,12,opt,name=enable_return_data,json=enableReturnData,proto3" json:"enableReturnData"`
+ // tracer_json_config configures the tracer using a JSON string
+ TracerJsonConfig string `protobuf:"bytes,13,opt,name=tracer_json_config,json=tracerJsonConfig,proto3" json:"tracerConfig"`
+}
+
+func (m *TraceConfig) Reset() { *m = TraceConfig{} }
+func (m *TraceConfig) String() string { return proto.CompactTextString(m) }
+func (*TraceConfig) ProtoMessage() {}
+func (*TraceConfig) Descriptor() ([]byte, []int) {
+ return fileDescriptor_d21ecc92c8c8583e, []int{9}
+}
+
+func (m *TraceConfig) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *TraceConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_TraceConfig.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *TraceConfig) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TraceConfig.Merge(m, src)
+}
+
+func (m *TraceConfig) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *TraceConfig) XXX_DiscardUnknown() {
+ xxx_messageInfo_TraceConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TraceConfig proto.InternalMessageInfo
+
+func (m *TraceConfig) GetTracer() string {
+ if m != nil {
+ return m.Tracer
+ }
+ return ""
+}
+
+func (m *TraceConfig) GetTimeout() string {
+ if m != nil {
+ return m.Timeout
+ }
+ return ""
+}
+
+func (m *TraceConfig) GetReexec() uint64 {
+ if m != nil {
+ return m.Reexec
+ }
+ return 0
+}
+
+func (m *TraceConfig) GetDisableStack() bool {
+ if m != nil {
+ return m.DisableStack
+ }
+ return false
+}
+
+func (m *TraceConfig) GetDisableStorage() bool {
+ if m != nil {
+ return m.DisableStorage
+ }
+ return false
+}
+
+func (m *TraceConfig) GetDebug() bool {
+ if m != nil {
+ return m.Debug
+ }
+ return false
+}
+
+func (m *TraceConfig) GetLimit() int32 {
+ if m != nil {
+ return m.Limit
+ }
+ return 0
+}
+
+func (m *TraceConfig) GetOverrides() *ChainConfig {
+ if m != nil {
+ return m.Overrides
+ }
+ return nil
+}
+
+func (m *TraceConfig) GetEnableMemory() bool {
+ if m != nil {
+ return m.EnableMemory
+ }
+ return false
+}
+
+func (m *TraceConfig) GetEnableReturnData() bool {
+ if m != nil {
+ return m.EnableReturnData
+ }
+ return false
+}
+
+func (m *TraceConfig) GetTracerJsonConfig() string {
+ if m != nil {
+ return m.TracerJsonConfig
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterEnum("ethermint.evm.v1.AccessType", AccessType_name, AccessType_value)
+ proto.RegisterType((*Params)(nil), "ethermint.evm.v1.Params")
+ proto.RegisterType((*AccessControl)(nil), "ethermint.evm.v1.AccessControl")
+ proto.RegisterType((*AccessControlType)(nil), "ethermint.evm.v1.AccessControlType")
+ proto.RegisterType((*ChainConfig)(nil), "ethermint.evm.v1.ChainConfig")
+ proto.RegisterType((*State)(nil), "ethermint.evm.v1.State")
+ proto.RegisterType((*TransactionLogs)(nil), "ethermint.evm.v1.TransactionLogs")
+ proto.RegisterType((*Log)(nil), "ethermint.evm.v1.Log")
+ proto.RegisterType((*TxResult)(nil), "ethermint.evm.v1.TxResult")
+ proto.RegisterType((*AccessTuple)(nil), "ethermint.evm.v1.AccessTuple")
+ proto.RegisterType((*TraceConfig)(nil), "ethermint.evm.v1.TraceConfig")
+}
+
+func init() { proto.RegisterFile("ethermint/evm/v1/evm.proto", fileDescriptor_d21ecc92c8c8583e) }
+
+var fileDescriptor_d21ecc92c8c8583e = []byte{
+ // 1882 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0x5b, 0x6f, 0xe3, 0xc6,
+ 0x15, 0xb6, 0x6c, 0xda, 0xa6, 0x46, 0xb2, 0xc4, 0x1d, 0xcb, 0x8e, 0xa2, 0xa4, 0xa6, 0xcb, 0x16,
+ 0xc5, 0xb6, 0x48, 0xec, 0xb5, 0x37, 0x6e, 0x8d, 0xa4, 0x37, 0xcb, 0x56, 0x5a, 0xbb, 0xde, 0x8d,
+ 0x31, 0x72, 0x5a, 0xa4, 0x68, 0x40, 0x8c, 0xc8, 0x09, 0xc5, 0x98, 0xe4, 0x08, 0x9c, 0x91, 0x56,
+ 0xea, 0x2f, 0x08, 0xb6, 0x2f, 0xed, 0x0f, 0x58, 0x20, 0x40, 0xff, 0x48, 0x1f, 0x83, 0x3e, 0xe5,
+ 0xb1, 0x28, 0x50, 0xb6, 0xd0, 0xbe, 0xf9, 0xd1, 0xef, 0x05, 0x8a, 0xb9, 0xe8, 0x6a, 0xc7, 0x71,
+ 0x5f, 0xec, 0x39, 0xb7, 0xef, 0x3b, 0xe7, 0xcc, 0x21, 0x67, 0x28, 0x50, 0x23, 0xbc, 0x4d, 0xd2,
+ 0x38, 0x4c, 0xf8, 0x2e, 0xe9, 0xc5, 0xbb, 0xbd, 0x3d, 0xf1, 0x6f, 0xa7, 0x93, 0x52, 0x4e, 0xa1,
+ 0x35, 0xb6, 0xed, 0x08, 0x65, 0x6f, 0xaf, 0x56, 0x09, 0x68, 0x40, 0xa5, 0x71, 0x57, 0xac, 0x94,
+ 0x9f, 0xf3, 0xef, 0x25, 0xb0, 0x72, 0x81, 0x53, 0x1c, 0x33, 0xb8, 0x07, 0xf2, 0xa4, 0x17, 0xbb,
+ 0x3e, 0x49, 0x68, 0x5c, 0xcd, 0x6d, 0xe7, 0x1e, 0xe7, 0xeb, 0x95, 0x9b, 0xcc, 0xb6, 0x06, 0x38,
+ 0x8e, 0xde, 0x77, 0xc6, 0x26, 0x07, 0x99, 0xa4, 0x17, 0x9f, 0x88, 0x25, 0x3c, 0x02, 0x80, 0xf4,
+ 0x79, 0x8a, 0x5d, 0x12, 0x76, 0x58, 0xd5, 0xd8, 0x5e, 0x7a, 0x9c, 0xaf, 0x3b, 0xc3, 0xcc, 0xce,
+ 0x37, 0x84, 0xb6, 0x71, 0x7a, 0xc1, 0x6e, 0x32, 0xfb, 0x91, 0x06, 0x18, 0x3b, 0x3a, 0x28, 0x2f,
+ 0x85, 0x46, 0xd8, 0x61, 0xf0, 0x53, 0x50, 0xf4, 0xda, 0x38, 0x4c, 0x5c, 0x8f, 0x26, 0x9f, 0x85,
+ 0x41, 0x75, 0x79, 0x3b, 0xf7, 0xb8, 0xb0, 0xff, 0x9d, 0x9d, 0xf9, 0xfc, 0x77, 0x8e, 0x85, 0xd7,
+ 0xb1, 0x74, 0xaa, 0xbf, 0xf5, 0x55, 0x66, 0x2f, 0xdc, 0x64, 0xf6, 0xba, 0x82, 0x9e, 0x06, 0x70,
+ 0x50, 0xc1, 0x9b, 0x78, 0xc2, 0x7d, 0xb0, 0x81, 0xa3, 0x88, 0xbe, 0x70, 0xbb, 0x89, 0x28, 0x98,
+ 0x78, 0x9c, 0xf8, 0x2e, 0xef, 0xb3, 0xea, 0xca, 0x76, 0xee, 0xb1, 0x89, 0xd6, 0xa5, 0xf1, 0xe3,
+ 0x89, 0xed, 0xb2, 0xcf, 0xe0, 0xbb, 0x00, 0x62, 0x8f, 0x87, 0x3d, 0xe2, 0x76, 0x52, 0xe2, 0xd1,
+ 0xb8, 0x13, 0x46, 0x84, 0x55, 0x57, 0x45, 0x75, 0xe8, 0x91, 0xb2, 0x5c, 0x4c, 0x0c, 0x70, 0x1f,
+ 0x14, 0x45, 0x73, 0xbc, 0x36, 0x4e, 0x12, 0x12, 0xb1, 0xaa, 0x29, 0xdb, 0x50, 0x1e, 0x66, 0x76,
+ 0xa1, 0xf1, 0xdb, 0x67, 0xc7, 0x5a, 0x8d, 0x0a, 0xa4, 0x17, 0x8f, 0x04, 0xf8, 0x29, 0x28, 0x61,
+ 0xcf, 0x23, 0x8c, 0x89, 0xac, 0x79, 0x4a, 0xa3, 0x6a, 0x5e, 0xd6, 0x6d, 0xdf, 0xae, 0xfb, 0x48,
+ 0xfa, 0x1d, 0x2b, 0xb7, 0xfa, 0x86, 0xa8, 0x7c, 0x98, 0xd9, 0x6b, 0x33, 0x6a, 0xb4, 0x86, 0xa7,
+ 0xc5, 0x33, 0xc3, 0x5c, 0xb4, 0x96, 0xce, 0x0c, 0x73, 0xc9, 0x32, 0x9c, 0xbf, 0xe4, 0xc0, 0xac,
+ 0x33, 0x3c, 0x02, 0x2b, 0x5e, 0x4a, 0x30, 0x27, 0x72, 0x97, 0x0b, 0xfb, 0xdf, 0xfb, 0x16, 0xd2,
+ 0xcb, 0x41, 0x87, 0xd4, 0x0d, 0x41, 0x8c, 0x74, 0x20, 0xfc, 0x19, 0x30, 0x3c, 0x1c, 0x45, 0xd5,
+ 0xc5, 0xff, 0x17, 0x40, 0x86, 0x39, 0xff, 0xca, 0x81, 0x47, 0xb7, 0x3c, 0xa0, 0x07, 0x0a, 0xba,
+ 0x29, 0x7c, 0xd0, 0x51, 0xc9, 0x95, 0xf6, 0xdf, 0xfe, 0x26, 0x6c, 0x09, 0xfa, 0xfd, 0x61, 0x66,
+ 0x83, 0x89, 0x7c, 0x93, 0xd9, 0x50, 0x8d, 0xc4, 0x14, 0x90, 0x83, 0x00, 0x1e, 0x7b, 0x40, 0x0f,
+ 0xac, 0xcf, 0x76, 0xde, 0x8d, 0x42, 0xc6, 0xab, 0x8b, 0x72, 0xd3, 0x9e, 0x0e, 0x33, 0x7b, 0x36,
+ 0xb1, 0xf3, 0x90, 0xf1, 0x9b, 0xcc, 0xae, 0xcd, 0xa0, 0x4e, 0x47, 0x3a, 0x62, 0x24, 0xe6, 0x02,
+ 0x9c, 0xff, 0x96, 0x40, 0x61, 0x6a, 0x5e, 0xe1, 0x1f, 0x40, 0xb9, 0x4d, 0x63, 0xc2, 0x38, 0xc1,
+ 0xbe, 0xdb, 0x8a, 0xa8, 0x77, 0xa5, 0x1f, 0xb0, 0xa7, 0xff, 0xcc, 0xec, 0x0d, 0x8f, 0xb2, 0x98,
+ 0x32, 0xe6, 0x5f, 0xed, 0x84, 0x74, 0x37, 0xc6, 0xbc, 0xbd, 0x73, 0x9a, 0x08, 0xd2, 0x4d, 0x45,
+ 0x3a, 0x17, 0xe9, 0xa0, 0xd2, 0x58, 0x53, 0x17, 0x0a, 0xd8, 0x06, 0x25, 0x1f, 0x53, 0xf7, 0x33,
+ 0x9a, 0x5e, 0x69, 0xf0, 0x45, 0x09, 0x5e, 0xff, 0x46, 0xf0, 0x61, 0x66, 0x17, 0x4f, 0x8e, 0x3e,
+ 0xfa, 0x90, 0xa6, 0x57, 0x12, 0xe2, 0x26, 0xb3, 0x37, 0x14, 0xd9, 0x2c, 0x90, 0x83, 0x8a, 0x3e,
+ 0xa6, 0x63, 0x37, 0xf8, 0x3b, 0x60, 0x8d, 0x1d, 0x58, 0xb7, 0xd3, 0xa1, 0x29, 0xaf, 0x2e, 0x89,
+ 0x07, 0xa9, 0xfe, 0xee, 0x30, 0xb3, 0x4b, 0x1a, 0xb2, 0xa9, 0x2c, 0x37, 0x99, 0xfd, 0xc6, 0x1c,
+ 0xa8, 0x8e, 0x71, 0x50, 0x49, 0xc3, 0x6a, 0x57, 0xd8, 0x02, 0x45, 0x12, 0x76, 0xf6, 0x0e, 0x9e,
+ 0xe8, 0x02, 0x0c, 0x59, 0xc0, 0x2f, 0xee, 0x2b, 0xa0, 0xd0, 0x38, 0xbd, 0xd8, 0x3b, 0x78, 0x32,
+ 0xca, 0x5f, 0xbf, 0x0a, 0xa6, 0x51, 0x1c, 0x54, 0x50, 0xa2, 0x4a, 0xfe, 0x14, 0x68, 0xd1, 0x6d,
+ 0x63, 0xd6, 0x96, 0x2f, 0x9a, 0x7c, 0xfd, 0xb1, 0x18, 0x20, 0x85, 0xf4, 0x6b, 0xcc, 0xda, 0x93,
+ 0xae, 0xb7, 0x06, 0x7f, 0xc4, 0x09, 0x0f, 0xbb, 0xf1, 0x08, 0x0b, 0xa8, 0x60, 0xe1, 0x35, 0x4e,
+ 0xf7, 0x40, 0xa7, 0xbb, 0xf2, 0xd0, 0x74, 0x0f, 0xee, 0x4a, 0xf7, 0x60, 0x36, 0x5d, 0xe5, 0x33,
+ 0xe6, 0x38, 0xd4, 0x1c, 0xab, 0x0f, 0xe5, 0x38, 0xbc, 0x8b, 0xe3, 0x70, 0x96, 0x43, 0xf9, 0x88,
+ 0xb9, 0x9c, 0xab, 0xb3, 0x6a, 0x3e, 0x78, 0x2e, 0x6f, 0x75, 0xa8, 0x34, 0xd6, 0x28, 0xf4, 0x2b,
+ 0x50, 0xf1, 0x68, 0xc2, 0xb8, 0xd0, 0x25, 0xb4, 0x13, 0x11, 0x4d, 0x91, 0x97, 0x14, 0x87, 0xf7,
+ 0x51, 0xbc, 0xa5, 0x5f, 0xec, 0x77, 0x84, 0x3b, 0x68, 0x7d, 0x56, 0xad, 0xc8, 0x5c, 0x60, 0x75,
+ 0x08, 0x27, 0x29, 0x6b, 0x75, 0xd3, 0x40, 0x13, 0x01, 0x49, 0xf4, 0xde, 0x7d, 0x44, 0x7a, 0x42,
+ 0xe7, 0x43, 0x1d, 0x54, 0x9e, 0xa8, 0x14, 0xc1, 0x27, 0xa0, 0x14, 0x0a, 0xd6, 0x56, 0x37, 0xd2,
+ 0xf0, 0x05, 0x09, 0xbf, 0x7f, 0x1f, 0xbc, 0x7e, 0xaa, 0x66, 0x03, 0x1d, 0xb4, 0x36, 0x52, 0x28,
+ 0x68, 0x1f, 0xc0, 0xb8, 0x1b, 0xa6, 0x6e, 0x10, 0x61, 0x2f, 0x24, 0xa9, 0x86, 0x2f, 0x4a, 0xf8,
+ 0x1f, 0xdf, 0x07, 0xff, 0xa6, 0x82, 0xbf, 0x1d, 0xec, 0x20, 0x4b, 0x28, 0x7f, 0xa5, 0x74, 0x8a,
+ 0xa5, 0x09, 0x8a, 0x2d, 0x92, 0x46, 0x61, 0xa2, 0xf1, 0xd7, 0x24, 0xfe, 0x93, 0xfb, 0xf0, 0xf5,
+ 0x04, 0x4d, 0x87, 0x39, 0xa8, 0xa0, 0xc4, 0x31, 0x68, 0x44, 0x13, 0x9f, 0x8e, 0x40, 0x1f, 0x3d,
+ 0x18, 0x74, 0x3a, 0xcc, 0x41, 0x05, 0x25, 0x2a, 0xd0, 0x00, 0xac, 0xe3, 0x34, 0xa5, 0x2f, 0xe6,
+ 0x1a, 0x02, 0x25, 0xf6, 0x4f, 0xee, 0xc3, 0x1e, 0xbd, 0xa7, 0x6f, 0x47, 0x8b, 0xf7, 0xb4, 0xd0,
+ 0xce, 0xb4, 0xc4, 0x07, 0x30, 0x48, 0xf1, 0x60, 0x8e, 0xa7, 0xf2, 0xe0, 0xc6, 0xdf, 0x0e, 0x76,
+ 0x90, 0x25, 0x94, 0x33, 0x2c, 0x9f, 0x83, 0x4a, 0x4c, 0xd2, 0x80, 0xb8, 0x09, 0xe1, 0xac, 0x13,
+ 0x85, 0x5c, 0xf3, 0x6c, 0x3c, 0xf8, 0x39, 0xb8, 0x2b, 0xdc, 0x41, 0x50, 0xaa, 0x9f, 0x6b, 0xed,
+ 0x78, 0x4a, 0x59, 0x1b, 0x27, 0x41, 0x1b, 0x87, 0x9a, 0x65, 0xf3, 0xc1, 0x53, 0x3a, 0x1b, 0xe8,
+ 0xa0, 0xb5, 0x91, 0x62, 0xbc, 0xd5, 0x1e, 0x4e, 0xbc, 0xee, 0x68, 0xab, 0xdf, 0x78, 0xf0, 0x56,
+ 0x4f, 0x87, 0x89, 0xfb, 0x99, 0x14, 0x25, 0xe8, 0x99, 0x61, 0x96, 0xac, 0xf2, 0x99, 0x61, 0x96,
+ 0x2d, 0xeb, 0xcc, 0x30, 0x2d, 0xeb, 0xd1, 0x99, 0x61, 0xae, 0x5b, 0x15, 0xb4, 0x36, 0xa0, 0x11,
+ 0x75, 0x7b, 0x4f, 0x55, 0x10, 0x2a, 0x90, 0x17, 0x98, 0xe9, 0x17, 0x0d, 0x2a, 0x79, 0x98, 0xe3,
+ 0x68, 0xc0, 0x74, 0x23, 0x90, 0xa5, 0xda, 0x33, 0x75, 0x6c, 0xed, 0x82, 0xe5, 0x26, 0x17, 0xf7,
+ 0x14, 0x0b, 0x2c, 0x5d, 0x91, 0x81, 0x3a, 0x6c, 0x91, 0x58, 0xc2, 0x0a, 0x58, 0xee, 0xe1, 0xa8,
+ 0x4b, 0xd4, 0x19, 0x89, 0x94, 0xe0, 0x5c, 0x80, 0xf2, 0x65, 0x8a, 0x13, 0x26, 0x6e, 0x77, 0x34,
+ 0x39, 0xa7, 0x01, 0x83, 0x10, 0x18, 0xf2, 0x9c, 0x50, 0xb1, 0x72, 0x0d, 0x7f, 0x08, 0x8c, 0x88,
+ 0x06, 0x4c, 0xde, 0x16, 0x0a, 0xfb, 0x1b, 0xb7, 0xaf, 0x26, 0xe7, 0x34, 0x40, 0xd2, 0xc5, 0xf9,
+ 0xfb, 0x22, 0x58, 0x3a, 0xa7, 0x01, 0xac, 0x82, 0x55, 0xec, 0xfb, 0x29, 0x61, 0x4c, 0x23, 0x8d,
+ 0x44, 0xb8, 0x09, 0x56, 0x38, 0xed, 0x84, 0x9e, 0x82, 0xcb, 0x23, 0x2d, 0x09, 0x62, 0x1f, 0x73,
+ 0x2c, 0x0f, 0xd6, 0x22, 0x92, 0x6b, 0x71, 0xc7, 0x94, 0x95, 0xb9, 0x49, 0x37, 0x6e, 0x91, 0x54,
+ 0x9e, 0x8f, 0x46, 0xbd, 0x7c, 0x9d, 0xd9, 0x05, 0xa9, 0x7f, 0x2e, 0xd5, 0x68, 0x5a, 0x80, 0xef,
+ 0x80, 0x55, 0xde, 0x9f, 0x3e, 0xeb, 0xd6, 0xaf, 0x33, 0xbb, 0xcc, 0x27, 0x65, 0x8a, 0xa3, 0x0c,
+ 0xad, 0xf0, 0xbe, 0x3c, 0xd2, 0x76, 0x81, 0xc9, 0xfb, 0x6e, 0x98, 0xf8, 0xa4, 0x2f, 0x8f, 0x33,
+ 0xa3, 0x5e, 0xb9, 0xce, 0x6c, 0x6b, 0xca, 0xfd, 0x54, 0xd8, 0xd0, 0x2a, 0xef, 0xcb, 0x05, 0x7c,
+ 0x07, 0x00, 0x95, 0x92, 0x64, 0x50, 0xa7, 0xd3, 0xda, 0x75, 0x66, 0xe7, 0xa5, 0x56, 0x62, 0x4f,
+ 0x96, 0xd0, 0x01, 0xcb, 0x0a, 0xdb, 0x94, 0xd8, 0xc5, 0xeb, 0xcc, 0x36, 0x23, 0x1a, 0x28, 0x4c,
+ 0x65, 0x12, 0xad, 0x4a, 0x49, 0x4c, 0x7b, 0xc4, 0x97, 0x47, 0x84, 0x89, 0x46, 0xa2, 0xf3, 0xa7,
+ 0x45, 0x60, 0x5e, 0xf6, 0x11, 0x61, 0xdd, 0x88, 0xc3, 0x0f, 0x81, 0x25, 0x2f, 0x60, 0xd8, 0xe3,
+ 0xee, 0x4c, 0x6b, 0xeb, 0x6f, 0x4d, 0x5e, 0xe8, 0xf3, 0x1e, 0x0e, 0x2a, 0x8f, 0x54, 0x47, 0xba,
+ 0xff, 0x15, 0xb0, 0xdc, 0x8a, 0x28, 0x8d, 0xe5, 0x24, 0x14, 0x91, 0x12, 0x20, 0x92, 0x5d, 0x93,
+ 0xbb, 0xbc, 0x24, 0x2f, 0xb7, 0xdf, 0xbd, 0xbd, 0xcb, 0x73, 0xa3, 0x52, 0xdf, 0xd4, 0x9f, 0x23,
+ 0x25, 0xc5, 0xad, 0xe3, 0x1d, 0xd1, 0x5b, 0x39, 0x4a, 0x16, 0x58, 0x4a, 0x09, 0x97, 0x9b, 0x56,
+ 0x44, 0x62, 0x09, 0x6b, 0xc0, 0x4c, 0x49, 0x8f, 0xa4, 0x9c, 0xf8, 0x72, 0x73, 0x4c, 0x34, 0x96,
+ 0xe1, 0x9b, 0xc0, 0x0c, 0x30, 0x73, 0xbb, 0x8c, 0xf8, 0x6a, 0x27, 0xd0, 0x6a, 0x80, 0xd9, 0xc7,
+ 0x8c, 0xf8, 0xef, 0x1b, 0x5f, 0x7c, 0x69, 0x2f, 0x38, 0x18, 0x14, 0xf4, 0x95, 0xb7, 0xdb, 0x89,
+ 0xc8, 0x3d, 0x13, 0xb6, 0x0f, 0x8a, 0x8c, 0xd3, 0x14, 0x07, 0xc4, 0xbd, 0x22, 0x03, 0x3d, 0x67,
+ 0x6a, 0x6a, 0xb4, 0xfe, 0x37, 0x64, 0xc0, 0xd0, 0xb4, 0xa0, 0x29, 0xbe, 0x34, 0x40, 0xe1, 0x32,
+ 0xc5, 0x1e, 0xd1, 0x17, 0x58, 0x31, 0xab, 0x42, 0x4c, 0x35, 0x85, 0x96, 0x04, 0x37, 0x0f, 0x63,
+ 0x42, 0xbb, 0x5c, 0x3f, 0x4f, 0x23, 0x51, 0x44, 0xa4, 0x84, 0xf4, 0x89, 0x27, 0xdb, 0x68, 0x20,
+ 0x2d, 0xc1, 0x03, 0xb0, 0xe6, 0x87, 0x0c, 0xb7, 0x22, 0xe2, 0x32, 0x8e, 0xbd, 0x2b, 0x55, 0x7e,
+ 0xdd, 0xba, 0xce, 0xec, 0xa2, 0x36, 0x34, 0x85, 0x1e, 0xcd, 0x48, 0xf0, 0x03, 0x50, 0x9e, 0x84,
+ 0xc9, 0x6c, 0xd5, 0x17, 0x5c, 0x1d, 0x5e, 0x67, 0x76, 0x69, 0xec, 0x2a, 0x2d, 0x68, 0x4e, 0x16,
+ 0x3b, 0xed, 0x93, 0x56, 0x37, 0x90, 0xc3, 0x67, 0x22, 0x25, 0x08, 0x6d, 0x14, 0xc6, 0x21, 0x97,
+ 0xc3, 0xb6, 0x8c, 0x94, 0x00, 0x3f, 0x00, 0x79, 0xda, 0x23, 0x69, 0x1a, 0xfa, 0x84, 0xc9, 0x0b,
+ 0xc4, 0xb7, 0x7d, 0x8c, 0xa2, 0x89, 0xbf, 0x28, 0x8e, 0x24, 0x32, 0xc9, 0x98, 0xc4, 0x34, 0x1d,
+ 0xc8, 0x2b, 0x82, 0x2e, 0x4e, 0x19, 0x9e, 0x49, 0x3d, 0x9a, 0x91, 0x60, 0x1d, 0x40, 0x1d, 0x96,
+ 0x12, 0xde, 0x4d, 0x13, 0x57, 0x3e, 0xff, 0x45, 0x19, 0x2b, 0x9f, 0x42, 0x65, 0x45, 0xd2, 0x78,
+ 0x82, 0x39, 0x46, 0xb7, 0x34, 0xf0, 0xe7, 0x00, 0xaa, 0x3d, 0x71, 0x3f, 0x67, 0x74, 0xfc, 0x35,
+ 0xad, 0xce, 0x78, 0xc9, 0xaf, 0xac, 0x3a, 0x67, 0x4b, 0x49, 0x67, 0x8c, 0xea, 0x2a, 0xce, 0x0c,
+ 0xd3, 0xb0, 0x96, 0xcf, 0x0c, 0x73, 0xd5, 0x32, 0xc7, 0xfd, 0xd3, 0x55, 0xa0, 0xf5, 0x91, 0x3c,
+ 0x95, 0xde, 0x8f, 0xfe, 0x96, 0x03, 0x53, 0x5f, 0x5e, 0xf0, 0xa7, 0xa0, 0x76, 0x74, 0x7c, 0xdc,
+ 0x68, 0x36, 0xdd, 0xcb, 0x4f, 0x2e, 0x1a, 0xee, 0x45, 0x03, 0x3d, 0x3b, 0x6d, 0x36, 0x4f, 0x3f,
+ 0x7a, 0x7e, 0xde, 0x68, 0x36, 0xad, 0x85, 0xda, 0xdb, 0x2f, 0x5f, 0x6d, 0x57, 0x27, 0xfe, 0x17,
+ 0xa2, 0x9f, 0x8c, 0x85, 0x34, 0x89, 0xc4, 0xa4, 0xbe, 0x07, 0x36, 0xa7, 0xa3, 0x51, 0xa3, 0x79,
+ 0x89, 0x4e, 0x8f, 0x2f, 0x1b, 0x27, 0x56, 0xae, 0x56, 0x7d, 0xf9, 0x6a, 0xbb, 0x32, 0x89, 0x44,
+ 0x84, 0xf1, 0x34, 0x14, 0xdf, 0xea, 0xf0, 0x10, 0x54, 0xef, 0xe6, 0x6c, 0x9c, 0x58, 0x8b, 0xb5,
+ 0xda, 0xcb, 0x57, 0xdb, 0x9b, 0x77, 0x31, 0x12, 0xbf, 0x66, 0x7c, 0xf1, 0xd7, 0xad, 0x85, 0xfa,
+ 0x2f, 0xbf, 0x1a, 0x6e, 0xe5, 0xbe, 0x1e, 0x6e, 0xe5, 0xfe, 0x33, 0xdc, 0xca, 0xfd, 0xf9, 0xf5,
+ 0xd6, 0xc2, 0xd7, 0xaf, 0xb7, 0x16, 0xfe, 0xf1, 0x7a, 0x6b, 0xe1, 0xf7, 0x3f, 0x08, 0x42, 0xde,
+ 0xee, 0xb6, 0x76, 0x3c, 0x1a, 0xef, 0x92, 0x5e, 0x4c, 0x99, 0xfe, 0xdb, 0xdb, 0x3b, 0xdc, 0xed,
+ 0xcb, 0x5f, 0x5b, 0xc4, 0x97, 0x25, 0x6b, 0xad, 0xc8, 0x5f, 0x51, 0x9e, 0xfe, 0x2f, 0x00, 0x00,
+ 0xff, 0xff, 0x92, 0x17, 0x5a, 0x71, 0x8b, 0x11, 0x00, 0x00,
+}
+
+func (m *Params) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Params) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ActiveStaticPrecompiles) > 0 {
+ for iNdEx := len(m.ActiveStaticPrecompiles) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.ActiveStaticPrecompiles[iNdEx])
+ copy(dAtA[i:], m.ActiveStaticPrecompiles[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.ActiveStaticPrecompiles[iNdEx])))
+ i--
+ dAtA[i] = 0x52
+ }
+ }
+ {
+ size, err := m.AccessControl.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x4a
+ if len(m.EVMChannels) > 0 {
+ for iNdEx := len(m.EVMChannels) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.EVMChannels[iNdEx])
+ copy(dAtA[i:], m.EVMChannels[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.EVMChannels[iNdEx])))
+ i--
+ dAtA[i] = 0x42
+ }
+ }
+ if m.AllowUnprotectedTxs {
+ i--
+ if m.AllowUnprotectedTxs {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x30
+ }
+ {
+ size, err := m.ChainConfig.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x2a
+ if len(m.ExtraEIPs) > 0 {
+ for iNdEx := len(m.ExtraEIPs) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.ExtraEIPs[iNdEx])
+ copy(dAtA[i:], m.ExtraEIPs[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.ExtraEIPs[iNdEx])))
+ i--
+ dAtA[i] = 0x22
+ }
+ }
+ if len(m.EvmDenom) > 0 {
+ i -= len(m.EvmDenom)
+ copy(dAtA[i:], m.EvmDenom)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.EvmDenom)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *AccessControl) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AccessControl) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *AccessControl) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Call.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ {
+ size, err := m.Create.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+}
+
+func (m *AccessControlType) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AccessControlType) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *AccessControlType) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.AccessControlList) > 0 {
+ for iNdEx := len(m.AccessControlList) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.AccessControlList[iNdEx])
+ copy(dAtA[i:], m.AccessControlList[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.AccessControlList[iNdEx])))
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if m.AccessType != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.AccessType))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ChainConfig) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ChainConfig) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ChainConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.CancunBlock != nil {
+ {
+ size := m.CancunBlock.Size()
+ i -= size
+ if _, err := m.CancunBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xba
+ }
+ if m.ShanghaiBlock != nil {
+ {
+ size := m.ShanghaiBlock.Size()
+ i -= size
+ if _, err := m.ShanghaiBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xb2
+ }
+ if m.MergeNetsplitBlock != nil {
+ {
+ size := m.MergeNetsplitBlock.Size()
+ i -= size
+ if _, err := m.MergeNetsplitBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xaa
+ }
+ if m.GrayGlacierBlock != nil {
+ {
+ size := m.GrayGlacierBlock.Size()
+ i -= size
+ if _, err := m.GrayGlacierBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0xa2
+ }
+ if m.ArrowGlacierBlock != nil {
+ {
+ size := m.ArrowGlacierBlock.Size()
+ i -= size
+ if _, err := m.ArrowGlacierBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x92
+ }
+ if m.LondonBlock != nil {
+ {
+ size := m.LondonBlock.Size()
+ i -= size
+ if _, err := m.LondonBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x8a
+ }
+ if m.BerlinBlock != nil {
+ {
+ size := m.BerlinBlock.Size()
+ i -= size
+ if _, err := m.BerlinBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x6a
+ }
+ if m.MuirGlacierBlock != nil {
+ {
+ size := m.MuirGlacierBlock.Size()
+ i -= size
+ if _, err := m.MuirGlacierBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x62
+ }
+ if m.IstanbulBlock != nil {
+ {
+ size := m.IstanbulBlock.Size()
+ i -= size
+ if _, err := m.IstanbulBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x5a
+ }
+ if m.PetersburgBlock != nil {
+ {
+ size := m.PetersburgBlock.Size()
+ i -= size
+ if _, err := m.PetersburgBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x52
+ }
+ if m.ConstantinopleBlock != nil {
+ {
+ size := m.ConstantinopleBlock.Size()
+ i -= size
+ if _, err := m.ConstantinopleBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x4a
+ }
+ if m.ByzantiumBlock != nil {
+ {
+ size := m.ByzantiumBlock.Size()
+ i -= size
+ if _, err := m.ByzantiumBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x42
+ }
+ if m.EIP158Block != nil {
+ {
+ size := m.EIP158Block.Size()
+ i -= size
+ if _, err := m.EIP158Block.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x3a
+ }
+ if m.EIP155Block != nil {
+ {
+ size := m.EIP155Block.Size()
+ i -= size
+ if _, err := m.EIP155Block.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x32
+ }
+ if len(m.EIP150Hash) > 0 {
+ i -= len(m.EIP150Hash)
+ copy(dAtA[i:], m.EIP150Hash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.EIP150Hash)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if m.EIP150Block != nil {
+ {
+ size := m.EIP150Block.Size()
+ i -= size
+ if _, err := m.EIP150Block.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x22
+ }
+ if m.DAOForkSupport {
+ i--
+ if m.DAOForkSupport {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.DAOForkBlock != nil {
+ {
+ size := m.DAOForkBlock.Size()
+ i -= size
+ if _, err := m.DAOForkBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.HomesteadBlock != nil {
+ {
+ size := m.HomesteadBlock.Size()
+ i -= size
+ if _, err := m.HomesteadBlock.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *State) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *State) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *State) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Value) > 0 {
+ i -= len(m.Value)
+ copy(dAtA[i:], m.Value)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Value)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Key) > 0 {
+ i -= len(m.Key)
+ copy(dAtA[i:], m.Key)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Key)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *TransactionLogs) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *TransactionLogs) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *TransactionLogs) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Logs) > 0 {
+ for iNdEx := len(m.Logs) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Logs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if len(m.Hash) > 0 {
+ i -= len(m.Hash)
+ copy(dAtA[i:], m.Hash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Hash)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *Log) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Log) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Log) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Removed {
+ i--
+ if m.Removed {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x48
+ }
+ if m.Index != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.Index))
+ i--
+ dAtA[i] = 0x40
+ }
+ if len(m.BlockHash) > 0 {
+ i -= len(m.BlockHash)
+ copy(dAtA[i:], m.BlockHash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.BlockHash)))
+ i--
+ dAtA[i] = 0x3a
+ }
+ if m.TxIndex != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.TxIndex))
+ i--
+ dAtA[i] = 0x30
+ }
+ if len(m.TxHash) > 0 {
+ i -= len(m.TxHash)
+ copy(dAtA[i:], m.TxHash)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.TxHash)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if m.BlockNumber != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.BlockNumber))
+ i--
+ dAtA[i] = 0x20
+ }
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Topics) > 0 {
+ for iNdEx := len(m.Topics) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.Topics[iNdEx])
+ copy(dAtA[i:], m.Topics[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Topics[iNdEx])))
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *TxResult) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *TxResult) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *TxResult) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.GasUsed != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.GasUsed))
+ i--
+ dAtA[i] = 0x30
+ }
+ if m.Reverted {
+ i--
+ if m.Reverted {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x28
+ }
+ if len(m.Ret) > 0 {
+ i -= len(m.Ret)
+ copy(dAtA[i:], m.Ret)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Ret)))
+ i--
+ dAtA[i] = 0x22
+ }
+ {
+ size, err := m.TxLogs.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ if len(m.Bloom) > 0 {
+ i -= len(m.Bloom)
+ copy(dAtA[i:], m.Bloom)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Bloom)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.ContractAddress) > 0 {
+ i -= len(m.ContractAddress)
+ copy(dAtA[i:], m.ContractAddress)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.ContractAddress)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *AccessTuple) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AccessTuple) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *AccessTuple) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.StorageKeys) > 0 {
+ for iNdEx := len(m.StorageKeys) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.StorageKeys[iNdEx])
+ copy(dAtA[i:], m.StorageKeys[iNdEx])
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.StorageKeys[iNdEx])))
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *TraceConfig) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *TraceConfig) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *TraceConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.TracerJsonConfig) > 0 {
+ i -= len(m.TracerJsonConfig)
+ copy(dAtA[i:], m.TracerJsonConfig)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.TracerJsonConfig)))
+ i--
+ dAtA[i] = 0x6a
+ }
+ if m.EnableReturnData {
+ i--
+ if m.EnableReturnData {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x60
+ }
+ if m.EnableMemory {
+ i--
+ if m.EnableMemory {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x58
+ }
+ if m.Overrides != nil {
+ {
+ size, err := m.Overrides.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintEvm(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x52
+ }
+ if m.Limit != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.Limit))
+ i--
+ dAtA[i] = 0x48
+ }
+ if m.Debug {
+ i--
+ if m.Debug {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x40
+ }
+ if m.DisableStorage {
+ i--
+ if m.DisableStorage {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x30
+ }
+ if m.DisableStack {
+ i--
+ if m.DisableStack {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x28
+ }
+ if m.Reexec != 0 {
+ i = encodeVarintEvm(dAtA, i, uint64(m.Reexec))
+ i--
+ dAtA[i] = 0x18
+ }
+ if len(m.Timeout) > 0 {
+ i -= len(m.Timeout)
+ copy(dAtA[i:], m.Timeout)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Timeout)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Tracer) > 0 {
+ i -= len(m.Tracer)
+ copy(dAtA[i:], m.Tracer)
+ i = encodeVarintEvm(dAtA, i, uint64(len(m.Tracer)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintEvm(dAtA []byte, offset int, v uint64) int {
+ offset -= sovEvm(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+
+func (m *Params) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.EvmDenom)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.ExtraEIPs) > 0 {
+ for _, s := range m.ExtraEIPs {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ l = m.ChainConfig.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ if m.AllowUnprotectedTxs {
+ n += 2
+ }
+ if len(m.EVMChannels) > 0 {
+ for _, s := range m.EVMChannels {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ l = m.AccessControl.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ if len(m.ActiveStaticPrecompiles) > 0 {
+ for _, s := range m.ActiveStaticPrecompiles {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *AccessControl) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = m.Create.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ l = m.Call.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ return n
+}
+
+func (m *AccessControlType) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.AccessType != 0 {
+ n += 1 + sovEvm(uint64(m.AccessType))
+ }
+ if len(m.AccessControlList) > 0 {
+ for _, s := range m.AccessControlList {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *ChainConfig) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.HomesteadBlock != nil {
+ l = m.HomesteadBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.DAOForkBlock != nil {
+ l = m.DAOForkBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.DAOForkSupport {
+ n += 2
+ }
+ if m.EIP150Block != nil {
+ l = m.EIP150Block.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.EIP150Hash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.EIP155Block != nil {
+ l = m.EIP155Block.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.EIP158Block != nil {
+ l = m.EIP158Block.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.ByzantiumBlock != nil {
+ l = m.ByzantiumBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.ConstantinopleBlock != nil {
+ l = m.ConstantinopleBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.PetersburgBlock != nil {
+ l = m.PetersburgBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.IstanbulBlock != nil {
+ l = m.IstanbulBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.MuirGlacierBlock != nil {
+ l = m.MuirGlacierBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.BerlinBlock != nil {
+ l = m.BerlinBlock.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.LondonBlock != nil {
+ l = m.LondonBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.ArrowGlacierBlock != nil {
+ l = m.ArrowGlacierBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.GrayGlacierBlock != nil {
+ l = m.GrayGlacierBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.MergeNetsplitBlock != nil {
+ l = m.MergeNetsplitBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.ShanghaiBlock != nil {
+ l = m.ShanghaiBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ if m.CancunBlock != nil {
+ l = m.CancunBlock.Size()
+ n += 2 + l + sovEvm(uint64(l))
+ }
+ return n
+}
+
+func (m *State) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ return n
+}
+
+func (m *TransactionLogs) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Hash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.Logs) > 0 {
+ for _, e := range m.Logs {
+ l = e.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *Log) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.Topics) > 0 {
+ for _, s := range m.Topics {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.BlockNumber != 0 {
+ n += 1 + sovEvm(uint64(m.BlockNumber))
+ }
+ l = len(m.TxHash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.TxIndex != 0 {
+ n += 1 + sovEvm(uint64(m.TxIndex))
+ }
+ l = len(m.BlockHash)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.Index != 0 {
+ n += 1 + sovEvm(uint64(m.Index))
+ }
+ if m.Removed {
+ n += 2
+ }
+ return n
+}
+
+func (m *TxResult) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ContractAddress)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.Bloom)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = m.TxLogs.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ l = len(m.Ret)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.Reverted {
+ n += 2
+ }
+ if m.GasUsed != 0 {
+ n += 1 + sovEvm(uint64(m.GasUsed))
+ }
+ return n
+}
+
+func (m *AccessTuple) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if len(m.StorageKeys) > 0 {
+ for _, s := range m.StorageKeys {
+ l = len(s)
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *TraceConfig) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Tracer)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ l = len(m.Timeout)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.Reexec != 0 {
+ n += 1 + sovEvm(uint64(m.Reexec))
+ }
+ if m.DisableStack {
+ n += 2
+ }
+ if m.DisableStorage {
+ n += 2
+ }
+ if m.Debug {
+ n += 2
+ }
+ if m.Limit != 0 {
+ n += 1 + sovEvm(uint64(m.Limit))
+ }
+ if m.Overrides != nil {
+ l = m.Overrides.Size()
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ if m.EnableMemory {
+ n += 2
+ }
+ if m.EnableReturnData {
+ n += 2
+ }
+ l = len(m.TracerJsonConfig)
+ if l > 0 {
+ n += 1 + l + sovEvm(uint64(l))
+ }
+ return n
+}
+
+func sovEvm(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+
+func sozEvm(x uint64) (n int) {
+ return sovEvm(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+func (m *Params) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Params: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EvmDenom", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EvmDenom = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ExtraEIPs", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ExtraEIPs = append(m.ExtraEIPs, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainConfig", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.ChainConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AllowUnprotectedTxs", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.AllowUnprotectedTxs = bool(v != 0)
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EVMChannels", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EVMChannels = append(m.EVMChannels, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccessControl", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.AccessControl.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ActiveStaticPrecompiles", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ActiveStaticPrecompiles = append(m.ActiveStaticPrecompiles, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *AccessControl) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AccessControl: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AccessControl: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Create", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Create.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Call", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Call.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *AccessControlType) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AccessControlType: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AccessControlType: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccessType", wireType)
+ }
+ m.AccessType = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.AccessType |= AccessType(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccessControlList", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.AccessControlList = append(m.AccessControlList, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *ChainConfig) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ChainConfig: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ChainConfig: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field HomesteadBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.HomesteadBlock = &v
+ if err := m.HomesteadBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DAOForkBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.DAOForkBlock = &v
+ if err := m.DAOForkBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DAOForkSupport", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.DAOForkSupport = bool(v != 0)
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP150Block", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.EIP150Block = &v
+ if err := m.EIP150Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP150Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.EIP150Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP155Block", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.EIP155Block = &v
+ if err := m.EIP155Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EIP158Block", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.EIP158Block = &v
+ if err := m.EIP158Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ByzantiumBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ByzantiumBlock = &v
+ if err := m.ByzantiumBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ConstantinopleBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ConstantinopleBlock = &v
+ if err := m.ConstantinopleBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PetersburgBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.PetersburgBlock = &v
+ if err := m.PetersburgBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 11:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field IstanbulBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.IstanbulBlock = &v
+ if err := m.IstanbulBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 12:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MuirGlacierBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.MuirGlacierBlock = &v
+ if err := m.MuirGlacierBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 13:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BerlinBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.BerlinBlock = &v
+ if err := m.BerlinBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 17:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LondonBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.LondonBlock = &v
+ if err := m.LondonBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 18:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ArrowGlacierBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ArrowGlacierBlock = &v
+ if err := m.ArrowGlacierBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 20:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GrayGlacierBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.GrayGlacierBlock = &v
+ if err := m.GrayGlacierBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 21:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MergeNetsplitBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.MergeNetsplitBlock = &v
+ if err := m.MergeNetsplitBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 22:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ShanghaiBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ShanghaiBlock = &v
+ if err := m.ShanghaiBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 23:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CancunBlock", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.CancunBlock = &v
+ if err := m.CancunBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *State) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: State: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: State: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *TransactionLogs) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TransactionLogs: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TransactionLogs: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Logs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Logs = append(m.Logs, &Log{})
+ if err := m.Logs[len(m.Logs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *Log) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Log: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Log: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Topics", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Topics = append(m.Topics, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockNumber", wireType)
+ }
+ m.BlockNumber = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BlockNumber |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.TxHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxIndex", wireType)
+ }
+ m.TxIndex = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TxIndex |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.BlockHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType)
+ }
+ m.Index = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Index |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Removed", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Removed = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *TxResult) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TxResult: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TxResult: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ContractAddress = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Bloom", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Bloom = append(m.Bloom[:0], dAtA[iNdEx:postIndex]...)
+ if m.Bloom == nil {
+ m.Bloom = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TxLogs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.TxLogs.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Ret", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Ret = append(m.Ret[:0], dAtA[iNdEx:postIndex]...)
+ if m.Ret == nil {
+ m.Ret = []byte{}
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Reverted", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Reverted = bool(v != 0)
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType)
+ }
+ m.GasUsed = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GasUsed |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *AccessTuple) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AccessTuple: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AccessTuple: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field StorageKeys", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.StorageKeys = append(m.StorageKeys, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func (m *TraceConfig) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TraceConfig: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TraceConfig: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Tracer", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Tracer = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timeout", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Timeout = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Reexec", wireType)
+ }
+ m.Reexec = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Reexec |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DisableStack", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.DisableStack = bool(v != 0)
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DisableStorage", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.DisableStorage = bool(v != 0)
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Debug", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Debug = bool(v != 0)
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType)
+ }
+ m.Limit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Limit |= int32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Overrides", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Overrides == nil {
+ m.Overrides = &ChainConfig{}
+ }
+ if err := m.Overrides.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 11:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EnableMemory", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.EnableMemory = bool(v != 0)
+ case 12:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EnableReturnData", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.EnableReturnData = bool(v != 0)
+ case 13:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TracerJsonConfig", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvm
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.TracerJsonConfig = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvm(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvm
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func skipEvm(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvm
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthEvm
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupEvm
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthEvm
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthEvm = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowEvm = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupEvm = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/evm/types/genesis.go b/x/evm/types/genesis.go
new file mode 100644
index 00000000..e8138457
--- /dev/null
+++ b/x/evm/types/genesis.go
@@ -0,0 +1,51 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "fmt"
+
+ "github.com/evmos/evmos/v19/types"
+)
+
+// Validate performs a basic validation of a GenesisAccount fields.
+func (ga GenesisAccount) Validate() error {
+ if err := types.ValidateAddress(ga.Address); err != nil {
+ return err
+ }
+ return ga.Storage.Validate()
+}
+
+// DefaultGenesisState sets default evm genesis state with empty accounts and default params and
+// chain config values.
+func DefaultGenesisState() *GenesisState {
+ return &GenesisState{
+ Accounts: []GenesisAccount{},
+ Params: DefaultParams(),
+ }
+}
+
+// NewGenesisState creates a new genesis state.
+func NewGenesisState(params Params, accounts []GenesisAccount) *GenesisState {
+ return &GenesisState{
+ Accounts: accounts,
+ Params: params,
+ }
+}
+
+// Validate performs basic genesis state validation returning an error upon any
+// failure.
+func (gs GenesisState) Validate() error {
+ seenAccounts := make(map[string]bool)
+ for _, acc := range gs.Accounts {
+ if seenAccounts[acc.Address] {
+ return fmt.Errorf("duplicated genesis account %s", acc.Address)
+ }
+ if err := acc.Validate(); err != nil {
+ return fmt.Errorf("invalid genesis account %s: %w", acc.Address, err)
+ }
+ seenAccounts[acc.Address] = true
+ }
+
+ return gs.Params.Validate()
+}
diff --git a/x/evm/types/genesis.pb.go b/x/evm/types/genesis.pb.go
new file mode 100644
index 00000000..725d904d
--- /dev/null
+++ b/x/evm/types/genesis.pb.go
@@ -0,0 +1,680 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/evm/v1/genesis.proto
+
+package types
+
+import (
+ fmt "fmt"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ proto "github.com/cosmos/gogoproto/proto"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// GenesisState defines the evm module's genesis state.
+type GenesisState struct {
+ // accounts is an array containing the ethereum genesis accounts.
+ Accounts []GenesisAccount `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts"`
+ // params defines all the parameters of the module.
+ Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"`
+}
+
+func (m *GenesisState) Reset() { *m = GenesisState{} }
+func (m *GenesisState) String() string { return proto.CompactTextString(m) }
+func (*GenesisState) ProtoMessage() {}
+func (*GenesisState) Descriptor() ([]byte, []int) {
+ return fileDescriptor_9bcdec50cc9d156d, []int{0}
+}
+func (m *GenesisState) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *GenesisState) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GenesisState.Merge(m, src)
+}
+func (m *GenesisState) XXX_Size() int {
+ return m.Size()
+}
+func (m *GenesisState) XXX_DiscardUnknown() {
+ xxx_messageInfo_GenesisState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GenesisState proto.InternalMessageInfo
+
+func (m *GenesisState) GetAccounts() []GenesisAccount {
+ if m != nil {
+ return m.Accounts
+ }
+ return nil
+}
+
+func (m *GenesisState) GetParams() Params {
+ if m != nil {
+ return m.Params
+ }
+ return Params{}
+}
+
+// GenesisAccount defines an account to be initialized in the genesis state.
+// Its main difference between with Geth's GenesisAccount is that it uses a
+// custom storage type and that it doesn't contain the private key field.
+type GenesisAccount struct {
+ // address defines an ethereum hex formated address of an account
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ // code defines the hex bytes of the account code.
+ Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
+ // storage defines the set of state key values for the account.
+ Storage Storage `protobuf:"bytes,3,rep,name=storage,proto3,castrepeated=Storage" json:"storage"`
+}
+
+func (m *GenesisAccount) Reset() { *m = GenesisAccount{} }
+func (m *GenesisAccount) String() string { return proto.CompactTextString(m) }
+func (*GenesisAccount) ProtoMessage() {}
+func (*GenesisAccount) Descriptor() ([]byte, []int) {
+ return fileDescriptor_9bcdec50cc9d156d, []int{1}
+}
+func (m *GenesisAccount) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *GenesisAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_GenesisAccount.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *GenesisAccount) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GenesisAccount.Merge(m, src)
+}
+func (m *GenesisAccount) XXX_Size() int {
+ return m.Size()
+}
+func (m *GenesisAccount) XXX_DiscardUnknown() {
+ xxx_messageInfo_GenesisAccount.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GenesisAccount proto.InternalMessageInfo
+
+func (m *GenesisAccount) GetAddress() string {
+ if m != nil {
+ return m.Address
+ }
+ return ""
+}
+
+func (m *GenesisAccount) GetCode() string {
+ if m != nil {
+ return m.Code
+ }
+ return ""
+}
+
+func (m *GenesisAccount) GetStorage() Storage {
+ if m != nil {
+ return m.Storage
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*GenesisState)(nil), "ethermint.evm.v1.GenesisState")
+ proto.RegisterType((*GenesisAccount)(nil), "ethermint.evm.v1.GenesisAccount")
+}
+
+func init() { proto.RegisterFile("ethermint/evm/v1/genesis.proto", fileDescriptor_9bcdec50cc9d156d) }
+
+var fileDescriptor_9bcdec50cc9d156d = []byte{
+ // 301 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x50, 0xbf, 0x4e, 0x83, 0x40,
+ 0x18, 0xe7, 0x6c, 0xd3, 0xda, 0xab, 0x51, 0x73, 0x31, 0x91, 0x30, 0x5c, 0x49, 0x07, 0xc3, 0x74,
+ 0x84, 0x9a, 0x18, 0x47, 0x65, 0x71, 0x35, 0x74, 0x73, 0xbb, 0xc2, 0x17, 0xca, 0x00, 0x47, 0xb8,
+ 0x2b, 0xd1, 0xd5, 0xd1, 0xc9, 0xe7, 0xf0, 0x49, 0x3a, 0x76, 0x74, 0x52, 0x03, 0x2f, 0x62, 0x38,
+ 0x68, 0x13, 0x65, 0xb9, 0x7c, 0x77, 0xbf, 0x7f, 0xdf, 0xfd, 0x30, 0x05, 0xb5, 0x86, 0x22, 0x4d,
+ 0x32, 0xe5, 0x42, 0x99, 0xba, 0xa5, 0xe7, 0xc6, 0x90, 0x81, 0x4c, 0x24, 0xcb, 0x0b, 0xa1, 0x04,
+ 0x39, 0x3f, 0xe0, 0x0c, 0xca, 0x94, 0x95, 0x9e, 0x65, 0xf5, 0x14, 0x0d, 0xa0, 0xd9, 0xd6, 0x45,
+ 0x2c, 0x62, 0xa1, 0x47, 0xb7, 0x99, 0xda, 0xd7, 0xf9, 0x1b, 0xc2, 0x27, 0x0f, 0xad, 0xeb, 0x52,
+ 0x71, 0x05, 0xc4, 0xc7, 0xc7, 0x3c, 0x0c, 0xc5, 0x26, 0x53, 0xd2, 0x44, 0xf6, 0xc0, 0x99, 0x2e,
+ 0x6c, 0xf6, 0x3f, 0x87, 0x75, 0x8a, 0xfb, 0x96, 0xe8, 0x0f, 0xb7, 0x5f, 0x33, 0x23, 0x38, 0xe8,
+ 0xc8, 0x0d, 0x1e, 0xe5, 0xbc, 0xe0, 0xa9, 0x34, 0x8f, 0x6c, 0xe4, 0x4c, 0x17, 0x66, 0xdf, 0xe1,
+ 0x51, 0xe3, 0x9d, 0xb2, 0x63, 0xcf, 0x5f, 0x11, 0x3e, 0xfd, 0x6b, 0x4d, 0x4c, 0x3c, 0xe6, 0x51,
+ 0x54, 0x80, 0x6c, 0xb6, 0x41, 0xce, 0x24, 0xd8, 0x5f, 0x09, 0xc1, 0xc3, 0x50, 0x44, 0xa0, 0x23,
+ 0x26, 0x81, 0x9e, 0x89, 0x8f, 0xc7, 0x52, 0x89, 0x82, 0xc7, 0x60, 0x0e, 0xf4, 0xee, 0x97, 0xfd,
+ 0x64, 0xfd, 0x4d, 0xff, 0xac, 0x09, 0xfe, 0xf8, 0x9e, 0x8d, 0x97, 0x2d, 0x3f, 0xd8, 0x0b, 0xfd,
+ 0xbb, 0x6d, 0x45, 0xd1, 0xae, 0xa2, 0xe8, 0xa7, 0xa2, 0xe8, 0xbd, 0xa6, 0xc6, 0xae, 0xa6, 0xc6,
+ 0x67, 0x4d, 0x8d, 0xa7, 0xab, 0x38, 0x51, 0xeb, 0xcd, 0x8a, 0x85, 0x22, 0x6d, 0x7a, 0x15, 0xb2,
+ 0x3b, 0x4b, 0xef, 0xd6, 0x7d, 0xd6, 0x85, 0xab, 0x97, 0x1c, 0xe4, 0x6a, 0xa4, 0xab, 0xbd, 0xfe,
+ 0x0d, 0x00, 0x00, 0xff, 0xff, 0x84, 0x47, 0xe2, 0x82, 0xc0, 0x01, 0x00, 0x00,
+}
+
+func (m *GenesisState) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintGenesis(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ if len(m.Accounts) > 0 {
+ for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Accounts[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintGenesis(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *GenesisAccount) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *GenesisAccount) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GenesisAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Storage) > 0 {
+ for iNdEx := len(m.Storage) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Storage[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintGenesis(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ }
+ if len(m.Code) > 0 {
+ i -= len(m.Code)
+ copy(dAtA[i:], m.Code)
+ i = encodeVarintGenesis(dAtA, i, uint64(len(m.Code)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
+ offset -= sovGenesis(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *GenesisState) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.Accounts) > 0 {
+ for _, e := range m.Accounts {
+ l = e.Size()
+ n += 1 + l + sovGenesis(uint64(l))
+ }
+ }
+ l = m.Params.Size()
+ n += 1 + l + sovGenesis(uint64(l))
+ return n
+}
+
+func (m *GenesisAccount) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovGenesis(uint64(l))
+ }
+ l = len(m.Code)
+ if l > 0 {
+ n += 1 + l + sovGenesis(uint64(l))
+ }
+ if len(m.Storage) > 0 {
+ for _, e := range m.Storage {
+ l = e.Size()
+ n += 1 + l + sovGenesis(uint64(l))
+ }
+ }
+ return n
+}
+
+func sovGenesis(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozGenesis(x uint64) (n int) {
+ return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *GenesisState) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Accounts", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Accounts = append(m.Accounts, GenesisAccount{})
+ if err := m.Accounts[len(m.Accounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipGenesis(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *GenesisAccount) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: GenesisAccount: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: GenesisAccount: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Code = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Storage", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Storage = append(m.Storage, State{})
+ if err := m.Storage[len(m.Storage)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipGenesis(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipGenesis(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthGenesis
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupGenesis
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthGenesis
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/evm/types/genesis_test.go b/x/evm/types/genesis_test.go
new file mode 100644
index 00000000..78368368
--- /dev/null
+++ b/x/evm/types/genesis_test.go
@@ -0,0 +1,225 @@
+package types
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/stretchr/testify/suite"
+
+ "github.com/evmos/evmos/v19/crypto/ethsecp256k1"
+)
+
+type GenesisTestSuite struct {
+ suite.Suite
+
+ address string
+ hash common.Hash
+ code string
+}
+
+func (suite *GenesisTestSuite) SetupTest() {
+ priv, err := ethsecp256k1.GenerateKey()
+ suite.Require().NoError(err)
+
+ suite.address = common.BytesToAddress(priv.PubKey().Address().Bytes()).String()
+ suite.hash = common.BytesToHash([]byte("hash"))
+ suite.code = common.Bytes2Hex([]byte{1, 2, 3})
+}
+
+func TestGenesisTestSuite(t *testing.T) {
+ suite.Run(t, new(GenesisTestSuite))
+}
+
+func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
+ testCases := []struct {
+ name string
+ genesisAccount GenesisAccount
+ expPass bool
+ }{
+ {
+ "valid genesis account",
+ GenesisAccount{
+ Address: suite.address,
+ Code: suite.code,
+ Storage: Storage{
+ NewState(suite.hash, suite.hash),
+ },
+ },
+ true,
+ },
+ {
+ "empty account address bytes",
+ GenesisAccount{
+ Address: "",
+ Code: suite.code,
+ Storage: Storage{
+ NewState(suite.hash, suite.hash),
+ },
+ },
+ false,
+ },
+ {
+ "empty code bytes",
+ GenesisAccount{
+ Address: suite.address,
+ Code: "",
+ Storage: Storage{
+ NewState(suite.hash, suite.hash),
+ },
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ err := tc.genesisAccount.Validate()
+ if tc.expPass {
+ suite.Require().NoError(err, tc.name)
+ } else {
+ suite.Require().Error(err, tc.name)
+ }
+ }
+}
+
+func (suite *GenesisTestSuite) TestValidateGenesis() {
+ testCases := []struct {
+ name string
+ genState *GenesisState
+ expPass bool
+ }{
+ {
+ name: "default",
+ genState: DefaultGenesisState(),
+ expPass: true,
+ },
+ {
+ name: "valid genesis",
+ genState: &GenesisState{
+ Accounts: []GenesisAccount{
+ {
+ Address: suite.address,
+
+ Code: suite.code,
+ Storage: Storage{
+ {Key: suite.hash.String()},
+ },
+ },
+ },
+ Params: DefaultParams(),
+ },
+ expPass: true,
+ },
+ {
+ name: "empty genesis",
+ genState: &GenesisState{},
+ expPass: false,
+ },
+ {
+ name: "copied genesis",
+ genState: NewGenesisState(DefaultGenesisState().Params, DefaultGenesisState().Accounts),
+ expPass: true,
+ },
+ {
+ name: "invalid genesis",
+ genState: &GenesisState{
+ Accounts: []GenesisAccount{
+ {
+ Address: common.Address{}.String(),
+ },
+ },
+ },
+ expPass: false,
+ },
+ {
+ name: "invalid genesis account",
+ genState: &GenesisState{
+ Accounts: []GenesisAccount{
+ {
+ Address: "123456",
+
+ Code: suite.code,
+ Storage: Storage{
+ {Key: suite.hash.String()},
+ },
+ },
+ },
+ Params: DefaultParams(),
+ },
+ expPass: false,
+ },
+ {
+ name: "duplicated genesis account",
+ genState: &GenesisState{
+ Accounts: []GenesisAccount{
+ {
+ Address: suite.address,
+
+ Code: suite.code,
+ Storage: Storage{
+ NewState(suite.hash, suite.hash),
+ },
+ },
+ {
+ Address: suite.address,
+
+ Code: suite.code,
+ Storage: Storage{
+ NewState(suite.hash, suite.hash),
+ },
+ },
+ },
+ },
+ expPass: false,
+ },
+ {
+ name: "duplicated tx log",
+ genState: &GenesisState{
+ Accounts: []GenesisAccount{
+ {
+ Address: suite.address,
+
+ Code: suite.code,
+ Storage: Storage{
+ {Key: suite.hash.String()},
+ },
+ },
+ },
+ },
+ expPass: false,
+ },
+ {
+ name: "invalid tx log",
+ genState: &GenesisState{
+ Accounts: []GenesisAccount{
+ {
+ Address: suite.address,
+
+ Code: suite.code,
+ Storage: Storage{
+ {Key: suite.hash.String()},
+ },
+ },
+ },
+ },
+ expPass: false,
+ },
+ {
+ name: "invalid params",
+ genState: &GenesisState{
+ Params: Params{},
+ },
+ expPass: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ err := tc.genState.Validate()
+ if tc.expPass {
+ suite.Require().NoError(err, tc.name)
+ } else {
+ suite.Require().Error(err, tc.name)
+ }
+ }
+}
diff --git a/x/evm/types/interfaces.go b/x/evm/types/interfaces.go
new file mode 100644
index 00000000..cece5eca
--- /dev/null
+++ b/x/evm/types/interfaces.go
@@ -0,0 +1,64 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math/big"
+
+ paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
+ "github.com/ethereum/go-ethereum/common"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+
+ feemarkettypes "github.com/evmos/evmos/v19/x/feemarket/types"
+)
+
+// AccountKeeper defines the expected account keeper interface
+type AccountKeeper interface {
+ NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
+ GetModuleAddress(moduleName string) sdk.AccAddress
+ GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
+ SetAccount(ctx sdk.Context, account authtypes.AccountI)
+ RemoveAccount(ctx sdk.Context, account authtypes.AccountI)
+ GetParams(ctx sdk.Context) (params authtypes.Params)
+ GetSequence(ctx sdk.Context, account sdk.AccAddress) (uint64, error)
+}
+
+// BankKeeper defines the expected interface needed to retrieve account balances.
+type BankKeeper interface {
+ authtypes.BankKeeper
+ GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
+ SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
+ MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
+ BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
+}
+
+// StakingKeeper returns the historical headers kept in store.
+type StakingKeeper interface {
+ GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool)
+ GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator stakingtypes.Validator, found bool)
+}
+
+// FeeMarketKeeper
+type FeeMarketKeeper interface {
+ GetBaseFee(ctx sdk.Context) *big.Int
+ GetParams(ctx sdk.Context) feemarkettypes.Params
+ CalculateBaseFee(ctx sdk.Context) *big.Int
+}
+
+// Erc20Keeper defines the expected interface needed to instantiate ERC20 precompiles.
+type Erc20Keeper interface {
+ GetERC20PrecompileInstance(ctx sdk.Context, address common.Address) (contract vm.PrecompiledContract, found bool, err error)
+}
+
+type (
+ LegacyParams = paramtypes.ParamSet
+ // Subspace defines an interface that implements the legacy Cosmos SDK x/params Subspace type.
+ // NOTE: This is used solely for migration of the Cosmos SDK x/params managed parameters.
+ Subspace interface {
+ GetParamSetIfExists(ctx sdk.Context, ps LegacyParams)
+ }
+)
diff --git a/x/evm/types/key.go b/x/evm/types/key.go
new file mode 100644
index 00000000..e9a163f6
--- /dev/null
+++ b/x/evm/types/key.go
@@ -0,0 +1,66 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+)
+
+const (
+ // ModuleName string name of module
+ ModuleName = "evm"
+
+ // StoreKey key for ethereum storage data, account code (StateDB) or block
+ // related data for Web3.
+ // The EVM module should use a prefix store.
+ StoreKey = ModuleName
+
+ // TransientKey is the key to access the EVM transient store, that is reset
+ // during the Commit phase.
+ TransientKey = "transient_" + ModuleName
+
+ // RouterKey uses module name for routing
+ RouterKey = ModuleName
+)
+
+// prefix bytes for the EVM persistent store
+const (
+ prefixCode = iota + 1
+ prefixStorage
+ prefixParams
+ prefixCodeHash
+)
+
+// prefix bytes for the EVM transient store
+const (
+ prefixTransientBloom = iota + 1
+ prefixTransientTxIndex
+ prefixTransientLogSize
+ prefixTransientGasUsed
+)
+
+// KVStore key prefixes
+var (
+ KeyPrefixCode = []byte{prefixCode}
+ KeyPrefixStorage = []byte{prefixStorage}
+ KeyPrefixParams = []byte{prefixParams}
+ KeyPrefixCodeHash = []byte{prefixCodeHash}
+)
+
+// Transient Store key prefixes
+var (
+ KeyPrefixTransientBloom = []byte{prefixTransientBloom}
+ KeyPrefixTransientTxIndex = []byte{prefixTransientTxIndex}
+ KeyPrefixTransientLogSize = []byte{prefixTransientLogSize}
+ KeyPrefixTransientGasUsed = []byte{prefixTransientGasUsed}
+)
+
+// AddressStoragePrefix returns a prefix to iterate over a given account storage.
+func AddressStoragePrefix(address common.Address) []byte {
+ return append(KeyPrefixStorage, address.Bytes()...)
+}
+
+// StateKey defines the full key under which an account state is stored.
+func StateKey(address common.Address, key []byte) []byte {
+ return append(AddressStoragePrefix(address), key...)
+}
diff --git a/x/evm/types/legacy_tx.go b/x/evm/types/legacy_tx.go
new file mode 100644
index 00000000..03ce4148
--- /dev/null
+++ b/x/evm/types/legacy_tx.go
@@ -0,0 +1,228 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math/big"
+
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+
+ errorsmod "cosmossdk.io/errors"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/types"
+)
+
+func NewLegacyTx(tx *ethtypes.Transaction) (*LegacyTx, error) {
+ txData := &LegacyTx{
+ Nonce: tx.Nonce(),
+ Data: tx.Data(),
+ GasLimit: tx.Gas(),
+ }
+
+ v, r, s := tx.RawSignatureValues()
+ if to := tx.To(); to != nil {
+ txData.To = to.Hex()
+ }
+
+ if tx.Value() != nil {
+ amountInt, err := types.SafeNewIntFromBigInt(tx.Value())
+ if err != nil {
+ return nil, err
+ }
+ txData.Amount = &amountInt
+ }
+
+ if tx.GasPrice() != nil {
+ gasPriceInt, err := types.SafeNewIntFromBigInt(tx.GasPrice())
+ if err != nil {
+ return nil, err
+ }
+ txData.GasPrice = &gasPriceInt
+ }
+
+ txData.SetSignatureValues(tx.ChainId(), v, r, s)
+ return txData, nil
+}
+
+// TxType returns the tx type
+func (tx *LegacyTx) TxType() uint8 {
+ return ethtypes.LegacyTxType
+}
+
+// Copy returns an instance with the same field values
+func (tx *LegacyTx) Copy() TxData {
+ return &LegacyTx{
+ Nonce: tx.Nonce,
+ GasPrice: tx.GasPrice,
+ GasLimit: tx.GasLimit,
+ To: tx.To,
+ Amount: tx.Amount,
+ Data: common.CopyBytes(tx.Data),
+ V: common.CopyBytes(tx.V),
+ R: common.CopyBytes(tx.R),
+ S: common.CopyBytes(tx.S),
+ }
+}
+
+// GetChainID returns the chain id field from the derived signature values
+func (tx *LegacyTx) GetChainID() *big.Int {
+ v, _, _ := tx.GetRawSignatureValues()
+ return DeriveChainID(v)
+}
+
+// GetAccessList returns nil
+func (tx *LegacyTx) GetAccessList() ethtypes.AccessList {
+ return nil
+}
+
+// GetData returns the a copy of the input data bytes.
+func (tx *LegacyTx) GetData() []byte {
+ return common.CopyBytes(tx.Data)
+}
+
+// GetGas returns the gas limit.
+func (tx *LegacyTx) GetGas() uint64 {
+ return tx.GasLimit
+}
+
+// GetGasPrice returns the gas price field.
+func (tx *LegacyTx) GetGasPrice() *big.Int {
+ if tx.GasPrice == nil {
+ return nil
+ }
+ return tx.GasPrice.BigInt()
+}
+
+// GetGasTipCap returns the gas price field.
+func (tx *LegacyTx) GetGasTipCap() *big.Int {
+ return tx.GetGasPrice()
+}
+
+// GetGasFeeCap returns the gas price field.
+func (tx *LegacyTx) GetGasFeeCap() *big.Int {
+ return tx.GetGasPrice()
+}
+
+// GetValue returns the tx amount.
+func (tx *LegacyTx) GetValue() *big.Int {
+ if tx.Amount == nil {
+ return nil
+ }
+ return tx.Amount.BigInt()
+}
+
+// GetNonce returns the account sequence for the transaction.
+func (tx *LegacyTx) GetNonce() uint64 { return tx.Nonce }
+
+// GetTo returns the pointer to the recipient address.
+func (tx *LegacyTx) GetTo() *common.Address {
+ if tx.To == "" {
+ return nil
+ }
+ to := common.HexToAddress(tx.To)
+ return &to
+}
+
+// AsEthereumData returns an LegacyTx transaction tx from the proto-formatted
+// TxData defined on the Cosmos EVM.
+func (tx *LegacyTx) AsEthereumData() ethtypes.TxData {
+ v, r, s := tx.GetRawSignatureValues()
+ return ðtypes.LegacyTx{
+ Nonce: tx.GetNonce(),
+ GasPrice: tx.GetGasPrice(),
+ Gas: tx.GetGas(),
+ To: tx.GetTo(),
+ Value: tx.GetValue(),
+ Data: tx.GetData(),
+ V: v,
+ R: r,
+ S: s,
+ }
+}
+
+// GetRawSignatureValues returns the V, R, S signature values of the transaction.
+// The return values should not be modified by the caller.
+func (tx *LegacyTx) GetRawSignatureValues() (v, r, s *big.Int) {
+ return rawSignatureValues(tx.V, tx.R, tx.S)
+}
+
+// SetSignatureValues sets the signature values to the transaction.
+func (tx *LegacyTx) SetSignatureValues(_, v, r, s *big.Int) {
+ if v != nil {
+ tx.V = v.Bytes()
+ }
+ if r != nil {
+ tx.R = r.Bytes()
+ }
+ if s != nil {
+ tx.S = s.Bytes()
+ }
+}
+
+// Validate performs a stateless validation of the tx fields.
+func (tx LegacyTx) Validate() error {
+ gasPrice := tx.GetGasPrice()
+ if gasPrice == nil {
+ return errorsmod.Wrap(ErrInvalidGasPrice, "gas price cannot be nil")
+ }
+
+ if gasPrice.Sign() == -1 {
+ return errorsmod.Wrapf(ErrInvalidGasPrice, "gas price cannot be negative %s", gasPrice)
+ }
+ if !types.IsValidInt256(gasPrice) {
+ return errorsmod.Wrap(ErrInvalidGasPrice, "out of bound")
+ }
+ if !types.IsValidInt256(tx.Fee()) {
+ return errorsmod.Wrap(ErrInvalidGasFee, "out of bound")
+ }
+
+ amount := tx.GetValue()
+ // Amount can be 0
+ if amount != nil && amount.Sign() == -1 {
+ return errorsmod.Wrapf(ErrInvalidAmount, "amount cannot be negative %s", amount)
+ }
+ if !types.IsValidInt256(amount) {
+ return errorsmod.Wrap(ErrInvalidAmount, "out of bound")
+ }
+
+ if tx.To != "" {
+ if err := types.ValidateAddress(tx.To); err != nil {
+ return errorsmod.Wrap(err, "invalid to address")
+ }
+ }
+
+ if tx.GetChainID() == nil {
+ return errorsmod.Wrap(
+ errortypes.ErrInvalidChainID,
+ "chain ID must be derived from LegacyTx txs",
+ )
+ }
+
+ return nil
+}
+
+// Fee returns gasprice * gaslimit.
+func (tx LegacyTx) Fee() *big.Int {
+ return fee(tx.GetGasPrice(), tx.GetGas())
+}
+
+// Cost returns amount + gasprice * gaslimit.
+func (tx LegacyTx) Cost() *big.Int {
+ return cost(tx.Fee(), tx.GetValue())
+}
+
+// EffectiveGasPrice is the same as GasPrice for LegacyTx
+func (tx LegacyTx) EffectiveGasPrice(_ *big.Int) *big.Int {
+ return tx.GetGasPrice()
+}
+
+// EffectiveFee is the same as Fee for LegacyTx
+func (tx LegacyTx) EffectiveFee(_ *big.Int) *big.Int {
+ return tx.Fee()
+}
+
+// EffectiveCost is the same as Cost for LegacyTx
+func (tx LegacyTx) EffectiveCost(_ *big.Int) *big.Int {
+ return tx.Cost()
+}
diff --git a/x/evm/types/legacy_tx_test.go b/x/evm/types/legacy_tx_test.go
new file mode 100644
index 00000000..92e00fc5
--- /dev/null
+++ b/x/evm/types/legacy_tx_test.go
@@ -0,0 +1,434 @@
+package types_test
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *TxDataTestSuite) TestNewLegacyTx() {
+ testCases := []struct {
+ name string
+ tx *ethtypes.Transaction
+ }{
+ {
+ "non-empty Transaction",
+ ethtypes.NewTx(ðtypes.AccessListTx{
+ Nonce: 1,
+ Data: []byte("data"),
+ Gas: 100,
+ Value: big.NewInt(1),
+ AccessList: ethtypes.AccessList{},
+ To: &suite.addr,
+ V: big.NewInt(1),
+ R: big.NewInt(1),
+ S: big.NewInt(1),
+ }),
+ },
+ }
+
+ for _, tc := range testCases {
+ tx, err := types.NewLegacyTx(tc.tx)
+ suite.Require().NoError(err)
+
+ suite.Require().NotEmpty(tc.tx)
+ suite.Require().Equal(uint8(0), tx.TxType())
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxTxType() {
+ tx := types.LegacyTx{}
+ actual := tx.TxType()
+
+ suite.Require().Equal(uint8(0), actual)
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxCopy() {
+ tx := &types.LegacyTx{}
+ txData := tx.Copy()
+
+ suite.Require().Equal(&types.LegacyTx{}, txData)
+ // TODO: Test for different pointers
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetChainID() {
+ tx := types.LegacyTx{}
+ actual := tx.GetChainID()
+
+ suite.Require().Nil(actual)
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetAccessList() {
+ tx := types.LegacyTx{}
+ actual := tx.GetAccessList()
+
+ suite.Require().Nil(actual)
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetData() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ }{
+ {
+ "non-empty transaction",
+ types.LegacyTx{
+ Data: nil,
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetData()
+
+ suite.Require().Equal(tc.tx.Data, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetGas() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ exp uint64
+ }{
+ {
+ "non-empty gas",
+ types.LegacyTx{
+ GasLimit: suite.uint64,
+ },
+ suite.uint64,
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGas()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetGasPrice() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ exp *big.Int
+ }{
+ {
+ "empty gasPrice",
+ types.LegacyTx{
+ GasPrice: nil,
+ },
+ nil,
+ },
+ {
+ "non-empty gasPrice",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasFeeCap()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetGasTipCap() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ exp *big.Int
+ }{
+ {
+ "non-empty gasPrice",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasTipCap()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetGasFeeCap() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ exp *big.Int
+ }{
+ {
+ "non-empty gasPrice",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetGasFeeCap()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetValue() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ exp *big.Int
+ }{
+ {
+ "empty amount",
+ types.LegacyTx{
+ Amount: nil,
+ },
+ nil,
+ },
+ {
+ "non-empty amount",
+ types.LegacyTx{
+ Amount: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetValue()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetNonce() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ exp uint64
+ }{
+ {
+ "none-empty nonce",
+ types.LegacyTx{
+ Nonce: suite.uint64,
+ },
+ suite.uint64,
+ },
+ }
+ for _, tc := range testCases {
+ actual := tc.tx.GetNonce()
+
+ suite.Require().Equal(tc.exp, actual)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxGetTo() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ exp *common.Address
+ }{
+ {
+ "empty address",
+ types.LegacyTx{
+ To: "",
+ },
+ nil,
+ },
+ {
+ "non-empty address",
+ types.LegacyTx{
+ To: suite.hexAddr,
+ },
+ &suite.addr,
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.GetTo()
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxAsEthereumData() {
+ tx := &types.LegacyTx{}
+ txData := tx.AsEthereumData()
+
+ suite.Require().Equal(ðtypes.LegacyTx{}, txData)
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxSetSignatureValues() {
+ testCases := []struct {
+ name string
+ v *big.Int
+ r *big.Int
+ s *big.Int
+ }{
+ {
+ "non-empty values",
+ suite.bigInt,
+ suite.bigInt,
+ suite.bigInt,
+ },
+ }
+ for _, tc := range testCases {
+ tx := &types.LegacyTx{}
+ tx.SetSignatureValues(nil, tc.v, tc.r, tc.s)
+
+ v, r, s := tx.GetRawSignatureValues()
+
+ suite.Require().Equal(tc.v, v, tc.name)
+ suite.Require().Equal(tc.r, r, tc.name)
+ suite.Require().Equal(tc.s, s, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxValidate() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ expError bool
+ }{
+ {
+ "empty",
+ types.LegacyTx{},
+ true,
+ },
+ {
+ "gas price is nil",
+ types.LegacyTx{
+ GasPrice: nil,
+ },
+ true,
+ },
+ {
+ "gas price is negative",
+ types.LegacyTx{
+ GasPrice: &suite.sdkMinusOneInt,
+ },
+ true,
+ },
+ {
+ "amount is negative",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ Amount: &suite.sdkMinusOneInt,
+ },
+ true,
+ },
+ {
+ "to address is invalid",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ Amount: &suite.sdkInt,
+ To: suite.invalidAddr,
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ err := tc.tx.Validate()
+
+ if tc.expError {
+ suite.Require().Error(err, tc.name)
+ continue
+ }
+
+ suite.Require().NoError(err, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxEffectiveGasPrice() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ baseFee *big.Int
+ exp *big.Int
+ }{
+ {
+ "non-empty legacy tx",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveGasPrice(tc.baseFee)
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxEffectiveFee() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ baseFee *big.Int
+ exp *big.Int
+ }{
+ {
+ "non-empty legacy tx",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ GasLimit: uint64(1),
+ },
+ (&suite.sdkInt).BigInt(),
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveFee(tc.baseFee)
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxEffectiveCost() {
+ testCases := []struct {
+ name string
+ tx types.LegacyTx
+ baseFee *big.Int
+ exp *big.Int
+ }{
+ {
+ "non-empty legacy tx",
+ types.LegacyTx{
+ GasPrice: &suite.sdkInt,
+ GasLimit: uint64(1),
+ Amount: &suite.sdkZeroInt,
+ },
+ (&suite.sdkInt).BigInt(),
+ (&suite.sdkInt).BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ actual := tc.tx.EffectiveCost(tc.baseFee)
+
+ suite.Require().Equal(tc.exp, actual, tc.name)
+ }
+}
+
+func (suite *TxDataTestSuite) TestLegacyTxFeeCost() {
+ tx := &types.LegacyTx{}
+
+ suite.Require().Panics(func() { tx.Fee() }, "should panic")
+ suite.Require().Panics(func() { tx.Cost() }, "should panic")
+}
diff --git a/x/evm/types/logs.go b/x/evm/types/logs.go
new file mode 100644
index 00000000..e5e54df5
--- /dev/null
+++ b/x/evm/types/logs.go
@@ -0,0 +1,129 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ evmostypes "github.com/evmos/evmos/v19/types"
+)
+
+// NewTransactionLogs creates a new NewTransactionLogs instance.
+func NewTransactionLogs(hash common.Hash, logs []*Log) TransactionLogs {
+ return TransactionLogs{
+ Hash: hash.String(),
+ Logs: logs,
+ }
+}
+
+// NewTransactionLogsFromEth creates a new NewTransactionLogs instance using []*ethtypes.Log.
+func NewTransactionLogsFromEth(hash common.Hash, ethlogs []*ethtypes.Log) TransactionLogs {
+ return TransactionLogs{
+ Hash: hash.String(),
+ Logs: NewLogsFromEth(ethlogs),
+ }
+}
+
+// Validate performs a basic validation of a GenesisAccount fields.
+func (tx TransactionLogs) Validate() error {
+ if evmostypes.IsEmptyHash(tx.Hash) {
+ return fmt.Errorf("hash cannot be the empty %s", tx.Hash)
+ }
+
+ for i, log := range tx.Logs {
+ if log == nil {
+ return fmt.Errorf("log %d cannot be nil", i)
+ }
+ if err := log.Validate(); err != nil {
+ return fmt.Errorf("invalid log %d: %w", i, err)
+ }
+ if log.TxHash != tx.Hash {
+ return fmt.Errorf("log tx hash mismatch (%s ≠%s)", log.TxHash, tx.Hash)
+ }
+ }
+ return nil
+}
+
+// EthLogs returns the Ethereum type Logs from the Transaction Logs.
+func (tx TransactionLogs) EthLogs() []*ethtypes.Log {
+ return LogsToEthereum(tx.Logs)
+}
+
+// Validate performs a basic validation of an ethereum Log fields.
+func (log *Log) Validate() error {
+ if err := evmostypes.ValidateAddress(log.Address); err != nil {
+ return fmt.Errorf("invalid log address %w", err)
+ }
+ if evmostypes.IsEmptyHash(log.BlockHash) {
+ return fmt.Errorf("block hash cannot be the empty %s", log.BlockHash)
+ }
+ if log.BlockNumber == 0 {
+ return errors.New("block number cannot be zero")
+ }
+ if evmostypes.IsEmptyHash(log.TxHash) {
+ return fmt.Errorf("tx hash cannot be the empty %s", log.TxHash)
+ }
+ return nil
+}
+
+// ToEthereum returns the Ethereum type Log from a Ethermint proto compatible Log.
+func (log *Log) ToEthereum() *ethtypes.Log {
+ topics := make([]common.Hash, len(log.Topics))
+ for i, topic := range log.Topics {
+ topics[i] = common.HexToHash(topic)
+ }
+
+ return ðtypes.Log{
+ Address: common.HexToAddress(log.Address),
+ Topics: topics,
+ Data: log.Data,
+ BlockNumber: log.BlockNumber,
+ TxHash: common.HexToHash(log.TxHash),
+ TxIndex: uint(log.TxIndex),
+ Index: uint(log.Index),
+ BlockHash: common.HexToHash(log.BlockHash),
+ Removed: log.Removed,
+ }
+}
+
+func NewLogsFromEth(ethlogs []*ethtypes.Log) []*Log {
+ var logs []*Log //nolint: prealloc
+ for _, ethlog := range ethlogs {
+ logs = append(logs, NewLogFromEth(ethlog))
+ }
+
+ return logs
+}
+
+// LogsToEthereum casts the Ethermint Logs to a slice of Ethereum Logs.
+func LogsToEthereum(logs []*Log) []*ethtypes.Log {
+ var ethLogs []*ethtypes.Log //nolint: prealloc
+ for i := range logs {
+ ethLogs = append(ethLogs, logs[i].ToEthereum())
+ }
+ return ethLogs
+}
+
+// NewLogFromEth creates a new Log instance from a Ethereum type Log.
+func NewLogFromEth(log *ethtypes.Log) *Log {
+ topics := make([]string, len(log.Topics))
+ for i, topic := range log.Topics {
+ topics[i] = topic.String()
+ }
+
+ return &Log{
+ Address: log.Address.String(),
+ Topics: topics,
+ Data: log.Data,
+ BlockNumber: log.BlockNumber,
+ TxHash: log.TxHash.String(),
+ TxIndex: uint64(log.TxIndex),
+ Index: uint64(log.Index),
+ BlockHash: log.BlockHash.String(),
+ Removed: log.Removed,
+ }
+}
diff --git a/x/evm/types/logs_test.go b/x/evm/types/logs_test.go
new file mode 100644
index 00000000..f1103b12
--- /dev/null
+++ b/x/evm/types/logs_test.go
@@ -0,0 +1,201 @@
+package types_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ "github.com/evmos/evmos/v19/x/evm/types"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func TestTransactionLogsValidate(t *testing.T) {
+ addr := utiltx.GenerateAddress().String()
+
+ testCases := []struct {
+ name string
+ txLogs types.TransactionLogs
+ expPass bool
+ }{
+ {
+ "valid log",
+ types.TransactionLogs{
+ Hash: common.BytesToHash([]byte("tx_hash")).String(),
+ Logs: []*types.Log{
+ {
+ Address: addr,
+ Topics: []string{common.BytesToHash([]byte("topic")).String()},
+ Data: []byte("data"),
+ BlockNumber: 1,
+ TxHash: common.BytesToHash([]byte("tx_hash")).String(),
+ TxIndex: 1,
+ BlockHash: common.BytesToHash([]byte("block_hash")).String(),
+ Index: 1,
+ Removed: false,
+ },
+ },
+ },
+ true,
+ },
+ {
+ "empty hash",
+ types.TransactionLogs{
+ Hash: common.Hash{}.String(),
+ },
+ false,
+ },
+ {
+ "nil log",
+ types.TransactionLogs{
+ Hash: common.BytesToHash([]byte("tx_hash")).String(),
+ Logs: []*types.Log{nil},
+ },
+ false,
+ },
+ {
+ "invalid log",
+ types.TransactionLogs{
+ Hash: common.BytesToHash([]byte("tx_hash")).String(),
+ Logs: []*types.Log{{}},
+ },
+ false,
+ },
+ {
+ "hash mismatch log",
+ types.TransactionLogs{
+ Hash: common.BytesToHash([]byte("tx_hash")).String(),
+ Logs: []*types.Log{
+ {
+ Address: addr,
+ Topics: []string{common.BytesToHash([]byte("topic")).String()},
+ Data: []byte("data"),
+ BlockNumber: 1,
+ TxHash: common.BytesToHash([]byte("other_hash")).String(),
+ TxIndex: 1,
+ BlockHash: common.BytesToHash([]byte("block_hash")).String(),
+ Index: 1,
+ Removed: false,
+ },
+ },
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ err := tc.txLogs.Validate()
+ if tc.expPass {
+ require.NoError(t, err, tc.name)
+ } else {
+ require.Error(t, err, tc.name)
+ }
+ }
+}
+
+func TestValidateLog(t *testing.T) {
+ addr := utiltx.GenerateAddress().String()
+
+ testCases := []struct {
+ name string
+ log *types.Log
+ expPass bool
+ }{
+ {
+ "valid log",
+ &types.Log{
+ Address: addr,
+ Topics: []string{common.BytesToHash([]byte("topic")).String()},
+ Data: []byte("data"),
+ BlockNumber: 1,
+ TxHash: common.BytesToHash([]byte("tx_hash")).String(),
+ TxIndex: 1,
+ BlockHash: common.BytesToHash([]byte("block_hash")).String(),
+ Index: 1,
+ Removed: false,
+ },
+ true,
+ },
+ {
+ "empty log", &types.Log{}, false,
+ },
+ {
+ "zero address",
+ &types.Log{
+ Address: common.Address{}.String(),
+ },
+ false,
+ },
+ {
+ "empty block hash",
+ &types.Log{
+ Address: addr,
+ BlockHash: common.Hash{}.String(),
+ },
+ false,
+ },
+ {
+ "zero block number",
+ &types.Log{
+ Address: addr,
+ BlockHash: common.BytesToHash([]byte("block_hash")).String(),
+ BlockNumber: 0,
+ },
+ false,
+ },
+ {
+ "empty tx hash",
+ &types.Log{
+ Address: addr,
+ BlockHash: common.BytesToHash([]byte("block_hash")).String(),
+ BlockNumber: 1,
+ TxHash: common.Hash{}.String(),
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ err := tc.log.Validate()
+ if tc.expPass {
+ require.NoError(t, err, tc.name)
+ } else {
+ require.Error(t, err, tc.name)
+ }
+ }
+}
+
+func TestConversionFunctions(t *testing.T) {
+ addr := utiltx.GenerateAddress().String()
+
+ txLogs := types.TransactionLogs{
+ Hash: common.BytesToHash([]byte("tx_hash")).String(),
+ Logs: []*types.Log{
+ {
+ Address: addr,
+ Topics: []string{common.BytesToHash([]byte("topic")).String()},
+ Data: []byte("data"),
+ BlockNumber: 1,
+ TxHash: common.BytesToHash([]byte("tx_hash")).String(),
+ TxIndex: 1,
+ BlockHash: common.BytesToHash([]byte("block_hash")).String(),
+ Index: 1,
+ Removed: false,
+ },
+ },
+ }
+
+ // convert valid log to eth logs and back (and validate)
+ conversionLogs := types.NewTransactionLogsFromEth(common.BytesToHash([]byte("tx_hash")), txLogs.EthLogs())
+ conversionErr := conversionLogs.Validate()
+
+ // create new transaction logs as copy of old valid one (and validate)
+ copyLogs := types.NewTransactionLogs(common.BytesToHash([]byte("tx_hash")), txLogs.Logs)
+ copyErr := copyLogs.Validate()
+
+ require.Nil(t, conversionErr)
+ require.Nil(t, copyErr)
+}
diff --git a/x/evm/types/msg.go b/x/evm/types/msg.go
new file mode 100644
index 00000000..16298390
--- /dev/null
+++ b/x/evm/types/msg.go
@@ -0,0 +1,390 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+
+ sdkmath "cosmossdk.io/math"
+
+ errorsmod "cosmossdk.io/errors"
+ "github.com/cosmos/cosmos-sdk/client"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/cosmos/cosmos-sdk/x/auth/ante"
+ "github.com/cosmos/cosmos-sdk/x/auth/signing"
+ authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
+
+ "github.com/evmos/evmos/v19/types"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+)
+
+var (
+ _ sdk.Msg = &MsgEthereumTx{}
+ _ sdk.Tx = &MsgEthereumTx{}
+ _ ante.GasTx = &MsgEthereumTx{}
+ _ sdk.Msg = &MsgUpdateParams{}
+
+ _ codectypes.UnpackInterfacesMessage = MsgEthereumTx{}
+)
+
+// message type and route constants
+const (
+ // TypeMsgEthereumTx defines the type string of an Ethereum transaction
+ TypeMsgEthereumTx = "ethereum_tx"
+)
+
+// NewTx returns a reference to a new Ethereum transaction message.
+func NewTx(
+ tx *EvmTxArgs,
+) *MsgEthereumTx {
+ return newMsgEthereumTx(tx)
+}
+
+func newMsgEthereumTx(
+ tx *EvmTxArgs,
+) *MsgEthereumTx {
+ var (
+ cid, amt, gp *sdkmath.Int
+ toAddr string
+ txData TxData
+ )
+
+ if tx.To != nil {
+ toAddr = tx.To.Hex()
+ }
+
+ if tx.Amount != nil {
+ amountInt := sdkmath.NewIntFromBigInt(tx.Amount)
+ amt = &amountInt
+ }
+
+ if tx.ChainID != nil {
+ chainIDInt := sdkmath.NewIntFromBigInt(tx.ChainID)
+ cid = &chainIDInt
+ }
+
+ if tx.GasPrice != nil {
+ gasPriceInt := sdkmath.NewIntFromBigInt(tx.GasPrice)
+ gp = &gasPriceInt
+ }
+
+ switch {
+ case tx.GasFeeCap != nil:
+ gtc := sdkmath.NewIntFromBigInt(tx.GasTipCap)
+ gfc := sdkmath.NewIntFromBigInt(tx.GasFeeCap)
+
+ txData = &DynamicFeeTx{
+ ChainID: cid,
+ Amount: amt,
+ To: toAddr,
+ GasTipCap: >c,
+ GasFeeCap: &gfc,
+ Nonce: tx.Nonce,
+ GasLimit: tx.GasLimit,
+ Data: tx.Input,
+ Accesses: NewAccessList(tx.Accesses),
+ }
+ case tx.Accesses != nil:
+ txData = &AccessListTx{
+ ChainID: cid,
+ Nonce: tx.Nonce,
+ To: toAddr,
+ Amount: amt,
+ GasLimit: tx.GasLimit,
+ GasPrice: gp,
+ Data: tx.Input,
+ Accesses: NewAccessList(tx.Accesses),
+ }
+ default:
+ txData = &LegacyTx{
+ To: toAddr,
+ Amount: amt,
+ GasPrice: gp,
+ Nonce: tx.Nonce,
+ GasLimit: tx.GasLimit,
+ Data: tx.Input,
+ }
+ }
+
+ dataAny, err := PackTxData(txData)
+ if err != nil {
+ panic(err)
+ }
+
+ msg := MsgEthereumTx{Data: dataAny}
+ msg.Hash = msg.AsTransaction().Hash().Hex()
+ return &msg
+}
+
+// FromEthereumTx populates the message fields from the given ethereum transaction
+func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) error {
+ txData, err := NewTxDataFromTx(tx)
+ if err != nil {
+ return err
+ }
+
+ anyTxData, err := PackTxData(txData)
+ if err != nil {
+ return err
+ }
+
+ msg.Data = anyTxData
+ msg.Hash = tx.Hash().Hex()
+ return nil
+}
+
+// Route returns the route value of an MsgEthereumTx.
+func (msg MsgEthereumTx) Route() string { return RouterKey }
+
+// Type returns the type value of an MsgEthereumTx.
+func (msg MsgEthereumTx) Type() string { return TypeMsgEthereumTx }
+
+// ValidateBasic implements the sdk.Msg interface. It performs basic validation
+// checks of a Transaction. If returns an error if validation fails.
+func (msg MsgEthereumTx) ValidateBasic() error {
+ if msg.From != "" {
+ if err := types.ValidateAddress(msg.From); err != nil {
+ return errorsmod.Wrap(err, "invalid from address")
+ }
+ }
+
+ // Validate Size_ field, should be kept empty
+ if msg.Size_ != 0 {
+ return errorsmod.Wrapf(errortypes.ErrInvalidRequest, "tx size is deprecated")
+ }
+
+ txData, err := UnpackTxData(msg.Data)
+ if err != nil {
+ return errorsmod.Wrap(err, "failed to unpack tx data")
+ }
+
+ gas := txData.GetGas()
+
+ // prevent txs with 0 gas to fill up the mempool
+ if gas == 0 {
+ return errorsmod.Wrap(ErrInvalidGasLimit, "gas limit must not be zero")
+ }
+
+ // prevent gas limit from overflow
+ if g := new(big.Int).SetUint64(gas); !g.IsInt64() {
+ return errorsmod.Wrap(ErrGasOverflow, "gas limit must be less than math.MaxInt64")
+ }
+
+ if err := txData.Validate(); err != nil {
+ return err
+ }
+
+ // Validate Hash field after validated txData to avoid panic
+ txHash := msg.AsTransaction().Hash().Hex()
+ if msg.Hash != txHash {
+ return errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid tx hash %s, expected: %s", msg.Hash, txHash)
+ }
+
+ return nil
+}
+
+// GetMsgs returns a single MsgEthereumTx as an sdk.Msg.
+func (msg *MsgEthereumTx) GetMsgs() []sdk.Msg {
+ return []sdk.Msg{msg}
+}
+
+// GetSigners returns the expected signers for an Ethereum transaction message.
+// For such a message, there should exist only a single 'signer'.
+//
+// NOTE: This method panics if 'Sign' hasn't been called first.
+func (msg *MsgEthereumTx) GetSigners() []sdk.AccAddress {
+ data, err := UnpackTxData(msg.Data)
+ if err != nil {
+ panic(err)
+ }
+
+ sender, err := msg.GetSender(data.GetChainID())
+ if err != nil {
+ panic(err)
+ }
+
+ signer := sdk.AccAddress(sender.Bytes())
+ return []sdk.AccAddress{signer}
+}
+
+// GetSignBytes returns the Amino bytes of an Ethereum transaction message used
+// for signing.
+//
+// NOTE: This method cannot be used as a chain ID is needed to create valid bytes
+// to sign over. Use 'RLPSignBytes' instead.
+func (msg MsgEthereumTx) GetSignBytes() []byte {
+ panic("must use 'RLPSignBytes' with a chain ID to get the valid bytes to sign")
+}
+
+// Sign calculates a secp256k1 ECDSA signature and signs the transaction. It
+// takes a keyring signer and the chainID to sign an Ethereum transaction according to
+// EIP155 standard.
+// This method mutates the transaction as it populates the V, R, S
+// fields of the Transaction's Signature.
+// The function will fail if the sender address is not defined for the msg or if
+// the sender is not registered on the keyring
+func (msg *MsgEthereumTx) Sign(ethSigner ethtypes.Signer, keyringSigner keyring.Signer) error {
+ from := msg.GetFrom()
+ if from.Empty() {
+ return fmt.Errorf("sender address not defined for message")
+ }
+
+ tx := msg.AsTransaction()
+ txHash := ethSigner.Hash(tx)
+
+ sig, _, err := keyringSigner.SignByAddress(from, txHash.Bytes())
+ if err != nil {
+ return err
+ }
+
+ tx, err = tx.WithSignature(ethSigner, sig)
+ if err != nil {
+ return err
+ }
+
+ return msg.FromEthereumTx(tx)
+}
+
+// GetGas implements the GasTx interface. It returns the GasLimit of the transaction.
+func (msg MsgEthereumTx) GetGas() uint64 {
+ txData, err := UnpackTxData(msg.Data)
+ if err != nil {
+ return 0
+ }
+ return txData.GetGas()
+}
+
+// GetFee returns the fee for non dynamic fee tx
+func (msg MsgEthereumTx) GetFee() *big.Int {
+ txData, err := UnpackTxData(msg.Data)
+ if err != nil {
+ return nil
+ }
+ return txData.Fee()
+}
+
+// GetEffectiveFee returns the fee for dynamic fee tx
+func (msg MsgEthereumTx) GetEffectiveFee(baseFee *big.Int) *big.Int {
+ txData, err := UnpackTxData(msg.Data)
+ if err != nil {
+ return nil
+ }
+ return txData.EffectiveFee(baseFee)
+}
+
+// GetFrom loads the ethereum sender address from the sigcache and returns an
+// sdk.AccAddress from its bytes
+func (msg *MsgEthereumTx) GetFrom() sdk.AccAddress {
+ if msg.From == "" {
+ return nil
+ }
+
+ return common.HexToAddress(msg.From).Bytes()
+}
+
+// AsTransaction creates an Ethereum Transaction type from the msg fields
+func (msg MsgEthereumTx) AsTransaction() *ethtypes.Transaction {
+ txData, err := UnpackTxData(msg.Data)
+ if err != nil {
+ return nil
+ }
+
+ return ethtypes.NewTx(txData.AsEthereumData())
+}
+
+// AsMessage creates an Ethereum core.Message from the msg fields
+func (msg MsgEthereumTx) AsMessage(signer ethtypes.Signer, baseFee *big.Int) (core.Message, error) {
+ return msg.AsTransaction().AsMessage(signer, baseFee)
+}
+
+// GetSender extracts the sender address from the signature values using the latest signer for the given chainID.
+func (msg *MsgEthereumTx) GetSender(chainID *big.Int) (common.Address, error) {
+ signer := ethtypes.LatestSignerForChainID(chainID)
+ from, err := signer.Sender(msg.AsTransaction())
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ msg.From = from.Hex()
+ return from, nil
+}
+
+// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
+func (msg MsgEthereumTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
+ return unpacker.UnpackAny(msg.Data, new(TxData))
+}
+
+// UnmarshalBinary decodes the canonical encoding of transactions.
+func (msg *MsgEthereumTx) UnmarshalBinary(b []byte) error {
+ tx := ðtypes.Transaction{}
+ if err := tx.UnmarshalBinary(b); err != nil {
+ return err
+ }
+ return msg.FromEthereumTx(tx)
+}
+
+// BuildTx builds the canonical cosmos tx from ethereum msg
+func (msg *MsgEthereumTx) BuildTx(b client.TxBuilder, evmDenom string) (signing.Tx, error) {
+ builder, ok := b.(authtx.ExtensionOptionsTxBuilder)
+ if !ok {
+ return nil, errors.New("unsupported builder")
+ }
+
+ option, err := codectypes.NewAnyWithValue(&ExtensionOptionsEthereumTx{})
+ if err != nil {
+ return nil, err
+ }
+
+ txData, err := UnpackTxData(msg.Data)
+ if err != nil {
+ return nil, err
+ }
+ fees := make(sdk.Coins, 0)
+ feeAmt := sdkmath.NewIntFromBigInt(txData.Fee())
+ if feeAmt.Sign() > 0 {
+ fees = append(fees, sdk.NewCoin(evmDenom, feeAmt))
+ }
+
+ builder.SetExtensionOptions(option)
+
+ // A valid msg should have empty `From`
+ msg.From = ""
+
+ err = builder.SetMsgs(msg)
+ if err != nil {
+ return nil, err
+ }
+ builder.SetFeeAmount(fees)
+ builder.SetGasLimit(msg.GetGas())
+ tx := builder.GetTx()
+ return tx, nil
+}
+
+// GetSigners returns the expected signers for a MsgUpdateParams message.
+func (m MsgUpdateParams) GetSigners() []sdk.AccAddress {
+ //#nosec G703 -- gosec raises a warning about a non-handled error which we deliberately ignore here
+ addr, _ := sdk.AccAddressFromBech32(m.Authority)
+ return []sdk.AccAddress{addr}
+}
+
+// ValidateBasic does a sanity check of the provided data
+func (m *MsgUpdateParams) ValidateBasic() error {
+ if _, err := sdk.AccAddressFromBech32(m.Authority); err != nil {
+ return errorsmod.Wrap(err, "invalid authority address")
+ }
+
+ return m.Params.Validate()
+}
+
+// GetSignBytes implements the LegacyMsg interface.
+func (m MsgUpdateParams) GetSignBytes() []byte {
+ return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m))
+}
diff --git a/x/evm/types/msg_test.go b/x/evm/types/msg_test.go
new file mode 100644
index 00000000..c9a7b292
--- /dev/null
+++ b/x/evm/types/msg_test.go
@@ -0,0 +1,911 @@
+package types_test
+
+import (
+ "fmt"
+ "math"
+ "math/big"
+ "reflect"
+ "strings"
+ "testing"
+
+ sdkmath "cosmossdk.io/math"
+ "github.com/stretchr/testify/suite"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/evmos/evmos/v19/crypto/ethsecp256k1"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+
+ "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/encoding"
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+const invalidAddress = "0x0000"
+
+type MsgsTestSuite struct {
+ suite.Suite
+
+ signer keyring.Signer
+ from common.Address
+ to common.Address
+ chainID *big.Int
+ hundredBigInt *big.Int
+
+ clientCtx client.Context
+}
+
+func TestMsgsTestSuite(t *testing.T) {
+ suite.Run(t, new(MsgsTestSuite))
+}
+
+func (suite *MsgsTestSuite) SetupTest() {
+ from, privFrom := utiltx.NewAddrKey()
+
+ suite.signer = utiltx.NewSigner(privFrom)
+ suite.from = from
+ suite.to = utiltx.GenerateAddress()
+ suite.chainID = big.NewInt(1)
+ suite.hundredBigInt = big.NewInt(100)
+
+ encodingConfig := encoding.MakeConfig(app.ModuleBasics)
+ suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
+}
+
+func (suite *MsgsTestSuite) TestMsgEthereumTx_Constructor() {
+ evmTx := &types.EvmTxArgs{
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ }
+ msg := types.NewTx(evmTx)
+
+ // suite.Require().Equal(msg.Data.To, suite.to.Hex())
+ suite.Require().Equal(msg.Route(), types.RouterKey)
+ suite.Require().Equal(msg.Type(), types.TypeMsgEthereumTx)
+ // suite.Require().NotNil(msg.To())
+ suite.Require().Equal(msg.GetMsgs(), []sdk.Msg{msg})
+ suite.Require().Panics(func() { msg.GetSigners() })
+ suite.Require().Panics(func() { msg.GetSignBytes() })
+
+ evmTx2 := &types.EvmTxArgs{
+ Nonce: 0,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ }
+ msg = types.NewTx(evmTx2)
+ suite.Require().NotNil(msg)
+ // suite.Require().Empty(msg.Data.To)
+ // suite.Require().Nil(msg.To())
+}
+
+func (suite *MsgsTestSuite) TestMsgEthereumTx_BuildTx() {
+ evmTx := &types.EvmTxArgs{
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ GasPrice: big.NewInt(1),
+ GasFeeCap: big.NewInt(1),
+ GasTipCap: big.NewInt(0),
+ Input: []byte("test"),
+ }
+ testCases := []struct {
+ name string
+ msg *types.MsgEthereumTx
+ expError bool
+ }{
+ {
+ "build tx - pass",
+ types.NewTx(evmTx),
+ false,
+ },
+ {
+ "build tx - fail: nil data",
+ types.NewTx(evmTx),
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ if strings.Contains(tc.name, "nil data") {
+ tc.msg.Data = nil
+ }
+
+ tx, err := tc.msg.BuildTx(suite.clientCtx.TxConfig.NewTxBuilder(), types.DefaultEVMDenom)
+ if tc.expError {
+ suite.Require().Error(err)
+ } else {
+ suite.Require().NoError(err)
+
+ suite.Require().Empty(tx.GetMemo())
+ suite.Require().Empty(tx.GetTimeoutHeight())
+ suite.Require().Equal(uint64(100000), tx.GetGas())
+ suite.Require().Equal(sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdkmath.NewInt(100000))), tx.GetFee())
+ }
+ }
+}
+
+func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasic() {
+ var (
+ hundredInt = big.NewInt(100)
+ validChainID = big.NewInt(9000)
+ zeroInt = big.NewInt(0)
+ minusOneInt = big.NewInt(-1)
+ //nolint:all
+ exp_2_255 = new(big.Int).Exp(big.NewInt(2), big.NewInt(255), nil)
+ )
+ testCases := []struct {
+ msg string
+ to string
+ amount *big.Int
+ gasLimit uint64
+ gasPrice *big.Int
+ gasFeeCap *big.Int
+ gasTipCap *big.Int
+ from string
+ accessList *ethtypes.AccessList
+ chainID *big.Int
+ expectPass bool
+ errMsg string
+ }{
+ {
+ msg: "pass with recipient - Legacy Tx",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "pass with recipient - AccessList Tx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "pass with recipient - DynamicFee Tx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: hundredInt,
+ gasTipCap: zeroInt,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "pass contract - Legacy Tx",
+ to: "",
+ from: suite.from.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "maxInt64 gas limit overflow",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: hundredInt,
+ gasLimit: math.MaxInt64 + 1,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "gas limit must be less than math.MaxInt64",
+ },
+ {
+ msg: "nil amount - Legacy Tx",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: nil,
+ gasLimit: 1000,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "negative amount - Legacy Tx",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: minusOneInt,
+ gasLimit: 1000,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "amount cannot be negative",
+ },
+ {
+ msg: "zero gas limit - Legacy Tx",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: hundredInt,
+ gasLimit: 0,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "gas limit must not be zero",
+ },
+ {
+ msg: "nil gas price - Legacy Tx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: nil,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "gas price cannot be nil",
+ },
+ {
+ msg: "negative gas price - Legacy Tx",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: minusOneInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "gas price cannot be negative",
+ },
+ {
+ msg: "zero gas price - Legacy Tx",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "invalid from address - Legacy Tx",
+ to: suite.to.Hex(),
+ from: invalidAddress,
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "invalid from address",
+ },
+ {
+ msg: "out of bound gas fee - Legacy Tx",
+ to: suite.to.Hex(),
+ from: suite.from.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: exp_2_255,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "out of bound",
+ },
+ {
+ msg: "nil amount - AccessListTx",
+ to: suite.to.Hex(),
+ amount: nil,
+ gasLimit: 1000,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "negative amount - AccessListTx",
+ to: suite.to.Hex(),
+ amount: minusOneInt,
+ gasLimit: 1000,
+ gasPrice: hundredInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "amount cannot be negative",
+ },
+ {
+ msg: "zero gas limit - AccessListTx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 0,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "gas limit must not be zero",
+ },
+ {
+ msg: "nil gas price - AccessListTx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: nil,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "cannot be nil: invalid gas price",
+ },
+ {
+ msg: "negative gas price - AccessListTx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: minusOneInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "gas price cannot be negative",
+ },
+ {
+ msg: "zero gas price - AccessListTx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: true,
+ },
+ {
+ msg: "invalid from address - AccessListTx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ from: invalidAddress,
+ accessList: ðtypes.AccessList{},
+ chainID: validChainID,
+ expectPass: false,
+ errMsg: "invalid from address",
+ },
+ {
+ msg: "chain ID not set on AccessListTx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ chainID: nil,
+ expectPass: false,
+ errMsg: "chain ID must be present on AccessList txs",
+ },
+ {
+ msg: "nil tx.Data - AccessList Tx",
+ to: suite.to.Hex(),
+ amount: hundredInt,
+ gasLimit: 1000,
+ gasPrice: zeroInt,
+ gasFeeCap: nil,
+ gasTipCap: nil,
+ accessList: ðtypes.AccessList{},
+ expectPass: false,
+ errMsg: "failed to unpack tx data",
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.msg, func() {
+ to := common.HexToAddress(tc.to)
+ evmTx := &types.EvmTxArgs{
+ ChainID: tc.chainID,
+ Nonce: 1,
+ To: &to,
+ Amount: tc.amount,
+ GasLimit: tc.gasLimit,
+ GasPrice: tc.gasPrice,
+ GasFeeCap: tc.gasFeeCap,
+ Accesses: tc.accessList,
+ }
+ tx := types.NewTx(evmTx)
+ tx.From = tc.from
+
+ // apply nil assignment here to test ValidateBasic function instead of NewTx
+ if strings.Contains(tc.msg, "nil tx.Data") {
+ tx.Data = nil
+ }
+
+ // for legacy_Tx need to sign tx because the chainID is derived
+ // from signature
+ if tc.accessList == nil && tc.from == suite.from.Hex() {
+ ethSigner := ethtypes.LatestSignerForChainID(tc.chainID)
+ err := tx.Sign(ethSigner, suite.signer)
+ suite.Require().NoError(err)
+ }
+
+ err := tx.ValidateBasic()
+
+ if tc.expectPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ suite.Require().Contains(err.Error(), tc.errMsg)
+ }
+ })
+ }
+}
+
+func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasicAdvanced() {
+ hundredInt := big.NewInt(100)
+ evmTx := &types.EvmTxArgs{
+ ChainID: hundredInt,
+ Nonce: 1,
+ Amount: big.NewInt(10),
+ GasLimit: 100000,
+ GasPrice: big.NewInt(150),
+ GasFeeCap: big.NewInt(200),
+ }
+
+ testCases := []struct {
+ msg string
+ msgBuilder func() *types.MsgEthereumTx
+ expectPass bool
+ }{
+ {
+ "fails - invalid tx hash",
+ func() *types.MsgEthereumTx {
+ msg := types.NewTx(evmTx)
+ msg.Hash = "0x00"
+ return msg
+ },
+ false,
+ },
+ {
+ "fails - invalid size",
+ func() *types.MsgEthereumTx {
+ msg := types.NewTx(evmTx)
+ msg.Size_ = 1
+ return msg
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.msg, func() {
+ err := tc.msgBuilder().ValidateBasic()
+ if tc.expectPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *MsgsTestSuite) TestMsgEthereumTx_Sign() {
+ testCases := []struct {
+ msg string
+ txParams *types.EvmTxArgs
+ ethSigner ethtypes.Signer
+ malleate func(tx *types.MsgEthereumTx)
+ expectPass bool
+ }{
+ {
+ "pass - EIP2930 signer",
+ &types.EvmTxArgs{
+ ChainID: suite.chainID,
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ Accesses: ðtypes.AccessList{},
+ },
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ func(tx *types.MsgEthereumTx) { tx.From = suite.from.Hex() },
+ true,
+ },
+ {
+ "pass - EIP155 signer",
+ &types.EvmTxArgs{
+ ChainID: suite.chainID,
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ },
+ ethtypes.NewEIP155Signer(suite.chainID),
+ func(tx *types.MsgEthereumTx) { tx.From = suite.from.Hex() },
+ true,
+ },
+ {
+ "pass - Homestead signer",
+ &types.EvmTxArgs{
+ ChainID: suite.chainID,
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ },
+ ethtypes.HomesteadSigner{},
+ func(tx *types.MsgEthereumTx) { tx.From = suite.from.Hex() },
+ true,
+ },
+ {
+ "pass - Frontier signer",
+ &types.EvmTxArgs{
+ ChainID: suite.chainID,
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ },
+ ethtypes.FrontierSigner{},
+ func(tx *types.MsgEthereumTx) { tx.From = suite.from.Hex() },
+ true,
+ },
+ {
+ "no from address ",
+ &types.EvmTxArgs{
+ ChainID: suite.chainID,
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ Accesses: ðtypes.AccessList{},
+ },
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ func(tx *types.MsgEthereumTx) { tx.From = "" },
+ false,
+ },
+ {
+ "from address ≠signer address",
+ &types.EvmTxArgs{
+ ChainID: suite.chainID,
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 100000,
+ Input: []byte("test"),
+ Accesses: ðtypes.AccessList{},
+ },
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ func(tx *types.MsgEthereumTx) { tx.From = suite.to.Hex() },
+ false,
+ },
+ }
+
+ for i, tc := range testCases {
+ tx := types.NewTx(tc.txParams)
+ tc.malleate(tx)
+ err := tx.Sign(tc.ethSigner, suite.signer)
+ if tc.expectPass {
+ suite.Require().NoError(err, "valid test %d failed: %s", i, tc.msg)
+
+ sender, err := tx.GetSender(suite.chainID)
+ suite.Require().NoError(err, tc.msg)
+ suite.Require().Equal(tx.From, sender.Hex(), tc.msg)
+ } else {
+ suite.Require().Error(err, "invalid test %d passed: %s", i, tc.msg)
+ }
+ }
+}
+
+func (suite *MsgsTestSuite) TestMsgEthereumTx_Getters() {
+ evmTx := &types.EvmTxArgs{
+ ChainID: suite.chainID,
+ Nonce: 0,
+ To: &suite.to,
+ GasLimit: 50,
+ GasPrice: suite.hundredBigInt,
+ Accesses: ðtypes.AccessList{},
+ }
+ testCases := []struct {
+ name string
+ ethSigner ethtypes.Signer
+ exp *big.Int
+ }{
+ {
+ "get fee - pass",
+
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ big.NewInt(5000),
+ },
+ {
+ "get fee - fail: nil data",
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ nil,
+ },
+ {
+ "get effective fee - pass",
+
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ big.NewInt(5000),
+ },
+ {
+ "get effective fee - fail: nil data",
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ nil,
+ },
+ {
+ "get gas - pass",
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ big.NewInt(50),
+ },
+ {
+ "get gas - fail: nil data",
+ ethtypes.NewEIP2930Signer(suite.chainID),
+ big.NewInt(0),
+ },
+ }
+
+ var fee, effFee *big.Int
+ for _, tc := range testCases {
+ tx := types.NewTx(evmTx)
+ if strings.Contains(tc.name, "nil data") {
+ tx.Data = nil
+ }
+ switch {
+ case strings.Contains(tc.name, "get fee"):
+ fee = tx.GetFee()
+ suite.Require().Equal(tc.exp, fee)
+ case strings.Contains(tc.name, "get effective fee"):
+ effFee = tx.GetEffectiveFee(big.NewInt(0))
+ suite.Require().Equal(tc.exp, effFee)
+ case strings.Contains(tc.name, "get gas"):
+ gas := tx.GetGas()
+ suite.Require().Equal(tc.exp.Uint64(), gas)
+ }
+ }
+}
+
+func (suite *MsgsTestSuite) TestFromEthereumTx() {
+ privkey, _ := ethsecp256k1.GenerateKey()
+ ethPriv, err := privkey.ToECDSA()
+ suite.Require().NoError(err)
+
+ // 10^80 is more than 256 bits
+ //nolint:all
+ exp_10_80 := new(big.Int).Mul(big.NewInt(1), new(big.Int).Exp(big.NewInt(10), big.NewInt(80), nil))
+
+ testCases := []struct {
+ msg string
+ expectPass bool
+ buildTx func() *ethtypes.Transaction
+ }{
+ {"success, normal tx", true, func() *ethtypes.Transaction {
+ tx := ethtypes.NewTx(ðtypes.AccessListTx{
+ Nonce: 0,
+ Data: nil,
+ To: &suite.to,
+ Value: big.NewInt(10),
+ GasPrice: big.NewInt(1),
+ Gas: 21000,
+ })
+ tx, err := ethtypes.SignTx(tx, ethtypes.NewEIP2930Signer(suite.chainID), ethPriv)
+ suite.Require().NoError(err)
+ return tx
+ }},
+ {"success, DynamicFeeTx", true, func() *ethtypes.Transaction {
+ tx := ethtypes.NewTx(ðtypes.DynamicFeeTx{
+ Nonce: 0,
+ Data: nil,
+ To: &suite.to,
+ Value: big.NewInt(10),
+ Gas: 21000,
+ })
+ tx, err := ethtypes.SignTx(tx, ethtypes.NewLondonSigner(suite.chainID), ethPriv)
+ suite.Require().NoError(err)
+ return tx
+ }},
+ {"fail, value bigger than 256bits - AccessListTx", false, func() *ethtypes.Transaction {
+ tx := ethtypes.NewTx(ðtypes.AccessListTx{
+ Nonce: 0,
+ Data: nil,
+ To: &suite.to,
+ Value: exp_10_80,
+ GasPrice: big.NewInt(1),
+ Gas: 21000,
+ })
+ tx, err := ethtypes.SignTx(tx, ethtypes.NewEIP2930Signer(suite.chainID), ethPriv)
+ suite.Require().NoError(err)
+ return tx
+ }},
+ {"fail, gas price bigger than 256bits - AccessListTx", false, func() *ethtypes.Transaction {
+ tx := ethtypes.NewTx(ðtypes.AccessListTx{
+ Nonce: 0,
+ Data: nil,
+ To: &suite.to,
+ Value: big.NewInt(1),
+ GasPrice: exp_10_80,
+ Gas: 21000,
+ })
+ tx, err := ethtypes.SignTx(tx, ethtypes.NewEIP2930Signer(suite.chainID), ethPriv)
+ suite.Require().NoError(err)
+ return tx
+ }},
+ {"fail, value bigger than 256bits - LegacyTx", false, func() *ethtypes.Transaction {
+ tx := ethtypes.NewTx(ðtypes.LegacyTx{
+ Nonce: 0,
+ Data: nil,
+ To: &suite.to,
+ Value: exp_10_80,
+ GasPrice: big.NewInt(1),
+ Gas: 21000,
+ })
+ tx, err := ethtypes.SignTx(tx, ethtypes.NewEIP2930Signer(suite.chainID), ethPriv)
+ suite.Require().NoError(err)
+ return tx
+ }},
+ {"fail, gas price bigger than 256bits - LegacyTx", false, func() *ethtypes.Transaction {
+ tx := ethtypes.NewTx(ðtypes.LegacyTx{
+ Nonce: 0,
+ Data: nil,
+ To: &suite.to,
+ Value: big.NewInt(1),
+ GasPrice: exp_10_80,
+ Gas: 21000,
+ })
+ tx, err := ethtypes.SignTx(tx, ethtypes.NewEIP2930Signer(suite.chainID), ethPriv)
+ suite.Require().NoError(err)
+ return tx
+ }},
+ }
+
+ for _, tc := range testCases {
+ ethTx := tc.buildTx()
+ tx := &types.MsgEthereumTx{}
+ err := tx.FromEthereumTx(ethTx)
+ if tc.expectPass {
+ suite.Require().NoError(err)
+
+ // round-trip test
+ suite.Require().NoError(assertEqual(tx.AsTransaction(), ethTx))
+ } else {
+ suite.Require().Error(err)
+ }
+ }
+}
+
+// TestTransactionCoding tests serializing/de-serializing to/from rlp and JSON.
+// adapted from go-ethereum
+func (suite *MsgsTestSuite) TestTransactionCoding() {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ suite.T().Fatalf("could not generate key: %v", err)
+ }
+ var (
+ signer = ethtypes.NewEIP2930Signer(common.Big1)
+ addr = common.HexToAddress("0x0000000000000000000000000000000000000001")
+ recipient = common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
+ accesses = ethtypes.AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}}
+ )
+ for i := uint64(0); i < 500; i++ {
+ var txdata ethtypes.TxData
+ switch i % 5 {
+ case 0:
+ // Legacy tx.
+ txdata = ðtypes.LegacyTx{
+ Nonce: i,
+ To: &recipient,
+ Gas: 1,
+ GasPrice: big.NewInt(2),
+ Data: []byte("abcdef"),
+ }
+ case 1:
+ // Legacy tx contract creation.
+ txdata = ðtypes.LegacyTx{
+ Nonce: i,
+ Gas: 1,
+ GasPrice: big.NewInt(2),
+ Data: []byte("abcdef"),
+ }
+ case 2:
+ // Tx with non-zero access list.
+ txdata = ðtypes.AccessListTx{
+ ChainID: big.NewInt(1),
+ Nonce: i,
+ To: &recipient,
+ Gas: 123457,
+ GasPrice: big.NewInt(10),
+ AccessList: accesses,
+ Data: []byte("abcdef"),
+ }
+ case 3:
+ // Tx with empty access list.
+ txdata = ðtypes.AccessListTx{
+ ChainID: big.NewInt(1),
+ Nonce: i,
+ To: &recipient,
+ Gas: 123457,
+ GasPrice: big.NewInt(10),
+ Data: []byte("abcdef"),
+ }
+ case 4:
+ // Contract creation with access list.
+ txdata = ðtypes.AccessListTx{
+ ChainID: big.NewInt(1),
+ Nonce: i,
+ Gas: 123457,
+ GasPrice: big.NewInt(10),
+ AccessList: accesses,
+ }
+ }
+ tx, err := ethtypes.SignNewTx(key, signer, txdata)
+ if err != nil {
+ suite.T().Fatalf("could not sign transaction: %v", err)
+ }
+ // RLP
+ parsedTx, err := encodeDecodeBinary(tx)
+ if err != nil {
+ suite.T().Fatal(err)
+ }
+ err = assertEqual(parsedTx.AsTransaction(), tx)
+ suite.Require().NoError(err)
+ }
+}
+
+func encodeDecodeBinary(tx *ethtypes.Transaction) (*types.MsgEthereumTx, error) {
+ data, err := tx.MarshalBinary()
+ if err != nil {
+ return nil, fmt.Errorf("rlp encoding failed: %v", err)
+ }
+ parsedTx := &types.MsgEthereumTx{}
+ if err := parsedTx.UnmarshalBinary(data); err != nil {
+ return nil, fmt.Errorf("rlp decoding failed: %v", err)
+ }
+ return parsedTx, nil
+}
+
+func assertEqual(orig *ethtypes.Transaction, cpy *ethtypes.Transaction) error {
+ // compare nonce, price, gaslimit, recipient, amount, payload, V, R, S
+ if want, got := orig.Hash(), cpy.Hash(); want != got {
+ return fmt.Errorf("parsed tx differs from original tx, want %v, got %v", want, got)
+ }
+ if want, got := orig.ChainId(), cpy.ChainId(); want.Cmp(got) != 0 {
+ return fmt.Errorf("invalid chain id, want %d, got %d", want, got)
+ }
+ if orig.AccessList() != nil {
+ if !reflect.DeepEqual(orig.AccessList(), cpy.AccessList()) {
+ return fmt.Errorf("access list wrong")
+ }
+ }
+ return nil
+}
diff --git a/x/evm/types/opcodes_hooks.go b/x/evm/types/opcodes_hooks.go
new file mode 100644
index 00000000..c2259bda
--- /dev/null
+++ b/x/evm/types/opcodes_hooks.go
@@ -0,0 +1,70 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package types
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// OpCodeHooks extends the geth OpCodeHooks interface to add custom hooks for EVM operations.
+// The hooks run before the respective opcode execution every time they are called.
+type OpCodeHooks interface {
+ vm.OpCodeHooks
+ AddCallHooks(hooks ...CallHook)
+ AddCreateHooks(hooks ...CreateHook)
+}
+
+// DefaultOpCodesHooks is the default implementation of OpCodeHooks for EVMOS chain
+// The hooks are used to enforce access control policies on EVM operations.
+// They are ran BEFORE the respective opcode execution every time they are called.
+type DefaultOpCodesHooks struct {
+ callHooks []CallHook
+ createHooks []CreateHook
+}
+
+// Make sure we comply with geth's OpCodeHooks interface
+var _ OpCodeHooks = (*DefaultOpCodesHooks)(nil)
+
+type (
+ CreateHook func(ev *vm.EVM, caller common.Address) error
+ CallHook func(ev *vm.EVM, caller common.Address, recipient common.Address) error
+)
+
+// NewDefaultOpCodesHooks creates a new DefaultOpCodesHooks instance
+func NewDefaultOpCodesHooks() OpCodeHooks {
+ return &DefaultOpCodesHooks{}
+}
+
+// AddCallHooks adds one or more hooks to the queue to be executed before the CALL opcode.
+// Hooks will be executed in the order they are added.
+func (h *DefaultOpCodesHooks) AddCallHooks(hooks ...CallHook) {
+ h.callHooks = append(h.callHooks, hooks...)
+}
+
+// AddCreateHooks adds one or more hooks to the queue to be executed before the CREATE opcode.
+// Hooks will be executed in the order they are added.
+func (h *DefaultOpCodesHooks) AddCreateHooks(hooks ...CreateHook) {
+ h.createHooks = append(h.createHooks, hooks...)
+}
+
+// CreateHook checks if the caller has permission to deploy contracts
+func (h *DefaultOpCodesHooks) CreateHook(evm *vm.EVM, caller common.Address) error {
+ for _, hook := range h.createHooks {
+ if err := hook(evm, caller); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// CallHook checks if the caller has permission to perform a call
+func (h *DefaultOpCodesHooks) CallHook(evm *vm.EVM, caller common.Address, recipient common.Address) error {
+ for _, hook := range h.callHooks {
+ if err := hook(evm, caller, recipient); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/x/evm/types/params.go b/x/evm/types/params.go
new file mode 100644
index 00000000..59e23c73
--- /dev/null
+++ b/x/evm/types/params.go
@@ -0,0 +1,299 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "fmt"
+ "math/big"
+ "slices"
+
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/types"
+ "github.com/evmos/evmos/v19/utils"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+var (
+ // DefaultEVMDenom defines the default EVM denomination on Evmos
+ DefaultEVMDenom = utils.BaseDenom
+ // DefaultAllowUnprotectedTxs rejects all unprotected txs (i.e false)
+ DefaultAllowUnprotectedTxs = false
+ // DefaultStaticPrecompiles defines the default active precompiles
+ DefaultStaticPrecompiles = []string{
+ P256PrecompileAddress, // P256 precompile
+ Bech32PrecompileAddress, // Bech32 precompile
+ StakingPrecompileAddress, // Staking precompile
+ DistributionPrecompileAddress, // Distribution precompile
+ ICS20PrecompileAddress, // ICS20 transfer precompile
+ VestingPrecompileAddress, // Vesting precompile
+ BankPrecompileAddress, // Bank precompile
+ }
+ // DefaultExtraEIPs defines the default extra EIPs to be included
+ // On v15, EIP 3855 was enabled
+ DefaultExtraEIPs = []string{"ethereum_3855"}
+ DefaultEVMChannels = []string{
+ "channel-10", // Injective
+ "channel-31", // Cronos
+ "channel-83", // Kava
+ }
+ DefaultCreateAllowlistAddresses []string
+ DefaultCallAllowlistAddresses []string
+ DefaultAccessControl = AccessControl{
+ Create: AccessControlType{
+ AccessType: AccessTypePermissionless,
+ AccessControlList: DefaultCreateAllowlistAddresses,
+ },
+ Call: AccessControlType{
+ AccessType: AccessTypePermissionless,
+ AccessControlList: DefaultCreateAllowlistAddresses,
+ },
+ }
+)
+
+// NewParams creates a new Params instance
+func NewParams(
+ evmDenom string,
+ allowUnprotectedTxs bool,
+ config ChainConfig,
+ extraEIPs []string,
+ activeStaticPrecompiles,
+ evmChannels []string,
+ accessControl AccessControl,
+) Params {
+ return Params{
+ EvmDenom: evmDenom,
+ AllowUnprotectedTxs: allowUnprotectedTxs,
+ ExtraEIPs: extraEIPs,
+ ChainConfig: config,
+ ActiveStaticPrecompiles: activeStaticPrecompiles,
+ EVMChannels: evmChannels,
+ AccessControl: accessControl,
+ }
+}
+
+// DefaultParams returns default evm parameters
+func DefaultParams() Params {
+ return Params{
+ EvmDenom: DefaultEVMDenom,
+ ChainConfig: DefaultChainConfig(),
+ ExtraEIPs: DefaultExtraEIPs,
+ AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
+ ActiveStaticPrecompiles: DefaultStaticPrecompiles,
+ EVMChannels: DefaultEVMChannels,
+ AccessControl: DefaultAccessControl,
+ }
+}
+
+// validateChannels checks if channels ids are valid
+func validateChannels(i interface{}) error {
+ channels, ok := i.([]string)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ for _, channel := range channels {
+ if err := host.ChannelIdentifierValidator(channel); err != nil {
+ return errorsmod.Wrap(
+ channeltypes.ErrInvalidChannelIdentifier, err.Error(),
+ )
+ }
+ }
+
+ return nil
+}
+
+// Validate performs basic validation on evm parameters.
+func (p Params) Validate() error {
+ if err := validateEVMDenom(p.EvmDenom); err != nil {
+ return err
+ }
+
+ if err := validateEIPs(p.ExtraEIPs); err != nil {
+ return err
+ }
+
+ if err := validateBool(p.AllowUnprotectedTxs); err != nil {
+ return err
+ }
+
+ if err := validateChainConfig(p.ChainConfig); err != nil {
+ return err
+ }
+
+ if err := ValidatePrecompiles(p.ActiveStaticPrecompiles); err != nil {
+ return err
+ }
+
+ if err := p.AccessControl.Validate(); err != nil {
+ return err
+ }
+
+ return validateChannels(p.EVMChannels)
+}
+
+// EIPs returns the ExtraEIPS as a slice.
+func (p Params) EIPs() []string {
+ eips := make([]string, len(p.ExtraEIPs))
+ copy(eips, p.ExtraEIPs)
+ return eips
+}
+
+// GetActiveStaticPrecompilesAddrs is a util function that the Active Precompiles
+// as a slice of addresses.
+func (p Params) GetActiveStaticPrecompilesAddrs() []common.Address {
+ precompiles := make([]common.Address, len(p.ActiveStaticPrecompiles))
+ for i, precompile := range p.ActiveStaticPrecompiles {
+ precompiles[i] = common.HexToAddress(precompile)
+ }
+ return precompiles
+}
+
+// IsEVMChannel returns true if the channel provided is in the list of
+// EVM channels
+func (p Params) IsEVMChannel(channel string) bool {
+ return slices.Contains(p.EVMChannels, channel)
+}
+
+func (ac AccessControl) Validate() error {
+ if err := ac.Create.Validate(); err != nil {
+ return err
+ }
+
+ if err := ac.Call.Validate(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (act AccessControlType) Validate() error {
+ if err := validateAccessType(act.AccessType); err != nil {
+ return err
+ }
+
+ if err := validateAllowlistAddresses(act.AccessControlList); err != nil {
+ return err
+ }
+ return nil
+}
+
+func validateAccessType(i interface{}) error {
+ accessType, ok := i.(AccessType)
+ if !ok {
+ return fmt.Errorf("invalid access type type: %T", i)
+ }
+
+ switch accessType {
+ case AccessTypePermissionless, AccessTypeRestricted, AccessTypePermissioned:
+ return nil
+ default:
+ return fmt.Errorf("invalid access type: %s", accessType)
+ }
+}
+
+func validateAllowlistAddresses(i interface{}) error {
+ addresses, ok := i.([]string)
+ if !ok {
+ return fmt.Errorf("invalid whitelist addresses type: %T", i)
+ }
+
+ for _, address := range addresses {
+ if err := types.ValidateAddress(address); err != nil {
+ return fmt.Errorf("invalid whitelist address: %s", address)
+ }
+ }
+ return nil
+}
+
+func validateEVMDenom(i interface{}) error {
+ denom, ok := i.(string)
+ if !ok {
+ return fmt.Errorf("invalid parameter EVM denom type: %T", i)
+ }
+
+ return sdk.ValidateDenom(denom)
+}
+
+func validateBool(i interface{}) error {
+ _, ok := i.(bool)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+ return nil
+}
+
+func validateEIPs(i interface{}) error {
+ eips, ok := i.([]string)
+ if !ok {
+ return fmt.Errorf("invalid EIP slice type: %T", i)
+ }
+
+ uniqueEIPs := make(map[string]struct{})
+
+ for _, eip := range eips {
+ if !vm.ExistsEipActivator(eip) {
+ return fmt.Errorf("EIP %s is not activateable, valid EIPs are: %s", eip, vm.ActivateableEips())
+ }
+
+ if err := vm.ValidateEIPName(eip); err != nil {
+ return fmt.Errorf("EIP %s name is not valid", eip)
+ }
+
+ if _, ok := uniqueEIPs[eip]; ok {
+ return fmt.Errorf("found duplicate EIP: %s", eip)
+ }
+ uniqueEIPs[eip] = struct{}{}
+
+ }
+
+ return nil
+}
+
+func validateChainConfig(i interface{}) error {
+ cfg, ok := i.(ChainConfig)
+ if !ok {
+ return fmt.Errorf("invalid chain config type: %T", i)
+ }
+
+ return cfg.Validate()
+}
+
+// ValidatePrecompiles checks if the precompile addresses are valid and unique.
+func ValidatePrecompiles(i interface{}) error {
+ precompiles, ok := i.([]string)
+ if !ok {
+ return fmt.Errorf("invalid precompile slice type: %T", i)
+ }
+
+ seenPrecompiles := make(map[string]struct{})
+ for _, precompile := range precompiles {
+ if _, ok := seenPrecompiles[precompile]; ok {
+ return fmt.Errorf("duplicate precompile %s", precompile)
+ }
+
+ if err := types.ValidateAddress(precompile); err != nil {
+ return fmt.Errorf("invalid precompile %s", precompile)
+ }
+
+ seenPrecompiles[precompile] = struct{}{}
+ }
+
+ // NOTE: Check that the precompiles are sorted. This is required
+ // to ensure determinism
+ if !slices.IsSorted(precompiles) {
+ return fmt.Errorf("precompiles need to be sorted: %s", precompiles)
+ }
+
+ return nil
+}
+
+// IsLondon returns if london hardfork is enabled.
+func IsLondon(ethConfig *params.ChainConfig, height int64) bool {
+ return ethConfig.IsLondon(big.NewInt(height))
+}
diff --git a/x/evm/types/params_legacy.go b/x/evm/types/params_legacy.go
new file mode 100644
index 00000000..4cf1b767
--- /dev/null
+++ b/x/evm/types/params_legacy.go
@@ -0,0 +1,36 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
+
+// Parameter keys
+var (
+ ParamStoreKeyEVMDenom = []byte("EVMDenom")
+ ParamStoreKeyEnableCreate = []byte("EnableCreate")
+ ParamStoreKeyEnableCall = []byte("EnableCall")
+ ParamStoreKeyExtraEIPs = []byte("EnableExtraEIPs")
+ ParamStoreKeyChainConfig = []byte("ChainConfig")
+ ParamStoreKeyAllowUnprotectedTxs = []byte("AllowUnprotectedTxs")
+)
+
+// Deprecated: ParamKeyTable returns the parameter key table.
+// Usage of x/params to manage parameters is deprecated in favor of x/gov
+// controlled execution of MsgUpdateParams messages. These types remain solely
+// for migration purposes and will be removed in a future release.
+func ParamKeyTable() paramtypes.KeyTable {
+ return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
+}
+
+// Deprecated: ParamSetPairs returns the parameter set pairs.
+// Usage of x/params to manage parameters is deprecated in favor of x/gov
+// controlled execution of MsgUpdateParams messages. These types remain solely
+// for migration purposes and will be removed in a future release.
+func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
+ return paramtypes.ParamSetPairs{
+ paramtypes.NewParamSetPair(ParamStoreKeyEVMDenom, &p.EvmDenom, validateEVMDenom),
+ paramtypes.NewParamSetPair(ParamStoreKeyExtraEIPs, &p.ExtraEIPs, validateEIPs),
+ paramtypes.NewParamSetPair(ParamStoreKeyChainConfig, &p.ChainConfig, validateChainConfig),
+ paramtypes.NewParamSetPair(ParamStoreKeyAllowUnprotectedTxs, &p.AllowUnprotectedTxs, validateBool),
+ }
+}
diff --git a/x/evm/types/params_test.go b/x/evm/types/params_test.go
new file mode 100644
index 00000000..52045cf4
--- /dev/null
+++ b/x/evm/types/params_test.go
@@ -0,0 +1,166 @@
+package types
+
+import (
+ "testing"
+
+ ethparams "github.com/ethereum/go-ethereum/params"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestParamsValidate(t *testing.T) {
+ t.Parallel()
+
+ extraEips := []string{"ethereum_2929", "ethereum_1884", "ethereum_1344"}
+ testCases := []struct {
+ name string
+ params Params
+ expPass bool
+ errContains string
+ }{
+ {
+ name: "default",
+ params: DefaultParams(),
+ expPass: true,
+ },
+ {
+ name: "valid",
+ params: NewParams(DefaultEVMDenom, false, DefaultChainConfig(), extraEips, nil, nil, DefaultAccessControl),
+ expPass: true,
+ },
+ {
+ name: "empty",
+ params: Params{},
+ errContains: "invalid denom: ", // NOTE: this returns the first error that occurs
+ },
+ {
+ name: "invalid evm denom",
+ params: Params{
+ EvmDenom: "@!#!@$!@5^32",
+ },
+ errContains: "invalid denom: @!#!@$!@5^32",
+ },
+ {
+ name: "invalid eip",
+ params: Params{
+ EvmDenom: DefaultEVMDenom,
+ ExtraEIPs: []string{"os_1000000"},
+ },
+ errContains: "EIP os_1000000 is not activateable, valid EIPs are",
+ },
+ {
+ name: "unsorted precompiles",
+ params: Params{
+ EvmDenom: DefaultEVMDenom,
+ ActiveStaticPrecompiles: []string{
+ "0x0000000000000000000000000000000000000801",
+ "0x0000000000000000000000000000000000000800",
+ },
+ },
+ errContains: "precompiles need to be sorted",
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ if !tc.expPass {
+ // NOTE: check that the necessary information is provided. Otherwise, a false
+ // error message could be accepted when checking for an empty string.
+ require.NotEmpty(t, tc.errContains, "expected test case to provide expected error message")
+ }
+
+ err := tc.params.Validate()
+
+ if tc.expPass {
+ require.NoError(t, err, "expected parameters to be valid")
+ } else {
+ require.Error(t, err, "expected parameters to be invalid")
+ require.ErrorContains(t, err, tc.errContains, "expected different error message")
+ }
+ })
+ }
+}
+
+func TestParamsEIPs(t *testing.T) {
+ extraEips := []string{"ethereum_2929", "ethereum_1884", "ethereum_1344"}
+ params := NewParams("ara", false, DefaultChainConfig(), extraEips, nil, nil, DefaultAccessControl)
+ actual := params.EIPs()
+
+ require.Equal(t, []string{"ethereum_2929", "ethereum_1884", "ethereum_1344"}, actual)
+}
+
+func TestParamsValidatePriv(t *testing.T) {
+ require.Error(t, validateEVMDenom(false))
+ require.NoError(t, validateEVMDenom("inj"))
+ require.Error(t, validateBool(""))
+ require.NoError(t, validateBool(true))
+ require.Error(t, validateEIPs(""))
+ require.Error(t, validateEIPs([]int64{1884}))
+ require.NoError(t, validateEIPs([]string{"ethereum_1884"}))
+ require.ErrorContains(t, validateEIPs([]string{"ethereum_1884", "ethereum_1884", "ethereum_1885"}), "duplicate EIP: ethereum_1884")
+ require.NoError(t, validateChannels([]string{"channel-0"}))
+ require.Error(t, validateChannels(false))
+ require.Error(t, validateChannels(int64(123)))
+ require.Error(t, validateChannels(""))
+}
+
+func TestValidateChainConfig(t *testing.T) {
+ testCases := []struct {
+ name string
+ i interface{}
+ expError bool
+ }{
+ {
+ "invalid chain config type",
+ "string",
+ true,
+ },
+ {
+ "valid chain config type",
+ DefaultChainConfig(),
+ false,
+ },
+ }
+ for _, tc := range testCases {
+ err := validateChainConfig(tc.i)
+
+ if tc.expError {
+ require.Error(t, err, tc.name)
+ } else {
+ require.NoError(t, err, tc.name)
+ }
+ }
+}
+
+func TestIsLondon(t *testing.T) {
+ testCases := []struct {
+ name string
+ height int64
+ result bool
+ }{
+ {
+ "Before london block",
+ 5,
+ false,
+ },
+ {
+ "After london block",
+ 12_965_001,
+ true,
+ },
+ {
+ "london block",
+ 12_965_000,
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ ethConfig := ethparams.MainnetChainConfig
+ require.Equal(t, IsLondon(ethConfig, tc.height), tc.result)
+ }
+}
diff --git a/x/evm/types/permissions.go b/x/evm/types/permissions.go
new file mode 100644
index 00000000..2cbb2636
--- /dev/null
+++ b/x/evm/types/permissions.go
@@ -0,0 +1,144 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package types
+
+import (
+ "fmt"
+ "slices"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// PermissionPolicy is the interface that defines the permission policy for contract creation and calls.
+// It is used to enforce access control policies on EVM operations.
+// The policy is ran BEFORE the respective opcode execution every time they are called.
+type PermissionPolicy interface {
+ // CanCreate checks if the contract creation is allowed.
+ CanCreate(signer, caller common.Address) bool
+ // CanCall checks if the any type of CALL opcode execution is allowed. This includes
+ // contract calls and transfers.
+ CanCall(signer, caller, recipient common.Address) bool
+
+ // GetCallHook returns a CallHook that checks if the caller is allowed to perform a call.
+ // This is used by the EVM opcode hooks to enforce access control policies.
+ GetCallHook(signer common.Address) CallHook
+ // GetCreateHook returns a CreateHook that checks if the caller is allowed to deploy contracts.
+ // This is used by the EVM opcode hooks to enforce access control policies.
+ GetCreateHook(signer common.Address) CreateHook
+}
+
+// RestrictedPermissionPolicy is a permission policy that restricts contract creation and calls based on a set of accessControl.
+// Note that all the properties are private, this enforces the permissions not to be modified
+// anywhere else within the code.
+// For users that require a custom permission policy, they can implement the PermissionPolicy interface.
+type RestrictedPermissionPolicy struct {
+ accessControl *AccessControl
+ canCreate callerFn
+ canCall callerFn
+}
+
+func NewRestrictedPermissionPolicy(accessControl *AccessControl, signer common.Address) PermissionPolicy {
+ // generate create function at instantiation for signer address to be check only once
+ // since it remains constant
+ canCreate := getCanCreateFn(accessControl, signer)
+ canCall := getCanCallFn(accessControl, signer)
+ return RestrictedPermissionPolicy{
+ accessControl: accessControl,
+ canCreate: canCreate,
+ canCall: canCall,
+ }
+}
+
+var _ PermissionPolicy = RestrictedPermissionPolicy{}
+
+// GetCallHook returns a CallHook that checks if the caller is allowed to perform a call.
+func (p RestrictedPermissionPolicy) GetCallHook(signer common.Address) CallHook {
+ return func(_ *vm.EVM, caller, recipient common.Address) error {
+ if p.CanCall(signer, caller, recipient) {
+ return nil
+ }
+ return fmt.Errorf("caller address %s does not have permission to perform a call", caller)
+ }
+}
+
+// GetCreateHook returns a CreateHook that checks if the caller is allowed to deploy contracts.
+func (p RestrictedPermissionPolicy) GetCreateHook(signer common.Address) CreateHook {
+ return func(_ *vm.EVM, caller common.Address) error {
+ if p.CanCreate(signer, caller) {
+ return nil
+ }
+ return fmt.Errorf("caller address %s does not have permission to deploy contracts", caller)
+ }
+}
+
+// CanCreate implements the PermissionPolicy interface.
+// It allows contract creation if access type is set to everybody.
+// Otherwise, it checks if:
+// - The signer is allowed to do so.
+// - If the signer is not allowed, then we check if the caller is allowed to do so.
+func (p RestrictedPermissionPolicy) CanCreate(_, caller common.Address) bool {
+ return p.canCreate(caller)
+}
+
+type callerFn = func(caller common.Address) bool
+
+func getCanCreateFn(accessControl *AccessControl, signer common.Address) callerFn {
+ addresses := accessControl.Create.AccessControlList
+
+ switch accessControl.Create.AccessType {
+ case AccessTypePermissionless:
+ return permissionlessCheckFn(addresses, signer)
+ case AccessTypeRestricted:
+ return func(_ common.Address) bool { return false }
+ case AccessTypePermissioned:
+ return permissionedCheckFn(addresses, signer)
+ }
+ return func(_ common.Address) bool { return false }
+}
+
+// CanCreate implements the PermissionPolicy interface.
+// It allows calls if access type is set to everybody.
+// Otherwise, it checks if:
+// - The signer is allowed to do so.
+// - If the signer is not allowed, then we check if the caller is allowed to do so.
+func (p RestrictedPermissionPolicy) CanCall(_, caller, _ common.Address) bool {
+ return p.canCall(caller)
+}
+
+func getCanCallFn(accessControl *AccessControl, signer common.Address) callerFn {
+ addresses := accessControl.Call.AccessControlList
+
+ switch accessControl.Call.AccessType {
+ case AccessTypePermissionless:
+ return permissionlessCheckFn(addresses, signer)
+ case AccessTypeRestricted:
+ return func(_ common.Address) bool { return false }
+ case AccessTypePermissioned:
+ return permissionedCheckFn(addresses, signer)
+ }
+ return func(_ common.Address) bool { return false }
+}
+
+// permissionlessCheckFn returns a callerFn that returns true unless the signer or the caller is
+// within the addresses slice.
+func permissionlessCheckFn(addresses []string, signer common.Address) callerFn {
+ strSigner := signer.String()
+ isSignerBlocked := !slices.Contains(addresses, strSigner)
+ return func(caller common.Address) bool {
+ strCaller := caller.String()
+ return isSignerBlocked && !slices.Contains(addresses, strCaller)
+ }
+}
+
+// permissionedCheckFn returns a callerFn that returns true if the signer or caller
+// is within the addresses slice.
+func permissionedCheckFn(addresses []string, signer common.Address) callerFn {
+ strSigner := signer.String()
+ isSignerAllowed := slices.Contains(addresses, strSigner)
+ return func(caller common.Address) bool {
+ strCaller := caller.String()
+ return isSignerAllowed || slices.Contains(addresses, strCaller)
+ }
+}
diff --git a/x/evm/types/permissions_test.go b/x/evm/types/permissions_test.go
new file mode 100644
index 00000000..5e7961f8
--- /dev/null
+++ b/x/evm/types/permissions_test.go
@@ -0,0 +1,233 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package types_test
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ testkeyring "github.com/evmos/evmos/v19/testutil/integration/evmos/keyring"
+ "github.com/evmos/evmos/v19/x/evm/types"
+ "github.com/stretchr/testify/suite"
+)
+
+type UnitTestSuite struct {
+ suite.Suite
+}
+
+func TestPermissionsSuite(t *testing.T) {
+ suite.Run(t, new(UnitTestSuite))
+}
+
+func (suite *UnitTestSuite) TestAccessControl() {
+ keyring := testkeyring.New(2)
+
+ testCases := []struct {
+ name string
+ getAccessControl func() types.AccessControl
+ canCall bool
+ canCreate bool
+ signer common.Address
+ caller common.Address
+ recipient common.Address
+ }{
+ {
+ name: "should allow call and create with default accessControl",
+ getAccessControl: func() types.AccessControl {
+ return types.DefaultParams().AccessControl
+ },
+ canCall: true,
+ canCreate: true,
+ signer: keyring.GetAddr(0),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(0),
+ },
+ {
+ name: "should not allow call and create with nobody accessControl",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Create.AccessType = types.AccessTypeRestricted
+ p.Call.AccessType = types.AccessTypeRestricted
+ return p
+ },
+ canCall: false,
+ canCreate: false,
+ signer: keyring.GetAddr(0),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(0),
+ },
+ {
+ name: "should not allow call with permissionless policy and signer in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Call.AccessType = types.AccessTypePermissionless
+ p.Call.AccessControlList = []string{keyring.GetAddr(0).String()}
+ return p
+ },
+ canCall: false,
+ canCreate: true,
+ signer: keyring.GetAddr(0),
+ caller: keyring.GetAddr(1),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should not allow call with permissionless policy and signer not in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Call.AccessType = types.AccessTypePermissionless
+ p.Call.AccessControlList = []string{keyring.GetAddr(0).String()}
+ return p
+ },
+ canCall: false,
+ canCreate: true,
+ signer: keyring.GetAddr(1),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should allow call with permissionless policy while caller nor signer are in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Call.AccessType = types.AccessTypePermissionless
+ p.Call.AccessControlList = []string{keyring.GetAddr(0).String()}
+ return p
+ },
+ canCall: true,
+ canCreate: true,
+ signer: keyring.GetAddr(1),
+ caller: keyring.GetAddr(1),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should allow call with permissionless policy and caller not in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Call.AccessType = types.AccessTypePermissionless
+ p.Call.AccessControlList = []string{keyring.GetAddr(1).String()}
+ return p
+ },
+ canCall: false,
+ canCreate: true,
+ signer: keyring.GetAddr(1),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should not allow create with permissionless policy and signer in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Create.AccessType = types.AccessTypePermissionless
+ p.Create.AccessControlList = []string{keyring.GetAddr(0).String()}
+ return p
+ },
+ canCall: true,
+ canCreate: false,
+ signer: keyring.GetAddr(0),
+ caller: keyring.GetAddr(1),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should not allow create with permissionless policy and signer not in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Create.AccessType = types.AccessTypePermissionless
+ p.Create.AccessControlList = []string{keyring.GetAddr(0).String()}
+ return p
+ },
+ canCall: true,
+ canCreate: false,
+ signer: keyring.GetAddr(1),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should allow create with permissionless policy while caller nor signer are in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Create.AccessType = types.AccessTypePermissionless
+ p.Create.AccessControlList = []string{keyring.GetAddr(0).String()}
+ return p
+ },
+ canCall: true,
+ canCreate: true,
+ signer: keyring.GetAddr(1),
+ caller: keyring.GetAddr(1),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should allow create with permissionless policy and caller not in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Create.AccessType = types.AccessTypePermissionless
+ p.Create.AccessControlList = []string{keyring.GetAddr(1).String()}
+ return p
+ },
+ canCall: true,
+ canCreate: false,
+ signer: keyring.GetAddr(1),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(1),
+ },
+ {
+ name: "should not allow call with permissioned policy and not in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Call.AccessType = types.AccessTypePermissioned
+ p.Call.AccessControlList = []string{keyring.GetAddr(1).String()}
+ return p
+ },
+ canCall: false,
+ canCreate: true,
+ signer: keyring.GetAddr(0),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(0),
+ },
+ {
+ name: "should not allow create with permissioned policy and not in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Create.AccessType = types.AccessTypePermissioned
+ p.Create.AccessControlList = []string{keyring.GetAddr(1).String()}
+ return p
+ },
+ canCall: true,
+ canCreate: false,
+ signer: keyring.GetAddr(0),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(0),
+ },
+ {
+ name: "should allow call and create with permissioned policy and address in AccessControlList",
+ getAccessControl: func() types.AccessControl {
+ p := types.DefaultParams().AccessControl
+ p.Create.AccessType = types.AccessTypePermissioned
+ p.Create.AccessControlList = []string{keyring.GetAddr(0).String()}
+ p.Call.AccessType = types.AccessTypePermissioned
+ p.Call.AccessControlList = []string{keyring.GetAddr(0).String()}
+ return p
+ },
+ canCall: true,
+ canCreate: true,
+ signer: keyring.GetAddr(0),
+ caller: keyring.GetAddr(0),
+ recipient: keyring.GetAddr(0),
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ accessControl := tc.getAccessControl()
+ permissionPolicy := types.NewRestrictedPermissionPolicy(
+ &accessControl,
+ tc.signer,
+ )
+
+ canCreate := permissionPolicy.CanCreate(tc.signer, tc.caller)
+ suite.Require().Equal(tc.canCreate, canCreate, "expected %v, got %v", tc.canCreate, canCreate)
+
+ canCall := permissionPolicy.CanCall(tc.signer, tc.caller, tc.recipient)
+ suite.Require().Equal(tc.canCall, canCall, "expected %v, got %v", tc.canCall, canCall)
+ })
+ }
+}
diff --git a/x/evm/types/precompiles.go b/x/evm/types/precompiles.go
new file mode 100644
index 00000000..3fcef41e
--- /dev/null
+++ b/x/evm/types/precompiles.go
@@ -0,0 +1,31 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package types
+
+const (
+ P256PrecompileAddress = "0x0000000000000000000000000000000000000100"
+ Bech32PrecompileAddress = "0x0000000000000000000000000000000000000400"
+)
+
+const (
+ StakingPrecompileAddress = "0x0000000000000000000000000000000000000800"
+ DistributionPrecompileAddress = "0x0000000000000000000000000000000000000801"
+ ICS20PrecompileAddress = "0x0000000000000000000000000000000000000802"
+ VestingPrecompileAddress = "0x0000000000000000000000000000000000000803"
+ BankPrecompileAddress = "0x0000000000000000000000000000000000000804"
+)
+
+// AvailableStaticPrecompiles defines the full list of all available EVM extension addresses.
+//
+// NOTE: To be explicit, this list does not include the dynamically registered EVM extensions
+// like the ERC-20 extensions.
+var AvailableStaticPrecompiles = []string{
+ P256PrecompileAddress,
+ Bech32PrecompileAddress,
+ StakingPrecompileAddress,
+ DistributionPrecompileAddress,
+ ICS20PrecompileAddress,
+ VestingPrecompileAddress,
+ BankPrecompileAddress,
+}
diff --git a/x/evm/types/query.go b/x/evm/types/query.go
new file mode 100644
index 00000000..062e3b8d
--- /dev/null
+++ b/x/evm/types/query.go
@@ -0,0 +1,26 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+)
+
+// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
+func (m QueryTraceTxRequest) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
+ for _, msg := range m.Predecessors {
+ if err := msg.UnpackInterfaces(unpacker); err != nil {
+ return err
+ }
+ }
+ return m.Msg.UnpackInterfaces(unpacker)
+}
+
+func (m QueryTraceBlockRequest) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
+ for _, msg := range m.Txs {
+ if err := msg.UnpackInterfaces(unpacker); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/x/evm/types/query.pb.go b/x/evm/types/query.pb.go
new file mode 100644
index 00000000..8a6d4715
--- /dev/null
+++ b/x/evm/types/query.pb.go
@@ -0,0 +1,5991 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/evm/v1/query.proto
+
+package types
+
+import (
+ context "context"
+ cosmossdk_io_math "cosmossdk.io/math"
+ fmt "fmt"
+ github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
+ query "github.com/cosmos/cosmos-sdk/types/query"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ grpc1 "github.com/cosmos/gogoproto/grpc"
+ proto "github.com/cosmos/gogoproto/proto"
+ github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types"
+ _ "google.golang.org/genproto/googleapis/api/annotations"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+ _ "google.golang.org/protobuf/types/known/timestamppb"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+ time "time"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+var _ = time.Kitchen
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// QueryAccountRequest is the request type for the Query/Account RPC method.
+type QueryAccountRequest struct {
+ // address is the ethereum hex address to query the account for.
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+}
+
+func (m *QueryAccountRequest) Reset() { *m = QueryAccountRequest{} }
+func (m *QueryAccountRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryAccountRequest) ProtoMessage() {}
+func (*QueryAccountRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{0}
+}
+func (m *QueryAccountRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryAccountRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryAccountRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryAccountRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryAccountRequest.Merge(m, src)
+}
+func (m *QueryAccountRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryAccountRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryAccountRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryAccountRequest proto.InternalMessageInfo
+
+// QueryAccountResponse is the response type for the Query/Account RPC method.
+type QueryAccountResponse struct {
+ // balance is the balance of the EVM denomination.
+ Balance string `protobuf:"bytes,1,opt,name=balance,proto3" json:"balance,omitempty"`
+ // code_hash is the hex-formatted code bytes from the EOA.
+ CodeHash string `protobuf:"bytes,2,opt,name=code_hash,json=codeHash,proto3" json:"code_hash,omitempty"`
+ // nonce is the account's sequence number.
+ Nonce uint64 `protobuf:"varint,3,opt,name=nonce,proto3" json:"nonce,omitempty"`
+}
+
+func (m *QueryAccountResponse) Reset() { *m = QueryAccountResponse{} }
+func (m *QueryAccountResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryAccountResponse) ProtoMessage() {}
+func (*QueryAccountResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{1}
+}
+func (m *QueryAccountResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryAccountResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryAccountResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryAccountResponse.Merge(m, src)
+}
+func (m *QueryAccountResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryAccountResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryAccountResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryAccountResponse proto.InternalMessageInfo
+
+func (m *QueryAccountResponse) GetBalance() string {
+ if m != nil {
+ return m.Balance
+ }
+ return ""
+}
+
+func (m *QueryAccountResponse) GetCodeHash() string {
+ if m != nil {
+ return m.CodeHash
+ }
+ return ""
+}
+
+func (m *QueryAccountResponse) GetNonce() uint64 {
+ if m != nil {
+ return m.Nonce
+ }
+ return 0
+}
+
+// QueryCosmosAccountRequest is the request type for the Query/CosmosAccount RPC
+// method.
+type QueryCosmosAccountRequest struct {
+ // address is the ethereum hex address to query the account for.
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+}
+
+func (m *QueryCosmosAccountRequest) Reset() { *m = QueryCosmosAccountRequest{} }
+func (m *QueryCosmosAccountRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryCosmosAccountRequest) ProtoMessage() {}
+func (*QueryCosmosAccountRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{2}
+}
+func (m *QueryCosmosAccountRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryCosmosAccountRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryCosmosAccountRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryCosmosAccountRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryCosmosAccountRequest.Merge(m, src)
+}
+func (m *QueryCosmosAccountRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryCosmosAccountRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryCosmosAccountRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryCosmosAccountRequest proto.InternalMessageInfo
+
+// QueryCosmosAccountResponse is the response type for the Query/CosmosAccount
+// RPC method.
+type QueryCosmosAccountResponse struct {
+ // cosmos_address is the cosmos address of the account.
+ CosmosAddress string `protobuf:"bytes,1,opt,name=cosmos_address,json=cosmosAddress,proto3" json:"cosmos_address,omitempty"`
+ // sequence is the account's sequence number.
+ Sequence uint64 `protobuf:"varint,2,opt,name=sequence,proto3" json:"sequence,omitempty"`
+ // account_number is the account number
+ AccountNumber uint64 `protobuf:"varint,3,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"`
+}
+
+func (m *QueryCosmosAccountResponse) Reset() { *m = QueryCosmosAccountResponse{} }
+func (m *QueryCosmosAccountResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryCosmosAccountResponse) ProtoMessage() {}
+func (*QueryCosmosAccountResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{3}
+}
+func (m *QueryCosmosAccountResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryCosmosAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryCosmosAccountResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryCosmosAccountResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryCosmosAccountResponse.Merge(m, src)
+}
+func (m *QueryCosmosAccountResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryCosmosAccountResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryCosmosAccountResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryCosmosAccountResponse proto.InternalMessageInfo
+
+func (m *QueryCosmosAccountResponse) GetCosmosAddress() string {
+ if m != nil {
+ return m.CosmosAddress
+ }
+ return ""
+}
+
+func (m *QueryCosmosAccountResponse) GetSequence() uint64 {
+ if m != nil {
+ return m.Sequence
+ }
+ return 0
+}
+
+func (m *QueryCosmosAccountResponse) GetAccountNumber() uint64 {
+ if m != nil {
+ return m.AccountNumber
+ }
+ return 0
+}
+
+// QueryValidatorAccountRequest is the request type for the
+// Query/ValidatorAccount RPC method.
+type QueryValidatorAccountRequest struct {
+ // cons_address is the validator cons address to query the account for.
+ ConsAddress string `protobuf:"bytes,1,opt,name=cons_address,json=consAddress,proto3" json:"cons_address,omitempty"`
+}
+
+func (m *QueryValidatorAccountRequest) Reset() { *m = QueryValidatorAccountRequest{} }
+func (m *QueryValidatorAccountRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryValidatorAccountRequest) ProtoMessage() {}
+func (*QueryValidatorAccountRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{4}
+}
+func (m *QueryValidatorAccountRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryValidatorAccountRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryValidatorAccountRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryValidatorAccountRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryValidatorAccountRequest.Merge(m, src)
+}
+func (m *QueryValidatorAccountRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryValidatorAccountRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryValidatorAccountRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryValidatorAccountRequest proto.InternalMessageInfo
+
+// QueryValidatorAccountResponse is the response type for the
+// Query/ValidatorAccount RPC method.
+type QueryValidatorAccountResponse struct {
+ // account_address is the cosmos address of the account in bech32 format.
+ AccountAddress string `protobuf:"bytes,1,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"`
+ // sequence is the account's sequence number.
+ Sequence uint64 `protobuf:"varint,2,opt,name=sequence,proto3" json:"sequence,omitempty"`
+ // account_number is the account number
+ AccountNumber uint64 `protobuf:"varint,3,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"`
+}
+
+func (m *QueryValidatorAccountResponse) Reset() { *m = QueryValidatorAccountResponse{} }
+func (m *QueryValidatorAccountResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryValidatorAccountResponse) ProtoMessage() {}
+func (*QueryValidatorAccountResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{5}
+}
+func (m *QueryValidatorAccountResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryValidatorAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryValidatorAccountResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryValidatorAccountResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryValidatorAccountResponse.Merge(m, src)
+}
+func (m *QueryValidatorAccountResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryValidatorAccountResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryValidatorAccountResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryValidatorAccountResponse proto.InternalMessageInfo
+
+func (m *QueryValidatorAccountResponse) GetAccountAddress() string {
+ if m != nil {
+ return m.AccountAddress
+ }
+ return ""
+}
+
+func (m *QueryValidatorAccountResponse) GetSequence() uint64 {
+ if m != nil {
+ return m.Sequence
+ }
+ return 0
+}
+
+func (m *QueryValidatorAccountResponse) GetAccountNumber() uint64 {
+ if m != nil {
+ return m.AccountNumber
+ }
+ return 0
+}
+
+// QueryBalanceRequest is the request type for the Query/Balance RPC method.
+type QueryBalanceRequest struct {
+ // address is the ethereum hex address to query the balance for.
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+}
+
+func (m *QueryBalanceRequest) Reset() { *m = QueryBalanceRequest{} }
+func (m *QueryBalanceRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryBalanceRequest) ProtoMessage() {}
+func (*QueryBalanceRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{6}
+}
+func (m *QueryBalanceRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBalanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBalanceRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBalanceRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBalanceRequest.Merge(m, src)
+}
+func (m *QueryBalanceRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBalanceRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBalanceRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBalanceRequest proto.InternalMessageInfo
+
+// QueryBalanceResponse is the response type for the Query/Balance RPC method.
+type QueryBalanceResponse struct {
+ // balance is the balance of the EVM denomination.
+ Balance string `protobuf:"bytes,1,opt,name=balance,proto3" json:"balance,omitempty"`
+}
+
+func (m *QueryBalanceResponse) Reset() { *m = QueryBalanceResponse{} }
+func (m *QueryBalanceResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryBalanceResponse) ProtoMessage() {}
+func (*QueryBalanceResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{7}
+}
+func (m *QueryBalanceResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBalanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBalanceResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBalanceResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBalanceResponse.Merge(m, src)
+}
+func (m *QueryBalanceResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBalanceResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBalanceResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBalanceResponse proto.InternalMessageInfo
+
+func (m *QueryBalanceResponse) GetBalance() string {
+ if m != nil {
+ return m.Balance
+ }
+ return ""
+}
+
+// QueryStorageRequest is the request type for the Query/Storage RPC method.
+type QueryStorageRequest struct {
+ // address is the ethereum hex address to query the storage state for.
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ // key defines the key of the storage state
+ Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
+}
+
+func (m *QueryStorageRequest) Reset() { *m = QueryStorageRequest{} }
+func (m *QueryStorageRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryStorageRequest) ProtoMessage() {}
+func (*QueryStorageRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{8}
+}
+func (m *QueryStorageRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryStorageRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryStorageRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryStorageRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryStorageRequest.Merge(m, src)
+}
+func (m *QueryStorageRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryStorageRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryStorageRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryStorageRequest proto.InternalMessageInfo
+
+// QueryStorageResponse is the response type for the Query/Storage RPC
+// method.
+type QueryStorageResponse struct {
+ // value defines the storage state value hash associated with the given key.
+ Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *QueryStorageResponse) Reset() { *m = QueryStorageResponse{} }
+func (m *QueryStorageResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryStorageResponse) ProtoMessage() {}
+func (*QueryStorageResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{9}
+}
+func (m *QueryStorageResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryStorageResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryStorageResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryStorageResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryStorageResponse.Merge(m, src)
+}
+func (m *QueryStorageResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryStorageResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryStorageResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryStorageResponse proto.InternalMessageInfo
+
+func (m *QueryStorageResponse) GetValue() string {
+ if m != nil {
+ return m.Value
+ }
+ return ""
+}
+
+// QueryCodeRequest is the request type for the Query/Code RPC method.
+type QueryCodeRequest struct {
+ // address is the ethereum hex address to query the code for.
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+}
+
+func (m *QueryCodeRequest) Reset() { *m = QueryCodeRequest{} }
+func (m *QueryCodeRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryCodeRequest) ProtoMessage() {}
+func (*QueryCodeRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{10}
+}
+func (m *QueryCodeRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryCodeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryCodeRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryCodeRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryCodeRequest.Merge(m, src)
+}
+func (m *QueryCodeRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryCodeRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryCodeRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryCodeRequest proto.InternalMessageInfo
+
+// QueryCodeResponse is the response type for the Query/Code RPC
+// method.
+type QueryCodeResponse struct {
+ // code represents the code bytes from an ethereum address.
+ Code []byte `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
+}
+
+func (m *QueryCodeResponse) Reset() { *m = QueryCodeResponse{} }
+func (m *QueryCodeResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryCodeResponse) ProtoMessage() {}
+func (*QueryCodeResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{11}
+}
+func (m *QueryCodeResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryCodeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryCodeResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryCodeResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryCodeResponse.Merge(m, src)
+}
+func (m *QueryCodeResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryCodeResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryCodeResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryCodeResponse proto.InternalMessageInfo
+
+func (m *QueryCodeResponse) GetCode() []byte {
+ if m != nil {
+ return m.Code
+ }
+ return nil
+}
+
+// QueryTxLogsRequest is the request type for the Query/TxLogs RPC method.
+type QueryTxLogsRequest struct {
+ // hash is the ethereum transaction hex hash to query the logs for.
+ Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
+ // pagination defines an optional pagination for the request.
+ Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"`
+}
+
+func (m *QueryTxLogsRequest) Reset() { *m = QueryTxLogsRequest{} }
+func (m *QueryTxLogsRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryTxLogsRequest) ProtoMessage() {}
+func (*QueryTxLogsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{12}
+}
+func (m *QueryTxLogsRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryTxLogsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryTxLogsRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryTxLogsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryTxLogsRequest.Merge(m, src)
+}
+func (m *QueryTxLogsRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryTxLogsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryTxLogsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryTxLogsRequest proto.InternalMessageInfo
+
+// QueryTxLogsResponse is the response type for the Query/TxLogs RPC method.
+type QueryTxLogsResponse struct {
+ // logs represents the ethereum logs generated from the given transaction.
+ Logs []*Log `protobuf:"bytes,1,rep,name=logs,proto3" json:"logs,omitempty"`
+ // pagination defines the pagination in the response.
+ Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"`
+}
+
+func (m *QueryTxLogsResponse) Reset() { *m = QueryTxLogsResponse{} }
+func (m *QueryTxLogsResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryTxLogsResponse) ProtoMessage() {}
+func (*QueryTxLogsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{13}
+}
+func (m *QueryTxLogsResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryTxLogsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryTxLogsResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryTxLogsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryTxLogsResponse.Merge(m, src)
+}
+func (m *QueryTxLogsResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryTxLogsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryTxLogsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryTxLogsResponse proto.InternalMessageInfo
+
+func (m *QueryTxLogsResponse) GetLogs() []*Log {
+ if m != nil {
+ return m.Logs
+ }
+ return nil
+}
+
+func (m *QueryTxLogsResponse) GetPagination() *query.PageResponse {
+ if m != nil {
+ return m.Pagination
+ }
+ return nil
+}
+
+// QueryParamsRequest defines the request type for querying x/evm parameters.
+type QueryParamsRequest struct {
+}
+
+func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} }
+func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryParamsRequest) ProtoMessage() {}
+func (*QueryParamsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{14}
+}
+func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryParamsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryParamsRequest.Merge(m, src)
+}
+func (m *QueryParamsRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryParamsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo
+
+// QueryParamsResponse defines the response type for querying x/evm parameters.
+type QueryParamsResponse struct {
+ // params define the evm module parameters.
+ Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
+}
+
+func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} }
+func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryParamsResponse) ProtoMessage() {}
+func (*QueryParamsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{15}
+}
+func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryParamsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryParamsResponse.Merge(m, src)
+}
+func (m *QueryParamsResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryParamsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo
+
+func (m *QueryParamsResponse) GetParams() Params {
+ if m != nil {
+ return m.Params
+ }
+ return Params{}
+}
+
+// EthCallRequest defines EthCall request
+type EthCallRequest struct {
+ // args uses the same json format as the json rpc api.
+ Args []byte `protobuf:"bytes,1,opt,name=args,proto3" json:"args,omitempty"`
+ // gas_cap defines the default gas cap to be used
+ GasCap uint64 `protobuf:"varint,2,opt,name=gas_cap,json=gasCap,proto3" json:"gas_cap,omitempty"`
+ // proposer_address of the requested block in hex format
+ ProposerAddress github_com_cosmos_cosmos_sdk_types.ConsAddress `protobuf:"bytes,3,opt,name=proposer_address,json=proposerAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.ConsAddress" json:"proposer_address,omitempty"`
+ // chain_id is the eip155 chain id parsed from the requested block header
+ ChainId int64 `protobuf:"varint,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+}
+
+func (m *EthCallRequest) Reset() { *m = EthCallRequest{} }
+func (m *EthCallRequest) String() string { return proto.CompactTextString(m) }
+func (*EthCallRequest) ProtoMessage() {}
+func (*EthCallRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{16}
+}
+func (m *EthCallRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EthCallRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EthCallRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EthCallRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EthCallRequest.Merge(m, src)
+}
+func (m *EthCallRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *EthCallRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_EthCallRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthCallRequest proto.InternalMessageInfo
+
+func (m *EthCallRequest) GetArgs() []byte {
+ if m != nil {
+ return m.Args
+ }
+ return nil
+}
+
+func (m *EthCallRequest) GetGasCap() uint64 {
+ if m != nil {
+ return m.GasCap
+ }
+ return 0
+}
+
+func (m *EthCallRequest) GetProposerAddress() github_com_cosmos_cosmos_sdk_types.ConsAddress {
+ if m != nil {
+ return m.ProposerAddress
+ }
+ return nil
+}
+
+func (m *EthCallRequest) GetChainId() int64 {
+ if m != nil {
+ return m.ChainId
+ }
+ return 0
+}
+
+// EstimateGasResponse defines EstimateGas response
+type EstimateGasResponse struct {
+ // gas returns the estimated gas
+ Gas uint64 `protobuf:"varint,1,opt,name=gas,proto3" json:"gas,omitempty"`
+}
+
+func (m *EstimateGasResponse) Reset() { *m = EstimateGasResponse{} }
+func (m *EstimateGasResponse) String() string { return proto.CompactTextString(m) }
+func (*EstimateGasResponse) ProtoMessage() {}
+func (*EstimateGasResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{17}
+}
+func (m *EstimateGasResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EstimateGasResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EstimateGasResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EstimateGasResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EstimateGasResponse.Merge(m, src)
+}
+func (m *EstimateGasResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *EstimateGasResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_EstimateGasResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EstimateGasResponse proto.InternalMessageInfo
+
+func (m *EstimateGasResponse) GetGas() uint64 {
+ if m != nil {
+ return m.Gas
+ }
+ return 0
+}
+
+// QueryTraceTxRequest defines TraceTx request
+type QueryTraceTxRequest struct {
+ // msg is the MsgEthereumTx for the requested transaction
+ Msg *MsgEthereumTx `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
+ // trace_config holds extra parameters to trace functions.
+ TraceConfig *TraceConfig `protobuf:"bytes,3,opt,name=trace_config,json=traceConfig,proto3" json:"trace_config,omitempty"`
+ // predecessors is an array of transactions included in the same block
+ // need to be replayed first to get correct context for tracing.
+ Predecessors []*MsgEthereumTx `protobuf:"bytes,4,rep,name=predecessors,proto3" json:"predecessors,omitempty"`
+ // block_number of requested transaction
+ BlockNumber int64 `protobuf:"varint,5,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"`
+ // block_hash of requested transaction
+ BlockHash string `protobuf:"bytes,6,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"`
+ // block_time of requested transaction
+ BlockTime time.Time `protobuf:"bytes,7,opt,name=block_time,json=blockTime,proto3,stdtime" json:"block_time"`
+ // proposer_address is the proposer of the requested block
+ ProposerAddress github_com_cosmos_cosmos_sdk_types.ConsAddress `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.ConsAddress" json:"proposer_address,omitempty"`
+ // chain_id is the eip155 chain id parsed from the requested block header
+ ChainId int64 `protobuf:"varint,9,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+ // block_max_gas of the block of the requested transaction
+ BlockMaxGas int64 `protobuf:"varint,10,opt,name=block_max_gas,json=blockMaxGas,proto3" json:"block_max_gas,omitempty"`
+}
+
+func (m *QueryTraceTxRequest) Reset() { *m = QueryTraceTxRequest{} }
+func (m *QueryTraceTxRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryTraceTxRequest) ProtoMessage() {}
+func (*QueryTraceTxRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{18}
+}
+func (m *QueryTraceTxRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryTraceTxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryTraceTxRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryTraceTxRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryTraceTxRequest.Merge(m, src)
+}
+func (m *QueryTraceTxRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryTraceTxRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryTraceTxRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryTraceTxRequest proto.InternalMessageInfo
+
+func (m *QueryTraceTxRequest) GetMsg() *MsgEthereumTx {
+ if m != nil {
+ return m.Msg
+ }
+ return nil
+}
+
+func (m *QueryTraceTxRequest) GetTraceConfig() *TraceConfig {
+ if m != nil {
+ return m.TraceConfig
+ }
+ return nil
+}
+
+func (m *QueryTraceTxRequest) GetPredecessors() []*MsgEthereumTx {
+ if m != nil {
+ return m.Predecessors
+ }
+ return nil
+}
+
+func (m *QueryTraceTxRequest) GetBlockNumber() int64 {
+ if m != nil {
+ return m.BlockNumber
+ }
+ return 0
+}
+
+func (m *QueryTraceTxRequest) GetBlockHash() string {
+ if m != nil {
+ return m.BlockHash
+ }
+ return ""
+}
+
+func (m *QueryTraceTxRequest) GetBlockTime() time.Time {
+ if m != nil {
+ return m.BlockTime
+ }
+ return time.Time{}
+}
+
+func (m *QueryTraceTxRequest) GetProposerAddress() github_com_cosmos_cosmos_sdk_types.ConsAddress {
+ if m != nil {
+ return m.ProposerAddress
+ }
+ return nil
+}
+
+func (m *QueryTraceTxRequest) GetChainId() int64 {
+ if m != nil {
+ return m.ChainId
+ }
+ return 0
+}
+
+func (m *QueryTraceTxRequest) GetBlockMaxGas() int64 {
+ if m != nil {
+ return m.BlockMaxGas
+ }
+ return 0
+}
+
+// QueryTraceTxResponse defines TraceTx response
+type QueryTraceTxResponse struct {
+ // data is the response serialized in bytes
+ Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+}
+
+func (m *QueryTraceTxResponse) Reset() { *m = QueryTraceTxResponse{} }
+func (m *QueryTraceTxResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryTraceTxResponse) ProtoMessage() {}
+func (*QueryTraceTxResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{19}
+}
+func (m *QueryTraceTxResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryTraceTxResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryTraceTxResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryTraceTxResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryTraceTxResponse.Merge(m, src)
+}
+func (m *QueryTraceTxResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryTraceTxResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryTraceTxResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryTraceTxResponse proto.InternalMessageInfo
+
+func (m *QueryTraceTxResponse) GetData() []byte {
+ if m != nil {
+ return m.Data
+ }
+ return nil
+}
+
+// QueryTraceBlockRequest defines TraceTx request
+type QueryTraceBlockRequest struct {
+ // txs is an array of messages in the block
+ Txs []*MsgEthereumTx `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"`
+ // trace_config holds extra parameters to trace functions.
+ TraceConfig *TraceConfig `protobuf:"bytes,3,opt,name=trace_config,json=traceConfig,proto3" json:"trace_config,omitempty"`
+ // block_number of the traced block
+ BlockNumber int64 `protobuf:"varint,5,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"`
+ // block_hash (hex) of the traced block
+ BlockHash string `protobuf:"bytes,6,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"`
+ // block_time of the traced block
+ BlockTime time.Time `protobuf:"bytes,7,opt,name=block_time,json=blockTime,proto3,stdtime" json:"block_time"`
+ // proposer_address is the address of the requested block
+ ProposerAddress github_com_cosmos_cosmos_sdk_types.ConsAddress `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.ConsAddress" json:"proposer_address,omitempty"`
+ // chain_id is the eip155 chain id parsed from the requested block header
+ ChainId int64 `protobuf:"varint,9,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+ // block_max_gas of the traced block
+ BlockMaxGas int64 `protobuf:"varint,10,opt,name=block_max_gas,json=blockMaxGas,proto3" json:"block_max_gas,omitempty"`
+}
+
+func (m *QueryTraceBlockRequest) Reset() { *m = QueryTraceBlockRequest{} }
+func (m *QueryTraceBlockRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryTraceBlockRequest) ProtoMessage() {}
+func (*QueryTraceBlockRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{20}
+}
+func (m *QueryTraceBlockRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryTraceBlockRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryTraceBlockRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryTraceBlockRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryTraceBlockRequest.Merge(m, src)
+}
+func (m *QueryTraceBlockRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryTraceBlockRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryTraceBlockRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryTraceBlockRequest proto.InternalMessageInfo
+
+func (m *QueryTraceBlockRequest) GetTxs() []*MsgEthereumTx {
+ if m != nil {
+ return m.Txs
+ }
+ return nil
+}
+
+func (m *QueryTraceBlockRequest) GetTraceConfig() *TraceConfig {
+ if m != nil {
+ return m.TraceConfig
+ }
+ return nil
+}
+
+func (m *QueryTraceBlockRequest) GetBlockNumber() int64 {
+ if m != nil {
+ return m.BlockNumber
+ }
+ return 0
+}
+
+func (m *QueryTraceBlockRequest) GetBlockHash() string {
+ if m != nil {
+ return m.BlockHash
+ }
+ return ""
+}
+
+func (m *QueryTraceBlockRequest) GetBlockTime() time.Time {
+ if m != nil {
+ return m.BlockTime
+ }
+ return time.Time{}
+}
+
+func (m *QueryTraceBlockRequest) GetProposerAddress() github_com_cosmos_cosmos_sdk_types.ConsAddress {
+ if m != nil {
+ return m.ProposerAddress
+ }
+ return nil
+}
+
+func (m *QueryTraceBlockRequest) GetChainId() int64 {
+ if m != nil {
+ return m.ChainId
+ }
+ return 0
+}
+
+func (m *QueryTraceBlockRequest) GetBlockMaxGas() int64 {
+ if m != nil {
+ return m.BlockMaxGas
+ }
+ return 0
+}
+
+// QueryTraceBlockResponse defines TraceBlock response
+type QueryTraceBlockResponse struct {
+ // data is the response serialized in bytes
+ Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+}
+
+func (m *QueryTraceBlockResponse) Reset() { *m = QueryTraceBlockResponse{} }
+func (m *QueryTraceBlockResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryTraceBlockResponse) ProtoMessage() {}
+func (*QueryTraceBlockResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{21}
+}
+func (m *QueryTraceBlockResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryTraceBlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryTraceBlockResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryTraceBlockResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryTraceBlockResponse.Merge(m, src)
+}
+func (m *QueryTraceBlockResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryTraceBlockResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryTraceBlockResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryTraceBlockResponse proto.InternalMessageInfo
+
+func (m *QueryTraceBlockResponse) GetData() []byte {
+ if m != nil {
+ return m.Data
+ }
+ return nil
+}
+
+// QueryBaseFeeRequest defines the request type for querying the EIP1559 base
+// fee.
+type QueryBaseFeeRequest struct {
+}
+
+func (m *QueryBaseFeeRequest) Reset() { *m = QueryBaseFeeRequest{} }
+func (m *QueryBaseFeeRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryBaseFeeRequest) ProtoMessage() {}
+func (*QueryBaseFeeRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{22}
+}
+func (m *QueryBaseFeeRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBaseFeeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBaseFeeRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBaseFeeRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBaseFeeRequest.Merge(m, src)
+}
+func (m *QueryBaseFeeRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBaseFeeRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBaseFeeRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBaseFeeRequest proto.InternalMessageInfo
+
+// QueryBaseFeeResponse returns the EIP1559 base fee.
+type QueryBaseFeeResponse struct {
+ // base_fee is the EIP1559 base fee
+ BaseFee *cosmossdk_io_math.Int `protobuf:"bytes,1,opt,name=base_fee,json=baseFee,proto3,customtype=cosmossdk.io/math.Int" json:"base_fee,omitempty"`
+}
+
+func (m *QueryBaseFeeResponse) Reset() { *m = QueryBaseFeeResponse{} }
+func (m *QueryBaseFeeResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryBaseFeeResponse) ProtoMessage() {}
+func (*QueryBaseFeeResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_e15a877459347994, []int{23}
+}
+func (m *QueryBaseFeeResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBaseFeeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBaseFeeResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBaseFeeResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBaseFeeResponse.Merge(m, src)
+}
+func (m *QueryBaseFeeResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBaseFeeResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBaseFeeResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBaseFeeResponse proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterType((*QueryAccountRequest)(nil), "ethermint.evm.v1.QueryAccountRequest")
+ proto.RegisterType((*QueryAccountResponse)(nil), "ethermint.evm.v1.QueryAccountResponse")
+ proto.RegisterType((*QueryCosmosAccountRequest)(nil), "ethermint.evm.v1.QueryCosmosAccountRequest")
+ proto.RegisterType((*QueryCosmosAccountResponse)(nil), "ethermint.evm.v1.QueryCosmosAccountResponse")
+ proto.RegisterType((*QueryValidatorAccountRequest)(nil), "ethermint.evm.v1.QueryValidatorAccountRequest")
+ proto.RegisterType((*QueryValidatorAccountResponse)(nil), "ethermint.evm.v1.QueryValidatorAccountResponse")
+ proto.RegisterType((*QueryBalanceRequest)(nil), "ethermint.evm.v1.QueryBalanceRequest")
+ proto.RegisterType((*QueryBalanceResponse)(nil), "ethermint.evm.v1.QueryBalanceResponse")
+ proto.RegisterType((*QueryStorageRequest)(nil), "ethermint.evm.v1.QueryStorageRequest")
+ proto.RegisterType((*QueryStorageResponse)(nil), "ethermint.evm.v1.QueryStorageResponse")
+ proto.RegisterType((*QueryCodeRequest)(nil), "ethermint.evm.v1.QueryCodeRequest")
+ proto.RegisterType((*QueryCodeResponse)(nil), "ethermint.evm.v1.QueryCodeResponse")
+ proto.RegisterType((*QueryTxLogsRequest)(nil), "ethermint.evm.v1.QueryTxLogsRequest")
+ proto.RegisterType((*QueryTxLogsResponse)(nil), "ethermint.evm.v1.QueryTxLogsResponse")
+ proto.RegisterType((*QueryParamsRequest)(nil), "ethermint.evm.v1.QueryParamsRequest")
+ proto.RegisterType((*QueryParamsResponse)(nil), "ethermint.evm.v1.QueryParamsResponse")
+ proto.RegisterType((*EthCallRequest)(nil), "ethermint.evm.v1.EthCallRequest")
+ proto.RegisterType((*EstimateGasResponse)(nil), "ethermint.evm.v1.EstimateGasResponse")
+ proto.RegisterType((*QueryTraceTxRequest)(nil), "ethermint.evm.v1.QueryTraceTxRequest")
+ proto.RegisterType((*QueryTraceTxResponse)(nil), "ethermint.evm.v1.QueryTraceTxResponse")
+ proto.RegisterType((*QueryTraceBlockRequest)(nil), "ethermint.evm.v1.QueryTraceBlockRequest")
+ proto.RegisterType((*QueryTraceBlockResponse)(nil), "ethermint.evm.v1.QueryTraceBlockResponse")
+ proto.RegisterType((*QueryBaseFeeRequest)(nil), "ethermint.evm.v1.QueryBaseFeeRequest")
+ proto.RegisterType((*QueryBaseFeeResponse)(nil), "ethermint.evm.v1.QueryBaseFeeResponse")
+}
+
+func init() { proto.RegisterFile("ethermint/evm/v1/query.proto", fileDescriptor_e15a877459347994) }
+
+var fileDescriptor_e15a877459347994 = []byte{
+ // 1466 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcf, 0x6f, 0x1b, 0x45,
+ 0x14, 0xce, 0xc6, 0x4e, 0xec, 0x8c, 0x93, 0xd6, 0x4c, 0xd3, 0xd6, 0xd9, 0x26, 0x76, 0xba, 0x90,
+ 0xd8, 0x2d, 0xed, 0x6e, 0x13, 0x50, 0x05, 0x5c, 0x68, 0x6d, 0xb5, 0xa5, 0xb4, 0x45, 0xc5, 0x44,
+ 0x1c, 0x90, 0x90, 0x35, 0x5e, 0x4f, 0xd7, 0x56, 0xbc, 0x3b, 0xee, 0xce, 0xd8, 0x72, 0x5a, 0xf5,
+ 0x40, 0x55, 0xf1, 0x43, 0x5c, 0x2a, 0x71, 0xe3, 0xd4, 0x3b, 0x37, 0x2e, 0x1c, 0xb9, 0xf6, 0x58,
+ 0x89, 0x0b, 0xe2, 0x50, 0x50, 0xc3, 0x81, 0xbf, 0x81, 0x13, 0x9a, 0x1f, 0x6b, 0xef, 0xda, 0xde,
+ 0x38, 0x45, 0xe5, 0xc6, 0x69, 0x77, 0x66, 0xde, 0xbc, 0xef, 0x9b, 0xf7, 0xde, 0xcc, 0xfb, 0xc0,
+ 0x2a, 0x66, 0x4d, 0xec, 0xbb, 0x2d, 0x8f, 0x59, 0xb8, 0xe7, 0x5a, 0xbd, 0x2d, 0xeb, 0x6e, 0x17,
+ 0xfb, 0x7b, 0x66, 0xc7, 0x27, 0x8c, 0xc0, 0xec, 0x60, 0xd5, 0xc4, 0x3d, 0xd7, 0xec, 0x6d, 0xe9,
+ 0x67, 0x6d, 0x42, 0x5d, 0x42, 0xad, 0x3a, 0xa2, 0x58, 0x9a, 0x5a, 0xbd, 0xad, 0x3a, 0x66, 0x68,
+ 0xcb, 0xea, 0x20, 0xa7, 0xe5, 0x21, 0xd6, 0x22, 0x9e, 0xdc, 0xad, 0xeb, 0x63, 0xbe, 0xb9, 0x13,
+ 0xb9, 0xb6, 0x32, 0xb6, 0xc6, 0xfa, 0x6a, 0x69, 0xd9, 0x21, 0x0e, 0x11, 0xbf, 0x16, 0xff, 0x53,
+ 0xb3, 0xab, 0x0e, 0x21, 0x4e, 0x1b, 0x5b, 0xa8, 0xd3, 0xb2, 0x90, 0xe7, 0x11, 0x26, 0x90, 0xa8,
+ 0x5a, 0x2d, 0xa8, 0x55, 0x31, 0xaa, 0x77, 0xef, 0x58, 0xac, 0xe5, 0x62, 0xca, 0x90, 0xdb, 0x91,
+ 0x06, 0xc6, 0xbb, 0xe0, 0xd8, 0xc7, 0x9c, 0xed, 0x65, 0xdb, 0x26, 0x5d, 0x8f, 0x55, 0xf1, 0xdd,
+ 0x2e, 0xa6, 0x0c, 0xe6, 0x40, 0x0a, 0x35, 0x1a, 0x3e, 0xa6, 0x34, 0xa7, 0xad, 0x6b, 0xa5, 0x85,
+ 0x6a, 0x30, 0x7c, 0x2f, 0xfd, 0xf5, 0x93, 0xc2, 0xcc, 0x5f, 0x4f, 0x0a, 0x33, 0x86, 0x0d, 0x96,
+ 0xa3, 0x5b, 0x69, 0x87, 0x78, 0x14, 0xf3, 0xbd, 0x75, 0xd4, 0x46, 0x9e, 0x8d, 0x83, 0xbd, 0x6a,
+ 0x08, 0x4f, 0x81, 0x05, 0x9b, 0x34, 0x70, 0xad, 0x89, 0x68, 0x33, 0x37, 0x2b, 0xd6, 0xd2, 0x7c,
+ 0xe2, 0x03, 0x44, 0x9b, 0x70, 0x19, 0xcc, 0x79, 0x84, 0x6f, 0x4a, 0xac, 0x6b, 0xa5, 0x64, 0x55,
+ 0x0e, 0x8c, 0xf7, 0xc1, 0x8a, 0x00, 0xa9, 0x88, 0xf0, 0xfe, 0x0b, 0x96, 0x5f, 0x6a, 0x40, 0x9f,
+ 0xe4, 0x41, 0x91, 0xdd, 0x00, 0x47, 0x64, 0xe6, 0x6a, 0x51, 0x4f, 0x4b, 0x72, 0xf6, 0xb2, 0x9c,
+ 0x84, 0x3a, 0x48, 0x53, 0x0e, 0xca, 0xf9, 0xcd, 0x0a, 0x7e, 0x83, 0x31, 0x77, 0x81, 0xa4, 0xd7,
+ 0x9a, 0xd7, 0x75, 0xeb, 0xd8, 0x57, 0x27, 0x58, 0x52, 0xb3, 0x1f, 0x89, 0x49, 0xe3, 0x06, 0x58,
+ 0x15, 0x3c, 0x3e, 0x45, 0xed, 0x56, 0x03, 0x31, 0xe2, 0x8f, 0x1c, 0xe6, 0x34, 0x58, 0xb4, 0x89,
+ 0x37, 0xca, 0x23, 0xc3, 0xe7, 0x2e, 0x8f, 0x9d, 0xea, 0x5b, 0x0d, 0xac, 0xc5, 0x78, 0x53, 0x07,
+ 0x2b, 0x82, 0xa3, 0x01, 0xab, 0xa8, 0xc7, 0x80, 0xec, 0x2b, 0x3c, 0x5a, 0x50, 0x44, 0x65, 0x99,
+ 0xe7, 0x97, 0x49, 0xcf, 0x05, 0x55, 0x44, 0x83, 0xad, 0xd3, 0x8a, 0xc8, 0xb8, 0xa1, 0xc0, 0x3e,
+ 0x61, 0xc4, 0x47, 0xce, 0x74, 0x30, 0x98, 0x05, 0x89, 0x5d, 0xbc, 0xa7, 0xea, 0x8d, 0xff, 0x86,
+ 0xe0, 0xcf, 0x29, 0xf8, 0x81, 0x33, 0x05, 0xbf, 0x0c, 0xe6, 0x7a, 0xa8, 0xdd, 0x0d, 0xc0, 0xe5,
+ 0xc0, 0xb8, 0x08, 0xb2, 0xaa, 0x94, 0x1a, 0x2f, 0x75, 0xc8, 0x22, 0x78, 0x2d, 0xb4, 0x4f, 0x41,
+ 0x40, 0x90, 0xe4, 0xb5, 0x2f, 0x76, 0x2d, 0x56, 0xc5, 0xbf, 0x71, 0x0f, 0x40, 0x61, 0xb8, 0xd3,
+ 0xbf, 0x49, 0x1c, 0x1a, 0x40, 0x40, 0x90, 0x14, 0x37, 0x46, 0xfa, 0x17, 0xff, 0xf0, 0x2a, 0x00,
+ 0xc3, 0x77, 0x45, 0x9c, 0x2d, 0xb3, 0xbd, 0x69, 0xca, 0xa2, 0x35, 0xf9, 0x23, 0x64, 0xca, 0xf7,
+ 0x4a, 0x3d, 0x42, 0xe6, 0xed, 0x61, 0xa8, 0xaa, 0xa1, 0x9d, 0x21, 0x92, 0xdf, 0x68, 0x2a, 0xb0,
+ 0x01, 0xb8, 0xe2, 0x79, 0x06, 0x24, 0xdb, 0xc4, 0xe1, 0xa7, 0x4b, 0x94, 0x32, 0xdb, 0xc7, 0xcd,
+ 0xd1, 0xa7, 0xcf, 0xbc, 0x49, 0x9c, 0xaa, 0x30, 0x81, 0xd7, 0x26, 0x90, 0x2a, 0x4e, 0x25, 0x25,
+ 0x71, 0xc2, 0xac, 0x8c, 0x65, 0x15, 0x87, 0xdb, 0xc8, 0x47, 0x6e, 0x10, 0x07, 0xe3, 0x96, 0x22,
+ 0x18, 0xcc, 0x2a, 0x82, 0x17, 0xc1, 0x7c, 0x47, 0xcc, 0x88, 0x00, 0x65, 0xb6, 0x73, 0xe3, 0x14,
+ 0xe5, 0x8e, 0x72, 0xf2, 0xe9, 0xf3, 0xc2, 0x4c, 0x55, 0x59, 0x1b, 0x3f, 0x69, 0xe0, 0xc8, 0x15,
+ 0xd6, 0xac, 0xa0, 0x76, 0x3b, 0x14, 0x69, 0xe4, 0x3b, 0x34, 0xc8, 0x09, 0xff, 0x87, 0x27, 0x41,
+ 0xca, 0x41, 0xb4, 0x66, 0xa3, 0x8e, 0xba, 0x1e, 0xf3, 0x0e, 0xa2, 0x15, 0xd4, 0x81, 0x9f, 0x83,
+ 0x6c, 0xc7, 0x27, 0x1d, 0x42, 0xb1, 0x3f, 0xb8, 0x62, 0xfc, 0x7a, 0x2c, 0x96, 0xb7, 0xff, 0x7e,
+ 0x5e, 0x30, 0x9d, 0x16, 0x6b, 0x76, 0xeb, 0xa6, 0x4d, 0x5c, 0x4b, 0xf5, 0x06, 0xf9, 0x39, 0x4f,
+ 0x1b, 0xbb, 0x16, 0xdb, 0xeb, 0x60, 0x6a, 0x56, 0x86, 0x77, 0xbb, 0x7a, 0x34, 0xf0, 0x15, 0xdc,
+ 0xcb, 0x15, 0x90, 0xb6, 0x9b, 0xa8, 0xe5, 0xd5, 0x5a, 0x8d, 0x5c, 0x72, 0x5d, 0x2b, 0x25, 0xaa,
+ 0x29, 0x31, 0xbe, 0xde, 0x30, 0x8a, 0xe0, 0xd8, 0x15, 0xca, 0x5a, 0x2e, 0x62, 0xf8, 0x1a, 0x1a,
+ 0x06, 0x22, 0x0b, 0x12, 0x0e, 0x92, 0xe4, 0x93, 0x55, 0xfe, 0x6b, 0x3c, 0x4a, 0x06, 0x39, 0xf5,
+ 0x91, 0x8d, 0x77, 0xfa, 0xc1, 0x39, 0xb7, 0x40, 0xc2, 0xa5, 0x8e, 0x8a, 0x57, 0x61, 0x3c, 0x5e,
+ 0xb7, 0xa8, 0x73, 0x85, 0xcf, 0xe1, 0xae, 0xbb, 0xd3, 0xaf, 0x72, 0x5b, 0x78, 0x09, 0x2c, 0x32,
+ 0xee, 0xa4, 0x66, 0x13, 0xef, 0x4e, 0xcb, 0x11, 0x27, 0xcd, 0x6c, 0xaf, 0x8d, 0xef, 0x15, 0x50,
+ 0x15, 0x61, 0x54, 0xcd, 0xb0, 0xe1, 0x00, 0x56, 0xc0, 0x62, 0xc7, 0xc7, 0x0d, 0x6c, 0x63, 0x4a,
+ 0x89, 0x4f, 0x73, 0x49, 0x51, 0x50, 0x53, 0xd1, 0x23, 0x9b, 0xf8, 0x2b, 0x59, 0x6f, 0x13, 0x7b,
+ 0x37, 0x78, 0x8f, 0xe6, 0x44, 0x64, 0x32, 0x62, 0x4e, 0xbe, 0x46, 0x70, 0x0d, 0x00, 0x69, 0x22,
+ 0x2e, 0xcd, 0xbc, 0xb8, 0x34, 0x0b, 0x62, 0x46, 0xf4, 0x99, 0x4a, 0xb0, 0xcc, 0x5b, 0x61, 0x2e,
+ 0x25, 0x8e, 0xa1, 0x9b, 0xb2, 0x4f, 0x9a, 0x41, 0x9f, 0x34, 0x77, 0x82, 0x3e, 0x59, 0x4e, 0xf3,
+ 0xa2, 0x79, 0xfc, 0x7b, 0x41, 0x53, 0x4e, 0xf8, 0xca, 0xc4, 0xdc, 0xa7, 0xff, 0x9b, 0xdc, 0x2f,
+ 0x44, 0x72, 0x0f, 0x0d, 0xb0, 0x24, 0xe9, 0xbb, 0xa8, 0x5f, 0xe3, 0xe9, 0x06, 0xa1, 0x08, 0xdc,
+ 0x42, 0xfd, 0x6b, 0x88, 0x7e, 0x98, 0x4c, 0xcf, 0x66, 0x13, 0xd5, 0x34, 0xeb, 0xd7, 0x5a, 0x5e,
+ 0x03, 0xf7, 0x8d, 0xb3, 0xea, 0x95, 0x1b, 0x54, 0xc1, 0xf0, 0x09, 0x6a, 0x20, 0x86, 0x82, 0x72,
+ 0xe7, 0xff, 0xc6, 0x8f, 0x09, 0x70, 0x62, 0x68, 0x5c, 0xe6, 0x5e, 0x43, 0x55, 0xc3, 0xfa, 0xc1,
+ 0x43, 0x30, 0xbd, 0x6a, 0x58, 0x9f, 0xbe, 0x82, 0xaa, 0xf9, 0x3f, 0xe1, 0xd3, 0x13, 0x6e, 0x9c,
+ 0x07, 0x27, 0xc7, 0x72, 0x76, 0x40, 0x8e, 0x8f, 0x0f, 0xfa, 0x35, 0xc5, 0x57, 0x71, 0xd0, 0x17,
+ 0x8c, 0x9b, 0x83, 0x5e, 0xac, 0xa6, 0x95, 0x8b, 0xb7, 0x41, 0x9a, 0x3f, 0xde, 0xb5, 0x3b, 0x58,
+ 0xf5, 0xc3, 0xf2, 0xca, 0x6f, 0xcf, 0x0b, 0xc7, 0xe5, 0x09, 0x69, 0x63, 0xd7, 0x6c, 0x11, 0xcb,
+ 0x45, 0xac, 0x69, 0x5e, 0xf7, 0x18, 0xef, 0xd3, 0x62, 0xf7, 0xf6, 0xcf, 0x8b, 0x60, 0x4e, 0xb8,
+ 0x83, 0x5f, 0x68, 0x20, 0xa5, 0xe4, 0x09, 0xdc, 0x18, 0x4f, 0xfd, 0x04, 0xfd, 0xa9, 0x6f, 0x4e,
+ 0x33, 0x93, 0xd4, 0x8c, 0xe2, 0xc3, 0x5f, 0xfe, 0xfc, 0x6e, 0xf6, 0x34, 0x2c, 0x70, 0xb5, 0x4c,
+ 0x68, 0xa0, 0x99, 0x95, 0x3c, 0xb1, 0xee, 0xab, 0x54, 0x3d, 0x80, 0xdf, 0x6b, 0x60, 0x29, 0xa2,
+ 0x00, 0xe1, 0x9b, 0x31, 0x10, 0x93, 0x94, 0xa6, 0x7e, 0xee, 0x70, 0xc6, 0x8a, 0x95, 0x29, 0x58,
+ 0x95, 0xe0, 0x66, 0x94, 0x55, 0x20, 0x34, 0xc7, 0xc8, 0xfd, 0xa0, 0x81, 0xec, 0xa8, 0x90, 0x83,
+ 0x66, 0x0c, 0x64, 0x8c, 0x7e, 0xd4, 0xad, 0x43, 0xdb, 0x2b, 0x96, 0x17, 0x05, 0xcb, 0x0b, 0xd0,
+ 0x8c, 0xb2, 0xec, 0x05, 0xf6, 0x43, 0xa2, 0x61, 0x5d, 0xfa, 0x00, 0x3e, 0xd4, 0x40, 0x4a, 0xc9,
+ 0xb5, 0xd8, 0x74, 0x46, 0x95, 0x60, 0x6c, 0x3a, 0x47, 0x54, 0x9f, 0x51, 0x12, 0x94, 0x0c, 0xb8,
+ 0x1e, 0xa5, 0xa4, 0xa4, 0x1f, 0x0d, 0x85, 0xec, 0x2b, 0x0d, 0xa4, 0x94, 0x68, 0x8b, 0x25, 0x11,
+ 0x55, 0x88, 0xb1, 0x24, 0x46, 0xb4, 0x9f, 0x71, 0x5e, 0x90, 0x28, 0xc2, 0x8d, 0x28, 0x09, 0x2a,
+ 0xcd, 0x86, 0x1c, 0xac, 0xfb, 0xbb, 0x78, 0xef, 0x01, 0xec, 0x81, 0x24, 0xd7, 0x75, 0xd0, 0x88,
+ 0x2d, 0x91, 0x81, 0x58, 0xd4, 0x5f, 0x3f, 0xd0, 0x46, 0xe1, 0x6f, 0x08, 0xfc, 0x02, 0x5c, 0x1b,
+ 0xad, 0x9e, 0x46, 0x24, 0x02, 0x14, 0xcc, 0x4b, 0x59, 0x03, 0xdf, 0x88, 0xf1, 0x1a, 0x51, 0x4f,
+ 0xfa, 0xc6, 0x14, 0x2b, 0x85, 0xbe, 0x2a, 0xd0, 0x4f, 0xc0, 0xe5, 0x28, 0xba, 0xd4, 0x4c, 0x90,
+ 0x81, 0x94, 0x92, 0x4c, 0x70, 0x7d, 0xdc, 0x5f, 0x54, 0x4d, 0xe9, 0xc5, 0x69, 0x2d, 0x22, 0xc0,
+ 0xcc, 0x0b, 0xcc, 0x1c, 0x3c, 0x11, 0xc5, 0xc4, 0xac, 0x59, 0xb3, 0x39, 0xd4, 0x3d, 0x90, 0x09,
+ 0xe9, 0x9d, 0x43, 0x20, 0x4f, 0x38, 0xeb, 0x04, 0xc1, 0x64, 0x18, 0x02, 0x77, 0x15, 0xea, 0x23,
+ 0xb8, 0xca, 0x94, 0xbf, 0xb6, 0xb0, 0x0f, 0x52, 0xaa, 0x6d, 0xc6, 0xd6, 0x59, 0x54, 0x5c, 0xc5,
+ 0xd6, 0xd9, 0x48, 0xf7, 0x8d, 0x3b, 0xb5, 0xec, 0x97, 0xac, 0x0f, 0x1f, 0x69, 0x00, 0x0c, 0x1f,
+ 0x74, 0x58, 0x3a, 0xc8, 0x6d, 0xb8, 0x4f, 0xeb, 0x67, 0x0e, 0x61, 0xa9, 0x38, 0x9c, 0x16, 0x1c,
+ 0x4e, 0xc1, 0x95, 0x49, 0x1c, 0x44, 0x87, 0xe1, 0x01, 0x50, 0x0d, 0xe1, 0x80, 0xdb, 0x1e, 0xee,
+ 0x23, 0x07, 0xdc, 0xf6, 0x48, 0x5f, 0x89, 0x0b, 0x40, 0xd0, 0x6b, 0xca, 0x97, 0x9e, 0xbe, 0xc8,
+ 0x6b, 0xcf, 0x5e, 0xe4, 0xb5, 0x3f, 0x5e, 0xe4, 0xb5, 0xc7, 0xfb, 0xf9, 0x99, 0x67, 0xfb, 0xf9,
+ 0x99, 0x5f, 0xf7, 0xf3, 0x33, 0x9f, 0x6d, 0x86, 0xfa, 0xed, 0x60, 0x2f, 0xa1, 0x56, 0x6f, 0xeb,
+ 0x1d, 0xab, 0x2f, 0xfc, 0x88, 0x9e, 0x5b, 0x9f, 0x17, 0xed, 0xfd, 0xad, 0x7f, 0x02, 0x00, 0x00,
+ 0xff, 0xff, 0x76, 0xcb, 0xf6, 0xc5, 0xce, 0x11, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// QueryClient is the client API for Query service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type QueryClient interface {
+ // Account queries an Ethereum account.
+ Account(ctx context.Context, in *QueryAccountRequest, opts ...grpc.CallOption) (*QueryAccountResponse, error)
+ // CosmosAccount queries an Ethereum account's Cosmos Address.
+ CosmosAccount(ctx context.Context, in *QueryCosmosAccountRequest, opts ...grpc.CallOption) (*QueryCosmosAccountResponse, error)
+ // ValidatorAccount queries an Ethereum account's from a validator consensus
+ // Address.
+ ValidatorAccount(ctx context.Context, in *QueryValidatorAccountRequest, opts ...grpc.CallOption) (*QueryValidatorAccountResponse, error)
+ // Balance queries the balance of a the EVM denomination for a single
+ // account.
+ Balance(ctx context.Context, in *QueryBalanceRequest, opts ...grpc.CallOption) (*QueryBalanceResponse, error)
+ // Storage queries the balance of all coins for a single account.
+ Storage(ctx context.Context, in *QueryStorageRequest, opts ...grpc.CallOption) (*QueryStorageResponse, error)
+ // Code queries the balance of all coins for a single account.
+ Code(ctx context.Context, in *QueryCodeRequest, opts ...grpc.CallOption) (*QueryCodeResponse, error)
+ // Params queries the parameters of x/evm module.
+ Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
+ // EthCall implements the `eth_call` rpc api
+ EthCall(ctx context.Context, in *EthCallRequest, opts ...grpc.CallOption) (*MsgEthereumTxResponse, error)
+ // EstimateGas implements the `eth_estimateGas` rpc api
+ EstimateGas(ctx context.Context, in *EthCallRequest, opts ...grpc.CallOption) (*EstimateGasResponse, error)
+ // TraceTx implements the `debug_traceTransaction` rpc api
+ TraceTx(ctx context.Context, in *QueryTraceTxRequest, opts ...grpc.CallOption) (*QueryTraceTxResponse, error)
+ // TraceBlock implements the `debug_traceBlockByNumber` and `debug_traceBlockByHash` rpc api
+ TraceBlock(ctx context.Context, in *QueryTraceBlockRequest, opts ...grpc.CallOption) (*QueryTraceBlockResponse, error)
+ // BaseFee queries the base fee of the parent block of the current block,
+ // it's similar to feemarket module's method, but also checks london hardfork status.
+ BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error)
+}
+
+type queryClient struct {
+ cc grpc1.ClientConn
+}
+
+func NewQueryClient(cc grpc1.ClientConn) QueryClient {
+ return &queryClient{cc}
+}
+
+func (c *queryClient) Account(ctx context.Context, in *QueryAccountRequest, opts ...grpc.CallOption) (*QueryAccountResponse, error) {
+ out := new(QueryAccountResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/Account", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) CosmosAccount(ctx context.Context, in *QueryCosmosAccountRequest, opts ...grpc.CallOption) (*QueryCosmosAccountResponse, error) {
+ out := new(QueryCosmosAccountResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/CosmosAccount", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) ValidatorAccount(ctx context.Context, in *QueryValidatorAccountRequest, opts ...grpc.CallOption) (*QueryValidatorAccountResponse, error) {
+ out := new(QueryValidatorAccountResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/ValidatorAccount", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) Balance(ctx context.Context, in *QueryBalanceRequest, opts ...grpc.CallOption) (*QueryBalanceResponse, error) {
+ out := new(QueryBalanceResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/Balance", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) Storage(ctx context.Context, in *QueryStorageRequest, opts ...grpc.CallOption) (*QueryStorageResponse, error) {
+ out := new(QueryStorageResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/Storage", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) Code(ctx context.Context, in *QueryCodeRequest, opts ...grpc.CallOption) (*QueryCodeResponse, error) {
+ out := new(QueryCodeResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/Code", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) {
+ out := new(QueryParamsResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/Params", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) EthCall(ctx context.Context, in *EthCallRequest, opts ...grpc.CallOption) (*MsgEthereumTxResponse, error) {
+ out := new(MsgEthereumTxResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/EthCall", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) EstimateGas(ctx context.Context, in *EthCallRequest, opts ...grpc.CallOption) (*EstimateGasResponse, error) {
+ out := new(EstimateGasResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/EstimateGas", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) TraceTx(ctx context.Context, in *QueryTraceTxRequest, opts ...grpc.CallOption) (*QueryTraceTxResponse, error) {
+ out := new(QueryTraceTxResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/TraceTx", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) TraceBlock(ctx context.Context, in *QueryTraceBlockRequest, opts ...grpc.CallOption) (*QueryTraceBlockResponse, error) {
+ out := new(QueryTraceBlockResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/TraceBlock", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error) {
+ out := new(QueryBaseFeeResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Query/BaseFee", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// QueryServer is the server API for Query service.
+type QueryServer interface {
+ // Account queries an Ethereum account.
+ Account(context.Context, *QueryAccountRequest) (*QueryAccountResponse, error)
+ // CosmosAccount queries an Ethereum account's Cosmos Address.
+ CosmosAccount(context.Context, *QueryCosmosAccountRequest) (*QueryCosmosAccountResponse, error)
+ // ValidatorAccount queries an Ethereum account's from a validator consensus
+ // Address.
+ ValidatorAccount(context.Context, *QueryValidatorAccountRequest) (*QueryValidatorAccountResponse, error)
+ // Balance queries the balance of a the EVM denomination for a single
+ // account.
+ Balance(context.Context, *QueryBalanceRequest) (*QueryBalanceResponse, error)
+ // Storage queries the balance of all coins for a single account.
+ Storage(context.Context, *QueryStorageRequest) (*QueryStorageResponse, error)
+ // Code queries the balance of all coins for a single account.
+ Code(context.Context, *QueryCodeRequest) (*QueryCodeResponse, error)
+ // Params queries the parameters of x/evm module.
+ Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
+ // EthCall implements the `eth_call` rpc api
+ EthCall(context.Context, *EthCallRequest) (*MsgEthereumTxResponse, error)
+ // EstimateGas implements the `eth_estimateGas` rpc api
+ EstimateGas(context.Context, *EthCallRequest) (*EstimateGasResponse, error)
+ // TraceTx implements the `debug_traceTransaction` rpc api
+ TraceTx(context.Context, *QueryTraceTxRequest) (*QueryTraceTxResponse, error)
+ // TraceBlock implements the `debug_traceBlockByNumber` and `debug_traceBlockByHash` rpc api
+ TraceBlock(context.Context, *QueryTraceBlockRequest) (*QueryTraceBlockResponse, error)
+ // BaseFee queries the base fee of the parent block of the current block,
+ // it's similar to feemarket module's method, but also checks london hardfork status.
+ BaseFee(context.Context, *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error)
+}
+
+// UnimplementedQueryServer can be embedded to have forward compatible implementations.
+type UnimplementedQueryServer struct {
+}
+
+func (*UnimplementedQueryServer) Account(ctx context.Context, req *QueryAccountRequest) (*QueryAccountResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Account not implemented")
+}
+func (*UnimplementedQueryServer) CosmosAccount(ctx context.Context, req *QueryCosmosAccountRequest) (*QueryCosmosAccountResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CosmosAccount not implemented")
+}
+func (*UnimplementedQueryServer) ValidatorAccount(ctx context.Context, req *QueryValidatorAccountRequest) (*QueryValidatorAccountResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ValidatorAccount not implemented")
+}
+func (*UnimplementedQueryServer) Balance(ctx context.Context, req *QueryBalanceRequest) (*QueryBalanceResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Balance not implemented")
+}
+func (*UnimplementedQueryServer) Storage(ctx context.Context, req *QueryStorageRequest) (*QueryStorageResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Storage not implemented")
+}
+func (*UnimplementedQueryServer) Code(ctx context.Context, req *QueryCodeRequest) (*QueryCodeResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Code not implemented")
+}
+func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
+}
+func (*UnimplementedQueryServer) EthCall(ctx context.Context, req *EthCallRequest) (*MsgEthereumTxResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method EthCall not implemented")
+}
+func (*UnimplementedQueryServer) EstimateGas(ctx context.Context, req *EthCallRequest) (*EstimateGasResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method EstimateGas not implemented")
+}
+func (*UnimplementedQueryServer) TraceTx(ctx context.Context, req *QueryTraceTxRequest) (*QueryTraceTxResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method TraceTx not implemented")
+}
+func (*UnimplementedQueryServer) TraceBlock(ctx context.Context, req *QueryTraceBlockRequest) (*QueryTraceBlockResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method TraceBlock not implemented")
+}
+func (*UnimplementedQueryServer) BaseFee(ctx context.Context, req *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method BaseFee not implemented")
+}
+
+func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
+ s.RegisterService(&_Query_serviceDesc, srv)
+}
+
+func _Query_Account_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryAccountRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).Account(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/Account",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).Account(ctx, req.(*QueryAccountRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_CosmosAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryCosmosAccountRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).CosmosAccount(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/CosmosAccount",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).CosmosAccount(ctx, req.(*QueryCosmosAccountRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_ValidatorAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryValidatorAccountRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).ValidatorAccount(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/ValidatorAccount",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).ValidatorAccount(ctx, req.(*QueryValidatorAccountRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_Balance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryBalanceRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).Balance(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/Balance",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).Balance(ctx, req.(*QueryBalanceRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_Storage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryStorageRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).Storage(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/Storage",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).Storage(ctx, req.(*QueryStorageRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_Code_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryCodeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).Code(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/Code",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).Code(ctx, req.(*QueryCodeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryParamsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).Params(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/Params",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_EthCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(EthCallRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).EthCall(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/EthCall",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).EthCall(ctx, req.(*EthCallRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_EstimateGas_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(EthCallRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).EstimateGas(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/EstimateGas",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).EstimateGas(ctx, req.(*EthCallRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_TraceTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryTraceTxRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).TraceTx(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/TraceTx",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).TraceTx(ctx, req.(*QueryTraceTxRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_TraceBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryTraceBlockRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).TraceBlock(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/TraceBlock",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).TraceBlock(ctx, req.(*QueryTraceBlockRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_BaseFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryBaseFeeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).BaseFee(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Query/BaseFee",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).BaseFee(ctx, req.(*QueryBaseFeeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Query_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "ethermint.evm.v1.Query",
+ HandlerType: (*QueryServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Account",
+ Handler: _Query_Account_Handler,
+ },
+ {
+ MethodName: "CosmosAccount",
+ Handler: _Query_CosmosAccount_Handler,
+ },
+ {
+ MethodName: "ValidatorAccount",
+ Handler: _Query_ValidatorAccount_Handler,
+ },
+ {
+ MethodName: "Balance",
+ Handler: _Query_Balance_Handler,
+ },
+ {
+ MethodName: "Storage",
+ Handler: _Query_Storage_Handler,
+ },
+ {
+ MethodName: "Code",
+ Handler: _Query_Code_Handler,
+ },
+ {
+ MethodName: "Params",
+ Handler: _Query_Params_Handler,
+ },
+ {
+ MethodName: "EthCall",
+ Handler: _Query_EthCall_Handler,
+ },
+ {
+ MethodName: "EstimateGas",
+ Handler: _Query_EstimateGas_Handler,
+ },
+ {
+ MethodName: "TraceTx",
+ Handler: _Query_TraceTx_Handler,
+ },
+ {
+ MethodName: "TraceBlock",
+ Handler: _Query_TraceBlock_Handler,
+ },
+ {
+ MethodName: "BaseFee",
+ Handler: _Query_BaseFee_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "ethermint/evm/v1/query.proto",
+}
+
+func (m *QueryAccountRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryAccountRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryAccountRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryAccountResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryAccountResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Nonce != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.Nonce))
+ i--
+ dAtA[i] = 0x18
+ }
+ if len(m.CodeHash) > 0 {
+ i -= len(m.CodeHash)
+ copy(dAtA[i:], m.CodeHash)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.CodeHash)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Balance) > 0 {
+ i -= len(m.Balance)
+ copy(dAtA[i:], m.Balance)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Balance)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryCosmosAccountRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryCosmosAccountRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryCosmosAccountRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryCosmosAccountResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryCosmosAccountResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryCosmosAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.AccountNumber != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.AccountNumber))
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.Sequence != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.Sequence))
+ i--
+ dAtA[i] = 0x10
+ }
+ if len(m.CosmosAddress) > 0 {
+ i -= len(m.CosmosAddress)
+ copy(dAtA[i:], m.CosmosAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.CosmosAddress)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryValidatorAccountRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryValidatorAccountRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryValidatorAccountRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ConsAddress) > 0 {
+ i -= len(m.ConsAddress)
+ copy(dAtA[i:], m.ConsAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ConsAddress)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryValidatorAccountResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryValidatorAccountResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryValidatorAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.AccountNumber != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.AccountNumber))
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.Sequence != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.Sequence))
+ i--
+ dAtA[i] = 0x10
+ }
+ if len(m.AccountAddress) > 0 {
+ i -= len(m.AccountAddress)
+ copy(dAtA[i:], m.AccountAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.AccountAddress)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBalanceRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBalanceRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBalanceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBalanceResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBalanceResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBalanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Balance) > 0 {
+ i -= len(m.Balance)
+ copy(dAtA[i:], m.Balance)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Balance)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryStorageRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryStorageRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryStorageRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Key) > 0 {
+ i -= len(m.Key)
+ copy(dAtA[i:], m.Key)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Key)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryStorageResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryStorageResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryStorageResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Value) > 0 {
+ i -= len(m.Value)
+ copy(dAtA[i:], m.Value)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Value)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryCodeRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryCodeRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryCodeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Address) > 0 {
+ i -= len(m.Address)
+ copy(dAtA[i:], m.Address)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Address)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryCodeResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryCodeResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryCodeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Code) > 0 {
+ i -= len(m.Code)
+ copy(dAtA[i:], m.Code)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Code)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryTxLogsRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryTxLogsRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryTxLogsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Pagination != nil {
+ {
+ size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Hash) > 0 {
+ i -= len(m.Hash)
+ copy(dAtA[i:], m.Hash)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Hash)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryTxLogsResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryTxLogsResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryTxLogsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Pagination != nil {
+ {
+ size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Logs) > 0 {
+ for iNdEx := len(m.Logs) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Logs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+}
+
+func (m *EthCallRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EthCallRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EthCallRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.ChainId != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.ChainId))
+ i--
+ dAtA[i] = 0x20
+ }
+ if len(m.ProposerAddress) > 0 {
+ i -= len(m.ProposerAddress)
+ copy(dAtA[i:], m.ProposerAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ProposerAddress)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.GasCap != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.GasCap))
+ i--
+ dAtA[i] = 0x10
+ }
+ if len(m.Args) > 0 {
+ i -= len(m.Args)
+ copy(dAtA[i:], m.Args)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Args)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *EstimateGasResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EstimateGasResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EstimateGasResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Gas != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.Gas))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryTraceTxRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryTraceTxRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryTraceTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.BlockMaxGas != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.BlockMaxGas))
+ i--
+ dAtA[i] = 0x50
+ }
+ if m.ChainId != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.ChainId))
+ i--
+ dAtA[i] = 0x48
+ }
+ if len(m.ProposerAddress) > 0 {
+ i -= len(m.ProposerAddress)
+ copy(dAtA[i:], m.ProposerAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ProposerAddress)))
+ i--
+ dAtA[i] = 0x42
+ }
+ n4, err4 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.BlockTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.BlockTime):])
+ if err4 != nil {
+ return 0, err4
+ }
+ i -= n4
+ i = encodeVarintQuery(dAtA, i, uint64(n4))
+ i--
+ dAtA[i] = 0x3a
+ if len(m.BlockHash) > 0 {
+ i -= len(m.BlockHash)
+ copy(dAtA[i:], m.BlockHash)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.BlockHash)))
+ i--
+ dAtA[i] = 0x32
+ }
+ if m.BlockNumber != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.BlockNumber))
+ i--
+ dAtA[i] = 0x28
+ }
+ if len(m.Predecessors) > 0 {
+ for iNdEx := len(m.Predecessors) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Predecessors[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x22
+ }
+ }
+ if m.TraceConfig != nil {
+ {
+ size, err := m.TraceConfig.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Msg != nil {
+ {
+ size, err := m.Msg.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryTraceTxResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryTraceTxResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryTraceTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryTraceBlockRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryTraceBlockRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryTraceBlockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.BlockMaxGas != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.BlockMaxGas))
+ i--
+ dAtA[i] = 0x50
+ }
+ if m.ChainId != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.ChainId))
+ i--
+ dAtA[i] = 0x48
+ }
+ if len(m.ProposerAddress) > 0 {
+ i -= len(m.ProposerAddress)
+ copy(dAtA[i:], m.ProposerAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ProposerAddress)))
+ i--
+ dAtA[i] = 0x42
+ }
+ n7, err7 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.BlockTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.BlockTime):])
+ if err7 != nil {
+ return 0, err7
+ }
+ i -= n7
+ i = encodeVarintQuery(dAtA, i, uint64(n7))
+ i--
+ dAtA[i] = 0x3a
+ if len(m.BlockHash) > 0 {
+ i -= len(m.BlockHash)
+ copy(dAtA[i:], m.BlockHash)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.BlockHash)))
+ i--
+ dAtA[i] = 0x32
+ }
+ if m.BlockNumber != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.BlockNumber))
+ i--
+ dAtA[i] = 0x28
+ }
+ if m.TraceConfig != nil {
+ {
+ size, err := m.TraceConfig.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Txs) > 0 {
+ for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Txs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryTraceBlockResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryTraceBlockResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryTraceBlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBaseFeeRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBaseFeeRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBaseFeeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBaseFeeResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBaseFeeResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBaseFeeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.BaseFee != nil {
+ {
+ size := m.BaseFee.Size()
+ i -= size
+ if _, err := m.BaseFee.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
+ offset -= sovQuery(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *QueryAccountRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryAccountResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Balance)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ l = len(m.CodeHash)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.Nonce != 0 {
+ n += 1 + sovQuery(uint64(m.Nonce))
+ }
+ return n
+}
+
+func (m *QueryCosmosAccountRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryCosmosAccountResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.CosmosAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.Sequence != 0 {
+ n += 1 + sovQuery(uint64(m.Sequence))
+ }
+ if m.AccountNumber != 0 {
+ n += 1 + sovQuery(uint64(m.AccountNumber))
+ }
+ return n
+}
+
+func (m *QueryValidatorAccountRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ConsAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryValidatorAccountResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.AccountAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.Sequence != 0 {
+ n += 1 + sovQuery(uint64(m.Sequence))
+ }
+ if m.AccountNumber != 0 {
+ n += 1 + sovQuery(uint64(m.AccountNumber))
+ }
+ return n
+}
+
+func (m *QueryBalanceRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryBalanceResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Balance)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryStorageRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryStorageResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryCodeRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Address)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryCodeResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Code)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryTxLogsRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Hash)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.Pagination != nil {
+ l = m.Pagination.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryTxLogsResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.Logs) > 0 {
+ for _, e := range m.Logs {
+ l = e.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ }
+ if m.Pagination != nil {
+ l = m.Pagination.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryParamsRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *QueryParamsResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = m.Params.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ return n
+}
+
+func (m *EthCallRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Args)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.GasCap != 0 {
+ n += 1 + sovQuery(uint64(m.GasCap))
+ }
+ l = len(m.ProposerAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.ChainId != 0 {
+ n += 1 + sovQuery(uint64(m.ChainId))
+ }
+ return n
+}
+
+func (m *EstimateGasResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Gas != 0 {
+ n += 1 + sovQuery(uint64(m.Gas))
+ }
+ return n
+}
+
+func (m *QueryTraceTxRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Msg != nil {
+ l = m.Msg.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.TraceConfig != nil {
+ l = m.TraceConfig.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if len(m.Predecessors) > 0 {
+ for _, e := range m.Predecessors {
+ l = e.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ }
+ if m.BlockNumber != 0 {
+ n += 1 + sovQuery(uint64(m.BlockNumber))
+ }
+ l = len(m.BlockHash)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.BlockTime)
+ n += 1 + l + sovQuery(uint64(l))
+ l = len(m.ProposerAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.ChainId != 0 {
+ n += 1 + sovQuery(uint64(m.ChainId))
+ }
+ if m.BlockMaxGas != 0 {
+ n += 1 + sovQuery(uint64(m.BlockMaxGas))
+ }
+ return n
+}
+
+func (m *QueryTraceTxResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryTraceBlockRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.Txs) > 0 {
+ for _, e := range m.Txs {
+ l = e.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ }
+ if m.TraceConfig != nil {
+ l = m.TraceConfig.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.BlockNumber != 0 {
+ n += 1 + sovQuery(uint64(m.BlockNumber))
+ }
+ l = len(m.BlockHash)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.BlockTime)
+ n += 1 + l + sovQuery(uint64(l))
+ l = len(m.ProposerAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ if m.ChainId != 0 {
+ n += 1 + sovQuery(uint64(m.ChainId))
+ }
+ if m.BlockMaxGas != 0 {
+ n += 1 + sovQuery(uint64(m.BlockMaxGas))
+ }
+ return n
+}
+
+func (m *QueryTraceBlockResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryBaseFeeRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *QueryBaseFeeResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.BaseFee != nil {
+ l = m.BaseFee.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func sovQuery(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozQuery(x uint64) (n int) {
+ return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *QueryAccountRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryAccountRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryAccountRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryAccountResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryAccountResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Balance = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CodeHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.CodeHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType)
+ }
+ m.Nonce = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Nonce |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryCosmosAccountRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryCosmosAccountRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryCosmosAccountRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryCosmosAccountResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryCosmosAccountResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryCosmosAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CosmosAddress", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.CosmosAddress = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
+ }
+ m.Sequence = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Sequence |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccountNumber", wireType)
+ }
+ m.AccountNumber = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.AccountNumber |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryValidatorAccountRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryValidatorAccountRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryValidatorAccountRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ConsAddress", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ConsAddress = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryValidatorAccountResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryValidatorAccountResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryValidatorAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccountAddress", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.AccountAddress = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
+ }
+ m.Sequence = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Sequence |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AccountNumber", wireType)
+ }
+ m.AccountNumber = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.AccountNumber |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBalanceRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBalanceRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBalanceRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBalanceResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Balance = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryStorageRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryStorageRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryStorageRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryStorageResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryStorageResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryStorageResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryCodeRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryCodeRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryCodeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Address = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryCodeResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryCodeResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryCodeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Code = append(m.Code[:0], dAtA[iNdEx:postIndex]...)
+ if m.Code == nil {
+ m.Code = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryTxLogsRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryTxLogsRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryTxLogsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Pagination == nil {
+ m.Pagination = &query.PageRequest{}
+ }
+ if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryTxLogsResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryTxLogsResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryTxLogsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Logs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Logs = append(m.Logs, &Log{})
+ if err := m.Logs[len(m.Logs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Pagination == nil {
+ m.Pagination = &query.PageResponse{}
+ }
+ if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *EthCallRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EthCallRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EthCallRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Args", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Args = append(m.Args[:0], dAtA[iNdEx:postIndex]...)
+ if m.Args == nil {
+ m.Args = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasCap", wireType)
+ }
+ m.GasCap = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GasCap |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...)
+ if m.ProposerAddress == nil {
+ m.ProposerAddress = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
+ }
+ m.ChainId = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ChainId |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *EstimateGasResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EstimateGasResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EstimateGasResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Gas", wireType)
+ }
+ m.Gas = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Gas |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryTraceTxRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryTraceTxRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryTraceTxRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Msg", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Msg == nil {
+ m.Msg = &MsgEthereumTx{}
+ }
+ if err := m.Msg.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TraceConfig", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.TraceConfig == nil {
+ m.TraceConfig = &TraceConfig{}
+ }
+ if err := m.TraceConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Predecessors", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Predecessors = append(m.Predecessors, &MsgEthereumTx{})
+ if err := m.Predecessors[len(m.Predecessors)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockNumber", wireType)
+ }
+ m.BlockNumber = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BlockNumber |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.BlockHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockTime", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.BlockTime, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...)
+ if m.ProposerAddress == nil {
+ m.ProposerAddress = []byte{}
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
+ }
+ m.ChainId = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ChainId |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 10:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockMaxGas", wireType)
+ }
+ m.BlockMaxGas = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BlockMaxGas |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryTraceTxResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryTraceTxResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryTraceTxResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryTraceBlockRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryTraceBlockRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryTraceBlockRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Txs = append(m.Txs, &MsgEthereumTx{})
+ if err := m.Txs[len(m.Txs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TraceConfig", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.TraceConfig == nil {
+ m.TraceConfig = &TraceConfig{}
+ }
+ if err := m.TraceConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockNumber", wireType)
+ }
+ m.BlockNumber = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BlockNumber |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.BlockHash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockTime", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.BlockTime, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...)
+ if m.ProposerAddress == nil {
+ m.ProposerAddress = []byte{}
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
+ }
+ m.ChainId = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ChainId |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 10:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockMaxGas", wireType)
+ }
+ m.BlockMaxGas = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BlockMaxGas |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryTraceBlockResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryTraceBlockResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryTraceBlockResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBaseFeeRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBaseFeeRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBaseFeeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBaseFeeResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBaseFeeResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBaseFeeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BaseFee", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.BaseFee = &v
+ if err := m.BaseFee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipQuery(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthQuery
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupQuery
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthQuery
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/evm/types/query.pb.gw.go b/x/evm/types/query.pb.gw.go
new file mode 100644
index 00000000..a7ba3846
--- /dev/null
+++ b/x/evm/types/query.pb.gw.go
@@ -0,0 +1,1178 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: ethermint/evm/v1/query.proto
+
+/*
+Package types is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package types
+
+import (
+ "context"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/grpc-ecosystem/grpc-gateway/utilities"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+// Suppress "imported and not used" errors
+var _ codes.Code
+var _ io.Reader
+var _ status.Status
+var _ = runtime.String
+var _ = utilities.NewDoubleArray
+var _ = descriptor.ForMessage
+var _ = metadata.Join
+
+func request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryAccountRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := client.Account(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryAccountRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := server.Account(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_CosmosAccount_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryCosmosAccountRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := client.CosmosAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_CosmosAccount_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryCosmosAccountRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := server.CosmosAccount(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_ValidatorAccount_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryValidatorAccountRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["cons_address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cons_address")
+ }
+
+ protoReq.ConsAddress, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cons_address", err)
+ }
+
+ msg, err := client.ValidatorAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_ValidatorAccount_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryValidatorAccountRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["cons_address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cons_address")
+ }
+
+ protoReq.ConsAddress, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cons_address", err)
+ }
+
+ msg, err := server.ValidatorAccount(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBalanceRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := client.Balance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBalanceRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := server.Balance(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_Storage_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryStorageRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ val, ok = pathParams["key"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "key")
+ }
+
+ protoReq.Key, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "key", err)
+ }
+
+ msg, err := client.Storage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_Storage_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryStorageRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ val, ok = pathParams["key"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "key")
+ }
+
+ protoReq.Key, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "key", err)
+ }
+
+ msg, err := server.Storage(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_Code_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryCodeRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := client.Code(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_Code_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryCodeRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
+ }
+
+ protoReq.Address, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
+ }
+
+ msg, err := server.Code(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryParamsRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryParamsRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := server.Params(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_Query_EthCall_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_Query_EthCall_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq EthCallRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_EthCall_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.EthCall(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_EthCall_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq EthCallRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_EthCall_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.EthCall(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_Query_EstimateGas_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_Query_EstimateGas_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq EthCallRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_EstimateGas_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.EstimateGas(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_EstimateGas_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq EthCallRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_EstimateGas_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.EstimateGas(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_Query_TraceTx_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_Query_TraceTx_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryTraceTxRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_TraceTx_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.TraceTx(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_TraceTx_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryTraceTxRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_TraceTx_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.TraceTx(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_Query_TraceBlock_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_Query_TraceBlock_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryTraceBlockRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_TraceBlock_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.TraceBlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_TraceBlock_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryTraceBlockRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_TraceBlock_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.TraceBlock(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_BaseFee_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBaseFeeRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := client.BaseFee(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_BaseFee_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBaseFeeRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := server.BaseFee(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
+// UnaryRPC :call QueryServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
+func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
+
+ mux.Handle("GET", pattern_Query_Account_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_Account_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Account_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_CosmosAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_CosmosAccount_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_CosmosAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_ValidatorAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_ValidatorAccount_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_ValidatorAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_Balance_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Storage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_Storage_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Storage_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Code_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_Code_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Code_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_EthCall_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_EthCall_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_EthCall_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_EstimateGas_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_EstimateGas_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_EstimateGas_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_TraceTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_TraceTx_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_TraceTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_TraceBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_TraceBlock_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_TraceBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_BaseFee_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_BaseFee_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_BaseFee_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterQueryHandler(ctx, mux, conn)
+}
+
+// RegisterQueryHandler registers the http handlers for service Query to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
+}
+
+// RegisterQueryHandlerClient registers the http handlers for service Query
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "QueryClient" to call the correct interceptors.
+func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
+
+ mux.Handle("GET", pattern_Query_Account_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_Account_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Account_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_CosmosAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_CosmosAccount_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_CosmosAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_ValidatorAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_ValidatorAccount_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_ValidatorAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_Balance_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Storage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_Storage_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Storage_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Code_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_Code_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Code_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_EthCall_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_EthCall_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_EthCall_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_EstimateGas_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_EstimateGas_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_EstimateGas_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_TraceTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_TraceTx_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_TraceTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_TraceBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_TraceBlock_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_TraceBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_BaseFee_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_BaseFee_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_BaseFee_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Query_Account_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"evmos", "evm", "v1", "account", "address"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_CosmosAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"evmos", "evm", "v1", "cosmos_account", "address"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_ValidatorAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"evmos", "evm", "v1", "validator_account", "cons_address"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_Balance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"evmos", "evm", "v1", "balances", "address"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_Storage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"evmos", "evm", "v1", "storage", "address", "key"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_Code_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"evmos", "evm", "v1", "codes", "address"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "evm", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_EthCall_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "evm", "v1", "eth_call"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_EstimateGas_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "evm", "v1", "estimate_gas"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_TraceTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "evm", "v1", "trace_tx"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_TraceBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "evm", "v1", "trace_block"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_BaseFee_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "evm", "v1", "base_fee"}, "", runtime.AssumeColonVerbOpt(false)))
+)
+
+var (
+ forward_Query_Account_0 = runtime.ForwardResponseMessage
+
+ forward_Query_CosmosAccount_0 = runtime.ForwardResponseMessage
+
+ forward_Query_ValidatorAccount_0 = runtime.ForwardResponseMessage
+
+ forward_Query_Balance_0 = runtime.ForwardResponseMessage
+
+ forward_Query_Storage_0 = runtime.ForwardResponseMessage
+
+ forward_Query_Code_0 = runtime.ForwardResponseMessage
+
+ forward_Query_Params_0 = runtime.ForwardResponseMessage
+
+ forward_Query_EthCall_0 = runtime.ForwardResponseMessage
+
+ forward_Query_EstimateGas_0 = runtime.ForwardResponseMessage
+
+ forward_Query_TraceTx_0 = runtime.ForwardResponseMessage
+
+ forward_Query_TraceBlock_0 = runtime.ForwardResponseMessage
+
+ forward_Query_BaseFee_0 = runtime.ForwardResponseMessage
+)
diff --git a/x/evm/types/storage.go b/x/evm/types/storage.go
new file mode 100644
index 00000000..730c157a
--- /dev/null
+++ b/x/evm/types/storage.go
@@ -0,0 +1,68 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "fmt"
+ "strings"
+
+ errorsmod "cosmossdk.io/errors"
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// Storage represents the account Storage map as a slice of single key value
+// State pairs. This is to prevent non determinism at genesis initialization or export.
+type Storage []State
+
+// Validate performs a basic validation of the Storage fields.
+func (s Storage) Validate() error {
+ seenStorage := make(map[string]bool)
+ for i, state := range s {
+ if seenStorage[state.Key] {
+ return errorsmod.Wrapf(ErrInvalidState, "duplicate state key %d: %s", i, state.Key)
+ }
+
+ if err := state.Validate(); err != nil {
+ return err
+ }
+
+ seenStorage[state.Key] = true
+ }
+ return nil
+}
+
+// String implements the stringer interface
+func (s Storage) String() string {
+ var str string
+ for _, state := range s {
+ str += fmt.Sprintf("%s\n", state.String())
+ }
+
+ return str
+}
+
+// Copy returns a copy of storage.
+func (s Storage) Copy() Storage {
+ cpy := make(Storage, len(s))
+ copy(cpy, s)
+
+ return cpy
+}
+
+// Validate performs a basic validation of the State fields.
+// NOTE: state value can be empty
+func (s State) Validate() error {
+ if strings.TrimSpace(s.Key) == "" {
+ return errorsmod.Wrap(ErrInvalidState, "state key hash cannot be blank")
+ }
+
+ return nil
+}
+
+// NewState creates a new State instance
+func NewState(key, value common.Hash) State {
+ return State{
+ Key: key.String(),
+ Value: value.String(),
+ }
+}
diff --git a/x/evm/types/storage_test.go b/x/evm/types/storage_test.go
new file mode 100644
index 00000000..515f2a83
--- /dev/null
+++ b/x/evm/types/storage_test.go
@@ -0,0 +1,84 @@
+package types
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/stretchr/testify/require"
+)
+
+func TestStorageValidate(t *testing.T) {
+ testCases := []struct {
+ name string
+ storage Storage
+ expPass bool
+ }{
+ {
+ "valid storage",
+ Storage{
+ NewState(common.BytesToHash([]byte{1, 2, 3}), common.BytesToHash([]byte{1, 2, 3})),
+ },
+ true,
+ },
+ {
+ "empty storage key bytes",
+ Storage{
+ {Key: ""},
+ },
+ false,
+ },
+ {
+ "duplicated storage key",
+ Storage{
+ {Key: common.BytesToHash([]byte{1, 2, 3}).String()},
+ {Key: common.BytesToHash([]byte{1, 2, 3}).String()},
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ err := tc.storage.Validate()
+ if tc.expPass {
+ require.NoError(t, err, tc.name)
+ } else {
+ require.Error(t, err, tc.name)
+ }
+ }
+}
+
+func TestStorageCopy(t *testing.T) {
+ testCases := []struct {
+ name string
+ storage Storage
+ }{
+ {
+ "single storage",
+ Storage{
+ NewState(common.BytesToHash([]byte{1, 2, 3}), common.BytesToHash([]byte{1, 2, 3})),
+ },
+ },
+ {
+ "empty storage key value bytes",
+ Storage{
+ {Key: common.Hash{}.String(), Value: common.Hash{}.String()},
+ },
+ },
+ {
+ "empty storage",
+ Storage{},
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ require.Equal(t, tc.storage, tc.storage.Copy(), tc.name)
+ }
+}
+
+func TestStorageString(t *testing.T) {
+ storage := Storage{NewState(common.BytesToHash([]byte("key")), common.BytesToHash([]byte("value")))}
+ str := "key:\"0x00000000000000000000000000000000000000000000000000000000006b6579\" value:\"0x00000000000000000000000000000000000000000000000000000076616c7565\" \n"
+ require.Equal(t, str, storage.String())
+}
diff --git a/x/evm/types/testdata/SimpleContractHardhat.json b/x/evm/types/testdata/SimpleContractHardhat.json
new file mode 100644
index 00000000..bb658782
--- /dev/null
+++ b/x/evm/types/testdata/SimpleContractHardhat.json
@@ -0,0 +1,37 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "SimpleContract",
+ "sourceName": "contracts/SimpleContract.sol",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "setValue",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "value",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x608060405234801561001057600080fd5b50610133806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80633fa4f24514603757806355241077146051575b600080fd5b603d6069565b604051604891906090565b60405180910390f35b606760048036038101906063919060d5565b606f565b005b60005481565b8060008190555050565b6000819050919050565b608a816079565b82525050565b600060208201905060a360008301846083565b92915050565b600080fd5b60b5816079565b811460bf57600080fd5b50565b60008135905060cf8160ae565b92915050565b60006020828403121560e85760e760a9565b5b600060f48482850160c2565b9150509291505056fea2646970667358221220c9305ac8499dab6bde1cc24810af134727f1640c623f14bce015f6812a73762764736f6c63430008130033",
+ "deployedBytecode": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80633fa4f24514603757806355241077146051575b600080fd5b603d6069565b604051604891906090565b60405180910390f35b606760048036038101906063919060d5565b606f565b005b60005481565b8060008190555050565b6000819050919050565b608a816079565b82525050565b600060208201905060a360008301846083565b92915050565b600080fd5b60b5816079565b811460bf57600080fd5b50565b60008135905060cf8160ae565b92915050565b60006020828403121560e85760e760a9565b5b600060f48482850160c2565b9150509291505056fea2646970667358221220c9305ac8499dab6bde1cc24810af134727f1640c623f14bce015f6812a73762764736f6c63430008130033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/x/evm/types/tracer.go b/x/evm/types/tracer.go
new file mode 100644
index 00000000..b35334f1
--- /dev/null
+++ b/x/evm/types/tracer.go
@@ -0,0 +1,111 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math/big"
+ "os"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/evmos/v19/x/evm/core/logger"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+const (
+ TracerAccessList = "access_list"
+ TracerJSON = "json"
+ TracerStruct = "struct"
+ TracerMarkdown = "markdown"
+)
+
+// NewTracer creates a new Logger tracer to collect execution traces from an
+// EVM transaction.
+func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height int64) vm.EVMLogger {
+ // TODO: enable additional log configuration
+ logCfg := &logger.Config{
+ Debug: true,
+ }
+
+ switch tracer {
+ case TracerAccessList:
+ preCompiles := vm.DefaultActivePrecompiles(cfg.Rules(big.NewInt(height), cfg.MergeNetsplitBlock != nil))
+ return logger.NewAccessListTracer(msg.AccessList(), msg.From(), *msg.To(), preCompiles)
+ case TracerJSON:
+ return logger.NewJSONLogger(logCfg, os.Stderr)
+ case TracerMarkdown:
+ return logger.NewMarkdownLogger(logCfg, os.Stdout) // TODO: Stderr ?
+ case TracerStruct:
+ return logger.NewStructLogger(logCfg)
+ default:
+ return NewNoOpTracer()
+ }
+}
+
+// TxTraceResult is the result of a single transaction trace during a block trace.
+type TxTraceResult struct {
+ Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
+ Error string `json:"error,omitempty"` // Trace failure produced by the tracer
+}
+
+var _ vm.EVMLogger = &NoOpTracer{}
+
+// NoOpTracer is an empty implementation of vm.Tracer interface
+type NoOpTracer struct{}
+
+// NewNoOpTracer creates a no-op vm.Tracer
+func NewNoOpTracer() *NoOpTracer {
+ return &NoOpTracer{}
+}
+
+// CaptureStart implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureStart(env *vm.EVM,
+ from common.Address,
+ to common.Address,
+ create bool,
+ input []byte,
+ gas uint64,
+ value *big.Int) {
+}
+
+// CaptureState implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+}
+
+// CaptureFault implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnd implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureEnd(output []byte, gasUsed uint64, tm time.Duration, err error) {}
+
+// CaptureEnter implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+// CaptureExit implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
+
+// CaptureTxStart implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureTxStart(gasLimit uint64) {}
+
+// CaptureTxEnd implements vm.Tracer interface
+//
+//nolint:revive // allow unused parameters to indicate expected signature
+func (dt NoOpTracer) CaptureTxEnd(restGas uint64) {}
diff --git a/x/evm/types/tracer_test.go b/x/evm/types/tracer_test.go
new file mode 100644
index 00000000..6e21f93a
--- /dev/null
+++ b/x/evm/types/tracer_test.go
@@ -0,0 +1,11 @@
+package types
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestNewNoOpTracer(t *testing.T) {
+ require.Equal(t, &NoOpTracer{}, NewNoOpTracer())
+}
diff --git a/x/evm/types/tx.go b/x/evm/types/tx.go
new file mode 100644
index 00000000..26a0fb35
--- /dev/null
+++ b/x/evm/types/tx.go
@@ -0,0 +1,81 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math"
+ "math/big"
+
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/evmos/evmos/v19/x/evm/core/vm"
+)
+
+// EvmTxArgs encapsulates all possible params to create all EVM txs types.
+// This includes LegacyTx, DynamicFeeTx and AccessListTx
+type EvmTxArgs struct {
+ Nonce uint64
+ GasLimit uint64
+ Input []byte
+ GasFeeCap *big.Int
+ GasPrice *big.Int
+ ChainID *big.Int
+ Amount *big.Int
+ GasTipCap *big.Int
+ To *common.Address
+ Accesses *ethtypes.AccessList
+}
+
+// ToTxData converts the EvmTxArgs to TxData
+func (args *EvmTxArgs) ToTxData() (TxData, error) {
+ ethTx := NewTx(args).AsTransaction()
+ return NewTxDataFromTx(ethTx)
+}
+
+// GetTxPriority returns the priority of a given Ethereum tx. It relies of the
+// priority reduction global variable to calculate the tx priority given the tx
+// tip price:
+//
+// tx_priority = tip_price / priority_reduction
+func GetTxPriority(txData TxData, baseFee *big.Int) (priority int64) {
+ // calculate priority based on effective gas price
+ tipPrice := txData.EffectiveGasPrice(baseFee)
+ // if london hardfork is not enabled, tipPrice is the gasPrice
+ if baseFee != nil {
+ tipPrice = new(big.Int).Sub(tipPrice, baseFee)
+ }
+
+ priority = math.MaxInt64
+ priorityBig := new(big.Int).Quo(tipPrice, DefaultPriorityReduction.BigInt())
+
+ // safety check
+ if priorityBig.IsInt64() {
+ priority = priorityBig.Int64()
+ }
+
+ return priority
+}
+
+// Failed returns if the contract execution failed in vm errors
+func (m *MsgEthereumTxResponse) Failed() bool {
+ return len(m.VmError) > 0
+}
+
+// Return is a helper function to help caller distinguish between revert reason
+// and function return. Return returns the data after execution if no error occurs.
+func (m *MsgEthereumTxResponse) Return() []byte {
+ if m.Failed() {
+ return nil
+ }
+ return common.CopyBytes(m.Ret)
+}
+
+// Revert returns the concrete revert reason if the execution is aborted by `REVERT`
+// opcode. Note the reason can be nil if no data supplied with revert opcode.
+func (m *MsgEthereumTxResponse) Revert() []byte {
+ if m.VmError != vm.ErrExecutionReverted.Error() {
+ return nil
+ }
+ return common.CopyBytes(m.Ret)
+}
diff --git a/x/evm/types/tx.pb.go b/x/evm/types/tx.pb.go
new file mode 100644
index 00000000..87185af1
--- /dev/null
+++ b/x/evm/types/tx.pb.go
@@ -0,0 +1,3264 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/evm/v1/tx.proto
+
+package types
+
+import (
+ context "context"
+ cosmossdk_io_math "cosmossdk.io/math"
+ encoding_binary "encoding/binary"
+ fmt "fmt"
+ _ "github.com/cosmos/cosmos-proto"
+ types "github.com/cosmos/cosmos-sdk/codec/types"
+ _ "github.com/cosmos/cosmos-sdk/types/msgservice"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ grpc1 "github.com/cosmos/gogoproto/grpc"
+ proto "github.com/cosmos/gogoproto/proto"
+ _ "google.golang.org/genproto/googleapis/api/annotations"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// MsgEthereumTx encapsulates an Ethereum transaction as an SDK message.
+type MsgEthereumTx struct {
+ // data is inner transaction data of the Ethereum transaction
+ Data *types.Any `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+ // size is the encoded storage size of the transaction (DEPRECATED)
+ Size_ float64 `protobuf:"fixed64,2,opt,name=size,proto3" json:"-"`
+ // hash of the transaction in hex format
+ Hash string `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty" rlp:"-"`
+ // from is the ethereum signer address in hex format. This address value is checked
+ // against the address derived from the signature (V, R, S) using the
+ // secp256k1 elliptic curve
+ From string `protobuf:"bytes,4,opt,name=from,proto3" json:"from,omitempty"`
+}
+
+func (m *MsgEthereumTx) Reset() { *m = MsgEthereumTx{} }
+func (m *MsgEthereumTx) String() string { return proto.CompactTextString(m) }
+func (*MsgEthereumTx) ProtoMessage() {}
+func (*MsgEthereumTx) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{0}
+}
+func (m *MsgEthereumTx) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgEthereumTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgEthereumTx.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *MsgEthereumTx) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgEthereumTx.Merge(m, src)
+}
+func (m *MsgEthereumTx) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgEthereumTx) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgEthereumTx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgEthereumTx proto.InternalMessageInfo
+
+// LegacyTx is the transaction data of regular Ethereum transactions.
+// NOTE: All non-protected transactions (i.e non EIP155 signed) will fail if the
+// AllowUnprotectedTxs parameter is disabled.
+type LegacyTx struct {
+ // nonce corresponds to the account nonce (transaction sequence).
+ Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"`
+ // gas_price defines the value for each gas unit
+ GasPrice *cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=gas_price,json=gasPrice,proto3,customtype=cosmossdk.io/math.Int" json:"gas_price,omitempty"`
+ // gas defines the gas limit defined for the transaction.
+ GasLimit uint64 `protobuf:"varint,3,opt,name=gas,proto3" json:"gas,omitempty"`
+ // to is the hex formatted address of the recipient
+ To string `protobuf:"bytes,4,opt,name=to,proto3" json:"to,omitempty"`
+ // value defines the unsigned integer value of the transaction amount.
+ Amount *cosmossdk_io_math.Int `protobuf:"bytes,5,opt,name=value,proto3,customtype=cosmossdk.io/math.Int" json:"value,omitempty"`
+ // data is the data payload bytes of the transaction.
+ Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"`
+ // v defines the signature value
+ V []byte `protobuf:"bytes,7,opt,name=v,proto3" json:"v,omitempty"`
+ // r defines the signature value
+ R []byte `protobuf:"bytes,8,opt,name=r,proto3" json:"r,omitempty"`
+ // s define the signature value
+ S []byte `protobuf:"bytes,9,opt,name=s,proto3" json:"s,omitempty"`
+}
+
+func (m *LegacyTx) Reset() { *m = LegacyTx{} }
+func (m *LegacyTx) String() string { return proto.CompactTextString(m) }
+func (*LegacyTx) ProtoMessage() {}
+func (*LegacyTx) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{1}
+}
+func (m *LegacyTx) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LegacyTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LegacyTx.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LegacyTx) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LegacyTx.Merge(m, src)
+}
+func (m *LegacyTx) XXX_Size() int {
+ return m.Size()
+}
+func (m *LegacyTx) XXX_DiscardUnknown() {
+ xxx_messageInfo_LegacyTx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LegacyTx proto.InternalMessageInfo
+
+// AccessListTx is the data of EIP-2930 access list transactions.
+type AccessListTx struct {
+ // chain_id of the destination EVM chain
+ ChainID *cosmossdk_io_math.Int `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3,customtype=cosmossdk.io/math.Int" json:"chainID"`
+ // nonce corresponds to the account nonce (transaction sequence).
+ Nonce uint64 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
+ // gas_price defines the value for each gas unit
+ GasPrice *cosmossdk_io_math.Int `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice,proto3,customtype=cosmossdk.io/math.Int" json:"gas_price,omitempty"`
+ // gas defines the gas limit defined for the transaction.
+ GasLimit uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"`
+ // to is the recipient address in hex format
+ To string `protobuf:"bytes,5,opt,name=to,proto3" json:"to,omitempty"`
+ // value defines the unsigned integer value of the transaction amount.
+ Amount *cosmossdk_io_math.Int `protobuf:"bytes,6,opt,name=value,proto3,customtype=cosmossdk.io/math.Int" json:"value,omitempty"`
+ // data is the data payload bytes of the transaction.
+ Data []byte `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"`
+ // accesses is an array of access tuples
+ Accesses AccessList `protobuf:"bytes,8,rep,name=accesses,proto3,castrepeated=AccessList" json:"accessList"`
+ // v defines the signature value
+ V []byte `protobuf:"bytes,9,opt,name=v,proto3" json:"v,omitempty"`
+ // r defines the signature value
+ R []byte `protobuf:"bytes,10,opt,name=r,proto3" json:"r,omitempty"`
+ // s define the signature value
+ S []byte `protobuf:"bytes,11,opt,name=s,proto3" json:"s,omitempty"`
+}
+
+func (m *AccessListTx) Reset() { *m = AccessListTx{} }
+func (m *AccessListTx) String() string { return proto.CompactTextString(m) }
+func (*AccessListTx) ProtoMessage() {}
+func (*AccessListTx) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{2}
+}
+func (m *AccessListTx) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *AccessListTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_AccessListTx.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *AccessListTx) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccessListTx.Merge(m, src)
+}
+func (m *AccessListTx) XXX_Size() int {
+ return m.Size()
+}
+func (m *AccessListTx) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccessListTx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccessListTx proto.InternalMessageInfo
+
+// DynamicFeeTx is the data of EIP-1559 dynamic fee transactions.
+type DynamicFeeTx struct {
+ // chain_id of the destination EVM chain
+ ChainID *cosmossdk_io_math.Int `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3,customtype=cosmossdk.io/math.Int" json:"chainID"`
+ // nonce corresponds to the account nonce (transaction sequence).
+ Nonce uint64 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
+ // gas_tip_cap defines the max value for the gas tip
+ GasTipCap *cosmossdk_io_math.Int `protobuf:"bytes,3,opt,name=gas_tip_cap,json=gasTipCap,proto3,customtype=cosmossdk.io/math.Int" json:"gas_tip_cap,omitempty"`
+ // gas_fee_cap defines the max value for the gas fee
+ GasFeeCap *cosmossdk_io_math.Int `protobuf:"bytes,4,opt,name=gas_fee_cap,json=gasFeeCap,proto3,customtype=cosmossdk.io/math.Int" json:"gas_fee_cap,omitempty"`
+ // gas defines the gas limit defined for the transaction.
+ GasLimit uint64 `protobuf:"varint,5,opt,name=gas,proto3" json:"gas,omitempty"`
+ // to is the hex formatted address of the recipient
+ To string `protobuf:"bytes,6,opt,name=to,proto3" json:"to,omitempty"`
+ // value defines the transaction amount.
+ Amount *cosmossdk_io_math.Int `protobuf:"bytes,7,opt,name=value,proto3,customtype=cosmossdk.io/math.Int" json:"value,omitempty"`
+ // data is the data payload bytes of the transaction.
+ Data []byte `protobuf:"bytes,8,opt,name=data,proto3" json:"data,omitempty"`
+ // accesses is an array of access tuples
+ Accesses AccessList `protobuf:"bytes,9,rep,name=accesses,proto3,castrepeated=AccessList" json:"accessList"`
+ // v defines the signature value
+ V []byte `protobuf:"bytes,10,opt,name=v,proto3" json:"v,omitempty"`
+ // r defines the signature value
+ R []byte `protobuf:"bytes,11,opt,name=r,proto3" json:"r,omitempty"`
+ // s define the signature value
+ S []byte `protobuf:"bytes,12,opt,name=s,proto3" json:"s,omitempty"`
+}
+
+func (m *DynamicFeeTx) Reset() { *m = DynamicFeeTx{} }
+func (m *DynamicFeeTx) String() string { return proto.CompactTextString(m) }
+func (*DynamicFeeTx) ProtoMessage() {}
+func (*DynamicFeeTx) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{3}
+}
+func (m *DynamicFeeTx) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *DynamicFeeTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_DynamicFeeTx.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *DynamicFeeTx) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_DynamicFeeTx.Merge(m, src)
+}
+func (m *DynamicFeeTx) XXX_Size() int {
+ return m.Size()
+}
+func (m *DynamicFeeTx) XXX_DiscardUnknown() {
+ xxx_messageInfo_DynamicFeeTx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DynamicFeeTx proto.InternalMessageInfo
+
+// ExtensionOptionsEthereumTx is an extension option for ethereum transactions
+type ExtensionOptionsEthereumTx struct {
+}
+
+func (m *ExtensionOptionsEthereumTx) Reset() { *m = ExtensionOptionsEthereumTx{} }
+func (m *ExtensionOptionsEthereumTx) String() string { return proto.CompactTextString(m) }
+func (*ExtensionOptionsEthereumTx) ProtoMessage() {}
+func (*ExtensionOptionsEthereumTx) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{4}
+}
+func (m *ExtensionOptionsEthereumTx) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ExtensionOptionsEthereumTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ExtensionOptionsEthereumTx.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ExtensionOptionsEthereumTx) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ExtensionOptionsEthereumTx.Merge(m, src)
+}
+func (m *ExtensionOptionsEthereumTx) XXX_Size() int {
+ return m.Size()
+}
+func (m *ExtensionOptionsEthereumTx) XXX_DiscardUnknown() {
+ xxx_messageInfo_ExtensionOptionsEthereumTx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ExtensionOptionsEthereumTx proto.InternalMessageInfo
+
+// MsgEthereumTxResponse defines the Msg/EthereumTx response type.
+type MsgEthereumTxResponse struct {
+ // hash of the ethereum transaction in hex format. This hash differs from the
+ // Tendermint sha256 hash of the transaction bytes. See
+ // https://github.com/tendermint/tendermint/issues/6539 for reference
+ Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
+ // logs contains the transaction hash and the proto-compatible ethereum
+ // logs.
+ Logs []*Log `protobuf:"bytes,2,rep,name=logs,proto3" json:"logs,omitempty"`
+ // ret is the returned data from evm function (result or data supplied with revert
+ // opcode)
+ Ret []byte `protobuf:"bytes,3,opt,name=ret,proto3" json:"ret,omitempty"`
+ // vm_error is the error returned by vm execution
+ VmError string `protobuf:"bytes,4,opt,name=vm_error,json=vmError,proto3" json:"vm_error,omitempty"`
+ // gas_used specifies how much gas was consumed by the transaction
+ GasUsed uint64 `protobuf:"varint,5,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
+}
+
+func (m *MsgEthereumTxResponse) Reset() { *m = MsgEthereumTxResponse{} }
+func (m *MsgEthereumTxResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgEthereumTxResponse) ProtoMessage() {}
+func (*MsgEthereumTxResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{5}
+}
+func (m *MsgEthereumTxResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgEthereumTxResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgEthereumTxResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *MsgEthereumTxResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgEthereumTxResponse.Merge(m, src)
+}
+func (m *MsgEthereumTxResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgEthereumTxResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgEthereumTxResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgEthereumTxResponse proto.InternalMessageInfo
+
+// MsgUpdateParams defines a Msg for updating the x/evm module parameters.
+type MsgUpdateParams struct {
+ // authority is the address of the governance account.
+ Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"`
+ // params defines the x/evm parameters to update.
+ // NOTE: All parameters must be supplied.
+ Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"`
+}
+
+func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} }
+func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) }
+func (*MsgUpdateParams) ProtoMessage() {}
+func (*MsgUpdateParams) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{6}
+}
+func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *MsgUpdateParams) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgUpdateParams.Merge(m, src)
+}
+func (m *MsgUpdateParams) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgUpdateParams) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo
+
+func (m *MsgUpdateParams) GetAuthority() string {
+ if m != nil {
+ return m.Authority
+ }
+ return ""
+}
+
+func (m *MsgUpdateParams) GetParams() Params {
+ if m != nil {
+ return m.Params
+ }
+ return Params{}
+}
+
+// MsgUpdateParamsResponse defines the response structure for executing a
+// MsgUpdateParams message.
+type MsgUpdateParamsResponse struct {
+}
+
+func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} }
+func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgUpdateParamsResponse) ProtoMessage() {}
+func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f75ac0a12d075f21, []int{7}
+}
+func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src)
+}
+func (m *MsgUpdateParamsResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterType((*MsgEthereumTx)(nil), "ethermint.evm.v1.MsgEthereumTx")
+ proto.RegisterType((*LegacyTx)(nil), "ethermint.evm.v1.LegacyTx")
+ proto.RegisterType((*AccessListTx)(nil), "ethermint.evm.v1.AccessListTx")
+ proto.RegisterType((*DynamicFeeTx)(nil), "ethermint.evm.v1.DynamicFeeTx")
+ proto.RegisterType((*ExtensionOptionsEthereumTx)(nil), "ethermint.evm.v1.ExtensionOptionsEthereumTx")
+ proto.RegisterType((*MsgEthereumTxResponse)(nil), "ethermint.evm.v1.MsgEthereumTxResponse")
+ proto.RegisterType((*MsgUpdateParams)(nil), "ethermint.evm.v1.MsgUpdateParams")
+ proto.RegisterType((*MsgUpdateParamsResponse)(nil), "ethermint.evm.v1.MsgUpdateParamsResponse")
+}
+
+func init() { proto.RegisterFile("ethermint/evm/v1/tx.proto", fileDescriptor_f75ac0a12d075f21) }
+
+var fileDescriptor_f75ac0a12d075f21 = []byte{
+ // 963 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xcf, 0x6f, 0xe3, 0x44,
+ 0x14, 0x8e, 0x13, 0xe7, 0xd7, 0x24, 0x2c, 0x2b, 0xab, 0xd5, 0x3a, 0x01, 0xe2, 0x6c, 0x90, 0x20,
+ 0x8b, 0x54, 0x5b, 0x2d, 0xd2, 0x8a, 0xed, 0x89, 0x66, 0xdb, 0x45, 0x8b, 0x5a, 0xb1, 0x32, 0xd9,
+ 0x0b, 0x20, 0x45, 0x53, 0x7b, 0x3a, 0x19, 0x11, 0x7b, 0x2c, 0xcf, 0xc4, 0x4a, 0x38, 0xee, 0x89,
+ 0x1b, 0x20, 0xfe, 0x01, 0x0e, 0x9c, 0x38, 0x71, 0xd8, 0x33, 0xe7, 0x15, 0xa7, 0x15, 0x5c, 0x10,
+ 0x07, 0x83, 0x52, 0x24, 0xa4, 0x1e, 0x39, 0x73, 0x40, 0x33, 0xe3, 0x34, 0xcd, 0x86, 0xb4, 0xb0,
+ 0x12, 0xdc, 0xe6, 0xf9, 0x7d, 0xef, 0xc7, 0x7c, 0xdf, 0xf8, 0x3d, 0xd0, 0x40, 0x7c, 0x88, 0xe2,
+ 0x80, 0x84, 0xdc, 0x41, 0x49, 0xe0, 0x24, 0xdb, 0x0e, 0x9f, 0xd8, 0x51, 0x4c, 0x39, 0x35, 0xae,
+ 0x9f, 0xbb, 0x6c, 0x94, 0x04, 0x76, 0xb2, 0xdd, 0xbc, 0xe1, 0x51, 0x16, 0x50, 0xe6, 0x04, 0x0c,
+ 0x0b, 0x64, 0xc0, 0xb0, 0x82, 0x36, 0x1b, 0xca, 0x31, 0x90, 0x96, 0xa3, 0x8c, 0xcc, 0xd5, 0x5c,
+ 0x29, 0x20, 0x92, 0x29, 0xdf, 0x06, 0xa6, 0x98, 0xaa, 0x18, 0x71, 0xca, 0xbe, 0xbe, 0x8c, 0x29,
+ 0xc5, 0x23, 0xe4, 0xc0, 0x88, 0x38, 0x30, 0x0c, 0x29, 0x87, 0x9c, 0xd0, 0x70, 0x9e, 0xaf, 0x91,
+ 0x79, 0xa5, 0x75, 0x3c, 0x3e, 0x71, 0x60, 0x38, 0x55, 0xae, 0xce, 0x67, 0x1a, 0x78, 0xe1, 0x88,
+ 0xe1, 0x03, 0x51, 0x10, 0x8d, 0x83, 0xfe, 0xc4, 0xe8, 0x02, 0xdd, 0x87, 0x1c, 0x9a, 0x5a, 0x5b,
+ 0xeb, 0xd6, 0x76, 0x36, 0x6c, 0x15, 0x6b, 0xcf, 0x63, 0xed, 0xbd, 0x70, 0xea, 0x4a, 0x84, 0xd1,
+ 0x00, 0x3a, 0x23, 0x9f, 0x20, 0x33, 0xdf, 0xd6, 0xba, 0x5a, 0xaf, 0x78, 0x96, 0x5a, 0xda, 0x96,
+ 0x2b, 0x3f, 0x19, 0x16, 0xd0, 0x87, 0x90, 0x0d, 0xcd, 0x42, 0x5b, 0xeb, 0x56, 0x7b, 0xb5, 0x3f,
+ 0x52, 0xab, 0x1c, 0x8f, 0xa2, 0xdd, 0xce, 0x56, 0xc7, 0x95, 0x0e, 0xc3, 0x00, 0xfa, 0x49, 0x4c,
+ 0x03, 0x53, 0x17, 0x00, 0x57, 0x9e, 0x77, 0xf5, 0x4f, 0xbf, 0xb2, 0x72, 0x9d, 0x2f, 0xf2, 0xa0,
+ 0x72, 0x88, 0x30, 0xf4, 0xa6, 0xfd, 0x89, 0xb1, 0x01, 0x8a, 0x21, 0x0d, 0x3d, 0x24, 0xbb, 0xd1,
+ 0x5d, 0x65, 0x18, 0xb7, 0x41, 0x15, 0x43, 0xc1, 0x1c, 0xf1, 0x54, 0xf5, 0x6a, 0xaf, 0xf1, 0x73,
+ 0x6a, 0x6d, 0x2a, 0x12, 0x99, 0xff, 0xb1, 0x4d, 0xa8, 0x13, 0x40, 0x3e, 0xb4, 0xef, 0x87, 0xdc,
+ 0xad, 0x60, 0xc8, 0x1e, 0x08, 0xa8, 0xd1, 0x02, 0x05, 0x0c, 0x99, 0x6c, 0x4a, 0xef, 0xd5, 0x67,
+ 0xa9, 0x55, 0x79, 0x07, 0xb2, 0x43, 0x12, 0x10, 0xee, 0x0a, 0x87, 0x71, 0x0d, 0xe4, 0x39, 0xcd,
+ 0x5a, 0xca, 0x73, 0x6a, 0xdc, 0x01, 0xc5, 0x04, 0x8e, 0xc6, 0xc8, 0x2c, 0xca, 0x1a, 0xaf, 0xae,
+ 0xad, 0x31, 0x4b, 0xad, 0xd2, 0x5e, 0x40, 0xc7, 0x21, 0x77, 0x55, 0x84, 0xb8, 0x9f, 0x64, 0xb1,
+ 0xd4, 0xd6, 0xba, 0xf5, 0x8c, 0xaf, 0x3a, 0xd0, 0x12, 0xb3, 0x2c, 0x3f, 0x68, 0x89, 0xb0, 0x62,
+ 0xb3, 0xa2, 0xac, 0x58, 0x58, 0xcc, 0xac, 0x2a, 0x8b, 0xed, 0x5e, 0x13, 0x4c, 0x7c, 0xff, 0x78,
+ 0xab, 0xd4, 0x9f, 0xec, 0x43, 0x0e, 0x3b, 0xdf, 0x15, 0x40, 0x7d, 0xcf, 0xf3, 0x10, 0x63, 0x87,
+ 0x84, 0xf1, 0xfe, 0xc4, 0x78, 0x17, 0x54, 0xbc, 0x21, 0x24, 0xe1, 0x80, 0xf8, 0x92, 0x9a, 0x6a,
+ 0xcf, 0xb9, 0xac, 0xb9, 0xf2, 0x5d, 0x01, 0xbe, 0xbf, 0x7f, 0x96, 0x5a, 0x65, 0x4f, 0x1d, 0xdd,
+ 0xec, 0xe0, 0x2f, 0x38, 0xce, 0xaf, 0xe5, 0xb8, 0xf0, 0xaf, 0x39, 0xd6, 0x2f, 0xe7, 0xb8, 0xb8,
+ 0xca, 0x71, 0xe9, 0xb9, 0x39, 0x2e, 0x5f, 0xe0, 0xf8, 0x43, 0x50, 0x81, 0x92, 0x28, 0xc4, 0xcc,
+ 0x4a, 0xbb, 0xd0, 0xad, 0xed, 0xbc, 0x62, 0x3f, 0xfb, 0x4f, 0xda, 0x8a, 0xca, 0xfe, 0x38, 0x1a,
+ 0xa1, 0x5e, 0xfb, 0x49, 0x6a, 0xe5, 0xce, 0x52, 0x0b, 0xc0, 0x73, 0x7e, 0xbf, 0xf9, 0xc5, 0x02,
+ 0x0b, 0xb6, 0xdd, 0xf3, 0x84, 0x4a, 0xc0, 0xea, 0x92, 0x80, 0x60, 0x49, 0xc0, 0xda, 0x3a, 0x01,
+ 0xff, 0x2c, 0x80, 0xfa, 0xfe, 0x34, 0x84, 0x01, 0xf1, 0xee, 0x21, 0xf4, 0xbf, 0x08, 0x78, 0x07,
+ 0xd4, 0x84, 0x80, 0x9c, 0x44, 0x03, 0x0f, 0x46, 0x57, 0x4b, 0x28, 0xe4, 0xee, 0x93, 0xe8, 0x2e,
+ 0x8c, 0xe6, 0xa1, 0x27, 0x08, 0xc9, 0x50, 0xfd, 0x9f, 0x84, 0xde, 0x43, 0x48, 0x84, 0x66, 0xf2,
+ 0x17, 0x2f, 0x97, 0xbf, 0xb4, 0x2a, 0x7f, 0xf9, 0xb9, 0xe5, 0xaf, 0xac, 0x91, 0xbf, 0xfa, 0x9f,
+ 0xc8, 0x0f, 0x96, 0xe4, 0xaf, 0x2d, 0xc9, 0x5f, 0x5f, 0x27, 0x7f, 0x07, 0x34, 0x0f, 0x26, 0x1c,
+ 0x85, 0x8c, 0xd0, 0xf0, 0xbd, 0x48, 0x8e, 0xe6, 0xc5, 0xc4, 0xcd, 0xe6, 0xde, 0xd7, 0x1a, 0xd8,
+ 0x5c, 0x9a, 0xc4, 0x2e, 0x62, 0x11, 0x0d, 0x99, 0xbc, 0xa8, 0x1c, 0xa6, 0x9a, 0x9a, 0x95, 0x72,
+ 0x7e, 0xde, 0x02, 0xfa, 0x88, 0x62, 0x66, 0xe6, 0xe5, 0x25, 0x37, 0x57, 0x2f, 0x79, 0x48, 0xb1,
+ 0x2b, 0x21, 0xc6, 0x75, 0x50, 0x88, 0x11, 0x97, 0x0f, 0xa0, 0xee, 0x8a, 0xa3, 0xd1, 0x00, 0x95,
+ 0x24, 0x18, 0xa0, 0x38, 0xa6, 0x71, 0x36, 0xed, 0xca, 0x49, 0x70, 0x20, 0x4c, 0xe1, 0x12, 0xd2,
+ 0x8f, 0x19, 0xf2, 0x95, 0x88, 0x6e, 0x19, 0x43, 0xf6, 0x90, 0x21, 0x7f, 0x3e, 0x9e, 0x35, 0xf0,
+ 0xe2, 0x11, 0xc3, 0x0f, 0x23, 0x1f, 0x72, 0xf4, 0x00, 0xc6, 0x30, 0x60, 0x62, 0x56, 0xc0, 0x31,
+ 0x1f, 0xd2, 0x98, 0xf0, 0x69, 0xf6, 0x9a, 0xcd, 0x1f, 0x1e, 0x6f, 0x6d, 0x64, 0x4b, 0x6d, 0xcf,
+ 0xf7, 0x63, 0xc4, 0xd8, 0xfb, 0x3c, 0x26, 0x21, 0x76, 0x17, 0x50, 0xe3, 0x36, 0x28, 0x45, 0x32,
+ 0x83, 0x7c, 0xb9, 0xb5, 0x1d, 0x73, 0xf5, 0x1a, 0xaa, 0x42, 0x4f, 0x17, 0x32, 0xb9, 0x19, 0x7a,
+ 0xf7, 0xda, 0xa3, 0xdf, 0xbf, 0x7d, 0x63, 0x91, 0xa7, 0xd3, 0x00, 0x37, 0x9e, 0x69, 0x69, 0xce,
+ 0xdd, 0x4e, 0xaa, 0x81, 0xc2, 0x11, 0xc3, 0xc6, 0x14, 0x80, 0x0b, 0x3b, 0xce, 0x5a, 0x2d, 0xb4,
+ 0x44, 0x7d, 0xf3, 0xf5, 0x2b, 0x00, 0xf3, 0xfc, 0x9d, 0x9b, 0x8f, 0x7e, 0xfc, 0xed, 0xcb, 0xfc,
+ 0x4b, 0x9d, 0x86, 0x58, 0xd1, 0x94, 0x9d, 0xef, 0xeb, 0x0c, 0x39, 0xe0, 0x13, 0xe3, 0x23, 0x50,
+ 0x5f, 0x62, 0xeb, 0xe6, 0xdf, 0xe6, 0xbe, 0x08, 0x69, 0xde, 0xba, 0x12, 0x32, 0x6f, 0xa0, 0xf7,
+ 0xf6, 0x93, 0x59, 0x4b, 0x7b, 0x3a, 0x6b, 0x69, 0xbf, 0xce, 0x5a, 0xda, 0xe7, 0xa7, 0xad, 0xdc,
+ 0xd3, 0xd3, 0x56, 0xee, 0xa7, 0xd3, 0x56, 0xee, 0x83, 0xd7, 0x30, 0xe1, 0xc3, 0xf1, 0xb1, 0xed,
+ 0xd1, 0x60, 0xd1, 0x1c, 0x65, 0x4e, 0xb2, 0xfd, 0x96, 0x33, 0x91, 0x8d, 0xf2, 0x69, 0x84, 0xd8,
+ 0x71, 0x49, 0xae, 0xf6, 0x37, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0xee, 0x9c, 0xdd, 0x06, 0xd7,
+ 0x08, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// MsgClient is the client API for Msg service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type MsgClient interface {
+ // EthereumTx defines a method submitting Ethereum transactions.
+ EthereumTx(ctx context.Context, in *MsgEthereumTx, opts ...grpc.CallOption) (*MsgEthereumTxResponse, error)
+ // UpdateParams defined a governance operation for updating the x/evm module parameters.
+ // The authority is hard-coded to the Cosmos SDK x/gov module account
+ UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error)
+}
+
+type msgClient struct {
+ cc grpc1.ClientConn
+}
+
+func NewMsgClient(cc grpc1.ClientConn) MsgClient {
+ return &msgClient{cc}
+}
+
+func (c *msgClient) EthereumTx(ctx context.Context, in *MsgEthereumTx, opts ...grpc.CallOption) (*MsgEthereumTxResponse, error) {
+ out := new(MsgEthereumTxResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Msg/EthereumTx", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) {
+ out := new(MsgUpdateParamsResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.evm.v1.Msg/UpdateParams", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// MsgServer is the server API for Msg service.
+type MsgServer interface {
+ // EthereumTx defines a method submitting Ethereum transactions.
+ EthereumTx(context.Context, *MsgEthereumTx) (*MsgEthereumTxResponse, error)
+ // UpdateParams defined a governance operation for updating the x/evm module parameters.
+ // The authority is hard-coded to the Cosmos SDK x/gov module account
+ UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error)
+}
+
+// UnimplementedMsgServer can be embedded to have forward compatible implementations.
+type UnimplementedMsgServer struct {
+}
+
+func (*UnimplementedMsgServer) EthereumTx(ctx context.Context, req *MsgEthereumTx) (*MsgEthereumTxResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method EthereumTx not implemented")
+}
+func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented")
+}
+
+func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
+ s.RegisterService(&_Msg_serviceDesc, srv)
+}
+
+func _Msg_EthereumTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MsgEthereumTx)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MsgServer).EthereumTx(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Msg/EthereumTx",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MsgServer).EthereumTx(ctx, req.(*MsgEthereumTx))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MsgUpdateParams)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MsgServer).UpdateParams(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.evm.v1.Msg/UpdateParams",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Msg_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "ethermint.evm.v1.Msg",
+ HandlerType: (*MsgServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "EthereumTx",
+ Handler: _Msg_EthereumTx_Handler,
+ },
+ {
+ MethodName: "UpdateParams",
+ Handler: _Msg_UpdateParams_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "ethermint/evm/v1/tx.proto",
+}
+
+func (m *MsgEthereumTx) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MsgEthereumTx) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgEthereumTx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.From) > 0 {
+ i -= len(m.From)
+ copy(dAtA[i:], m.From)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.From)))
+ i--
+ dAtA[i] = 0x22
+ }
+ if len(m.Hash) > 0 {
+ i -= len(m.Hash)
+ copy(dAtA[i:], m.Hash)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Hash)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Size_ != 0 {
+ i -= 8
+ encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Size_))))
+ i--
+ dAtA[i] = 0x11
+ }
+ if m.Data != nil {
+ {
+ size, err := m.Data.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *LegacyTx) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LegacyTx) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LegacyTx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.S) > 0 {
+ i -= len(m.S)
+ copy(dAtA[i:], m.S)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.S)))
+ i--
+ dAtA[i] = 0x4a
+ }
+ if len(m.R) > 0 {
+ i -= len(m.R)
+ copy(dAtA[i:], m.R)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.R)))
+ i--
+ dAtA[i] = 0x42
+ }
+ if len(m.V) > 0 {
+ i -= len(m.V)
+ copy(dAtA[i:], m.V)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.V)))
+ i--
+ dAtA[i] = 0x3a
+ }
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x32
+ }
+ if m.Amount != nil {
+ {
+ size := m.Amount.Size()
+ i -= size
+ if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x2a
+ }
+ if len(m.To) > 0 {
+ i -= len(m.To)
+ copy(dAtA[i:], m.To)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.To)))
+ i--
+ dAtA[i] = 0x22
+ }
+ if m.GasLimit != 0 {
+ i = encodeVarintTx(dAtA, i, uint64(m.GasLimit))
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.GasPrice != nil {
+ {
+ size := m.GasPrice.Size()
+ i -= size
+ if _, err := m.GasPrice.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.Nonce != 0 {
+ i = encodeVarintTx(dAtA, i, uint64(m.Nonce))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *AccessListTx) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AccessListTx) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *AccessListTx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.S) > 0 {
+ i -= len(m.S)
+ copy(dAtA[i:], m.S)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.S)))
+ i--
+ dAtA[i] = 0x5a
+ }
+ if len(m.R) > 0 {
+ i -= len(m.R)
+ copy(dAtA[i:], m.R)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.R)))
+ i--
+ dAtA[i] = 0x52
+ }
+ if len(m.V) > 0 {
+ i -= len(m.V)
+ copy(dAtA[i:], m.V)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.V)))
+ i--
+ dAtA[i] = 0x4a
+ }
+ if len(m.Accesses) > 0 {
+ for iNdEx := len(m.Accesses) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Accesses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x42
+ }
+ }
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x3a
+ }
+ if m.Amount != nil {
+ {
+ size := m.Amount.Size()
+ i -= size
+ if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x32
+ }
+ if len(m.To) > 0 {
+ i -= len(m.To)
+ copy(dAtA[i:], m.To)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.To)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if m.GasLimit != 0 {
+ i = encodeVarintTx(dAtA, i, uint64(m.GasLimit))
+ i--
+ dAtA[i] = 0x20
+ }
+ if m.GasPrice != nil {
+ {
+ size := m.GasPrice.Size()
+ i -= size
+ if _, err := m.GasPrice.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Nonce != 0 {
+ i = encodeVarintTx(dAtA, i, uint64(m.Nonce))
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.ChainID != nil {
+ {
+ size := m.ChainID.Size()
+ i -= size
+ if _, err := m.ChainID.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *DynamicFeeTx) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *DynamicFeeTx) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DynamicFeeTx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.S) > 0 {
+ i -= len(m.S)
+ copy(dAtA[i:], m.S)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.S)))
+ i--
+ dAtA[i] = 0x62
+ }
+ if len(m.R) > 0 {
+ i -= len(m.R)
+ copy(dAtA[i:], m.R)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.R)))
+ i--
+ dAtA[i] = 0x5a
+ }
+ if len(m.V) > 0 {
+ i -= len(m.V)
+ copy(dAtA[i:], m.V)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.V)))
+ i--
+ dAtA[i] = 0x52
+ }
+ if len(m.Accesses) > 0 {
+ for iNdEx := len(m.Accesses) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Accesses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x4a
+ }
+ }
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x42
+ }
+ if m.Amount != nil {
+ {
+ size := m.Amount.Size()
+ i -= size
+ if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x3a
+ }
+ if len(m.To) > 0 {
+ i -= len(m.To)
+ copy(dAtA[i:], m.To)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.To)))
+ i--
+ dAtA[i] = 0x32
+ }
+ if m.GasLimit != 0 {
+ i = encodeVarintTx(dAtA, i, uint64(m.GasLimit))
+ i--
+ dAtA[i] = 0x28
+ }
+ if m.GasFeeCap != nil {
+ {
+ size := m.GasFeeCap.Size()
+ i -= size
+ if _, err := m.GasFeeCap.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x22
+ }
+ if m.GasTipCap != nil {
+ {
+ size := m.GasTipCap.Size()
+ i -= size
+ if _, err := m.GasTipCap.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Nonce != 0 {
+ i = encodeVarintTx(dAtA, i, uint64(m.Nonce))
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.ChainID != nil {
+ {
+ size := m.ChainID.Size()
+ i -= size
+ if _, err := m.ChainID.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ExtensionOptionsEthereumTx) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ExtensionOptionsEthereumTx) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExtensionOptionsEthereumTx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgEthereumTxResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MsgEthereumTxResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgEthereumTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.GasUsed != 0 {
+ i = encodeVarintTx(dAtA, i, uint64(m.GasUsed))
+ i--
+ dAtA[i] = 0x28
+ }
+ if len(m.VmError) > 0 {
+ i -= len(m.VmError)
+ copy(dAtA[i:], m.VmError)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.VmError)))
+ i--
+ dAtA[i] = 0x22
+ }
+ if len(m.Ret) > 0 {
+ i -= len(m.Ret)
+ copy(dAtA[i:], m.Ret)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Ret)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Logs) > 0 {
+ for iNdEx := len(m.Logs) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Logs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ if len(m.Hash) > 0 {
+ i -= len(m.Hash)
+ copy(dAtA[i:], m.Hash)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Hash)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ if len(m.Authority) > 0 {
+ i -= len(m.Authority)
+ copy(dAtA[i:], m.Authority)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Authority)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintTx(dAtA []byte, offset int, v uint64) int {
+ offset -= sovTx(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *MsgEthereumTx) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Data != nil {
+ l = m.Data.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.Size_ != 0 {
+ n += 9
+ }
+ l = len(m.Hash)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.From)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *LegacyTx) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Nonce != 0 {
+ n += 1 + sovTx(uint64(m.Nonce))
+ }
+ if m.GasPrice != nil {
+ l = m.GasPrice.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.GasLimit != 0 {
+ n += 1 + sovTx(uint64(m.GasLimit))
+ }
+ l = len(m.To)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.Amount != nil {
+ l = m.Amount.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.V)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.R)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.S)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *AccessListTx) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.ChainID != nil {
+ l = m.ChainID.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.Nonce != 0 {
+ n += 1 + sovTx(uint64(m.Nonce))
+ }
+ if m.GasPrice != nil {
+ l = m.GasPrice.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.GasLimit != 0 {
+ n += 1 + sovTx(uint64(m.GasLimit))
+ }
+ l = len(m.To)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.Amount != nil {
+ l = m.Amount.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if len(m.Accesses) > 0 {
+ for _, e := range m.Accesses {
+ l = e.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ }
+ l = len(m.V)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.R)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.S)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *DynamicFeeTx) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.ChainID != nil {
+ l = m.ChainID.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.Nonce != 0 {
+ n += 1 + sovTx(uint64(m.Nonce))
+ }
+ if m.GasTipCap != nil {
+ l = m.GasTipCap.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.GasFeeCap != nil {
+ l = m.GasFeeCap.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.GasLimit != 0 {
+ n += 1 + sovTx(uint64(m.GasLimit))
+ }
+ l = len(m.To)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.Amount != nil {
+ l = m.Amount.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if len(m.Accesses) > 0 {
+ for _, e := range m.Accesses {
+ l = e.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ }
+ l = len(m.V)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.R)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.S)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *ExtensionOptionsEthereumTx) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *MsgEthereumTxResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Hash)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if len(m.Logs) > 0 {
+ for _, e := range m.Logs {
+ l = e.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ }
+ l = len(m.Ret)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.VmError)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.GasUsed != 0 {
+ n += 1 + sovTx(uint64(m.GasUsed))
+ }
+ return n
+}
+
+func (m *MsgUpdateParams) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Authority)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = m.Params.Size()
+ n += 1 + l + sovTx(uint64(l))
+ return n
+}
+
+func (m *MsgUpdateParamsResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func sovTx(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTx(x uint64) (n int) {
+ return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *MsgEthereumTx) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MsgEthereumTx: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgEthereumTx: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Data == nil {
+ m.Data = &types.Any{}
+ }
+ if err := m.Data.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 1 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Size_", wireType)
+ }
+ var v uint64
+ if (iNdEx + 8) > l {
+ return io.ErrUnexpectedEOF
+ }
+ v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:]))
+ iNdEx += 8
+ m.Size_ = float64(math.Float64frombits(v))
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field From", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.From = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LegacyTx) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LegacyTx: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LegacyTx: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType)
+ }
+ m.Nonce = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Nonce |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasPrice", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.GasPrice = &v
+ if err := m.GasPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasLimit", wireType)
+ }
+ m.GasLimit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GasLimit |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.To = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.Amount = &v
+ if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field V", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.V = append(m.V[:0], dAtA[iNdEx:postIndex]...)
+ if m.V == nil {
+ m.V = []byte{}
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field R", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.R = append(m.R[:0], dAtA[iNdEx:postIndex]...)
+ if m.R == nil {
+ m.R = []byte{}
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field S", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.S = append(m.S[:0], dAtA[iNdEx:postIndex]...)
+ if m.S == nil {
+ m.S = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AccessListTx) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AccessListTx: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AccessListTx: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ChainID = &v
+ if err := m.ChainID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType)
+ }
+ m.Nonce = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Nonce |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasPrice", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.GasPrice = &v
+ if err := m.GasPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasLimit", wireType)
+ }
+ m.GasLimit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GasLimit |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.To = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.Amount = &v
+ if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Accesses", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Accesses = append(m.Accesses, AccessTuple{})
+ if err := m.Accesses[len(m.Accesses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field V", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.V = append(m.V[:0], dAtA[iNdEx:postIndex]...)
+ if m.V == nil {
+ m.V = []byte{}
+ }
+ iNdEx = postIndex
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field R", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.R = append(m.R[:0], dAtA[iNdEx:postIndex]...)
+ if m.R == nil {
+ m.R = []byte{}
+ }
+ iNdEx = postIndex
+ case 11:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field S", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.S = append(m.S[:0], dAtA[iNdEx:postIndex]...)
+ if m.S == nil {
+ m.S = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *DynamicFeeTx) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: DynamicFeeTx: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: DynamicFeeTx: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.ChainID = &v
+ if err := m.ChainID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType)
+ }
+ m.Nonce = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Nonce |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasTipCap", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.GasTipCap = &v
+ if err := m.GasTipCap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasFeeCap", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.GasFeeCap = &v
+ if err := m.GasFeeCap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasLimit", wireType)
+ }
+ m.GasLimit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GasLimit |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.To = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.Amount = &v
+ if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Accesses", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Accesses = append(m.Accesses, AccessTuple{})
+ if err := m.Accesses[len(m.Accesses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field V", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.V = append(m.V[:0], dAtA[iNdEx:postIndex]...)
+ if m.V == nil {
+ m.V = []byte{}
+ }
+ iNdEx = postIndex
+ case 11:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field R", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.R = append(m.R[:0], dAtA[iNdEx:postIndex]...)
+ if m.R == nil {
+ m.R = []byte{}
+ }
+ iNdEx = postIndex
+ case 12:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field S", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.S = append(m.S[:0], dAtA[iNdEx:postIndex]...)
+ if m.S == nil {
+ m.S = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ExtensionOptionsEthereumTx) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ExtensionOptionsEthereumTx: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ExtensionOptionsEthereumTx: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgEthereumTxResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MsgEthereumTxResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgEthereumTxResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Hash = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Logs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Logs = append(m.Logs, &Log{})
+ if err := m.Logs[len(m.Logs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Ret", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Ret = append(m.Ret[:0], dAtA[iNdEx:postIndex]...)
+ if m.Ret == nil {
+ m.Ret = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field VmError", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.VmError = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType)
+ }
+ m.GasUsed = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GasUsed |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Authority = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipTx(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthTx
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupTx
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthTx
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowTx = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/evm/types/tx.pb.gw.go b/x/evm/types/tx.pb.gw.go
new file mode 100644
index 00000000..08f74667
--- /dev/null
+++ b/x/evm/types/tx.pb.gw.go
@@ -0,0 +1,171 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: ethermint/evm/v1/tx.proto
+
+/*
+Package types is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package types
+
+import (
+ "context"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/grpc-ecosystem/grpc-gateway/utilities"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+// Suppress "imported and not used" errors
+var _ codes.Code
+var _ io.Reader
+var _ status.Status
+var _ = runtime.String
+var _ = utilities.NewDoubleArray
+var _ = descriptor.ForMessage
+var _ = metadata.Join
+
+var (
+ filter_Msg_EthereumTx_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_Msg_EthereumTx_0(ctx context.Context, marshaler runtime.Marshaler, client MsgClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq MsgEthereumTx
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_EthereumTx_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.EthereumTx(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Msg_EthereumTx_0(ctx context.Context, marshaler runtime.Marshaler, server MsgServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq MsgEthereumTx
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_EthereumTx_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.EthereumTx(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+// RegisterMsgHandlerServer registers the http handlers for service Msg to "mux".
+// UnaryRPC :call MsgServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterMsgHandlerFromEndpoint instead.
+func RegisterMsgHandlerServer(ctx context.Context, mux *runtime.ServeMux, server MsgServer) error {
+
+ mux.Handle("POST", pattern_Msg_EthereumTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Msg_EthereumTx_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Msg_EthereumTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// RegisterMsgHandlerFromEndpoint is same as RegisterMsgHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterMsgHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterMsgHandler(ctx, mux, conn)
+}
+
+// RegisterMsgHandler registers the http handlers for service Msg to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterMsgHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterMsgHandlerClient(ctx, mux, NewMsgClient(conn))
+}
+
+// RegisterMsgHandlerClient registers the http handlers for service Msg
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "MsgClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "MsgClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "MsgClient" to call the correct interceptors.
+func RegisterMsgHandlerClient(ctx context.Context, mux *runtime.ServeMux, client MsgClient) error {
+
+ mux.Handle("POST", pattern_Msg_EthereumTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Msg_EthereumTx_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Msg_EthereumTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Msg_EthereumTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "evm", "v1", "ethereum_tx"}, "", runtime.AssumeColonVerbOpt(false)))
+)
+
+var (
+ forward_Msg_EthereumTx_0 = runtime.ForwardResponseMessage
+)
diff --git a/x/evm/types/tx_args.go b/x/evm/types/tx_args.go
new file mode 100644
index 00000000..11f66e68
--- /dev/null
+++ b/x/evm/types/tx_args.go
@@ -0,0 +1,250 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+
+ sdkmath "cosmossdk.io/math"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/common/math"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+)
+
+// TransactionArgs represents the arguments to construct a new transaction
+// or a message call using JSON-RPC.
+// Duplicate struct definition since geth struct is in internal package
+// Ref: https://github.com/ethereum/go-ethereum/blob/release/1.10.4/internal/ethapi/transaction_args.go#L36
+type TransactionArgs struct {
+ From *common.Address `json:"from"`
+ To *common.Address `json:"to"`
+ Gas *hexutil.Uint64 `json:"gas"`
+ GasPrice *hexutil.Big `json:"gasPrice"`
+ MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
+ MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
+ Value *hexutil.Big `json:"value"`
+ Nonce *hexutil.Uint64 `json:"nonce"`
+
+ // We accept "data" and "input" for backwards-compatibility reasons.
+ // "input" is the newer name and should be preferred by clients.
+ // Issue detail: https://github.com/ethereum/go-ethereum/issues/15628
+ Data *hexutil.Bytes `json:"data"`
+ Input *hexutil.Bytes `json:"input"`
+
+ // Introduced by AccessListTxType transaction.
+ AccessList *ethtypes.AccessList `json:"accessList,omitempty"`
+ ChainID *hexutil.Big `json:"chainId,omitempty"`
+}
+
+// String return the struct in a string format
+func (args *TransactionArgs) String() string {
+ // Todo: There is currently a bug with hexutil.Big when the value its nil, printing would trigger an exception
+ return fmt.Sprintf("TransactionArgs{From:%v, To:%v, Gas:%v,"+
+ " Nonce:%v, Data:%v, Input:%v, AccessList:%v}",
+ args.From,
+ args.To,
+ args.Gas,
+ args.Nonce,
+ args.Data,
+ args.Input,
+ args.AccessList)
+}
+
+// ToTransaction converts the arguments to an ethereum transaction.
+// This assumes that setTxDefaults has been called.
+func (args *TransactionArgs) ToTransaction() *MsgEthereumTx {
+ var (
+ chainID, value, gasPrice, maxFeePerGas, maxPriorityFeePerGas sdkmath.Int
+ gas, nonce uint64
+ from, to string
+ )
+
+ // Set sender address or use zero address if none specified.
+ if args.ChainID != nil {
+ chainID = sdkmath.NewIntFromBigInt(args.ChainID.ToInt())
+ }
+
+ if args.Nonce != nil {
+ nonce = uint64(*args.Nonce)
+ }
+
+ if args.Gas != nil {
+ gas = uint64(*args.Gas)
+ }
+
+ if args.GasPrice != nil {
+ gasPrice = sdkmath.NewIntFromBigInt(args.GasPrice.ToInt())
+ }
+
+ if args.MaxFeePerGas != nil {
+ maxFeePerGas = sdkmath.NewIntFromBigInt(args.MaxFeePerGas.ToInt())
+ }
+
+ if args.MaxPriorityFeePerGas != nil {
+ maxPriorityFeePerGas = sdkmath.NewIntFromBigInt(args.MaxPriorityFeePerGas.ToInt())
+ }
+
+ if args.Value != nil {
+ value = sdkmath.NewIntFromBigInt(args.Value.ToInt())
+ }
+
+ if args.To != nil {
+ to = args.To.Hex()
+ }
+
+ var data TxData
+ switch {
+ case args.MaxFeePerGas != nil:
+ al := AccessList{}
+ if args.AccessList != nil {
+ al = NewAccessList(args.AccessList)
+ }
+
+ data = &DynamicFeeTx{
+ To: to,
+ ChainID: &chainID,
+ Nonce: nonce,
+ GasLimit: gas,
+ GasFeeCap: &maxFeePerGas,
+ GasTipCap: &maxPriorityFeePerGas,
+ Amount: &value,
+ Data: args.GetData(),
+ Accesses: al,
+ }
+ case args.AccessList != nil:
+ data = &AccessListTx{
+ To: to,
+ ChainID: &chainID,
+ Nonce: nonce,
+ GasLimit: gas,
+ GasPrice: &gasPrice,
+ Amount: &value,
+ Data: args.GetData(),
+ Accesses: NewAccessList(args.AccessList),
+ }
+ default:
+ data = &LegacyTx{
+ To: to,
+ Nonce: nonce,
+ GasLimit: gas,
+ GasPrice: &gasPrice,
+ Amount: &value,
+ Data: args.GetData(),
+ }
+ }
+
+ anyData, err := PackTxData(data)
+ if err != nil {
+ return nil
+ }
+
+ if args.From != nil {
+ from = args.From.Hex()
+ }
+
+ msg := MsgEthereumTx{
+ Data: anyData,
+ From: from,
+ }
+ msg.Hash = msg.AsTransaction().Hash().Hex()
+ return &msg
+}
+
+// ToMessage converts the arguments to the Message type used by the core evm.
+// This assumes that setTxDefaults has been called.
+func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (ethtypes.Message, error) {
+ // Reject invalid combinations of pre- and post-1559 fee styles
+ if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
+ return ethtypes.Message{}, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
+ }
+
+ // Set sender address or use zero address if none specified.
+ addr := args.GetFrom()
+
+ // Set default gas & gas price if none were set
+ gas := globalGasCap
+ if gas == 0 {
+ gas = uint64(math.MaxUint64 / 2)
+ }
+ if args.Gas != nil {
+ gas = uint64(*args.Gas)
+ }
+ if globalGasCap != 0 && globalGasCap < gas {
+ gas = globalGasCap
+ }
+ var (
+ gasPrice *big.Int
+ gasFeeCap *big.Int
+ gasTipCap *big.Int
+ )
+ if baseFee == nil {
+ // If there's no basefee, then it must be a non-1559 execution
+ gasPrice = new(big.Int)
+ if args.GasPrice != nil {
+ gasPrice = args.GasPrice.ToInt()
+ }
+ gasFeeCap, gasTipCap = gasPrice, gasPrice
+ } else {
+ // A basefee is provided, necessitating 1559-type execution
+ if args.GasPrice != nil {
+ // User specified the legacy gas field, convert to 1559 gas typing
+ gasPrice = args.GasPrice.ToInt()
+ gasFeeCap, gasTipCap = gasPrice, gasPrice
+ } else {
+ // User specified 1559 gas feilds (or none), use those
+ gasFeeCap = new(big.Int)
+ if args.MaxFeePerGas != nil {
+ gasFeeCap = args.MaxFeePerGas.ToInt()
+ }
+ gasTipCap = new(big.Int)
+ if args.MaxPriorityFeePerGas != nil {
+ gasTipCap = args.MaxPriorityFeePerGas.ToInt()
+ }
+ // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
+ gasPrice = new(big.Int)
+ if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 {
+ gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
+ }
+ }
+ }
+ value := new(big.Int)
+ if args.Value != nil {
+ value = args.Value.ToInt()
+ }
+ data := args.GetData()
+ var accessList ethtypes.AccessList
+ if args.AccessList != nil {
+ accessList = *args.AccessList
+ }
+
+ nonce := uint64(0)
+ if args.Nonce != nil {
+ nonce = uint64(*args.Nonce)
+ }
+
+ msg := ethtypes.NewMessage(addr, args.To, nonce, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true)
+ return msg, nil
+}
+
+// GetFrom retrieves the transaction sender address.
+func (args *TransactionArgs) GetFrom() common.Address {
+ if args.From == nil {
+ return common.Address{}
+ }
+ return *args.From
+}
+
+// GetData retrieves the transaction calldata. Input field is preferred.
+func (args *TransactionArgs) GetData() []byte {
+ if args.Input != nil {
+ return *args.Input
+ }
+ if args.Data != nil {
+ return *args.Data
+ }
+ return nil
+}
diff --git a/x/evm/types/tx_args_test.go b/x/evm/types/tx_args_test.go
new file mode 100644
index 00000000..1a07d7f2
--- /dev/null
+++ b/x/evm/types/tx_args_test.go
@@ -0,0 +1,289 @@
+package types_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+
+ "github.com/evmos/evmos/v19/x/evm/types"
+)
+
+func (suite *TxDataTestSuite) TestTxArgsString() {
+ testCases := []struct {
+ name string
+ txArgs types.TransactionArgs
+ expectedString string
+ }{
+ {
+ "empty tx args",
+ types.TransactionArgs{},
+ "TransactionArgs{From:, To:, Gas:, Nonce:, Data:, Input:, AccessList:}",
+ },
+ {
+ "tx args with fields",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ Nonce: &suite.hexUint64,
+ Input: &suite.hexInputBytes,
+ Data: &suite.hexDataBytes,
+ AccessList: ðtypes.AccessList{},
+ },
+ fmt.Sprintf("TransactionArgs{From:%v, To:%v, Gas:%v, Nonce:%v, Data:%v, Input:%v, AccessList:%v}",
+ &suite.addr,
+ &suite.addr,
+ &suite.hexUint64,
+ &suite.hexUint64,
+ &suite.hexDataBytes,
+ &suite.hexInputBytes,
+ ðtypes.AccessList{}),
+ },
+ }
+ for _, tc := range testCases {
+ outputString := tc.txArgs.String()
+ suite.Require().Equal(outputString, tc.expectedString)
+ }
+}
+
+func (suite *TxDataTestSuite) TestConvertTxArgsEthTx() {
+ testCases := []struct {
+ name string
+ txArgs types.TransactionArgs
+ }{
+ {
+ "empty tx args",
+ types.TransactionArgs{},
+ },
+ {
+ "no nil args",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ GasPrice: &suite.hexBigInt,
+ MaxFeePerGas: &suite.hexBigInt,
+ MaxPriorityFeePerGas: &suite.hexBigInt,
+ Value: &suite.hexBigInt,
+ Nonce: &suite.hexUint64,
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ AccessList: ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ ChainID: &suite.hexBigInt,
+ },
+ },
+ {
+ "max fee per gas nil, but access list not nil",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ GasPrice: &suite.hexBigInt,
+ MaxFeePerGas: nil,
+ MaxPriorityFeePerGas: &suite.hexBigInt,
+ Value: &suite.hexBigInt,
+ Nonce: &suite.hexUint64,
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ AccessList: ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ ChainID: &suite.hexBigInt,
+ },
+ },
+ }
+ for _, tc := range testCases {
+ res := tc.txArgs.ToTransaction()
+ suite.Require().NotNil(res)
+ }
+}
+
+func (suite *TxDataTestSuite) TestToMessageEVM() {
+ testCases := []struct {
+ name string
+ txArgs types.TransactionArgs
+ globalGasCap uint64
+ baseFee *big.Int
+ expError bool
+ }{
+ {
+ "empty tx args",
+ types.TransactionArgs{},
+ uint64(0),
+ nil,
+ false,
+ },
+ {
+ "specify gasPrice and (maxFeePerGas or maxPriorityFeePerGas)",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ GasPrice: &suite.hexBigInt,
+ MaxFeePerGas: &suite.hexBigInt,
+ MaxPriorityFeePerGas: &suite.hexBigInt,
+ Value: &suite.hexBigInt,
+ Nonce: &suite.hexUint64,
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ AccessList: ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ ChainID: &suite.hexBigInt,
+ },
+ uint64(0),
+ nil,
+ true,
+ },
+ {
+ "non-1559 execution, zero gas cap",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ GasPrice: &suite.hexBigInt,
+ MaxFeePerGas: nil,
+ MaxPriorityFeePerGas: nil,
+ Value: &suite.hexBigInt,
+ Nonce: &suite.hexUint64,
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ AccessList: ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ ChainID: &suite.hexBigInt,
+ },
+ uint64(0),
+ nil,
+ false,
+ },
+ {
+ "non-1559 execution, nonzero gas cap",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ GasPrice: &suite.hexBigInt,
+ MaxFeePerGas: nil,
+ MaxPriorityFeePerGas: nil,
+ Value: &suite.hexBigInt,
+ Nonce: &suite.hexUint64,
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ AccessList: ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ ChainID: &suite.hexBigInt,
+ },
+ uint64(1),
+ nil,
+ false,
+ },
+ {
+ "1559-type execution, nil gas price",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ GasPrice: nil,
+ MaxFeePerGas: &suite.hexBigInt,
+ MaxPriorityFeePerGas: &suite.hexBigInt,
+ Value: &suite.hexBigInt,
+ Nonce: &suite.hexUint64,
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ AccessList: ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ ChainID: &suite.hexBigInt,
+ },
+ uint64(1),
+ suite.bigInt,
+ false,
+ },
+ {
+ "1559-type execution, non-nil gas price",
+ types.TransactionArgs{
+ From: &suite.addr,
+ To: &suite.addr,
+ Gas: &suite.hexUint64,
+ GasPrice: &suite.hexBigInt,
+ MaxFeePerGas: nil,
+ MaxPriorityFeePerGas: nil,
+ Value: &suite.hexBigInt,
+ Nonce: &suite.hexUint64,
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ AccessList: ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
+ ChainID: &suite.hexBigInt,
+ },
+ uint64(1),
+ suite.bigInt,
+ false,
+ },
+ }
+ for _, tc := range testCases {
+ res, err := tc.txArgs.ToMessage(tc.globalGasCap, tc.baseFee)
+
+ if tc.expError {
+ suite.Require().NotNil(err)
+ } else {
+ suite.Require().Nil(err)
+ suite.Require().NotNil(res)
+ }
+ }
+}
+
+func (suite *TxDataTestSuite) TestGetFrom() {
+ testCases := []struct {
+ name string
+ txArgs types.TransactionArgs
+ expAddress common.Address
+ }{
+ {
+ "empty from field",
+ types.TransactionArgs{},
+ common.Address{},
+ },
+ {
+ "non-empty from field",
+ types.TransactionArgs{
+ From: &suite.addr,
+ },
+ suite.addr,
+ },
+ }
+ for _, tc := range testCases {
+ retrievedAddress := tc.txArgs.GetFrom()
+ suite.Require().Equal(retrievedAddress, tc.expAddress)
+ }
+}
+
+func (suite *TxDataTestSuite) TestGetData() {
+ testCases := []struct {
+ name string
+ txArgs types.TransactionArgs
+ expectedOutput []byte
+ }{
+ {
+ "empty input and data fields",
+ types.TransactionArgs{
+ Data: nil,
+ Input: nil,
+ },
+ nil,
+ },
+ {
+ "empty input field, non-empty data field",
+ types.TransactionArgs{
+ Data: &suite.hexDataBytes,
+ Input: nil,
+ },
+ []byte("data"),
+ },
+ {
+ "non-empty input and data fields",
+ types.TransactionArgs{
+ Data: &suite.hexDataBytes,
+ Input: &suite.hexInputBytes,
+ },
+ []byte("input"),
+ },
+ }
+ for _, tc := range testCases {
+ retrievedData := tc.txArgs.GetData()
+ suite.Require().Equal(retrievedData, tc.expectedOutput)
+ }
+}
diff --git a/x/evm/types/tx_data.go b/x/evm/types/tx_data.go
new file mode 100644
index 00000000..2f3ae6f2
--- /dev/null
+++ b/x/evm/types/tx_data.go
@@ -0,0 +1,125 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+)
+
+var (
+ _ TxData = &LegacyTx{}
+ _ TxData = &AccessListTx{}
+ _ TxData = &DynamicFeeTx{}
+)
+
+// TxData implements the Ethereum transaction tx structure. It is used
+// solely as intended in Ethereum abiding by the protocol.
+type TxData interface {
+ // TODO: embed ethtypes.TxData. See https://github.com/ethereum/go-ethereum/issues/23154
+
+ TxType() byte
+ Copy() TxData
+ GetChainID() *big.Int
+ GetAccessList() ethtypes.AccessList
+ GetData() []byte
+ GetNonce() uint64
+ GetGas() uint64
+ GetGasPrice() *big.Int
+ GetGasTipCap() *big.Int
+ GetGasFeeCap() *big.Int
+ GetValue() *big.Int
+ GetTo() *common.Address
+
+ GetRawSignatureValues() (v, r, s *big.Int)
+ SetSignatureValues(chainID, v, r, s *big.Int)
+
+ AsEthereumData() ethtypes.TxData
+ Validate() error
+
+ // static fee
+ Fee() *big.Int
+ Cost() *big.Int
+
+ // effective gasPrice/fee/cost according to current base fee
+ EffectiveGasPrice(baseFee *big.Int) *big.Int
+ EffectiveFee(baseFee *big.Int) *big.Int
+ EffectiveCost(baseFee *big.Int) *big.Int
+}
+
+// NOTE: All non-protected transactions (i.e non EIP155 signed) will fail if the
+// AllowUnprotectedTxs parameter is disabled.
+func NewTxDataFromTx(tx *ethtypes.Transaction) (TxData, error) {
+ var txData TxData
+ var err error
+ switch tx.Type() {
+ case ethtypes.DynamicFeeTxType:
+ txData, err = NewDynamicFeeTx(tx)
+ case ethtypes.AccessListTxType:
+ txData, err = newAccessListTx(tx)
+ default:
+ txData, err = NewLegacyTx(tx)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ return txData, nil
+}
+
+// DeriveChainID derives the chain id from the given v parameter.
+//
+// CONTRACT: v value is either:
+//
+// - {0,1} + CHAIN_ID * 2 + 35, if EIP155 is used
+// - {0,1} + 27, otherwise
+//
+// Ref: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
+func DeriveChainID(v *big.Int) *big.Int {
+ if v == nil || v.Sign() < 1 {
+ return nil
+ }
+
+ if v.BitLen() <= 64 {
+ v := v.Uint64()
+ if v == 27 || v == 28 {
+ return new(big.Int)
+ }
+
+ if v < 35 {
+ return nil
+ }
+
+ // V MUST be of the form {0,1} + CHAIN_ID * 2 + 35
+ return new(big.Int).SetUint64((v - 35) / 2)
+ }
+ v = new(big.Int).Sub(v, big.NewInt(35))
+ return v.Div(v, big.NewInt(2))
+}
+
+func rawSignatureValues(vBz, rBz, sBz []byte) (v, r, s *big.Int) {
+ if len(vBz) > 0 {
+ v = new(big.Int).SetBytes(vBz)
+ }
+ if len(rBz) > 0 {
+ r = new(big.Int).SetBytes(rBz)
+ }
+ if len(sBz) > 0 {
+ s = new(big.Int).SetBytes(sBz)
+ }
+ return v, r, s
+}
+
+func fee(gasPrice *big.Int, gas uint64) *big.Int {
+ gasLimit := new(big.Int).SetUint64(gas)
+ return new(big.Int).Mul(gasPrice, gasLimit)
+}
+
+func cost(fee, value *big.Int) *big.Int {
+ if value != nil {
+ return new(big.Int).Add(fee, value)
+ }
+ return fee
+}
diff --git a/x/evm/types/tx_data_test.go b/x/evm/types/tx_data_test.go
new file mode 100644
index 00000000..7d2db408
--- /dev/null
+++ b/x/evm/types/tx_data_test.go
@@ -0,0 +1,89 @@
+package types
+
+import (
+ "math/big"
+ "testing"
+
+ sdkmath "cosmossdk.io/math"
+ "github.com/stretchr/testify/require"
+)
+
+func TestTxData_chainID(t *testing.T) {
+ chainID := sdkmath.NewInt(1)
+
+ testCases := []struct {
+ msg string
+ data TxData
+ expChainID *big.Int
+ }{
+ {
+ "access list tx", &AccessListTx{Accesses: AccessList{}, ChainID: &chainID}, big.NewInt(1),
+ },
+ {
+ "access list tx, nil chain ID", &AccessListTx{Accesses: AccessList{}}, nil,
+ },
+ {
+ "legacy tx, derived", &LegacyTx{}, nil,
+ },
+ }
+
+ for _, tc := range testCases {
+ chainID := tc.data.GetChainID()
+ require.Equal(t, chainID, tc.expChainID, tc.msg)
+ }
+}
+
+func TestTxData_DeriveChainID(t *testing.T) {
+ bitLen64, ok := new(big.Int).SetString("0x8000000000000000", 0)
+ require.True(t, ok)
+
+ bitLen80, ok := new(big.Int).SetString("0x80000000000000000000", 0)
+ require.True(t, ok)
+
+ expBitLen80, ok := new(big.Int).SetString("302231454903657293676526", 0)
+ require.True(t, ok)
+
+ testCases := []struct {
+ msg string
+ data TxData
+ expChainID *big.Int
+ }{
+ {
+ "v = -1", &LegacyTx{V: big.NewInt(-1).Bytes()}, nil,
+ },
+ {
+ "v = 0", &LegacyTx{V: big.NewInt(0).Bytes()}, nil,
+ },
+ {
+ "v = 1", &LegacyTx{V: big.NewInt(1).Bytes()}, nil,
+ },
+ {
+ "v = 27", &LegacyTx{V: big.NewInt(27).Bytes()}, new(big.Int),
+ },
+ {
+ "v = 28", &LegacyTx{V: big.NewInt(28).Bytes()}, new(big.Int),
+ },
+ {
+ "Ethereum mainnet", &LegacyTx{V: big.NewInt(37).Bytes()}, big.NewInt(1),
+ },
+ {
+ "chain ID 9000", &LegacyTx{V: big.NewInt(18035).Bytes()}, big.NewInt(9000),
+ },
+ {
+ "bit len 64", &LegacyTx{V: bitLen64.Bytes()}, big.NewInt(4611686018427387886),
+ },
+ {
+ "bit len 80", &LegacyTx{V: bitLen80.Bytes()}, expBitLen80,
+ },
+ {
+ "v = nil ", &LegacyTx{V: nil}, nil,
+ },
+ }
+
+ for _, tc := range testCases {
+ v, _, _ := tc.data.GetRawSignatureValues()
+
+ chainID := DeriveChainID(v)
+ require.Equal(t, tc.expChainID, chainID, tc.msg)
+ }
+}
diff --git a/x/evm/types/tx_types.go b/x/evm/types/tx_types.go
new file mode 100644
index 00000000..f1debce9
--- /dev/null
+++ b/x/evm/types/tx_types.go
@@ -0,0 +1,20 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ gethtypes "github.com/ethereum/go-ethereum/core/types"
+)
+
+func GetTxTypeName(txType int) string {
+ switch txType {
+ case gethtypes.DynamicFeeTxType:
+ return "DynamicFeeTxType"
+ case gethtypes.LegacyTxType:
+ return "LegacyTxType"
+ case gethtypes.AccessListTxType:
+ return "AccessListTxType"
+ default:
+ panic("unknown tx type")
+ }
+}
diff --git a/x/evm/types/utils.go b/x/evm/types/utils.go
new file mode 100644
index 00000000..bd01d73e
--- /dev/null
+++ b/x/evm/types/utils.go
@@ -0,0 +1,136 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+
+package types
+
+import (
+ "bytes"
+ "fmt"
+ "math/big"
+
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ errortypes "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/cosmos/gogoproto/proto"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+var (
+ // DefaultPriorityReduction is the default amount of price values required for 1 unit of priority.
+ // Because priority is `int64` while price is `big.Int`, it's necessary to scale down the range to keep it more pratical.
+ // The default value is the same as the `sdk.DefaultPowerReduction`.
+ DefaultPriorityReduction = sdk.DefaultPowerReduction
+
+ // EmptyCodeHash is keccak256 hash of nil to represent empty code.
+ EmptyCodeHash = crypto.Keccak256(nil)
+)
+
+// IsEmptyCodeHash checks if the given byte slice represents an empty code hash.
+func IsEmptyCodeHash(bz []byte) bool {
+ return bytes.Equal(bz, EmptyCodeHash)
+}
+
+// DecodeTxResponse decodes an protobuf-encoded byte slice into TxResponse
+func DecodeTxResponse(in []byte) (*MsgEthereumTxResponse, error) {
+ var txMsgData sdk.TxMsgData
+ if err := proto.Unmarshal(in, &txMsgData); err != nil {
+ return nil, err
+ }
+
+ if len(txMsgData.MsgResponses) == 0 {
+ return &MsgEthereumTxResponse{}, nil
+ }
+
+ var res MsgEthereumTxResponse
+ if err := proto.Unmarshal(txMsgData.MsgResponses[0].Value, &res); err != nil {
+ return nil, errorsmod.Wrap(err, "failed to unmarshal tx response message data")
+ }
+
+ return &res, nil
+}
+
+// EncodeTransactionLogs encodes TransactionLogs slice into a protobuf-encoded byte slice.
+func EncodeTransactionLogs(res *TransactionLogs) ([]byte, error) {
+ return proto.Marshal(res)
+}
+
+// DecodeTransactionLogs decodes an protobuf-encoded byte slice into TransactionLogs
+func DecodeTransactionLogs(data []byte) (TransactionLogs, error) {
+ var logs TransactionLogs
+ err := proto.Unmarshal(data, &logs)
+ if err != nil {
+ return TransactionLogs{}, err
+ }
+ return logs, nil
+}
+
+// UnwrapEthereumMsg extracts MsgEthereumTx from wrapping sdk.Tx
+func UnwrapEthereumMsg(tx *sdk.Tx, ethHash common.Hash) (*MsgEthereumTx, error) {
+ if tx == nil {
+ return nil, fmt.Errorf("invalid tx: nil")
+ }
+
+ for _, msg := range (*tx).GetMsgs() {
+ ethMsg, ok := msg.(*MsgEthereumTx)
+ if !ok {
+ return nil, fmt.Errorf("invalid tx type: %T", tx)
+ }
+ txHash := ethMsg.AsTransaction().Hash()
+ ethMsg.Hash = txHash.Hex()
+ if txHash == ethHash {
+ return ethMsg, nil
+ }
+ }
+
+ return nil, fmt.Errorf("eth tx not found: %s", ethHash)
+}
+
+// UnpackEthMsg unpacks an Ethereum message from a Cosmos SDK message
+func UnpackEthMsg(msg sdk.Msg) (
+ ethMsg *MsgEthereumTx,
+ txData TxData,
+ from sdk.AccAddress,
+ err error,
+) {
+ msgEthTx, ok := msg.(*MsgEthereumTx)
+ if !ok {
+ return nil, nil, nil, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*MsgEthereumTx)(nil))
+ }
+
+ txData, err = UnpackTxData(msgEthTx.Data)
+ if err != nil {
+ return nil, nil, nil, errorsmod.Wrap(err, "failed to unpack tx data any for tx")
+ }
+
+ // sender address should be in the tx cache from the previous AnteHandle call
+ from = msgEthTx.GetFrom()
+ return msgEthTx, txData, from, nil
+}
+
+// BinSearch executes the binary search and hone in on an executable gas limit
+func BinSearch(lo, hi uint64, executable func(uint64) (bool, *MsgEthereumTxResponse, error)) (uint64, error) {
+ for lo+1 < hi {
+ mid := (hi + lo) / 2
+ failed, _, err := executable(mid)
+ // If the error is not nil(consensus error), it means the provided message
+ // call or transaction will never be accepted no matter how much gas it is
+ // assigned. Return the error directly, don't struggle any more.
+ if err != nil {
+ return 0, err
+ }
+ if failed {
+ lo = mid
+ } else {
+ hi = mid
+ }
+ }
+ return hi, nil
+}
+
+// EffectiveGasPrice computes the effective gas price based on eip-1559 rules
+// `effectiveGasPrice = min(baseFee + tipCap, feeCap)`
+func EffectiveGasPrice(baseFee, feeCap, tipCap *big.Int) *big.Int {
+ return math.BigMin(new(big.Int).Add(tipCap, baseFee), feeCap)
+}
diff --git a/x/evm/types/utils_test.go b/x/evm/types/utils_test.go
new file mode 100644
index 00000000..80066670
--- /dev/null
+++ b/x/evm/types/utils_test.go
@@ -0,0 +1,128 @@
+package types_test
+
+import (
+ "errors"
+ "math/big"
+ "testing"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ proto "github.com/cosmos/gogoproto/proto"
+
+ "github.com/evmos/evmos/v19/app"
+ "github.com/evmos/evmos/v19/encoding"
+ utiltx "github.com/evmos/evmos/v19/testutil/tx"
+ evmtypes "github.com/evmos/evmos/v19/x/evm/types"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestEvmDataEncoding(t *testing.T) {
+ ret := []byte{0x5, 0x8}
+
+ data := &evmtypes.MsgEthereumTxResponse{
+ Hash: common.BytesToHash([]byte("hash")).String(),
+ Logs: []*evmtypes.Log{{
+ Data: []byte{1, 2, 3, 4},
+ BlockNumber: 17,
+ }},
+ Ret: ret,
+ }
+
+ anyData := codectypes.UnsafePackAny(data)
+ txData := &sdk.TxMsgData{
+ MsgResponses: []*codectypes.Any{anyData},
+ }
+
+ txDataBz, err := proto.Marshal(txData)
+ require.NoError(t, err)
+
+ res, err := evmtypes.DecodeTxResponse(txDataBz)
+ require.NoError(t, err)
+ require.NotNil(t, res)
+ require.Equal(t, data.Logs, res.Logs)
+ require.Equal(t, ret, res.Ret)
+}
+
+func TestUnwrapEthererumMsg(t *testing.T) {
+ _, err := evmtypes.UnwrapEthereumMsg(nil, common.Hash{})
+ require.NotNil(t, err)
+
+ encodingConfig := encoding.MakeConfig(app.ModuleBasics)
+ clientCtx := client.Context{}.WithTxConfig(encodingConfig.TxConfig)
+ builder, _ := clientCtx.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
+
+ tx := builder.GetTx().(sdk.Tx)
+ _, err = evmtypes.UnwrapEthereumMsg(&tx, common.Hash{})
+ require.NotNil(t, err)
+
+ evmTxParams := &evmtypes.EvmTxArgs{
+ ChainID: big.NewInt(1),
+ Nonce: 0,
+ To: &common.Address{},
+ Amount: big.NewInt(0),
+ GasLimit: 0,
+ GasPrice: big.NewInt(0),
+ Input: []byte{},
+ }
+
+ msg := evmtypes.NewTx(evmTxParams)
+ err = builder.SetMsgs(msg)
+ require.Nil(t, err)
+
+ tx = builder.GetTx().(sdk.Tx)
+ unwrappedMsg, err := evmtypes.UnwrapEthereumMsg(&tx, msg.AsTransaction().Hash())
+ require.Nil(t, err)
+ require.Equal(t, unwrappedMsg, msg)
+}
+
+func TestBinSearch(t *testing.T) {
+ successExecutable := func(gas uint64) (bool, *evmtypes.MsgEthereumTxResponse, error) {
+ target := uint64(21000)
+ return gas < target, nil, nil
+ }
+ failedExecutable := func(_ uint64) (bool, *evmtypes.MsgEthereumTxResponse, error) {
+ return true, nil, errors.New("contract failed")
+ }
+
+ gas, err := evmtypes.BinSearch(20000, 21001, successExecutable)
+ require.NoError(t, err)
+ require.Equal(t, gas, uint64(21000))
+
+ gas, err = evmtypes.BinSearch(20000, 21001, failedExecutable)
+ require.Error(t, err)
+ require.Equal(t, gas, uint64(0))
+}
+
+func TestTransactionLogsEncodeDecode(t *testing.T) {
+ addr := utiltx.GenerateAddress().String()
+
+ txLogs := evmtypes.TransactionLogs{
+ Hash: common.BytesToHash([]byte("tx_hash")).String(),
+ Logs: []*evmtypes.Log{
+ {
+ Address: addr,
+ Topics: []string{common.BytesToHash([]byte("topic")).String()},
+ Data: []byte("data"),
+ BlockNumber: 1,
+ TxHash: common.BytesToHash([]byte("tx_hash")).String(),
+ TxIndex: 1,
+ BlockHash: common.BytesToHash([]byte("block_hash")).String(),
+ Index: 1,
+ Removed: false,
+ },
+ },
+ }
+
+ txLogsEncoded, encodeErr := evmtypes.EncodeTransactionLogs(&txLogs)
+ require.Nil(t, encodeErr)
+
+ txLogsEncodedDecoded, decodeErr := evmtypes.DecodeTransactionLogs(txLogsEncoded)
+ require.Nil(t, decodeErr)
+ require.Equal(t, txLogs, txLogsEncodedDecoded)
+}
diff --git a/x/feemarket/client/cli/query.go b/x/feemarket/client/cli/query.go
new file mode 100644
index 00000000..b6a62539
--- /dev/null
+++ b/x/feemarket/client/cli/query.go
@@ -0,0 +1,118 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package cli
+
+import (
+ "github.com/spf13/cobra"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/client/flags"
+
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+// GetQueryCmd returns the parent command for all x/feemarket CLI query commands.
+func GetQueryCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: types.ModuleName,
+ Short: "Querying commands for the fee market module",
+ DisableFlagParsing: true,
+ SuggestionsMinimumDistance: 2,
+ RunE: client.ValidateCmd,
+ }
+
+ cmd.AddCommand(
+ GetBlockGasCmd(),
+ GetBaseFeeCmd(),
+ GetParamsCmd(),
+ )
+ return cmd
+}
+
+// GetBlockGasCmd queries the gas used in a block
+func GetBlockGasCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "block-gas",
+ Short: "Get the block gas used at a given block height",
+ Long: `Get the block gas used at a given block height.
+If the height is not provided, it will use the latest height from context`,
+ Args: cobra.NoArgs,
+ RunE: func(cmd *cobra.Command, _ []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ queryClient := types.NewQueryClient(clientCtx)
+
+ ctx := cmd.Context()
+ res, err := queryClient.BlockGas(ctx, &types.QueryBlockGasRequest{})
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+ return cmd
+}
+
+// GetParamsCmd queries the fee market params
+func GetParamsCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "params",
+ Short: "Get the fee market params",
+ Long: "Get the fee market parameter values.",
+ Args: cobra.NoArgs,
+ RunE: func(cmd *cobra.Command, _ []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ queryClient := types.NewQueryClient(clientCtx)
+
+ res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{})
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+ return cmd
+}
+
+// GetBaseFeeCmd queries the base fee at a given height
+func GetBaseFeeCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "base-fee",
+ Short: "Get the base fee amount at a given block height",
+ Long: `Get the base fee amount at a given block height.
+If the height is not provided, it will use the latest height from context.`,
+ Args: cobra.NoArgs,
+ RunE: func(cmd *cobra.Command, _ []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ queryClient := types.NewQueryClient(clientCtx)
+
+ ctx := cmd.Context()
+ res, err := queryClient.BaseFee(ctx, &types.QueryBaseFeeRequest{})
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+ return cmd
+}
diff --git a/x/feemarket/genesis.go b/x/feemarket/genesis.go
new file mode 100644
index 00000000..02733738
--- /dev/null
+++ b/x/feemarket/genesis.go
@@ -0,0 +1,36 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package feemarket
+
+import (
+ errorsmod "cosmossdk.io/errors"
+ abci "github.com/cometbft/cometbft/abci/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/evmos/os/x/feemarket/keeper"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+// InitGenesis initializes genesis state based on exported genesis
+func InitGenesis(
+ ctx sdk.Context,
+ k keeper.Keeper,
+ data types.GenesisState,
+) []abci.ValidatorUpdate {
+ err := k.SetParams(ctx, data.Params)
+ if err != nil {
+ panic(errorsmod.Wrap(err, "could not set parameters at genesis"))
+ }
+
+ k.SetBlockGasWanted(ctx, data.BlockGas)
+
+ return []abci.ValidatorUpdate{}
+}
+
+// ExportGenesis exports genesis state of the fee market module
+func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
+ return &types.GenesisState{
+ Params: k.GetParams(ctx),
+ BlockGas: k.GetBlockGasWanted(ctx),
+ }
+}
diff --git a/x/feemarket/keeper/abci.go b/x/feemarket/keeper/abci.go
new file mode 100644
index 00000000..1db8d273
--- /dev/null
+++ b/x/feemarket/keeper/abci.go
@@ -0,0 +1,80 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "fmt"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/evmos/os/x/feemarket/types"
+
+ "cosmossdk.io/math"
+ "github.com/cosmos/cosmos-sdk/telemetry"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+// BeginBlock updates base fee
+func (k *Keeper) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
+ baseFee := k.CalculateBaseFee(ctx)
+
+ // return immediately if base fee is nil
+ if baseFee == nil {
+ return
+ }
+
+ k.SetBaseFee(ctx, baseFee)
+
+ defer func() {
+ telemetry.SetGauge(float32(baseFee.Int64()), "feemarket", "base_fee")
+ }()
+
+ // Store current base fee in event
+ ctx.EventManager().EmitEvents(sdk.Events{
+ sdk.NewEvent(
+ types.EventTypeFeeMarket,
+ sdk.NewAttribute(types.AttributeKeyBaseFee, baseFee.String()),
+ ),
+ })
+}
+
+// EndBlock update block gas wanted.
+// The EVM end block logic doesn't update the validator set, thus it returns
+// an empty slice.
+func (k *Keeper) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) {
+ if ctx.BlockGasMeter() == nil {
+ k.Logger(ctx).Error("block gas meter is nil when setting block gas wanted")
+ return
+ }
+
+ gasWanted := math.NewIntFromUint64(k.GetTransientGasWanted(ctx))
+ gasUsed := math.NewIntFromUint64(ctx.BlockGasMeter().GasConsumedToLimit())
+
+ if !gasWanted.IsInt64() {
+ k.Logger(ctx).Error("integer overflow by integer type conversion. Gas wanted > MaxInt64", "gas wanted", gasWanted.String())
+ return
+ }
+
+ if !gasUsed.IsInt64() {
+ k.Logger(ctx).Error("integer overflow by integer type conversion. Gas used > MaxInt64", "gas used", gasUsed.String())
+ return
+ }
+
+ // to prevent BaseFee manipulation we limit the gasWanted so that
+ // gasWanted = max(gasWanted * MinGasMultiplier, gasUsed)
+ // this will be keep BaseFee protected from un-penalized manipulation
+ // more info here https://github.com/evmos/ethermint/pull/1105#discussion_r888798925
+ minGasMultiplier := k.GetParams(ctx).MinGasMultiplier
+ limitedGasWanted := math.LegacyNewDec(gasWanted.Int64()).Mul(minGasMultiplier)
+ updatedGasWanted := math.LegacyMaxDec(limitedGasWanted, math.LegacyNewDec(gasUsed.Int64())).TruncateInt().Uint64()
+ k.SetBlockGasWanted(ctx, updatedGasWanted)
+
+ defer func() {
+ telemetry.SetGauge(float32(updatedGasWanted), "feemarket", "block_gas")
+ }()
+
+ ctx.EventManager().EmitEvent(sdk.NewEvent(
+ "block_gas",
+ sdk.NewAttribute("height", fmt.Sprintf("%d", ctx.BlockHeight())),
+ sdk.NewAttribute("amount", fmt.Sprintf("%d", updatedGasWanted)),
+ ))
+}
diff --git a/x/feemarket/keeper/abci_test.go b/x/feemarket/keeper/abci_test.go
new file mode 100644
index 00000000..ae338c93
--- /dev/null
+++ b/x/feemarket/keeper/abci_test.go
@@ -0,0 +1,48 @@
+package keeper_test
+
+import (
+ "fmt"
+
+ "github.com/cometbft/cometbft/abci/types"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+)
+
+func (suite *KeeperTestSuite) TestEndBlock() {
+ testCases := []struct {
+ name string
+ NoBaseFee bool
+ malleate func()
+ expGasWanted uint64
+ }{
+ {
+ "baseFee nil",
+ true,
+ func() {},
+ uint64(0),
+ },
+ {
+ "pass",
+ false,
+ func() {
+ meter := storetypes.NewGasMeter(uint64(1000000000))
+ suite.ctx = suite.ctx.WithBlockGasMeter(meter)
+ suite.app.FeeMarketKeeper.SetTransientBlockGasWanted(suite.ctx, 5000000)
+ },
+ uint64(2500000),
+ },
+ }
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.SetupTest() // reset
+ params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
+ params.NoBaseFee = tc.NoBaseFee
+ err := suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+
+ tc.malleate()
+ suite.app.FeeMarketKeeper.EndBlock(suite.ctx, types.RequestEndBlock{Height: 1})
+ gasWanted := suite.app.FeeMarketKeeper.GetBlockGasWanted(suite.ctx)
+ suite.Require().Equal(tc.expGasWanted, gasWanted, tc.name)
+ })
+ }
+}
diff --git a/x/feemarket/keeper/eip1559.go b/x/feemarket/keeper/eip1559.go
new file mode 100644
index 00000000..6b738b52
--- /dev/null
+++ b/x/feemarket/keeper/eip1559.go
@@ -0,0 +1,94 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+)
+
+// CalculateBaseFee calculates the base fee for the current block. This is only calculated once per
+// block during BeginBlock. If the NoBaseFee parameter is enabled or below activation height, this function returns nil.
+// NOTE: This code is inspired from the go-ethereum EIP1559 implementation and adapted to Cosmos SDK-based
+// chains. For the canonical code refer to: https://github.com/ethereum/go-ethereum/blob/master/consensus/misc/eip1559.go
+func (k Keeper) CalculateBaseFee(ctx sdk.Context) *big.Int {
+ params := k.GetParams(ctx)
+
+ // Ignore the calculation if not enabled
+ if !params.IsBaseFeeEnabled(ctx.BlockHeight()) {
+ return nil
+ }
+
+ consParams := ctx.ConsensusParams()
+
+ // If the current block is the first EIP-1559 block, return the base fee
+ // defined in the parameters (DefaultBaseFee if it hasn't been changed by
+ // governance).
+ if ctx.BlockHeight() == params.EnableHeight {
+ return params.BaseFee.BigInt()
+ }
+
+ // get the block gas used and the base fee values for the parent block.
+ // NOTE: this is not the parent's base fee but the current block's base fee,
+ // as it is retrieved from the transient store, which is committed to the
+ // persistent KVStore after EndBlock (ABCI Commit).
+ parentBaseFee := params.BaseFee.BigInt()
+ if parentBaseFee == nil {
+ return nil
+ }
+
+ parentGasUsed := k.GetBlockGasWanted(ctx)
+
+ gasLimit := new(big.Int).SetUint64(math.MaxUint64)
+
+ // NOTE: a MaxGas equal to -1 means that block gas is unlimited
+ if consParams != nil && consParams.Block != nil && consParams.Block.MaxGas > -1 {
+ gasLimit = big.NewInt(consParams.Block.MaxGas)
+ }
+
+ // CONTRACT: ElasticityMultiplier cannot be 0 as it's checked in the params
+ // validation
+ parentGasTargetBig := new(big.Int).Div(gasLimit, new(big.Int).SetUint64(uint64(params.ElasticityMultiplier)))
+ if !parentGasTargetBig.IsUint64() {
+ return nil
+ }
+
+ parentGasTarget := parentGasTargetBig.Uint64()
+ baseFeeChangeDenominator := new(big.Int).SetUint64(uint64(params.BaseFeeChangeDenominator))
+
+ // If the parent gasUsed is the same as the target, the baseFee remains
+ // unchanged.
+ if parentGasUsed == parentGasTarget {
+ return new(big.Int).Set(parentBaseFee)
+ }
+
+ if parentGasUsed > parentGasTarget {
+ // If the parent block used more gas than its target, the baseFee should
+ // increase.
+ gasUsedDelta := new(big.Int).SetUint64(parentGasUsed - parentGasTarget)
+ x := new(big.Int).Mul(parentBaseFee, gasUsedDelta)
+ y := x.Div(x, parentGasTargetBig)
+ baseFeeDelta := math.BigMax(
+ x.Div(y, baseFeeChangeDenominator),
+ common.Big1,
+ )
+
+ return x.Add(parentBaseFee, baseFeeDelta)
+ }
+
+ // Otherwise if the parent block used less gas than its target, the baseFee
+ // should decrease.
+ gasUsedDelta := new(big.Int).SetUint64(parentGasTarget - parentGasUsed)
+ x := new(big.Int).Mul(parentBaseFee, gasUsedDelta)
+ y := x.Div(x, parentGasTargetBig)
+ baseFeeDelta := x.Div(y, baseFeeChangeDenominator)
+
+ // Set global min gas price as lower bound of the base fee, transactions below
+ // the min gas price don't even reach the mempool.
+ minGasPrice := params.MinGasPrice.TruncateInt().BigInt()
+ return math.BigMax(x.Sub(parentBaseFee, baseFeeDelta), minGasPrice)
+}
diff --git a/x/feemarket/keeper/eip1559_test.go b/x/feemarket/keeper/eip1559_test.go
new file mode 100644
index 00000000..6b40450e
--- /dev/null
+++ b/x/feemarket/keeper/eip1559_test.go
@@ -0,0 +1,117 @@
+package keeper_test
+
+import (
+ "fmt"
+ "math/big"
+
+ "cosmossdk.io/math"
+ tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+)
+
+func (suite *KeeperTestSuite) TestCalculateBaseFee() {
+ testCases := []struct {
+ name string
+ NoBaseFee bool
+ blockHeight int64
+ parentBlockGasWanted uint64
+ minGasPrice math.LegacyDec
+ expFee *big.Int
+ }{
+ {
+ "without BaseFee",
+ true,
+ 0,
+ 0,
+ math.LegacyZeroDec(),
+ nil,
+ },
+ {
+ "with BaseFee - initial EIP-1559 block",
+ false,
+ 0,
+ 0,
+ math.LegacyZeroDec(),
+ suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee.BigInt(),
+ },
+ {
+ "with BaseFee - parent block wanted the same gas as its target (ElasticityMultiplier = 2)",
+ false,
+ 1,
+ 50,
+ math.LegacyZeroDec(),
+ suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee.BigInt(),
+ },
+ {
+ "with BaseFee - parent block wanted the same gas as its target, with higher min gas price (ElasticityMultiplier = 2)",
+ false,
+ 1,
+ 50,
+ math.LegacyNewDec(1500000000),
+ suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee.BigInt(),
+ },
+ {
+ "with BaseFee - parent block wanted more gas than its target (ElasticityMultiplier = 2)",
+ false,
+ 1,
+ 100,
+ math.LegacyZeroDec(),
+ big.NewInt(1125000000),
+ },
+ {
+ "with BaseFee - parent block wanted more gas than its target, with higher min gas price (ElasticityMultiplier = 2)",
+ false,
+ 1,
+ 100,
+ math.LegacyNewDec(1500000000),
+ big.NewInt(1125000000),
+ },
+ {
+ "with BaseFee - Parent gas wanted smaller than parent gas target (ElasticityMultiplier = 2)",
+ false,
+ 1,
+ 25,
+ math.LegacyZeroDec(),
+ big.NewInt(937500000),
+ },
+ {
+ "with BaseFee - Parent gas wanted smaller than parent gas target, with higher min gas price (ElasticityMultiplier = 2)",
+ false,
+ 1,
+ 25,
+ math.LegacyNewDec(1500000000),
+ big.NewInt(1500000000),
+ },
+ }
+ for _, tc := range testCases {
+ suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
+ suite.SetupTest() // reset
+
+ params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
+ params.NoBaseFee = tc.NoBaseFee
+ params.MinGasPrice = tc.minGasPrice
+ err := suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+
+ // Set block height
+ suite.ctx = suite.ctx.WithBlockHeight(tc.blockHeight)
+
+ // Set parent block gas
+ suite.app.FeeMarketKeeper.SetBlockGasWanted(suite.ctx, tc.parentBlockGasWanted)
+
+ // Set next block target/gasLimit through Consensus Param MaxGas
+ blockParams := tmproto.BlockParams{
+ MaxGas: 100,
+ MaxBytes: 10,
+ }
+ consParams := tmproto.ConsensusParams{Block: &blockParams}
+ suite.ctx = suite.ctx.WithConsensusParams(&consParams)
+
+ fee := suite.app.FeeMarketKeeper.CalculateBaseFee(suite.ctx)
+ if tc.NoBaseFee {
+ suite.Require().Nil(fee, tc.name)
+ } else {
+ suite.Require().Equal(tc.expFee, fee, tc.name)
+ }
+ })
+ }
+}
diff --git a/x/feemarket/keeper/grpc_query.go b/x/feemarket/keeper/grpc_query.go
new file mode 100644
index 00000000..bc2f869b
--- /dev/null
+++ b/x/feemarket/keeper/grpc_query.go
@@ -0,0 +1,54 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "context"
+
+ errorsmod "cosmossdk.io/errors"
+ sdkmath "cosmossdk.io/math"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+var _ types.QueryServer = Keeper{}
+
+// Params implements the Query/Params gRPC method
+func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
+ ctx := sdk.UnwrapSDKContext(c)
+ params := k.GetParams(ctx)
+
+ return &types.QueryParamsResponse{
+ Params: params,
+ }, nil
+}
+
+// BaseFee implements the Query/BaseFee gRPC method
+func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types.QueryBaseFeeResponse, error) {
+ ctx := sdk.UnwrapSDKContext(c)
+
+ res := &types.QueryBaseFeeResponse{}
+ baseFee := k.GetBaseFee(ctx)
+
+ if baseFee != nil {
+ aux := sdkmath.NewIntFromBigInt(baseFee)
+ res.BaseFee = &aux
+ }
+
+ return res, nil
+}
+
+// BlockGas implements the Query/BlockGas gRPC method
+func (k Keeper) BlockGas(c context.Context, _ *types.QueryBlockGasRequest) (*types.QueryBlockGasResponse, error) {
+ ctx := sdk.UnwrapSDKContext(c)
+ gas := sdkmath.NewIntFromUint64(k.GetBlockGasWanted(ctx))
+
+ if !gas.IsInt64() {
+ return nil, errorsmod.Wrapf(sdk.ErrIntOverflowCoin, "block gas %s is higher than MaxInt64", gas)
+ }
+
+ return &types.QueryBlockGasResponse{
+ Gas: gas.Int64(),
+ }, nil
+}
diff --git a/x/feemarket/keeper/grpc_query_test.go b/x/feemarket/keeper/grpc_query_test.go
new file mode 100644
index 00000000..86d3305b
--- /dev/null
+++ b/x/feemarket/keeper/grpc_query_test.go
@@ -0,0 +1,100 @@
+package keeper_test
+
+import (
+ sdkmath "cosmossdk.io/math"
+ ethparams "github.com/ethereum/go-ethereum/params"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+func (suite *KeeperTestSuite) TestQueryParams() {
+ testCases := []struct {
+ name string
+ expPass bool
+ }{
+ {
+ "pass",
+ true,
+ },
+ }
+ for _, tc := range testCases {
+ params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
+ exp := &types.QueryParamsResponse{Params: params}
+
+ res, err := suite.queryClient.Params(suite.ctx.Context(), &types.QueryParamsRequest{})
+ if tc.expPass {
+ suite.Require().Equal(exp, res, tc.name)
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryBaseFee() {
+ var (
+ aux sdkmath.Int
+ expRes *types.QueryBaseFeeResponse
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "pass - default Base Fee",
+ func() {
+ initialBaseFee := sdkmath.NewInt(ethparams.InitialBaseFee)
+ expRes = &types.QueryBaseFeeResponse{BaseFee: &initialBaseFee}
+ },
+ true,
+ },
+ {
+ "pass - non-nil Base Fee",
+ func() {
+ baseFee := sdkmath.OneInt().BigInt()
+ suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, baseFee)
+
+ aux = sdkmath.NewIntFromBigInt(baseFee)
+ expRes = &types.QueryBaseFeeResponse{BaseFee: &aux}
+ },
+ true,
+ },
+ }
+ for _, tc := range testCases {
+ tc.malleate()
+
+ res, err := suite.queryClient.BaseFee(suite.ctx.Context(), &types.QueryBaseFeeRequest{})
+ if tc.expPass {
+ suite.Require().NotNil(res)
+ suite.Require().Equal(expRes, res, tc.name)
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ }
+}
+
+func (suite *KeeperTestSuite) TestQueryBlockGas() {
+ testCases := []struct {
+ name string
+ expPass bool
+ }{
+ {
+ "pass",
+ true,
+ },
+ }
+ for _, tc := range testCases {
+ gas := suite.app.FeeMarketKeeper.GetBlockGasWanted(suite.ctx)
+ exp := &types.QueryBlockGasResponse{Gas: int64(gas)}
+
+ res, err := suite.queryClient.BlockGas(suite.ctx.Context(), &types.QueryBlockGasRequest{})
+ if tc.expPass {
+ suite.Require().Equal(exp, res, tc.name)
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ }
+}
diff --git a/x/feemarket/keeper/integration_test.go b/x/feemarket/keeper/integration_test.go
new file mode 100644
index 00000000..740a5dd3
--- /dev/null
+++ b/x/feemarket/keeper/integration_test.go
@@ -0,0 +1,445 @@
+package keeper_test
+
+import (
+ "math/big"
+ "strings"
+
+ "cosmossdk.io/math"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/testutil"
+ "github.com/evmos/os/crypto/ethsecp256k1"
+ utiltx "github.com/evmos/os/testutil/tx"
+ "github.com/evmos/os/utils"
+
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+)
+
+const chainID = utils.TestnetChainID + "-1"
+
+var _ = Describe("Feemarket", func() {
+ var (
+ privKey *ethsecp256k1.PrivKey
+ msg banktypes.MsgSend
+ )
+
+ Describe("Performing Cosmos transactions", func() {
+ Context("with min-gas-prices (local) < MinGasPrices (feemarket param)", func() {
+ BeforeEach(func() {
+ privKey, msg = setupTestWithContext(chainID, "1", math.LegacyNewDec(3), math.ZeroInt())
+ })
+
+ Context("during CheckTx", func() {
+ It("should reject transactions with gasPrice < MinGasPrices", func() {
+ gasPrice := math.NewInt(2)
+ _, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ })
+
+ It("should accept transactions with gasPrice >= MinGasPrices", func() {
+ gasPrice := math.NewInt(3)
+ res, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ })
+ })
+
+ Context("during DeliverTx", func() {
+ It("should reject transactions with gasPrice < MinGasPrices", func() {
+ gasPrice := math.NewInt(2)
+ _, err := testutil.DeliverTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).NotTo(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ })
+
+ It("should accept transactions with gasPrice >= MinGasPrices", func() {
+ gasPrice := math.NewInt(3)
+ res, err := testutil.DeliverTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ s.Require().NoError(err)
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ })
+ })
+ })
+
+ Context("with min-gas-prices (local) == MinGasPrices (feemarket param)", func() {
+ BeforeEach(func() {
+ privKey, msg = setupTestWithContext(chainID, "3", math.LegacyNewDec(3), math.ZeroInt())
+ })
+
+ Context("during CheckTx", func() {
+ It("should reject transactions with gasPrice < min-gas-prices", func() {
+ gasPrice := math.NewInt(2)
+ _, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "insufficient fee"),
+ ).To(BeTrue(), err.Error())
+ })
+
+ It("should accept transactions with gasPrice >= MinGasPrices", func() {
+ gasPrice := math.NewInt(3)
+ res, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ })
+ })
+
+ Context("during DeliverTx", func() {
+ It("should reject transactions with gasPrice < MinGasPrices", func() {
+ gasPrice := math.NewInt(2)
+ _, err := testutil.DeliverTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).NotTo(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ })
+
+ It("should accept transactions with gasPrice >= MinGasPrices", func() {
+ gasPrice := math.NewInt(3)
+ res, err := testutil.DeliverTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ })
+ })
+ })
+
+ Context("with MinGasPrices (feemarket param) < min-gas-prices (local)", func() {
+ BeforeEach(func() {
+ privKey, msg = setupTestWithContext(chainID, "5", math.LegacyNewDec(3), math.NewInt(5))
+ })
+
+ //nolint
+ Context("during CheckTx", func() {
+ It("should reject transactions with gasPrice < MinGasPrices", func() {
+ gasPrice := math.NewInt(2)
+ _, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "insufficient fee"),
+ ).To(BeTrue(), err.Error())
+ })
+
+ It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() {
+ gasPrice := math.NewInt(4)
+ _, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "insufficient fee"),
+ ).To(BeTrue(), err.Error())
+ })
+
+ It("should accept transactions with gasPrice >= baseFee", func() {
+ gasPrice := math.NewInt(5)
+ res, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ })
+ })
+
+ //nolint
+ Context("during DeliverTx", func() {
+ It("should reject transactions with gasPrice < MinGasPrices", func() {
+ gasPrice := math.NewInt(2)
+ _, err := testutil.DeliverTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).NotTo(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ })
+
+ It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() {
+ gasPrice := math.NewInt(4)
+ _, err := testutil.CheckTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "insufficient fee"),
+ ).To(BeTrue(), err.Error())
+ })
+ It("should accept transactions with gasPrice >= baseFee", func() {
+ gasPrice := math.NewInt(5)
+ res, err := testutil.DeliverTx(s.ctx, s.app, privKey, &gasPrice, &msg)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ })
+ })
+ })
+ })
+
+ Describe("Performing EVM transactions", func() {
+ type txParams struct {
+ gasPrice *big.Int
+ gasFeeCap *big.Int
+ gasTipCap *big.Int
+ accesses *ethtypes.AccessList
+ }
+ type getprices func() txParams
+
+ Context("with BaseFee (feemarket) < MinGasPrices (feemarket param)", func() {
+ var (
+ baseFee int64
+ minGasPrices int64
+ )
+
+ BeforeEach(func() {
+ baseFee = 10_000_000_000
+ minGasPrices = baseFee + 30_000_000_000
+
+ // Note that the tests run the same transactions with `gasLimit =
+ // 100000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`,
+ // a `minGasPrices = 40_000_000_000` results in `minGlobalFee =
+ // 4000000000000000`
+ privKey, _ = setupTestWithContext(chainID, "1", math.LegacyNewDec(minGasPrices), math.NewInt(baseFee))
+ })
+
+ Context("during CheckTx", func() {
+ DescribeTable("should reject transactions with EffectivePrice < MinGasPrices",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ _, err := testutil.CheckEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil}
+ }),
+ Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams {
+ // Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000)
+ return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}}
+ }),
+ Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice < MinGasPrices", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices + 10_000_000_000), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ )
+
+ DescribeTable("should accept transactions with gasPrice >= MinGasPrices",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ res, err := testutil.CheckEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(minGasPrices), nil, nil, nil}
+ }),
+ // Note that this tx is not rejected on CheckTx, but not on DeliverTx,
+ // as the baseFee is set to minGasPrices during DeliverTx when baseFee
+ // < minGasPrices
+ Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice > MinGasPrices", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices), big.NewInt(30_000_000_000), ðtypes.AccessList{}}
+ }),
+ )
+ })
+
+ Context("during DeliverTx", func() {
+ DescribeTable("should reject transactions with gasPrice < MinGasPrices",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ _, err := testutil.DeliverEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil}
+ }),
+ Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams {
+ // Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000)
+ return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}}
+ }),
+ )
+
+ DescribeTable("should accept transactions with gasPrice >= MinGasPrices",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ res, err := testutil.DeliverEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).To(BeNil(), "transaction should have succeeded")
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(minGasPrices + 1), nil, nil, nil}
+ }),
+ Entry("dynamic tx, EffectivePrice > MinGasPrices", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices + 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}}
+ }),
+ )
+ })
+ })
+
+ Context("with MinGasPrices (feemarket param) < BaseFee (feemarket)", func() {
+ var (
+ baseFee int64
+ minGasPrices int64
+ )
+
+ BeforeEach(func() {
+ baseFee = 10_000_000_000
+ minGasPrices = baseFee - 5_000_000_000
+
+ // Note that the tests run the same transactions with `gasLimit =
+ // 100_000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`,
+ // a `minGasPrices = 5_000_000_000` results in `minGlobalFee =
+ // 500_000_000_000_000`
+ privKey, _ = setupTestWithContext(chainID, "1", math.LegacyNewDec(minGasPrices), math.NewInt(baseFee))
+ })
+
+ Context("during CheckTx", func() {
+ DescribeTable("should reject transactions with gasPrice < MinGasPrices",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ _, err := testutil.CheckEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil}
+ }),
+ Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(minGasPrices - 1_000_000_000), ðtypes.AccessList{}}
+ }),
+ )
+
+ DescribeTable("should reject transactions with MinGasPrices < tx gasPrice < EffectivePrice",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ _, err := testutil.CheckEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "insufficient fee"),
+ ).To(BeTrue(), err.Error())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(baseFee - 1_000_000_000), nil, nil, nil}
+ }),
+ Entry("dynamic tx", func() txParams {
+ return txParams{nil, big.NewInt(baseFee - 1_000_000_000), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ )
+
+ DescribeTable("should accept transactions with gasPrice >= EffectivePrice",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ res, err := testutil.CheckEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).To(BeNil(), "transaction should have succeeded")
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(baseFee), nil, nil, nil}
+ }),
+ Entry("dynamic tx", func() txParams {
+ return txParams{nil, big.NewInt(baseFee), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ )
+ })
+
+ Context("during DeliverTx", func() {
+ DescribeTable("should reject transactions with gasPrice < MinGasPrices",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ _, err := testutil.DeliverEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).ToNot(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "provided fee < minimum global fee"),
+ ).To(BeTrue(), err.Error())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil}
+ }),
+ Entry("dynamic tx", func() txParams {
+ return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), nil, ðtypes.AccessList{}}
+ }),
+ )
+
+ DescribeTable("should reject transactions with MinGasPrices < gasPrice < EffectivePrice",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ _, err := testutil.DeliverEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).NotTo(BeNil(), "transaction should have failed")
+ Expect(
+ strings.Contains(err.Error(),
+ "insufficient fee"),
+ ).To(BeTrue(), err.Error())
+ },
+ // Note that the baseFee is not 10_000_000_000 anymore but updates to 8_750_000_000 because of the s.Commit
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(baseFee - 2_000_000_000), nil, nil, nil}
+ }),
+ Entry("dynamic tx", func() txParams {
+ return txParams{nil, big.NewInt(baseFee - 2_000_000_000), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ )
+
+ DescribeTable("should accept transactions with gasPrice >= EffectivePrice",
+ func(malleate getprices) {
+ p := malleate()
+ to := utiltx.GenerateAddress()
+ msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
+ res, err := testutil.DeliverEthTx(s.app, privKey, msgEthereumTx)
+ Expect(err).To(BeNil())
+ Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
+ },
+ Entry("legacy tx", func() txParams {
+ return txParams{big.NewInt(baseFee), nil, nil, nil}
+ }),
+ Entry("dynamic tx", func() txParams {
+ return txParams{nil, big.NewInt(baseFee), big.NewInt(0), ðtypes.AccessList{}}
+ }),
+ )
+ })
+ })
+ })
+})
diff --git a/x/feemarket/keeper/keeper.go b/x/feemarket/keeper/keeper.go
new file mode 100644
index 00000000..dd9edcb8
--- /dev/null
+++ b/x/feemarket/keeper/keeper.go
@@ -0,0 +1,114 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ "github.com/cometbft/cometbft/libs/log"
+ "github.com/cosmos/cosmos-sdk/codec"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
+
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+// KeyPrefixBaseFeeV1 TODO: Temporary will be removed with params refactor PR
+var KeyPrefixBaseFeeV1 = []byte{2}
+
+// Keeper grants access to the Fee Market module state.
+type Keeper struct {
+ // Protobuf codec
+ cdc codec.BinaryCodec
+ // Store key required for the Fee Market Prefix KVStore.
+ storeKey storetypes.StoreKey
+ transientKey storetypes.StoreKey
+ // the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account.
+ authority sdk.AccAddress
+ // Legacy subspace
+ ss paramstypes.Subspace
+}
+
+// NewKeeper generates new fee market module keeper
+func NewKeeper(
+ cdc codec.BinaryCodec, authority sdk.AccAddress, storeKey, transientKey storetypes.StoreKey, ss paramstypes.Subspace,
+) Keeper {
+ // ensure authority account is correctly formatted
+ if err := sdk.VerifyAddressFormat(authority); err != nil {
+ panic(err)
+ }
+
+ return Keeper{
+ cdc: cdc,
+ storeKey: storeKey,
+ authority: authority,
+ transientKey: transientKey,
+ ss: ss,
+ }
+}
+
+// Logger returns a module-specific logger.
+func (k Keeper) Logger(ctx sdk.Context) log.Logger {
+ return ctx.Logger().With("module", types.ModuleName)
+}
+
+// ----------------------------------------------------------------------------
+// Parent Block Gas Used
+// Required by EIP1559 base fee calculation.
+// ----------------------------------------------------------------------------
+
+// SetBlockGasWanted sets the block gas wanted to the store.
+// CONTRACT: this should be only called during EndBlock.
+func (k Keeper) SetBlockGasWanted(ctx sdk.Context, gas uint64) {
+ store := ctx.KVStore(k.storeKey)
+ gasBz := sdk.Uint64ToBigEndian(gas)
+ store.Set(types.KeyPrefixBlockGasWanted, gasBz)
+}
+
+// GetBlockGasWanted returns the last block gas wanted value from the store.
+func (k Keeper) GetBlockGasWanted(ctx sdk.Context) uint64 {
+ store := ctx.KVStore(k.storeKey)
+ bz := store.Get(types.KeyPrefixBlockGasWanted)
+ if len(bz) == 0 {
+ return 0
+ }
+
+ return sdk.BigEndianToUint64(bz)
+}
+
+// GetTransientGasWanted returns the gas wanted in the current block from transient store.
+func (k Keeper) GetTransientGasWanted(ctx sdk.Context) uint64 {
+ store := ctx.TransientStore(k.transientKey)
+ bz := store.Get(types.KeyPrefixTransientBlockGasWanted)
+ if len(bz) == 0 {
+ return 0
+ }
+ return sdk.BigEndianToUint64(bz)
+}
+
+// SetTransientBlockGasWanted sets the block gas wanted to the transient store.
+func (k Keeper) SetTransientBlockGasWanted(ctx sdk.Context, gasWanted uint64) {
+ store := ctx.TransientStore(k.transientKey)
+ gasBz := sdk.Uint64ToBigEndian(gasWanted)
+ store.Set(types.KeyPrefixTransientBlockGasWanted, gasBz)
+}
+
+// AddTransientGasWanted adds the cumulative gas wanted in the transient store
+func (k Keeper) AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) {
+ result := k.GetTransientGasWanted(ctx) + gasWanted
+ k.SetTransientBlockGasWanted(ctx, result)
+ return result, nil
+}
+
+// GetBaseFeeV1 get the base fee from v1 version of states.
+// return nil if base fee is not enabled
+// TODO: Figure out if this will be deleted ?
+func (k Keeper) GetBaseFeeV1(ctx sdk.Context) *big.Int {
+ store := ctx.KVStore(k.storeKey)
+ bz := store.Get(KeyPrefixBaseFeeV1)
+ if len(bz) == 0 {
+ return nil
+ }
+ return new(big.Int).SetBytes(bz)
+}
diff --git a/x/feemarket/keeper/keeper_test.go b/x/feemarket/keeper/keeper_test.go
new file mode 100644
index 00000000..78bace63
--- /dev/null
+++ b/x/feemarket/keeper/keeper_test.go
@@ -0,0 +1,52 @@
+package keeper_test
+
+import (
+ "math/big"
+
+ "cosmossdk.io/math"
+)
+
+func (suite *KeeperTestSuite) TestSetGetBlockGasWanted() {
+ testCases := []struct {
+ name string
+ malleate func()
+ expGas uint64
+ }{
+ {
+ "with last block given",
+ func() {
+ suite.app.FeeMarketKeeper.SetBlockGasWanted(suite.ctx, uint64(1000000))
+ },
+ uint64(1000000),
+ },
+ }
+ for _, tc := range testCases {
+ tc.malleate()
+
+ gas := suite.app.FeeMarketKeeper.GetBlockGasWanted(suite.ctx)
+ suite.Require().Equal(tc.expGas, gas, tc.name)
+ }
+}
+
+func (suite *KeeperTestSuite) TestSetGetGasFee() {
+ testCases := []struct {
+ name string
+ malleate func()
+ expFee *big.Int
+ }{
+ {
+ "with last block given",
+ func() {
+ suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, math.LegacyOneDec().BigInt())
+ },
+ math.LegacyOneDec().BigInt(),
+ },
+ }
+
+ for _, tc := range testCases {
+ tc.malleate()
+
+ fee := suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx)
+ suite.Require().Equal(tc.expFee, fee, tc.name)
+ }
+}
diff --git a/x/feemarket/keeper/migrations.go b/x/feemarket/keeper/migrations.go
new file mode 100644
index 00000000..18dbf95c
--- /dev/null
+++ b/x/feemarket/keeper/migrations.go
@@ -0,0 +1,28 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ v4 "github.com/evmos/os/x/feemarket/migrations/v4"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+// Migrator is a struct for handling in-place store migrations.
+type Migrator struct {
+ keeper Keeper
+ legacySubspace types.Subspace
+}
+
+// NewMigrator returns a new Migrator.
+func NewMigrator(keeper Keeper, legacySubspace types.Subspace) Migrator {
+ return Migrator{
+ keeper: keeper,
+ legacySubspace: legacySubspace,
+ }
+}
+
+// Migrate3to4 migrates the store from consensus version 3 to 4
+func (m Migrator) Migrate3to4(ctx sdk.Context) error {
+ return v4.MigrateStore(ctx, m.keeper.storeKey, m.legacySubspace, m.keeper.cdc)
+}
diff --git a/x/feemarket/keeper/migrations_test.go b/x/feemarket/keeper/migrations_test.go
new file mode 100644
index 00000000..b50b4dec
--- /dev/null
+++ b/x/feemarket/keeper/migrations_test.go
@@ -0,0 +1,41 @@
+package keeper_test
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ feemarketkeeper "github.com/evmos/os/x/feemarket/keeper"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+type mockSubspace struct {
+ ps types.Params
+}
+
+func newMockSubspace(ps types.Params) mockSubspace {
+ return mockSubspace{ps: ps}
+}
+
+func (ms mockSubspace) GetParamSetIfExists(_ sdk.Context, ps types.LegacyParams) {
+ *ps.(*types.Params) = ms.ps
+}
+
+func (suite *KeeperTestSuite) TestMigrations() {
+ legacySubspace := newMockSubspace(types.DefaultParams())
+ migrator := feemarketkeeper.NewMigrator(suite.app.FeeMarketKeeper, legacySubspace)
+
+ testCases := []struct {
+ name string
+ migrateFunc func(ctx sdk.Context) error
+ }{
+ {
+ "Run Migrate3to4",
+ migrator.Migrate3to4,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ err := tc.migrateFunc(suite.ctx)
+ suite.Require().NoError(err)
+ })
+ }
+}
diff --git a/x/feemarket/keeper/msg_server.go b/x/feemarket/keeper/msg_server.go
new file mode 100644
index 00000000..007e2e55
--- /dev/null
+++ b/x/feemarket/keeper/msg_server.go
@@ -0,0 +1,29 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "context"
+
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+// UpdateParams implements the gRPC MsgServer interface. When an UpdateParams
+// proposal passes, it updates the module parameters. The update can only be
+// performed if the requested authority is the Cosmos SDK governance module
+// account.
+func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
+ if k.authority.String() != req.Authority {
+ return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority.String(), req.Authority)
+ }
+
+ ctx := sdk.UnwrapSDKContext(goCtx)
+ if err := k.SetParams(ctx, req.Params); err != nil {
+ return nil, err
+ }
+
+ return &types.MsgUpdateParamsResponse{}, nil
+}
diff --git a/x/feemarket/keeper/msg_server_test.go b/x/feemarket/keeper/msg_server_test.go
new file mode 100644
index 00000000..57b985c3
--- /dev/null
+++ b/x/feemarket/keeper/msg_server_test.go
@@ -0,0 +1,40 @@
+package keeper_test
+
+import (
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+func (suite *KeeperTestSuite) TestUpdateParams() {
+ testCases := []struct {
+ name string
+ request *types.MsgUpdateParams
+ expectErr bool
+ }{
+ {
+ name: "fail - invalid authority",
+ request: &types.MsgUpdateParams{Authority: "foobar"},
+ expectErr: true,
+ },
+ {
+ name: "pass - valid Update msg",
+ request: &types.MsgUpdateParams{
+ Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
+ Params: types.DefaultParams(),
+ },
+ expectErr: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run("MsgUpdateParams", func() {
+ _, err := suite.app.FeeMarketKeeper.UpdateParams(suite.ctx, tc.request)
+ if tc.expectErr {
+ suite.Require().Error(err)
+ } else {
+ suite.Require().NoError(err)
+ }
+ })
+ }
+}
diff --git a/x/feemarket/keeper/params.go b/x/feemarket/keeper/params.go
new file mode 100644
index 00000000..d70a8a09
--- /dev/null
+++ b/x/feemarket/keeper/params.go
@@ -0,0 +1,83 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package keeper
+
+import (
+ "math/big"
+
+ "cosmossdk.io/math"
+ "github.com/evmos/os/x/feemarket/types"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+// GetParams returns the total set of fee market parameters.
+func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
+ store := ctx.KVStore(k.storeKey)
+ bz := store.Get(types.ParamsKey)
+ if len(bz) == 0 {
+ k.ss.GetParamSetIfExists(ctx, ¶ms)
+ } else {
+ k.cdc.MustUnmarshal(bz, ¶ms)
+ }
+
+ // zero the nil params for legacy blocks
+ if params.MinGasPrice.IsNil() {
+ params.MinGasPrice = math.LegacyZeroDec()
+ }
+
+ if params.MinGasMultiplier.IsNil() {
+ params.MinGasMultiplier = math.LegacyZeroDec()
+ }
+
+ return
+}
+
+// SetParams sets the fee market params in a single key
+func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error {
+ store := ctx.KVStore(k.storeKey)
+ bz, err := k.cdc.Marshal(¶ms)
+ if err != nil {
+ return err
+ }
+
+ store.Set(types.ParamsKey, bz)
+
+ return nil
+}
+
+// ----------------------------------------------------------------------------
+// Parent Base Fee
+// Required by EIP1559 base fee calculation.
+// ----------------------------------------------------------------------------
+
+// GetBaseFeeEnabled returns true if base fee is enabled
+func (k Keeper) GetBaseFeeEnabled(ctx sdk.Context) bool {
+ params := k.GetParams(ctx)
+ return !params.NoBaseFee && ctx.BlockHeight() >= params.EnableHeight
+}
+
+// GetBaseFee gets the base fee from the store
+func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int {
+ params := k.GetParams(ctx)
+ if params.NoBaseFee {
+ return nil
+ }
+
+ baseFee := params.BaseFee.BigInt()
+ if baseFee == nil || baseFee.Sign() == 0 {
+ // try v1 format
+ return k.GetBaseFeeV1(ctx)
+ }
+ return baseFee
+}
+
+// SetBaseFee set's the base fee in the store
+func (k Keeper) SetBaseFee(ctx sdk.Context, baseFee *big.Int) {
+ params := k.GetParams(ctx)
+ params.BaseFee = math.NewIntFromBigInt(baseFee)
+ err := k.SetParams(ctx, params)
+ if err != nil {
+ return
+ }
+}
diff --git a/x/feemarket/keeper/params_test.go b/x/feemarket/keeper/params_test.go
new file mode 100644
index 00000000..a46e58a9
--- /dev/null
+++ b/x/feemarket/keeper/params_test.go
@@ -0,0 +1,82 @@
+package keeper_test
+
+import (
+ "reflect"
+
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+func (suite *KeeperTestSuite) TestGetParams() {
+ params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
+ suite.Require().NotNil(params.BaseFee)
+ suite.Require().NotNil(params.MinGasPrice)
+ suite.Require().NotNil(params.MinGasMultiplier)
+}
+
+func (suite *KeeperTestSuite) TestSetGetParams() {
+ params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
+ err := suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ testCases := []struct {
+ name string
+ paramsFun func() interface{}
+ getFun func() interface{}
+ expected bool
+ }{
+ {
+ "success - Checks if the default params are set correctly",
+ func() interface{} {
+ return types.DefaultParams()
+ },
+ func() interface{} {
+ return suite.app.FeeMarketKeeper.GetParams(suite.ctx)
+ },
+ true,
+ },
+ {
+ "success - Check ElasticityMultiplier is set to 3 and can be retrieved correctly",
+ func() interface{} {
+ params.ElasticityMultiplier = 3
+ err := suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ return params.ElasticityMultiplier
+ },
+ func() interface{} {
+ return suite.app.FeeMarketKeeper.GetParams(suite.ctx).ElasticityMultiplier
+ },
+ true,
+ },
+ {
+ "success - Check BaseFeeEnabled is computed with its default params and can be retrieved correctly",
+ func() interface{} {
+ err := suite.app.FeeMarketKeeper.SetParams(suite.ctx, types.DefaultParams())
+ suite.Require().NoError(err)
+ return true
+ },
+ func() interface{} {
+ return suite.app.FeeMarketKeeper.GetBaseFeeEnabled(suite.ctx)
+ },
+ true,
+ },
+ {
+ "success - Check BaseFeeEnabled is computed with alternate params and can be retrieved correctly",
+ func() interface{} {
+ params.NoBaseFee = true
+ params.EnableHeight = 5
+ err := suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
+ suite.Require().NoError(err)
+ return true
+ },
+ func() interface{} {
+ return suite.app.FeeMarketKeeper.GetBaseFeeEnabled(suite.ctx)
+ },
+ false,
+ },
+ }
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ outcome := reflect.DeepEqual(tc.paramsFun(), tc.getFun())
+ suite.Require().Equal(tc.expected, outcome)
+ })
+ }
+}
diff --git a/x/feemarket/keeper/setup_test.go b/x/feemarket/keeper/setup_test.go
new file mode 100644
index 00000000..05518124
--- /dev/null
+++ b/x/feemarket/keeper/setup_test.go
@@ -0,0 +1,58 @@
+package keeper_test
+
+import (
+ "testing"
+
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/ginkgo/v2"
+ //nolint:revive // dot imports are fine for Ginkgo
+ . "github.com/onsi/gomega"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/codec"
+ "github.com/cosmos/cosmos-sdk/crypto/keyring"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ app "github.com/evmos/os/example_chain"
+ "github.com/evmos/os/utils"
+ "github.com/evmos/os/x/feemarket/types"
+ "github.com/stretchr/testify/suite"
+)
+
+type KeeperTestSuite struct {
+ suite.Suite
+
+ ctx sdk.Context
+ app *app.ExampleChain
+ queryClient types.QueryClient
+ address common.Address
+ consAddress sdk.ConsAddress
+
+ // for generate test tx
+ clientCtx client.Context
+ ethSigner ethtypes.Signer
+
+ appCodec codec.Codec
+ signer keyring.Signer
+ denom string
+}
+
+var s *KeeperTestSuite
+
+func TestKeeperTestSuite(t *testing.T) {
+ s = new(KeeperTestSuite)
+ suite.Run(t, s)
+
+ // Run Ginkgo integration tests
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Keeper Suite")
+}
+
+// SetupTest setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
+func (suite *KeeperTestSuite) SetupTest() {
+ checkTx := false
+ chainID := utils.TestnetChainID + "-1"
+ suite.app = app.Setup(checkTx, nil, chainID)
+ suite.SetupApp(checkTx, chainID)
+}
diff --git a/x/feemarket/keeper/utils_test.go b/x/feemarket/keeper/utils_test.go
new file mode 100644
index 00000000..4478e301
--- /dev/null
+++ b/x/feemarket/keeper/utils_test.go
@@ -0,0 +1,210 @@
+package keeper_test
+
+import (
+ "encoding/json"
+ "math/big"
+ "time"
+
+ "cosmossdk.io/math"
+ dbm "github.com/cometbft/cometbft-db"
+ abci "github.com/cometbft/cometbft/abci/types"
+ "github.com/cometbft/cometbft/libs/log"
+ "github.com/cosmos/cosmos-sdk/baseapp"
+ "github.com/cosmos/cosmos-sdk/client"
+ simutils "github.com/cosmos/cosmos-sdk/testutil/sims"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
+ stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+ "github.com/ethereum/go-ethereum/common"
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/evmos/evmos/v19/testutil"
+ "github.com/evmos/os/crypto/ethsecp256k1"
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+ utiltx "github.com/evmos/os/testutil/tx"
+ "github.com/evmos/os/utils"
+ evmtypes "github.com/evmos/os/x/evm/types"
+ "github.com/evmos/os/x/feemarket/types"
+ "github.com/stretchr/testify/require"
+)
+
+func (suite *KeeperTestSuite) SetupApp(checkTx bool, chainID string) {
+ t := suite.T()
+ // account key
+ priv, err := ethsecp256k1.GenerateKey()
+ require.NoError(t, err)
+ suite.address = common.BytesToAddress(priv.PubKey().Address().Bytes())
+ suite.signer = utiltx.NewSigner(priv)
+
+ // consensus key
+ priv, err = ethsecp256k1.GenerateKey()
+ require.NoError(t, err)
+ suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())
+
+ header := testutil.NewHeader(
+ 1, time.Now().UTC(), chainID, suite.consAddress, nil, nil,
+ )
+
+ suite.ctx = suite.app.BaseApp.NewContext(checkTx, header)
+
+ queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
+ types.RegisterQueryServer(queryHelper, suite.app.FeeMarketKeeper)
+ suite.queryClient = types.NewQueryClient(queryHelper)
+
+ acc := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0)
+ suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
+
+ valAddr := sdk.ValAddress(suite.address.Bytes())
+ validator, err := stakingtypes.NewValidator(valAddr, priv.PubKey(), stakingtypes.Description{})
+ require.NoError(t, err)
+ validator = stakingkeeper.TestingUpdateValidator(suite.app.StakingKeeper.Keeper, suite.ctx, validator, true)
+ err = suite.app.StakingKeeper.Hooks().AfterValidatorCreated(suite.ctx, validator.GetOperator())
+ require.NoError(t, err)
+
+ err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
+ require.NoError(t, err)
+ suite.app.StakingKeeper.SetValidator(suite.ctx, validator)
+
+ stakingParams := stakingtypes.DefaultParams()
+ stakingParams.BondDenom = utils.BaseDenom
+ err = suite.app.StakingKeeper.SetParams(suite.ctx, stakingParams)
+ require.NoError(t, err)
+
+ encodingConfig := encoding.MakeConfig(example_app.ModuleBasics)
+ suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
+ suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
+ suite.appCodec = encodingConfig.Codec
+ suite.denom = evmtypes.DefaultEVMDenom
+}
+
+// Commit commits and starts a new block with an updated context.
+func (suite *KeeperTestSuite) Commit() {
+ suite.CommitAfter(time.Second * 0)
+}
+
+// Commit commits a block at a given time.
+func (suite *KeeperTestSuite) CommitAfter(t time.Duration) {
+ var err error
+ suite.ctx, err = testutil.CommitAndCreateNewCtx(suite.ctx, suite.app, t, nil)
+ suite.Require().NoError(err)
+ queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
+ types.RegisterQueryServer(queryHelper, suite.app.FeeMarketKeeper)
+ suite.queryClient = types.NewQueryClient(queryHelper)
+}
+
+// setupTestWithContext sets up a test chain with an example Cosmos send msg,
+// given a local (validator config) and a global (feemarket param) minGasPrice
+//
+//nolint:unparam
+func setupTestWithContext(chainID, valMinGasPrice string, minGasPrice math.LegacyDec, baseFee math.Int) (*ethsecp256k1.PrivKey, banktypes.MsgSend) {
+ privKey, msg := setupTest(valMinGasPrice+s.denom, chainID)
+ params := types.DefaultParams()
+ params.MinGasPrice = minGasPrice
+ err := s.app.FeeMarketKeeper.SetParams(s.ctx, params)
+ s.Require().NoError(err)
+ s.app.FeeMarketKeeper.SetBaseFee(s.ctx, baseFee.BigInt())
+ s.Commit()
+
+ return privKey, msg
+}
+
+func setupTest(localMinGasPrices, chainID string) (*ethsecp256k1.PrivKey, banktypes.MsgSend) {
+ setupChain(localMinGasPrices, chainID)
+
+ address, privKey := utiltx.NewAccAddressAndKey()
+ amount, ok := math.NewIntFromString("10000000000000000000")
+ s.Require().True(ok)
+ initBalance := sdk.Coins{sdk.Coin{
+ Denom: s.denom,
+ Amount: amount,
+ }}
+ err := testutil.FundAccount(s.ctx, s.app.BankKeeper, address, initBalance)
+ s.Require().NoError(err)
+
+ msg := banktypes.MsgSend{
+ FromAddress: address.String(),
+ ToAddress: address.String(),
+ Amount: sdk.Coins{sdk.Coin{
+ Denom: s.denom,
+ Amount: math.NewInt(10000),
+ }},
+ }
+ s.Commit()
+ return privKey, msg
+}
+
+func setupChain(localMinGasPricesStr string, chainID string) {
+ // Initialize the app, so we can use SetMinGasPrices to set the
+ // validator-specific min-gas-prices setting
+ db := dbm.NewMemDB()
+ newapp := example_app.NewEvmos(
+ log.NewNopLogger(),
+ db,
+ nil,
+ true,
+ map[int64]bool{},
+ example_app.DefaultNodeHome,
+ 5,
+ encoding.MakeConfig(example_app.ModuleBasics),
+ simutils.NewAppOptionsWithFlagHome(example_app.DefaultNodeHome),
+ baseapp.SetChainID(chainID),
+ baseapp.SetMinGasPrices(localMinGasPricesStr),
+ )
+
+ genesisState := example_app.NewTestGenesisState(newapp.AppCodec())
+ genesisState[types.ModuleName] = newapp.AppCodec().MustMarshalJSON(types.DefaultGenesisState())
+
+ stateBytes, err := json.MarshalIndent(genesisState, "", " ")
+ s.Require().NoError(err)
+
+ // Initialize the chain
+ newapp.InitChain(
+ abci.RequestInitChain{
+ ChainId: chainID,
+ Validators: []abci.ValidatorUpdate{},
+ AppStateBytes: stateBytes,
+ ConsensusParams: example_app.DefaultConsensusParams,
+ },
+ )
+
+ s.app = newapp
+ s.SetupApp(false, chainID)
+}
+
+func getNonce(addressBytes []byte) uint64 {
+ return s.app.EvmKeeper.GetNonce(
+ s.ctx,
+ common.BytesToAddress(addressBytes),
+ )
+}
+
+func buildEthTx(
+ priv *ethsecp256k1.PrivKey,
+ to *common.Address,
+ gasPrice *big.Int,
+ gasFeeCap *big.Int,
+ gasTipCap *big.Int,
+ accesses *ethtypes.AccessList,
+) *evmtypes.MsgEthereumTx {
+ chainID := s.app.EvmKeeper.ChainID()
+ from := common.BytesToAddress(priv.PubKey().Address().Bytes())
+ nonce := getNonce(from.Bytes())
+ data := make([]byte, 0)
+ gasLimit := uint64(100000)
+ ethTxParams := &evmtypes.EvmTxArgs{
+ ChainID: chainID,
+ Nonce: nonce,
+ To: to,
+ GasLimit: gasLimit,
+ GasPrice: gasPrice,
+ GasFeeCap: gasFeeCap,
+ GasTipCap: gasTipCap,
+ Input: data,
+ Accesses: accesses,
+ }
+ msgEthereumTx := evmtypes.NewTx(ethTxParams)
+ msgEthereumTx.From = from.String()
+ return msgEthereumTx
+}
diff --git a/x/feemarket/migrations/v4/migrate.go b/x/feemarket/migrations/v4/migrate.go
new file mode 100644
index 00000000..be3e0f42
--- /dev/null
+++ b/x/feemarket/migrations/v4/migrate.go
@@ -0,0 +1,40 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package v4
+
+import (
+ "github.com/cosmos/cosmos-sdk/codec"
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+// MigrateStore migrates the x/evm module state from the consensus version 3 to
+// version 4. Specifically, it takes the parameters that are currently stored
+// and managed by the Cosmos SDK params module and stores them directly into the x/evm module state.
+func MigrateStore(
+ ctx sdk.Context,
+ storeKey storetypes.StoreKey,
+ legacySubspace types.Subspace,
+ cdc codec.BinaryCodec,
+) error {
+ var (
+ store = ctx.KVStore(storeKey)
+ params types.Params
+ )
+
+ legacySubspace.GetParamSetIfExists(ctx, ¶ms)
+
+ if err := params.Validate(); err != nil {
+ return err
+ }
+
+ bz, err := cdc.Marshal(¶ms)
+ if err != nil {
+ return err
+ }
+
+ store.Set(types.ParamsKey, bz)
+
+ return nil
+}
diff --git a/x/feemarket/migrations/v4/migrate_test.go b/x/feemarket/migrations/v4/migrate_test.go
new file mode 100644
index 00000000..8aa0622c
--- /dev/null
+++ b/x/feemarket/migrations/v4/migrate_test.go
@@ -0,0 +1,66 @@
+// Copyright 2022 Evmos Foundation
+// This file is part of the Evmos Network packages.
+//
+// Evmos is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Evmos packages are distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE
+package v4_test
+
+import (
+ "testing"
+
+ "github.com/cosmos/cosmos-sdk/testutil"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/evmos/os/encoding"
+ example_app "github.com/evmos/os/example_chain"
+ v4 "github.com/evmos/os/x/feemarket/migrations/v4"
+ "github.com/evmos/os/x/feemarket/types"
+ "github.com/stretchr/testify/require"
+)
+
+type mockSubspace struct {
+ ps types.Params
+}
+
+func newMockSubspaceEmpty() mockSubspace {
+ return mockSubspace{}
+}
+
+func newMockSubspace(ps types.Params) mockSubspace {
+ return mockSubspace{ps: ps}
+}
+
+func (ms mockSubspace) GetParamSetIfExists(_ sdk.Context, ps types.LegacyParams) {
+ *ps.(*types.Params) = ms.ps
+}
+
+func TestMigrate(t *testing.T) {
+ encCfg := encoding.MakeConfig(example_app.ModuleBasics)
+ cdc := encCfg.Codec
+
+ storeKey := sdk.NewKVStoreKey(types.ModuleName)
+ tKey := sdk.NewTransientStoreKey("transient_test")
+ ctx := testutil.DefaultContext(storeKey, tKey)
+ kvStore := ctx.KVStore(storeKey)
+
+ legacySubspaceEmpty := newMockSubspaceEmpty()
+ require.Error(t, v4.MigrateStore(ctx, storeKey, legacySubspaceEmpty, cdc))
+
+ legacySubspace := newMockSubspace(types.DefaultParams())
+ require.NoError(t, v4.MigrateStore(ctx, storeKey, legacySubspace, cdc))
+
+ paramsBz := kvStore.Get(types.ParamsKey)
+ var params types.Params
+ cdc.MustUnmarshal(paramsBz, ¶ms)
+
+ require.Equal(t, params, legacySubspace.ps)
+}
diff --git a/x/feemarket/migrations/v4/types/feemarket.pb.go b/x/feemarket/migrations/v4/types/feemarket.pb.go
new file mode 100644
index 00000000..df2f2ac8
--- /dev/null
+++ b/x/feemarket/migrations/v4/types/feemarket.pb.go
@@ -0,0 +1,592 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/feemarket/v1/feemarket.proto
+
+package types
+
+import (
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ cosmossdk_io_math "cosmossdk.io/math"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ proto "github.com/cosmos/gogoproto/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = proto.Marshal
+ _ = fmt.Errorf
+ _ = math.Inf
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// Params defines the EVM module parameters
+type Params struct {
+ // no_base_fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
+ NoBaseFee bool `protobuf:"varint,1,opt,name=no_base_fee,json=noBaseFee,proto3" json:"no_base_fee,omitempty"`
+ // base_fee_change_denominator bounds the amount the base fee can change
+ // between blocks.
+ BaseFeeChangeDenominator uint32 `protobuf:"varint,2,opt,name=base_fee_change_denominator,json=baseFeeChangeDenominator,proto3" json:"base_fee_change_denominator,omitempty"`
+ // elasticity_multiplier bounds the maximum gas limit an EIP-1559 block may
+ // have.
+ ElasticityMultiplier uint32 `protobuf:"varint,3,opt,name=elasticity_multiplier,json=elasticityMultiplier,proto3" json:"elasticity_multiplier,omitempty"`
+ // enable_height defines at which block height the base fee calculation is enabled.
+ EnableHeight int64 `protobuf:"varint,5,opt,name=enable_height,json=enableHeight,proto3" json:"enable_height,omitempty"`
+ // base_fee for EIP-1559 blocks.
+ BaseFee cosmossdk_io_math.Int `protobuf:"bytes,6,opt,name=base_fee,json=baseFee,proto3,customtype=cosmossdk.io/math.Int" json:"base_fee"`
+ // min_gas_price defines the minimum gas price value for cosmos and eth transactions
+ MinGasPrice cosmossdk_io_math.LegacyDec `protobuf:"bytes,7,opt,name=min_gas_price,json=minGasPrice,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"min_gas_price"`
+ // min_gas_multiplier bounds the minimum gas used to be charged
+ // to senders based on gas limit
+ MinGasMultiplier cosmossdk_io_math.LegacyDec `protobuf:"bytes,8,opt,name=min_gas_multiplier,json=minGasMultiplier,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"min_gas_multiplier"`
+}
+
+func (m *Params) Reset() { *m = Params{} }
+func (m *Params) String() string { return proto.CompactTextString(m) }
+func (*Params) ProtoMessage() {}
+func (*Params) Descriptor() ([]byte, []int) {
+ return fileDescriptor_4feb8b20cf98e6e1, []int{0}
+}
+
+func (m *Params) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+
+func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Params.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+
+func (m *Params) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Params.Merge(m, src)
+}
+
+func (m *Params) XXX_Size() int {
+ return m.Size()
+}
+
+func (m *Params) XXX_DiscardUnknown() {
+ xxx_messageInfo_Params.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Params proto.InternalMessageInfo
+
+func (m *Params) GetNoBaseFee() bool {
+ if m != nil {
+ return m.NoBaseFee
+ }
+ return false
+}
+
+func (m *Params) GetBaseFeeChangeDenominator() uint32 {
+ if m != nil {
+ return m.BaseFeeChangeDenominator
+ }
+ return 0
+}
+
+func (m *Params) GetElasticityMultiplier() uint32 {
+ if m != nil {
+ return m.ElasticityMultiplier
+ }
+ return 0
+}
+
+func (m *Params) GetEnableHeight() int64 {
+ if m != nil {
+ return m.EnableHeight
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Params)(nil), "ethermint.feemarket.v1.Params")
+}
+
+func init() {
+ proto.RegisterFile("ethermint/feemarket/v1/feemarket.proto", fileDescriptor_4feb8b20cf98e6e1)
+}
+
+var fileDescriptor_4feb8b20cf98e6e1 = []byte{
+ // 388 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xc1, 0x8a, 0xdb, 0x30,
+ 0x14, 0xb4, 0x9a, 0xdd, 0xac, 0x57, 0xdb, 0x40, 0x10, 0xdb, 0x62, 0x5a, 0xf0, 0x9a, 0x16, 0x16,
+ 0x1f, 0x5a, 0x9b, 0x65, 0xcf, 0xbd, 0xa4, 0x21, 0x6d, 0x0a, 0x85, 0xe0, 0x63, 0x29, 0x08, 0xd9,
+ 0x79, 0xb1, 0x45, 0x2c, 0xc9, 0x58, 0x4a, 0x68, 0xfe, 0xa2, 0x9f, 0x95, 0x63, 0x4e, 0xa5, 0xf4,
+ 0x10, 0x4a, 0xf2, 0x23, 0x25, 0x76, 0x62, 0xe7, 0xda, 0x3d, 0x49, 0x7a, 0x33, 0x9a, 0x79, 0xd2,
+ 0x1b, 0x7c, 0x0f, 0x26, 0x83, 0x52, 0x70, 0x69, 0xc2, 0x19, 0x80, 0x60, 0xe5, 0x1c, 0x4c, 0xb8,
+ 0x7c, 0x68, 0x0f, 0x41, 0x51, 0x2a, 0xa3, 0xc8, 0xcb, 0x86, 0x17, 0xb4, 0xd0, 0xf2, 0xe1, 0xd5,
+ 0x6d, 0xaa, 0x52, 0x55, 0x51, 0xc2, 0xc3, 0xae, 0x66, 0xbf, 0xf9, 0xd5, 0xc1, 0xdd, 0x09, 0x2b,
+ 0x99, 0xd0, 0xc4, 0xc5, 0x37, 0x52, 0xd1, 0x98, 0x69, 0xa0, 0x33, 0x00, 0x07, 0x79, 0xc8, 0xb7,
+ 0xa3, 0x6b, 0xa9, 0x06, 0x4c, 0xc3, 0x08, 0x80, 0x7c, 0xc0, 0xaf, 0x4f, 0x20, 0x4d, 0x32, 0x26,
+ 0x53, 0xa0, 0x53, 0x90, 0x4a, 0x70, 0xc9, 0x8c, 0x2a, 0x9d, 0x67, 0x1e, 0xf2, 0x7b, 0x91, 0x13,
+ 0xd7, 0xec, 0x8f, 0x15, 0x61, 0xd8, 0xe2, 0xe4, 0x11, 0xbf, 0x80, 0x9c, 0x69, 0xc3, 0x13, 0x6e,
+ 0x56, 0x54, 0x2c, 0x72, 0xc3, 0x8b, 0x9c, 0x43, 0xe9, 0x74, 0xaa, 0x8b, 0xb7, 0x2d, 0xf8, 0xb5,
+ 0xc1, 0xc8, 0x5b, 0xdc, 0x03, 0xc9, 0xe2, 0x1c, 0x68, 0x06, 0x3c, 0xcd, 0x8c, 0x73, 0xe9, 0x21,
+ 0xbf, 0x13, 0x3d, 0xaf, 0x8b, 0x9f, 0xab, 0x1a, 0x19, 0x63, 0xbb, 0xe9, 0xba, 0xeb, 0x21, 0xff,
+ 0x7a, 0x10, 0xac, 0xb7, 0x77, 0xd6, 0x9f, 0xed, 0xdd, 0x7d, 0xca, 0x4d, 0xb6, 0x88, 0x83, 0x44,
+ 0x89, 0x30, 0x51, 0x5a, 0x28, 0x7d, 0x5c, 0xde, 0xeb, 0xe9, 0x3c, 0x34, 0xab, 0x02, 0x74, 0x30,
+ 0x96, 0x26, 0xba, 0x3a, 0x76, 0x4d, 0x22, 0xdc, 0x13, 0x5c, 0xd2, 0x94, 0x69, 0x5a, 0x94, 0x3c,
+ 0x01, 0xe7, 0xea, 0xbf, 0xf5, 0x86, 0x90, 0x44, 0x37, 0x82, 0xcb, 0x4f, 0x4c, 0x4f, 0x0e, 0x12,
+ 0xe4, 0x3b, 0x26, 0x27, 0xcd, 0xb3, 0x57, 0xdb, 0x4f, 0x12, 0xee, 0xd7, 0xc2, 0xed, 0x0f, 0x7d,
+ 0xb9, 0xb0, 0x2f, 0xfa, 0x97, 0x51, 0x9f, 0x4b, 0x6e, 0x38, 0xcb, 0x9b, 0xf1, 0x0d, 0x46, 0xeb,
+ 0x9d, 0x8b, 0x36, 0x3b, 0x17, 0xfd, 0xdd, 0xb9, 0xe8, 0xe7, 0xde, 0xb5, 0x36, 0x7b, 0xd7, 0xfa,
+ 0xbd, 0x77, 0xad, 0x6f, 0xef, 0xce, 0xbc, 0x60, 0x79, 0xb0, 0x6a, 0x93, 0xf5, 0xe3, 0x2c, 0x5b,
+ 0x95, 0x6b, 0xdc, 0xad, 0x72, 0xf2, 0xf8, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xa5, 0xce, 0xeb, 0x97,
+ 0x7f, 0x02, 0x00, 0x00,
+}
+
+func (m *Params) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Params) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size := m.MinGasMultiplier.Size()
+ i -= size
+ if _, err := m.MinGasMultiplier.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintFeemarket(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x42
+ {
+ size := m.MinGasPrice.Size()
+ i -= size
+ if _, err := m.MinGasPrice.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintFeemarket(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x3a
+ {
+ size := m.BaseFee.Size()
+ i -= size
+ if _, err := m.BaseFee.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintFeemarket(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x32
+ if m.EnableHeight != 0 {
+ i = encodeVarintFeemarket(dAtA, i, uint64(m.EnableHeight))
+ i--
+ dAtA[i] = 0x28
+ }
+ if m.ElasticityMultiplier != 0 {
+ i = encodeVarintFeemarket(dAtA, i, uint64(m.ElasticityMultiplier))
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.BaseFeeChangeDenominator != 0 {
+ i = encodeVarintFeemarket(dAtA, i, uint64(m.BaseFeeChangeDenominator))
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.NoBaseFee {
+ i--
+ if m.NoBaseFee {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintFeemarket(dAtA []byte, offset int, v uint64) int {
+ offset -= sovFeemarket(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+
+func (m *Params) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.NoBaseFee {
+ n += 2
+ }
+ if m.BaseFeeChangeDenominator != 0 {
+ n += 1 + sovFeemarket(uint64(m.BaseFeeChangeDenominator))
+ }
+ if m.ElasticityMultiplier != 0 {
+ n += 1 + sovFeemarket(uint64(m.ElasticityMultiplier))
+ }
+ if m.EnableHeight != 0 {
+ n += 1 + sovFeemarket(uint64(m.EnableHeight))
+ }
+ l = m.BaseFee.Size()
+ n += 1 + l + sovFeemarket(uint64(l))
+ l = m.MinGasPrice.Size()
+ n += 1 + l + sovFeemarket(uint64(l))
+ l = m.MinGasMultiplier.Size()
+ n += 1 + l + sovFeemarket(uint64(l))
+ return n
+}
+
+func sovFeemarket(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+
+func sozFeemarket(x uint64) (n int) {
+ return sovFeemarket(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+func (m *Params) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Params: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NoBaseFee", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.NoBaseFee = bool(v != 0)
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BaseFeeChangeDenominator", wireType)
+ }
+ m.BaseFeeChangeDenominator = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BaseFeeChangeDenominator |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ElasticityMultiplier", wireType)
+ }
+ m.ElasticityMultiplier = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ElasticityMultiplier |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EnableHeight", wireType)
+ }
+ m.EnableHeight = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.EnableHeight |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BaseFee", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.BaseFee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MinGasPrice", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.MinGasPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MinGasMultiplier", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.MinGasMultiplier.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipFeemarket(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+func skipFeemarket(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthFeemarket
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupFeemarket
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthFeemarket
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthFeemarket = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowFeemarket = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupFeemarket = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/feemarket/migrations/v4/types/params.go b/x/feemarket/migrations/v4/types/params.go
new file mode 100644
index 00000000..d26a5789
--- /dev/null
+++ b/x/feemarket/migrations/v4/types/params.go
@@ -0,0 +1,203 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "fmt"
+
+ "github.com/evmos/os/x/feemarket/types"
+
+ "cosmossdk.io/math"
+ paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var _ types.LegacyParams = &Params{}
+
+// Parameter keys
+var (
+ ParamsKey = []byte("Params")
+ ParamStoreKeyNoBaseFee = []byte("NoBaseFee")
+ ParamStoreKeyBaseFeeChangeDenominator = []byte("BaseFeeChangeDenominator")
+ ParamStoreKeyElasticityMultiplier = []byte("ElasticityMultiplier")
+ ParamStoreKeyBaseFee = []byte("BaseFee")
+ ParamStoreKeyEnableHeight = []byte("EnableHeight")
+ ParamStoreKeyMinGasPrice = []byte("MinGasPrice")
+ ParamStoreKeyMinGasMultiplier = []byte("MinGasMultiplier")
+)
+
+var (
+ // DefaultMinGasMultiplier is 0.5 or 50%
+ DefaultMinGasMultiplier = math.LegacyNewDecWithPrec(50, 2)
+ // DefaultMinGasPrice is 0 (i.e disabled)
+ DefaultMinGasPrice = math.LegacyZeroDec()
+ DefaultEnableHeight = int64(0)
+ DefaultNoBaseFee = false
+)
+
+// ParamKeyTable returns the parameter key table.
+func ParamKeyTable() paramtypes.KeyTable {
+ return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
+}
+
+// ParamSetPairs returns the parameter set pairs.
+func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
+ return paramtypes.ParamSetPairs{
+ paramtypes.NewParamSetPair(ParamStoreKeyNoBaseFee, &p.NoBaseFee, validateBool),
+ paramtypes.NewParamSetPair(ParamStoreKeyBaseFeeChangeDenominator, &p.BaseFeeChangeDenominator, validateBaseFeeChangeDenominator),
+ paramtypes.NewParamSetPair(ParamStoreKeyElasticityMultiplier, &p.ElasticityMultiplier, validateElasticityMultiplier),
+ paramtypes.NewParamSetPair(ParamStoreKeyBaseFee, &p.BaseFee, validateBaseFee),
+ paramtypes.NewParamSetPair(ParamStoreKeyEnableHeight, &p.EnableHeight, validateEnableHeight),
+ paramtypes.NewParamSetPair(ParamStoreKeyMinGasPrice, &p.MinGasPrice, validateMinGasPrice),
+ paramtypes.NewParamSetPair(ParamStoreKeyMinGasMultiplier, &p.MinGasMultiplier, validateMinGasPrice),
+ }
+}
+
+// NewParams creates a new Params instance
+func NewParams(
+ noBaseFee bool,
+ baseFeeChangeDenom,
+ elasticityMultiplier uint32,
+ baseFee uint64,
+ enableHeight int64,
+ minGasPrice math.LegacyDec,
+ minGasPriceMultiplier math.LegacyDec,
+) Params {
+ return Params{
+ NoBaseFee: noBaseFee,
+ BaseFeeChangeDenominator: baseFeeChangeDenom,
+ ElasticityMultiplier: elasticityMultiplier,
+ BaseFee: math.NewIntFromUint64(baseFee),
+ EnableHeight: enableHeight,
+ MinGasPrice: minGasPrice,
+ MinGasMultiplier: minGasPriceMultiplier,
+ }
+}
+
+// DefaultParams returns default evm parameters
+func DefaultParams() Params {
+ return Params{
+ NoBaseFee: DefaultNoBaseFee,
+ BaseFeeChangeDenominator: params.BaseFeeChangeDenominator,
+ ElasticityMultiplier: params.ElasticityMultiplier,
+ BaseFee: math.NewIntFromUint64(params.InitialBaseFee),
+ EnableHeight: DefaultEnableHeight,
+ MinGasPrice: DefaultMinGasPrice,
+ MinGasMultiplier: DefaultMinGasMultiplier,
+ }
+}
+
+// Validate performs basic validation on fee market parameters.
+func (p Params) Validate() error {
+ if p.BaseFeeChangeDenominator == 0 {
+ return fmt.Errorf("base fee change denominator cannot be 0")
+ }
+
+ if p.BaseFee.IsNegative() {
+ return fmt.Errorf("initial base fee cannot be negative: %s", p.BaseFee)
+ }
+
+ if p.EnableHeight < 0 {
+ return fmt.Errorf("enable height cannot be negative: %d", p.EnableHeight)
+ }
+
+ if err := validateMinGasMultiplier(p.MinGasMultiplier); err != nil {
+ return err
+ }
+
+ return validateMinGasPrice(p.MinGasPrice)
+}
+
+func validateBool(i interface{}) error {
+ _, ok := i.(bool)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+ return nil
+}
+
+func validateBaseFeeChangeDenominator(i interface{}) error {
+ value, ok := i.(uint32)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if value == 0 {
+ return fmt.Errorf("base fee change denominator cannot be 0")
+ }
+
+ return nil
+}
+
+func validateElasticityMultiplier(i interface{}) error {
+ _, ok := i.(uint32)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+ return nil
+}
+
+func validateBaseFee(i interface{}) error {
+ value, ok := i.(math.Int)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if value.IsNegative() {
+ return fmt.Errorf("base fee cannot be negative")
+ }
+
+ return nil
+}
+
+func validateEnableHeight(i interface{}) error {
+ value, ok := i.(int64)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if value < 0 {
+ return fmt.Errorf("enable height cannot be negative: %d", value)
+ }
+
+ return nil
+}
+
+func validateMinGasPrice(i interface{}) error {
+ v, ok := i.(math.LegacyDec)
+
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if v.IsNil() {
+ return fmt.Errorf("invalid parameter: nil")
+ }
+
+ if v.IsNegative() {
+ return fmt.Errorf("value cannot be negative: %s", i)
+ }
+
+ return nil
+}
+
+func validateMinGasMultiplier(i interface{}) error {
+ v, ok := i.(math.LegacyDec)
+
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if v.IsNil() {
+ return fmt.Errorf("invalid parameter: nil")
+ }
+
+ if v.IsNegative() {
+ return fmt.Errorf("value cannot be negative: %s", v)
+ }
+
+ if v.GT(math.LegacyOneDec()) {
+ return fmt.Errorf("value cannot be greater than 1: %s", v)
+ }
+ return nil
+}
diff --git a/x/feemarket/module.go b/x/feemarket/module.go
new file mode 100644
index 00000000..92571a0c
--- /dev/null
+++ b/x/feemarket/module.go
@@ -0,0 +1,177 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package feemarket
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+
+ "github.com/gorilla/mux"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/spf13/cobra"
+
+ abci "github.com/cometbft/cometbft/abci/types"
+
+ "github.com/cosmos/cosmos-sdk/client"
+ "github.com/cosmos/cosmos-sdk/codec"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/module"
+ simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
+
+ "github.com/evmos/os/x/feemarket/client/cli"
+ "github.com/evmos/os/x/feemarket/keeper"
+ "github.com/evmos/os/x/feemarket/types"
+)
+
+// consensusVersion defines the current x/feemarket module consensus version.
+const consensusVersion = 4
+
+var (
+ _ module.AppModule = AppModule{}
+ _ module.AppModuleBasic = AppModuleBasic{}
+ _ module.EndBlockAppModule = AppModule{}
+ _ module.BeginBlockAppModule = AppModule{}
+)
+
+// AppModuleBasic defines the basic application module used by the fee market module.
+type AppModuleBasic struct{}
+
+// Name returns the fee market module's name.
+func (AppModuleBasic) Name() string {
+ return types.ModuleName
+}
+
+// RegisterLegacyAminoCodec performs a no-op as the fee market module doesn't support amino.
+func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
+ types.RegisterLegacyAminoCodec(cdc)
+}
+
+// ConsensusVersion returns the consensus state-breaking version for the module.
+func (AppModuleBasic) ConsensusVersion() uint64 {
+ return consensusVersion
+}
+
+// DefaultGenesis returns default genesis state as raw bytes for the fee market
+// module.
+func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
+ return cdc.MustMarshalJSON(types.DefaultGenesisState())
+}
+
+// ValidateGenesis is the validation check of the Genesis
+func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error {
+ var genesisState types.GenesisState
+ if err := cdc.UnmarshalJSON(bz, &genesisState); err != nil {
+ return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
+ }
+
+ return genesisState.Validate()
+}
+
+// RegisterRESTRoutes performs a no-op as the EVM module doesn't expose REST
+// endpoints
+func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {
+}
+
+func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) {
+ if err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(c)); err != nil {
+ panic(err)
+ }
+}
+
+// GetTxCmd returns the root tx command for the fee market module.
+func (AppModuleBasic) GetTxCmd() *cobra.Command {
+ return nil
+}
+
+// GetQueryCmd returns no root query command for the fee market module.
+func (AppModuleBasic) GetQueryCmd() *cobra.Command {
+ return cli.GetQueryCmd()
+}
+
+// RegisterInterfaces registers interfaces and implementations of the fee market module.
+func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
+ types.RegisterInterfaces(registry)
+}
+
+// ____________________________________________________________________________
+
+// AppModule implements an application module for the fee market module.
+type AppModule struct {
+ AppModuleBasic
+ keeper keeper.Keeper
+ // legacySubspace is used solely for migration of x/params managed parameters
+ legacySubspace types.Subspace
+}
+
+// NewAppModule creates a new AppModule object
+func NewAppModule(k keeper.Keeper, ss types.Subspace) AppModule {
+ return AppModule{
+ AppModuleBasic: AppModuleBasic{},
+ keeper: k,
+ legacySubspace: ss,
+ }
+}
+
+// Name returns the fee market module's name.
+func (AppModule) Name() string {
+ return types.ModuleName
+}
+
+// RegisterInvariants interface for registering invariants. Performs a no-op
+// as the fee market module doesn't expose invariants.
+func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
+
+// RegisterServices registers the GRPC query service and migrator service to respond to the
+// module-specific GRPC queries and handle the upgrade store migration for the module.
+func (am AppModule) RegisterServices(cfg module.Configurator) {
+ types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
+ types.RegisterMsgServer(cfg.MsgServer(), &am.keeper)
+
+ m := keeper.NewMigrator(am.keeper, am.legacySubspace)
+ if err := cfg.RegisterMigration(types.ModuleName, 3, m.Migrate3to4); err != nil {
+ panic(err)
+ }
+}
+
+// BeginBlock returns the begin block for the fee market module.
+func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
+ am.keeper.BeginBlock(ctx, req)
+}
+
+// EndBlock returns the end blocker for the fee market module. It returns no validator
+// updates.
+func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate {
+ am.keeper.EndBlock(ctx, req)
+ return []abci.ValidatorUpdate{}
+}
+
+// InitGenesis performs genesis initialization for the fee market module. It returns
+// no validator updates.
+func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
+ var genesisState types.GenesisState
+
+ cdc.MustUnmarshalJSON(data, &genesisState)
+ InitGenesis(ctx, am.keeper, genesisState)
+ return []abci.ValidatorUpdate{}
+}
+
+// ExportGenesis returns the exported genesis state as raw bytes for the fee market
+// module.
+func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
+ gs := ExportGenesis(ctx, am.keeper)
+ return cdc.MustMarshalJSON(gs)
+}
+
+// RegisterStoreDecoder registers a decoder for fee market module's types
+func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
+
+// GenerateGenesisState creates a randomized GenState of the fee market module.
+func (AppModule) GenerateGenesisState(_ *module.SimulationState) {
+}
+
+// WeightedOperations returns the all the fee market module operations with their respective weights.
+func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation {
+ return nil
+}
diff --git a/x/feemarket/types/codec.go b/x/feemarket/types/codec.go
new file mode 100644
index 00000000..11ec3877
--- /dev/null
+++ b/x/feemarket/types/codec.go
@@ -0,0 +1,45 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "github.com/cosmos/cosmos-sdk/codec"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/cosmos/cosmos-sdk/types/msgservice"
+)
+
+var (
+ amino = codec.NewLegacyAmino()
+ // ModuleCdc references the global fee market module codec. Note, the codec should
+ // ONLY be used in certain instances of tests and for JSON encoding.
+ ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
+
+ // AminoCdc is a amino codec created to support amino JSON compatible msgs.
+ AminoCdc = codec.NewAminoCodec(amino)
+)
+
+const (
+ // Amino names
+ updateParamsName = "ethermint/feemarket/MsgUpdateParams"
+)
+
+// NOTE: This is required for the GetSignBytes function
+func init() {
+ RegisterLegacyAminoCodec(amino)
+ amino.Seal()
+}
+
+// RegisterInterfaces registers the client interfaces to protobuf Any.
+func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
+ registry.RegisterImplementations(
+ (*sdk.Msg)(nil),
+ &MsgUpdateParams{},
+ )
+ msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
+}
+
+// RegisterLegacyAminoCodec required for EIP-712
+func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
+ cdc.RegisterConcrete(&MsgUpdateParams{}, updateParamsName, nil)
+}
diff --git a/x/feemarket/types/events.go b/x/feemarket/types/events.go
new file mode 100644
index 00000000..9a776e9d
--- /dev/null
+++ b/x/feemarket/types/events.go
@@ -0,0 +1,10 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+// feemarket module events
+const (
+ EventTypeFeeMarket = "fee_market"
+
+ AttributeKeyBaseFee = "base_fee"
+)
diff --git a/x/feemarket/types/events.pb.go b/x/feemarket/types/events.pb.go
new file mode 100644
index 00000000..0bf9c0a7
--- /dev/null
+++ b/x/feemarket/types/events.pb.go
@@ -0,0 +1,546 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/feemarket/v1/events.proto
+
+package types
+
+import (
+ fmt "fmt"
+ proto "github.com/cosmos/gogoproto/proto"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// EventFeeMarket is the event type for the fee market module
+type EventFeeMarket struct {
+ // base_fee for EIP-1559 blocks
+ BaseFee string `protobuf:"bytes,1,opt,name=base_fee,json=baseFee,proto3" json:"base_fee,omitempty"`
+}
+
+func (m *EventFeeMarket) Reset() { *m = EventFeeMarket{} }
+func (m *EventFeeMarket) String() string { return proto.CompactTextString(m) }
+func (*EventFeeMarket) ProtoMessage() {}
+func (*EventFeeMarket) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c6edce8d670faff7, []int{0}
+}
+func (m *EventFeeMarket) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EventFeeMarket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EventFeeMarket.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EventFeeMarket) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EventFeeMarket.Merge(m, src)
+}
+func (m *EventFeeMarket) XXX_Size() int {
+ return m.Size()
+}
+func (m *EventFeeMarket) XXX_DiscardUnknown() {
+ xxx_messageInfo_EventFeeMarket.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EventFeeMarket proto.InternalMessageInfo
+
+func (m *EventFeeMarket) GetBaseFee() string {
+ if m != nil {
+ return m.BaseFee
+ }
+ return ""
+}
+
+// EventBlockGas defines an Ethereum block gas event
+type EventBlockGas struct {
+ // height of the block
+ Height string `protobuf:"bytes,1,opt,name=height,proto3" json:"height,omitempty"`
+ // amount of gas wanted by the block
+ Amount string `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount,omitempty"`
+}
+
+func (m *EventBlockGas) Reset() { *m = EventBlockGas{} }
+func (m *EventBlockGas) String() string { return proto.CompactTextString(m) }
+func (*EventBlockGas) ProtoMessage() {}
+func (*EventBlockGas) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c6edce8d670faff7, []int{1}
+}
+func (m *EventBlockGas) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *EventBlockGas) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_EventBlockGas.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *EventBlockGas) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_EventBlockGas.Merge(m, src)
+}
+func (m *EventBlockGas) XXX_Size() int {
+ return m.Size()
+}
+func (m *EventBlockGas) XXX_DiscardUnknown() {
+ xxx_messageInfo_EventBlockGas.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EventBlockGas proto.InternalMessageInfo
+
+func (m *EventBlockGas) GetHeight() string {
+ if m != nil {
+ return m.Height
+ }
+ return ""
+}
+
+func (m *EventBlockGas) GetAmount() string {
+ if m != nil {
+ return m.Amount
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*EventFeeMarket)(nil), "ethermint.feemarket.v1.EventFeeMarket")
+ proto.RegisterType((*EventBlockGas)(nil), "ethermint.feemarket.v1.EventBlockGas")
+}
+
+func init() {
+ proto.RegisterFile("ethermint/feemarket/v1/events.proto", fileDescriptor_c6edce8d670faff7)
+}
+
+var fileDescriptor_c6edce8d670faff7 = []byte{
+ // 215 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4e, 0x2d, 0xc9, 0x48,
+ 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x4b, 0x4d, 0xcd, 0x4d, 0x2c, 0xca, 0x4e, 0x2d, 0xd1,
+ 0x2f, 0x33, 0xd4, 0x4f, 0x2d, 0x4b, 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
+ 0x12, 0x83, 0x2b, 0xd2, 0x83, 0x2b, 0xd2, 0x2b, 0x33, 0x54, 0xd2, 0xe6, 0xe2, 0x73, 0x05, 0xa9,
+ 0x73, 0x4b, 0x4d, 0xf5, 0x05, 0x0b, 0x0a, 0x49, 0x72, 0x71, 0x24, 0x25, 0x16, 0xa7, 0xc6, 0xa7,
+ 0xa5, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xb1, 0x83, 0xf8, 0x6e, 0xa9, 0xa9, 0x4a,
+ 0xf6, 0x5c, 0xbc, 0x60, 0xc5, 0x4e, 0x39, 0xf9, 0xc9, 0xd9, 0xee, 0x89, 0xc5, 0x42, 0x62, 0x5c,
+ 0x6c, 0x19, 0xa9, 0x99, 0xe9, 0x19, 0x25, 0x50, 0x95, 0x50, 0x1e, 0x48, 0x3c, 0x31, 0x37, 0xbf,
+ 0x34, 0xaf, 0x44, 0x82, 0x09, 0x22, 0x0e, 0xe1, 0x39, 0xb9, 0x9d, 0x78, 0x24, 0xc7, 0x78, 0xe1,
+ 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70,
+ 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x4e, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae,
+ 0x7e, 0x6a, 0x59, 0x6e, 0x7e, 0x31, 0x94, 0x2c, 0x33, 0xb4, 0xd0, 0xaf, 0x40, 0xf2, 0x57, 0x49,
+ 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x53, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb8,
+ 0x18, 0x5d, 0x8d, 0xfb, 0x00, 0x00, 0x00,
+}
+
+func (m *EventFeeMarket) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EventFeeMarket) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EventFeeMarket) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.BaseFee) > 0 {
+ i -= len(m.BaseFee)
+ copy(dAtA[i:], m.BaseFee)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.BaseFee)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *EventBlockGas) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EventBlockGas) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *EventBlockGas) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Amount) > 0 {
+ i -= len(m.Amount)
+ copy(dAtA[i:], m.Amount)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Amount)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Height) > 0 {
+ i -= len(m.Height)
+ copy(dAtA[i:], m.Height)
+ i = encodeVarintEvents(dAtA, i, uint64(len(m.Height)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintEvents(dAtA []byte, offset int, v uint64) int {
+ offset -= sovEvents(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *EventFeeMarket) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.BaseFee)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ return n
+}
+
+func (m *EventBlockGas) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Height)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ l = len(m.Amount)
+ if l > 0 {
+ n += 1 + l + sovEvents(uint64(l))
+ }
+ return n
+}
+
+func sovEvents(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozEvents(x uint64) (n int) {
+ return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *EventFeeMarket) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EventFeeMarket: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EventFeeMarket: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BaseFee", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.BaseFee = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvents(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *EventBlockGas) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EventBlockGas: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EventBlockGas: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Height = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEvents
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Amount = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEvents(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthEvents
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipEvents(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEvents
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthEvents
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupEvents
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthEvents
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthEvents = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowEvents = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupEvents = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/feemarket/types/feemarket.pb.go b/x/feemarket/types/feemarket.pb.go
new file mode 100644
index 00000000..d231c3b4
--- /dev/null
+++ b/x/feemarket/types/feemarket.pb.go
@@ -0,0 +1,581 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/feemarket/v1/feemarket.proto
+
+package types
+
+import (
+ cosmossdk_io_math "cosmossdk.io/math"
+ fmt "fmt"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ proto "github.com/cosmos/gogoproto/proto"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// Params defines the EVM module parameters
+type Params struct {
+ // no_base_fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
+ NoBaseFee bool `protobuf:"varint,1,opt,name=no_base_fee,json=noBaseFee,proto3" json:"no_base_fee,omitempty"`
+ // base_fee_change_denominator bounds the amount the base fee can change
+ // between blocks.
+ BaseFeeChangeDenominator uint32 `protobuf:"varint,2,opt,name=base_fee_change_denominator,json=baseFeeChangeDenominator,proto3" json:"base_fee_change_denominator,omitempty"`
+ // elasticity_multiplier bounds the maximum gas limit an EIP-1559 block may
+ // have.
+ ElasticityMultiplier uint32 `protobuf:"varint,3,opt,name=elasticity_multiplier,json=elasticityMultiplier,proto3" json:"elasticity_multiplier,omitempty"`
+ // enable_height defines at which block height the base fee calculation is enabled.
+ EnableHeight int64 `protobuf:"varint,5,opt,name=enable_height,json=enableHeight,proto3" json:"enable_height,omitempty"`
+ // base_fee for EIP-1559 blocks.
+ BaseFee cosmossdk_io_math.Int `protobuf:"bytes,6,opt,name=base_fee,json=baseFee,proto3,customtype=cosmossdk.io/math.Int" json:"base_fee"`
+ // min_gas_price defines the minimum gas price value for cosmos and eth transactions
+ MinGasPrice cosmossdk_io_math.LegacyDec `protobuf:"bytes,7,opt,name=min_gas_price,json=minGasPrice,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"min_gas_price"`
+ // min_gas_multiplier bounds the minimum gas used to be charged
+ // to senders based on gas limit
+ MinGasMultiplier cosmossdk_io_math.LegacyDec `protobuf:"bytes,8,opt,name=min_gas_multiplier,json=minGasMultiplier,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"min_gas_multiplier"`
+}
+
+func (m *Params) Reset() { *m = Params{} }
+func (m *Params) String() string { return proto.CompactTextString(m) }
+func (*Params) ProtoMessage() {}
+func (*Params) Descriptor() ([]byte, []int) {
+ return fileDescriptor_4feb8b20cf98e6e1, []int{0}
+}
+func (m *Params) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Params.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Params) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Params.Merge(m, src)
+}
+func (m *Params) XXX_Size() int {
+ return m.Size()
+}
+func (m *Params) XXX_DiscardUnknown() {
+ xxx_messageInfo_Params.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Params proto.InternalMessageInfo
+
+func (m *Params) GetNoBaseFee() bool {
+ if m != nil {
+ return m.NoBaseFee
+ }
+ return false
+}
+
+func (m *Params) GetBaseFeeChangeDenominator() uint32 {
+ if m != nil {
+ return m.BaseFeeChangeDenominator
+ }
+ return 0
+}
+
+func (m *Params) GetElasticityMultiplier() uint32 {
+ if m != nil {
+ return m.ElasticityMultiplier
+ }
+ return 0
+}
+
+func (m *Params) GetEnableHeight() int64 {
+ if m != nil {
+ return m.EnableHeight
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Params)(nil), "ethermint.feemarket.v1.Params")
+}
+
+func init() {
+ proto.RegisterFile("ethermint/feemarket/v1/feemarket.proto", fileDescriptor_4feb8b20cf98e6e1)
+}
+
+var fileDescriptor_4feb8b20cf98e6e1 = []byte{
+ // 404 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x41, 0x6b, 0xdb, 0x30,
+ 0x14, 0xc7, 0xad, 0xa5, 0x4d, 0x5d, 0x75, 0x81, 0x20, 0xda, 0x61, 0x56, 0xe6, 0x9a, 0x15, 0x86,
+ 0x0f, 0xc3, 0x26, 0xf4, 0xd2, 0xcb, 0x2e, 0x59, 0x69, 0xb7, 0xb1, 0x41, 0xe7, 0xe3, 0x2e, 0x42,
+ 0x76, 0x5f, 0x6c, 0x11, 0x4b, 0x32, 0x96, 0x62, 0x96, 0x6f, 0xb1, 0x6f, 0xb2, 0xaf, 0x91, 0x63,
+ 0x8e, 0x63, 0x87, 0x30, 0x92, 0x2f, 0x32, 0x62, 0x27, 0x76, 0x60, 0x97, 0x5d, 0x84, 0xf4, 0xfe,
+ 0xff, 0xdf, 0x9f, 0xf7, 0xd0, 0xc3, 0x6f, 0xc0, 0x64, 0x50, 0x0a, 0x2e, 0x4d, 0x38, 0x01, 0x10,
+ 0xac, 0x9c, 0x82, 0x09, 0xab, 0x51, 0xf7, 0x08, 0x8a, 0x52, 0x19, 0x45, 0x5e, 0xb4, 0xbe, 0xa0,
+ 0x93, 0xaa, 0xd1, 0xcb, 0xf3, 0x54, 0xa5, 0xaa, 0xb6, 0x84, 0xdb, 0x5b, 0xe3, 0x7e, 0xfd, 0xb3,
+ 0x87, 0xfb, 0x8f, 0xac, 0x64, 0x42, 0x13, 0x17, 0x9f, 0x49, 0x45, 0x63, 0xa6, 0x81, 0x4e, 0x00,
+ 0x1c, 0xe4, 0x21, 0xdf, 0x8e, 0x4e, 0xa5, 0x1a, 0x33, 0x0d, 0xf7, 0x00, 0xe4, 0x1d, 0xbe, 0xdc,
+ 0x8b, 0x34, 0xc9, 0x98, 0x4c, 0x81, 0x3e, 0x81, 0x54, 0x82, 0x4b, 0x66, 0x54, 0xe9, 0x3c, 0xf3,
+ 0x90, 0x3f, 0x88, 0x9c, 0xb8, 0x71, 0xbf, 0xaf, 0x0d, 0x77, 0x9d, 0x4e, 0x6e, 0xf0, 0x05, 0xe4,
+ 0x4c, 0x1b, 0x9e, 0x70, 0x33, 0xa7, 0x62, 0x96, 0x1b, 0x5e, 0xe4, 0x1c, 0x4a, 0xa7, 0x57, 0x83,
+ 0xe7, 0x9d, 0xf8, 0xa5, 0xd5, 0xc8, 0x35, 0x1e, 0x80, 0x64, 0x71, 0x0e, 0x34, 0x03, 0x9e, 0x66,
+ 0xc6, 0x39, 0xf6, 0x90, 0xdf, 0x8b, 0x9e, 0x37, 0xc5, 0x0f, 0x75, 0x8d, 0xdc, 0x62, 0xbb, 0xed,
+ 0xba, 0xef, 0x21, 0xff, 0x74, 0xfc, 0x6a, 0xb1, 0xba, 0xb2, 0x7e, 0xaf, 0xae, 0x2e, 0x12, 0xa5,
+ 0x85, 0xd2, 0xfa, 0x69, 0x1a, 0x70, 0x15, 0x0a, 0x66, 0xb2, 0xe0, 0xa3, 0x34, 0xd1, 0xc9, 0xae,
+ 0x49, 0xf2, 0x80, 0x07, 0x82, 0x4b, 0x9a, 0x32, 0x4d, 0x8b, 0x92, 0x27, 0xe0, 0x9c, 0xd4, 0xf8,
+ 0xf5, 0x0e, 0xbf, 0xfc, 0x17, 0xff, 0x0c, 0x29, 0x4b, 0xe6, 0x77, 0x90, 0x44, 0x67, 0x82, 0xcb,
+ 0x07, 0xa6, 0x1f, 0xb7, 0x1c, 0xf9, 0x8a, 0xc9, 0x3e, 0xe8, 0x60, 0x32, 0xfb, 0xff, 0xd3, 0x86,
+ 0x4d, 0x5a, 0x37, 0xfa, 0xa7, 0x23, 0xfb, 0x68, 0x78, 0x1c, 0x0d, 0xb9, 0xe4, 0x86, 0xb3, 0xbc,
+ 0xfd, 0x97, 0xf1, 0xfd, 0x62, 0xed, 0xa2, 0xe5, 0xda, 0x45, 0x7f, 0xd6, 0x2e, 0xfa, 0xb1, 0x71,
+ 0xad, 0xe5, 0xc6, 0xb5, 0x7e, 0x6d, 0x5c, 0xeb, 0xdb, 0xdb, 0x94, 0x9b, 0x6c, 0x16, 0x07, 0x89,
+ 0x12, 0x21, 0x54, 0x42, 0xe9, 0xdd, 0x59, 0x8d, 0x6e, 0xc3, 0xef, 0x07, 0x4b, 0x63, 0xe6, 0x05,
+ 0xe8, 0xb8, 0x5f, 0x2f, 0xc0, 0xcd, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x3d, 0xcc, 0x8c,
+ 0x58, 0x02, 0x00, 0x00,
+}
+
+func (m *Params) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Params) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size := m.MinGasMultiplier.Size()
+ i -= size
+ if _, err := m.MinGasMultiplier.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintFeemarket(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x42
+ {
+ size := m.MinGasPrice.Size()
+ i -= size
+ if _, err := m.MinGasPrice.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintFeemarket(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x3a
+ {
+ size := m.BaseFee.Size()
+ i -= size
+ if _, err := m.BaseFee.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintFeemarket(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x32
+ if m.EnableHeight != 0 {
+ i = encodeVarintFeemarket(dAtA, i, uint64(m.EnableHeight))
+ i--
+ dAtA[i] = 0x28
+ }
+ if m.ElasticityMultiplier != 0 {
+ i = encodeVarintFeemarket(dAtA, i, uint64(m.ElasticityMultiplier))
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.BaseFeeChangeDenominator != 0 {
+ i = encodeVarintFeemarket(dAtA, i, uint64(m.BaseFeeChangeDenominator))
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.NoBaseFee {
+ i--
+ if m.NoBaseFee {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintFeemarket(dAtA []byte, offset int, v uint64) int {
+ offset -= sovFeemarket(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *Params) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.NoBaseFee {
+ n += 2
+ }
+ if m.BaseFeeChangeDenominator != 0 {
+ n += 1 + sovFeemarket(uint64(m.BaseFeeChangeDenominator))
+ }
+ if m.ElasticityMultiplier != 0 {
+ n += 1 + sovFeemarket(uint64(m.ElasticityMultiplier))
+ }
+ if m.EnableHeight != 0 {
+ n += 1 + sovFeemarket(uint64(m.EnableHeight))
+ }
+ l = m.BaseFee.Size()
+ n += 1 + l + sovFeemarket(uint64(l))
+ l = m.MinGasPrice.Size()
+ n += 1 + l + sovFeemarket(uint64(l))
+ l = m.MinGasMultiplier.Size()
+ n += 1 + l + sovFeemarket(uint64(l))
+ return n
+}
+
+func sovFeemarket(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozFeemarket(x uint64) (n int) {
+ return sovFeemarket(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Params) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Params: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NoBaseFee", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.NoBaseFee = bool(v != 0)
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BaseFeeChangeDenominator", wireType)
+ }
+ m.BaseFeeChangeDenominator = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BaseFeeChangeDenominator |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ElasticityMultiplier", wireType)
+ }
+ m.ElasticityMultiplier = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ElasticityMultiplier |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EnableHeight", wireType)
+ }
+ m.EnableHeight = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.EnableHeight |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BaseFee", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.BaseFee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MinGasPrice", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.MinGasPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MinGasMultiplier", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.MinGasMultiplier.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipFeemarket(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthFeemarket
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipFeemarket(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFeemarket
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthFeemarket
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupFeemarket
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthFeemarket
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthFeemarket = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowFeemarket = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupFeemarket = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/feemarket/types/genesis.go b/x/feemarket/types/genesis.go
new file mode 100644
index 00000000..7a4a37eb
--- /dev/null
+++ b/x/feemarket/types/genesis.go
@@ -0,0 +1,25 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+// DefaultGenesisState sets default fee market genesis state.
+func DefaultGenesisState() *GenesisState {
+ return &GenesisState{
+ Params: DefaultParams(),
+ BlockGas: 0,
+ }
+}
+
+// NewGenesisState creates a new genesis state.
+func NewGenesisState(params Params, blockGas uint64) *GenesisState {
+ return &GenesisState{
+ Params: params,
+ BlockGas: blockGas,
+ }
+}
+
+// Validate performs basic genesis state validation returning an error upon any
+// failure.
+func (gs GenesisState) Validate() error {
+ return gs.Params.Validate()
+}
diff --git a/x/feemarket/types/genesis.pb.go b/x/feemarket/types/genesis.pb.go
new file mode 100644
index 00000000..ebc67987
--- /dev/null
+++ b/x/feemarket/types/genesis.pb.go
@@ -0,0 +1,364 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/feemarket/v1/genesis.proto
+
+package types
+
+import (
+ fmt "fmt"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ proto "github.com/cosmos/gogoproto/proto"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// GenesisState defines the feemarket module's genesis state.
+type GenesisState struct {
+ // params defines all the parameters of the feemarket module.
+ Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
+ // block_gas is the amount of gas wanted on the last block before the upgrade.
+ // Zero by default.
+ BlockGas uint64 `protobuf:"varint,3,opt,name=block_gas,json=blockGas,proto3" json:"block_gas,omitempty"`
+}
+
+func (m *GenesisState) Reset() { *m = GenesisState{} }
+func (m *GenesisState) String() string { return proto.CompactTextString(m) }
+func (*GenesisState) ProtoMessage() {}
+func (*GenesisState) Descriptor() ([]byte, []int) {
+ return fileDescriptor_6241c21661288629, []int{0}
+}
+func (m *GenesisState) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *GenesisState) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GenesisState.Merge(m, src)
+}
+func (m *GenesisState) XXX_Size() int {
+ return m.Size()
+}
+func (m *GenesisState) XXX_DiscardUnknown() {
+ xxx_messageInfo_GenesisState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GenesisState proto.InternalMessageInfo
+
+func (m *GenesisState) GetParams() Params {
+ if m != nil {
+ return m.Params
+ }
+ return Params{}
+}
+
+func (m *GenesisState) GetBlockGas() uint64 {
+ if m != nil {
+ return m.BlockGas
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*GenesisState)(nil), "ethermint.feemarket.v1.GenesisState")
+}
+
+func init() {
+ proto.RegisterFile("ethermint/feemarket/v1/genesis.proto", fileDescriptor_6241c21661288629)
+}
+
+var fileDescriptor_6241c21661288629 = []byte{
+ // 246 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x49, 0x2d, 0xc9, 0x48,
+ 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x4b, 0x4d, 0xcd, 0x4d, 0x2c, 0xca, 0x4e, 0x2d, 0xd1,
+ 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
+ 0x17, 0x12, 0x83, 0xab, 0xd2, 0x83, 0xab, 0xd2, 0x2b, 0x33, 0x94, 0x52, 0xc3, 0xa1, 0x1b, 0xa1,
+ 0x08, 0xac, 0x5f, 0x4a, 0x24, 0x3d, 0x3f, 0x3d, 0x1f, 0xcc, 0xd4, 0x07, 0xb1, 0x20, 0xa2, 0x4a,
+ 0x95, 0x5c, 0x3c, 0xee, 0x10, 0x6b, 0x82, 0x4b, 0x12, 0x4b, 0x52, 0x85, 0x6c, 0xb8, 0xd8, 0x0a,
+ 0x12, 0x8b, 0x12, 0x73, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0xe4, 0xf4, 0xb0, 0x5b,
+ 0xab, 0x17, 0x00, 0x56, 0xe5, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x54, 0x8f, 0x90, 0x34,
+ 0x17, 0x67, 0x52, 0x4e, 0x7e, 0x72, 0x76, 0x7c, 0x7a, 0x62, 0xb1, 0x04, 0xb3, 0x02, 0xa3, 0x06,
+ 0x4b, 0x10, 0x07, 0x58, 0xc0, 0x3d, 0xb1, 0xd8, 0x8b, 0x85, 0x83, 0x49, 0x80, 0x39, 0x88, 0x23,
+ 0x29, 0xb1, 0x38, 0x35, 0x3e, 0x2d, 0x35, 0xd5, 0xc9, 0xed, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f,
+ 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b,
+ 0x8f, 0xe5, 0x18, 0xa2, 0x74, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5,
+ 0x53, 0xcb, 0x72, 0xf3, 0x8b, 0xa1, 0x64, 0x99, 0xa1, 0x85, 0x7e, 0x05, 0x92, 0x2f, 0x4b, 0x2a,
+ 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x3e, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x70,
+ 0xda, 0x21, 0x47, 0x01, 0x00, 0x00,
+}
+
+func (m *GenesisState) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.BlockGas != 0 {
+ i = encodeVarintGenesis(dAtA, i, uint64(m.BlockGas))
+ i--
+ dAtA[i] = 0x18
+ }
+ {
+ size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintGenesis(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
+ offset -= sovGenesis(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *GenesisState) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = m.Params.Size()
+ n += 1 + l + sovGenesis(uint64(l))
+ if m.BlockGas != 0 {
+ n += 1 + sovGenesis(uint64(m.BlockGas))
+ }
+ return n
+}
+
+func sovGenesis(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozGenesis(x uint64) (n int) {
+ return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *GenesisState) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BlockGas", wireType)
+ }
+ m.BlockGas = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.BlockGas |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipGenesis(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthGenesis
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipGenesis(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthGenesis
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupGenesis
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthGenesis
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/feemarket/types/genesis_test.go b/x/feemarket/types/genesis_test.go
new file mode 100644
index 00000000..843f70fc
--- /dev/null
+++ b/x/feemarket/types/genesis_test.go
@@ -0,0 +1,63 @@
+package types
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+)
+
+type GenesisTestSuite struct {
+ suite.Suite
+}
+
+func TestGenesisTestSuite(t *testing.T) {
+ suite.Run(t, new(GenesisTestSuite))
+}
+
+func (suite *GenesisTestSuite) TestValidateGenesis() {
+ testCases := []struct {
+ name string
+ genState *GenesisState
+ expPass bool
+ }{
+ {
+ "default",
+ DefaultGenesisState(),
+ true,
+ },
+ {
+ "valid genesis",
+ &GenesisState{
+ DefaultParams(),
+ uint64(1),
+ },
+ true,
+ },
+ {
+ "valid New genesis",
+ NewGenesisState(
+ DefaultParams(),
+ uint64(1),
+ ),
+ true,
+ },
+ {
+ "empty genesis",
+ &GenesisState{
+ Params: Params{},
+ BlockGas: 0,
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ err := tc.genState.Validate()
+ if tc.expPass {
+ suite.Require().NoError(err, tc.name)
+ } else {
+ suite.Require().Error(err, tc.name)
+ }
+ }
+}
diff --git a/x/feemarket/types/interfaces.go b/x/feemarket/types/interfaces.go
new file mode 100644
index 00000000..6689b8f5
--- /dev/null
+++ b/x/feemarket/types/interfaces.go
@@ -0,0 +1,17 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
+)
+
+type (
+ LegacyParams = paramtypes.ParamSet
+ // Subspace defines an interface that implements the legacy Cosmos SDK x/params Subspace type.
+ // NOTE: This is used solely for migration of the Cosmos SDK x/params managed parameters.
+ Subspace interface {
+ GetParamSetIfExists(ctx sdk.Context, ps LegacyParams)
+ }
+)
diff --git a/x/feemarket/types/keys.go b/x/feemarket/types/keys.go
new file mode 100644
index 00000000..2739e36c
--- /dev/null
+++ b/x/feemarket/types/keys.go
@@ -0,0 +1,39 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+const (
+ // ModuleName string name of module
+ ModuleName = "feemarket"
+
+ // StoreKey key for base fee and block gas used.
+ // The Fee Market module should use a prefix store.
+ StoreKey = ModuleName
+
+ // RouterKey uses module name for routing
+ RouterKey = ModuleName
+
+ // TransientKey is the key to access the FeeMarket transient store, that is reset
+ // during the Commit phase.
+ TransientKey = "transient_" + ModuleName
+)
+
+// prefix bytes for the feemarket persistent store
+const (
+ prefixBlockGasWanted = iota + 1
+ deprecatedPrefixBaseFee // unused
+)
+
+const (
+ prefixTransientBlockGasUsed = iota + 1
+)
+
+// KVStore key prefixes
+var (
+ KeyPrefixBlockGasWanted = []byte{prefixBlockGasWanted}
+)
+
+// Transient Store key prefixes
+var (
+ KeyPrefixTransientBlockGasWanted = []byte{prefixTransientBlockGasUsed}
+)
diff --git a/x/feemarket/types/msg.go b/x/feemarket/types/msg.go
new file mode 100644
index 00000000..053b603a
--- /dev/null
+++ b/x/feemarket/types/msg.go
@@ -0,0 +1,30 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ errorsmod "cosmossdk.io/errors"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+var _ sdk.Msg = &MsgUpdateParams{}
+
+// GetSigners returns the expected signers for a MsgUpdateParams message.
+func (m *MsgUpdateParams) GetSigners() []sdk.AccAddress {
+ addr := sdk.MustAccAddressFromBech32(m.Authority)
+ return []sdk.AccAddress{addr}
+}
+
+// ValidateBasic does a sanity check of the provided data
+func (m *MsgUpdateParams) ValidateBasic() error {
+ if _, err := sdk.AccAddressFromBech32(m.Authority); err != nil {
+ return errorsmod.Wrap(err, "invalid authority address")
+ }
+
+ return m.Params.Validate()
+}
+
+// GetSignBytes implements the LegacyMsg interface.
+func (m MsgUpdateParams) GetSignBytes() []byte {
+ return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m))
+}
diff --git a/x/feemarket/types/msg_test.go b/x/feemarket/types/msg_test.go
new file mode 100644
index 00000000..aaa9fa9e
--- /dev/null
+++ b/x/feemarket/types/msg_test.go
@@ -0,0 +1,53 @@
+package types
+
+import (
+ "testing"
+
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
+ "github.com/stretchr/testify/suite"
+)
+
+type MsgsTestSuite struct {
+ suite.Suite
+}
+
+func TestMsgsTestSuite(t *testing.T) {
+ suite.Run(t, new(MsgsTestSuite))
+}
+
+func (suite *MsgsTestSuite) TestMsgUpdateValidateBasic() {
+ testCases := []struct {
+ name string
+ msgUpdate *MsgUpdateParams
+ expPass bool
+ }{
+ {
+ "fail - invalid authority address",
+ &MsgUpdateParams{
+ Authority: "invalid",
+ Params: DefaultParams(),
+ },
+ false,
+ },
+ {
+ "pass - valid msg",
+ &MsgUpdateParams{
+ Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
+ Params: DefaultParams(),
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ suite.Run(tc.name, func() {
+ err := tc.msgUpdate.ValidateBasic()
+ if tc.expPass {
+ suite.NoError(err)
+ } else {
+ suite.Error(err)
+ }
+ })
+ }
+}
diff --git a/x/feemarket/types/params.go b/x/feemarket/types/params.go
new file mode 100644
index 00000000..115c3b3e
--- /dev/null
+++ b/x/feemarket/types/params.go
@@ -0,0 +1,205 @@
+// Copyright Tharsis Labs Ltd.(Evmos)
+// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)
+package types
+
+import (
+ "fmt"
+
+ "cosmossdk.io/math"
+ paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var (
+ // DefaultMinGasMultiplier is 0.5 or 50%
+ DefaultMinGasMultiplier = math.LegacyNewDecWithPrec(50, 2)
+ // DefaultMinGasPrice is 0 (i.e disabled)
+ DefaultMinGasPrice = math.LegacyZeroDec()
+ // DefaultEnableHeight is 0 (i.e disabled)
+ DefaultEnableHeight = int64(0)
+ // DefaultNoBaseFee is false
+ DefaultNoBaseFee = false
+)
+
+// Parameter keys
+var (
+ ParamsKey = []byte("Params")
+ ParamStoreKeyNoBaseFee = []byte("NoBaseFee")
+ ParamStoreKeyBaseFeeChangeDenominator = []byte("BaseFeeChangeDenominator")
+ ParamStoreKeyElasticityMultiplier = []byte("ElasticityMultiplier")
+ ParamStoreKeyBaseFee = []byte("BaseFee")
+ ParamStoreKeyEnableHeight = []byte("EnableHeight")
+ ParamStoreKeyMinGasPrice = []byte("MinGasPrice")
+ ParamStoreKeyMinGasMultiplier = []byte("MinGasMultiplier")
+)
+
+// ParamKeyTable returns the parameter key table.
+func ParamKeyTable() paramtypes.KeyTable {
+ return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
+}
+
+// ParamSetPairs returns the parameter set pairs.
+func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
+ return paramtypes.ParamSetPairs{
+ paramtypes.NewParamSetPair(ParamStoreKeyNoBaseFee, &p.NoBaseFee, validateBool),
+ paramtypes.NewParamSetPair(ParamStoreKeyBaseFeeChangeDenominator, &p.BaseFeeChangeDenominator, validateBaseFeeChangeDenominator),
+ paramtypes.NewParamSetPair(ParamStoreKeyElasticityMultiplier, &p.ElasticityMultiplier, validateElasticityMultiplier),
+ paramtypes.NewParamSetPair(ParamStoreKeyBaseFee, &p.BaseFee, validateBaseFee),
+ paramtypes.NewParamSetPair(ParamStoreKeyEnableHeight, &p.EnableHeight, validateEnableHeight),
+ paramtypes.NewParamSetPair(ParamStoreKeyMinGasPrice, &p.MinGasPrice, validateMinGasPrice),
+ paramtypes.NewParamSetPair(ParamStoreKeyMinGasMultiplier, &p.MinGasMultiplier, validateMinGasPrice),
+ }
+}
+
+// NewParams creates a new Params instance
+func NewParams(
+ noBaseFee bool,
+ baseFeeChangeDenom,
+ elasticityMultiplier uint32,
+ baseFee uint64,
+ enableHeight int64,
+ minGasPrice math.LegacyDec,
+ minGasPriceMultiplier math.LegacyDec,
+) Params {
+ return Params{
+ NoBaseFee: noBaseFee,
+ BaseFeeChangeDenominator: baseFeeChangeDenom,
+ ElasticityMultiplier: elasticityMultiplier,
+ BaseFee: math.NewIntFromUint64(baseFee),
+ EnableHeight: enableHeight,
+ MinGasPrice: minGasPrice,
+ MinGasMultiplier: minGasPriceMultiplier,
+ }
+}
+
+// DefaultParams returns default evm parameters
+func DefaultParams() Params {
+ return Params{
+ NoBaseFee: DefaultNoBaseFee,
+ BaseFeeChangeDenominator: params.BaseFeeChangeDenominator,
+ ElasticityMultiplier: params.ElasticityMultiplier,
+ BaseFee: math.NewIntFromUint64(params.InitialBaseFee),
+ EnableHeight: DefaultEnableHeight,
+ MinGasPrice: DefaultMinGasPrice,
+ MinGasMultiplier: DefaultMinGasMultiplier,
+ }
+}
+
+// Validate performs basic validation on fee market parameters.
+func (p Params) Validate() error {
+ if p.BaseFeeChangeDenominator == 0 {
+ return fmt.Errorf("base fee change denominator cannot be 0")
+ }
+
+ if p.BaseFee.IsNegative() {
+ return fmt.Errorf("initial base fee cannot be negative: %s", p.BaseFee)
+ }
+
+ if p.EnableHeight < 0 {
+ return fmt.Errorf("enable height cannot be negative: %d", p.EnableHeight)
+ }
+
+ if err := validateMinGasMultiplier(p.MinGasMultiplier); err != nil {
+ return err
+ }
+
+ return validateMinGasPrice(p.MinGasPrice)
+}
+
+func validateBool(i interface{}) error {
+ _, ok := i.(bool)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+ return nil
+}
+
+func (p *Params) IsBaseFeeEnabled(height int64) bool {
+ return !p.NoBaseFee && height >= p.EnableHeight
+}
+
+func validateMinGasPrice(i interface{}) error {
+ v, ok := i.(math.LegacyDec)
+
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if v.IsNil() {
+ return fmt.Errorf("invalid parameter: nil")
+ }
+
+ if v.IsNegative() {
+ return fmt.Errorf("value cannot be negative: %s", i)
+ }
+
+ return nil
+}
+
+func validateBaseFeeChangeDenominator(i interface{}) error {
+ value, ok := i.(uint32)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if value == 0 {
+ return fmt.Errorf("base fee change denominator cannot be 0")
+ }
+
+ return nil
+}
+
+func validateElasticityMultiplier(i interface{}) error {
+ _, ok := i.(uint32)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+ return nil
+}
+
+func validateBaseFee(i interface{}) error {
+ value, ok := i.(math.Int)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if value.IsNegative() {
+ return fmt.Errorf("base fee cannot be negative")
+ }
+
+ return nil
+}
+
+func validateEnableHeight(i interface{}) error {
+ value, ok := i.(int64)
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if value < 0 {
+ return fmt.Errorf("enable height cannot be negative: %d", value)
+ }
+
+ return nil
+}
+
+func validateMinGasMultiplier(i interface{}) error {
+ v, ok := i.(math.LegacyDec)
+
+ if !ok {
+ return fmt.Errorf("invalid parameter type: %T", i)
+ }
+
+ if v.IsNil() {
+ return fmt.Errorf("invalid parameter: nil")
+ }
+
+ if v.IsNegative() {
+ return fmt.Errorf("value cannot be negative: %s", v)
+ }
+
+ if v.GT(math.LegacyOneDec()) {
+ return fmt.Errorf("value cannot be greater than 1: %s", v)
+ }
+ return nil
+}
diff --git a/x/feemarket/types/params_test.go b/x/feemarket/types/params_test.go
new file mode 100644
index 00000000..f27c2d05
--- /dev/null
+++ b/x/feemarket/types/params_test.go
@@ -0,0 +1,119 @@
+package types
+
+import (
+ "testing"
+
+ "cosmossdk.io/math"
+ "github.com/stretchr/testify/suite"
+)
+
+type ParamsTestSuite struct {
+ suite.Suite
+}
+
+func TestParamsTestSuite(t *testing.T) {
+ suite.Run(t, new(ParamsTestSuite))
+}
+
+func (suite *ParamsTestSuite) TestParamsValidate() {
+ testCases := []struct {
+ name string
+ params Params
+ expError bool
+ }{
+ {"default", DefaultParams(), false},
+ {
+ "valid",
+ NewParams(true, 7, 3, 2000000000, int64(544435345345435345), math.LegacyNewDecWithPrec(20, 4), DefaultMinGasMultiplier),
+ false,
+ },
+ {
+ "empty",
+ Params{},
+ true,
+ },
+ {
+ "base fee change denominator is 0 ",
+ NewParams(true, 0, 3, 2000000000, int64(544435345345435345), math.LegacyNewDecWithPrec(20, 4), DefaultMinGasMultiplier),
+ true,
+ },
+ {
+ "invalid: min gas price negative",
+ NewParams(true, 7, 3, 2000000000, int64(544435345345435345), math.LegacyNewDecFromInt(math.NewInt(-1)), DefaultMinGasMultiplier),
+ true,
+ },
+ {
+ "valid: min gas multiplier zero",
+ NewParams(true, 7, 3, 2000000000, int64(544435345345435345), DefaultMinGasPrice, math.LegacyZeroDec()),
+ false,
+ },
+ {
+ "invalid: min gas multiplier is negative",
+ NewParams(true, 7, 3, 2000000000, int64(544435345345435345), DefaultMinGasPrice, math.LegacyNewDecWithPrec(-5, 1)),
+ true,
+ },
+ {
+ "invalid: min gas multiplier bigger than 1",
+ NewParams(true, 7, 3, 2000000000, int64(544435345345435345), math.LegacyNewDecWithPrec(20, 4), math.LegacyNewDec(2)),
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ err := tc.params.Validate()
+
+ if tc.expError {
+ suite.Require().Error(err, tc.name)
+ } else {
+ suite.Require().NoError(err, tc.name)
+ }
+ }
+}
+
+func (suite *ParamsTestSuite) TestParamsValidatePriv() {
+ suite.Require().Error(validateBool(2))
+ suite.Require().NoError(validateBool(true))
+ suite.Require().Error(validateBaseFeeChangeDenominator(0))
+ suite.Require().Error(validateBaseFeeChangeDenominator(uint32(0)))
+ suite.Require().NoError(validateBaseFeeChangeDenominator(uint32(7)))
+ suite.Require().Error(validateElasticityMultiplier(""))
+ suite.Require().NoError(validateElasticityMultiplier(uint32(2)))
+ suite.Require().Error(validateBaseFee(""))
+ suite.Require().Error(validateBaseFee(int64(2000000000)))
+ suite.Require().Error(validateBaseFee(math.NewInt(-2000000000)))
+ suite.Require().NoError(validateBaseFee(math.NewInt(2000000000)))
+ suite.Require().Error(validateEnableHeight(""))
+ suite.Require().Error(validateEnableHeight(int64(-544435345345435345)))
+ suite.Require().NoError(validateEnableHeight(int64(544435345345435345)))
+ suite.Require().Error(validateMinGasPrice(math.LegacyDec{}))
+ suite.Require().Error(validateMinGasMultiplier(math.LegacyNewDec(-5)))
+ suite.Require().Error(validateMinGasMultiplier(math.LegacyDec{}))
+ suite.Require().Error(validateMinGasMultiplier(""))
+}
+
+func (suite *ParamsTestSuite) TestParamsValidateMinGasPrice() {
+ testCases := []struct {
+ name string
+ value interface{}
+ expError bool
+ }{
+ {"default", DefaultParams().MinGasPrice, false},
+ {"valid", math.LegacyNewDecFromInt(math.NewInt(1)), false},
+ {"invalid - wrong type - bool", false, true},
+ {"invalid - wrong type - string", "", true},
+ {"invalid - wrong type - int64", int64(123), true},
+ {"invalid - wrong type - math.Int", math.NewInt(1), true},
+ {"invalid - is nil", nil, true},
+ {"invalid - is negative", math.LegacyNewDecFromInt(math.NewInt(-1)), true},
+ }
+
+ for _, tc := range testCases {
+ err := validateMinGasPrice(tc.value)
+
+ if tc.expError {
+ suite.Require().Error(err, tc.name)
+ } else {
+ suite.Require().NoError(err, tc.name)
+ }
+ }
+}
diff --git a/x/feemarket/types/query.pb.go b/x/feemarket/types/query.pb.go
new file mode 100644
index 00000000..b25c7080
--- /dev/null
+++ b/x/feemarket/types/query.pb.go
@@ -0,0 +1,1196 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/feemarket/v1/query.proto
+
+package types
+
+import (
+ context "context"
+ cosmossdk_io_math "cosmossdk.io/math"
+ fmt "fmt"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ grpc1 "github.com/cosmos/gogoproto/grpc"
+ proto "github.com/cosmos/gogoproto/proto"
+ _ "google.golang.org/genproto/googleapis/api/annotations"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// QueryParamsRequest defines the request type for querying x/evm parameters.
+type QueryParamsRequest struct {
+}
+
+func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} }
+func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryParamsRequest) ProtoMessage() {}
+func (*QueryParamsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_71a07c1ffd85fde2, []int{0}
+}
+func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryParamsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryParamsRequest.Merge(m, src)
+}
+func (m *QueryParamsRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryParamsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo
+
+// QueryParamsResponse defines the response type for querying x/evm parameters.
+type QueryParamsResponse struct {
+ // params define the evm module parameters.
+ Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
+}
+
+func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} }
+func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryParamsResponse) ProtoMessage() {}
+func (*QueryParamsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_71a07c1ffd85fde2, []int{1}
+}
+func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryParamsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryParamsResponse.Merge(m, src)
+}
+func (m *QueryParamsResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryParamsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo
+
+func (m *QueryParamsResponse) GetParams() Params {
+ if m != nil {
+ return m.Params
+ }
+ return Params{}
+}
+
+// QueryBaseFeeRequest defines the request type for querying the EIP1559 base
+// fee.
+type QueryBaseFeeRequest struct {
+}
+
+func (m *QueryBaseFeeRequest) Reset() { *m = QueryBaseFeeRequest{} }
+func (m *QueryBaseFeeRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryBaseFeeRequest) ProtoMessage() {}
+func (*QueryBaseFeeRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_71a07c1ffd85fde2, []int{2}
+}
+func (m *QueryBaseFeeRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBaseFeeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBaseFeeRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBaseFeeRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBaseFeeRequest.Merge(m, src)
+}
+func (m *QueryBaseFeeRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBaseFeeRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBaseFeeRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBaseFeeRequest proto.InternalMessageInfo
+
+// QueryBaseFeeResponse returns the EIP1559 base fee.
+type QueryBaseFeeResponse struct {
+ // base_fee is the EIP1559 base fee
+ BaseFee *cosmossdk_io_math.Int `protobuf:"bytes,1,opt,name=base_fee,json=baseFee,proto3,customtype=cosmossdk.io/math.Int" json:"base_fee,omitempty"`
+}
+
+func (m *QueryBaseFeeResponse) Reset() { *m = QueryBaseFeeResponse{} }
+func (m *QueryBaseFeeResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryBaseFeeResponse) ProtoMessage() {}
+func (*QueryBaseFeeResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_71a07c1ffd85fde2, []int{3}
+}
+func (m *QueryBaseFeeResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBaseFeeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBaseFeeResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBaseFeeResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBaseFeeResponse.Merge(m, src)
+}
+func (m *QueryBaseFeeResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBaseFeeResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBaseFeeResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBaseFeeResponse proto.InternalMessageInfo
+
+// QueryBlockGasRequest defines the request type for querying the EIP1559 base
+// fee.
+type QueryBlockGasRequest struct {
+}
+
+func (m *QueryBlockGasRequest) Reset() { *m = QueryBlockGasRequest{} }
+func (m *QueryBlockGasRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryBlockGasRequest) ProtoMessage() {}
+func (*QueryBlockGasRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_71a07c1ffd85fde2, []int{4}
+}
+func (m *QueryBlockGasRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBlockGasRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBlockGasRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBlockGasRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBlockGasRequest.Merge(m, src)
+}
+func (m *QueryBlockGasRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBlockGasRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBlockGasRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBlockGasRequest proto.InternalMessageInfo
+
+// QueryBlockGasResponse returns block gas used for a given height.
+type QueryBlockGasResponse struct {
+ // gas is the returned block gas
+ Gas int64 `protobuf:"varint,1,opt,name=gas,proto3" json:"gas,omitempty"`
+}
+
+func (m *QueryBlockGasResponse) Reset() { *m = QueryBlockGasResponse{} }
+func (m *QueryBlockGasResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryBlockGasResponse) ProtoMessage() {}
+func (*QueryBlockGasResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_71a07c1ffd85fde2, []int{5}
+}
+func (m *QueryBlockGasResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryBlockGasResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryBlockGasResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *QueryBlockGasResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryBlockGasResponse.Merge(m, src)
+}
+func (m *QueryBlockGasResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryBlockGasResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryBlockGasResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryBlockGasResponse proto.InternalMessageInfo
+
+func (m *QueryBlockGasResponse) GetGas() int64 {
+ if m != nil {
+ return m.Gas
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*QueryParamsRequest)(nil), "ethermint.feemarket.v1.QueryParamsRequest")
+ proto.RegisterType((*QueryParamsResponse)(nil), "ethermint.feemarket.v1.QueryParamsResponse")
+ proto.RegisterType((*QueryBaseFeeRequest)(nil), "ethermint.feemarket.v1.QueryBaseFeeRequest")
+ proto.RegisterType((*QueryBaseFeeResponse)(nil), "ethermint.feemarket.v1.QueryBaseFeeResponse")
+ proto.RegisterType((*QueryBlockGasRequest)(nil), "ethermint.feemarket.v1.QueryBlockGasRequest")
+ proto.RegisterType((*QueryBlockGasResponse)(nil), "ethermint.feemarket.v1.QueryBlockGasResponse")
+}
+
+func init() {
+ proto.RegisterFile("ethermint/feemarket/v1/query.proto", fileDescriptor_71a07c1ffd85fde2)
+}
+
+var fileDescriptor_71a07c1ffd85fde2 = []byte{
+ // 447 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xbf, 0x6f, 0xd3, 0x40,
+ 0x14, 0xce, 0x11, 0x48, 0xcb, 0xb1, 0xa0, 0x23, 0xa9, 0xc0, 0x0a, 0x17, 0x64, 0x01, 0xe2, 0x47,
+ 0xb9, 0x53, 0x0a, 0x03, 0x03, 0x93, 0x87, 0x22, 0x24, 0x06, 0x30, 0x1b, 0x4b, 0x75, 0x0e, 0xaf,
+ 0x8e, 0x95, 0xda, 0xe7, 0xfa, 0x2e, 0x16, 0x5d, 0x91, 0x58, 0x18, 0x10, 0x12, 0x7f, 0x07, 0xff,
+ 0x47, 0xc7, 0x4a, 0x2c, 0x88, 0xa1, 0x42, 0x09, 0x7f, 0x08, 0xf2, 0xdd, 0x39, 0x60, 0x48, 0x68,
+ 0x16, 0xeb, 0xe9, 0xf9, 0x7b, 0xdf, 0xf7, 0xbd, 0xef, 0xe9, 0xb0, 0x0f, 0x7a, 0x0c, 0x45, 0x9a,
+ 0x64, 0x9a, 0xef, 0x03, 0xa4, 0xa2, 0x98, 0x80, 0xe6, 0xe5, 0x90, 0x1f, 0x4e, 0xa1, 0x38, 0x62,
+ 0x79, 0x21, 0xb5, 0x24, 0x5b, 0x0b, 0x0c, 0x5b, 0x60, 0x58, 0x39, 0xf4, 0x6e, 0xaf, 0x98, 0xfd,
+ 0x0d, 0x32, 0xf3, 0x5e, 0x37, 0x96, 0xb1, 0x34, 0x25, 0xaf, 0x2a, 0xd7, 0xed, 0xc7, 0x52, 0xc6,
+ 0x07, 0xc0, 0x45, 0x9e, 0x70, 0x91, 0x65, 0x52, 0x0b, 0x9d, 0xc8, 0x4c, 0xd9, 0xbf, 0x7e, 0x17,
+ 0x93, 0x97, 0x95, 0x85, 0x17, 0xa2, 0x10, 0xa9, 0x0a, 0xe1, 0x70, 0x0a, 0x4a, 0xfb, 0xaf, 0xf0,
+ 0x95, 0x46, 0x57, 0xe5, 0x32, 0x53, 0x40, 0x9e, 0xe0, 0x4e, 0x6e, 0x3a, 0x57, 0xd1, 0x0d, 0x74,
+ 0xe7, 0xd2, 0x0e, 0x65, 0xcb, 0x1d, 0x33, 0x3b, 0x17, 0x9c, 0x3f, 0x3e, 0x1d, 0xb4, 0x42, 0x37,
+ 0xe3, 0xf7, 0x1c, 0x69, 0x20, 0x14, 0xec, 0x02, 0xd4, 0x5a, 0xcf, 0x71, 0xb7, 0xd9, 0x76, 0x62,
+ 0x8f, 0xf0, 0x66, 0x24, 0x14, 0xec, 0xed, 0x03, 0x18, 0xb9, 0x8b, 0xc1, 0xb5, 0xef, 0xa7, 0x83,
+ 0xde, 0x48, 0xaa, 0x54, 0x2a, 0xf5, 0x66, 0xc2, 0x12, 0xc9, 0x53, 0xa1, 0xc7, 0xec, 0x59, 0xa6,
+ 0xc3, 0x8d, 0xc8, 0x4e, 0xfb, 0x5b, 0x35, 0xdb, 0x81, 0x1c, 0x4d, 0x9e, 0x8a, 0xc5, 0x46, 0x77,
+ 0x71, 0xef, 0xaf, 0xbe, 0x93, 0xb9, 0x8c, 0xdb, 0xb1, 0xb0, 0x0b, 0xb5, 0xc3, 0xaa, 0xdc, 0xf9,
+ 0xd2, 0xc6, 0x17, 0x0c, 0x96, 0xbc, 0x47, 0xb8, 0x63, 0x57, 0x21, 0xf7, 0x56, 0xad, 0xfa, 0x6f,
+ 0x7a, 0xde, 0xfd, 0xb5, 0xb0, 0x56, 0xdf, 0xf7, 0xdf, 0x7d, 0xfd, 0xf9, 0xf9, 0x5c, 0x9f, 0x78,
+ 0x1c, 0xca, 0x54, 0xaa, 0xe6, 0x85, 0x6d, 0x72, 0xe4, 0x03, 0xc2, 0x1b, 0x2e, 0x1e, 0xf2, 0x7f,
+ 0xf2, 0x66, 0xb6, 0xde, 0xf6, 0x7a, 0x60, 0x67, 0xe5, 0xa6, 0xb1, 0x42, 0x49, 0x7f, 0x99, 0x95,
+ 0xfa, 0x16, 0xe4, 0x23, 0xc2, 0x9b, 0x75, 0x8a, 0xe4, 0x0c, 0x81, 0xe6, 0x11, 0xbc, 0x07, 0x6b,
+ 0xa2, 0x9d, 0x9f, 0x5b, 0xc6, 0xcf, 0x80, 0x5c, 0x5f, 0xea, 0xa7, 0x42, 0xef, 0xc5, 0x42, 0x05,
+ 0xbb, 0xc7, 0x33, 0x8a, 0x4e, 0x66, 0x14, 0xfd, 0x98, 0x51, 0xf4, 0x69, 0x4e, 0x5b, 0x27, 0x73,
+ 0xda, 0xfa, 0x36, 0xa7, 0xad, 0xd7, 0xdb, 0x71, 0xa2, 0xc7, 0xd3, 0x88, 0x8d, 0x64, 0xea, 0x28,
+ 0xec, 0xb7, 0x1c, 0x3e, 0xe6, 0x6f, 0xff, 0xa0, 0xd3, 0x47, 0x39, 0xa8, 0xa8, 0x63, 0x5e, 0xc4,
+ 0xc3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x58, 0x21, 0xec, 0xab, 0x03, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// QueryClient is the client API for Query service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type QueryClient interface {
+ // Params queries the parameters of x/feemarket module.
+ Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
+ // BaseFee queries the base fee of the parent block of the current block.
+ BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error)
+ // BlockGas queries the gas used at a given block height
+ BlockGas(ctx context.Context, in *QueryBlockGasRequest, opts ...grpc.CallOption) (*QueryBlockGasResponse, error)
+}
+
+type queryClient struct {
+ cc grpc1.ClientConn
+}
+
+func NewQueryClient(cc grpc1.ClientConn) QueryClient {
+ return &queryClient{cc}
+}
+
+func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) {
+ out := new(QueryParamsResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.feemarket.v1.Query/Params", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error) {
+ out := new(QueryBaseFeeResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.feemarket.v1.Query/BaseFee", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) BlockGas(ctx context.Context, in *QueryBlockGasRequest, opts ...grpc.CallOption) (*QueryBlockGasResponse, error) {
+ out := new(QueryBlockGasResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.feemarket.v1.Query/BlockGas", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// QueryServer is the server API for Query service.
+type QueryServer interface {
+ // Params queries the parameters of x/feemarket module.
+ Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
+ // BaseFee queries the base fee of the parent block of the current block.
+ BaseFee(context.Context, *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error)
+ // BlockGas queries the gas used at a given block height
+ BlockGas(context.Context, *QueryBlockGasRequest) (*QueryBlockGasResponse, error)
+}
+
+// UnimplementedQueryServer can be embedded to have forward compatible implementations.
+type UnimplementedQueryServer struct {
+}
+
+func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
+}
+func (*UnimplementedQueryServer) BaseFee(ctx context.Context, req *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method BaseFee not implemented")
+}
+func (*UnimplementedQueryServer) BlockGas(ctx context.Context, req *QueryBlockGasRequest) (*QueryBlockGasResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method BlockGas not implemented")
+}
+
+func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
+ s.RegisterService(&_Query_serviceDesc, srv)
+}
+
+func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryParamsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).Params(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.feemarket.v1.Query/Params",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_BaseFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryBaseFeeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).BaseFee(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.feemarket.v1.Query/BaseFee",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).BaseFee(ctx, req.(*QueryBaseFeeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_BlockGas_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryBlockGasRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).BlockGas(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.feemarket.v1.Query/BlockGas",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).BlockGas(ctx, req.(*QueryBlockGasRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Query_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "ethermint.feemarket.v1.Query",
+ HandlerType: (*QueryServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Params",
+ Handler: _Query_Params_Handler,
+ },
+ {
+ MethodName: "BaseFee",
+ Handler: _Query_BaseFee_Handler,
+ },
+ {
+ MethodName: "BlockGas",
+ Handler: _Query_BlockGas_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "ethermint/feemarket/v1/query.proto",
+}
+
+func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBaseFeeRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBaseFeeRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBaseFeeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBaseFeeResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBaseFeeResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBaseFeeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.BaseFee != nil {
+ {
+ size := m.BaseFee.Size()
+ i -= size
+ if _, err := m.BaseFee.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBlockGasRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBlockGasRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBlockGasRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryBlockGasResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *QueryBlockGasResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryBlockGasResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Gas != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.Gas))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
+ offset -= sovQuery(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *QueryParamsRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *QueryParamsResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = m.Params.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ return n
+}
+
+func (m *QueryBaseFeeRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *QueryBaseFeeResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.BaseFee != nil {
+ l = m.BaseFee.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryBlockGasRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *QueryBlockGasResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Gas != 0 {
+ n += 1 + sovQuery(uint64(m.Gas))
+ }
+ return n
+}
+
+func sovQuery(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozQuery(x uint64) (n int) {
+ return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBaseFeeRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBaseFeeRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBaseFeeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBaseFeeResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBaseFeeResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBaseFeeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BaseFee", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var v cosmossdk_io_math.Int
+ m.BaseFee = &v
+ if err := m.BaseFee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBlockGasRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBlockGasRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBlockGasRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryBlockGasResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: QueryBlockGasResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryBlockGasResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Gas", wireType)
+ }
+ m.Gas = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Gas |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipQuery(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthQuery
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupQuery
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthQuery
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/feemarket/types/query.pb.gw.go b/x/feemarket/types/query.pb.gw.go
new file mode 100644
index 00000000..2cf37834
--- /dev/null
+++ b/x/feemarket/types/query.pb.gw.go
@@ -0,0 +1,283 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: ethermint/feemarket/v1/query.proto
+
+/*
+Package types is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package types
+
+import (
+ "context"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/grpc-ecosystem/grpc-gateway/utilities"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+// Suppress "imported and not used" errors
+var _ codes.Code
+var _ io.Reader
+var _ status.Status
+var _ = runtime.String
+var _ = utilities.NewDoubleArray
+var _ = descriptor.ForMessage
+var _ = metadata.Join
+
+func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryParamsRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryParamsRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := server.Params(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_BaseFee_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBaseFeeRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := client.BaseFee(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_BaseFee_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBaseFeeRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := server.BaseFee(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_BlockGas_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBlockGasRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := client.BlockGas(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_BlockGas_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryBlockGasRequest
+ var metadata runtime.ServerMetadata
+
+ msg, err := server.BlockGas(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
+// UnaryRPC :call QueryServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
+func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
+
+ mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_BaseFee_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_BaseFee_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_BaseFee_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_BlockGas_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_BlockGas_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_BlockGas_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterQueryHandler(ctx, mux, conn)
+}
+
+// RegisterQueryHandler registers the http handlers for service Query to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
+}
+
+// RegisterQueryHandlerClient registers the http handlers for service Query
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "QueryClient" to call the correct interceptors.
+func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
+
+ mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_BaseFee_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_BaseFee_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_BaseFee_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_BlockGas_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_BlockGas_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_BlockGas_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "feemarket", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_BaseFee_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "feemarket", "v1", "base_fee"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_BlockGas_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"evmos", "feemarket", "v1", "block_gas"}, "", runtime.AssumeColonVerbOpt(false)))
+)
+
+var (
+ forward_Query_Params_0 = runtime.ForwardResponseMessage
+
+ forward_Query_BaseFee_0 = runtime.ForwardResponseMessage
+
+ forward_Query_BlockGas_0 = runtime.ForwardResponseMessage
+)
diff --git a/x/feemarket/types/tx.pb.go b/x/feemarket/types/tx.pb.go
new file mode 100644
index 00000000..0cc39a8d
--- /dev/null
+++ b/x/feemarket/types/tx.pb.go
@@ -0,0 +1,595 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/feemarket/v1/tx.proto
+
+package types
+
+import (
+ context "context"
+ fmt "fmt"
+ _ "github.com/cosmos/cosmos-proto"
+ _ "github.com/cosmos/cosmos-sdk/types/msgservice"
+ _ "github.com/cosmos/gogoproto/gogoproto"
+ grpc1 "github.com/cosmos/gogoproto/grpc"
+ proto "github.com/cosmos/gogoproto/proto"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// MsgUpdateParams defines a Msg for updating the x/feemarket module parameters.
+type MsgUpdateParams struct {
+ // authority is the address of the governance account.
+ Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"`
+ // params defines the x/feemarket parameters to update.
+ // NOTE: All parameters must be supplied.
+ Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"`
+}
+
+func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} }
+func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) }
+func (*MsgUpdateParams) ProtoMessage() {}
+func (*MsgUpdateParams) Descriptor() ([]byte, []int) {
+ return fileDescriptor_78aff2584dbf2838, []int{0}
+}
+func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *MsgUpdateParams) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgUpdateParams.Merge(m, src)
+}
+func (m *MsgUpdateParams) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgUpdateParams) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo
+
+func (m *MsgUpdateParams) GetAuthority() string {
+ if m != nil {
+ return m.Authority
+ }
+ return ""
+}
+
+func (m *MsgUpdateParams) GetParams() Params {
+ if m != nil {
+ return m.Params
+ }
+ return Params{}
+}
+
+// MsgUpdateParamsResponse defines the response structure for executing a
+// MsgUpdateParams message.
+type MsgUpdateParamsResponse struct {
+}
+
+func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} }
+func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgUpdateParamsResponse) ProtoMessage() {}
+func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_78aff2584dbf2838, []int{1}
+}
+func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src)
+}
+func (m *MsgUpdateParamsResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterType((*MsgUpdateParams)(nil), "ethermint.feemarket.v1.MsgUpdateParams")
+ proto.RegisterType((*MsgUpdateParamsResponse)(nil), "ethermint.feemarket.v1.MsgUpdateParamsResponse")
+}
+
+func init() { proto.RegisterFile("ethermint/feemarket/v1/tx.proto", fileDescriptor_78aff2584dbf2838) }
+
+var fileDescriptor_78aff2584dbf2838 = []byte{
+ // 323 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0x2d, 0xc9, 0x48,
+ 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x4b, 0x4d, 0xcd, 0x4d, 0x2c, 0xca, 0x4e, 0x2d, 0xd1,
+ 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x83, 0x2b, 0xd0,
+ 0x83, 0x2b, 0xd0, 0x2b, 0x33, 0x94, 0x12, 0x4f, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0xd6, 0xcf, 0x2d,
+ 0x4e, 0x07, 0xa9, 0xcf, 0x2d, 0x4e, 0x87, 0x68, 0x90, 0x92, 0x84, 0x48, 0xc4, 0x83, 0x79, 0xfa,
+ 0x10, 0x0e, 0x54, 0x4a, 0x0d, 0x87, 0x65, 0x08, 0x83, 0x21, 0xea, 0x44, 0xd2, 0xf3, 0xd3, 0xf3,
+ 0x21, 0xfa, 0x41, 0x2c, 0x88, 0xa8, 0xd2, 0x74, 0x46, 0x2e, 0x7e, 0xdf, 0xe2, 0xf4, 0xd0, 0x82,
+ 0x94, 0xc4, 0x92, 0xd4, 0x80, 0xc4, 0xa2, 0xc4, 0xdc, 0x62, 0x21, 0x33, 0x2e, 0xce, 0xc4, 0xd2,
+ 0x92, 0x8c, 0xfc, 0xa2, 0xcc, 0x92, 0x4a, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x4e, 0x27, 0x89, 0x4b,
+ 0x5b, 0x74, 0x45, 0xa0, 0xd6, 0x3a, 0xa6, 0xa4, 0x14, 0xa5, 0x16, 0x17, 0x07, 0x97, 0x14, 0x65,
+ 0xe6, 0xa5, 0x07, 0x21, 0x94, 0x0a, 0xd9, 0x70, 0xb1, 0x15, 0x80, 0x4d, 0x90, 0x60, 0x52, 0x60,
+ 0xd4, 0xe0, 0x36, 0x92, 0xd3, 0xc3, 0xee, 0x4d, 0x3d, 0x88, 0x3d, 0x4e, 0x2c, 0x27, 0xee, 0xc9,
+ 0x33, 0x04, 0x41, 0xf5, 0x58, 0xf1, 0x35, 0x3d, 0xdf, 0xa0, 0x85, 0x30, 0x4d, 0x49, 0x92, 0x4b,
+ 0x1c, 0xcd, 0x61, 0x41, 0xa9, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x46, 0xf9, 0x5c, 0xcc, 0xbe,
+ 0xc5, 0xe9, 0x42, 0x19, 0x5c, 0x3c, 0x28, 0xee, 0x56, 0xc7, 0x65, 0x1f, 0x9a, 0x39, 0x52, 0xfa,
+ 0x44, 0x2a, 0x84, 0x59, 0xe8, 0xe4, 0x76, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f,
+ 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c,
+ 0x51, 0x3a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xa9, 0x65, 0xa0,
+ 0xb8, 0x83, 0x90, 0x65, 0x86, 0x16, 0xfa, 0x15, 0x48, 0x11, 0x52, 0x52, 0x59, 0x90, 0x5a, 0x9c,
+ 0xc4, 0x06, 0x0e, 0x74, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb9, 0x9c, 0xe1, 0x8d, 0x21,
+ 0x02, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// MsgClient is the client API for Msg service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type MsgClient interface {
+ // UpdateParams defined a governance operation for updating the x/feemarket module parameters.
+ // The authority is hard-coded to the Cosmos SDK x/gov module account
+ UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error)
+}
+
+type msgClient struct {
+ cc grpc1.ClientConn
+}
+
+func NewMsgClient(cc grpc1.ClientConn) MsgClient {
+ return &msgClient{cc}
+}
+
+func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) {
+ out := new(MsgUpdateParamsResponse)
+ err := c.cc.Invoke(ctx, "/ethermint.feemarket.v1.Msg/UpdateParams", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// MsgServer is the server API for Msg service.
+type MsgServer interface {
+ // UpdateParams defined a governance operation for updating the x/feemarket module parameters.
+ // The authority is hard-coded to the Cosmos SDK x/gov module account
+ UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error)
+}
+
+// UnimplementedMsgServer can be embedded to have forward compatible implementations.
+type UnimplementedMsgServer struct {
+}
+
+func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented")
+}
+
+func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
+ s.RegisterService(&_Msg_serviceDesc, srv)
+}
+
+func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MsgUpdateParams)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MsgServer).UpdateParams(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ethermint.feemarket.v1.Msg/UpdateParams",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Msg_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "ethermint.feemarket.v1.Msg",
+ HandlerType: (*MsgServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "UpdateParams",
+ Handler: _Msg_UpdateParams_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "ethermint/feemarket/v1/tx.proto",
+}
+
+func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ if len(m.Authority) > 0 {
+ i -= len(m.Authority)
+ copy(dAtA[i:], m.Authority)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Authority)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintTx(dAtA []byte, offset int, v uint64) int {
+ offset -= sovTx(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *MsgUpdateParams) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Authority)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = m.Params.Size()
+ n += 1 + l + sovTx(uint64(l))
+ return n
+}
+
+func (m *MsgUpdateParamsResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func sovTx(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTx(x uint64) (n int) {
+ return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Authority = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipTx(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthTx
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupTx
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthTx
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowTx = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/feemarket/types/tx.pb.gw.go b/x/feemarket/types/tx.pb.gw.go
new file mode 100644
index 00000000..94e8fb7d
--- /dev/null
+++ b/x/feemarket/types/tx.pb.gw.go
@@ -0,0 +1,161 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: ethermint/feemarket/v1/tx.proto
+
+/*
+Package types is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package types
+
+import (
+ "context"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/grpc-ecosystem/grpc-gateway/utilities"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+// Suppress "imported and not used" errors
+var (
+ _ codes.Code
+ _ io.Reader
+ _ status.Status
+ _ = runtime.String
+ _ = utilities.NewDoubleArray
+ _ = descriptor.ForMessage
+ _ = metadata.Join
+)
+
+var filter_Msg_UpdateParams_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+
+func request_Msg_UpdateParams_0(ctx context.Context, marshaler runtime.Marshaler, client MsgClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq MsgUpdateParams
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_UpdateParams_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UpdateParams(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+}
+
+func local_request_Msg_UpdateParams_0(ctx context.Context, marshaler runtime.Marshaler, server MsgServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq MsgUpdateParams
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_UpdateParams_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UpdateParams(ctx, &protoReq)
+ return msg, metadata, err
+}
+
+// RegisterMsgHandlerServer registers the http handlers for service Msg to "mux".
+// UnaryRPC :call MsgServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterMsgHandlerFromEndpoint instead.
+func RegisterMsgHandlerServer(ctx context.Context, mux *runtime.ServeMux, server MsgServer) error {
+ mux.Handle("POST", pattern_Msg_UpdateParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Msg_UpdateParams_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Msg_UpdateParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+ })
+
+ return nil
+}
+
+// RegisterMsgHandlerFromEndpoint is same as RegisterMsgHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterMsgHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterMsgHandler(ctx, mux, conn)
+}
+
+// RegisterMsgHandler registers the http handlers for service Msg to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterMsgHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterMsgHandlerClient(ctx, mux, NewMsgClient(conn))
+}
+
+// RegisterMsgHandlerClient registers the http handlers for service Msg
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "MsgClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "MsgClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "MsgClient" to call the correct interceptors.
+func RegisterMsgHandlerClient(ctx context.Context, mux *runtime.ServeMux, client MsgClient) error {
+ mux.Handle("POST", pattern_Msg_UpdateParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Msg_UpdateParams_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Msg_UpdateParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+ })
+
+ return nil
+}
+
+var pattern_Msg_UpdateParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ethermint", "feemarket", "v1", "tx", "update_params"}, "", runtime.AssumeColonVerbOpt(false)))
+
+var forward_Msg_UpdateParams_0 = runtime.ForwardResponseMessage