A Transaction Manifest is a human-readable description of intended actions to be executed on the Radix network.
- Overview
- Key Features
- Structure
- Core Concepts
- Value Representation
- Subintents and Pre-authorizations
- Notarization
- Transaction Types
- Standard Transaction Types
- Advanced Transaction Types
- Subintents and Multi-Party Transactions
- Technical Implementation
- Instruction System
- Basic Structure
- Instruction Categories
- Processing Pipeline
- Manifest Compilation
- Transaction Structure
- Intent Processing
- Value Representation
- SBOR Implementation
- Type Conversion
- Execution Model
- Atomic Processing
- Resource Tracking
- Multi-Intent Coordination
- Advantages Over Traditional Models
- Asset-Oriented vs Message-Based Transactions
- Enhanced Security Model
- Native Composability
- Improved User Experience
- Technical Advantages
- System Architecture Benefits
- Examples
- Basic Token Operations
- DeFi Operations
- Multi-Party Transactions
Overview
Unlike traditional blockchain transaction models that rely on opaque smart contract calls, Transaction Manifests are inherently asset-oriented transactions that provide a listing of commands to the Radix network specifically focused on the movement of assets between accounts and decentralized application (dApp) components.
The manifest system represents a fundamental shift in how blockchain transactions are constructed and validated. Traditional blockchain platforms like Ethereum typically use transactions that simply pass a message to a single smart contract, which then coordinates whatever should happen internally. These messages are usually hashed, making them unreadable to users, and even if they weren't hashed, they would tell users nothing about the actual outcome of the transaction.
In contrast, Radix Transaction Manifests describe movements of assets in a way that mirrors real-world interactions. They make it possible to compose multiple actions to be executed atomically by describing a sequence of component calls and movements of resources between components. For example, a simple token transfer manifest would explicitly describe withdrawing tokens from one account and depositing them into another, rather than just calling a generic "transfer" function.
A key innovation of the manifest system is its ability to provide clear guarantees about transaction outcomes. The manifest can include assertions about minimum amounts of assets received or specific outcomes that must be met, otherwise the transaction will fail. This helps protect users from unexpected results and various forms of transaction manipulation.
The manifest system also enables true atomic composability without requiring special smart contract code. Because the manifest can describe asset movements between multiple components, different dApp functionalities can be seamlessly combined in a single transaction. For instance, a user could compose a transaction that swaps tokens on one decentralized exchange and immediately uses those tokens in another dApp, all guaranteed to either completely succeed or completely fail.
With the introduction of subintents (also known as pre-authorizations) in the Cuttlefish network upgrade, the manifest system gained additional capabilities for coordinating multi-party transactions. This allows for advanced use cases like delegated fee payments, where a dApp can pay transaction fees on behalf of users, and intent-based partial trades, where users can safely express one side of a potential trade that can be matched later.
The Transaction Manifest system represents a core innovation in blockchain architecture, providing a more transparent, composable, and user-focused approach to transaction construction and validation. By making transactions human-readable and focusing on explicit asset movements, it helps users understand exactly what they're authorizing while enabling powerful new patterns of interaction between dApps and users.
Key Features
- Asset-Oriented Design: Transaction Manifests are built around the explicit movement of assets, reflecting real-world interactions rather than abstract smart contract state changes. This design choice makes transactions more intuitive and easier to understand. For example, a token swap transaction clearly shows assets being withdrawn from a user's account, passed to a decentralized exchange component, and the received tokens being deposited back to the user's account.
- Human-Readable Format: Unlike traditional blockchain transactions that often present as opaque hexadecimal strings or hashes, Transaction Manifests use a human-readable format that describes each step of the transaction. This transparency allows users and developers to understand exactly what a transaction will do before it's executed. The manifest syntax includes clear commands for actions like withdrawing assets, calling component methods, and making assertions about transaction outcomes.
- Transaction Guarantees: The manifest system allows users to specify explicit guarantees about transaction outcomes. Through assertion commands, users can ensure minimum amounts of assets received or specific transaction conditions that must be met. If these conditions aren't satisfied, the transaction automatically fails and rolls back, protecting users from unexpected results.
- Native Atomic Composability: One of the most powerful features of Transaction Manifests is their inherent support for atomic composability. Multiple component interactions can be seamlessly combined within a single transaction, with all operations either succeeding together or failing together. This eliminates the need for complex smart contract integrations when combining different dApp functionalities.
- Authorization Model: Transaction Manifests implement a sophisticated authorization system through the concept of proofs and the authorization zone. Rather than using simple account signatures, the system allows for flexible authorization rules that can require various combinations of resource ownership, badges, or other credentials. This enables complex access control while maintaining transaction transparency.
- Delegated Fee Payments: The manifest system introduces innovative approaches to transaction fees. Through the pre-authorization system, dApps can pay transaction fees on behalf of users, removing the need for users to hold network tokens just to interact with applications. This solves the common "double onboarding" problem where users need both application tokens and network tokens to use a dApp.
- Resource Safety: Transaction Manifests enforce strict rules about resource handling. All resources withdrawn during a transaction must be explicitly accounted for - either deposited somewhere or burned - by the end of the transaction. This prevents resources from being accidentally lost or stranded during complex operations.
- Multi-Party Transaction Support: Through the subintent system, Transaction Manifests enable sophisticated multi-party transactions. Different users can independently authorize their portions of a larger atomic transaction, which can then be combined and executed as a single unit. This enables new use cases like coordinated purchases, atomic swaps, and other operations requiring multiple parties.
- Transaction Preview: The manifest system supports accurate transaction previews. Because manifests explicitly describe all resource movements, wallets and other client software can show users exactly what will happen in a transaction before they sign it. This includes showing what assets will be spent, what will be received, and what components will be interacted with.
Structure
- Basic Components: The structure of a Radix Transaction Manifest is built around a sequence of instructions that define the transaction's behavior. Each manifest consists of commands for the type of operation, followed by zero or more arguments in manifest value syntax, and ending with a semicolon. These instructions are processed in order by the Radix Engine, with the entire transaction rolling back if any instruction fails.
- Transaction Intent: At the core of every transaction is a transaction intent, which contains:
- A transaction header defining the notary and tip.
- An intent header capturing validity constraints.
- An optional message.
- The transaction manifest itself.
- Zero or more subintents.
- Manifest Instructions: Instructions in the manifest fall into several main categories:
- Resource management (withdrawing, depositing, and moving assets).
- Method calls to components.
- Authorization instructions.
- Assertions and guarantees about transaction outcomes.
Core Concepts
- Transaction Worktop: The transaction worktop serves as a temporary storage area for resources during transaction execution. Resources returned from component calls are automatically placed on the worktop, where they can be organized into buckets for use in subsequent instructions. The worktop must be empty by the end of the transaction, ensuring all resources are properly accounted for.
- Authorization Zone: The authorization zone is a specialized space that holds proofs required for transaction authorization. These proofs can come from two sources:
- Signatures on the transaction, which are automatically converted to "virtual signature proofs".
- Proofs returned by method calls during transaction execution.
- Buckets: Buckets act as containers for resources being moved within a transaction. They can be created from resources on the worktop and then passed as arguments to component method calls. Buckets provide a way to precisely control and track resource movements throughout the transaction.
- Proofs: The proof system is central to transaction authorization. Proofs demonstrate ownership or permission to interact with components and resources. They can be:
- Created from resources in buckets.
- Generated from signatures.
- Obtained from component method calls.
Value Representation
Transaction Manifests use a specific syntax for representing values, which includes:
- Basic leaf values (integers, strings, booleans).
- Composite values (tuples, enums, arrays, maps).
- Special manifest-specific values (addresses, buckets, proofs).
Subintents and Pre-authorizations
The manifest system supports subintents (also called pre-authorizations), which allow portions of larger transactions to be independently authorized. Each subintent contains its own manifest and can interact with its parent transaction through a yielding mechanism. This enables complex multi-party transactions while maintaining atomic execution guarantees.
Notarization
Every transaction requires notarization, which serves to:
- Verify the correctness of transaction signatures.
- Prevent tampering with signed transaction content.
- Enable multi-signature coordination.
- Support transaction submission control.
The notary is typically the party orchestrating the transaction construction and submission process, such as a wallet application or a transaction aggregator service.
Transaction Types
Standard Transaction Types
- General Transactions: The most common type of transaction on the Radix network is the general transaction, which can include withdrawals from accounts, calls to non-account components, deposits to accounts, and proof productions. This flexible transaction type supports the majority of typical DeFi interactions while maintaining clear summaries of what matters to users: what they lose, what they gain, and what they're interacting with.
- Simple Transfers: Simple transfers represent a specialized subset of transactions designed specifically for straightforward asset movements between accounts. These transactions are structured to be easily understood by hardware wallets and typically involve a single withdrawal from one account and a single deposit to another account. This type is particularly important for basic token transfers and integration with hardware security modules.
- Pool Operations: The manifest system includes specialized transaction types for interacting with liquidity pools. These include dedicated patterns for contributing to pools and redeeming from pools, ensuring these common DeFi operations can be clearly presented to users with appropriate guarantees about outcomes.
- Validator Operations: Specific transaction types exist for validator-related operations, including:
- Staking XRD to validators and receiving liquid stake unit tokens.
- Unstaking from validators and receiving claim NFTs.
- Claiming unstaked XRD using claim NFTs.
Advanced Transaction Types
- Resource Creation: Transaction Manifests support the creation of both fungible and non-fungible resources through dedicated manifest instructions. These transactions handle the specification of resource properties, initial supply, and metadata, enabling the creation of new tokens and NFTs directly through transactions.
- Package Deployment: Transactions can deploy new packages (smart contract code) to the network. These transactions include special instructions for publishing code and setting up package configuration, including owner roles and metadata.
- Account Configuration: Special transaction types exist for updating account settings, such as modifying deposit rules, resource preferences, and authorized depositor lists. These transactions allow users to control how their accounts interact with the broader network.
Subintents and Multi-Party Transactions
- Pre-authorization Flows: The manifest system supports sophisticated multi-party transactions through its pre-authorization system. Users can authorize portions of larger atomic transactions independently, which can then be combined into complete transactions. This enables several advanced use cases:
- Delegated Fee Payment: One of the most important applications of subintents is delegated fee payment, where dApps can pay transaction fees on behalf of users. This solves the "double onboarding" problem by removing the requirement for users to hold network tokens just to interact with applications.
- Atomic Trading: The subintent system enables intent-based partial trades, where users can express one side of a desired trade through a subintent. These subintents can then be matched and combined by aggregator services to create atomic trades between parties.
- Coordinated Actions: Multiple users can coordinate complex transactions where all participants need to agree and participate for the transaction to succeed. This enables use cases like coordinated ticket purchases where either all participants succeed in their purchase or none do.
Technical Implementation
Instruction System
Basic Structure
Transaction Manifests adopt a bash-like grammar where each instruction contains a command type, zero or more arguments in manifest value syntax, and ends with a semicolon. This structure allows for clear expression of transaction intent while maintaining machine processability.
Instruction Categories
The manifest system includes several major categories of instructions:
- Resource Management: These instructions handle the movement and manipulation of resources, including operations like:
- Taking resources from the worktop.
- Creating and managing buckets.
- Burning resources.
- Making assertions about resource quantities.
- Component Interaction: Instructions for interacting with components include method calls, function calls, and specialized instructions for common operations like creating accounts, minting tokens, and managing metadata.
- Authorization Control: The authorization system uses instructions for managing proofs, including:
- Creating proofs from buckets or the authorization zone.
- Cloning and dropping proofs.
- Managing the authorization zone.
Processing Pipeline
Manifest Compilation
When a transaction is created, the manifest is first processed into a standardized format. This involves:
- Validating instruction syntax.
- Converting named references to indexed references.
- Organizing instructions into a structured format.
Transaction Structure
The processed transaction includes several layers:
- The notarized transaction (outer layer).
- The signed transaction intent.
- The transaction intent.
- Individual subintents.
Each layer includes appropriate signatures and validation information.
Intent Processing
The execution of a transaction follows the intent structure, with:
- A single transaction intent at the root.
- Zero or more subintents arranged in a tree structure.
- Controlled interaction between intents through yielding mechanisms.
Value Representation
SBOR Implementation
The manifest system uses a specific implementation of SBOR (Scrypto Binary Object Representation) for encoding values. This includes:
- Basic value types (numbers, strings, booleans).
- Composite types (tuples, enums, arrays, maps).
- Special manifest-specific types (addresses, buckets, proofs).
Type Conversion
When processing transactions, manifest values are converted between different SBOR implementations:
- Manifest SBOR (used in the transaction manifest).
- Scrypto SBOR (used by the Radix Engine).
Execution Model
Atomic Processing
All instructions in a manifest must complete successfully for the transaction to succeed. If any instruction fails:
- The entire transaction is rolled back.
- No state changes are committed.
- Any locked fees are consumed.
Resource Tracking
The execution system maintains strict tracking of resources through:
- The transaction worktop.
- Named buckets.
- The authorization zone.
All resources must be accounted for by the end of transaction execution.
Multi-Intent Coordination
For transactions involving multiple intents, the system coordinates:
- Parent-child relationships between intents.
- Resource passing through yields.
- Authorization verification between intents.
- Atomic execution across all intents.
Advantages Over Traditional Models
Asset-Oriented vs Message-Based Transactions
Traditional blockchain platforms like Ethereum use a message-based transaction model where transactions are simply messages passed to smart contracts. This approach requires users to trust that smart contracts will handle their assets correctly without any clear visibility into what will happen. In contrast, Radix Transaction Manifests explicitly describe the movement of assets between accounts and components, making transaction outcomes transparent and predictable.
Enhanced Security Model
- Prevention of Blind Signing: On traditional platforms, users often must "blind sign" transactions, seeing only an opaque transaction hash or limited parameter information. This has led to numerous hacks and exploits where users unknowingly authorize malicious transactions. Transaction Manifests solve this by providing clear, human-readable descriptions of all asset movements and component interactions.
- Resource Safety: The manifest system enforces strict resource tracking throughout transaction execution. Unlike traditional models where assets might be lost due to smart contract bugs, Transaction Manifests require explicit accounting for all resources, ensuring they are either properly deposited or intentionally burned by the end of the transaction.
Native Composability
- Direct Component Integration: Traditional platforms require special smart contract code to enable interaction between different applications. Transaction Manifests enable native atomic composability, allowing assets returned from one component to be directly passed to another without additional coordination code.
- Multi-Party Transactions: The subintent system provides native support for complex multi-party transactions without requiring special smart contract logic. This enables use cases like atomic swaps and coordinated purchases that would require complex trustless escrow contracts on traditional platforms.
Improved User Experience
- Transaction Preview: Because manifests explicitly describe all asset movements, users can see exactly what will happen in a transaction before signing. This is in contrast to traditional platforms where transaction outcomes might be unclear until after execution.
- Fee Delegation: The manifest system enables innovative approaches to transaction fees. Through pre-authorizations, dApps can pay transaction fees on behalf of users, solving the "double onboarding" problem where users need both application tokens and network tokens to use a dApp.
Technical Advantages
- Flexible Authorization: Unlike traditional models that rely primarily on simple account signatures, Transaction Manifests support sophisticated authorization rules through the proof system. This enables complex access control while maintaining transaction transparency.
- Transaction Guarantees: The manifest system allows users to specify explicit guarantees about transaction outcomes through assertion commands. If these conditions aren't met, the transaction automatically fails and rolls back. This provides protection against unexpected outcomes that might occur in traditional smart contract interactions.
System Architecture Benefits
- State Sharding Support: The manifest system was designed with state sharding in mind, enabling the network to process transactions in parallel while maintaining atomic execution guarantees. The explicit description of asset movements and component interactions allows the network to understand transaction dependencies without requiring global state access.
- Platform Evolution: Due to the fundamental nature of traditional smart contract platforms' transaction models, they cannot easily adopt manifest-like features without breaking existing applications. The Radix manifest system provides a foundation that can evolve while maintaining backward compatibility.
Examples
Basic Token Operations
- Simple Token Transfer: The most basic application is transferring tokens between accounts. Here's an example of transferring 10 XRD:
# Lock fees to pay for the transaction
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2") "lock_fee" Decimal("10");
# Withdraw 10 XRD from account
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2") "withdraw"
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("10");
# Take XRD from worktop and create a bucket
TAKE_FROM_WORKTOP
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("10")
Bucket("xrd_bucket");
# Deposit to recipient account
CALL_METHOD Address("account_sim1cyvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cve475365")
"deposit"
Bucket("xrd_bucket");
- NFT Creation: Creating a new NFT collection requires more complex configuration:
CREATE_NON_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY
# Owner role configuration
Enum<OwnerRole::None>()
# NFT ID type
Enum<NonFungibleIdType::Integer>()
# Track supply
true
# NFT data schema
Enum<0u8>(
Enum<0u8>(
Tuple(
Array<Enum>(),
Array<Tuple>(),
Array<Enum>()
)
),
Enum<0u8>(66u8),
Array<String>()
)
# Initial NFTs to mint
Map<NonFungibleLocalId, Tuple>(
NonFungibleLocalId("#1#") => Tuple(
Tuple(
"Name",
"Description",
"<https://example.com/image.png>"
)
)
)
# Access rules
Tuple(
Some(
Tuple(
Some(Enum<AccessRule::AllowAll>()),
Some(Enum<AccessRule::DenyAll>())
)
),
None,
None,
None,
None,
None,
None
)
# Metadata
Tuple(
Map<String, Tuple>(
"name" => Tuple(
Some(Enum<Metadata::String>("MyNFT")),
true
)
),
Map<String, Enum>()
)
None;
DeFi Operations
- DEX Token Swap: A typical DEX swap transaction combining multiple operations:
# Lock fees
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2")
"lock_fee"
Decimal("10");
# Withdraw tokens to swap
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2")
"withdraw"
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("100");
# Prepare tokens for swap
TAKE_FROM_WORKTOP
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("100")
Bucket("input_tokens");
# Execute swap with minimum output guarantee
CALL_METHOD Address("component_sim1q0d9pmtn6xsrsqkdxlzyjrdnc9n94n9fma3jtrrehymst2rv4k")
"swap"
Bucket("input_tokens");
# Assert minimum received amount
ASSERT_WORKTOP_CONTAINS
Address("resource_sim1n2q4le7dpzucmpnksxj5ku28r3t776pgk879cahgm76c2kfpz48fpj")
Decimal("95");
# Deposit everything received back to account
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2")
"deposit_batch"
Expression("ENTIRE_WORKTOP");
Multi-Party Transactions
- Pre-authorized Swap: An example of a pre-authorized trading subintent:
- Delegated Fee Payment: Example of a dApp paying fees for a user transaction:
# Verify this can only be used by specific aggregator
VERIFY_PARENT Enum<AccessRule::Protected>(
Enum<AccessRuleNode::ProofRule>(
Enum<ProofRule::Require>(
Enum<ResourceOrNonFungible::NonFungible>(
NonFungibleGlobalId("resource_sim1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxx8x44q5:...")
)
)
)
);
# Ensure clean starting state
ASSERT_WORKTOP_IS_EMPTY;
# Withdraw tokens to trade
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2")
"withdraw"
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("100");
# Prepare tokens and yield to parent
TAKE_FROM_WORKTOP
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("100")
Bucket("trade_tokens");
YIELD_TO_PARENT Bucket("trade_tokens");
# Expect specific token type and amount back
ASSERT_WORKTOP_CONTAINS
Address("resource_sim1n2q4le7dpzucmpnksxj5ku28r3t776pgk879cahgm76c2kfpz48fpj")
Decimal("95");
# Deposit received tokens
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2")
"deposit_batch"
Expression("ENTIRE_WORKTOP");
# Ensure clean starting state
ASSERT_WORKTOP_IS_EMPTY;
# User withdraws and deposits tokens
CALL_METHOD Address("account_sim1qsw6l5leaj62zd38x8f6qhlue76f9lz0n2s49s3mzu8qczjhm2")
"withdraw"
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("1");
TAKE_FROM_WORKTOP
Address("resource_sim1qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs6d89k")
Decimal("1")
Bucket("xrd");
# Small amount sent back to dApp for fees
CALL_METHOD Address("component_sim1cpvs7ulg02ah8mhcc84q7zsj4ta3pfz77uknu29xy50yelakkujqze")
"deposit"
Bucket("xrd");
# Return control to parent intent which handles fees
YIELD_TO_PARENT;