Skip to content

Latest commit

 

History

History
5125 lines (3119 loc) · 320 KB

transaction_script_documentation.md

File metadata and controls

5125 lines (3119 loc) · 320 KB

Overview of Diem Transaction Scripts

Introduction

On-chain state is updated via the execution of transaction scripts sent from accounts that exist on-chain. This page documents each allowed transaction script on Diem, and the common state changes that can be performed to the blockchain via these transaction scripts along with their arguments and common error conditions.

The execution of a transaction script can result in a number of different error conditions and statuses being returned for each transaction that is committed on-chain. These statuses and errors can be categorized into two buckets:

  • Predefined statuses: are specific statuses that are returned from the VM, e.g., OutOfGas, or Executed; and
  • Move Abort errors: are errors that are raised from the Move modules and/or scripts published on-chain.

There are also a number of statuses that can be returned at the time of submission of the transaction to the system through JSON-RPC, these are detailed in the JSON-RPC specification.

Predefined Statuses

The predefined set of runtime statuses that can be returned to the user as a result of executing any transaction script is given by the following table:

Name Description
Executed The transaction was executed successfully.
OutOfGas The transaction ran out of gas during execution.
MiscellaneousError The transaction was malformed, e.g., an argument was not in BCS format. Possible, but unlikely to occur.
ExecutionFailure{ ...} The transaction encountered an uncaught error. Possible, but unlikely to occur.

This set of statuses is considered stable, and they should not be expected to change. Any changes will be publicized and an upgrade process will be outlined if/when these statuses or their meanings are updated.

Move Aborts

Each Move abort error status consists of two pieces of data:

  • The Move location where the abort was raised. This can be either from within a Script or from within a specific Module.
  • The abort_code that was raised.

The abort_code is a u64 that is constructed from two values:

  1. The error category which is encoded in the lower 8 bits of the code. Error categories are declared in the Errors module and are globally unique across the Diem framework. There is a limited fixed set of predefined categories, and the framework is guaranteed to use these consistently.
  2. The error reason which is encoded in the remaining 56 bits of the code. The reason is a unique number relative to the module which raised the error and can be used to obtain more information about the error at hand. It should primarily be used for diagnosis purposes. Error reasons may change over time as the framework evolves.

The most common set of Move abort errors that can be returned depend on the transaction script and they are therefore detailed in the documentation for each transaction script. Each abort condition is broken down into its category, reason, and a description of the error in the context of the particular transaction script e.g.,

Error Category Error Reason Description
Errors::NOT_PUBLISHED DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY payer doesn't hold a balance in Currency.
Errors::LIMIT_EXCEEDED DiemAccount::EINSUFFICIENT_BALANCE amount is greater than payer's balance in Currency.

For each of these tables, the error categories should be considered stable; any changes to these categories will be be well-publicized in advance. On the other hand, the error reasons should be considered only semi-stable; changes to these may occur without notice, but changes are not expected to be common.

Move Explain

The abort conditions detailed in each transaction script are not meant to be complete, but the list of error categories are. Additionally, any abort conditions raised will have a human readable explanation attached to it (if possible) in the response from a JSON-RPC query for a committed transaction. These explanations are based off of the human-understandable explanations provided by the Move Explain tool which can also be called on the command-line.

Specifications

Transaction scripts come together with formal specifications. See this document for a discussion of specifications and pointers to further documentation.


Transaction Script Summaries


The set of transaction scripts that are allowed to be sent to the blockchain can be categorized into six different buckets:

This section contains a brief summary for each along with a link to the script's detailed documentation. The entire list of detailed documentation for each transaction script categorized in the same manner as here can be found in the transaction scripts section in this document.

Account Creation


Script create_child_vasp_account

Creates a Child VASP account with its parent being the sending account of the transaction. The sender of the transaction must be a Parent VASP account.

Script documentation: create_child_vasp_account


Script create_validator_operator_account

Creates a Validator Operator account. This transaction can only be sent by the Diem Root account.

Script documentation: create_validator_operator_account


Script create_validator_account

Creates a Validator account. This transaction can only be sent by the Diem Root account.

Script documentation: create_validator_account


Script create_parent_vasp_account

Creates a Parent VASP account with the specified human name. Must be called by the Treasury Compliance account.

Script documentation: create_parent_vasp_account


Script create_designated_dealer

Creates a Designated Dealer account with the provided information, and initializes it with default mint tiers. The transaction can only be sent by the Treasury Compliance account.

Script documentation: create_designated_dealer

Account Administration


Script add_currency_to_account

Adds a zero Currency balance to the sending account. This will enable account to send, receive, and hold Diem::Diem<Currency> coins. This transaction can be successfully sent by any account that is allowed to hold balances (e.g., VASP, Designated Dealer).

Script documentation: add_currency_to_account


Script add_recovery_rotation_capability

Stores the sending accounts ability to rotate its authentication key with a designated recovery account. Both the sending and recovery accounts need to belong to the same VASP and both be VASP accounts. After this transaction both the sending account and the specified recovery account can rotate the sender account's authentication key.

Script documentation: add_recovery_rotation_capability


Script publish_shared_ed25519_public_key

Rotates the authentication key of the sending account to the newly-specified public key and publishes a new shared authentication key under the sender's account. Any account can send this transaction.

Script documentation: publish_shared_ed25519_public_key


Script rotate_authentication_key

Rotates the transaction sender's authentication key to the supplied new authentication key. May be sent by any account.

Script documentation: rotate_authentication_key


Script rotate_authentication_key_with_nonce

Rotates the sender's authentication key to the supplied new authentication key. May be sent by any account that has a sliding nonce resource published under it (usually this is Treasury Compliance or Diem Root accounts).

Script documentation: rotate_authentication_key_with_nonce


Script rotate_authentication_key_with_nonce_admin

Rotates the specified account's authentication key to the supplied new authentication key. May only be sent by the Diem Root account as a write set transaction.

Script documentation: rotate_authentication_key_with_nonce_admin


Script rotate_authentication_key_with_recovery_address

Rotates the authentication key of a specified account that is part of a recovery address to a new authentication key. Only used for accounts that are part of a recovery address (see Script::add_recovery_rotation_capability for account restrictions).

Script documentation: rotate_authentication_key_with_recovery_address


Script rotate_dual_attestation_info

Updates the url used for off-chain communication, and the public key used to verify dual attestation on-chain. Transaction can be sent by any account that has dual attestation information published under it. In practice the only such accounts are Designated Dealers and Parent VASPs.

Script documentation: rotate_dual_attestation_info


Script rotate_shared_ed25519_public_key

Rotates the authentication key in a SharedEd25519PublicKey. This transaction can be sent by any account that has previously published a shared ed25519 public key using Script::publish_shared_ed25519_public_key.

Script documentation: rotate_shared_ed25519_public_key

Payments


Script peer_to_peer_with_metadata

Transfers a given number of coins in a specified currency from one account to another. Transfers over a specified amount defined on-chain that are between two different VASPs, or other accounts that have opted-in will be subject to on-chain checks to ensure the receiver has agreed to receive the coins. This transaction can be sent by any account that can hold a balance, and to any account that can hold a balance. Both accounts must hold balances in the currency being transacted.

Script documentation: peer_to_peer_with_metadata

Validator and Validator Operator Administration


Script add_validator_and_reconfigure

Adds a validator account to the validator set, and triggers a reconfiguration of the system to admit the account to the validator set for the system. This transaction can only be successfully called by the Diem Root account.

Script documentation: add_validator_and_reconfigure


Script register_validator_config

Updates a validator's configuration. This does not reconfigure the system and will not update the configuration in the validator set that is seen by other validators in the network. Can only be successfully sent by a Validator Operator account that is already registered with a validator.

Script documentation: register_validator_config


Script remove_validator_and_reconfigure

This script removes a validator account from the validator set, and triggers a reconfiguration of the system to remove the validator from the system. This transaction can only be successfully called by the Diem Root account.

Script documentation: remove_validator_and_reconfigure


Script set_validator_config_and_reconfigure

Updates a validator's configuration, and triggers a reconfiguration of the system to update the validator set with this new validator configuration. Can only be successfully sent by a Validator Operator account that is already registered with a validator.

Script documentation: set_validator_config_and_reconfigure


Script set_validator_operator

Sets the validator operator for a validator in the validator's configuration resource "locally" and does not reconfigure the system. Changes from this transaction will not picked up by the system until a reconfiguration of the system is triggered. May only be sent by an account with Validator role.

Script documentation: set_validator_operator


Script set_validator_operator_with_nonce_admin

Sets the validator operator for a validator in the validator's configuration resource "locally" and does not reconfigure the system. Changes from this transaction will not picked up by the system until a reconfiguration of the system is triggered. May only be sent by the Diem Root account as a write set transaction.

Script documentation: set_validator_operator_with_nonce_admin

Treasury and Compliance Operations


Script preburn

Moves a specified number of coins in a given currency from the account's balance to its preburn area after which the coins may be burned. This transaction may be sent by any account that holds a balance and preburn area in the specified currency.

Script documentation: preburn


Script burn

Burns all coins held in the preburn resource at the specified preburn address and removes them from the system. The sending account must be the Treasury Compliance account. The account that holds the preburn resource will normally be a Designated Dealer, but there are no enforced requirements that it be one.

Script documentation: burn


Script cancel_burn

Cancels and returns all coins held in the preburn area under preburn_address and returns the funds to the preburn_address's balance. Can only be successfully sent by an account with Treasury Compliance role.

Script documentation: cancel_burn


Script burn_txn_fees

Burns the transaction fees collected in the CoinType currency so that the Diem association may reclaim the backing coins off-chain. May only be sent by the Treasury Compliance account.

Script documentation: burn_txn_fees


Script tiered_mint

Mints a specified number of coins in a currency to a Designated Dealer. The sending account must be the Treasury Compliance account, and coins can only be minted to a Designated Dealer account.

Script documentation: tiered_mint


Script freeze_account

Freezes the account at address. The sending account of this transaction must be the Treasury Compliance account. The account being frozen cannot be the Diem Root or Treasury Compliance account. After the successful execution of this transaction no transactions may be sent from the frozen account, and the frozen account may not send or receive coins.

Script documentation: freeze_account


Script unfreeze_account

Unfreezes the account at address. The sending account of this transaction must be the Treasury Compliance account. After the successful execution of this transaction transactions may be sent from the previously frozen account, and coins may be sent and received.

Script documentation: unfreeze_account


Script update_dual_attestation_limit

Update the dual attestation limit on-chain. Defined in terms of micro-XDX. The transaction can only be sent by the Treasury Compliance account. After this transaction all inter-VASP payments over this limit must be checked for dual attestation.

Script documentation: update_dual_attestation_limit


Script update_exchange_rate

Update the rough on-chain exchange rate between a specified currency and XDX (as a conversion to micro-XDX). The transaction can only be sent by the Treasury Compliance account. After this transaction the updated exchange rate will be used for normalization of gas prices, and for dual attestation checking.

Script documentation: update_exchange_rate


Script update_minting_ability

Script to allow or disallow minting of new coins in a specified currency. This transaction can only be sent by the Treasury Compliance account. Turning minting off for a currency will have no effect on coins already in circulation, and coins may still be removed from the system.

Script documentation: update_minting_ability

System Administration


Script update_diem_version

Updates the Diem major version that is stored on-chain and is used by the VM. This transaction can only be sent from the Diem Root account.

Script documentation: update_diem_version


Script add_to_script_allow_list

Adds a script hash to the transaction allowlist. This transaction can only be sent by the Diem Root account. Scripts with this hash can be sent afterward the successful execution of this script.

Script documentation: add_to_script_allow_list


Transaction Scripts


Account Creation

Script create_child_vasp_account

Summary

Creates a Child VASP account with its parent being the sending account of the transaction. The sender of the transaction must be a Parent VASP account.

Technical Description

Creates a ChildVASP account for the sender parent_vasp at child_address with a balance of child_initial_balance in CoinType and an initial authentication key of auth_key_prefix | child_address.

