use.std::collections::smt use.kernel::account use.kernel::asset use.kernel::asset_vault use.kernel::memory # ERRORS # ================================================================================================= # Asset mint operation would cause the new total supply to exceed the maximum allowed asset amount const.ERR_FAUCET_NEW_TOTAL_SUPPLY_WOULD_EXCEED_MAX_ASSET_AMOUNT=0x0002002A # Asset amount to burn can not exceed the existing total supply const.ERR_FAUCET_BURN_CANNOT_EXCEED_EXISTING_TOTAL_SUPPLY=0x0002002B # Failed to mint new non-fungible asset because it was already issued const.ERR_FAUCET_NON_FUNGIBLE_ASSET_ALREADY_ISSUED=0x0002002C # The burn_non_fungible_asset procedure can only be called on a non-fungible faucet const.ERR_FAUCET_BURN_NON_FUNGIBLE_ASSET_CAN_ONLY_BE_CALLED_ON_NON_FUNGIBLE_FAUCET=0x0002002D # Failed to burn non-existent non-fungible asset in the vault const.ERR_FAUCET_NON_FUNGIBLE_ASSET_TO_BURN_NOT_FOUND=0x0002002E # FUNGIBLE ASSETS # ================================================================================================== #! Mints a fungible asset associated with the fungible faucet the transaction is being executed #! against. #! #! Panics: #! - If the transaction is not being executed against a fungible faucet. #! - If the fungible asset being minted is not associated with the faucet the transaction is #! being executed against. #! - If the asset is not well formed. #! - If the total issuance after minting is greater than the maximum amount allowed. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! - amount is the amount of the fungible asset to mint. #! - ASSET is the asset that was minted. export.mint_fungible_asset # assert that the asset is associated with the faucet the transaction is being executed against # and that the asset is valid exec.account::get_id exec.asset::validate_fungible_asset_origin # => [ASSET] # get the current total issuance exec.account::get_faucet_storage_data_slot exec.account::get_item # => [TOTAL_ISSUANCE, ASSET] # prepare stack to ensure that minting the asset will not exceed the maximum dup.7 dup exec.asset::get_fungible_asset_max_amount dup.3 # => [total_issuance, max_allowed_issuance, amount, amount, TOTAL_ISSUANCE, ASSET] # compute difference to ensure that the total issuance will not exceed the maximum sub lte assert.err=ERR_FAUCET_NEW_TOTAL_SUPPLY_WOULD_EXCEED_MAX_ASSET_AMOUNT # => [amount, TOTAL_ISSUANCE, ASSET] # update the total issuance add exec.account::get_faucet_storage_data_slot exec.account::set_item dropw # => [ASSET] # add the asset to the input vault for asset preservation checks dupw exec.memory::get_input_vault_root_ptr movdn.4 exec.asset_vault::add_fungible_asset dropw # => [ASSET] end #! Burns a fungible asset associated with the fungible faucet the transaction is being executed #! against. #! #! Panics: #! - If the transaction is not being executed against a fungible faucet. #! - If the fungible asset being burned is not associated with the faucet the transaction is #! being executed against. #! - If the asset is not well formed. #! - If the amount being burned is greater than the total input to the transaction. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! - ASSET is the asset that was burned. proc.burn_fungible_asset # assert that the asset is associated with the faucet the transaction is being executed against # and that the asset is valid exec.account::get_id exec.asset::validate_fungible_asset_origin # => [ASSET] # fetch TOTAL_ISSUANCE such that we can compute the new total issuance exec.account::get_faucet_storage_data_slot exec.account::get_item # => [TOTAL_ISSUANCE, ASSET] # assert that the asset amount being burned is less or equal to the total issuance dup.7 dup dup.2 lte assert.err=ERR_FAUCET_BURN_CANNOT_EXCEED_EXISTING_TOTAL_SUPPLY # => [amount, TOTAL_ISSUANCE, ASSET] # compute new total issuance sub exec.account::get_faucet_storage_data_slot exec.account::set_item dropw # => [ASSET] # remove the asset from the input vault dupw exec.memory::get_input_vault_root_ptr movdn.4 exec.asset_vault::remove_fungible_asset dropw # => [ASSET] end #! Returns the total issuance of the fungible faucet the transaction is being executed against. #! #! Stack: [] #! Outputs: [total_issuance] #! #! - total_issuance is the total issuance of the fungible faucet the transaction is being executed #! against. export.get_total_issuance # fetch the TOTAL_ISSUANCE from storage exec.account::get_faucet_storage_data_slot exec.account::get_item # => [TOTAL_ISSUANCE] # extract the total_issuance and purge the padding movdn.3 drop drop drop # => [total_issuance] end # NON-FUNGIBLE ASSETS # ================================================================================================== #! Mints a non-fungible asset associated with the non-fungible faucet the transaction is being #! executed against. #! #! Panics: #! - If the transaction is not being executed against a non-fungible faucet. #! - If the non-fungible asset being minted is not associated with the faucet the transaction is #! being executed against. #! - If the non-fungible asset being minted already exists. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! - ASSET is the asset that was minted. proc.mint_non_fungible_asset # assert that the asset is associated with the faucet the transaction is being executed against # and that the asset is valid exec.account::get_id exec.asset::validate_non_fungible_asset_origin # => [ASSET] # fetch the root of the SMT containing the non-fungible assets dupw exec.account::get_faucet_storage_data_slot exec.account::get_item # => [SMT_ROOT, ASSET, ASSET] # prepare stack for insert of non-fungible asset into tracking SMT swapw dupw # => [ASSET, ASSET, SMT_ROOT, ASSET] # insert the non-fungible asset into the tracking SMT exec.smt::set # => [OLD_VAL, SMT_ROOT', ASSET] # assert the `OLD_VAL` is EMPTY_WORD, indicating that the non-fungible asset did not already exist # we only need to check ASSET[1] as this is always set to the faucet_id and can not be 0. drop drop eq.0 assert.err=ERR_FAUCET_NON_FUNGIBLE_ASSET_ALREADY_ISSUED drop # => [SMT_ROOT', ASSET] # update the root of the SMT containing the non-fungible assets exec.account::get_faucet_storage_data_slot exec.account::set_item dropw # => [ASSET] # add the non-fungible asset to the input vault for asset preservation checks exec.memory::get_input_vault_root_ptr movdn.4 exec.asset_vault::add_non_fungible_asset # => [ASSET] end #! Burns a non-fungible asset associated with the non-fungible faucet the transaction is being #! executed against. #! #! Panics: #! - If the transaction is not being executed against a non-fungible faucet. #! - If the non-fungible asset being burned is not associated with the faucet the transaction is #! being executed against. #! - If the non-fungible asset being burned does not exist or was not provided as input to the #! transaction via a note or the accounts vault. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! - ASSET is the asset that was burned. proc.burn_non_fungible_asset # assert that we are executing a transaction against the non-fungible faucet (access checks) exec.account::get_id exec.account::is_non_fungible_faucet assert.err=ERR_FAUCET_BURN_NON_FUNGIBLE_ASSET_CAN_ONLY_BE_CALLED_ON_NON_FUNGIBLE_FAUCET # => [ASSET] # duplicate asset dupw # => [ASSET, ASSET] # fetch the root of the SMT containing the non-fungible assets exec.account::get_faucet_storage_data_slot exec.account::get_item # => [SMT_ROOT, ASSET, ASSET] # prepare stack for removal of non-fungible asset from tracking SMT swapw padw # => [EMPTY_WORD, ASSET, SMT_ROOT, ASSET] # remove the non-fungible asset from the tracking SMT exec.smt::set # => [OLD_VAL, SMT_ROOT', ASSET] # assert the `OLD_VAL` is not EMPTY_WORD, indicating that the non-fungible asset exists. # we only need to check ASSET[1] as this is always set to the faucet_id and can not be 0. drop drop eq.0 not assert.err=ERR_FAUCET_NON_FUNGIBLE_ASSET_TO_BURN_NOT_FOUND drop # => [SMT_ROOT', ASSET] # update the root of the SMT containing the non-fungible assets exec.account::get_faucet_storage_data_slot exec.account::set_item dropw # => [ASSET] # remove the non-fungible asset from the input vault for asset preservation checks exec.memory::get_input_vault_root_ptr movdn.4 exec.asset_vault::remove_non_fungible_asset # => [ASSET] end # PUBLIC INTERFACE # ================================================================================================== #! Mint an asset from the faucet the transaction is being executed against. #! #! Panics: #! - If the transaction is not being executed against a faucet. #! - If the asset being minted is not associated with the faucet the transaction is being executed #! against. #! - If the asset is not well formed. #! - For fungible faucets if the total issuance after minting is greater than the maximum amount #! allowed. #! - For non-fungible faucets if the non-fungible asset being minted already exists. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! - ASSET is the asset that was minted. export.mint # check if the asset is a fungible asset exec.asset::is_fungible_asset # => [is_fungible_asset, ASSET] if.true # mint the fungible asset exec.mint_fungible_asset # => [ASSET] else # mint the non-fungible asset exec.mint_non_fungible_asset # => [ASSET] end end #! Burn an asset from the faucet the transaction is being executed against. #! #! Panics: #! - If the transaction is not being executed against a faucet. #! - If the asset being burned is not associated with the faucet the transaction is being executed #! against. #! - If the asset is not well formed. #! - For fungible faucets if the amount being burned is greater than the total input to the #! transaction. #! - For non-fungible faucets if the non-fungible asset being burned does not exist or was not #! provided as input to the transaction via a note or the accounts vault. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! - ASSET is the asset that was burned. export.burn # check if the asset is a fungible asset exec.asset::is_fungible_asset # => [is_fungible_asset, ASSET] if.true # burn the fungible asset exec.burn_fungible_asset # => [ASSET] else # burn the non-fungible asset exec.burn_non_fungible_asset # => [ASSET] end end