-
Notifications
You must be signed in to change notification settings - Fork 124
Description
Motivation
We are using the basic fungible faucet's token metadata in a few places, i.e. itself, NetworkFungibleFaucet and the agglayer faucet. To deduplicate the conversion from that metadata into the storage layout and to have a way to abstract over the concrete faucets, it would be good to introduce a TokenMetadata type, that is:
Implementation
/// The metadata of a fungible faucet's token.
///
/// ## Storage Layout
///
/// - [`Self::metadata_slot`]: `[token_supply, max_supply, decimals, token_symbol]`, where:
/// - `token_supply` is the current supply of the token.
/// - `max_supply` is the maximum supply of the token.
/// - `decimals` are the decimals of the token.
/// - `token_symbol` is the [`TokenSymbol`] encoded to a [`Felt`].
#[derive(Clone, Copy)]
pub struct TokenMetadata {
token_supply: Felt,
max_supply: Felt,
decimals: u8,
symbol: TokenSymbol,
}It is basically a standardized storage slot, and so it can implement conversion from and to StorageSlot:
impl TokenMetadata {
/// TODO
pub fn metadata_slot() -> &'static StorageSlotName {
todo!("return miden::standards::fungible_faucets::metadata like BasicFungibleFaucet does")
}
}
impl From<TokenMetadata> for Word {
fn from(metadata: TokenMetadata) -> Self {
Word::new([
metadata.token_supply,
metadata.max_supply,
Felt::from(metadata.decimals),
Felt::from(metadata.symbol),
])
}
}
impl From<TokenMetadata> for StorageSlot {
fn from(metadata: TokenMetadata) -> Self {
StorageSlot::new(
TokenMetadata::metadata_slot().clone(),
StorageSlotContent::Value(Word::from(metadata)),
)
}
}
impl TryFrom<&StorageSlot> for TokenMetadata {
type Error = todo!();
fn try_from(value: &StorageSlot) -> Result<Self, Self::Error> {
todo!("extract content if name is TokenMetadata::metadata_slot() and decode word")
}
}
impl TryFrom<&AccountStorage> for TokenMetadata {
type Error = todo!();
fn try_from(value: &AccountStorage) -> Result<Self, Self::Error> {
todo!("calls TokenMetadata::try_from(storage_slot) on the appropriate slot")
}
}It would also have most of the methods that BasicFungibleFaucet has now, e.g. new to enforce basic constraints, getters for the fields and the standard metadata_slot name.
Usage
Then we can redefine the faucet types more cleanly as:
pub struct BasicFungibleFaucet {
metadata: TokenMetadata
}
pub struct NetworkFungibleFaucet {
metadata: TokenMetadata,
owner_account_id: AccountId,
}And in create_agglayer_faucet_component, construct a TokenMetadata and convert it into a storage slot without duplicating the details of how it is laid out.
Abstraction
This type basically allows abstracting over BasicFungibleFaucet and NetworkFungibleFaucet since both have the same slot. So, we can get the current token supply from both kinds of faucets by reconstructing TokenMetadata::try_from(account_storage) and getting the token_supply.
Context