If add_all_currencies is true, the child address will have a zero balance in all available currencies in the system.

The new account will be a child account of the transaction sender, which must be a Parent VASP account. The child account will be recorded against the limit of child accounts of the creating Parent VASP account.

Events

Successful execution with a child_initial_balance greater than zero will emit:

Parameters
Name Type Description
CoinType Type The Move type for the CoinType that the child account should be created with. CoinType must be an already-registered currency on-chain.
parent_vasp &signer The signer reference of the sending account. Must be a Parent VASP account.
child_address address Address of the to-be-created Child VASP account.
auth_key_prefix vector<u8> The authentication key prefix that will be used initially for the newly created account.
add_all_currencies bool Whether to publish balance resources for all known currencies when the account is created.
child_initial_balance u64 The initial balance in CoinType to give the child account when it's created.

Common Abort Conditions
Error Category Error Reason Description
Errors::INVALID_ARGUMENT DiemAccount::EMALFORMED_AUTHENTICATION_KEY The auth_key_prefix was not of length 32.
Errors::REQUIRES_ROLE Roles::EPARENT_VASP The sending account wasn't a Parent VASP account.
Errors::ALREADY_PUBLISHED Roles::EROLE_ID The child_address address is already taken.
Errors::LIMIT_EXCEEDED VASP::ETOO_MANY_CHILDREN The sending account has reached the maximum number of allowed child accounts.
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO The CoinType is not a registered currency on-chain.
Errors::INVALID_STATE DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED The withdrawal capability for the sending account has already been extracted.
Errors::NOT_PUBLISHED DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY The sending account doesn't have a balance in CoinType.
Errors::LIMIT_EXCEEDED DiemAccount::EINSUFFICIENT_BALANCE The sending account doesn't have at least child_initial_balance of CoinType balance.
Errors::INVALID_ARGUMENT DiemAccount::ECANNOT_CREATE_AT_VM_RESERVED The child_address is the reserved address 0x0.

Related Scripts
public fun create_child_vasp_account<CoinType>(parent_vasp: &signer, child_address: address, auth_key_prefix: vector<u8>, add_all_currencies: bool, child_initial_balance: u64)
Implementation
fun create_child_vasp_account<CoinType>(
    parent_vasp: &signer,
    child_address: address,
    auth_key_prefix: vector<u8>,
    add_all_currencies: bool,
    child_initial_balance: u64
) {
    DiemAccount::create_child_vasp_account<CoinType>(
        parent_vasp,
        child_address,
        auth_key_prefix,
        add_all_currencies,
    );
    // Give the newly created child `child_initial_balance` coins
    if (child_initial_balance > 0) {
        let vasp_withdrawal_cap = DiemAccount::extract_withdraw_capability(parent_vasp);
        DiemAccount::pay_from<CoinType>(
            &vasp_withdrawal_cap, child_address, child_initial_balance, x"", x""
        );
        DiemAccount::restore_withdraw_capability(vasp_withdrawal_cap);
    };
}
Specification
include DiemAccount::TransactionChecks{sender: parent_vasp};

let parent_addr = Signer::spec_address_of(parent_vasp);

let parent_cap = DiemAccount::spec_get_withdraw_cap(parent_addr);
include DiemAccount::CreateChildVASPAccountAbortsIf<CoinType>{
    parent: parent_vasp, new_account_address: child_address};
aborts_if child_initial_balance > max_u64() with Errors::LIMIT_EXCEEDED;
include (child_initial_balance > 0) ==>
    DiemAccount::ExtractWithdrawCapAbortsIf{sender_addr: parent_addr};
include (child_initial_balance > 0) ==>
    DiemAccount::PayFromAbortsIfRestricted<CoinType>{
        cap: parent_cap,
        payee: child_address,
        amount: child_initial_balance,
        metadata: x"",
        metadata_signature: x""
    };
include DiemAccount::CreateChildVASPAccountEnsures<CoinType>{
    parent_addr: parent_addr,
    child_addr: child_address,
};
ensures DiemAccount::balance<CoinType>(child_address) == child_initial_balance;
ensures DiemAccount::balance<CoinType>(parent_addr)
    == old(DiemAccount::balance<CoinType>(parent_addr)) - child_initial_balance;
aborts_with [check]
    Errors::REQUIRES_ROLE,
    Errors::ALREADY_PUBLISHED,
    Errors::LIMIT_EXCEEDED,
    Errors::NOT_PUBLISHED,
    Errors::INVALID_STATE,
    Errors::INVALID_ARGUMENT;

Access Control: Only Parent VASP accounts can create Child VASP accounts [A7].

include Roles::AbortsIfNotParentVasp{account: parent_vasp};

Script create_validator_operator_account

Summary

Creates a Validator Operator account. This transaction can only be sent by the Diem Root account.

Technical Description

Creates an account with a Validator Operator role at new_account_address, with authentication key auth_key_prefix | new_account_address. It publishes a ValidatorOperatorConfig::ValidatorOperatorConfig resource with the specified human_name. This script does not assign the validator operator to any validator accounts but only creates the account.

Parameters
Name Type Description
dr_account &signer The signer reference of the sending account of this transaction. Must be the Diem Root signer.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
new_account_address address Address of the to-be-created Validator account.
auth_key_prefix vector<u8> The authentication key prefix that will be used initially for the newly created account.
human_name vector<u8> ASCII-encoded human name for the validator.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under dr_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::REQUIRES_ROLE Roles::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::ALREADY_PUBLISHED Roles::EROLE_ID The new_account_address address is already taken.

Related Scripts
public fun create_validator_operator_account(dr_account: &signer, sliding_nonce: u64, new_account_address: address, auth_key_prefix: vector<u8>, human_name: vector<u8>)
Implementation
fun create_validator_operator_account(
    dr_account: &signer,
    sliding_nonce: u64,
    new_account_address: address,
    auth_key_prefix: vector<u8>,
    human_name: vector<u8>
) {
    SlidingNonce::record_nonce_or_abort(dr_account, sliding_nonce);
    DiemAccount::create_validator_operator_account(
        dr_account,
        new_account_address,
        auth_key_prefix,
        human_name,
    );
}
Specification

Only Diem root may create Validator Operator accounts Authentication: ValidatorAccountAbortsIf includes AbortsIfNotDiemRoot. Checks that above table includes all error categories. The verifier finds an abort that is not documented, and cannot occur in practice:

  • REQUIRES_ROLE comes from Roles::assert_diem_root. However, assert_diem_root checks the literal Diem root address before checking the role, and the role abort is unreachable in practice, since only Diem root has the Diem root role.

Access Control: Only the Diem Root account can create Validator Operator accounts [A4].

include Roles::AbortsIfNotDiemRoot{account: dr_account};

Script create_validator_account

Summary

Creates a Validator account. This transaction can only be sent by the Diem Root account.

Technical Description

Creates an account with a Validator role at new_account_address, with authentication key auth_key_prefix | new_account_address. It publishes a ValidatorConfig::ValidatorConfig resource with empty config, and operator_account fields. The human_name field of the ValidatorConfig::ValidatorConfig is set to the passed in human_name. This script does not add the validator to the validator set or the system, but only creates the account.

Parameters
Name Type Description
dr_account &signer The signer reference of the sending account of this transaction. Must be the Diem Root signer.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
new_account_address address Address of the to-be-created Validator account.
auth_key_prefix vector<u8> The authentication key prefix that will be used initially for the newly created account.
human_name vector<u8> ASCII-encoded human name for the validator.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under dr_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::REQUIRES_ROLE Roles::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::ALREADY_PUBLISHED Roles::EROLE_ID The new_account_address address is already taken.

Related Scripts
public fun create_validator_account(dr_account: &signer, sliding_nonce: u64, new_account_address: address, auth_key_prefix: vector<u8>, human_name: vector<u8>)
Implementation
fun create_validator_account(
    dr_account: &signer,
    sliding_nonce: u64,
    new_account_address: address,
    auth_key_prefix: vector<u8>,
    human_name: vector<u8>,
) {
    SlidingNonce::record_nonce_or_abort(dr_account, sliding_nonce);
    DiemAccount::create_validator_account(
        dr_account,
        new_account_address,
        auth_key_prefix,
        human_name,
    );
  }
Specification

Only Diem root may create Validator accounts Authentication: ValidatorAccountAbortsIf includes AbortsIfNotDiemRoot. Checks that above table includes all error categories. The verifier finds an abort that is not documented, and cannot occur in practice:

  • REQUIRES_ROLE comes from Roles::assert_diem_root. However, assert_diem_root checks the literal Diem root address before checking the role, and the role abort is unreachable in practice, since only Diem root has the Diem root role.

Access Control: Only the Diem Root account can create Validator accounts [A3].

include Roles::AbortsIfNotDiemRoot{account: dr_account};

Script create_parent_vasp_account

Summary

Creates a Parent VASP account with the specified human name. Must be called by the Treasury Compliance account.

Technical Description

Creates an account with the Parent VASP role at address with authentication key auth_key_prefix | new_account_address and a 0 balance of type CoinType. If add_all_currencies is true, 0 balances for all available currencies in the system will also be added. This can only be invoked by an TreasuryCompliance account. sliding_nonce is a unique nonce for operation, see SlidingNonce for details.

Parameters
Name Type Description
CoinType Type The Move type for the CoinType currency that the Parent VASP account should be initialized with. CoinType must be an already-registered currency on-chain.
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
new_account_address address Address of the to-be-created Parent VASP account.
auth_key_prefix vector<u8> The authentication key prefix that will be used initially for the newly created account.
human_name vector<u8> ASCII-encoded human name for the Parent VASP.
add_all_currencies bool Whether to publish balance resources for all known currencies when the account is created.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under tc_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.
Errors::REQUIRES_ROLE Roles::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO The CoinType is not a registered currency on-chain.
Errors::ALREADY_PUBLISHED Roles::EROLE_ID The new_account_address address is already taken.

Related Scripts
public fun create_parent_vasp_account<CoinType>(tc_account: &signer, sliding_nonce: u64, new_account_address: address, auth_key_prefix: vector<u8>, human_name: vector<u8>, add_all_currencies: bool)
Implementation
fun create_parent_vasp_account<CoinType>(
    tc_account: &signer,
    sliding_nonce: u64,
    new_account_address: address,
    auth_key_prefix: vector<u8>,
    human_name: vector<u8>,
    add_all_currencies: bool
) {
    SlidingNonce::record_nonce_or_abort(tc_account, sliding_nonce);
    DiemAccount::create_parent_vasp_account<CoinType>(
        tc_account,
        new_account_address,
        auth_key_prefix,
        human_name,
        add_all_currencies
    );
}
Specification
include DiemAccount::TransactionChecks{sender: tc_account};
include SlidingNonce::RecordNonceAbortsIf{account: tc_account, seq_nonce: sliding_nonce};
include DiemAccount::CreateParentVASPAccountAbortsIf<CoinType>{creator_account: tc_account};
include DiemAccount::CreateParentVASPAccountEnsures<CoinType>;
aborts_with [check]
    Errors::INVALID_ARGUMENT,
    Errors::REQUIRES_ADDRESS,
    Errors::NOT_PUBLISHED,
    Errors::ALREADY_PUBLISHED,
    Errors::REQUIRES_ROLE;

Access Control: Only the Treasury Compliance account can create Parent VASP accounts [A6].

include Roles::AbortsIfNotTreasuryCompliance{account: tc_account};

Script create_designated_dealer

Summary

Creates a Designated Dealer account with the provided information, and initializes it with default mint tiers. The transaction can only be sent by the Treasury Compliance account.

Technical Description

Creates an account with the Designated Dealer role at addr with authentication key auth_key_prefix | addr and a 0 balance of type Currency. If add_all_currencies is true, 0 balances for all available currencies in the system will also be added. This can only be invoked by an account with the TreasuryCompliance role.

At the time of creation the account is also initialized with default mint tiers of (500_000, 5000_000, 50_000_000, 500_000_000), and preburn areas for each currency that is added to the account.

