Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions docs/builder/smart-contracts/index.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
---
title: "Miden Smart Contracts"
description: "Reference documentation for building Miden smart contracts in Rust using the Miden SDK."
description: "Build Miden smart contracts with Rust, Miden Assembly, and reusable Miden Standards."
pagination_prev: null
---

# Miden Smart Contracts

This section is the complete reference for building smart contracts on Miden using Rust and the Miden SDK. If you're new to Miden, follow the hands-on [Miden Bank Tutorial](../tutorials/miden-bank/).
This section covers the developer-facing paths for building smart contracts on Miden. Start with the overview for the execution model, use Rust for account, note, and transaction development, and use Miden Standards when you want reusable account components, note scripts, faucet policies, and protocol-compatible building blocks.

All Miden Rust contracts compile under these constraints: `#![no_std]`, Rust 2024 edition.
If you're new to Miden, follow the hands-on [Miden Bank Tutorial](../tutorials/miden-bank/).

## Core concepts
## Sections

<CardGrid cols={3}>
<Card title="Overview" href="./overview" eyebrow="Model">
Learn how accounts, notes, transactions, and components fit together.
</Card>
<Card title="Rust" href="./rust" eyebrow="Authoring path">
Build accounts, notes, transactions, and reusable logic with the Rust-first workflow.
</Card>
<Card title="Miden Standards" href="./standards/" eyebrow="Reusable libraries">
Use standard components, note scripts, faucet policies, and MASM modules.
</Card>
</CardGrid>

## Inside Rust

<CardGrid cols={3}>
<Card title="Accounts" href="./accounts/" eyebrow="State & code">
Expand All @@ -25,17 +39,17 @@ All Miden Rust contracts compile under these constraints: `#![no_std]`, Rust 202
<Card title="Cross-component calls" href="./cross-component-calls" eyebrow="Composition">
Calling methods across account components and from note scripts.
</Card>
</CardGrid>

## Reference

<CardGrid cols={3}>
<Card title="Types" href="./types" eyebrow="Primitives">
Core types: Felt, Word, AccountId, NoteId, and more.
</Card>
<Card title="Patterns" href="./patterns" eyebrow="Recipes">
Access control, rate limiting, spending limits, and anti-patterns.
</Card>
</CardGrid>

## Reference

<CardGrid cols={3}>
<Card title="API reference" href="https://docs.rs/miden/latest/miden/" eyebrow="docs.rs">
Complete API documentation for the miden crate.
</Card>
Expand Down
96 changes: 96 additions & 0 deletions docs/builder/smart-contracts/standards/account-components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: "Account Components"
description: "Use standard account components for wallets, authentication, access control, faucets, and metadata."
---

# Account Components

Standard account components are prebuilt modules you can compose into accounts. They give an account a recognizable interface, such as "can receive assets", "can authenticate with this signature scheme", "can mint fungible tokens", or "uses this access-control model".

Use these components from Rust when you build accounts with the SDK, or import the underlying MASM modules when you are writing lower-level account code. The same standards surface is what note scripts and transaction scripts rely on when they call account procedures.

## Common components
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to list everything here or just "common" ones?

In any case, TokenPolicyManager would also be useful to mention, and probably the BasicBlocklist and BasicAllowlist. These are not in 0.14.x (as the PR description suggests), iirc, but neither is Authority which is already listed.


| Component | Use it for | Rust module |
|-----------|------------|-------------|
| `BasicWallet` | Holding assets, receiving assets from standard notes, and moving assets into output notes. | `miden_standards::account::wallets` |
| `FungibleFaucet` | Minting, sending, receiving, and burning fungible assets from faucet accounts. | `miden_standards::account::faucets` |
| `AuthSingleSig` | Authenticating transactions with one supported signature scheme. | `miden_standards::account::auth` |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `AuthSingleSig` | Authenticating transactions with one supported signature scheme. | `miden_standards::account::auth` |
| `AuthSingleSig` | Single-signature authentication of transactions. | `miden_standards::account::auth` |

