-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(evm): gas usage in precompiles: limits, local gas meters #2093
Changes from 16 commits
87355c8
c27bdad
abd2d91
f3e3b87
67de775
6845613
84c63b6
362ed5a
3c9a984
c37446a
f602811
3dc8f2c
50c8247
947ddce
10fac9e
3ee5f59
df34075
8151d98
3b94b1b
6ff8739
c43219e
e53d6ad
dfaf522
cdeb00d
f688bae
fe15859
e67045e
f5d37ac
667aec8
fcaa604
fa8063c
6d0deb8
8d0e2fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
types | ||
artifacts | ||
cache | ||
.env |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,11 +71,7 @@ func (k Keeper) CallContractWithInput( | |
) (evmResp *evm.MsgEthereumTxResponse, evmObj *vm.EVM, err error) { | ||
// This is a `defer` pattern to add behavior that runs in the case that the | ||
// error is non-nil, creating a concise way to add extra information. | ||
defer func() { | ||
if err != nil { | ||
err = fmt.Errorf("CallContractError: %w", err) | ||
} | ||
}() | ||
defer HandleOutOfGasPanic(&err, "CallContractError") | ||
nonce := k.GetAccNonce(ctx, fromAcc) | ||
|
||
unusedBigInt := big.NewInt(0) | ||
|
@@ -108,11 +104,8 @@ func (k Keeper) CallContractWithInput( | |
// sent by a user | ||
txConfig := k.TxConfig(ctx, gethcommon.BigToHash(big.NewInt(0))) | ||
|
||
// Using tmp context to not modify the state in case of evm revert | ||
tmpCtx, commitCtx := ctx.CacheContext() | ||
|
||
evmResp, evmObj, err = k.ApplyEvmMsg( | ||
tmpCtx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, true, | ||
ctx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, true, | ||
) | ||
if err != nil { | ||
// We don't know the actual gas used, so consuming the gas limit | ||
|
@@ -135,20 +128,21 @@ func (k Keeper) CallContractWithInput( | |
} else { | ||
// Success, committing the state to ctx | ||
if commit { | ||
commitCtx() | ||
totalGasUsed, err := k.AddToBlockGasUsed(ctx, evmResp.GasUsed) | ||
blockGasUsed, err := k.AddToBlockGasUsed(ctx, evmResp.GasUsed) | ||
if err != nil { | ||
k.ResetGasMeterAndConsumeGas(ctx, ctx.GasMeter().Limit()) | ||
return nil, nil, errors.Wrap(err, "error adding transient gas used to block") | ||
} | ||
k.ResetGasMeterAndConsumeGas(ctx, totalGasUsed) | ||
k.ResetGasMeterAndConsumeGas(ctx, blockGasUsed) | ||
k.updateBlockBloom(ctx, evmResp, uint64(txConfig.LogIndex)) | ||
err = k.EmitEthereumTxEvents(ctx, contract, gethcore.LegacyTxType, evmMsg, evmResp) | ||
if err != nil { | ||
return nil, nil, errors.Wrap(err, "error emitting ethereum tx events") | ||
} | ||
blockTxIdx := uint64(txConfig.TxIndex) + 1 | ||
k.EvmState.BlockTxIndex.Set(ctx, blockTxIdx) | ||
// TODO: remove after migrating logs | ||
//err = k.EmitLogEvents(ctx, evmResp) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be removed? |
||
//if err != nil { | ||
// return nil, nil, errors.Wrap(err, "error emitting tx logs") | ||
//} | ||
|
||
//blockTxIdx := uint64(txConfig.TxIndex) + 1 | ||
//k.EvmState.BlockTxIndex.Set(ctx, blockTxIdx) | ||
} | ||
return evmResp, evmObj, nil | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,7 @@ func (s *Suite) TestERC20Calls() { | |
s.T().Log("Transfer - Not enough funds") | ||
{ | ||
amt := big.NewInt(9_420) | ||
_, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, amt, deps.Ctx) | ||
_, _, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, amt, deps.Ctx) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider verifying gas usage in transfer failure test. Given that the PR focuses on gas management, we should capture and verify the gas usage (currently ignored with - _, _, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, amt, deps.Ctx)
+ _, gasUsed, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, amt, deps.Ctx)
+ s.Require().Greater(gasUsed.Uint64(), uint64(0), "should consume gas even on failure")
|
||
s.ErrorContains(err, "ERC20: transfer amount exceeds balance") | ||
// balances unchanged | ||
evmtest.AssertERC20BalanceEqual(s.T(), deps, contract, deps.Sender.EthAddr, big.NewInt(0)) | ||
|
@@ -45,7 +45,7 @@ func (s *Suite) TestERC20Calls() { | |
s.T().Log("Transfer - Success (sanity check)") | ||
{ | ||
amt := big.NewInt(9_420) | ||
sentAmt, err := deps.EvmKeeper.ERC20().Transfer( | ||
sentAmt, _, err := deps.EvmKeeper.ERC20().Transfer( | ||
contract, evm.EVM_MODULE_ADDRESS, deps.Sender.EthAddr, amt, deps.Ctx, | ||
) | ||
s.Require().NoError(err) | ||
Comment on lines
+48
to
51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test coverage for gas management. The success case should verify gas consumption and include additional test cases for gas limits, aligning with the PR's objectives for precompile gas management. - sentAmt, _, err := deps.EvmKeeper.ERC20().Transfer(
+ sentAmt, gasUsed, err := deps.EvmKeeper.ERC20().Transfer(
contract, evm.EVM_MODULE_ADDRESS, deps.Sender.EthAddr, amt, deps.Ctx,
)
s.Require().NoError(err)
+ s.Require().Greater(gasUsed.Uint64(), uint64(0), "successful transfer should consume gas") Consider adding a new test case: s.T().Log("Transfer - Respects gas limits")
{
amt := big.NewInt(1000)
// Test with insufficient gas limit
lowGasCtx := deps.Ctx.WithGasMeter(sdk.NewGasMeter(100))
_, gasUsed, err := deps.EvmKeeper.ERC20().Transfer(
contract, evm.EVM_MODULE_ADDRESS, deps.Sender.EthAddr, amt, lowGasCtx,
)
s.ErrorContains(err, "out of gas")
} |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Optimize error handling using custom errors.
The current string concatenation approach for error messages is gas-intensive. Consider using custom errors, which are more gas-efficient and provide the same level of detail.
Here's how you could optimize this: