Skip to content

Commit 9ff0798

Browse files
authored
fix: payout gas limit estimation (flashbots#523)
## 📝 Summary Fix payout gas limit estimation for new revm semantics. ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [ ] Added tests (if applicable)
1 parent acf57ce commit 9ff0798

File tree

5 files changed

+81
-9
lines changed

5 files changed

+81
-9
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rbuilder/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ built = { version = "0.7.1", features = ["git2", "chrono"] }
142142

143143
[dev-dependencies]
144144
tempfile = "3.8"
145+
assert_matches = "1.5.0"
145146
criterion = { version = "0.5.1", features = ["html_reports", "async_tokio"] }
146147

147148
[features]

crates/rbuilder/src/building/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ impl<Tracer: SimulationTracer> PartialBlock<Tracer> {
597597
nonce,
598598
ctx.attributes.suggested_fee_recipient,
599599
gas_limit,
600-
value.to(),
600+
value,
601601
)?;
602602
// payout tx has no blobs so it's safe to unwrap
603603
let tx = TransactionSignedEcRecoveredWithBlobs::new_no_blobs(tx).unwrap();

crates/rbuilder/src/building/order_commit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> {
593593
nonce,
594594
to,
595595
payout.gas_limit,
596-
payout.tx_value.to(),
596+
payout.tx_value,
597597
) {
598598
// payout tx has no blobs so it's safe to unwrap
599599
Ok(tx) => TransactionSignedEcRecoveredWithBlobs::new_no_blobs(tx).unwrap(),

crates/rbuilder/src/building/payout_tx.rs

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn create_payout_tx(
1515
nonce: u64,
1616
to: Address,
1717
gas_limit: u64,
18-
value: u128,
18+
value: U256,
1919
) -> Result<Recovered<TransactionSigned>, secp256k1::Error> {
2020
let tx = Transaction::Eip1559(TxEip1559 {
2121
chain_id: chain_spec.chain.id(),
@@ -24,7 +24,7 @@ pub fn create_payout_tx(
2424
max_fee_per_gas: basefee as u128,
2525
max_priority_fee_per_gas: 0,
2626
to: TransactionKind::Call(to),
27-
value: U256::from(value),
27+
value,
2828
..Default::default()
2929
});
3030

@@ -53,22 +53,23 @@ pub fn insert_test_payout_tx(
5353

5454
let nonce = state.nonce(builder_signer.address)?;
5555

56-
let mut cfg = ctx.evm_env.cfg_env.clone();
57-
// disable balance check so we can estimate the gas cost without having any funds
58-
cfg.disable_balance_check = true;
59-
56+
let tx_value = 10u128.pow(18); // 10 ether
6057
let tx = create_payout_tx(
6158
ctx.chain_spec.as_ref(),
6259
ctx.evm_env.block_env.basefee,
6360
builder_signer,
6461
nonce,
6562
to,
6663
gas_limit,
67-
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
64+
U256::from(tx_value),
6865
)?;
6966

7067
let mut db = state.new_db_ref();
7168
let mut evm = ctx.evm_factory.create_evm(db.as_mut(), ctx.evm_env.clone());
69+
70+
let cache_account = evm.db_mut().load_cache_account(builder_signer.address)?;
71+
cache_account.increment_balance(tx_value * 2); // double to cover tx value and fee
72+
7273
let res = evm.transact(&tx)?;
7374
match res.result {
7475
ExecutionResult::Success {
@@ -130,3 +131,66 @@ pub fn estimate_payout_gas_limit(
130131
}
131132
}
132133
}
134+
135+
#[cfg(test)]
136+
mod tests {
137+
use super::*;
138+
use crate::building::builders::mock_block_building_helper::MockRootHasher;
139+
use alloy_eips::eip1559::INITIAL_BASE_FEE;
140+
use alloy_primitives::B256;
141+
use assert_matches::assert_matches;
142+
use reth_chainspec::{EthereumHardfork, MAINNET};
143+
use reth_db::{tables, transaction::DbTxMut};
144+
use reth_primitives::Account;
145+
use reth_provider::test_utils::create_test_provider_factory_with_chain_spec;
146+
use revm::primitives::hardfork::SpecId;
147+
use std::sync::Arc;
148+
149+
#[test]
150+
fn estimate_payout_tx_gas_limit() {
151+
let signer = Signer::random();
152+
let proposer = Address::random();
153+
let chain_spec = MAINNET.clone();
154+
let spec_id = SpecId::CANCUN;
155+
let cancun_timestamp = chain_spec
156+
.fork(EthereumHardfork::Cancun)
157+
.as_timestamp()
158+
.unwrap();
159+
160+
// Insert proposer
161+
let provider_factory = create_test_provider_factory_with_chain_spec(chain_spec.clone());
162+
let provider_rw = provider_factory.provider_rw().unwrap();
163+
provider_rw
164+
.tx_ref()
165+
.put::<tables::PlainAccountState>(
166+
proposer,
167+
Account {
168+
balance: U256::ZERO,
169+
nonce: 1,
170+
bytecode_hash: Some(B256::random()),
171+
},
172+
)
173+
.unwrap();
174+
provider_rw.commit().unwrap();
175+
176+
let mut block: alloy_rpc_types::Block = Default::default();
177+
block.header.base_fee_per_gas = Some(INITIAL_BASE_FEE);
178+
block.header.timestamp = cancun_timestamp + 1;
179+
block.header.gas_limit = 30_000_000;
180+
let ctx = BlockBuildingContext::from_onchain_block(
181+
block,
182+
chain_spec,
183+
Some(spec_id),
184+
Default::default(),
185+
signer.address,
186+
proposer,
187+
Some(signer),
188+
Arc::new(MockRootHasher {}),
189+
);
190+
let mut state = BlockState::new(provider_factory.latest().unwrap());
191+
192+
let estimate_result = estimate_payout_gas_limit(proposer, &ctx, &mut state, 0);
193+
assert_matches!(estimate_result, Ok(_));
194+
assert_eq!(estimate_result.unwrap(), 21_000);
195+
}
196+
}

0 commit comments

Comments
 (0)