Parameters
Name Type Description
Currency Type The Move type for the Currency that the Designated Dealer should be initialized with. Currency must be an already-registered currency on-chain.
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
addr address Address of the to-be-created Designated Dealer account.
auth_key_prefix vector<u8> The authentication key prefix that will be used initially for the newly created account.
human_name vector<u8> ASCII-encoded human name for the Designated Dealer.
add_all_currencies bool Whether to publish preburn, balance, and tier info resources for all known (SCS) currencies or just Currency when the account is created.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under tc_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.
Errors::REQUIRES_ROLE Roles::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO The Currency is not a registered currency on-chain.
Errors::ALREADY_PUBLISHED Roles::EROLE_ID The addr address is already taken.

Related Scripts
public fun create_designated_dealer<Currency>(tc_account: &signer, sliding_nonce: u64, addr: address, auth_key_prefix: vector<u8>, human_name: vector<u8>, add_all_currencies: bool)
Implementation
fun create_designated_dealer<Currency>(
    tc_account: &signer,
    sliding_nonce: u64,
    addr: address,
    auth_key_prefix: vector<u8>,
    human_name: vector<u8>,
    add_all_currencies: bool,
) {
    SlidingNonce::record_nonce_or_abort(tc_account, sliding_nonce);
    DiemAccount::create_designated_dealer<Currency>(
        tc_account,
        addr,
        auth_key_prefix,
        human_name,
        add_all_currencies
    );
}
Specification
include DiemAccount::TransactionChecks{sender: tc_account};
include SlidingNonce::RecordNonceAbortsIf{account: tc_account, seq_nonce: sliding_nonce};
include DiemAccount::CreateDesignatedDealerAbortsIf<Currency>{
    creator_account: tc_account, new_account_address: addr};
include DiemAccount::CreateDesignatedDealerEnsures<Currency>{new_account_address: addr};
aborts_with [check]
    Errors::INVALID_ARGUMENT,
    Errors::REQUIRES_ADDRESS,
    Errors::NOT_PUBLISHED,
    Errors::ALREADY_PUBLISHED,
    Errors::REQUIRES_ROLE;

Access Control: Only the Treasury Compliance account can create Designated Dealer accounts [A5].

include Roles::AbortsIfNotTreasuryCompliance{account: tc_account};

Account Administration

Script add_currency_to_account

Summary

Adds a zero Currency balance to the sending account. This will enable account to send, receive, and hold Diem::Diem<Currency> coins. This transaction can be successfully sent by any account that is allowed to hold balances (e.g., VASP, Designated Dealer).

Technical Description

After the successful execution of this transaction the sending account will have a DiemAccount::Balance<Currency> resource with zero balance published under it. Only accounts that can hold balances can send this transaction, the sending account cannot already have a DiemAccount::Balance<Currency> published under it.

Parameters
Name Type Description
Currency Type The Move type for the Currency being added to the sending account of the transaction. Currency must be an already-registered currency on-chain.
account &signer The signer of the sending account of the transaction.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO The Currency is not a registered currency on-chain.
Errors::INVALID_ARGUMENT DiemAccount::EROLE_CANT_STORE_BALANCE The sending account's role does not permit balances.
Errors::ALREADY_PUBLISHED DiemAccount::EADD_EXISTING_CURRENCY A balance for Currency is already published under the sending account.

Related Scripts
public fun add_currency_to_account<Currency>(account: &signer)
Implementation
fun add_currency_to_account<Currency>(account: &signer) {
    DiemAccount::add_currency<Currency>(account);
}
Specification

Access Control: The account must be allowed to hold balances. Only Designated Dealers, Parent VASPs, and Child VASPs can hold balances [D1][D2][D3][D4][D5][D6][D7].


Script add_recovery_rotation_capability

Summary

Stores the sending accounts ability to rotate its authentication key with a designated recovery account. Both the sending and recovery accounts need to belong to the same VASP and both be VASP accounts. After this transaction both the sending account and the specified recovery account can rotate the sender account's authentication key.

Technical Description

Adds the DiemAccount::KeyRotationCapability for the sending account (to_recover_account) to the RecoveryAddress::RecoveryAddress resource under recovery_address. After this transaction has been executed successfully the account at recovery_address and the to_recover_account may rotate the authentication key of to_recover_account (the sender of this transaction).

The sending account of this transaction (to_recover_account) must not have previously given away its unique key rotation capability, and must be a VASP account. The account at recovery_address must also be a VASP account belonging to the same VASP as the to_recover_account. Additionally the account at recovery_address must have already initialized itself as a recovery account address using the Script::create_recovery_address transaction script.

The sending account's (to_recover_account) key rotation capability is removed in this transaction and stored in the RecoveryAddress::RecoveryAddress resource stored under the account at recovery_address.

Parameters
Name Type Description
to_recover_account &signer The signer reference of the sending account of this transaction.
recovery_address address The account address where the to_recover_account's DiemAccount::KeyRotationCapability will be stored.

Common Abort Conditions
Error Category Error Reason Description
Errors::INVALID_STATE DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED to_recover_account has already delegated/extracted its DiemAccount::KeyRotationCapability.
Errors::NOT_PUBLISHED RecoveryAddress::ERECOVERY_ADDRESS recovery_address does not have a RecoveryAddress resource published under it.
Errors::INVALID_ARGUMENT RecoveryAddress::EINVALID_KEY_ROTATION_DELEGATION to_recover_account and recovery_address do not belong to the same VASP.
Errors::LIMIT_EXCEEDED RecoveryAddress::EMAX_KEYS_REGISTERED RecoveryAddress::MAX_REGISTERED_KEYS have already been registered with this recovery_address.

Related Scripts
public fun add_recovery_rotation_capability(to_recover_account: &signer, recovery_address: address)
Implementation
fun add_recovery_rotation_capability(to_recover_account: &signer, recovery_address: address) {
    RecoveryAddress::add_rotation_capability(
        DiemAccount::extract_key_rotation_capability(to_recover_account), recovery_address
    )
}
Specification
include DiemAccount::TransactionChecks{sender: to_recover_account};
include DiemAccount::ExtractKeyRotationCapabilityAbortsIf{account: to_recover_account};
include DiemAccount::ExtractKeyRotationCapabilityEnsures{account: to_recover_account};

let addr = Signer::spec_address_of(to_recover_account);

let rotation_cap = DiemAccount::spec_get_key_rotation_cap(addr);
include RecoveryAddress::AddRotationCapabilityAbortsIf{
    to_recover: rotation_cap
};
ensures RecoveryAddress::spec_get_rotation_caps(recovery_address)[
    len(RecoveryAddress::spec_get_rotation_caps(recovery_address)) - 1] == old(rotation_cap);
aborts_with [check]
    Errors::INVALID_STATE,
    Errors::NOT_PUBLISHED,
    Errors::LIMIT_EXCEEDED,
    Errors::INVALID_ARGUMENT;

Script publish_shared_ed25519_public_key

Summary

Rotates the authentication key of the sending account to the newly-specified public key and publishes a new shared authentication key under the sender's account. Any account can send this transaction.

Technical Description

Rotates the authentication key of the sending account to public_key, and publishes a SharedEd25519PublicKey::SharedEd25519PublicKey resource containing the 32-byte ed25519 public_key and the DiemAccount::KeyRotationCapability for account under account.

Parameters
Name Type Description
account &signer The signer reference of the sending account of the transaction.
public_key vector<u8> 32-byte Ed25519 public key for account' authentication key to be rotated to and stored.

Common Abort Conditions
Error Category Error Reason Description
Errors::INVALID_STATE DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED account has already delegated/extracted its DiemAccount::KeyRotationCapability resource.
Errors::ALREADY_PUBLISHED SharedEd25519PublicKey::ESHARED_KEY The SharedEd25519PublicKey::SharedEd25519PublicKey resource is already published under account.
Errors::INVALID_ARGUMENT SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY public_key is an invalid ed25519 public key.

Related Scripts
public fun publish_shared_ed25519_public_key(account: &signer, public_key: vector<u8>)
Implementation
fun publish_shared_ed25519_public_key(account: &signer, public_key: vector<u8>) {
    SharedEd25519PublicKey::publish(account, public_key)
}
Specification

Script create_recovery_address

Summary

Initializes the sending account as a recovery address that may be used by the VASP that it belongs to. The sending account must be a VASP account. Multiple recovery addresses can exist for a single VASP, but accounts in each must be disjoint.

Technical Description

Publishes a RecoveryAddress::RecoveryAddress resource under account. It then extracts the DiemAccount::KeyRotationCapability for account and adds it to the resource. After the successful execution of this transaction other accounts may add their key rotation to this resource so that account may be used as a recovery account for those accounts.

Parameters
Name Type Description
account &signer The signer of the sending account of the transaction.

Common Abort Conditions
Error Category Error Reason Description
Errors::INVALID_STATE DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED account has already delegated/extracted its DiemAccount::KeyRotationCapability.
Errors::INVALID_ARGUMENT RecoveryAddress::ENOT_A_VASP account is not a VASP account.
Errors::INVALID_ARGUMENT RecoveryAddress::EKEY_ROTATION_DEPENDENCY_CYCLE A key rotation recovery cycle would be created by adding account's key rotation capability.
Errors::ALREADY_PUBLISHED RecoveryAddress::ERECOVERY_ADDRESS A RecoveryAddress::RecoveryAddress resource has already been published under account.

Related Scripts
public fun create_recovery_address(account: &signer)
Implementation
Specification
include DiemAccount::TransactionChecks{sender: account};
include DiemAccount::ExtractKeyRotationCapabilityAbortsIf;
include DiemAccount::ExtractKeyRotationCapabilityEnsures;

let account_addr = Signer::spec_address_of(account);

let rotation_cap = DiemAccount::spec_get_key_rotation_cap(account_addr);
include RecoveryAddress::PublishAbortsIf{
    recovery_account: account,
    rotation_cap: rotation_cap
};
ensures RecoveryAddress::spec_is_recovery_address(account_addr);
ensures len(RecoveryAddress::spec_get_rotation_caps(account_addr)) == 1;
ensures RecoveryAddress::spec_get_rotation_caps(account_addr)[0] == old(rotation_cap);
aborts_with [check]
    Errors::INVALID_STATE,
    Errors::INVALID_ARGUMENT,
    Errors::ALREADY_PUBLISHED;

Script rotate_authentication_key

Summary

Rotates the transaction sender's authentication key to the supplied new authentication key. May be sent by any account.

Technical Description

Rotate the account's DiemAccount::DiemAccount authentication_key field to new_key. new_key must be a valid ed25519 public key, and account must not have previously delegated its DiemAccount::KeyRotationCapability.

Parameters
Name Type Description
account &signer Signer reference of the sending account of the transaction.
new_key vector<u8> New ed25519 public key to be used for account.

Common Abort Conditions
Error Category Error Reason Description
Errors::INVALID_STATE DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED account has already delegated/extracted its DiemAccount::KeyRotationCapability.
Errors::INVALID_ARGUMENT DiemAccount::EMALFORMED_AUTHENTICATION_KEY new_key was an invalid length.

Related Scripts
public fun rotate_authentication_key(account: &signer, new_key: vector<u8>)
Implementation
fun rotate_authentication_key(account: &signer, new_key: vector<u8>) {
    let key_rotation_capability = DiemAccount::extract_key_rotation_capability(account);
    DiemAccount::rotate_authentication_key(&key_rotation_capability, new_key);
    DiemAccount::restore_key_rotation_capability(key_rotation_capability);
}
Specification
include DiemAccount::TransactionChecks{sender: account};

let account_addr = Signer::spec_address_of(account);
include DiemAccount::ExtractKeyRotationCapabilityAbortsIf;

let key_rotation_capability = DiemAccount::spec_get_key_rotation_cap(account_addr);
include DiemAccount::RotateAuthenticationKeyAbortsIf{cap: key_rotation_capability, new_authentication_key: new_key};

This rotates the authentication key of account to new_key

