use assert_matches::assert_matches;
use miden_protocol::account::auth::{AuthScheme, PublicKeyCommitment};
use miden_protocol::account::{AccountBuilder, AccountId, AccountType, StorageMapKey};
use miden_protocol::asset::{AssetAmount, TokenSymbol};
use miden_protocol::{Felt, Word};
use super::{
FungibleFaucet,
create_guarded_user_fungible_faucet,
create_multisig_user_fungible_faucet,
create_network_fungible_faucet,
create_singlesig_user_fungible_faucet,
};
use crate::account::access::{AccessControl, PausableManager};
use crate::account::auth::{
Approver,
AuthGuardedMultisig,
AuthMultisig,
AuthNetworkAccount,
AuthSingleSig,
AuthSingleSigAcl,
GuardianConfig,
};
use crate::account::faucets::{Description, FungibleFaucetError, TokenMetadata, TokenName};
use crate::account::policies::{BurnPolicy, MintPolicy, TokenPolicyManager, TransferPolicy};
use crate::account::wallets::BasicWallet;
use crate::testing::faucet::{
user_faucet_guarded,
user_faucet_multisig,
user_faucet_single_sig_acl,
};
use crate::tx_script::ExpirationTransactionScript;
fn allow_all_policy_manager() -> TokenPolicyManager {
TokenPolicyManager::builder()
.active_mint_policy(MintPolicy::allow_all())
.active_burn_policy(BurnPolicy::allow_all())
.active_send_policy(TransferPolicy::allow_all())
.active_receive_policy(TransferPolicy::allow_all())
.build()
}
fn sample_faucet() -> FungibleFaucet {
FungibleFaucet::builder()
.name(TokenName::new("polygon").unwrap())
.symbol(TokenSymbol::try_from("POL").unwrap())
.decimals(2)
.max_supply(AssetAmount::from(123u32))
.description(Description::new("A polygon token").unwrap())
.build()
.unwrap()
}
#[test]
fn user_fungible_faucet_with_single_sig_acl() {
let pub_key_word = Word::new([Felt::ONE; 4]);
let init_seed: [u8; 32] = [
90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183,
204, 149, 90, 166, 68, 100, 73, 106, 168, 125, 237, 138, 16,
];
let token_symbol_string = "POL";
let token_symbol = TokenSymbol::try_from(token_symbol_string).unwrap();
let token_name_string = "polygon";
let description_string = "A polygon token";
let auth_component =
user_faucet_single_sig_acl(pub_key_word.into(), AuthScheme::Falcon512Poseidon2);
let faucet_account = create_singlesig_user_fungible_faucet(
init_seed,
sample_faucet(),
auth_component,
allow_all_policy_manager(),
AccountType::Private,
)
.unwrap();
assert_eq!(
faucet_account.storage().get_item(AuthSingleSigAcl::public_key_slot()).unwrap(),
pub_key_word
);
for probed_root in [
FungibleFaucet::mint_and_send_root(),
FungibleFaucet::set_max_supply_root(),
FungibleFaucet::set_description_root(),
FungibleFaucet::set_logo_uri_root(),
FungibleFaucet::set_external_link_root(),
TokenPolicyManager::set_mint_policy_root(),
TokenPolicyManager::set_burn_policy_root(),
TokenPolicyManager::set_send_policy_root(),
TokenPolicyManager::set_receive_policy_root(),
PausableManager::pause_root(),
PausableManager::unpause_root(),
] {
let value = faucet_account
.storage()
.get_map_item(
AuthSingleSigAcl::exempt_procedure_roots_slot(),
StorageMapKey::from_raw(probed_root.as_word()),
)
.unwrap();
assert_eq!(value, Word::empty());
}
assert_eq!(
faucet_account.storage().get_item(FungibleFaucet::token_config_slot()).unwrap(),
[Felt::ZERO, Felt::from(123_u32), Felt::from(2_u32), token_symbol.into()].into()
);
let name_0 = faucet_account.storage().get_item(TokenMetadata::name_chunk_0_slot()).unwrap();
let name_1 = faucet_account.storage().get_item(TokenMetadata::name_chunk_1_slot()).unwrap();
let decoded_name = TokenName::try_from_words(&[name_0, name_1]).unwrap();
assert_eq!(decoded_name.as_str(), token_name_string);
let expected_desc_words = Description::new(description_string).unwrap().to_words();
for (i, expected) in expected_desc_words.iter().enumerate() {
let chunk = faucet_account.storage().get_item(TokenMetadata::description_slot(i)).unwrap();
assert_eq!(chunk, *expected);
}
let _faucet_component = FungibleFaucet::try_from(faucet_account.clone()).unwrap();
}
fn sample_approvers(n: u32) -> alloc::vec::Vec<(PublicKeyCommitment, AuthScheme)> {
(0..n)
.map(|i| {
(
PublicKeyCommitment::from(Word::new([Felt::from(i + 1); 4])),
AuthScheme::Falcon512Poseidon2,
)
})
.collect()
}
#[test]
fn user_fungible_faucet_with_multisig() {
let threshold = 2;
let num_approvers = 3;
let auth_component = user_faucet_multisig(sample_approvers(num_approvers), threshold).unwrap();
let faucet_account = create_multisig_user_fungible_faucet(
[3u8; 32],
sample_faucet(),
auth_component,
allow_all_policy_manager(),
AccountType::Private,
)
.unwrap();
assert_eq!(
faucet_account
.storage()
.get_item(AuthMultisig::threshold_config_slot())
.unwrap(),
[Felt::from(threshold), Felt::from(num_approvers), Felt::ZERO, Felt::ZERO].into()
);
let _faucet_component = FungibleFaucet::try_from(faucet_account).unwrap();
}
#[test]
fn user_fungible_faucet_with_guarded_multisig() {
let threshold = 2;
let num_approvers = 3;
let approver = Approver::new(
PublicKeyCommitment::from(Word::new([Felt::from(99_u32); 4])),
AuthScheme::Falcon512Poseidon2,
);
let guardian = GuardianConfig::new(approver);
let auth_component =
user_faucet_guarded(sample_approvers(num_approvers), threshold, guardian).unwrap();
let faucet_account = create_guarded_user_fungible_faucet(
[4u8; 32],
sample_faucet(),
auth_component,
allow_all_policy_manager(),
AccountType::Private,
)
.unwrap();
assert_eq!(
faucet_account
.storage()
.get_item(AuthGuardedMultisig::threshold_config_slot())
.unwrap(),
[Felt::from(threshold), Felt::from(num_approvers), Felt::ZERO, Felt::ZERO].into()
);
let _faucet_component = FungibleFaucet::try_from(faucet_account).unwrap();
}
#[test]
fn network_fungible_faucet_with_ownable2step() {
use miden_protocol::testing::account_id::ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_UPDATABLE_CODE;
let owner = AccountId::try_from(ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_UPDATABLE_CODE).unwrap();
let _account = create_network_fungible_faucet(
[7u8; 32],
sample_faucet(),
AccessControl::Ownable2Step { owner },
allow_all_policy_manager(),
)
.expect("Ownable2Step network faucet should be accepted");
}
#[test]
fn network_fungible_faucet_allowlists_expiration_tx_script() {
use miden_protocol::testing::account_id::ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_UPDATABLE_CODE;
let owner = AccountId::try_from(ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_UPDATABLE_CODE).unwrap();
let account = create_network_fungible_faucet(
[8u8; 32],
sample_faucet(),
AccessControl::Ownable2Step { owner },
allow_all_policy_manager(),
)
.unwrap();
let stored = account
.storage()
.get_map_item(
AuthNetworkAccount::allowed_tx_scripts_slot(),
StorageMapKey::new(ExpirationTransactionScript::script_root().as_word()),
)
.unwrap();
assert_eq!(stored, [Felt::ONE, Felt::ZERO, Felt::ZERO, Felt::ZERO].into());
}
#[test]
fn faucet_create_from_account() {
let mock_word = Word::from([0, 1, 2, 3u32]);
let mock_public_key = PublicKeyCommitment::from(mock_word);
let mock_seed = mock_word.as_bytes();
let token_symbol = TokenSymbol::new("POL").expect("invalid token symbol");
let faucet = FungibleFaucet::builder()
.name(TokenName::new("POL").unwrap())
.symbol(token_symbol)
.decimals(10)
.max_supply(AssetAmount::from(100u32))
.build()
.expect("failed to create faucet");
let faucet_account = AccountBuilder::new(mock_seed)
.with_component(faucet)
.with_auth_component(AuthSingleSig::new(Approver::new(
mock_public_key,
AuthScheme::Falcon512Poseidon2,
)))
.build_existing()
.expect("failed to create wallet account");
let _fungible_faucet =
FungibleFaucet::try_from(faucet_account).expect("fungible faucet creation failed");
let invalid_faucet_account = AccountBuilder::new(mock_seed)
.with_auth_component(AuthSingleSig::new(Approver::new(
mock_public_key,
AuthScheme::Falcon512Poseidon2,
)))
.with_component(BasicWallet)
.build_existing()
.expect("failed to create wallet account");
let err = FungibleFaucet::try_from(invalid_faucet_account)
.expect_err("fungible faucet creation should fail");
assert_matches!(err, FungibleFaucetError::MissingFungibleFaucetInterface);
}
#[test]
fn get_faucet_procedures() {
let _mint_and_send_root = FungibleFaucet::mint_and_send_root();
let _receive_and_burn_root = FungibleFaucet::receive_and_burn_root();
let _set_max_supply_root = FungibleFaucet::set_max_supply_root();
let _set_description_root = FungibleFaucet::set_description_root();
let _set_logo_uri_root = FungibleFaucet::set_logo_uri_root();
let _set_external_link_root = FungibleFaucet::set_external_link_root();
let _set_mint_policy_root = TokenPolicyManager::set_mint_policy_root();
let _set_burn_policy_root = TokenPolicyManager::set_burn_policy_root();
let _set_send_policy_root = TokenPolicyManager::set_send_policy_root();
let _set_receive_policy_root = TokenPolicyManager::set_receive_policy_root();
}