Skip to content

Commit 8492bda

Browse files
committed
chore: update by review tips
1 parent b34f762 commit 8492bda

1 file changed

Lines changed: 70 additions & 6 deletions

File tree

src/evm/api/mod.rs

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,18 @@ impl<DB: Database, I> BscEvm<DB, I> {
110110
}
111111
}
112112

113-
/// Fund the beneficiary with `value` so a value-transferring BSC system tx
114-
/// (e.g. the block-reward deposit) does not fail balance checks during trace
115-
/// replay — archive state at block start has not yet received that reward.
116-
/// Trace-mode only; callers must gate on `tx.is_system_transaction`.
113+
/// Stand in for `post_execution::distribute_incoming`'s SYSTEM_ADDRESS →
114+
/// validator credit, which trace replay skips. Use `incr_balance`, not
115+
/// `set_balance`, so the archive-state balance survives the deposit's
116+
/// `B + V → B` round-trip. Runs before the handler's tx checkpoint, so a
117+
/// (very unlikely) system-tx revert would leave the top-up in place.
117118
pub(crate) fn fund_beneficiary_for_system_tx_replay(&mut self, value: revm::primitives::U256) {
118-
if !self.trace {
119+
if !self.trace || value.is_zero() {
119120
return;
120121
}
121122
let beneficiary = self.block.beneficiary;
122123
if let Ok(mut account) = self.journal_mut().load_account_mut(beneficiary) {
123-
account.set_balance(value);
124+
let _ = account.incr_balance(value);
124125
}
125126
}
126127
}
@@ -558,4 +559,67 @@ mod tests {
558559
"system transaction should be marked after inspect_one_tx()"
559560
);
560561
}
562+
563+
fn read_beneficiary_balance(
564+
evm: &mut BscEvm<InMemoryDB, NoOpInspector>,
565+
beneficiary: Address,
566+
) -> U256 {
567+
use revm::context::{ContextTr, JournalTr};
568+
use revm_context_interface::journaled_state::account::JournaledAccountTr;
569+
*evm.journal_mut()
570+
.load_account_mut(beneficiary)
571+
.expect("beneficiary account should load")
572+
.balance()
573+
}
574+
575+
const TRACE_BENEFICIARY_INITIAL_BALANCE: u64 = 1_000_000_000_000u64;
576+
577+
#[test]
578+
fn fund_uses_incr_semantics_not_set() {
579+
let beneficiary = Address::from([0x10; 20]);
580+
let mut evm = make_trace_replay_evm(beneficiary, VALIDATOR_SYSTEM_CONTRACT);
581+
582+
let initial = U256::from(TRACE_BENEFICIARY_INITIAL_BALANCE);
583+
let top_up = U256::from(42_000u64);
584+
evm.fund_beneficiary_for_system_tx_replay(top_up);
585+
586+
assert_eq!(read_beneficiary_balance(&mut evm, beneficiary), initial + top_up);
587+
}
588+
589+
#[test]
590+
fn fund_is_noop_for_zero_value() {
591+
let beneficiary = Address::from([0x10; 20]);
592+
let mut evm = make_trace_replay_evm(beneficiary, VALIDATOR_SYSTEM_CONTRACT);
593+
594+
let initial = U256::from(TRACE_BENEFICIARY_INITIAL_BALANCE);
595+
evm.fund_beneficiary_for_system_tx_replay(U256::ZERO);
596+
597+
assert_eq!(read_beneficiary_balance(&mut evm, beneficiary), initial);
598+
}
599+
600+
#[test]
601+
fn fund_is_noop_when_trace_disabled() {
602+
let beneficiary = Address::from([0x10; 20]);
603+
let mut cfg_env = CfgEnv::new_with_spec(BscHardfork::Osaka).with_chain_id(56);
604+
cfg_env.tx_gas_limit_cap = Some(2u64.pow(24));
605+
let block_env = BlockEnv {
606+
beneficiary,
607+
prevrandao: Some(U256::from(1).into()),
608+
..Default::default()
609+
};
610+
let mut db = InMemoryDB::default();
611+
db.insert_account_info(
612+
beneficiary,
613+
AccountInfo {
614+
balance: U256::from(TRACE_BENEFICIARY_INITIAL_BALANCE),
615+
..AccountInfo::default()
616+
},
617+
);
618+
let mut evm = BscEvm::new(EvmEnv::new(cfg_env, block_env), db, NoOpInspector, false, false);
619+
620+
let initial = U256::from(TRACE_BENEFICIARY_INITIAL_BALANCE);
621+
evm.fund_beneficiary_for_system_tx_replay(U256::from(123u64));
622+
623+
assert_eq!(read_beneficiary_balance(&mut evm, beneficiary), initial);
624+
}
561625
}

0 commit comments

Comments
 (0)