include DiemAccount::RotateAuthenticationKeyEnsures{addr: account_addr, new_authentication_key: new_key};
aborts_with [check]
    Errors::INVALID_STATE,
    Errors::INVALID_ARGUMENT;

Access Control: The account can rotate its own authentication key unless it has delegrated the capability [H17][J17].


Script rotate_authentication_key_with_nonce

Summary

Rotates the sender's authentication key to the supplied new authentication key. May be sent by any account that has a sliding nonce resource published under it (usually this is Treasury Compliance or Diem Root accounts).

Technical Description

Rotates the account's DiemAccount::DiemAccount authentication_key field to new_key. new_key must be a valid ed25519 public key, and account must not have previously delegated its DiemAccount::KeyRotationCapability.

Parameters
Name Type Description
account &signer Signer reference of the sending account of the transaction.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
new_key vector<u8> New ed25519 public key to be used for account.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::INVALID_STATE DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED account has already delegated/extracted its DiemAccount::KeyRotationCapability.
Errors::INVALID_ARGUMENT DiemAccount::EMALFORMED_AUTHENTICATION_KEY new_key was an invalid length.

Related Scripts
public fun rotate_authentication_key_with_nonce(account: &signer, sliding_nonce: u64, new_key: vector<u8>)
Implementation
fun rotate_authentication_key_with_nonce(account: &signer, sliding_nonce: u64, new_key: vector<u8>) {
    SlidingNonce::record_nonce_or_abort(account, sliding_nonce);
    let key_rotation_capability = DiemAccount::extract_key_rotation_capability(account);
    DiemAccount::rotate_authentication_key(&key_rotation_capability, new_key);
    DiemAccount::restore_key_rotation_capability(key_rotation_capability);
}
Specification
include DiemAccount::TransactionChecks{sender: account};

let account_addr = Signer::spec_address_of(account);
include SlidingNonce::RecordNonceAbortsIf{ seq_nonce: sliding_nonce };
include DiemAccount::ExtractKeyRotationCapabilityAbortsIf;

let key_rotation_capability = DiemAccount::spec_get_key_rotation_cap(account_addr);
include DiemAccount::RotateAuthenticationKeyAbortsIf{cap: key_rotation_capability, new_authentication_key: new_key};

This rotates the authentication key of account to new_key

include DiemAccount::RotateAuthenticationKeyEnsures{addr: account_addr, new_authentication_key: new_key};
aborts_with [check]
    Errors::INVALID_ARGUMENT,
    Errors::INVALID_STATE,
    Errors::NOT_PUBLISHED;

Access Control: The account can rotate its own authentication key unless it has delegrated the capability [H17][J17].


Script rotate_authentication_key_with_nonce_admin

Summary

Rotates the specified account's authentication key to the supplied new authentication key. May only be sent by the Diem Root account as a write set transaction.

Technical Description

Rotate the account's DiemAccount::DiemAccount authentication_key field to new_key. new_key must be a valid ed25519 public key, and account must not have previously delegated its DiemAccount::KeyRotationCapability.

Parameters
Name Type Description
dr_account &signer The signer reference of the sending account of the write set transaction. May only be the Diem Root signer.
account &signer Signer reference of account specified in the execute_as field of the write set transaction.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction for Diem Root.
new_key vector<u8> New ed25519 public key to be used for account.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under dr_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce in dr_account is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce in dr_account is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce in dr_account has been previously recorded.
Errors::INVALID_STATE DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED account has already delegated/extracted its DiemAccount::KeyRotationCapability.
Errors::INVALID_ARGUMENT DiemAccount::EMALFORMED_AUTHENTICATION_KEY new_key was an invalid length.

Related Scripts
public fun rotate_authentication_key_with_nonce_admin(dr_account: &signer, account: &signer, sliding_nonce: u64, new_key: vector<u8>)
Implementation
fun rotate_authentication_key_with_nonce_admin(dr_account: &signer, account: &signer, sliding_nonce: u64, new_key: vector<u8>) {
    SlidingNonce::record_nonce_or_abort(dr_account, sliding_nonce);
    let key_rotation_capability = DiemAccount::extract_key_rotation_capability(account);
    DiemAccount::rotate_authentication_key(&key_rotation_capability, new_key);
    DiemAccount::restore_key_rotation_capability(key_rotation_capability);
}
Specification
include DiemAccount::TransactionChecks{sender: account};

let account_addr = Signer::spec_address_of(account);
include SlidingNonce::RecordNonceAbortsIf{ account: dr_account, seq_nonce: sliding_nonce };
include DiemAccount::ExtractKeyRotationCapabilityAbortsIf;

let key_rotation_capability = DiemAccount::spec_get_key_rotation_cap(account_addr);
include DiemAccount::RotateAuthenticationKeyAbortsIf{cap: key_rotation_capability, new_authentication_key: new_key};

This rotates the authentication key of account to new_key

include DiemAccount::RotateAuthenticationKeyEnsures{addr: account_addr, new_authentication_key: new_key};
aborts_with [check]
    Errors::INVALID_ARGUMENT,
    Errors::INVALID_STATE,
    Errors::NOT_PUBLISHED;

Access Control: Only the Diem Root account can process the admin scripts [H9].

requires Roles::has_diem_root_role(dr_account);

This is ensured by DiemAccount::writeset_prologue. The account can rotate its own authentication key unless it has delegrated the capability [H17][J17].


Script rotate_authentication_key_with_recovery_address

Summary

Rotates the authentication key of a specified account that is part of a recovery address to a new authentication key. Only used for accounts that are part of a recovery address (see Script::add_recovery_rotation_capability for account restrictions).

Technical Description

Rotates the authentication key of the to_recover account to new_key using the DiemAccount::KeyRotationCapability stored in the RecoveryAddress::RecoveryAddress resource published under recovery_address. This transaction can be sent either by the to_recover account, or by the account where the RecoveryAddress::RecoveryAddress resource is published that contains to_recover's DiemAccount::KeyRotationCapability.

Parameters
Name Type Description
account &signer Signer reference of the sending account of the transaction.
recovery_address address Address where RecoveryAddress::RecoveryAddress that holds to_recover's DiemAccount::KeyRotationCapability is published.
to_recover address The address of the account whose authentication key will be updated.
new_key vector<u8> New ed25519 public key to be used for the account at the to_recover address.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED RecoveryAddress::ERECOVERY_ADDRESS recovery_address does not have a RecoveryAddress::RecoveryAddress resource published under it.
Errors::INVALID_ARGUMENT RecoveryAddress::ECANNOT_ROTATE_KEY The address of account is not recovery_address or to_recover.
Errors::INVALID_ARGUMENT RecoveryAddress::EACCOUNT_NOT_RECOVERABLE to_recover's DiemAccount::KeyRotationCapability is not in the RecoveryAddress::RecoveryAddress resource published under recovery_address.
Errors::INVALID_ARGUMENT DiemAccount::EMALFORMED_AUTHENTICATION_KEY new_key was an invalid length.

Related Scripts
public fun rotate_authentication_key_with_recovery_address(account: &signer, recovery_address: address, to_recover: address, new_key: vector<u8>)
Implementation
fun rotate_authentication_key_with_recovery_address(
    account: &signer,
    recovery_address: address,
    to_recover: address,
    new_key: vector<u8>
) {
    RecoveryAddress::rotate_authentication_key(account, recovery_address, to_recover, new_key)
}
Specification

Access Control: The delegatee at the recovery address has to hold the key rotation capability for the address to recover. The address of the transaction signer has to be either the delegatee's address or the address to recover [H17][J17].

let account_addr = Signer::spec_address_of(account);
aborts_if !RecoveryAddress::spec_holds_key_rotation_cap_for(recovery_address, to_recover) with Errors::INVALID_ARGUMENT;
aborts_if !(account_addr == recovery_address || account_addr == to_recover) with Errors::INVALID_ARGUMENT;

Script rotate_dual_attestation_info

Summary

Updates the url used for off-chain communication, and the public key used to verify dual attestation on-chain. Transaction can be sent by any account that has dual attestation information published under it. In practice the only such accounts are Designated Dealers and Parent VASPs.

Technical Description

Updates the base_url and compliance_public_key fields of the DualAttestation::Credential resource published under account. The new_key must be a valid ed25519 public key.

Events

Successful execution of this transaction emits two events:

Parameters
Name Type Description
account &signer Signer reference of the sending account of the transaction.
new_url vector<u8> ASCII-encoded url to be used for off-chain communication with account.
new_key vector<u8> New ed25519 public key to be used for on-chain dual attestation checking.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED DualAttestation::ECREDENTIAL A DualAttestation::Credential resource is not published under account.
Errors::INVALID_ARGUMENT DualAttestation::EINVALID_PUBLIC_KEY new_key is not a valid ed25519 public key.

Related Scripts
public fun rotate_dual_attestation_info(account: &signer, new_url: vector<u8>, new_key: vector<u8>)
Implementation
fun rotate_dual_attestation_info(account: &signer, new_url: vector<u8>, new_key: vector<u8>) {
    DualAttestation::rotate_base_url(account, new_url);
    DualAttestation::rotate_compliance_public_key(account, new_key)
}
Specification

Access Control: Only the account having Credential can rotate the info. Credential is granted to either a Parent VASP or a designated dealer [H16].


Script rotate_shared_ed25519_public_key

Summary

Rotates the authentication key in a SharedEd25519PublicKey. This transaction can be sent by any account that has previously published a shared ed25519 public key using Script::publish_shared_ed25519_public_key.

Technical Description

This first rotates the public key stored in account's SharedEd25519PublicKey::SharedEd25519PublicKey resource to public_key, after which it rotates the authentication key using the capability stored in account's SharedEd25519PublicKey::SharedEd25519PublicKey to a new value derived from public_key

Parameters
Name Type Description
account &signer The signer reference of the sending account of the transaction.
public_key vector<u8> 32-byte Ed25519 public key.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SharedEd25519PublicKey::ESHARED_KEY A SharedEd25519PublicKey::SharedEd25519PublicKey resource is not published under account.
Errors::INVALID_ARGUMENT SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY public_key is an invalid ed25519 public key.

Related Scripts
public fun rotate_shared_ed25519_public_key(account: &signer, public_key: vector<u8>)
Implementation
fun rotate_shared_ed25519_public_key(account: &signer, public_key: vector<u8>) {
    SharedEd25519PublicKey::rotate_key(account, public_key)
}
Specification
include DiemAccount::TransactionChecks{sender: account};
include SharedEd25519PublicKey::RotateKeyAbortsIf{new_public_key: public_key};
include SharedEd25519PublicKey::RotateKeyEnsures{new_public_key: public_key};
aborts_with [check]
    Errors::NOT_PUBLISHED,
    Errors::INVALID_ARGUMENT;

Payments

Script peer_to_peer_with_metadata

Summary

Transfers a given number of coins in a specified currency from one account to another. Transfers over a specified amount defined on-chain that are between two different VASPs, or other accounts that have opted-in will be subject to on-chain checks to ensure the receiver has agreed to receive the coins. This transaction can be sent by any account that can hold a balance, and to any account that can hold a balance. Both accounts must hold balances in the currency being transacted.

Technical Description

Transfers amount coins of type Currency from payer to payee with (optional) associated metadata and an (optional) metadata_signature on the message metadata | Signer::address_of(payer) | amount | DualAttestation::DOMAIN_SEPARATOR. The metadata and metadata_signature parameters are only required if amount >= DualAttestation::get_cur_microdiem_limit XDX and payer and payee are distinct VASPs. However, a transaction sender can opt in to dual attestation even when it is not required (e.g., a DesignatedDealer -> VASP payment) by providing a non-empty metadata_signature. Standardized metadata BCS format can be found in diem_types::transaction::metadata::Metadata.

Events

Successful execution of this script emits two events:

