Skip to content

Commit 1453be0

Browse files
committed
complete inspector
1 parent 0833ebf commit 1453be0

1 file changed

Lines changed: 65 additions & 18 deletions

File tree

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
21
use crate::mint_precompile::NATIVE_MINT_PRECOMPILE_ADDRESS;
32
use alloy_primitives::{Address, U256};
3+
use bytes::Bytes;
44
use revm::db::Database;
5-
use revm::precompile::Precompile;
6-
use revm::primitives::{ExecutionResult, Output, TransactTo};
7-
use revm::{Evm, Inspector};
5+
use revm::primitives::{
6+
AccountInfo, CallInputs, CallOutcome, ExecutionResult, Output, TransactTo, B160,
7+
};
8+
use revm::{DatabaseCommit, Evm, Inspector, JournaledState};
89
use std::collections::HashSet;
910

1011
/// An inspector that gates calls to the native mint precompile.
1112
///
1213
/// This inspector enforces an allowlist and various limits on the minting of the native token.
1314
/// It also performs the state mutation (crediting the balance) when the precompile call is
1415
/// successful.
16+
#[derive(Clone, Debug)]
1517
pub struct MintInspector {
1618
/// The address of the native mint precompile.
1719
precompile: Address,
1820
/// A static list of addresses that are allowed to call the precompile.
1921
allow: HashSet<Address>,
20-
/// An optional on-chain registry for validating callers.
21-
registry: Option<Address>,
2222
/// The maximum amount that can be minted in a single call.
2323
per_call_cap: U256,
2424
/// The maximum amount that can be minted in a single block.
@@ -28,21 +28,68 @@ pub struct MintInspector {
2828
}
2929

3030
impl<DB: Database> Inspector<DB> for MintInspector {
31-
/// Called before the execution of a transaction.
32-
fn transact_inspect(
31+
fn call(
3332
&mut self,
3433
context: &mut revm::InnerEvmContext<DB>,
35-
transact_to: TransactTo,
36-
caller: Address,
37-
value: U256,
38-
) -> Option<Vec<u8>> {
39-
// Reset the per-block mint counter at the beginning of each transaction.
40-
self.minted_this_block = U256::ZERO;
34+
inputs: &mut CallInputs,
35+
) -> Option<CallOutcome> {
36+
// Intercept calls to the native mint precompile.
37+
if inputs.contract != self.precompile {
38+
return None;
39+
}
40+
41+
// Check if the caller is authorized.
42+
if !self.allow.contains(&inputs.caller) {
43+
// Return a revert outcome if the caller is not authorized.
44+
let outcome = CallOutcome::new().with_revert(Bytes::from_static(b"unauthorized"));
45+
return Some(outcome);
46+
}
47+
48+
// Decode the amount from the input.
49+
let amount = U256::from_be_slice(&inputs.input[20..52]);
50+
51+
// Check if the amount exceeds the per-call cap.
52+
if amount > self.per_call_cap {
53+
let outcome = CallOutcome::new().with_revert(Bytes::from_static(b"over per-call cap"));
54+
return Some(outcome);
55+
}
56+
57+
// Check if the amount exceeds the per-block cap.
58+
if let Some(per_block_cap) = self.per_block_cap {
59+
if self.minted_this_block + amount > per_block_cap {
60+
let outcome =
61+
CallOutcome::new().with_revert(Bytes::from_static(b"over per-block cap"));
62+
return Some(outcome);
63+
}
64+
}
65+
4166
None
4267
}
4368

44-
/// Called after the execution of a transaction.
45-
fn transact_end(&mut self, context: &mut revm::InnerEvmContext<DB>, result: ExecutionResult) {
46-
// No-op
69+
fn call_end(
70+
&mut self,
71+
context: &mut revm::InnerEvmContext<DB>,
72+
inputs: &CallInputs,
73+
outcome: CallOutcome,
74+
) -> CallOutcome {
75+
// Only handle successful calls to the native mint precompile.
76+
if inputs.contract != self.precompile || outcome.is_revert() {
77+
return outcome;
78+
}
79+
80+
// Decode the recipient and amount from the input.
81+
let to = Address::from_slice(&inputs.input[0..20]);
82+
let amount = U256::from_be_slice(&inputs.input[20..52]);
83+
84+
// Credit the recipient's balance.
85+
// This is the core state mutation logic.
86+
let (account, _) = context.journaled_state.load_account(to, context.db).unwrap();
87+
account.info.balance += amount;
88+
self.minted_this_block += amount;
89+
90+
// Mark the account as touched so the state change is persisted.
91+
context.journaled_state.touch(&to);
92+
93+
outcome
4794
}
48-
}
95+
}

0 commit comments

Comments
 (0)