Skip to main content

miden_standards/account/faucets/
mod.rs

1use miden_protocol::account::StorageSlotName;
2use miden_protocol::errors::{AccountError, TokenSymbolError};
3use thiserror::Error;
4
5use crate::account::access::Ownable2StepError;
6use crate::account::policies::{BurnOwnerOnly, MintOwnerOnly, TokenPolicyManager};
7use crate::utils::FixedWidthStringError;
8
9mod fungible;
10mod non_fungible;
11#[cfg(test)]
12mod test_utils;
13mod token_metadata;
14
15pub use fungible::{
16    FungibleFaucet,
17    FungibleFaucetBuilder,
18    create_guarded_user_fungible_faucet,
19    create_multisig_user_fungible_faucet,
20    create_native_fungible_faucet_for_genesis,
21    create_network_fungible_faucet,
22    create_singlesig_user_fungible_faucet,
23};
24pub use non_fungible::{
25    AssetStatus,
26    NonFungibleFaucet,
27    NonFungibleFaucetBuilder,
28    create_network_non_fungible_faucet,
29    create_user_non_fungible_faucet,
30};
31pub use token_metadata::{Description, ExternalLink, LogoURI, TokenMetadata, TokenName};
32
33// OWNER-ONLY POLICY DEPENDENCY CHECK
34// ================================================================================================
35
36/// Returns `true` if `token_policy_manager` registers an owner-gated mint or burn policy, either as
37/// the active policy or as a reserved alternative that `set_mint_policy` / `set_burn_policy` can
38/// activate later.
39///
40/// The owner-controlled policy family calls `ownable2step::assert_sender_is_owner`, which reads a
41/// storage slot installed by [`Ownable2Step`](crate::account::access::Ownable2Step) and owned by no
42/// policy component. A faucet registering such a policy without that component builds successfully
43/// and then aborts on every dispatch to the policy, disabling minting or burning for the lifetime
44/// of the account.
45///
46/// TODO: This is a temporary, faucet-specific check covering the one configuration the factories
47/// can get wrong. Remove it once components can declare their dependencies generally
48/// ([#2621](https://github.com/0xMiden/protocol/issues/2621)): the owner-only policy components
49/// will then declare the ownership component themselves and every account is validated, not just
50/// the ones these factories build.
51pub(crate) fn registers_owner_only_policy(token_policy_manager: &TokenPolicyManager) -> bool {
52    token_policy_manager.allowed_mint_policies().contains(&MintOwnerOnly::root())
53        || token_policy_manager.allowed_burn_policies().contains(&BurnOwnerOnly::root())
54}
55
56// TOKEN METADATA ERROR
57// ================================================================================================
58
59/// Errors raised when parsing token metadata from storage.
60#[derive(Debug, Error)]
61pub enum TokenMetadataError {
62    #[error("failed to retrieve storage slot with name {slot_name}")]
63    StorageLookupFailed {
64        slot_name: StorageSlotName,
65        source: AccountError,
66    },
67    #[error("invalid string data in field '{field}'")]
68    InvalidStringField {
69        field: &'static str,
70        #[source]
71        source: FixedWidthStringError,
72    },
73    #[error("mutability flag at index {index} has invalid value {value}: must be 0 or 1")]
74    InvalidMutabilityFlag { index: usize, value: u64 },
75    #[error("storage slot name mismatch: expected {expected}, got {actual}")]
76    SlotNameMismatch {
77        expected: StorageSlotName,
78        actual: StorageSlotName,
79    },
80    #[error("invalid token symbol")]
81    InvalidTokenSymbol(#[source] TokenSymbolError),
82}
83
84// FUNGIBLE FAUCET ERROR
85// ================================================================================================
86
87/// Basic fungible faucet related errors.
88#[derive(Debug, Error)]
89pub enum FungibleFaucetError {
90    #[error("faucet metadata decimals is {actual} which exceeds max value of {max}")]
91    TooManyDecimals { actual: u64, max: u8 },
92    #[error("faucet metadata max supply is {actual} which exceeds max value of {max}")]
93    MaxSupplyTooLarge { actual: u64, max: u64 },
94    #[error("token supply {token_supply} exceeds max_supply {max_supply}")]
95    TokenSupplyExceedsMaxSupply { token_supply: u64, max_supply: u64 },
96    #[error(
97        "account interface does not have the procedures of the basic fungible faucet component"
98    )]
99    MissingFungibleFaucetInterface,
100    #[error("account creation failed")]
101    AccountError(#[source] AccountError),
102    #[error("account is not a fungible faucet account")]
103    NotAFungibleFaucetAccount,
104    #[error("failed to read ownership data from storage")]
105    OwnershipError(#[source] Ownable2StepError),
106    #[error(
107        "faucet registers an owner-gated mint or burn policy but does not install the Ownable2Step component the policy reads the owner from"
108    )]
109    OwnerOnlyPolicyWithoutOwnable2Step,
110    #[error(transparent)]
111    TokenMetadata(#[from] TokenMetadataError),
112}
113
114// NON-FUNGIBLE FAUCET ERROR
115// ================================================================================================
116
117/// Non-fungible (NFT) faucet related errors.
118#[derive(Debug, Error)]
119pub enum NonFungibleFaucetError {
120    #[error("account creation failed")]
121    AccountCreationFailed(#[source] AccountError),
122    #[error("account is not a non-fungible faucet account")]
123    NotANonFungibleFaucetAccount,
124    #[error("asset status registry holds invalid status code {status}: must be 0, 1 or 2")]
125    InvalidAssetStatus { status: u64 },
126    #[error(
127        "faucet registers an owner-gated mint or burn policy but does not install the Ownable2Step component the policy reads the owner from"
128    )]
129    OwnerOnlyPolicyWithoutOwnable2Step,
130    #[error(transparent)]
131    TokenMetadata(#[from] TokenMetadataError),
132}