Parameters
Name Type Description
Currency Type The Move type for the Currency being sent in this transaction. Currency must be an already-registered currency on-chain.
payer &signer The signer reference of the sending account that coins are being transferred from.
payee address The address of the account the coins are being transferred to.
metadata vector<u8> Optional metadata about this payment.
metadata_signature vector<u8> Optional signature over metadata and payment information. See

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY payer doesn't hold a balance in Currency.
Errors::LIMIT_EXCEEDED DiemAccount::EINSUFFICIENT_BALANCE amount is greater than payer's balance in Currency.
Errors::INVALID_ARGUMENT DiemAccount::ECOIN_DEPOSIT_IS_ZERO amount is zero.
Errors::NOT_PUBLISHED DiemAccount::EPAYEE_DOES_NOT_EXIST No account exists at the payee address.
Errors::INVALID_ARGUMENT DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE An account exists at payee, but it does not accept payments in Currency.
Errors::INVALID_STATE AccountFreezing::EACCOUNT_FROZEN The payee account is frozen.
Errors::INVALID_ARGUMENT DualAttestation::EMALFORMED_METADATA_SIGNATURE metadata_signature is not 64 bytes.
Errors::INVALID_ARGUMENT DualAttestation::EINVALID_METADATA_SIGNATURE metadata_signature does not verify on the against the payee's DualAttestation::Credential compliance_public_key public key.
Errors::LIMIT_EXCEEDED DiemAccount::EWITHDRAWAL_EXCEEDS_LIMITS payer has exceeded its daily withdrawal limits for the backing coins of XDX.
Errors::LIMIT_EXCEEDED DiemAccount::EDEPOSIT_EXCEEDS_LIMITS payee has exceeded its daily deposit limits for XDX.

Related Scripts
public fun peer_to_peer_with_metadata<Currency>(payer: &signer, payee: address, amount: u64, metadata: vector<u8>, metadata_signature: vector<u8>)
Implementation
fun peer_to_peer_with_metadata<Currency>(
    payer: &signer,
    payee: address,
    amount: u64,
    metadata: vector<u8>,
    metadata_signature: vector<u8>
) {
    let payer_withdrawal_cap = DiemAccount::extract_withdraw_capability(payer);
    DiemAccount::pay_from<Currency>(
        &payer_withdrawal_cap, payee, amount, metadata, metadata_signature
    );
    DiemAccount::restore_withdraw_capability(payer_withdrawal_cap);
}
Specification
include DiemAccount::TransactionChecks{sender: payer};

let payer_addr = Signer::spec_address_of(payer);

let cap = DiemAccount::spec_get_withdraw_cap(payer_addr);
include DiemAccount::ExtractWithdrawCapAbortsIf{sender_addr: payer_addr};
include DiemAccount::PayFromAbortsIf<Currency>{cap: cap};

The balances of payer and payee change by the correct amount.

ensures payer_addr != payee
    ==> DiemAccount::balance<Currency>(payer_addr)
    == old(DiemAccount::balance<Currency>(payer_addr)) - amount;
ensures payer_addr != payee
    ==> DiemAccount::balance<Currency>(payee)
    == old(DiemAccount::balance<Currency>(payee)) + amount;
ensures payer_addr == payee
    ==> DiemAccount::balance<Currency>(payee)
    == old(DiemAccount::balance<Currency>(payee));
aborts_with [check]
    Errors::NOT_PUBLISHED,
    Errors::INVALID_STATE,
    Errors::INVALID_ARGUMENT,
    Errors::LIMIT_EXCEEDED;

Access Control: Both the payer and the payee must hold the balances of the Currency. Only Designated Dealers, Parent VASPs, and Child VASPs can hold balances [D1][D2][D3][D4][D5][D6][D7].

aborts_if !exists<DiemAccount::Balance<Currency>>(payer_addr) with Errors::NOT_PUBLISHED;
aborts_if !exists<DiemAccount::Balance<Currency>>(payee) with Errors::INVALID_ARGUMENT;

Validator and Validator Operator Administration

Script add_validator_and_reconfigure

Summary

Adds a validator account to the validator set, and triggers a reconfiguration of the system to admit the account to the validator set for the system. This transaction can only be successfully called by the Diem Root account.

Technical Description

This script adds the account at validator_address to the validator set. This transaction emits a DiemConfig::NewEpochEvent event and triggers a reconfiguration. Once the reconfiguration triggered by this script's execution has been performed, the account at the validator_address is considered to be a validator in the network.

This transaction script will fail if the validator_address address is already in the validator set or does not have a ValidatorConfig::ValidatorConfig resource already published under it.

Parameters
Name Type Description
dr_account &signer The signer reference of the sending account of this transaction. Must be the Diem Root signer.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
validator_name vector<u8> ASCII-encoded human name for the validator. Must match the human name in the ValidatorConfig::ValidatorConfig for the validator.
validator_address address The validator account address to be added to the validator set.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under dr_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::REQUIRES_ROLE Roles::EDIEM_ROOT The sending account is not the Diem Root account.
0 0 The provided validator_name does not match the already-recorded human name for the validator.
Errors::INVALID_ARGUMENT DiemSystem::EINVALID_PROSPECTIVE_VALIDATOR The validator to be added does not have a ValidatorConfig::ValidatorConfig resource published under it, or its config field is empty.
Errors::INVALID_ARGUMENT DiemSystem::EALREADY_A_VALIDATOR The validator_address account is already a registered validator.
Errors::INVALID_STATE DiemConfig::EINVALID_BLOCK_TIME An invalid time value was encountered in reconfiguration. Unlikely to occur.

Related Scripts
public fun add_validator_and_reconfigure(dr_account: &signer, sliding_nonce: u64, validator_name: vector<u8>, validator_address: address)
Implementation
fun add_validator_and_reconfigure(
    dr_account: &signer,
    sliding_nonce: u64,
    validator_name: vector<u8>,
    validator_address: address
) {
    SlidingNonce::record_nonce_or_abort(dr_account, sliding_nonce);
    assert(ValidatorConfig::get_human_name(validator_address) == validator_name, 0);
    DiemSystem::add_validator(dr_account, validator_address);
}
Specification
include DiemAccount::TransactionChecks{sender: dr_account};
include SlidingNonce::RecordNonceAbortsIf{seq_nonce: sliding_nonce, account: dr_account};
include ValidatorConfig::AbortsIfNoValidatorConfig{addr: validator_address};
aborts_if ValidatorConfig::get_human_name(validator_address) != validator_name with 0;
include DiemSystem::AddValidatorAbortsIf{validator_addr: validator_address};
include DiemSystem::AddValidatorEnsures{validator_addr: validator_address};

Reports INVALID_STATE because of is_operating() and !existsDiemSystem::CapabilityHolder. is_operating() is always true during transactions, and CapabilityHolder is published during initialization (Genesis). Reports REQUIRES_ROLE if dr_account is not Diem root, but that can't happen in practice because it aborts with NOT_PUBLISHED or REQUIRES_ADDRESS, first.

Access Control: Only the Diem Root account can add Validators [H13].

include Roles::AbortsIfNotDiemRoot{account: dr_account};

Script register_validator_config

Summary

Updates a validator's configuration. This does not reconfigure the system and will not update the configuration in the validator set that is seen by other validators in the network. Can only be successfully sent by a Validator Operator account that is already registered with a validator.

Technical Description

This updates the fields with corresponding names held in the ValidatorConfig::ValidatorConfig config resource held under validator_account. It does not emit a DiemConfig::NewEpochEvent so the copy of this config held in the validator set will not be updated, and the changes are only "locally" under the validator_account account address.

Parameters
Name Type Description
validator_operator_account &signer Signer reference of the sending account. Must be the registered validator operator for the validator at validator_address.
validator_account address The address of the validator's ValidatorConfig::ValidatorConfig resource being updated.
consensus_pubkey vector<u8> New Ed25519 public key to be used in the updated ValidatorConfig::ValidatorConfig.
validator_network_addresses vector<u8> New set of validator_network_addresses to be used in the updated ValidatorConfig::ValidatorConfig.
fullnode_network_addresses vector<u8> New set of fullnode_network_addresses to be used in the updated ValidatorConfig::ValidatorConfig.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED ValidatorConfig::EVALIDATOR_CONFIG validator_address does not have a ValidatorConfig::ValidatorConfig resource published under it.
Errors::INVALID_ARGUMENT ValidatorConfig::EINVALID_TRANSACTION_SENDER validator_operator_account is not the registered operator for the validator at validator_address.
Errors::INVALID_ARGUMENT ValidatorConfig::EINVALID_CONSENSUS_KEY consensus_pubkey is not a valid ed25519 public key.

Related Scripts
public fun register_validator_config(validator_operator_account: &signer, validator_account: address, consensus_pubkey: vector<u8>, validator_network_addresses: vector<u8>, fullnode_network_addresses: vector<u8>)
Implementation
fun register_validator_config(
    validator_operator_account: &signer,
    // TODO Rename to validator_addr, since it is an address.
    validator_account: address,
    consensus_pubkey: vector<u8>,
    validator_network_addresses: vector<u8>,
    fullnode_network_addresses: vector<u8>,
) {
    ValidatorConfig::set_config(
        validator_operator_account,
        validator_account,
        consensus_pubkey,
        validator_network_addresses,
        fullnode_network_addresses
    );
 }
Specification

Access control rule is that only the validator operator for a validator may set call this, but there is an aborts_if in SetConfigAbortsIf that tests that directly.

include DiemAccount::TransactionChecks{sender: validator_operator_account};
include ValidatorConfig::SetConfigAbortsIf {validator_addr: validator_account};
ensures ValidatorConfig::is_valid(validator_account);
aborts_with [check]
    Errors::INVALID_ARGUMENT,
    Errors::NOT_PUBLISHED;

Access Control: Only the Validator Operator account which has been registered with the validator can update the validator's configuration [H14].

aborts_if Signer::address_of(validator_operator_account) !=
            ValidatorConfig::get_operator(validator_account)
                with Errors::INVALID_ARGUMENT;

Script remove_validator_and_reconfigure

Summary

This script removes a validator account from the validator set, and triggers a reconfiguration of the system to remove the validator from the system. This transaction can only be successfully called by the Diem Root account.

Technical Description

This script removes the account at validator_address from the validator set. This transaction emits a DiemConfig::NewEpochEvent event. Once the reconfiguration triggered by this event has been performed, the account at validator_address is no longer considered to be a validator in the network. This transaction will fail if the validator at validator_address is not in the validator set.

Parameters
Name Type Description
dr_account &signer The signer reference of the sending account of this transaction. Must be the Diem Root signer.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
validator_name vector<u8> ASCII-encoded human name for the validator. Must match the human name in the ValidatorConfig::ValidatorConfig for the validator.
validator_address address The validator account address to be removed from the validator set.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under dr_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE The sending account is not the Diem Root account or Treasury Compliance account
0 0 The provided validator_name does not match the already-recorded human name for the validator.
Errors::INVALID_ARGUMENT DiemSystem::ENOT_AN_ACTIVE_VALIDATOR The validator to be removed is not in the validator set.
Errors::REQUIRES_ADDRESS CoreAddresses::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::REQUIRES_ROLE Roles::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::INVALID_STATE DiemConfig::EINVALID_BLOCK_TIME An invalid time value was encountered in reconfiguration. Unlikely to occur.

Related Scripts
public fun remove_validator_and_reconfigure(dr_account: &signer, sliding_nonce: u64, validator_name: vector<u8>, validator_address: address)
Implementation
fun remove_validator_and_reconfigure(
    dr_account: &signer,
    sliding_nonce: u64,
    validator_name: vector<u8>,
    validator_address: address
) {
    SlidingNonce::record_nonce_or_abort(dr_account, sliding_nonce);
    // TODO: Use an error code from Errors.move
    assert(ValidatorConfig::get_human_name(validator_address) == validator_name, 0);
    DiemSystem::remove_validator(dr_account, validator_address);
}
Specification
include DiemAccount::TransactionChecks{sender: dr_account};
include SlidingNonce::RecordNonceAbortsIf{seq_nonce: sliding_nonce, account: dr_account};
include ValidatorConfig::AbortsIfNoValidatorConfig{addr: validator_address};
aborts_if ValidatorConfig::get_human_name(validator_address) != validator_name with 0;
include DiemSystem::RemoveValidatorAbortsIf{validator_addr: validator_address};
include DiemSystem::RemoveValidatorEnsures{validator_addr: validator_address};

