use revm::{
context::{Block, ContextTr, JournalTr},
handler::EvmTr,
primitives::{address, hardfork::SpecId, Address, Bytes, ONE_ETHER, ONE_GWEI, U256},
statetest_types::blockchain::Withdrawal,
Database, DatabaseCommit, SystemCallCommitEvm,
};
#[inline]
pub fn post_block_transition<
'a,
DB: Database + DatabaseCommit + 'a,
EVM: SystemCallCommitEvm<Error: core::fmt::Debug> + EvmTr<Context: ContextTr<Db = DB>>,
>(
evm: &mut EVM,
block: impl Block,
withdrawals: &[Withdrawal],
spec: SpecId,
) -> Result<(), EVM::Error> {
let block_reward = block_reward(spec, 0);
if block_reward != 0 {
evm.ctx_mut()
.journal_mut()
.balance_incr(block.beneficiary(), U256::from(block_reward))
.expect("Db actions to pass");
}
if spec.is_enabled_in(SpecId::SHANGHAI) {
for withdrawal in withdrawals {
evm.ctx_mut()
.journal_mut()
.balance_incr(
withdrawal.address,
withdrawal.amount.saturating_mul(U256::from(ONE_GWEI)),
)
.expect("Db actions to pass");
}
}
evm.commit_inner();
if spec.is_enabled_in(SpecId::PRAGUE) {
system_call_eip7002_withdrawal_request(evm)?;
}
if spec.is_enabled_in(SpecId::PRAGUE) {
system_call_eip7251_consolidation_request(evm)?;
}
Ok(())
}
#[inline]
pub const fn block_reward(spec: SpecId, ommers: usize) -> u128 {
if spec.is_enabled_in(SpecId::MERGE) {
return 0;
}
let reward = if spec.is_enabled_in(SpecId::CONSTANTINOPLE) {
ONE_ETHER * 2
} else if spec.is_enabled_in(SpecId::BYZANTIUM) {
ONE_ETHER * 3
} else {
ONE_ETHER * 5
};
reward + (reward >> 5) * ommers as u128
}
pub const WITHDRAWAL_REQUEST_ADDRESS: Address =
address!("0x00000961Ef480Eb55e80D19ad83579A64c007002");
pub(crate) fn system_call_eip7002_withdrawal_request<EVM>(evm: &mut EVM) -> Result<(), EVM::Error>
where
EVM: SystemCallCommitEvm<Error: core::fmt::Debug>,
{
evm.system_call_commit(WITHDRAWAL_REQUEST_ADDRESS, Bytes::new())?;
Ok(())
}
pub const CONSOLIDATION_REQUEST_ADDRESS: Address =
address!("0x0000BBdDc7CE488642fb579F8B00f3a590007251");
pub(crate) fn system_call_eip7251_consolidation_request<EVM>(
evm: &mut EVM,
) -> Result<(), EVM::Error>
where
EVM: SystemCallCommitEvm<Error: core::fmt::Debug>,
{
evm.system_call_commit(CONSOLIDATION_REQUEST_ADDRESS, Bytes::new())?;
Ok(())
}