This component supports various signature schemes.

| `AuthSingleSigAcl` | Single-signature authentication with an access-control list. | `miden_standards::account::auth` |
| `AuthMultisig` / `AuthMultisigSmart` | Threshold or policy-aware multisig authentication. | `miden_standards::account::auth` |
| `AuthGuardedMultisig` | Multisig guarded by a guardian configuration. | `miden_standards::account::auth` |
| `AuthNetworkAccount` | Authentication for network-account flows. | `miden_standards::account::auth` |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `AuthNetworkAccount` | Authentication for network-account flows. | `miden_standards::account::auth` |
| `AuthNetworkAccount` | Authentication through note allowlists for network accounts. | `miden_standards::account::auth` |

| `Ownable2Step` | Ownership transfer with an explicit accept step. | `miden_standards::account::access` |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `Ownable2Step` | Ownership transfer with an explicit accept step. | `miden_standards::account::access` |
| `Ownable2Step` | Access control for account owners. | `miden_standards::account::access` |

Not sure what framing is best, but I think the primary purpose of the component is more about defining what account owner means, and the transfer of ownership is secondary.

| `RoleBasedAccessControl` | Role-based authorization for standard policy management. | `miden_standards::account::access` |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `RoleBasedAccessControl` | Role-based authorization for standard policy management. | `miden_standards::account::access` |
| `RoleBasedAccessControl` | Role-based authorization for token policy management. | `miden_standards::account::access` |

Fits better with TokenPolicyManager.

| `Authority` | Shared authority component used by policy-management standards. | `miden_standards::account::access` |

These are building blocks. They do not prevent you from adding custom components to the same account.

:::info v0.14 differences
The v0.14 snapshot uses separate `BasicFungibleFaucet` and `NetworkFungibleFaucet` components and does not include RBAC, authority, guarded multisig, smart multisig, or network-account auth in the same form. Use the v0.14 versioned docs when building against the v0.14 crates.
:::

## Start with wallet and auth

Most regular accounts need:

- an authentication component, such as `AuthSingleSig` or `AuthMultisig`
- a wallet component, usually `BasicWallet`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- a wallet component, usually `BasicWallet`
- the `BasicWallet` component

For now we don't have any other wallet components and I don't think we plan on having one.


`AuthSingleSig` controls transaction authorization. `BasicWallet` exposes the standard wallet procedures used by common notes, including the ability to receive assets and move assets into output notes.

```rust title="Compose a regular account with standard auth and wallet components"
use miden_protocol::Word;
use miden_protocol::account::auth::{AuthScheme, PublicKeyCommitment};
use miden_protocol::account::{AccountBuilder, AccountStorageMode, AccountType};
use miden_standards::account::auth::AuthSingleSig;
use miden_standards::account::wallets::BasicWallet;

fn build_wallet_account() -> Result<(), Box<dyn std::error::Error>> {
let public_key = PublicKeyCommitment::from(Word::from([1, 2, 3, 4u32]));

let account = AccountBuilder::new([1; 32])
.account_type(AccountType::RegularAccountImmutableCode)
.storage_mode(AccountStorageMode::Public)
.with_auth_component(AuthSingleSig::new(public_key, AuthScheme::Falcon512Poseidon2))
.with_component(BasicWallet)
.build()?;

assert_eq!(account.account_type(), AccountType::RegularAccountImmutableCode);
Ok(())
}
```

For authentication details, see [Authentication](../accounts/authentication). For how component methods are authored in Rust, see [Components](../accounts/components).

## Check note compatibility

Standard notes assume the consuming account exposes the procedures they need. For example, P2ID and P2IDE notes need a wallet-compatible account that can receive assets. SWAP notes additionally need the wallet procedure that moves the requested asset into the payback note.

At the builder level, the practical rule is:

