Skip to content

chore: remove faucet sysdata storage slot#2335

Merged
PhilippGackstatter merged 45 commits intonextfrom
pgackst-remove-sysdata-protocol-slot
Feb 2, 2026
Merged

chore: remove faucet sysdata storage slot#2335
PhilippGackstatter merged 45 commits intonextfrom
pgackst-remove-sysdata-protocol-slot

Conversation

@PhilippGackstatter
Copy link
Contributor

@PhilippGackstatter PhilippGackstatter commented Jan 23, 2026

Removes the protocol-reserved faucet slot (miden::protocol::faucet::sysdata).

This slot was used for tracking the amount of issued fungible assets or the non-fungible assets that were already minted.

The logic for fungible assets is moved to miden::standards::faucets::{distribute, burn}. The non-fungible logic has no replacement since we don't currently have a standard component for this.

Changes

  • Removes building faucet accounts with reserved slots and the corresponding checks in the tx kernel prologue.
  • Removes kernel procedures FAUCET_GET_TOTAL_FUNGIBLE_ASSET_ISSUANCE_OFFSET and FAUCET_IS_NON_FUNGIBLE_ASSET_ISSUED_OFFSET that allowed accessing the reserved slot.
  • Replaces asset::get_fungible_asset_max_amount with asset::FUNGIBLE_ASSET_MAX_AMOUNT.
  • burn_non_fungible_asset seems to have only checked that the asset to burn is from a non-fungible faucet without checking its origin and so that was changed to use validate_non_fungible_asset_origin instead.
  • FungibleFaucetExt was removed. Instead, we should use let faucet = BasicFungibleFaucet::try_from(&account) instead and access faucet.token_supply(). A better way to abstract over this would be Implement standard TokenMetadata storage slot #2344.

Follow-Up

NetworkFungibleFaucet wraps more functionality of BasicFungibleFaucet to deduplicate code. The general reason we do this is for reusing the fungible faucet metadata logic, but I think at this point we're using it independent of BasicFungibleFaucet (e.g. also in create_agglayer_faucet_component) which suggests this should be its own standard, e.g. TokenMetadata. This would cleanly allow reusing it in all those faucets without depending on the basic fungible faucet. Will create an issue for this.

closes #2318

Comment on lines +95 to +97
exec.account::get_id
swap drop
# => [faucet_id_prefix, ASSET]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still want to keep around mint_non_fungible_asset?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm missing context. Did you expect it to be removed?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm getting ahead of myself here, thinking about programmable assets already. NVM

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you! I left some comments inline.

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you!

Comment on lines +95 to +97
exec.account::get_id
swap drop
# => [faucet_id_prefix, ASSET]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm getting ahead of myself here, thinking about programmable assets already. NVM

Comment on lines -133 to -147
pub proc get_total_issuance
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]

exec.kernel_proc_offsets::faucet_get_total_fungible_asset_issuance_offset
# => [offset, pad(15)]

syscall.exec_kernel_proc
# => [total_issuance, pad(15)]

# clean the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [total_issuance]
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think get_total_issuance or equivalent would be helpful to have in standards/faucets/mod.masm as a convenience wrapper, instead of accessing the metadata slot elements individually which is error prone. Can be done in follow-up work if you agree that it's useful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally agreed, though since this is very likely to change in the short-term, I'd like to avoid adding code that needs to be refactored as part of programmable assets. After we've determined how "built-in" fungible assets work and where they live (protocol, standards) we can for sure re-add these convenience wrappers. But let me know if you need something like this sooner than after that refactor!

dup.1 dup.1
# => [max_supply, token_supply, max_supply, token_supply, amount, tag, note_type, RECIPIENT]

# assert that token_supply <= max_supply
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this check needed? IIUC, if:

  • token_supply <= max_supply at construction, and
  • token_supply <= max_supply as of last call to distribute

then we don't need to check again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right, under the assumption that the checks from BasicFungibleFaucet have been done - which is what you mean by construction, I assume. I'm being very defensive here and assume these checks have not been done.

Since this code is deployed by users into their accounts, they'd be responsible for not writing an EvilBasicFungibleFaucet that bypasses those checks.

But, this also protects against other faulty code that updates this slot in invalid ways, in which case distribute might exhibit unintended behavior. So, really depends on what we want to assume.

My thinking now is that, since it's already implemented, the checks are relatively cheap in terms of cycles and making the code somewhat less safe would require additional work, I'm inclined to keep it as-is. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking now is that, since it's already implemented, the checks are relatively cheap in terms of cycles and making the code somewhat less safe would require additional work, I'm inclined to keep it as-is. What do you think?

That was my thinking as well: the checks are cheap and it's probably fine to have them, even if the edge case they are trying to catch is rather unlikely.

lte assert.err=ERR_FUNGIBLE_ASSET_TOKEN_SUPPLY_EXCEEDS_MAX_SUPPLY
# => [max_supply, token_supply, amount, tag, note_type, RECIPIENT]

# assert max_supply <= FUNGIBLE_ASSET_MAX_AMOUNT
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here - can't we assert this at construction time?

# => [total_issuance, max_supply, amount, tag, note_type, RECIPIENT]
# assert amount <= max_mint_amount
lte assert.err=ERR_FUNGIBLE_ASSET_DISTRIBUTE_AMOUNT_EXCEEDS_MAX_SUPPLY
# => [token_supply, amount, tag, note_type, RECIPIENT]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While correct, I find this logic a little more complex than expected.
The (subjectively) more intuitive check would be:

  1. Compute new_token_supply
  2. Assert new_token_supply < max_supply
  3. Assert amount < FUNGIBLE_ASSET_MAX_AMOUNT

AFAICS, this will be safe under the following assumptions:

  1. max_supply < FUNGIBLE_ASSET_MAX_AMOUNT (by construction? see my above comments)
  2. current_supply < FUNGIBLE_ASSET_MAX_AMOUNT (this is true as a result of 1. + the invariant that current_supply < max_supply)

then, new_token_supply might overflow FUNGIBLE_ASSET_MAX_AMOUNT, but will not overflow the Felt, and so checking new_token_supply < max_supply works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this would also work totally fine and is easier to understand, so may be worth doing (but see other comment).

faucet.symbol.into(),
Felt::ZERO,
]);
let metadata_word = faucet.to_metadata_word();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is nice and contained. I'd love to see a similar pattern done for create_agglayer_faucet_component, where we have a struct and a way to convert it into an AccountComponent easily. And then we could avoid hardcoding the metadata layout and use sth like to_metadata_word here.

pub struct AggLayerFaucet {
   // ...
}

impl From<AggLayerFaucet> for AccountComponent {
    // ...
}

I'll open an issue to track this.

(and same for AggLayerBridge)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the ideal point to do this would be after #2344, since you can then reuse the TokenMetadata slot easily.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect, even better!

Co-authored-by: Marti <marti@miden.team>
@PhilippGackstatter PhilippGackstatter merged commit 72eaa19 into next Feb 2, 2026
18 checks passed
@PhilippGackstatter PhilippGackstatter deleted the pgackst-remove-sysdata-protocol-slot branch February 2, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove reserved faucet sysdata slot

5 participants