# ERRORS
# =================================================================================================
const ERR_VAULT_INVALID_ENABLE_CALLBACKS = "enable_callbacks must be 0 or 1"
# CONSTANTS
# =================================================================================================
# Specifies the maximum amount a fungible asset can represent.
#
# This is 2^63 - 2^31. See account_delta.masm for more details.
pub const FUNGIBLE_ASSET_MAX_AMOUNT=0x7fffffff80000000
# The number of elements in an asset, i.e. vault key and value.
pub const ASSET_SIZE = 8
# The offset of the asset value in an asset stored in memory.
pub const ASSET_VALUE_MEMORY_OFFSET = 4
# The flag representing disabled callbacks.
pub const CALLBACKS_DISABLED = 0
# The flag representing enabled callbacks.
pub const CALLBACKS_ENABLED = 1
# PROCEDURES
# =================================================================================================
#! Stores an asset key and value into memory at the given pointer.
#!
#! The memory range pointer..pointer+8 will be overwritten.
#!
#! Inputs: [ptr, ASSET_KEY, ASSET_VALUE]
#! Outputs: []
#!
#! Where:
#! - ptr is the memory address where the asset will be stored.
#! - ASSET_KEY is the 4-element word representing the asset key.
#! - ASSET_VALUE is the 4-element word representing the asset value.
pub proc store
# store asset key
movdn.4 dup.4
# => [ptr, ASSET_KEY, ptr, ASSET_VALUE]
mem_storew_le dropw
# => [ptr, ASSET_VALUE]
# store asset value
add.ASSET_VALUE_MEMORY_OFFSET mem_storew_le dropw
# => []
end
#! Loads an asset key and value from memory given a pointer to the asset.
#!
#! Inputs: [ptr]
#! Outputs: [ASSET_KEY, ASSET_VALUE]
#!
#! Where:
#! - ptr is the memory address of the asset.
#! - ASSET_KEY is the 4-element word representing the asset key.
#! - ASSET_VALUE is the 4-element word representing the asset value.
pub proc load
# load asset value
padw dup.4 add.ASSET_VALUE_MEMORY_OFFSET mem_loadw_le
# => [ASSET_VALUE, ptr]
# load asset key
padw movup.8 mem_loadw_le
# => [ASSET_KEY, ASSET_VALUE]
end
#! Returns the balance of the given fungible asset and consumes it.
#!
#! WARNING: Assumes that the given asset value is fungible and does NOT validate it.
#!
#! Inputs: [ASSET_VALUE]
#! Outputs: [balance]
#!
#! Where:
#! - ASSET_VALUE is the fungible asset from which to extract the balance.
#! - balance is the amount of the fungible asset.
pub proc fungible_value_into_amount
movdn.3 drop drop drop
# => [balance]
end
#! Returns the balance of the given fungible asset.
#!
#! WARNING: Assumes that the given asset value is fungible and does NOT validate it.
#!
#! Inputs: [ASSET_KEY, ASSET_VALUE]
#! Outputs: [amount, ASSET_KEY, ASSET_VALUE]
#!
#! Where:
#! - ASSET_VALUE is the fungible asset from which to extract the balance.
#! - amount is the amount of the fungible asset.
pub proc fungible_to_amount
# => [ASSET_KEY, [amount, 0, 0, 0]]
dup.4
# => [amount, ASSET_KEY, ASSET_VALUE]
end
#! Returns the faucet ID from an asset vault key.
#!
#! WARNING: The faucet ID is not validated.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [faucet_id_suffix, faucet_id_prefix, ASSET_KEY]
#!
#! Where:
#! - faucet_id is the account ID in the vault key.
#! - ASSET_KEY is the vault key from which to extract the faucet ID.
pub proc key_to_faucet_id
# => [asset_id_suffix, asset_id_prefix, faucet_id_suffix_and_metadata, faucet_id_prefix]
dup.3 dup.3
# => [faucet_id_suffix_and_metadata, faucet_id_prefix, ASSET_KEY]
exec.split_suffix_and_metadata drop
# => [faucet_id_suffix, faucet_id_prefix, ASSET_KEY]
end
#! Returns the faucet ID from an asset vault key and consumes it.
#!
#! WARNING: The faucet ID is not validated.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [faucet_id_suffix, faucet_id_prefix]
#!
#! Where:
#! - faucet_id is the account ID in the vault key.
#! - ASSET_KEY is the vault key from which to extract the faucet ID.
pub proc key_into_faucet_id
# => [asset_id_suffix, asset_id_prefix, faucet_id_suffix_and_metadata, faucet_id_prefix]
drop drop
# => [faucet_id_suffix_and_metadata, faucet_id_prefix]
exec.split_suffix_and_metadata drop
# => [faucet_id_suffix, faucet_id_prefix]
end
#! Returns the asset ID from an asset vault key.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [asset_id_suffix, asset_id_prefix, ASSET_KEY]
#!
#! Where:
#! - asset_id is the asset ID in the vault key.
#! - ASSET_KEY is the vault key from which to extract the asset ID.
pub proc key_to_asset_id
# => [asset_id_suffix, asset_id_prefix, faucet_id_suffix, faucet_id_prefix]
dup.1 dup.1
# => [asset_id_suffix, asset_id_prefix, ASSET_KEY]
end
#! Returns the asset ID from an asset vault key and consumes it.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [asset_id_suffix, asset_id_prefix]
#!
#! Where:
#! - asset_id is the asset ID in the vault key.
#! - ASSET_KEY is the vault key from which to extract the asset ID.
pub proc key_into_asset_id
# => [asset_id_suffix, asset_id_prefix, faucet_id_suffix, faucet_id_prefix]
movup.2 drop movup.2 drop
# => [asset_id_suffix, asset_id_prefix]
end
#! Returns the asset callbacks flag from an asset vault key.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [callbacks_enabled, ASSET_KEY]
#!
#! Where:
#! - ASSET_KEY is the vault key from which to extract the metadata.
#! - callbacks_enabled is 1 if callbacks are enabled and 0 if disabled.
pub proc key_to_callbacks_enabled
# => [asset_id_suffix, asset_id_prefix, faucet_id_suffix_and_metadata, faucet_id_prefix]
dup.2
# => [faucet_id_suffix_and_metadata, ASSET_KEY]
exec.split_suffix_and_metadata swap drop
# => [asset_metadata, ASSET_KEY]
exec.metadata_into_callbacks_enabled
# => [callbacks_enabled, ASSET_KEY]
end
#! Creates a fungible asset vault key for the specified faucet.
#!
#! Inputs: [enable_callbacks, faucet_id_suffix, faucet_id_prefix]
#! Outputs: [ASSET_KEY]
#!
#! Where:
#! - enable_callbacks is a flag (0 or 1) indicating whether asset callbacks are enabled.
#! - faucet_id_{suffix,prefix} are the suffix and prefix felts of the fungible faucet.
#! - ASSET_KEY is the vault key for the fungible asset.
#!
#! Panics if:
#! - enable_callbacks is not 0 or 1.
#!
#! Invocation: exec
pub proc create_fungible_key
exec.create_metadata
# => [asset_metadata, faucet_id_suffix, faucet_id_prefix]
# merge the asset metadata into the lower 8 bits of the suffix
# this is safe since create_metadata builds only valid metadata
add
# => [faucet_id_suffix_and_metadata, faucet_id_prefix]
push.0.0
# => [0, 0, faucet_id_suffix_and_metadata, faucet_id_prefix]
# => [ASSET_KEY]
end
#! Creates a fungible asset for the specified fungible faucet and amount.
#!
#! WARNING: Does not validate the faucet ID or amount.
#!
#! Inputs: [enable_callbacks, faucet_id_suffix, faucet_id_prefix, amount]
#! Outputs: [ASSET_KEY, ASSET_VALUE]
#!
#! Where:
#! - enable_callbacks is a flag (0 or 1) indicating whether asset callbacks are enabled.
#! - faucet_id_{suffix,prefix} are the suffix and prefix felts of the faucet to create the asset
#! for.
#! - amount is the amount of the asset to create.
#! - ASSET_KEY is the vault key of the created fungible asset
#! - ASSET_VALUE is the value of the created fungible asset.
#!
#! Panics if:
#! - enable_callbacks is not 0 or 1.
#!
#! Invocation: exec
pub proc create_fungible_asset_unchecked
# => [enable_callbacks, faucet_id_suffix, faucet_id_prefix, amount]
# pad amount into ASSET_VALUE
repeat.3 push.0 movdn.4 end
# => [enable_callbacks, faucet_id_suffix, faucet_id_prefix, ASSET_VALUE]
exec.create_fungible_key
# => [ASSET_KEY, ASSET_VALUE]
end
#! Creates a non fungible asset for the specified non-fungible faucet.
#!
#! WARNING: Does not validate its inputs.
#!
#! Inputs: [enable_callbacks, faucet_id_suffix, faucet_id_prefix, DATA_HASH]
#! Outputs: [ASSET_KEY, ASSET_VALUE]
#!
#! Where:
#! - enable_callbacks is a flag (0 or 1) indicating whether asset callbacks are enabled.
#! - faucet_id_{suffix,prefix} are the suffix and prefix felts of the faucet to create the asset
#! for.
#! - DATA_HASH is the data hash of the non-fungible asset to create.
#! - ASSET_KEY is the vault key of the created non-fungible asset.
#! - ASSET_VALUE is the value of the created non-fungible asset, which is identical to DATA_HASH.
#!
#! Panics if:
#! - enable_callbacks is not 0 or 1.
#!
#! Invocation: exec
pub proc create_non_fungible_asset_unchecked
exec.create_metadata
# => [asset_metadata, faucet_id_suffix, faucet_id_prefix, DATA_HASH]
# merge the asset metadata into the lower 8 bits of the suffix
add
# => [faucet_id_suffix_and_metadata, faucet_id_prefix, DATA_HASH]
# copy hashes at indices 0 and 1 in the data hash word to the corresponding index in the key
# word
dup.3 dup.3
# => [hash0, hash1, faucet_id_suffix_and_metadata, faucet_id_prefix, DATA_HASH]
# => [ASSET_KEY, ASSET_VALUE]
end
#! Splits the merged faucet ID suffix and the asset metadata.
#!
#! Inputs: [faucet_id_suffix_and_metadata]
#! Outputs: [asset_metadata, faucet_id_suffix]
#!
#! Where:
#! - faucet_id_suffix_and_metadata is the faucet ID suffix merged with the asset metadata.
#! - faucet_id_suffix is the suffix of the account ID.
#! - asset_metadata is the asset metadata.
pub proc split_suffix_and_metadata
u32split
# => [suffix_metadata_lo, suffix_metadata_hi]
dup movdn.2
# => [suffix_metadata_lo, suffix_metadata_hi, suffix_metadata_lo]
# clear lower 8 bits of the lo part to get the actual ID suffix
u32and.0xffffff00 swap
# => [suffix_metadata_hi, suffix_metadata_lo', suffix_metadata_lo]
# reassemble the ID suffix by multiplying the hi part with 2^32 and adding the lo part
mul.0x0100000000 add
# => [faucet_id_suffix, suffix_metadata_lo]
# extract lower 8 bits of the lo part to get the metadata
swap u32and.0xff
# => [asset_metadata, faucet_id_suffix]
end
#! Validates that asset metadata is well formed and consumes it.
#!
#! Inputs: [asset_metadata]
#! Outputs: []
#!
#! Panics if:
#! - asset_metadata is not a valid u32 or exceeds CALLBACKS_ENABLED.
pub proc validate_metadata
u32assert.err=ERR_VAULT_INVALID_ENABLE_CALLBACKS
u32lte.CALLBACKS_ENABLED
assert.err=ERR_VAULT_INVALID_ENABLE_CALLBACKS
# => []
end
#! Creates asset metadata from the provided inputs.
#!
#! Inputs: [enable_callbacks]
#! Outputs: [asset_metadata]
#!
#! Where:
#! - enable_callbacks is a flag (0 or 1) indicating whether the asset callbacks flag should be set.
#! - asset_metadata is the asset metadata.
#!
#! Panics if:
#! - enable_callbacks is not 0 or 1.
proc create_metadata
# for now, enable_callbacks is identical to asset_metadata
dup exec.validate_metadata
# => [asset_metadata]
end
#! Extracts the asset callback flag from asset metadata.
#!
#! WARNING: asset_metadata is assumed to be a byte (in particular a valid u32)
#!
#! Inputs: [asset_metadata]
#! Outputs: [callbacks_enabled]
#!
#! Where:
#! - asset_metadata is the asset metadata.
#! - callbacks_enabled is 1 if callbacks are enabled and 0 if disabled.
proc metadata_into_callbacks_enabled
# extract the least significant bit of the metadata
u32and.1
# => [callbacks_enabled]
end