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    "faucets/policies/transfer/basic_allowlist.masl"
20);
21
22procedure_root!(
23    BASIC_ALLOWLIST_TRANSFER_POLICY_ROOT,
24    BasicAllowlist::NAME,
25    BasicAllowlist::PROC_NAME,
26    BasicAllowlist::code()
27);
28
29/// The basic allowlist transfer policy account component.
30///
31/// Pair with a [`crate::account::policies::TokenPolicyManager`] whose send and receive
32/// policy  maps include [`BasicAllowlist::root`]. When active, transfers fail if the
33/// native account (asset recipient or note creator) is not currently allowed on the
34/// issuing faucet.
35///
36/// Allow / disallow administration is intentionally not part of this component. The
37/// `allow_account` / `disallow_account` procedures live in the standards library and require
38/// an auth-wrapped admin component (see [`super::AllowlistOwnerControlled`]) to be safely
39/// exposed on a production faucet.
40#[derive(Debug, Clone, Default)]
41pub struct BasicAllowlist(AllowlistStorage);
42
43impl BasicAllowlist {
44    /// The name of the component.
45    pub const NAME: &'static str =
46        "miden::standards::components::faucets::policies::transfer::basic_allowlist";
47
48    pub(crate) const PROC_NAME: &str = "check_policy";
49
50    /// Creates a basic allowlist with the given initial allowed accounts.
51    pub fn with_allowed_accounts<I>(allowed_accounts: I) -> Self
52    where
53        I: IntoIterator<Item = AccountId>,
54    {
55        Self(AllowlistStorage::with_allowed_accounts(allowed_accounts))
56    }
57
58    /// Returns the initial allowed accounts captured in this component.
59    pub fn allowed_accounts(&self) -> &BTreeSet<AccountId> {
60        self.0.allowed_accounts()
61    }
62
63    /// Returns the [`AccountComponentCode`] of this component.
64    pub fn code() -> &'static AccountComponentCode {
65        &BASIC_ALLOWLIST_TRANSFER_POLICY_CODE
66    }
67
68    /// Returns the MAST root of the basic allowlist transfer policy procedure.
69    pub fn root() -> AccountProcedureRoot {
70        *BASIC_ALLOWLIST_TRANSFER_POLICY_ROOT
71    }
72}
73
74impl From<AllowlistStorage> for BasicAllowlist {
75    fn from(storage: AllowlistStorage) -> Self {
76        Self(storage)
77    }
78}
79
80impl From<BasicAllowlist> for AccountComponent {
81    fn from(allowlist: BasicAllowlist) -> Self {
82        let storage_schema = StorageSchema::new([AllowlistStorage::allowed_accounts_slot_schema()])
83            .expect("storage schema should be valid");
84
85        let metadata = AccountComponentMetadata::new(BasicAllowlist::NAME)
86            .with_description(
87                "Basic allowlist transfer policy: predicate procedure plus the `allowed_accounts` \
88                 storage map it reads",
89            )
90            .with_storage_schema(storage_schema);
91
92        AccountComponent::new(BasicAllowlist::code().clone(), vec![allowlist.0.into_slot()], metadata)
93            .expect(
94                "basic allowlist transfer policy component should satisfy the requirements of a valid account component",
95            )
96    }
97}