arbos/util/
transfer.rs

1use alloy_primitives::{Address, U256};
2use arb_storage::DatabaseError;
3
4/// Failure modes returned by the balance-mutation callback that `arbos`
5/// hands state changes to.
6#[derive(Debug, Clone, thiserror::Error)]
7pub enum BalanceError {
8    /// `from` did not hold enough funds to cover the requested movement.
9    #[error("insufficient balance on {account}: available {available}, requested {requested}")]
10    InsufficientBalance {
11        account: Address,
12        available: U256,
13        requested: U256,
14    },
15
16    /// The underlying state database failed while servicing the transfer.
17    #[error(transparent)]
18    Database(#[from] DatabaseError),
19}
20
21/// Transfers balance between two addresses.
22///
23/// `from == None` is a mint, `to == None` is a burn.
24pub fn transfer_balance<F>(
25    from: Option<&Address>,
26    to: Option<&Address>,
27    amount: U256,
28    mut state_fn: F,
29) -> Result<(), BalanceError>
30where
31    F: FnMut(Option<&Address>, Option<&Address>, U256) -> Result<(), BalanceError>,
32{
33    state_fn(from, to, amount)
34}
35
36/// Mints `amount` to `to`.
37pub fn mint_balance<F>(to: &Address, amount: U256, state_fn: F) -> Result<(), BalanceError>
38where
39    F: FnMut(Option<&Address>, Option<&Address>, U256) -> Result<(), BalanceError>,
40{
41    transfer_balance(None, Some(to), amount, state_fn)
42}
43
44/// Burns `amount` from `from`.
45pub fn burn_balance<F>(from: &Address, amount: U256, state_fn: F) -> Result<(), BalanceError>
46where
47    F: FnMut(Option<&Address>, Option<&Address>, U256) -> Result<(), BalanceError>,
48{
49    transfer_balance(Some(from), None, amount, state_fn)
50}