- Add `BasicWallet` to accounts that should receive standard asset-transfer notes.
- Add `FungibleFaucet` to faucet accounts that should mint or burn fungible assets.
- Add auth components to every account that must reject unauthorized transactions.
Comment on lines +70 to +74
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would differentiate the last point into two:

  • for local/user accounts: add an auth component
  • for network accounts: add an access control component


If you write a custom wallet component instead of using `BasicWallet`, match the expected interface deliberately and test consumption of the relevant standard notes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of suggesting that builders match the interface, I'd change the framing to: "build on top of BasicWallet", i.e. adding BasicWallet and a custom extension component.


## Rust and MASM entry points

Rust APIs are the usual entry point for account composition. MASM modules are available when you need exact low-level behavior.

| Area | Rust module | MASM module family |
|------|-------------|--------------------|
| Wallets | `miden_standards::account::wallets` | `miden::standards::wallets::*` |
| Authentication | `miden_standards::account::auth` | `miden::standards::auth::*` |
| Access control | `miden_standards::account::access` | `miden::standards::access::*` |
| Faucets | `miden_standards::account::faucets` | `miden::standards::faucets::*` |
| Metadata | `miden_standards::account::metadata` | `miden::standards::metadata::*` |

Reach for MASM directly when you are implementing low-level behavior, integrating a custom component with a standard procedure, or verifying exact stack effects.

## Related pages

- [Standard notes](./standard-notes) - which account interfaces each standard note expects
- [Faucets and policies](./faucets-and-policies) - using faucet and mint policy components
- [`miden-standards` account source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards/src/account) - current implementation
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this link to the corresponding release, for which these docs are built? This would at least prevent confusion, and in the worst case prevent looking at the wrong source and building something that's broken because of it.

I think this might be a more general doc problem, namely that we're linking to next in many cases, but as mentioned above, this seems very problematic. Would be useful to somehow inject the $CURRENT_VERSION of the docs into such links or otherwise check in CI that github.com links point to $CURRENT_VERSION.

143 changes: 143 additions & 0 deletions docs/builder/smart-contracts/standards/faucets-and-policies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: "Faucets and Policies"
description: "Build fungible token faucets and choose standard mint, burn, send, and receive policies."
---

# Faucets and Policies

In Miden, a token issuer is an account. A fungible faucet account can mint and burn the fungible asset identified by that faucet's account ID. The standard faucet components give builders a reusable way to create token issuers without hand-writing the entire faucet interface.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heads-up: This is going to be outdated in 0.15 (see also 0xMiden/protocol#2956). The account type no longer decides what type of asset can be issued, instead this is decided at the asset level (AssetComposition).


Use this page when you need to create a faucet account, decide who can mint or burn, or understand how faucet behavior relates to standard notes.

:::info v0.14 differences
The current unstable standards surface uses a unified `FungibleFaucet` component and a richer `TokenPolicyManager`. The v0.14 snapshot uses separate `BasicFungibleFaucet` and `NetworkFungibleFaucet` components plus mint-policy components. Use the versioned docs if you are building against v0.14.
:::

## Faucet component

The current standard fungible faucet component is `FungibleFaucet`.

| Surface | Entry point |
|---------|-------------|
| Rust component | `miden_standards::account::faucets::FungibleFaucet` |
| Rust builder/helper | `FungibleFaucetBuilder`, `create_fungible_faucet` |
| MASM component | `miden::standards::faucets::fungible` |
| Account type | `FungibleFaucet` account |

Public storage is typical for shared token faucets because clients can discover faucet state and metadata. Private storage is possible, but it changes who can observe the faucet's state.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Replace "storage" with "state", since for a public account, everything is public, not just storage (in particular also the account's asset vault and code).


