# ERRORS
# =================================================================================================
const ERR_ACCOUNT_ID_UNKNOWN_VERSION="unknown version in account ID"
const ERR_ACCOUNT_ID_SUFFIX_MOST_SIGNIFICANT_BIT_MUST_BE_ZERO="most significant bit of the account ID suffix must be zero"
const ERR_ACCOUNT_ID_UNKNOWN_STORAGE_MODE="unknown account storage mode in account ID"
const ERR_ACCOUNT_ID_SUFFIX_LEAST_SIGNIFICANT_BYTE_MUST_BE_ZERO="least significant byte of the account ID suffix must be zero"
const ERR_ACCOUNT_ID_NON_PUBLIC_NETWORK_ACCOUNT="the account ID must have storage mode public if the network flag is set"
# CONSTANTS
# =================================================================================================
# Bit pattern for a faucet account, after the account type mask has been applied.
const FAUCET_ACCOUNT=0x20 # 0b10_0000
# Bit pattern for an account w/ updatable code, after the account type mask has been applied.
const REGULAR_ACCOUNT_UPDATABLE_CODE=0x10 # 0b01_0000
# Bit pattern for an account w/ immutable code, after the account type mask has been applied.
const REGULAR_ACCOUNT_IMMUTABLE_CODE=0 # 0b00_0000
# Bit pattern for a fungible faucet w/ immutable code, after the account type mask has been applied.
const FUNGIBLE_FAUCET_ACCOUNT=0x20 # 0b10_0000
# Bit pattern for a non-fungible faucet w/ immutable code, after the account type mask has been
# applied.
const NON_FUNGIBLE_FAUCET_ACCOUNT=0x30 # 0b11_0000
# Given the least significant 32 bits of an account id's prefix, this mask defines the bits used
# to determine the account type.
const ACCOUNT_ID_TYPE_MASK_U32=0x30 # 0b11_0000
# Given the least significant 32 bits of an account id's prefix, this mask defines the bits used
# to determine the account version.
const ACCOUNT_VERSION_MASK_U32=0x0f # 0b1111
# Given the least significant 32 bits of an account ID's prefix, this mask defines the bits used
# to determine the account storage mode.
const ACCOUNT_ID_STORAGE_MODE_MASK_U32=0xC0 # 0b1100_0000
# Given the least significant 32 bits of an account ID's first felt with the storage mode mask
# applied, this value defines the non-existent, invalid storage mode.
const ACCOUNT_ID_STORAGE_MODE_INVALID_U32=0xc0 # 0b1100_0000
# PROCEDURES
# =================================================================================================
#! Returns a boolean indicating whether the account is a fungible faucet.
#!
#! Inputs: [account_id_prefix]
#! Outputs: [is_fungible_faucet]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_fungible_faucet is a boolean indicating whether the account is a fungible faucet.
pub proc is_fungible_faucet
exec.id_type eq.FUNGIBLE_FAUCET_ACCOUNT
# => [is_fungible_faucet]
end
#! Returns a boolean indicating whether the account is a non-fungible faucet.
#!
#! Inputs: [account_id_prefix]
#! Outputs: [is_non_fungible_faucet]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_non_fungible_faucet is a boolean indicating whether the account is a non-fungible faucet.
pub proc is_non_fungible_faucet
exec.id_type eq.NON_FUNGIBLE_FAUCET_ACCOUNT
# => [is_non_fungible_faucet]
end
#! Returns a boolean indicating whether the given account_ids are equal.
#!
#! Inputs: [account_id_suffix, account_id_prefix, other_account_id_suffix, other_account_id_prefix]
#! Outputs: [is_id_equal]
#!
#! Where:
#! - account_id_{suffix,prefix} are the suffix and prefix felts of an account ID.
#! - other_account_id_{suffix,prefix} are the suffix and prefix felts of the other account ID to
#! compare against.
#! - is_id_equal is a boolean indicating whether the account IDs are equal.
pub proc is_equal
movup.2 eq
# => [is_suffix_equal, account_id_prefix, other_account_id_prefix]
movdn.2 eq
# => [is_prefix_equal, is_suffix_equal]
and
# => [is_id_equal]
end
#! Returns a boolean indicating whether the account is a faucet.
#!
#! Inputs: [account_id_prefix]
#! Outputs: [is_faucet]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_faucet is a boolean indicating whether the account is a faucet.
pub proc is_faucet
u32split swap drop u32and.FAUCET_ACCOUNT neq.0
# => [is_faucet]
end
#! Returns a boolean indicating whether the account is a regular updatable account.
#!
#! Inputs: [account_id_prefix]
#! Outputs: [is_updatable_account]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_updatable_account is a boolean indicating whether the account is a regular updatable
#! account.
pub proc is_updatable_account
exec.id_type eq.REGULAR_ACCOUNT_UPDATABLE_CODE
# => [is_updatable_account]
end
#! Returns a boolean indicating whether the account is a regular immutable account.
#!
#! Inputs: [account_id_prefix]
#! Outputs: [is_immutable_account]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_immutable_account is a boolean indicating whether the account is a regular immutable
#! account.
pub proc is_immutable_account
exec.id_type eq.REGULAR_ACCOUNT_IMMUTABLE_CODE
# => [is_immutable_account]
end
#! Validates an account ID. Note that this does not validate anything about the account type,
#! since any 2-bit pattern is a valid account type.
#!
#! Inputs: [account_id_suffix, account_id_prefix]
#! Outputs: []
#!
#! Where:
#! - account_id_{suffix,prefix} are the suffix and prefix felts of the account ID.
#!
#! Panics if:
#! - account_id_prefix does not contain version zero.
#! - account_id_prefix does not contain either the public, network or private storage mode.
#! - account_id_suffix does not have its most significant bit set to zero.
#! - account_id_suffix does not have its lower 8 bits set to zero.
pub proc validate
# Validate lower 8 bits of suffix are zero.
# ---------------------------------------------------------------------------------------------
u32split
# => [account_id_suffix_lo, account_id_suffix_hi, account_id_prefix]
u32and.0xff eq.0
# => [is_least_significant_byte_zero, account_id_suffix_hi, account_id_prefix]
assert.err=ERR_ACCOUNT_ID_SUFFIX_LEAST_SIGNIFICANT_BYTE_MUST_BE_ZERO
# => [account_id_suffix_hi, account_id_prefix]
# Validate most significant bit in suffix is zero.
# ---------------------------------------------------------------------------------------------
u32shr.31 eq.0
# => [is_most_significant_bit_zero, account_id_prefix]
assert.err=ERR_ACCOUNT_ID_SUFFIX_MOST_SIGNIFICANT_BIT_MUST_BE_ZERO
# => [account_id_prefix]
# Validate version in prefix. For now only version 0 is supported.
# ---------------------------------------------------------------------------------------------
dup exec.id_version
# => [id_version, account_id_prefix]
assertz.err=ERR_ACCOUNT_ID_UNKNOWN_VERSION
# => [account_id_prefix]
# Validate storage mode in prefix.
# ---------------------------------------------------------------------------------------------
# there are 3 valid and 1 invalid storage mode
# instead of checking the presence of any of the valid modes, we check the absence of the
# invalid mode
u32split swap drop
# => [account_id_prefix_lo]
u32and.ACCOUNT_ID_STORAGE_MODE_MASK_U32
# => [id_storage_mode_masked]
eq.ACCOUNT_ID_STORAGE_MODE_INVALID_U32
# => [is_storage_mode_invalid]
assertz.err=ERR_ACCOUNT_ID_UNKNOWN_STORAGE_MODE
# => []
end
#! Shapes the suffix so it meets the requirements of the account ID, by setting the lower 8 bits to
#! zero.
#!
#! Inputs: [seed_digest_suffix]
#! Outputs: [account_id_suffix]
#!
#! Where:
#! - seed_digest_suffix is the suffix of the digest that should be shaped into the suffix
#! of an account ID.
#! - account_id_suffix is the suffix of an account ID.
pub proc shape_suffix
u32split
# => [seed_digest_suffix_lo, seed_digest_suffix_hi]
# clear lower 8 bits of the lo part
u32and.0xffffff00 swap
# => [seed_digest_suffix_hi, seed_digest_suffix_lo']
# reassemble the suffix by multiplying the hi part with 2^32 and adding the lo part
mul.0x0100000000 add
# => [account_id_suffix]
end
# HELPER PROCEDURES
# =================================================================================================
#! Extracts the account ID version from the prefix of an account ID.
#!
#! Inputs: [account_id_prefix]
#! Outputs: [id_version]
#!
#! Where:
#! - account_id_prefix is the prefix of an account ID.
#! - id_version is the version number of the ID.
proc id_version
# extract the lower 32 bits
u32split swap drop
# => [account_id_prefix_lo]
# mask out the version
u32and.ACCOUNT_VERSION_MASK_U32
# => [id_version]
end
#! Returns the least significant half of an account ID prefix with the account type bits masked out.
#!
#! The account type can be obtained by comparing this value with the following constants:
#! - REGULAR_ACCOUNT_UPDATABLE_CODE
#! - REGULAR_ACCOUNT_IMMUTABLE_CODE
#! - FUNGIBLE_FAUCET_ACCOUNT
#! - NON_FUNGIBLE_FAUCET_ACCOUNT
#!
#! Inputs: [account_id_prefix]
#! Outputs: [account_type]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - account_type is the account type.
proc id_type
u32split swap drop u32and.ACCOUNT_ID_TYPE_MASK_U32
# => [account_type]
end