Skip to main content

miden_agglayer/
b2agg_note.rs

1//! Bridge Out note creation utilities.
2//!
3//! This module provides helpers for creating B2AGG (Bridge to AggLayer) notes,
4//! which are used to bridge assets out from Miden to the AggLayer network.
5
6use alloc::vec::Vec;
7
8use miden_assembly::Library;
9use miden_assembly::serde::Deserializable;
10use miden_core::Felt;
11use miden_protocol::account::AccountId;
12use miden_protocol::crypto::rand::FeltRng;
13use miden_protocol::errors::NoteError;
14use miden_protocol::note::{
15    Note,
16    NoteAssets,
17    NoteAttachment,
18    NoteAttachments,
19    NoteRecipient,
20    NoteScript,
21    NoteScriptRoot,
22    NoteStorage,
23    NoteType,
24    PartialNoteMetadata,
25};
26use miden_standards::note::{NetworkAccountTarget, NoteExecutionHint};
27use miden_utils_sync::LazyLock;
28
29use crate::EthAddress;
30
31// NOTE SCRIPT
32// ================================================================================================
33
34// Initialize the B2AGG note script only once
35static B2AGG_SCRIPT: LazyLock<NoteScript> = LazyLock::new(|| {
36    let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/b2agg.masl"));
37    let library =
38        Library::read_from_bytes(bytes).expect("shipped B2AGG script library is well-formed");
39    NoteScript::from_library(&library).expect("shipped B2AGG script is well-formed")
40});
41
42// B2AGG NOTE
43// ================================================================================================
44
45/// B2AGG (Bridge to AggLayer) note.
46///
47/// This note is used to bridge assets from Miden to another network via the AggLayer.
48/// When consumed by a bridge account, the assets are burned and a corresponding
49/// claim can be made on the destination network. B2AGG notes are always public.
50pub struct B2AggNote;
51
52impl B2AggNote {
53    // CONSTANTS
54    // --------------------------------------------------------------------------------------------
55
56    /// Expected number of storage items for a B2AGG note.
57    pub const NUM_STORAGE_ITEMS: usize = 6;
58
59    // PUBLIC ACCESSORS
60    // --------------------------------------------------------------------------------------------
61
62    /// Returns the B2AGG (Bridge to AggLayer) note script.
63    pub fn script() -> NoteScript {
64        B2AGG_SCRIPT.clone()
65    }
66
67    /// Returns the B2AGG note script root.
68    pub fn script_root() -> NoteScriptRoot {
69        B2AGG_SCRIPT.root()
70    }
71
72    // BUILDERS
73    // --------------------------------------------------------------------------------------------
74
75    /// Creates a B2AGG (Bridge to AggLayer) note.
76    ///
77    /// This note is used to bridge assets from Miden to another network via the AggLayer.
78    /// When consumed by a bridge account, the assets are burned and a corresponding
79    /// claim can be made on the destination network. B2AGG notes are always public.
80    ///
81    /// # Parameters
82    /// - `destination_network`: The AggLayer-assigned network ID for the destination chain
83    /// - `destination_address`: The Ethereum address on the destination network
84    /// - `assets`: The assets to bridge (must be fungible assets from a network faucet)
85    /// - `target_account_id`: The account ID that will consume this note (bridge account)
86    /// - `sender_account_id`: The account ID of the note creator
87    /// - `rng`: Random number generator for creating the note serial number
88    ///
89    /// # Errors
90    /// Returns an error if note creation fails.
91    pub fn create<R: FeltRng>(
92        destination_network: u32,
93        destination_address: EthAddress,
94        assets: NoteAssets,
95        target_account_id: AccountId,
96        sender_account_id: AccountId,
97        rng: &mut R,
98    ) -> Result<Note, NoteError> {
99        let note_storage = build_note_storage(destination_network, destination_address)?;
100
101        let attachment = NetworkAccountTarget::new(target_account_id, NoteExecutionHint::Always)
102            .map_err(|error| {
103                NoteError::other_with_source("failed to create b2agg network account target", error)
104            })?;
105        let attachments = NoteAttachments::from(NoteAttachment::from(attachment));
106
107        let metadata = PartialNoteMetadata::new(sender_account_id, NoteType::Public);
108
109        let recipient = NoteRecipient::new(rng.draw_word(), Self::script(), note_storage);
110
111        Ok(Note::with_attachments(assets, metadata, recipient, attachments))
112    }
113}
114
115// HELPER FUNCTIONS
116// ================================================================================================
117
118/// Builds the note storage for a B2AGG note.
119///
120/// The storage layout is:
121/// - 1 felt: destination_network
122/// - 5 felts: destination_address (20 bytes as 5 u32 values)
123fn build_note_storage(
124    destination_network: u32,
125    destination_address: EthAddress,
126) -> Result<NoteStorage, NoteError> {
127    let mut elements = Vec::with_capacity(6);
128
129    let destination_network = u32::from_le_bytes(destination_network.to_be_bytes());
130    elements.push(Felt::from(destination_network));
131    elements.extend(destination_address.to_elements());
132
133    NoteStorage::new(elements)
134}