# BASIC FUNGIBLE FAUCET CONTRACT # ================================================================================================= # This is a basic fungible faucet smart contract. # # It allows the owner of the faucet to mint, distribute, and burn tokens. Token metadata is stored # in account storage at position 1 as [max_supply, decimals, token_symbol, 0], where: # - max_supply is the maximum supply of the token. # - decimals are the decimals of the token. # - token_symbol as three chars encoded in a Felt. use.miden::account use.miden::asset use.miden::faucet use.miden::tx use.miden::contracts::auth::basic # CONSTANTS # ================================================================================================= const.PRIVATE_NOTE=2 # ERRORS # ================================================================================================= # Distribute would cause the maximum supply to be exceeded const.ERR_FUNGIBLE_ASSET_DISTRIBUTE_WOULD_CAUSE_MAX_SUPPLY_TO_BE_EXCEEDED=0x0002004A # CONSTANTS # ================================================================================================= # The slot in this component's storage layout where the metadata is stored. const.METADATA_SLOT=0 # Basic authentication for the faucet owner. export.basic::auth_tx_rpo_falcon512 #! Distributes freshly minted fungible assets to the provided recipient. #! #! Inputs: [amount, tag, aux, note_type, execution_hint, RECIPIENT] #! Outputs: [note_idx, 0, 0, 0, 0, 0, 0, 0, 0, ...] #! #! - amount is the amount to be minted and sent. #! - tag is the tag to be included in the note. #! - aux is the auxiliary data to be included in the note. #! - note_type is the type of the note that holds the asset. #! - execution_hint is the execution hint of the note that holds the asset. #! - RECIPIENT is the recipient of the asset, i.e., #! hash(hash(hash(serial_num, [0; 4]), script_hash), input_hash). #! - note_idx is the index of the output note. #! This cannot directly be accessed from another context. #! #! FAILS if: #! - The transaction is being executed against an account that is not a fungible asset faucet. #! - The total issuance after minting is greater than the maximum allowed supply. export.distribute.1 # get max supply of this faucet. We assume it is stored at pos 3 of slot 1 push.METADATA_SLOT exec.account::get_item drop drop drop # => [max_supply, amount, tag, aux, note_type, execution_hint, RECIPIENT, ...] # get total issuance of this faucet so far and add amount to be minted exec.faucet::get_total_issuance # => [total_issuance, max_supply, amount, tag, aux, note_type, execution_hint, RECIPIENT, ...] # compute maximum amount that can be minted, max_mint_amount = max_supply - total_issuance sub # => [max_supply - total_issuance, amount, tag, aux, note_type, execution_hint, RECIPIENT, ...] # check that amount =< max_supply - total_issuance, fails if otherwise dup.1 gte assert.err=ERR_FUNGIBLE_ASSET_DISTRIBUTE_WOULD_CAUSE_MAX_SUPPLY_TO_BE_EXCEEDED # => [asset, tag, aux, note_type, execution_hint, RECIPIENT, ...] # creating the asset exec.asset::create_fungible_asset # => [ASSET, tag, aux, note_type, execution_hint, RECIPIENT, ...] # mint the asset; this is needed to satisfy asset preservation logic. exec.faucet::mint # => [ASSET, tag, aux, note_type, execution_hint, RECIPIENT, ...] # store and drop the ASSET loc_storew.0 dropw # => [tag, aux, note_type, execution_hint, RECIPIENT, ...] # create a note exec.tx::create_note # => [note_idx, EMPTY_WORD, EMPTY_WORD, ...] # load the ASSET and add it to the note movdn.4 loc_loadw.0 exec.tx::add_asset_to_note movup.4 # => [note_idx, ASSET, EMPTY_WORD, ...] end #! Burns fungible assets. #! #! Input: [ASSET] #! Outputs: [] #! #! - ASSET is the fungible asset to be burned. #! #! Fails if: #! - The transaction is executed against an account which is not a fungible asset faucet. #! - The transaction is executed against a faucet which is not the origin of the specified asset. #! - The amount about to be burned is greater than the outstanding supply of the asset. export.burn # burning the asset exec.faucet::burn # => [ASSET] # increments the nonce (anyone should be able to call that function) push.1 exec.account::incr_nonce # clear the stack padw swapw dropw # => [...] end