|
89 | 89 | let beneficiary = ctx.block().beneficiary(); |
90 | 90 | let basefee = ctx.block().basefee() as u128; |
91 | 91 | let effective_gas_price = ctx.tx().effective_gas_price(basefee); |
92 | | - let gas_used = exec_result.gas().used() as u128; |
| 92 | + let gas_used = exec_result.gas().used(); |
93 | 93 |
|
94 | | - // Calculate total fee (base fee + priority fee) instead of just priority fee |
95 | | - let total_fee_amount = U256::from(effective_gas_price * gas_used); |
| 94 | + let total_fee_amount = U256::from(effective_gas_price) * U256::from(gas_used); |
96 | 95 |
|
97 | 96 | // Transfer the total fee to the beneficiary (both base fee and priority fee) |
98 | 97 | evm.ctx_mut() |
@@ -505,6 +504,62 @@ mod tests { |
505 | 504 | ); |
506 | 505 | } |
507 | 506 |
|
| 507 | + #[test] |
| 508 | + fn test_reward_beneficiary_large_values_no_overflow() { |
| 509 | + let beneficiary = address!("1100000000000000000000000000000000000011"); |
| 510 | + let caller = address!("2200000000000000000000000000000000000022"); |
| 511 | + // Values that would overflow u128 when multiplied: (u128::MAX / 1000) * 2000 > u128::MAX |
| 512 | + let gas_price = u128::MAX / 1000; |
| 513 | + let gas_used = 2000u64; |
| 514 | + |
| 515 | + let db: CacheDB<EmptyDBTyped<Infallible>> = CacheDB::new(EmptyDB::default()); |
| 516 | + let mut evm = Context::mainnet().with_db(db).build_mainnet(); |
| 517 | + |
| 518 | + evm.block.beneficiary = beneficiary; |
| 519 | + evm.block.basefee = 0; |
| 520 | + evm.tx.caller = caller; |
| 521 | + evm.tx.gas_price = gas_price; |
| 522 | + |
| 523 | + let interpreter_result = InterpreterResult::new( |
| 524 | + InstructionResult::Return, |
| 525 | + alloy_primitives::Bytes::new(), |
| 526 | + Gas::new_spent(gas_used), |
| 527 | + ); |
| 528 | + let call_outcome = CallOutcome::new(interpreter_result, 0..0); |
| 529 | + let mut exec_result = FrameResult::Call(call_outcome); |
| 530 | + |
| 531 | + let initial_balance = evm |
| 532 | + .journaled_state |
| 533 | + .load_account(beneficiary) |
| 534 | + .unwrap() |
| 535 | + .info |
| 536 | + .balance; |
| 537 | + |
| 538 | + let handler: ArcEvmHandler<_, EVMError<Infallible>> = |
| 539 | + ArcEvmHandler::new(ArcHardforkFlags::default()); |
| 540 | + let result = handler.reward_beneficiary(&mut evm, &mut exec_result); |
| 541 | + |
| 542 | + assert!( |
| 543 | + result.is_ok(), |
| 544 | + "reward_beneficiary should succeed with large values" |
| 545 | + ); |
| 546 | + |
| 547 | + let expected_fee = U256::from(gas_price) * U256::from(gas_used); |
| 548 | + |
| 549 | + let final_balance = evm |
| 550 | + .journaled_state |
| 551 | + .load_account(beneficiary) |
| 552 | + .unwrap() |
| 553 | + .info |
| 554 | + .balance; |
| 555 | + let balance_increase = final_balance - initial_balance; |
| 556 | + |
| 557 | + assert_eq!( |
| 558 | + balance_increase, expected_fee, |
| 559 | + "Beneficiary should receive correct fee even with large values that would overflow u128" |
| 560 | + ); |
| 561 | + } |
| 562 | + |
508 | 563 | #[derive(Debug)] |
509 | 564 | struct BlocklistTestCase { |
510 | 565 | name: &'static str, |
|
0 commit comments