Token Metadata extension to form standard#2439
Token Metadata extension to form standard#2439afa7789 wants to merge 78 commits into0xMiden:nextfrom
Conversation
55282e1 to
b1dba96
Compare
|
We should also consider adding the corresponding metadata and the new constructor to the network fungible faucets: https://github.com/afa7789/miden-base/blob/f7426116833b1f76da3195738ccb838a52880f80/crates/miden-standards/src/account/faucets/network_fungible.rs#L93-L101 |
|
@afa7789 we should also add a flag and procedure to change max_supply. It's basically similar to have we have done in |
In this branch ? pr ? |
Yes, it would be better if you can have this in this PR. |
|
@bobbinth @mmagician this is ready for review :) |
bobbinth
left a comment
There was a problem hiding this comment.
Not a review - but I left a couple of comments inline. The main one is about how we can handle returning large amounts of data from account interface procedures.
|
@afa7789 Additionally, as this discussion #2423 (comment) has been concluded, you can update the PR with the following:
For
|
5548bd5 to
609b355
Compare
| /// - Slot 12–17: logo_uri (6 Words) | ||
| /// - Slot 18–23: external_link (6 Words) | ||
| #[derive(Debug, Clone, Default)] | ||
| pub struct Info { |
There was a problem hiding this comment.
Why is this not part of TokenMetadata directly?
It feels very closely related, so I would consider including it. Making it a separate component means users always need to remember to include it in their account next to TokenMetadata and need to decode both TokenMetadata and Info to get all the related data, so this pushes some complexity up the stack.
It would also be nice if we could set mutability flags directly via the mentioned TokenMetadataBuilder, e.g. TokenMetadataBuilder::new(...).description("abc").mutable_description().build().
Related, I think Info does not be an AccountComponent, since it does not have any code. This suggests it is a set of standard storage slots but not a full account component (a combination of functionality / code and storage). So in the same way as TokenMetadata is not an account component (but more like a standardized storage slot), we could make Info a reusable set of storage slots. I would then include it in TokenMetadata, which in turn is included in BasicFungibleFaucet (a proper account component). Notably, this does not prevent reusing Info for other purposes in the future (such as for NFTs).
Naming: I think this is more aptly described as TokenMetadata. This is more generic metadata than what is currently called TokenMetadata which is specific to fungible assets. So maybe it is better to rename the current TokenMetadata to FungibleTokenMetadata to free up that name for this.
|
@PhilippGackstatter I did most of the mentioned things. |
ebcbd2e to
671a9dc
Compare
ecf267b to
2e50884
Compare
…metadata parameters
…id ownership issues
…mplify faucet creation
- Introduced FungibleTokenMetadataBuilder to simplify the creation of FungibleTokenMetadata instances. - Updated all instances of FungibleTokenMetadata creation across the codebase to utilize the new builder pattern. - Enhanced readability and maintainability by allowing optional fields to be set in a chainable manner. - Adjusted tests and mock implementations to accommodate the new builder approach.
…n metadata handling
bobbinth
left a comment
There was a problem hiding this comment.
Looks good! Thank you! Not a full review - I mostly reviewed Rust code for now - but I left some comments inline. The main one is about code organization.
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Show resolved
Hide resolved
| #[derive(Debug, Clone)] | ||
| pub struct AggLayerFaucet { | ||
| metadata: TokenMetadata, | ||
| metadata: FungibleTokenMetadata, |
There was a problem hiding this comment.
This seems to be different from the pattern we use for NetworkFungibleFaucet and BasicFungibleFaucet. Specifically, here we put the metdata inside the AggLayerFaucet component, but there, metadata is an external component.
We should probably adjust this to make it work similarly to NetworkFungibleFaucet and BasicFungibleFaucet - but maybe that's for a follow-up PR (in this case, we can probably omit making changes to the AggLayerFaucet in this PR.
There was a problem hiding this comment.
but maybe that's for a follow-up PR (in this case, we can probably omit making changes to the AggLayerFaucet in this PR.
Okay, that's probably a good idea.
- moved `TokenMetadata` and `TokenName` structs to manage token metadata including name, description, logo URI, and external link. - Implemented `FixedWidthString` for encoding fixed-width UTF-8 strings into storage words. - Added utility functions for reading and writing token metadata to account storage. - Created a new module for string utilities and organized existing modules.
PhilippGackstatter
left a comment
There was a problem hiding this comment.
I find this PR hard to review due to the large amount of changes. I still think we should try to split this PR into smaller ones, e.g. one that introduces FixedWidthString and the types building on top of it, and another PR that makes the changes to TokenMetadata. Otherwise, I think we'll need more iterations for this PR due to more re-reviewing of code.
| fn felt_with_high_byte_set_returns_invalid_utf8() { | ||
| // Construct a Word where one felt has its 8th byte non-zero, | ||
| // which violates the 7-bytes-per-felt invariant. | ||
| // A value with byte[7] != 0: 2^56 exceeds the Goldilocks prime so we need a | ||
| // different approach — set a byte in positions 0..7 that decodes to invalid UTF-8. | ||
| // The length byte will claim len=0xFF (255) which exceeds the buffer, triggering the error. | ||
| let overflow_len = Felt::try_from(0xff_u64).unwrap(); |
There was a problem hiding this comment.
The test name doesn't fit what it's doing, right? The test does sets the low byte in the felt to non-zero, but not the high byte.
This test is useful and we should keep it, but probably under a different name.
Separately, it would be useful to have a test that sets the high byte to non-zero and make sure it errors, which we could do like this:
// Construct a Word where one felt has its 8th byte non-zero,
// which violates the 7-bytes-per-felt invariant.
// The felt has bit 63 set, making it a valid felt but an invalid length prefix.
let high_byte_non_zero = Felt::try_from(2u64.pow(63)).unwrap();
let words = [
Word::from([Felt::ZERO, high_byte_non_zero, Felt::ZERO, Felt::ZERO]),
Word::from([Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::ZERO]),
];
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/builder.rs
Outdated
Show resolved
Hide resolved
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
| pub(super) const TOKEN_SYMBOL_TYPE: &str = | ||
| "miden::standards::fungible_faucets::metadata::token_symbol"; |
There was a problem hiding this comment.
I'd remove this module and move this definition to:
impl TokenSymbol {
pub fn schema_type() -> SchemaType { ... }
}There was a problem hiding this comment.
Not sure about this, cause TokenSymbol lives in the miden-protocol part, so maybe better to not change it. And only work within miden-standards.
|
@PhilippGackstatter
and another PR:
And close this one? I will still do all the code suggestions here before doing that. cc: @onurinanc @bobbinth |
I would definitely do this. I think the |
Unified metadata: One place for account/faucet metadata: token (symbol, decimals, max_supply), owner, name, and content URI. Slot names live under miden::standards::metadata::* (and ownable for owner).
Layout: Token metadata and owner in slots 0–1; name in 2 words (name_0, name_1); content URI in 6 words (content_uri_0..5). Same layout in Rust and MASM.
Faucets: Basic and network fungible faucets support optional name and content URI; both re-export metadata getters (get_name, get_content_uri, get_token_metadata, get_max_supply, get_decimals, get_token_symbol; network also get_owner).
Standalone Info: Non-faucet accounts can use the metadata Info component (name + content URI) for future use (e.g. NFTs).
Testing: Unit tests in miden-standards (metadata storage, recovery); integration tests in miden-testing (MASM getters, faucet + metadata).