```rust title="Create a fungible faucet with allow-all policies"
use miden_protocol::Word;
use miden_protocol::account::AccountStorageMode;
use miden_protocol::account::auth::{AuthScheme, PublicKeyCommitment};
use miden_protocol::asset::{AssetAmount, TokenSymbol};
use miden_standards::AuthMethod;
use miden_standards::account::access::AccessControl;
use miden_standards::account::faucets::{
Description,
FungibleFaucet,
TokenName,
create_fungible_faucet,
};
use miden_standards::account::policies::{
BurnPolicyConfig,
MintPolicyConfig,
PolicyRegistration,
TokenPolicyManager,
TransferPolicy,
};

fn create_faucet_account() -> Result<(), Box<dyn std::error::Error>> {
let public_key = PublicKeyCommitment::from(Word::from([1, 2, 3, 4u32]));

let faucet = FungibleFaucet::builder()
.name(TokenName::new("Example Token")?)
.symbol(TokenSymbol::new("EXT")?)
.decimals(6)
.max_supply(AssetAmount::from(1_000_000u32))
.description(Description::new("Example token")?)
.build()?;

let policies = TokenPolicyManager::new()
.with_mint_policy(MintPolicyConfig::AllowAll, PolicyRegistration::Active)?
.with_burn_policy(BurnPolicyConfig::AllowAll, PolicyRegistration::Active)?
.with_send_policy(TransferPolicy::AllowAll, PolicyRegistration::Active)?
.with_receive_policy(TransferPolicy::AllowAll, PolicyRegistration::Active)?;

let account = create_fungible_faucet(
[9; 32],
faucet,
AccountStorageMode::Public,
AuthMethod::SingleSig {
approver: (public_key, AuthScheme::Falcon512Poseidon2),
},
AccessControl::AuthControlled,
policies,
)?;

assert!(account.is_faucet());
Ok(())
}
```

## Token identity

A fungible asset is tied to its faucet account ID. The faucet's metadata describes the token, while the account ID identifies the asset issuer.

| Field | Meaning |
|-------|---------|
| Symbol | Short token symbol. |
| Decimals | Display precision for client UX. |
| Max supply | Upper bound enforced by the faucet component. |
| Metadata | Optional display fields such as token name, description, logo URI, and external link. |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: TokenName is mandatory.

| Faucet account ID | The issuer ID used when constructing fungible assets and checking balances. |

When an account checks its balance for a fungible token, it queries by the faucet account ID.

## Choose policy modules

Policy modules decide which operations are allowed for a token faucet.

| Policy area | Current standard examples | Use it for |
|-------------|---------------------------|------------|
| Mint | `MintAllowAll`, `MintOwnerOnly` | Gate mint operations. |
| Burn | `BurnAllowAll`, `BurnOwnerOnly` | Gate burn operations. |
| Send | `TransferAllowAll`, `BasicBlocklist`, `OwnerControlledBlocklist` | Gate assets leaving accounts through notes. |
| Receive | `TransferAllowAll`, `BasicBlocklist`, `OwnerControlledBlocklist` | Gate assets entering account vaults. |

`TokenPolicyManager` owns the active policy roots and validates policy changes. Authority for changing policies comes from the account's access-control setup, such as owner-controlled or role-based authority.

## Mint with notes

Minting does not directly credit a recipient's account vault. A faucet creates a note carrying the minted asset, and the recipient consumes that note to receive the asset.

For standard flows:

- The faucet creates a mint note or a P2ID note containing the minted asset.
- The recipient discovers and consumes the note.
- The recipient's account must be able to receive the asset, usually by including `BasicWallet`.

This is the same two-transaction note model described in [What are Notes?](../notes/introduction).

## Burn returned assets

Burning is also note-based. A burn note returns assets to the faucet and executes the standard burn behavior. Use `BurnNote` from `miden-standards` rather than hand-writing a burn script unless your protocol needs custom conditions.

## When to write a custom faucet

Use `FungibleFaucet` when supply, metadata, minting, burning, and transfer policies match the standard pattern.

Write a custom faucet component when:

- Minting depends on application state, proofs, allowlists, or rate limits.
- Supply policy is more complex than a fixed max supply and a standard authority check.
- You need custom public methods beyond the standard faucet interface.

