Skip to content

Commit

Permalink
Add antehandler for EVM to check gas exceed limit or not (#1821)
Browse files Browse the repository at this point in the history
* Add antehandler for EVM to check gas exceed limit or not

* Separate the check for EVM message

* Fix lint

* Fix some test

* Fix gas

* Enable log

* Add log

* Add log

* Add stdout

* Fix docker

* Fix associate tx causing chain halt issue

* fix go mod

* Fix lint

* Removel og

* Fix gas

* Fix gas

* Fix go mod

* Fix unit test

* fix docker
  • Loading branch information
yzang2019 authored Aug 30, 2024
1 parent f50837e commit 942e73d
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 57 deletions.
92 changes: 51 additions & 41 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,25 @@ import (
"sync"
"time"

"github.com/cosmos/cosmos-sdk/server"
"github.com/gorilla/mux"
"github.com/rakyll/statik/fs"
"github.com/sei-protocol/sei-db/ss"

"github.com/ethereum/go-ethereum/ethclient"
ethrpc "github.com/ethereum/go-ethereum/rpc"
"github.com/sei-protocol/sei-chain/app/antedecorators"
"github.com/sei-protocol/sei-chain/evmrpc"
"github.com/sei-protocol/sei-chain/precompiles"
"go.opentelemetry.io/otel/trace"

storetypes "github.com/cosmos/cosmos-sdk/store/types"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkacltypes "github.com/cosmos/cosmos-sdk/types/accesscontrol"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
genesistypes "github.com/cosmos/cosmos-sdk/types/genesis"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
aclmodule "github.com/cosmos/cosmos-sdk/x/accesscontrol"
aclclient "github.com/cosmos/cosmos-sdk/x/accesscontrol/client"
aclconstants "github.com/cosmos/cosmos-sdk/x/accesscontrol/constants"
Expand Down Expand Up @@ -114,13 +101,24 @@ import (
ibcporttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types"
ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper"
"github.com/ethereum/go-ethereum/ethclient"
ethrpc "github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/mux"
"github.com/rakyll/statik/fs"
"github.com/sei-protocol/sei-chain/aclmapping"
aclutils "github.com/sei-protocol/sei-chain/aclmapping/utils"
"github.com/sei-protocol/sei-chain/app/antedecorators"
appparams "github.com/sei-protocol/sei-chain/app/params"
"github.com/sei-protocol/sei-chain/app/upgrades"
v0upgrade "github.com/sei-protocol/sei-chain/app/upgrades/v0"
"github.com/sei-protocol/sei-chain/evmrpc"
"github.com/sei-protocol/sei-chain/precompiles"
"github.com/sei-protocol/sei-chain/utils"
"github.com/sei-protocol/sei-chain/utils/metrics"
"github.com/sei-protocol/sei-chain/wasmbinding"
epochmodule "github.com/sei-protocol/sei-chain/x/epoch"
epochmodulekeeper "github.com/sei-protocol/sei-chain/x/epoch/keeper"
epochmoduletypes "github.com/sei-protocol/sei-chain/x/epoch/types"
"github.com/sei-protocol/sei-chain/x/evm"
evmante "github.com/sei-protocol/sei-chain/x/evm/ante"
"github.com/sei-protocol/sei-chain/x/evm/blocktest"
Expand All @@ -132,6 +130,13 @@ import (
mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli"
mintkeeper "github.com/sei-protocol/sei-chain/x/mint/keeper"
minttypes "github.com/sei-protocol/sei-chain/x/mint/types"
oraclemodule "github.com/sei-protocol/sei-chain/x/oracle"
oraclekeeper "github.com/sei-protocol/sei-chain/x/oracle/keeper"
oracletypes "github.com/sei-protocol/sei-chain/x/oracle/types"
tokenfactorymodule "github.com/sei-protocol/sei-chain/x/tokenfactory"
tokenfactorykeeper "github.com/sei-protocol/sei-chain/x/tokenfactory/keeper"
tokenfactorytypes "github.com/sei-protocol/sei-chain/x/tokenfactory/types"
"github.com/sei-protocol/sei-db/ss"
seidb "github.com/sei-protocol/sei-db/ss/types"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
Expand All @@ -140,20 +145,7 @@ import (
tmos "github.com/tendermint/tendermint/libs/os"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"

"github.com/sei-protocol/sei-chain/utils/metrics"

oraclemodule "github.com/sei-protocol/sei-chain/x/oracle"
oraclekeeper "github.com/sei-protocol/sei-chain/x/oracle/keeper"
oracletypes "github.com/sei-protocol/sei-chain/x/oracle/types"

epochmodule "github.com/sei-protocol/sei-chain/x/epoch"
epochmodulekeeper "github.com/sei-protocol/sei-chain/x/epoch/keeper"
epochmoduletypes "github.com/sei-protocol/sei-chain/x/epoch/types"

tokenfactorymodule "github.com/sei-protocol/sei-chain/x/tokenfactory"
tokenfactorykeeper "github.com/sei-protocol/sei-chain/x/tokenfactory/keeper"
tokenfactorytypes "github.com/sei-protocol/sei-chain/x/tokenfactory/types"
"go.opentelemetry.io/otel/trace"

// this line is used by starport scaffolding # stargate/app/moduleImport

Expand All @@ -163,7 +155,6 @@ import (

// unnamed import of statik for openapi/swagger UI support
_ "github.com/sei-protocol/sei-chain/docs/swagger"

ssconfig "github.com/sei-protocol/sei-db/config"
)

Expand Down Expand Up @@ -1859,26 +1850,45 @@ func RegisterSwaggerAPI(rtr *mux.Router) {
func (app *App) checkTotalBlockGasWanted(ctx sdk.Context, txs [][]byte) bool {
totalGasWanted := uint64(0)
for _, tx := range txs {
decoded, err := app.txDecoder(tx)
decodedTx, err := app.txDecoder(tx)
if err != nil {
// such tx will not be processed and thus won't consume gas. Skipping
continue
}
feeTx, ok := decoded.(sdk.FeeTx)
if !ok {
// such tx will not be processed and thus won't consume gas. Skipping
continue
}
isGasless, err := antedecorators.IsTxGasless(decoded, ctx, app.OracleKeeper, &app.EvmKeeper)
// check gasless first (this has to happen before other checks to avoid panics)
isGasless, err := antedecorators.IsTxGasless(decodedTx, ctx, app.OracleKeeper, &app.EvmKeeper)
if err != nil {
ctx.Logger().Error("error checking if tx is gasless", "error", err)
continue
}
if isGasless {
continue
}
// Check for overflow before adding
gasWanted := feeTx.GetGas()
// Check whether it's associate tx
gasWanted := uint64(0)
// Check whether it's an EVM or Cosmos tx
isEVM, err := evmante.IsEVMMessage(decodedTx)
if err != nil {
continue
}
if isEVM {
msg := evmtypes.MustGetEVMTransactionMessage(decodedTx)
if msg.IsAssociateTx() {
continue
}
etx, _ := msg.AsTransaction()
gasWanted = etx.Gas()
} else {
feeTx, ok := decodedTx.(sdk.FeeTx)
if !ok {
// such tx will not be processed and thus won't consume gas. Skipping
continue
}

// Check for overflow before adding
gasWanted = feeTx.GetGas()
}

if int64(gasWanted) < 0 || int64(totalGasWanted) > math.MaxInt64-int64(gasWanted) {
return false
}
Expand Down
8 changes: 4 additions & 4 deletions contracts/test/AssociateTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ describe("Associate Balances", function () {
const afterSei = BigInt(await getSeiBalance(seiAddr))
const afterEvm = await ethers.provider.getBalance(evmAddr)

// console.log(`SEI Balance (before): ${beforeSei}`)
// console.log(`EVM Balance (before): ${beforeEvm}`)
// console.log(`SEI Balance (after): ${afterSei}`)
// console.log(`EVM Balance (after): ${afterEvm}`)
console.log(`SEI Balance (before): ${beforeSei}`)
console.log(`EVM Balance (before): ${beforeEvm}`)
console.log(`SEI Balance (after): ${afterSei}`)
console.log(`EVM Balance (after): ${afterEvm}`)

const multiplier = BigInt(1000000000000)
expect(afterEvm).to.equal((beforeSei * multiplier) + beforeEvm - (gas * multiplier))
Expand Down
2 changes: 0 additions & 2 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.3'

services:
node0:
platform: linux/amd64
Expand Down
3 changes: 1 addition & 2 deletions docker/localnode/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
FROM ubuntu:latest
ENV HOME="/root" PATH="/root/go/bin:/sei-protocol/sei-chain/integration_test/upgrade_module/scripts/:$PATH"
RUN apt-get update && \
apt-get install -y make git build-essential jq python3 curl vim uuid-runtime nodejs
RUN apt-get update && apt-get install -y make build-essential git jq python3 curl vim uuid-runtime
RUN curl -L https://go.dev/dl/go1.22.4.linux-amd64.tar.gz | tar xvzf - -C /usr/local/
RUN curl -L https://foundry.paradigm.xyz | bash
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ require (
replace (
github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.2.4-0.20240816184629-eb6d20caf603
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.33
github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.34
github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9
github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.2
github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-22 h1:t/m1qXER+DEMrcpqgoYmUxifkA
github.com/sei-protocol/go-ethereum v1.13.5-sei-22/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ=
github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA=
github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8=
github.com/sei-protocol/sei-cosmos v0.3.33 h1:6BmEmNOqotT0OqwLFQiCyRcZTxJfG/x/CNQadljAKok=
github.com/sei-protocol/sei-cosmos v0.3.33/go.mod h1:og/KbejR/zSQ8otapODEDU9zYNhFSUDbq9+tgeYePyU=
github.com/sei-protocol/sei-cosmos v0.3.34 h1:U2TqBEMJC9ztDqSxi7ET+HEEx0CyyAs6D+Y5VOfYTAc=
github.com/sei-protocol/sei-cosmos v0.3.34/go.mod h1:og/KbejR/zSQ8otapODEDU9zYNhFSUDbq9+tgeYePyU=
github.com/sei-protocol/sei-db v0.0.43 h1:m9kIWqSBCvKRLPGbAttlqCytIlPxVZbKchAEbVKSHHk=
github.com/sei-protocol/sei-db v0.0.43/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI=
github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE=
Expand Down
154 changes: 154 additions & 0 deletions integration_test/dapp_tests/steak/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
const { execute } = require("../../../contracts/test/lib");

const encodeBase64 = (obj) => {
return Buffer.from(JSON.stringify(obj)).toString("base64");
};

const getValidators = async () => {
const command = `seid q staking validators --output json`;
const output = await execute(command);
const response = JSON.parse(output);
return response.validators.map((v) => v.operator_address);
};

const getCodeIdFromContractAddress = async (contractAddress) => {
const command = `seid q wasm contract ${contractAddress} --output json`;
const output = await execute(command);
const response = JSON.parse(output);
return response.contract_info.code_id;
};

// Note: Not using the `deployWasm` function because we need to retrieve the
// hub and token contract addresses from the event logs
const instantiateHubContract = async (
codeId,
adminAddress,
instantiateMsg,
label
) => {
const jsonString = JSON.stringify(instantiateMsg).replace(/"/g, '\\"');
const command = `seid tx wasm instantiate ${codeId} "${jsonString}" --label ${label} --admin ${adminAddress} --from admin --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json`;
const output = await execute(command);
const response = JSON.parse(output);
// Get all attributes with _contractAddress
if (!response.logs || response.logs.length === 0) {
throw new Error("logs not returned");
}
const addresses = [];
for (let event of response.logs[0].events) {
if (event.type === "instantiate") {
for (let attribute of event.attributes) {
if (attribute.key === "_contract_address") {
addresses.push(attribute.value);
}
}
}
}

// Return hub and token contracts
const contracts = {};
for (let address of addresses) {
const contractCodeId = await getCodeIdFromContractAddress(address);
if (contractCodeId === `${codeId}`) {
contracts.hubContract = address;
} else {
contracts.tokenContract = address;
}
}
return contracts;
};

const bond = async (contractAddress, address, amount) => {
const msg = {
bond: {},
};
const jsonString = JSON.stringify(msg).replace(/"/g, '\\"');
const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --amount=${amount}usei --from=${address} --gas=500000 --gas-prices=0.1usei --broadcast-mode=block -y --output=json`;
const output = await execute(command);
const response = JSON.parse(output);
if (response.code !== 0) {
throw new Error(response.raw_log);
}
return response;
};

const unbond = async (hubAddress, tokenAddress, address, amount) => {
const msg = {
send: {
contract: hubAddress,
amount: `${amount}`,
msg: encodeBase64({
queue_unbond: {},
}),
},
};
const jsonString = JSON.stringify(msg).replace(/"/g, '\\"');
const command = `seid tx wasm execute ${tokenAddress} "${jsonString}" --from=${address} --gas=500000 --gas-prices=0.1usei --broadcast-mode=block -y --output=json`;
const output = await execute(command);
const response = JSON.parse(output);
if (response.code !== 0) {
throw new Error(response.raw_log);
}
return response;
};

const harvest = async (contractAddress, address) => {
const msg = {
harvest: {},
};
const jsonString = JSON.stringify(msg).replace(/"/g, '\\"');
const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --from=${address} --gas=500000 --gas-prices=0.1usei --broadcast-mode=block -y --output=json`;
const output = await execute(command);
const response = JSON.parse(output);
if (response.code !== 0) {
throw new Error(response.raw_log);
}
return response;
};

const queryTokenBalance = async (contractAddress, address) => {
const msg = {
balance: {
address,
},
};
const jsonString = JSON.stringify(msg).replace(/"/g, '\\"');
const command = `seid q wasm contract-state smart ${contractAddress} "${jsonString}" --output=json`;
const output = await execute(command);
const response = JSON.parse(output);
return response.data.balance;
};

const addAccount = async (accountName) => {
const command = `seid keys add ${accountName}-${Date.now()} --output=json`;
const output = await execute(command);
return JSON.parse(output);
};

const transferTokens = async (tokenAddress, sender, destination, amount) => {
const msg = {
transfer: {
recipient: destination,
amount: `${amount}`,
},
};
const jsonString = JSON.stringify(msg).replace(/"/g, '\\"');
const command = `seid tx wasm execute ${tokenAddress} "${jsonString}" --from=${sender} --gas=200000 --gas-prices=0.1usei --broadcast-mode=block -y --output=json`;
const output = await execute(command);
const response = JSON.parse(output);
if (response.code !== 0) {
throw new Error(response.raw_log);
}
return response;
};

module.exports = {
getValidators,
instantiateHubContract,
bond,
unbond,
harvest,
queryTokenBalance,
addAccount,
transferTokens,
};
9 changes: 9 additions & 0 deletions x/evm/ante/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ func (gl BasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, n
return ctx, sdkerrors.ErrUnsupportedTxType
}

// Check if gas exceed the limit
if cp := ctx.ConsensusParams(); cp != nil && cp.Block != nil {
// If there exists a maximum block gas limit, we must ensure that the tx
// does not exceed it.
if cp.Block.MaxGas > 0 && etx.Gas() > uint64(cp.Block.MaxGas) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "tx gas limit %d exceeds block max gas %d", etx.Gas(), cp.Block.MaxGas)
}
}

//TODO: support blobs (leaving this commented out)
// Ensure blob transactions have valid commitments
//if etx.Type() == ethtypes.BlobTxType {
Expand Down
Loading

0 comments on commit 942e73d

Please sign in to comment.