Reports INVALID_STATE because of is_operating() and !existsDiemSystem::CapabilityHolder. is_operating() is always true during transactions, and CapabilityHolder is published during initialization (Genesis). Reports REQUIRES_ROLE if dr_account is not Diem root, but that can't happen in practice because it aborts with NOT_PUBLISHED or REQUIRES_ADDRESS, first.

Access Control: Only the Diem Root account can remove Validators [H13].

include Roles::AbortsIfNotDiemRoot{account: dr_account};

Script set_validator_config_and_reconfigure

Summary

Updates a validator's configuration, and triggers a reconfiguration of the system to update the validator set with this new validator configuration. Can only be successfully sent by a Validator Operator account that is already registered with a validator.

Technical Description

This updates the fields with corresponding names held in the ValidatorConfig::ValidatorConfig config resource held under validator_account. It then emits a DiemConfig::NewEpochEvent to trigger a reconfiguration of the system. This reconfiguration will update the validator set on-chain with the updated ValidatorConfig::ValidatorConfig.

Parameters
Name Type Description
validator_operator_account &signer Signer reference of the sending account. Must be the registered validator operator for the validator at validator_address.
validator_account address The address of the validator's ValidatorConfig::ValidatorConfig resource being updated.
consensus_pubkey vector<u8> New Ed25519 public key to be used in the updated ValidatorConfig::ValidatorConfig.
validator_network_addresses vector<u8> New set of validator_network_addresses to be used in the updated ValidatorConfig::ValidatorConfig.
fullnode_network_addresses vector<u8> New set of fullnode_network_addresses to be used in the updated ValidatorConfig::ValidatorConfig.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED ValidatorConfig::EVALIDATOR_CONFIG validator_address does not have a ValidatorConfig::ValidatorConfig resource published under it.
Errors::REQUIRES_ROLE Roles::EVALIDATOR_OPERATOR validator_operator_account does not have a Validator Operator role.
Errors::INVALID_ARGUMENT ValidatorConfig::EINVALID_TRANSACTION_SENDER validator_operator_account is not the registered operator for the validator at validator_address.
Errors::INVALID_ARGUMENT ValidatorConfig::EINVALID_CONSENSUS_KEY consensus_pubkey is not a valid ed25519 public key.
Errors::INVALID_STATE DiemConfig::EINVALID_BLOCK_TIME An invalid time value was encountered in reconfiguration. Unlikely to occur.

Related Scripts
public fun set_validator_config_and_reconfigure(validator_operator_account: &signer, validator_account: address, consensus_pubkey: vector<u8>, validator_network_addresses: vector<u8>, fullnode_network_addresses: vector<u8>)
Implementation
fun set_validator_config_and_reconfigure(
    validator_operator_account: &signer,
    validator_account: address,
    consensus_pubkey: vector<u8>,
    validator_network_addresses: vector<u8>,
    fullnode_network_addresses: vector<u8>,
) {
    ValidatorConfig::set_config(
        validator_operator_account,
        validator_account,
        consensus_pubkey,
        validator_network_addresses,
        fullnode_network_addresses
    );
    DiemSystem::update_config_and_reconfigure(validator_operator_account, validator_account);
 }
Specification
include DiemAccount::TransactionChecks{sender: validator_operator_account};
include DiemSystem::UpdateConfigAndReconfigureEnsures{validator_addr: validator_account};
ensures ValidatorConfig::is_valid(validator_account);
ensures ValidatorConfig::spec_get_config(validator_account)
    == ValidatorConfig::Config {
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
};
include ValidatorConfig::SetConfigAbortsIf{validator_addr: validator_account};
include DiemSystem::UpdateConfigAndReconfigureAbortsIf{validator_addr: validator_account};

let is_validator_info_updated =
    (exists v_info in DiemSystem::spec_get_validators():
        v_info.addr == validator_account
        && v_info.config != ValidatorConfig::Config {
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
           });
include is_validator_info_updated ==> DiemConfig::ReconfigureAbortsIf;

This reports a possible INVALID_STATE abort, which comes from an assert in DiemConfig::reconfigure_ that config.last_reconfiguration_time is not in the future. This is a system error that a user for which there is no useful recovery except to resubmit the transaction.

Access Control: Only the Validator Operator account which has been registered with the validator can update the validator's configuration [H14].

aborts_if Signer::address_of(validator_operator_account) !=
            ValidatorConfig::get_operator(validator_account)
                with Errors::INVALID_ARGUMENT;

Script set_validator_operator

Summary

Sets the validator operator for a validator in the validator's configuration resource "locally" and does not reconfigure the system. Changes from this transaction will not picked up by the system until a reconfiguration of the system is triggered. May only be sent by an account with Validator role.

Technical Description

Sets the account at operator_account address and with the specified human_name as an operator for the sending validator account. The account at operator_account address must have a Validator Operator role and have a ValidatorOperatorConfig::ValidatorOperatorConfig resource published under it. The sending account must be a Validator and have a ValidatorConfig::ValidatorConfig resource published under it. This script does not emit a DiemConfig::NewEpochEvent and no reconfiguration of the system is initiated by this script.

Parameters
Name Type Description
account &signer The signer reference of the sending account of the transaction.
operator_name vector<u8> Validator operator's human name.
operator_account address Address of the validator operator account to be added as the account validator's operator.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG The ValidatorOperatorConfig::ValidatorOperatorConfig resource is not published under operator_account.
0 0 The human_name field of the ValidatorOperatorConfig::ValidatorOperatorConfig resource under operator_account does not match the provided human_name.
Errors::REQUIRES_ROLE Roles::EVALIDATOR account does not have a Validator account role.
Errors::INVALID_ARGUMENT ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR The account at operator_account does not have a ValidatorOperatorConfig::ValidatorOperatorConfig resource.
Errors::NOT_PUBLISHED ValidatorConfig::EVALIDATOR_CONFIG A ValidatorConfig::ValidatorConfig is not published under account.

Related Scripts
public fun set_validator_operator(account: &signer, operator_name: vector<u8>, operator_account: address)
Implementation
fun set_validator_operator(
    account: &signer,
    operator_name: vector<u8>,
    operator_account: address
) {
    assert(ValidatorOperatorConfig::get_human_name(operator_account) == operator_name, 0);
    ValidatorConfig::set_operator(account, operator_account);
}
Specification

let account_addr = Signer::address_of(account);
include DiemAccount::TransactionChecks{sender: account};
include ValidatorConfig::AbortsIfNoValidatorConfig{addr: account_addr};
aborts_if ValidatorOperatorConfig::get_human_name(operator_account) != operator_name with 0;
include ValidatorConfig::SetOperatorAbortsIf{validator_account: account, operator_addr: operator_account};
include ValidatorConfig::SetOperatorEnsures{validator_account: account, operator_addr: operator_account};

Reports INVALID_STATE because of !existsDiemSystem::CapabilityHolder, but that can't happen because CapabilityHolder is published during initialization (Genesis).

aborts_with [check]
    0, // Odd error code in assert on second statement in add_validator_and_reconfigure
    Errors::INVALID_ARGUMENT,
    Errors::NOT_PUBLISHED,
    Errors::REQUIRES_ROLE;

Access Control: Only a Validator account can set its Validator Operator [H15].

include Roles::AbortsIfNotValidator{validator_addr: account_addr};

Script set_validator_operator_with_nonce_admin

Summary

Sets the validator operator for a validator in the validator's configuration resource "locally" and does not reconfigure the system. Changes from this transaction will not picked up by the system until a reconfiguration of the system is triggered. May only be sent by the Diem Root account as a write set transaction.

Technical Description

Sets the account at operator_account address and with the specified human_name as an operator for the validator account. The account at operator_account address must have a Validator Operator role and have a ValidatorOperatorConfig::ValidatorOperatorConfig resource published under it. The account represented by the account signer must be a Validator and have a ValidatorConfig::ValidatorConfig resource published under it. No reconfiguration of the system is initiated by this script.

Parameters
Name Type Description
dr_account &signer The signer reference of the sending account of the write set transaction. May only be the Diem Root signer.
account &signer Signer reference of account specified in the execute_as field of the write set transaction.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction for Diem Root.
operator_name vector<u8> Validator operator's human name.
operator_account address Address of the validator operator account to be added as the account validator's operator.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under dr_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce in dr_account is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce in dr_account is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce in dr_account has been previously recorded.
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE The sending account is not the Diem Root account or Treasury Compliance account
Errors::NOT_PUBLISHED ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG The ValidatorOperatorConfig::ValidatorOperatorConfig resource is not published under operator_account.
0 0 The human_name field of the ValidatorOperatorConfig::ValidatorOperatorConfig resource under operator_account does not match the provided human_name.
Errors::REQUIRES_ROLE Roles::EVALIDATOR account does not have a Validator account role.
Errors::INVALID_ARGUMENT ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR The account at operator_account does not have a ValidatorOperatorConfig::ValidatorOperatorConfig resource.
Errors::NOT_PUBLISHED ValidatorConfig::EVALIDATOR_CONFIG A ValidatorConfig::ValidatorConfig is not published under account.

Related Scripts
public fun set_validator_operator_with_nonce_admin(dr_account: &signer, account: &signer, sliding_nonce: u64, operator_name: vector<u8>, operator_account: address)
Implementation
fun set_validator_operator_with_nonce_admin(
    dr_account: &signer,
    account: &signer,
    sliding_nonce: u64,
    operator_name: vector<u8>,
    operator_account: address
) {
    SlidingNonce::record_nonce_or_abort(dr_account, sliding_nonce);
    assert(ValidatorOperatorConfig::get_human_name(operator_account) == operator_name, 0);
    ValidatorConfig::set_operator(account, operator_account);
}
Specification

let account_addr = Signer::address_of(account);
include DiemAccount::TransactionChecks{sender: account};
include SlidingNonce::RecordNonceAbortsIf{seq_nonce: sliding_nonce, account: dr_account};
include ValidatorConfig::AbortsIfNoValidatorConfig{addr: account_addr};
aborts_if ValidatorOperatorConfig::get_human_name(operator_account) != operator_name with 0;
include ValidatorConfig::SetOperatorAbortsIf{validator_account: account, operator_addr: operator_account};
include ValidatorConfig::SetOperatorEnsures{validator_account: account, operator_addr: operator_account};
aborts_with [check]
    0, // Odd error code in assert on second statement in add_validator_and_reconfigure
    Errors::INVALID_ARGUMENT,
    Errors::NOT_PUBLISHED,
    Errors::REQUIRES_ROLE;

Access Control: Only the Diem Root account can process the admin scripts [H9].

requires Roles::has_diem_root_role(dr_account);

This is ensured by DiemAccount::writeset_prologue. Only a Validator account can set its Validator Operator [H15].

include Roles::AbortsIfNotValidator{validator_addr: account_addr};

Treasury and Compliance Operations

Script preburn

Summary

Moves a specified number of coins in a given currency from the account's balance to its preburn area after which the coins may be burned. This transaction may be sent by any account that holds a balance and preburn area in the specified currency.

Technical Description

Moves the specified amount of coins in Token currency from the sending account's DiemAccount::Balance<Token> to the Diem::Preburn<Token> published under the same account. account must have both of these resources published under it at the start of this transaction in order for it to execute successfully.

Events

Successful execution of this script emits two events:

