MsgTransferTokens

Executes token transfers between addresses.

Proto Definition

message MsgTransferTokens {
  string creator = 1; // Address initiating the transfer
  string collectionId = 2; // Collection containing tokens to transfer
  repeated Transfer transfers = 3; // Transfer operations (must pass approvals)
}

message MsgTransferTokensResponse {}

message Transfer {
  // The address of the sender of the transfer.
  string from = 1;
  // The addresses of the recipients of the transfer.
  repeated string toAddresses = 2;
  // The balances to be transferred.
  repeated Balance balances = 3;
  // If defined, we will use the predeterminedBalances from the specified approval to calculate the balances at execution time.
  // We will override the balances field with the precalculated balances. Only applicable for approvals with predeterminedBalances set.
  ApprovalIdentifierDetails precalculateBalancesFromApproval = 4;
  // The Merkle proofs / solutions for all Merkle challenges required for the transfer.
  repeated MerkleProof merkleProofs = 5;
  // The ETH signature proofs / solutions for all ETH signature challenges required for the transfer.
  repeated ETHSignatureProof ethSignatureProofs = 6;
  // The memo for the transfer.
  string memo = 7;
  // The prioritized approvals for the transfer. By default, we scan linearly through the approvals and use the first match.
  // This field can be used to prioritize specific approvals and scan through them first.
  repeated ApprovalIdentifierDetails prioritizedApprovals = 8;
  // Whether to only check prioritized approvals for the transfer.
  // If true, we will only check the prioritized approvals and fail if none of them match (i.e. do not check any non-prioritized approvals).
  // If false, we will check the prioritized approvals first and then scan through the rest of the approvals.
  bool onlyCheckPrioritizedCollectionApprovals = 9;
  // Whether to only check prioritized approvals for the transfer.
  // If true, we will only check the prioritized approvals and fail if none of them match (i.e. do not check any non-prioritized approvals).
  // If false, we will check the prioritized approvals first and then scan through the rest of the approvals.
  bool onlyCheckPrioritizedIncomingApprovals = 10;
  // Whether to only check prioritized approvals for the transfer.
  // If true, we will only check the prioritized approvals and fail if none of them match (i.e. do not check any non-prioritized approvals).
  // If false, we will check the prioritized approvals first and then scan through the rest of the approvals.
  bool onlyCheckPrioritizedOutgoingApprovals = 11;
  // The options for precalculating the balances.
  PrecalculationOptions precalculationOptions = 12;
}

message PrecalculationOptions {
  // The timestamp to override with when calculating the balances.
  string overrideTimestamp = 1;
  // The IDs to override with when calculating the balances.
  repeated UintRange tokenIdsOverride = 2;
}

Auto-Scan vs Prioritized Approvals

The transfer approval system operates in two modes to balance efficiency and precision:

Auto-Scan Mode (Default)

By default, the system automatically scans through available approvals to find a match for the transfer. This mode:

  • Works with: Approvals using Empty Approval Criteria (no side effects)

  • Behavior: Automatically finds and uses the first matching approval

  • Use case: Simple transfers without custom logic or side effects

  • No versioning required: The system handles approval selection automatically

Prioritized Approvals (Required for Side Effects)

CRITICAL REQUIREMENT: Any transfer with side effects or custom approval criteria MUST always be prioritized with proper versioning set. No exceptions.

Race Condition Protection

The versioning control ensures that before submitting, the user knows the exact approval they are using:

Example: Coin Transfer Approval

Example: Auto-Scan Safe Transfer

Control Flags

  • onlyCheckPrioritizedCollectionApprovals: If true, only check prioritized approvals

  • onlyCheckPrioritizedIncomingApprovals: If true, only check prioritized incoming approvals

  • onlyCheckPrioritizedOutgoingApprovals: If true, only check prioritized outgoing approvals

Setting these to true is recommended when using prioritized approvals to ensure deterministic behavior.

Transfer Validation Process

Each transfer undergoes a systematic validation process to ensure security and proper authorization:

Validation Steps

Override Behavior

Collection approvals can override user-level approvals:

  • overridesFromOutgoingApprovals: true - Forcefully skips sender approval check

  • overridesToIncomingApprovals: true - Forcefully skips recipient approval checks

This allows collection managers to enable transfers that would otherwise be blocked by user settings.

Failure Points

Transfers fail at the first validation step that doesn't pass:

  1. Insufficient Balances - Sender doesn't own the tokens

  2. No Collection Approval - No valid collection-level approval found

  3. Blocked by Sender - Sender's outgoing approvals reject the transfer

  4. Blocked by Recipient - Recipient's incoming approvals reject the transfer

ETH Signature Proofs

ETH Signature Proofs are required when transfers use ETH Signature Challenges. Each proof contains:

  • nonce: The unique identifier that was signed

  • signature: The Ethereum signature of the message nonce + "-" + creatorAddress

Important: Each signature can only be used once per challenge tracker. The system tracks used signatures to prevent replay attacks.

Collection ID Auto-Lookup

If you specify collectionId as "0", it will automatically lookup the latest collection ID created. This can be used if you are creating a collection and do not know the official collection ID yet but want to perform a multi-message transaction.

Usage Example

JSON Example

Last updated