Skip to main content

miden_standards/account/policies/transfer/
basic_allowlist.rs

1use alloc::collections::BTreeSet;
2
3use miden_protocol::account::component::{
4    AccountComponentCode,
5    AccountComponentMetadata,
6    StorageSchema,
7};
8use miden_protocol::account::{AccountComponent, AccountId, AccountProcedureRoot};
9
10use crate::account::account_component_code;
11use crate::account::policies::transfer::allowlist::AllowlistStorage;
12use crate::procedure_root;
13
14// BASIC ALLOWLIST TRANSFER POLICY
15// ================================================================================================
16
17account_component_code!(
18    BASIC_ALLOWLIST_TRANSFER_POLICY_CODE,
19    "miden-standards-faucets-policies-transfer-basic-allowlist.masp"
20);
21
22// PROCEDURE ROOTS
23// ================================================================================================
24
25/// MASL library namespace used for procedure-root lookups. Distinct from [`BasicAllowlist::NAME`],
26/// which mirrors the standards-side MASM module path.
27const BASIC_ALLOWLIST_LIBRARY_PATH: &str =
28    "miden::standards::components::faucets::policies::transfer::basic_allowlist";
29
30procedure_root!(
31    BASIC_ALLOWLIST_TRANSFER_POLICY_ROOT,
32    BASIC_ALLOWLIST_LIBRARY_PATH,
33    BasicAllowlist::PROC_NAME,
34    BasicAllowlist::code()
35);
36
37/// The basic allowlist transfer policy account component.
38///
39/// Pair with a [`crate::account::policies::TokenPolicyManager`] whose send and receive
40/// policy  maps include [`BasicAllowlist::root`]. When active, transfers fail if the
41/// native account (asset recipient or note creator) is not currently allowed on the
42/// issuing faucet.
43///
44/// The issuing faucet is exempt from its own allowlist.
45///
46/// Allow / disallow administration is intentionally not part of this component. The
47/// `allow_account` / `disallow_account` procedures live in the standards library and require
48/// an auth-wrapped admin component (see [`super::AllowlistManager`]) to be safely
49/// exposed on a production faucet.
50#[derive(Debug, Clone, Default)]
51pub struct BasicAllowlist(AllowlistStorage);
52
53impl BasicAllowlist {
54    /// The name of the component.
55    pub const NAME: &'static str = "miden::standards::faucets::policies::transfer::basic_allowlist";
56
57    pub(crate) const PROC_NAME: &str = "check_policy";
58
59    /// Creates a basic allowlist with the given initial allowed accounts.
60    pub fn with_allowed_accounts<I>(allowed_accounts: I) -> Self
61    where
62        I: IntoIterator<Item = AccountId>,
63    {
64        Self(AllowlistStorage::with_allowed_accounts(allowed_accounts))
65    }
66
67    /// Returns the initial allowed accounts captured in this component.
68    pub fn allowed_accounts(&self) -> &BTreeSet<AccountId> {
69        self.0.allowed_accounts()
70    }
71
72    /// Returns the [`AccountComponentCode`] of this component.
73    pub fn code() -> &'static AccountComponentCode {
74        &BASIC_ALLOWLIST_TRANSFER_POLICY_CODE
75    }
76
77    /// Returns the MAST root of the basic allowlist transfer policy procedure.
78    pub fn root() -> AccountProcedureRoot {
79        *BASIC_ALLOWLIST_TRANSFER_POLICY_ROOT
80    }
81}
82
83impl From<AllowlistStorage> for BasicAllowlist {
84    fn from(storage: AllowlistStorage) -> Self {
85        Self(storage)
86    }
87}
88
89impl From<BasicAllowlist> for AccountComponent {
90    fn from(allowlist: BasicAllowlist) -> Self {
91        let storage_schema = StorageSchema::new([AllowlistStorage::allowed_accounts_slot_schema()])
92            .expect("storage schema should be valid");
93
94        let metadata = AccountComponentMetadata::new(BasicAllowlist::NAME)
95            .with_description(
96                "Basic allowlist transfer policy: predicate procedure plus the `allowed_accounts` \
97                 storage map it reads",
98            )
99            .with_storage_schema(storage_schema);
100
101        AccountComponent::new(BasicAllowlist::code().clone(), vec![allowlist.0.into_slot()], metadata)
102            .expect(
103                "basic allowlist transfer policy component should satisfy the requirements of a valid account component",
104            )
105    }
106}