Parameters
Name Type Description
Token Type The Move type for the Token currency being moved to the preburn area. Token must be an already-registered currency on-chain.
account &signer The signer reference of the sending account.
amount u64 The amount in Token to be moved to the preburn area.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO The Token is not a registered currency on-chain.
Errors::INVALID_STATE DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED The withdrawal capability for account has already been extracted.
Errors::LIMIT_EXCEEDED DiemAccount::EINSUFFICIENT_BALANCE amount is greater than payer's balance in Token.
Errors::NOT_PUBLISHED DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY account doesn't hold a balance in Token.
Errors::NOT_PUBLISHED Diem::EPREBURN account doesn't have a Diem::Preburn<Token> resource published under it.
Errors::INVALID_STATE Diem::EPREBURN_OCCUPIED The value field in the Diem::Preburn<Token> resource under the sender is non-zero.
Errors::NOT_PUBLISHED Roles::EROLE_ID The account did not have a role assigned to it.
Errors::REQUIRES_ROLE Roles::EDESIGNATED_DEALER The account did not have the role of DesignatedDealer.

Related Scripts
public fun preburn<Token>(account: &signer, amount: u64)
Implementation
fun preburn<Token>(account: &signer, amount: u64) {
    let withdraw_cap = DiemAccount::extract_withdraw_capability(account);
    DiemAccount::preburn<Token>(account, &withdraw_cap, amount);
    DiemAccount::restore_withdraw_capability(withdraw_cap);
}
Specification
include DiemAccount::TransactionChecks{sender: account};

let account_addr = Signer::spec_address_of(account);

let cap = DiemAccount::spec_get_withdraw_cap(account_addr);
include DiemAccount::ExtractWithdrawCapAbortsIf{sender_addr: account_addr};
include DiemAccount::PreburnAbortsIf<Token>{dd: account, cap: cap};
include DiemAccount::PreburnEnsures<Token>{dd_addr: account_addr, payer: account_addr};
aborts_with [check]
    Errors::NOT_PUBLISHED,
    Errors::INVALID_STATE,
    Errors::REQUIRES_ROLE,
    Errors::LIMIT_EXCEEDED;

Access Control: Only the account with a preburn area can preburn [H4].

include Diem::AbortsIfNoPreburn<Token>{preburn_address: account_addr};

Script burn

Summary

Burns all coins held in the preburn resource at the specified preburn address and removes them from the system. The sending account must be the Treasury Compliance account. The account that holds the preburn resource will normally be a Designated Dealer, but there are no enforced requirements that it be one.

Technical Description

This transaction permanently destroys all the coins of Token type stored in the Diem::Preburn<Token> resource published under the preburn_address account address.

This transaction will only succeed if the sending account has a Diem::BurnCapability<Token>, and a Diem::Preburn<Token> resource exists under preburn_address, with a non-zero to_burn field. After the successful execution of this transaction the total_value field in the Diem::CurrencyInfo<Token> resource published under 0xA550C18 will be decremented by the value of the to_burn field of the preburn resource under preburn_address immediately before this transaction, and the to_burn field of the preburn resource will have a zero value.

Events

The successful execution of this transaction will emit a Diem::BurnEvent on the event handle held in the Diem::CurrencyInfo<Token> resource's burn_events published under 0xA550C18.

Parameters
Name Type Description
Token Type The Move type for the Token currency being burned. Token must be an already-registered currency on-chain.
tc_account &signer The signer reference of the sending account of this transaction, must have a burn capability for Token published under it.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
preburn_address address The address where the coins to-be-burned are currently held.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_CAPABILITY Diem::EBURN_CAPABILITY The sending account does not have a Diem::BurnCapability<Token> published under it.
Errors::NOT_PUBLISHED Diem::EPREBURN The account at preburn_address does not have a Diem::Preburn<Token> resource published under it.
Errors::INVALID_STATE Diem::EPREBURN_EMPTY The Diem::Preburn<Token> resource is empty (has a value of 0).
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO The specified Token is not a registered currency on-chain.

Related Scripts
public fun burn<Token>(account: &signer, sliding_nonce: u64, preburn_address: address)
Implementation
fun burn<Token>(account: &signer, sliding_nonce: u64, preburn_address: address) {
    SlidingNonce::record_nonce_or_abort(account, sliding_nonce);
    Diem::burn<Token>(account, preburn_address)
}
Specification

Access Control: Only the account with the burn capability can burn coins [H3].

include Diem::AbortsIfNoBurnCapability<Token>{account: account};

Script cancel_burn

Summary

Cancels and returns all coins held in the preburn area under preburn_address and returns the funds to the preburn_address's balance. Can only be successfully sent by an account with Treasury Compliance role.

Technical Description

Cancels and returns all coins held in the Diem::Preburn<Token> resource under the preburn_address and return the funds to the preburn_address account's DiemAccount::Balance<Token>. The transaction must be sent by an account with a Diem::BurnCapability<Token> resource published under it. The account at preburn_address must have a Diem::Preburn<Token> resource published under it, and its value must be nonzero. The transaction removes the entire balance held in the Diem::Preburn<Token> resource, and returns it back to the account's DiemAccount::Balance<Token> under preburn_address. Due to this, the account at preburn_address must already have a balance in the Token currency published before this script is called otherwise the transaction will fail.

Events

The successful execution of this transaction will emit:

Parameters
Name Type Description
Token Type The Move type for the Token currenty that burning is being cancelled for. Token must be an already-registered currency on-chain.
account &signer The signer reference of the sending account of this transaction, must have a burn capability for Token published under it.
preburn_address address The address where the coins to-be-burned are currently held.

Common Abort Conditions
Error Category Error Reason Description
Errors::REQUIRES_CAPABILITY Diem::EBURN_CAPABILITY The sending account does not have a Diem::BurnCapability<Token> published under it.
Errors::NOT_PUBLISHED Diem::EPREBURN The account at preburn_address does not have a Diem::Preburn<Token> resource published under it.
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO The specified Token is not a registered currency on-chain.
Errors::INVALID_ARGUMENT DiemAccount::ECOIN_DEPOSIT_IS_ZERO The value held in the preburn resource was zero.
Errors::INVALID_ARGUMENT DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE The account at preburn_address doesn't have a balance resource for Token.
Errors::LIMIT_EXCEEDED DiemAccount::EDEPOSIT_EXCEEDS_LIMITS The depositing of the funds held in the prebun area would exceed the account's account limits.
Errors::INVALID_STATE DualAttestation::EPAYEE_COMPLIANCE_KEY_NOT_SET The account does not have a compliance key set on it but dual attestion checking was performed.

Related Scripts
public fun cancel_burn<Token>(account: &signer, preburn_address: address)
Implementation
fun cancel_burn<Token>(account: &signer, preburn_address: address) {
    DiemAccount::cancel_burn<Token>(account, preburn_address)
}
Specification
include DiemAccount::TransactionChecks{sender: account};
include DiemAccount::CancelBurnAbortsIf<Token>;

let preburn_value_at_addr = global<Diem::Preburn<Token>>(preburn_address).to_burn.value;

let total_preburn_value =
    global<Diem::CurrencyInfo<Token>>(CoreAddresses::CURRENCY_INFO_ADDRESS()).preburn_value;

let balance_at_addr = DiemAccount::balance<Token>(preburn_address);

The value stored at Diem::Preburn under preburn_address should become zero.

ensures preburn_value_at_addr == 0;

The total value of preburn for Token should decrease by the preburned amount.

ensures total_preburn_value == old(total_preburn_value) - old(preburn_value_at_addr);

The balance of Token at preburn_address should increase by the preburned amount.

ensures balance_at_addr == old(balance_at_addr) + old(preburn_value_at_addr);
aborts_with [check]
    Errors::REQUIRES_CAPABILITY,
    Errors::NOT_PUBLISHED,
    Errors::INVALID_ARGUMENT,
    Errors::LIMIT_EXCEEDED,
    Errors::INVALID_STATE;

Access Control: Only the account with the burn capability can cancel burning [H3].

include Diem::AbortsIfNoBurnCapability<Token>{account: account};

Script burn_txn_fees

Summary

Burns the transaction fees collected in the CoinType currency so that the Diem association may reclaim the backing coins off-chain. May only be sent by the Treasury Compliance account.

Technical Description

Burns the transaction fees collected in CoinType so that the association may reclaim the backing coins. Once this transaction has executed successfully all transaction fees that will have been collected in CoinType since the last time this script was called with that specific currency. Both balance and preburn fields in the TransactionFee::TransactionFee<CoinType> resource published under the 0xB1E55ED account address will have a value of 0 after the successful execution of this script.

Events

The successful execution of this transaction will emit a Diem::BurnEvent on the event handle held in the Diem::CurrencyInfo<CoinType> resource's burn_events published under 0xA550C18.

Parameters
Name Type Description
CoinType Type The Move type for the CoinType being added to the sending account of the transaction. CoinType must be an already-registered currency on-chain.
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.

Common Abort Conditions
Error Category Error Reason Description
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.
Errors::NOT_PUBLISHED TransactionFee::ETRANSACTION_FEE CoinType is not an accepted transaction fee currency.
Errors::INVALID_ARGUMENT Diem::ECOIN The collected fees in CoinType are zero.

Related Scripts
public fun burn_txn_fees<CoinType>(tc_account: &signer)
Implementation
fun burn_txn_fees<CoinType>(tc_account: &signer) {
    TransactionFee::burn_fees<CoinType>(tc_account);
}

Script tiered_mint

Summary

Mints a specified number of coins in a currency to a Designated Dealer. The sending account must be the Treasury Compliance account, and coins can only be minted to a Designated Dealer account.

Technical Description

Mints mint_amount of coins in the CoinType currency to Designated Dealer account at designated_dealer_address. The tier_index parameter specifies which tier should be used to check verify the off-chain approval policy, and is based in part on the on-chain tier values for the specific Designated Dealer, and the number of CoinType coins that have been minted to the dealer over the past 24 hours. Every Designated Dealer has 4 tiers for each currency that they support. The sending tc_account must be the Treasury Compliance account, and the receiver an authorized Designated Dealer account.

Events

Successful execution of the transaction will emit two events:

Parameters
Name Type Description
CoinType Type The Move type for the CoinType being minted. CoinType must be an already-registered currency on-chain.
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
designated_dealer_address address The address of the Designated Dealer account being minted to.
mint_amount u64 The number of coins to be minted.
tier_index u64 The mint tier index to use for the Designated Dealer account.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under tc_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE tc_account is not the Treasury Compliance account.
Errors::REQUIRES_ROLE Roles::ETREASURY_COMPLIANCE tc_account is not the Treasury Compliance account.
Errors::INVALID_ARGUMENT DesignatedDealer::EINVALID_MINT_AMOUNT mint_amount is zero.
Errors::NOT_PUBLISHED DesignatedDealer::EDEALER DesignatedDealer::Dealer or DesignatedDealer::TierInfo<CoinType> resource does not exist at designated_dealer_address.
Errors::INVALID_ARGUMENT DesignatedDealer::EINVALID_TIER_INDEX The tier_index is out of bounds.
Errors::INVALID_ARGUMENT DesignatedDealer::EINVALID_AMOUNT_FOR_TIER mint_amount exceeds the maximum allowed amount for tier_index.
Errors::REQUIRES_CAPABILITY Diem::EMINT_CAPABILITY tc_account does not have a Diem::MintCapability<CoinType> resource published under it.
Errors::INVALID_STATE Diem::EMINTING_NOT_ALLOWED Minting is not currently allowed for CoinType coins.
Errors::LIMIT_EXCEEDED DiemAccount::EDEPOSIT_EXCEEDS_LIMITS The depositing of the funds would exceed the account's account limits.

Related Scripts
public fun tiered_mint<CoinType>(tc_account: &signer, sliding_nonce: u64, designated_dealer_address: address, mint_amount: u64, tier_index: u64)
Implementation
fun tiered_mint<CoinType>(
    tc_account: &signer,
    sliding_nonce: u64,
    designated_dealer_address: address,
    mint_amount: u64,
    tier_index: u64
) {
    SlidingNonce::record_nonce_or_abort(tc_account, sliding_nonce);
    DiemAccount::tiered_mint<CoinType>(
        tc_account, designated_dealer_address, mint_amount, tier_index
    );
}
Specification