Comment on lines +130 to +135
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • The TokenPolicyManager allows for custom policies to check minting, burning and transfers. Users should be nudged to first check if implementing such a custom policy satisfies their use case. Only if that's not the case, should they resort to writing their own faucet.
  • Somewhat agree with the 2nd point, though a complex supply policy could also be handled in a CUSTOM_MINT note that is the only note allowed by the faucet to mint assets. This would move the logic outside the faucet and wouldn't require a custom faucet.
  • 3rd point reads a bit ambiguous: If users only need additional public methods, extending the faucet account with additional procedures may be a fine solution and wouldn't require a custom faucet per se. But if they need customized versions of the faucets' procedures, then, yes, they would have to write it themselves.

Even then, consider reusing standard auth, ownership, and wallet components where they fit. Custom faucet logic does not require custom authentication or custom note formats by default.

## Related pages

- [Account components](./account-components) - composing faucets with standard auth and ownership components
- [Standard notes](./standard-notes) - mint and burn notes
- [Assets, Vault, and Faucet migration notes](../../migration/asset-vault-faucet) - v0.14 asset and faucet changes
- [`miden-standards` faucet source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards/src/account/faucets) - current implementation
63 changes: 63 additions & 0 deletions docs/builder/smart-contracts/standards/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: "Miden Standards"
description: "Use standard Miden account components, notes, faucets, and policies from Rust or Miden Assembly."
---

# Miden Standards

Miden Standards are reusable building blocks for common smart-contract behavior: wallet interfaces, authentication components, token faucets, note scripts, and policy modules.

Use them when you want your account, note, or transaction flow to interoperate with the rest of the Miden ecosystem instead of defining every interface from scratch.

:::caution Current docs are unstable
The current docs track the unstable standards line. The v0.14 snapshot has a different standards surface in a few important places, especially faucet and policy APIs. Use the version selector if you are building against v0.14.
:::

This section is a builder guide, not the canonical standards specification. It explains which standard to reach for, how it fits into the smart-contract model, and where to switch to reference docs when you need exact procedure names, storage schemas, or script roots.

## How standards fit into smart contracts

Smart Contracts is the domain. Rust and Miden Assembly are authoring paths inside that domain.

| Layer | Role |
|------|------|
| Rust | Compose standard account components and construct standard notes through Rust APIs. |
| Miden Assembly | Import and call standard MASM modules directly when writing low-level account, note, transaction, or library code. |
| Miden Standards | Shared account components, note scripts, faucet policies, and helper modules used by both authoring paths. |

## What this section covers

<CardGrid cols={3}>
<Card title="Account components" href="./account-components" eyebrow="Compose accounts">
Use standard wallet, authentication, access-control, faucet, and metadata components.
</Card>
<Card title="Standard notes" href="./standard-notes" eyebrow="Move assets">
Choose P2ID, P2IDE, SWAP, PSWAP, mint, and burn note scripts.
</Card>
<Card title="Faucets and policies" href="./faucets-and-policies" eyebrow="Issue tokens">
Build token faucets and choose mint, burn, send, and receive policy modules.
</Card>
</CardGrid>

## When to use standards

Use a standard component or note when:

- You want other accounts, note scripts, clients, or tooling to recognize your account interface.
- Your behavior matches an existing pattern, such as holding assets, receiving a P2ID transfer, minting a fungible token, or verifying a single signature.
- You need a stable building block before adding custom application logic.

Write custom components or note scripts when:

- The authorization rules are application-specific.
- The note consumption condition is not covered by P2ID, P2IDE, SWAP, mint, or burn notes.
- The account's state model needs custom storage and custom exported methods.

You can mix both approaches. A typical application account starts with standard authentication and wallet components, then adds one or more custom components for protocol-specific logic.

## Related pages

- [Accounts](../accounts/) - components, storage, authentication, and account operations
- [Notes](../notes/) - note model, note scripts, standard note types, and output notes
- [Cross-component calls](../cross-component-calls) - calling component interfaces from scripts and components
- [`miden-standards` source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards) - current standards implementation
Loading