Access Control: Only the Treasury Compliance account can mint [H1].

include Roles::AbortsIfNotTreasuryCompliance{account: tc_account};

Script freeze_account

Summary

Freezes the account at address. The sending account of this transaction must be the Treasury Compliance account. The account being frozen cannot be the Diem Root or Treasury Compliance account. After the successful execution of this transaction no transactions may be sent from the frozen account, and the frozen account may not send or receive coins.

Technical Description

Sets the AccountFreezing::FreezingBit to true and emits a AccountFreezing::FreezeAccountEvent. The transaction sender must be the Treasury Compliance account, but the account at to_freeze_account must not be either 0xA550C18 (the Diem Root address), or 0xB1E55ED (the Treasury Compliance address). Note that this is a per-account property e.g., freezing a Parent VASP will not effect the status any of its child accounts and vice versa.

Events

Successful execution of this transaction will emit a AccountFreezing::FreezeAccountEvent on the freeze_event_handle held in the AccountFreezing::FreezeEventsHolder resource published under 0xA550C18 with the frozen_address being the to_freeze_account.

Parameters
Name Type Description
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
to_freeze_account address The account address to be frozen.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under tc_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.
Errors::REQUIRES_ROLE Roles::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.
Errors::INVALID_ARGUMENT AccountFreezing::ECANNOT_FREEZE_TC to_freeze_account was the Treasury Compliance account (0xB1E55ED).
Errors::INVALID_ARGUMENT AccountFreezing::ECANNOT_FREEZE_DIEM_ROOT to_freeze_account was the Diem Root account (0xA550C18).

Related Scripts
public fun freeze_account(tc_account: &signer, sliding_nonce: u64, to_freeze_account: address)
Implementation
fun freeze_account(tc_account: &signer, sliding_nonce: u64, to_freeze_account: address) {
    SlidingNonce::record_nonce_or_abort(tc_account, sliding_nonce);
    AccountFreezing::freeze_account(tc_account, to_freeze_account);
}

Script unfreeze_account

Summary

Unfreezes the account at address. The sending account of this transaction must be the Treasury Compliance account. After the successful execution of this transaction transactions may be sent from the previously frozen account, and coins may be sent and received.

Technical Description

Sets the AccountFreezing::FreezingBit to false and emits a AccountFreezing::UnFreezeAccountEvent. The transaction sender must be the Treasury Compliance account. Note that this is a per-account property so unfreezing a Parent VASP will not effect the status any of its child accounts and vice versa.

Events

Successful execution of this script will emit a AccountFreezing::UnFreezeAccountEvent with the unfrozen_address set the to_unfreeze_account's address.

Parameters
Name Type Description
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
to_unfreeze_account address The account address to be frozen.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE The sending account is not the Treasury Compliance account.

Related Scripts
public fun unfreeze_account(account: &signer, sliding_nonce: u64, to_unfreeze_account: address)
Implementation
fun unfreeze_account(account: &signer, sliding_nonce: u64, to_unfreeze_account: address) {
    SlidingNonce::record_nonce_or_abort(account, sliding_nonce);
    AccountFreezing::unfreeze_account(account, to_unfreeze_account);
}

Script update_dual_attestation_limit

Summary

Update the dual attestation limit on-chain. Defined in terms of micro-XDX. The transaction can only be sent by the Treasury Compliance account. After this transaction all inter-VASP payments over this limit must be checked for dual attestation.

Technical Description

Updates the micro_xdx_limit field of the DualAttestation::Limit resource published under 0xA550C18. The amount is set in micro-XDX.

Parameters
Name Type Description
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
new_micro_xdx_limit u64 The new dual attestation limit to be used on-chain.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under tc_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE tc_account is not the Treasury Compliance account.

Related Scripts
public fun update_dual_attestation_limit(tc_account: &signer, sliding_nonce: u64, new_micro_xdx_limit: u64)
Implementation
fun update_dual_attestation_limit(
    tc_account: &signer,
    sliding_nonce: u64,
    new_micro_xdx_limit: u64
) {
    SlidingNonce::record_nonce_or_abort(tc_account, sliding_nonce);
    DualAttestation::set_microdiem_limit(tc_account, new_micro_xdx_limit);
}

Script update_exchange_rate

Summary

Update the rough on-chain exchange rate between a specified currency and XDX (as a conversion to micro-XDX). The transaction can only be sent by the Treasury Compliance account. After this transaction the updated exchange rate will be used for normalization of gas prices, and for dual attestation checking.

Technical Description

Updates the on-chain exchange rate from the given Currency to micro-XDX. The exchange rate is given by new_exchange_rate_numerator/new_exchange_rate_denominator.

Parameters
Name Type Description
Currency Type The Move type for the Currency whose exchange rate is being updated. Currency must be an already-registered currency on-chain.
tc_account &signer The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for the transaction.
new_exchange_rate_numerator u64 The numerator for the new to micro-XDX exchange rate for Currency.
new_exchange_rate_denominator u64 The denominator for the new to micro-XDX exchange rate for Currency.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under tc_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE tc_account is not the Treasury Compliance account.
Errors::REQUIRES_ROLE Roles::ETREASURY_COMPLIANCE tc_account is not the Treasury Compliance account.
Errors::INVALID_ARGUMENT FixedPoint32::EDENOMINATOR new_exchange_rate_denominator is zero.
Errors::INVALID_ARGUMENT FixedPoint32::ERATIO_OUT_OF_RANGE The quotient is unrepresentable as a FixedPoint32.
Errors::LIMIT_EXCEEDED FixedPoint32::ERATIO_OUT_OF_RANGE The quotient is unrepresentable as a FixedPoint32.

Related Scripts
public fun update_exchange_rate<Currency>(tc_account: &signer, sliding_nonce: u64, new_exchange_rate_numerator: u64, new_exchange_rate_denominator: u64)
Implementation
fun update_exchange_rate<Currency>(
    tc_account: &signer,
    sliding_nonce: u64,
    new_exchange_rate_numerator: u64,
    new_exchange_rate_denominator: u64,
) {
    SlidingNonce::record_nonce_or_abort(tc_account, sliding_nonce);
    let rate = FixedPoint32::create_from_rational(
        new_exchange_rate_numerator,
        new_exchange_rate_denominator,
    );
    Diem::update_xdx_exchange_rate<Currency>(tc_account, rate);
}
Specification
include DiemAccount::TransactionChecks{sender: tc_account};
include SlidingNonce::RecordNonceAbortsIf{ account: tc_account, seq_nonce: sliding_nonce };
include FixedPoint32::CreateFromRationalAbortsIf{
    numerator: new_exchange_rate_numerator,
    denominator: new_exchange_rate_denominator
};

let rate = FixedPoint32::spec_create_from_rational(
    new_exchange_rate_numerator,
    new_exchange_rate_denominator
);
include Diem::UpdateXDXExchangeRateAbortsIf<Currency>;
aborts_with [check]
    Errors::INVALID_ARGUMENT,
    Errors::REQUIRES_ADDRESS,
    Errors::LIMIT_EXCEEDED,
    Errors::REQUIRES_ROLE,
    Errors::NOT_PUBLISHED;

Access Control: Only the Treasury Compliance account can update the exchange rate [H5].

include Roles::AbortsIfNotTreasuryCompliance{account: tc_account};

Script update_minting_ability

use 0x1::Diem;

Summary

Script to allow or disallow minting of new coins in a specified currency. This transaction can only be sent by the Treasury Compliance account. Turning minting off for a currency will have no effect on coins already in circulation, and coins may still be removed from the system.

Technical Description

This transaction sets the can_mint field of the Diem::CurrencyInfo<Currency> resource published under 0xA550C18 to the value of allow_minting. Minting of coins if allowed if this field is set to true and minting of new coins in Currency is disallowed otherwise. This transaction needs to be sent by the Treasury Compliance account.

Parameters
Name Type Description
Currency Type The Move type for the Currency whose minting ability is being updated. Currency must be an already-registered currency on-chain.
account &signer Signer reference of the sending account. Must be the Diem Root account.
allow_minting bool Whether to allow minting of new coins in Currency.

Common Abort Conditions
Error Category Error Reason Description
Errors::REQUIRES_ADDRESS CoreAddresses::ETREASURY_COMPLIANCE tc_account is not the Treasury Compliance account.
Errors::NOT_PUBLISHED Diem::ECURRENCY_INFO Currency is not a registered currency on-chain.

Related Scripts
public fun update_minting_ability<Currency>(tc_account: &signer, allow_minting: bool)
Implementation
fun update_minting_ability<Currency>(
    tc_account: &signer,
    allow_minting: bool
) {
    Diem::update_minting_ability<Currency>(tc_account, allow_minting);
}

System Administration

Script update_diem_version

Summary

Updates the Diem major version that is stored on-chain and is used by the VM. This transaction can only be sent from the Diem Root account.

Technical Description

Updates the DiemVersion on-chain config and emits a DiemConfig::NewEpochEvent to trigger a reconfiguration of the system. The major version that is passed in must be strictly greater than the current major version held on-chain. The VM reads this information and can use it to preserve backwards compatibility with previous major versions of the VM.

Parameters
Name Type Description
account &signer Signer reference of the sending account. Must be the Diem Root account.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.
major u64 The major version of the VM to be used from this transaction on.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::EDIEM_ROOT account is not the Diem Root account.
Errors::INVALID_ARGUMENT DiemVersion::EINVALID_MAJOR_VERSION_NUMBER major is less-than or equal to the current major version stored on-chain.
public fun update_diem_version(account: &signer, sliding_nonce: u64, major: u64)
Implementation
fun update_diem_version(account: &signer, sliding_nonce: u64, major: u64) {
    SlidingNonce::record_nonce_or_abort(account, sliding_nonce);
    DiemVersion::set(account, major)
}

Script add_to_script_allow_list

Summary

Adds a script hash to the transaction allowlist. This transaction can only be sent by the Diem Root account. Scripts with this hash can be sent afterward the successful execution of this script.

Technical Description

The sending account (dr_account) must be the Diem Root account. The script allow list must not already hold the script hash being added. The sliding_nonce must be a valid nonce for the Diem Root account. After this transaction has executed successfully a reconfiguration will be initiated, and the on-chain config DiemTransactionPublishingOption::DiemTransactionPublishingOption's script_allow_list field will contain the new script hash and transactions with this hash can be successfully sent to the network.

Parameters
Name Type Description
dr_account &signer The signer reference of the sending account of this transaction. Must be the Diem Root signer.
hash vector<u8> The hash of the script to be added to the script allowlist.
sliding_nonce u64 The sliding_nonce (see: SlidingNonce) to be used for this transaction.

Common Abort Conditions
Error Category Error Reason Description
Errors::NOT_PUBLISHED SlidingNonce::ESLIDING_NONCE A SlidingNonce resource is not published under dr_account.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_OLD The sliding_nonce is too old and it's impossible to determine if it's duplicated or not.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_TOO_NEW The sliding_nonce is too far in the future.
Errors::INVALID_ARGUMENT SlidingNonce::ENONCE_ALREADY_RECORDED The sliding_nonce has been previously recorded.
Errors::REQUIRES_ADDRESS CoreAddresses::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::REQUIRES_ROLE Roles::EDIEM_ROOT The sending account is not the Diem Root account.
Errors::INVALID_ARGUMENT DiemTransactionPublishingOption::EINVALID_SCRIPT_HASH The script hash is an invalid length.
Errors::INVALID_ARGUMENT DiemTransactionPublishingOption::EALLOWLIST_ALREADY_CONTAINS_SCRIPT The on-chain allowlist already contains the script hash.
public fun add_to_script_allow_list(dr_account: &signer, hash: vector<u8>, sliding_nonce: u64)
Implementation
fun add_to_script_allow_list(dr_account: &signer, hash: vector<u8>, sliding_nonce: u64,) {
    SlidingNonce::record_nonce_or_abort(dr_account, sliding_nonce);
    DiemTransactionPublishingOption::add_to_script_allow_list(dr_account, hash)
}

Index