diff --git a/CHANGELOG.md b/CHANGELOG.md index 20b0a54e1e..0aabe8b965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ - Added `component_metadata()` to all account components to expose their metadata ([#2596](https://github.com/0xMiden/protocol/pull/2596)). - Added `Package` support in `MockChainBuilder` & `NoteScript` ([#2502](https://github.com/0xMiden/protocol/pull/2502)). - Added `ProgramExecutor` hooks to support DAP and other custom transaction program executors ([#2574](https://github.com/0xMiden/protocol/pull/2574)). +- [BREAKING] Changed `native_account::remove_asset` to return the asset value remaining in the vault instead of the removed value ([#2626](https://github.com/0xMiden/protocol/pull/2626)). - Implement `TransactionEventId::event_name` and `Host::resolve_event` for better VM diagnostics during even handler failures ([#2628](https://github.com/0xMiden/protocol/pull/2628)). - Added `FixedWidthString` for fixed-width UTF-8 string storage in `miden-standards` (`miden::standards::utils::string`). ([#2633](https://github.com/0xMiden/protocol/pull/2633)) @@ -98,12 +99,13 @@ - Added Ownable2Step as an Account Component ([#2572](https://github.com/0xMiden/protocol/pull/2572)) - [BREAKING] Introduced `PrivateNoteHeader` for output notes and removed `RawOutputNote::Header` variant ([#2569](https://github.com/0xMiden/protocol/pull/2569)). - [BREAKING] Changed `asset::create_fungible_asset` and `faucet::create_fungible_asset` signature to take `enable_callbacks` flag ([#2571](https://github.com/0xMiden/protocol/pull/2571)). - - [BREAKING] Fixed `TokenSymbol::try_from(Felt)` to reject values below `MIN_ENCODED_VALUE`; implemented `Display` for `TokenSymbol` replacing the fallible `to_string()` method; removed `Default` derive ([#2464](https://github.com/0xMiden/protocol/issues/2464)). - Moved `AccountSchemaCommitment` component into a sub-module ([#2603](https://github.com/0xMiden/protocol/pull/2603)). -- Added foreign account ID assertion in `account::load_foreign_account` ([#2560](https://github.com/0xMiden/protocol/pull/2560)). +- [BREAKING] `AssetVault::remove_asset` returns the asset value remaining in the vault `Option` rather than the removed value `Asset` ([#2626](https://github.com/0xMiden/protocol/pull/2626)). +- [BREAKING] `miden::protocol::faucet::burn` no longer returns the burnt asset value ([#2626](https://github.com/0xMiden/protocol/pull/2626)). - Fixed overlap in initial and active account storage slot memory region ([#2557](https://github.com/0xMiden/protocol/pull/2557)). - Fixed link map entry pointer validation bypass ([#2556](https://github.com/0xMiden/protocol/pull/2556)). +- Added foreign account ID assertion in `account::load_foreign_account` ([#2560](https://github.com/0xMiden/protocol/pull/2560)). ## 0.13.3 (2026-01-27) diff --git a/crates/miden-protocol/asm/kernels/transaction/api.masm b/crates/miden-protocol/asm/kernels/transaction/api.masm index 0ee3b5d49a..4eb2efbfb1 100644 --- a/crates/miden-protocol/asm/kernels/transaction/api.masm +++ b/crates/miden-protocol/asm/kernels/transaction/api.masm @@ -583,14 +583,15 @@ pub proc account_add_asset # => [ASSET_VALUE', pad(12)] end -#! Removes the specified asset from the vault. +#! Removes the specified asset from the vault and returns the remaining asset value. #! #! Inputs: [ASSET_KEY, ASSET_VALUE, pad(8)] -#! Outputs: [ASSET_VALUE, pad(12)] +#! Outputs: [REMAINING_ASSET_VALUE, pad(12)] #! #! Where: #! - ASSET_KEY is the vault key of the asset to remove from the vault. #! - ASSET_VALUE is the value of the asset to remove from the vault. +#! - REMAINING_ASSET_VALUE is the value of the asset remaining in the vault after removal. #! #! Panics if: #! - the fungible asset is not found in the vault. @@ -610,7 +611,7 @@ pub proc account_remove_asset # remove the specified asset from the account vault, emitting the corresponding events exec.account::remove_asset_from_vault - # => [ASSET_VALUE, pad(12)] + # => [REMAINING_ASSET_VALUE, pad(12)] end #! Returns the asset associated with the provided asset vault key in the active account's vault. @@ -780,11 +781,11 @@ end #! Burn an asset from the faucet the transaction is being executed against. #! #! Inputs: [ASSET_KEY, ASSET_VALUE, pad(8)] -#! Outputs: [ASSET_VALUE, pad(12)] +#! Outputs: [pad(16)] #! #! Where: #! - ASSET_KEY is the vault key of the asset to burn. -#! - ASSET_VALUE is the value of the asset that was burned. +#! - ASSET_VALUE is the value of the asset to burn. #! #! Panics if: #! - the transaction is not being executed against a faucet. @@ -810,7 +811,7 @@ pub proc faucet_burn_asset # burn the asset exec.faucet::burn - # => [ASSET_VALUE, pad(12)] + # => [pad(16)] end #! Returns whether the active account defines callbacks. diff --git a/crates/miden-protocol/asm/kernels/transaction/lib/account.masm b/crates/miden-protocol/asm/kernels/transaction/lib/account.masm index b751cb3597..40003cfe92 100644 --- a/crates/miden-protocol/asm/kernels/transaction/lib/account.masm +++ b/crates/miden-protocol/asm/kernels/transaction/lib/account.masm @@ -742,14 +742,15 @@ pub proc add_asset_to_vault # => [PROCESSED_ASSET_VALUE'] end -#! Removes the specified asset from the account vault. +#! Removes the specified asset from the account vault and returns the remaining asset value. #! #! Inputs: [ASSET_KEY, ASSET_VALUE] -#! Outputs: [ASSET_VALUE] +#! Outputs: [REMAINING_ASSET_VALUE] #! #! Where: #! - ASSET_KEY is the asset vault key of the asset to remove from the vault. #! - ASSET_VALUE is the value of the asset to remove from the vault. +#! - REMAINING_ASSET_VALUE is the value of the asset remaining in the vault after removal. #! #! Panics if: #! - the fungible asset is not found in the vault. @@ -770,17 +771,17 @@ pub proc remove_asset_from_vault # remove the asset from the account vault exec.asset_vault::remove_asset - # => [ASSET_VALUE, ASSET_KEY, ASSET_VALUE] + # => [REMAINING_ASSET_VALUE, ASSET_KEY, ASSET_VALUE] - swapw - # => [ASSET_KEY, ASSET_VALUE, ASSET_VALUE] + movdnw.2 + # => [ASSET_KEY, ASSET_VALUE, REMAINING_ASSET_VALUE] # emit event to signal that an asset is being removed from the account vault emit.ACCOUNT_VAULT_AFTER_REMOVE_ASSET_EVENT - # => [ASSET_KEY, ASSET_VALUE, ASSET_VALUE] + # => [ASSET_KEY, ASSET_VALUE, REMAINING_ASSET_VALUE] exec.account_delta::remove_asset - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] end #! Returns the ASSET_VALUE associated with the provided asset vault key in the active account's vault. diff --git a/crates/miden-protocol/asm/kernels/transaction/lib/asset_vault.masm b/crates/miden-protocol/asm/kernels/transaction/lib/asset_vault.masm index a65766a267..51444b0773 100644 --- a/crates/miden-protocol/asm/kernels/transaction/lib/asset_vault.masm +++ b/crates/miden-protocol/asm/kernels/transaction/lib/asset_vault.masm @@ -150,20 +150,8 @@ pub proc add_fungible_asset padw loc_load.0 mem_loadw_le # => [VAULT_ROOT, MERGED_ASSET_VALUE, ASSET_KEY, CUR_VAULT_VALUE, MERGED_ASSET_VALUE] - movdnw.2 padw - # => [EMPTY_WORD, MERGED_ASSET_VALUE, ASSET_KEY, VAULT_ROOT, CUR_VAULT_VALUE, MERGED_ASSET_VALUE] - - # check if amount of new asset is zero - # if it is zero, insert EMPTY_WORD to keep the merkle tree sparse - dupw.1 - exec.fungible_asset::value_into_amount - eq.0 - # => [is_amount_zero, EMPTY_WORD, MERGED_ASSET_VALUE, ASSET_KEY, VAULT_ROOT, CUR_VAULT_VALUE, MERGED_ASSET_VALUE] - - # If is_amount_zero EMPTY_WORD remains. - # If !is_amount_zero MERGED_ASSET_VALUE remains. - cdropw - # => [EMPTY_WORD_OR_MERGED_ASSET_VALUE, ASSET_KEY, VAULT_ROOT, CUR_VAULT_VALUE, MERGED_ASSET_VALUE] + movdnw.2 + # => [MERGED_ASSET_VALUE, ASSET_KEY, VAULT_ROOT, CUR_VAULT_VALUE, MERGED_ASSET_VALUE] # update asset in vault exec.smt::set @@ -261,21 +249,22 @@ end # REMOVE ASSET # ================================================================================================= -#! Splits ASSET_VALUE off the existing asset in the vault associated with the ASSET_KEY. +#! Splits ASSET_VALUE off the existing asset in the vault associated with the ASSET_KEY +#! and returns the remaining asset value. #! #! For instance, if ASSET_KEY points to a fungible asset with amount 100, and ASSET_VALUE has -#! amount 30, then a fungible asset with amount 70 remains in the vault. +#! amount 30, then a fungible asset with amount 70 remains in the vault and is returned. #! #! Inputs: [ASSET_KEY, ASSET_VALUE, vault_root_ptr] -#! Outputs: [ASSET_VALUE] +#! Outputs: [REMAINING_ASSET_VALUE] #! #! Where: #! - ASSET_KEY is the asset vault key of the fungible asset to remove from the vault. -#! - ASSET_VALUE is the fungible asset that was removed from the vault. +#! - REMAINING_ASSET_VALUE is the value of the fungible asset remaining in the vault after removal. #! - vault_root_ptr is a pointer to the memory location at which the vault root is stored. #! #! Locals: -#! - 0..4: ASSET_VALUE +#! - 0..4: REMAINING_ASSET_VALUE #! #! Panics if: #! - the amount of the asset in the vault is less than the amount to be removed. @@ -293,33 +282,22 @@ pub proc remove_fungible_asset movdnw.2 # => [ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] - # store ASSET_VALUE so we can return it later - loc_storew_le.0 - # => [ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] - dupw.2 swapw # => [ASSET_VALUE, PEEKED_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] - # compute PEEKED_ASSET_VALUE - ASSET_VALUE + # compute REMAINING_ASSET_VALUE = PEEKED_ASSET_VALUE - ASSET_VALUE exec.fungible_asset::split - # => [NEW_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] - - padw dupw.1 exec.fungible_asset::value_into_amount - # => [new_amount, EMPTY_WORD, NEW_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] - - eq.0 - # => [is_new_amount_zero, EMPTY_WORD, NEW_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] + # => [REMAINING_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] - # If is_new_amount_zero EMPTY_WORD remains. - # If !is_new_amount_zero NEW_ASSET_VALUE remains. - cdropw - # => [EMPTY_WORD_OR_NEW_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] + # store remaining asset value so we can return it later + loc_storew_le.0 + # => [REMAINING_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] dup.12 padw movup.4 mem_loadw_le - # => [VAULT_ROOT, EMPTY_WORD_OR_NEW_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] + # => [VAULT_ROOT, REMAINING_ASSET_VALUE, ASSET_KEY, PEEKED_ASSET_VALUE, vault_root_ptr] movdnw.2 - # => [EMPTY_WORD_OR_NEW_ASSET_VALUE, ASSET_KEY, VAULT_ROOT, PEEKED_ASSET_VALUE, vault_root_ptr] + # => [REMAINING_ASSET_VALUE, ASSET_KEY, VAULT_ROOT, PEEKED_ASSET_VALUE, vault_root_ptr] # update asset in vault and assert the old value is equivalent to the peeked value provided # via peek_asset @@ -335,20 +313,23 @@ pub proc remove_fungible_asset # => [NEW_VAULT_ROOT] loc_loadw_le.0 - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] end -#! Remove the specified non-fungible asset from the vault. +#! Remove the specified non-fungible asset from the vault and return the remaining asset value. +#! +#! Since non-fungible assets are either fully present or absent, the remaining value after +#! removal is always EMPTY_WORD. #! #! Note that the ASSET_VALUE is only needed to check against the asset that was removed from the #! vault. #! #! Inputs: [ASSET_KEY, ASSET_VALUE, vault_root_ptr] -#! Outputs: [ASSET_VALUE] +#! Outputs: [REMAINING_ASSET_VALUE] #! #! Where: #! - ASSET_KEY is the asset vault key of the non-fungible asset to remove from the vault. -#! - ASSET_VALUE is the non-fungible asset that was removed from the vault. +#! - REMAINING_ASSET_VALUE is always EMPTY_WORD (nothing remains after removing a non-fungible asset). #! - vault_root_ptr is a pointer to the memory location at which the vault root is stored. #! #! Panics if: @@ -366,22 +347,27 @@ pub proc remove_non_fungible_asset exec.smt::set # => [REMOVED_ASSET_VALUE, NEW_VAULT_ROOT, ASSET_VALUE, vault_root_ptr] - dupw.2 assert_eqw.err=ERR_VAULT_NON_FUNGIBLE_ASSET_TO_REMOVE_NOT_FOUND - # => [NEW_VAULT_ROOT, ASSET_VALUE, vault_root_ptr] + movupw.2 assert_eqw.err=ERR_VAULT_NON_FUNGIBLE_ASSET_TO_REMOVE_NOT_FOUND + # => [NEW_VAULT_ROOT, vault_root_ptr] # update the vault root - movup.8 mem_storew_le dropw - # => [ASSET_VALUE] + movup.4 mem_storew_le dropw + # => [] + + # push EMPTY_WORD to represent that nothing remains after non-fungible removal + padw + # => [REMAINING_ASSET_VALUE] end -#! Remove the specified asset from the vault. +#! Remove the specified asset from the vault and return the remaining asset value. #! #! Inputs: [ASSET_KEY, ASSET_VALUE, vault_root_ptr] -#! Outputs: [ASSET_VALUE] +#! Outputs: [REMAINING_ASSET_VALUE] #! #! Where: #! - ASSET_KEY is the asset vault key of the asset to remove from the vault. #! - ASSET_VALUE is the value of the asset to remove from the vault. +#! - REMAINING_ASSET_VALUE is the value of the asset remaining in the vault after removal. #! - vault_root_ptr is a pointer to the memory location at which the vault root is stored. #! #! Panics if: @@ -396,9 +382,9 @@ pub proc remove_asset # remove the asset from the asset vault if.true exec.remove_fungible_asset - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] else exec.remove_non_fungible_asset - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] end end diff --git a/crates/miden-protocol/asm/kernels/transaction/lib/faucet.masm b/crates/miden-protocol/asm/kernels/transaction/lib/faucet.masm index 1dca7cf99d..c3d4223641 100644 --- a/crates/miden-protocol/asm/kernels/transaction/lib/faucet.masm +++ b/crates/miden-protocol/asm/kernels/transaction/lib/faucet.masm @@ -43,11 +43,11 @@ end #! against. #! #! Inputs: [ASSET_KEY, ASSET_VALUE] -#! Outputs: [ASSET_VALUE] +#! Outputs: [] #! #! Where: #! - ASSET_KEY is the vault key of the asset to burn. -#! - ASSET_VALUE is the value of the asset value to burn. +#! - ASSET_VALUE is the value of the asset to burn. #! #! Panics if: #! - the transaction is not being executed against a fungible faucet. @@ -67,7 +67,11 @@ proc burn_fungible_asset # remove the asset from the input vault for asset preservation exec.asset_vault::remove_fungible_asset - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] + + # drop the remaining value (not meaningful to the caller) + dropw + # => [] end # NON-FUNGIBLE ASSETS @@ -109,11 +113,11 @@ end #! executed against. #! #! Inputs: [ASSET_KEY, ASSET_VALUE] -#! Outputs: [ASSET_VALUE] +#! Outputs: [] #! #! Where: #! - ASSET_KEY is the vault key of the asset to burn. -#! - ASSET_VALUE is the value of the asset value to burn. +#! - ASSET_VALUE is the value of the asset to burn. #! #! Panics if: #! - the transaction is not being executed against a non-fungible faucet. @@ -132,7 +136,11 @@ proc burn_non_fungible_asset # => [ASSET_KEY, ASSET_VALUE, input_vault_root_ptr] exec.asset_vault::remove_non_fungible_asset - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] + + # drop the remaining value (not meaningful to the caller) + dropw + # => [] end # PUBLIC INTERFACE @@ -177,11 +185,11 @@ end #! Burn an asset from the faucet the transaction is being executed against. #! #! Inputs: [ASSET_KEY, ASSET_VALUE] -#! Outputs: [ASSET_VALUE] +#! Outputs: [] #! #! Where: #! - ASSET_KEY is the vault key of the asset to burn. -#! - ASSET_VALUE is the value of the asset value to burn. +#! - ASSET_VALUE is the value of the asset to burn. #! #! Panics if: #! - the transaction is not being executed against a faucet. @@ -200,10 +208,10 @@ pub proc burn if.true # burn the fungible asset exec.burn_fungible_asset - # => [ASSET_VALUE] + # => [] else # burn the non-fungible asset exec.burn_non_fungible_asset - # => [ASSET_VALUE] + # => [] end end diff --git a/crates/miden-protocol/asm/protocol/faucet.masm b/crates/miden-protocol/asm/protocol/faucet.masm index 15648cc698..c9f105c743 100644 --- a/crates/miden-protocol/asm/protocol/faucet.masm +++ b/crates/miden-protocol/asm/protocol/faucet.masm @@ -101,11 +101,11 @@ end #! Burn an asset from the faucet the transaction is being executed against. #! #! Inputs: [ASSET_KEY, ASSET_VALUE] -#! Outputs: [ASSET_VALUE] +#! Outputs: [] #! #! Where: #! - ASSET_KEY is the vault key of the asset to burn. -#! - ASSET_VALUE is the value of the asset that was burned. +#! - ASSET_VALUE is the value of the asset to burn. #! #! Panics if: #! - the transaction is not being executed against a faucet. @@ -127,11 +127,11 @@ pub proc burn # => [offset, ASSET_KEY, ASSET_VALUE, pad(7)] syscall.exec_kernel_proc - # => [ASSET_VALUE, pad(12)] + # => [pad(16)] # clean the stack - swapdw dropw dropw swapw dropw - # => [ASSET_VALUE] + dropw dropw dropw dropw + # => [] end #! Returns whether the active account defines callbacks. diff --git a/crates/miden-protocol/asm/protocol/native_account.masm b/crates/miden-protocol/asm/protocol/native_account.masm index 1c67fa5492..c3f390dd73 100644 --- a/crates/miden-protocol/asm/protocol/native_account.masm +++ b/crates/miden-protocol/asm/protocol/native_account.masm @@ -231,14 +231,16 @@ pub proc add_asset # => [ASSET_VALUE'] end -#! Remove the specified asset from the vault. +#! Remove the specified asset from the vault and return the remaining asset value. #! #! Inputs: [ASSET_KEY, ASSET_VALUE] -#! Outputs: [ASSET_VALUE] +#! Outputs: [REMAINING_ASSET_VALUE] #! #! Where: #! - ASSET_KEY is the vault key of the asset to remove from the vault. #! - ASSET_VALUE is the value of the asset to remove from the vault. +#! - REMAINING_ASSET_VALUE is the value of the asset remaining in the vault after removal which may +#! be the empty word if nothing remains (e.g. if a non-fungible asset is removed). #! #! Panics if: #! - the fungible asset is not found in the vault. @@ -255,11 +257,11 @@ pub proc remove_asset # => [offset, ASSET_KEY, ASSET_VALUE, pad(7)] syscall.exec_kernel_proc - # => [ASSET_VALUE, pad(12)] + # => [REMAINING_ASSET_VALUE, pad(12)] # clean the stack swapdw dropw dropw swapw dropw - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] end # CODE diff --git a/crates/miden-protocol/src/asset/vault/mod.rs b/crates/miden-protocol/src/asset/vault/mod.rs index 35c7f1c643..9ba8c652e8 100644 --- a/crates/miden-protocol/src/asset/vault/mod.rs +++ b/crates/miden-protocol/src/asset/vault/mod.rs @@ -193,9 +193,13 @@ impl AssetVault { for (&asset, &action) in delta.non_fungible().iter() { match action { - NonFungibleDeltaAction::Add => self.add_non_fungible_asset(asset), - NonFungibleDeltaAction::Remove => self.remove_non_fungible_asset(asset), - }?; + NonFungibleDeltaAction::Add => { + self.add_non_fungible_asset(asset)?; + }, + NonFungibleDeltaAction::Remove => { + self.remove_non_fungible_asset(asset)?; + }, + } } Ok(()) @@ -267,27 +271,32 @@ impl AssetVault { // REMOVE ASSET // -------------------------------------------------------------------------------------------- - /// Remove the specified asset from the vault and returns the asset that was just removed. + /// Remove the specified asset from the vault and returns the remaining asset, if any. + /// + /// - For fungible assets, returns `Some(Asset::Fungible(remaining))` with the remaining balance + /// (which may have amount 0). + /// - For non-fungible assets, returns `None` since non-fungible assets are either fully present + /// or absent. /// /// # Errors /// - The fungible asset is not found in the vault. /// - The amount of the fungible asset in the vault is less than the amount to be removed. /// - The non-fungible asset is not found in the vault. - pub fn remove_asset(&mut self, asset: Asset) -> Result { + pub fn remove_asset(&mut self, asset: Asset) -> Result, AssetVaultError> { match asset { Asset::Fungible(asset) => { - let asset = self.remove_fungible_asset(asset)?; - Ok(Asset::Fungible(asset)) + let remaining = self.remove_fungible_asset(asset)?; + Ok(Some(Asset::Fungible(remaining))) }, Asset::NonFungible(asset) => { - let asset = self.remove_non_fungible_asset(asset)?; - Ok(Asset::NonFungible(asset)) + self.remove_non_fungible_asset(asset)?; + Ok(None) }, } } - /// Remove the specified fungible asset from the vault and returns the asset that was just - /// removed. If the final amount of the asset is zero, the asset is removed from the vault. + /// Remove the specified fungible asset from the vault and returns the remaining fungible + /// asset. If the final amount of the asset is zero, the asset is removed from the vault. /// /// # Errors /// - The asset is not found in the vault. @@ -325,11 +334,10 @@ impl AssetVault { .insert(new_asset.vault_key().to_word(), new_asset.to_value_word()) .map_err(AssetVaultError::MaxLeafEntriesExceeded)?; - Ok(other_asset) + Ok(new_asset) } - /// Remove the specified non-fungible asset from the vault and returns the asset that was just - /// removed. + /// Remove the specified non-fungible asset from the vault. /// /// # Errors /// - The non-fungible asset is not found in the vault. @@ -337,7 +345,7 @@ impl AssetVault { fn remove_non_fungible_asset( &mut self, asset: NonFungibleAsset, - ) -> Result { + ) -> Result<(), AssetVaultError> { // remove the asset from the vault. let old = self .asset_tree @@ -349,8 +357,7 @@ impl AssetVault { return Err(AssetVaultError::NonFungibleAssetNotFound(asset)); } - // return the asset that was removed. - Ok(asset) + Ok(()) } } diff --git a/crates/miden-standards/asm/standards/faucets/mod.masm b/crates/miden-standards/asm/standards/faucets/mod.masm index 4256a6b4ce..a7679ce69e 100644 --- a/crates/miden-standards/asm/standards/faucets/mod.masm +++ b/crates/miden-standards/asm/standards/faucets/mod.masm @@ -198,7 +198,7 @@ pub proc burn # burn the asset # this ensures we only burn assets that were issued by this faucet (which implies they are # fungible) - exec.faucet::burn dropw + exec.faucet::burn # => [amount, pad(16)] # Subtract burnt amount from current token_supply in storage. diff --git a/crates/miden-standards/src/testing/mock_account_code.rs b/crates/miden-standards/src/testing/mock_account_code.rs index 8146673c82..6f4b8aa061 100644 --- a/crates/miden-standards/src/testing/mock_account_code.rs +++ b/crates/miden-standards/src/testing/mock_account_code.rs @@ -15,10 +15,10 @@ const MOCK_FAUCET_CODE: &str = " end #! Inputs: [ASSET_KEY, ASSET_VALUE, pad(8)] - #! Outputs: [ASSET_VALUE, pad(12)] + #! Outputs: [pad(16)] pub proc burn exec.faucet::burn - # => [ASSET_VALUE, pad(12)] + # => [pad(16)] end "; @@ -113,10 +113,10 @@ const MOCK_ACCOUNT_CODE: &str = " end #! Inputs: [ASSET_KEY, ASSET_VALUE, pad(8)] - #! Outputs: [ASSET_VALUE, pad(12)] + #! Outputs: [REMAINING_ASSET_VALUE, pad(12)] pub proc remove_asset exec.native_account::remove_asset - # => [ASSET_VALUE, pad(12)] + # => [REMAINING_ASSET_VALUE, pad(12)] end #! Inputs: [pad(16)] diff --git a/crates/miden-testing/src/kernel_tests/tx/test_account_delta.rs b/crates/miden-testing/src/kernel_tests/tx/test_account_delta.rs index 99c4dac8b5..2e262fd533 100644 --- a/crates/miden-testing/src/kernel_tests/tx/test_account_delta.rs +++ b/crates/miden-testing/src/kernel_tests/tx/test_account_delta.rs @@ -556,12 +556,15 @@ async fn non_fungible_asset_delta() -> anyhow::Result<()> { exec.util::create_default_note_with_moved_asset # => [] - # remove and re-add asset 3 + # remove asset 3 push.{ASSET3_VALUE} push.{ASSET3_KEY} exec.remove_asset - # => [ASSET_VALUE] + # => [REMAINING_ASSET_VALUE] + dropw + # re-add asset 3 + push.{ASSET3_VALUE} push.{ASSET3_KEY} # => [ASSET_KEY, ASSET_VALUE] exec.add_asset dropw diff --git a/crates/miden-testing/src/kernel_tests/tx/test_asset_vault.rs b/crates/miden-testing/src/kernel_tests/tx/test_asset_vault.rs index f551c63db1..e4bdfefce9 100644 --- a/crates/miden-testing/src/kernel_tests/tx/test_asset_vault.rs +++ b/crates/miden-testing/src/kernel_tests/tx/test_asset_vault.rs @@ -1,5 +1,4 @@ use assert_matches::assert_matches; -use miden_protocol::ONE; use miden_protocol::account::AccountId; use miden_protocol::asset::{ Asset, @@ -24,6 +23,7 @@ use miden_protocol::testing::account_id::{ }; use miden_protocol::testing::constants::{FUNGIBLE_ASSET_AMOUNT, NON_FUNGIBLE_ASSET_DATA}; use miden_protocol::transaction::memory; +use miden_protocol::{ONE, Word}; use crate::executor::CodeExecutor; use crate::kernel_tests::tx::ExecutionOutputExt; @@ -362,13 +362,10 @@ async fn test_remove_fungible_asset_success_no_balance_remaining() -> anyhow::Re let exec_output = &tx_context.execute_code(&code).await?; - assert_eq!( - exec_output.get_stack_word(0), - account_vault - .remove_asset(Asset::Fungible(remove_fungible_asset)) - .unwrap() - .to_value_word() - ); + let remaining = account_vault + .remove_asset(Asset::Fungible(remove_fungible_asset))? + .expect("fungible removal should return remaining asset"); + assert_eq!(exec_output.get_stack_word(0), remaining.to_value_word()); assert_eq!( exec_output.get_kernel_mem_word(memory::NATIVE_ACCT_VAULT_ROOT_PTR), @@ -441,13 +438,10 @@ async fn test_remove_fungible_asset_success_balance_remaining() -> anyhow::Resul let exec_output = &tx_context.execute_code(&code).await?; - assert_eq!( - exec_output.get_stack_word(0), - account_vault - .remove_asset(Asset::Fungible(remove_fungible_asset)) - .unwrap() - .to_value_word() - ); + let remaining = account_vault + .remove_asset(Asset::Fungible(remove_fungible_asset))? + .expect("fungible removal should return remaining asset"); + assert_eq!(exec_output.get_stack_word(0), remaining.to_value_word()); assert_eq!( exec_output.get_kernel_mem_word(memory::NATIVE_ACCT_VAULT_ROOT_PTR), @@ -533,10 +527,11 @@ async fn test_remove_non_fungible_asset_success() -> anyhow::Result<()> { let exec_output = &tx_context.execute_code(&code).await?; - assert_eq!( - exec_output.get_stack_word(0), - account_vault.remove_asset(non_fungible_asset).unwrap().to_value_word() + assert!( + account_vault.remove_asset(non_fungible_asset)?.is_none(), + "non-fungible removal should return None" ); + assert_eq!(exec_output.get_stack_word(0), Word::default()); assert_eq!( exec_output.get_kernel_mem_word(memory::NATIVE_ACCT_VAULT_ROOT_PTR), diff --git a/crates/miden-testing/src/kernel_tests/tx/test_faucet.rs b/crates/miden-testing/src/kernel_tests/tx/test_faucet.rs index d436abbe05..59796ae2ec 100644 --- a/crates/miden-testing/src/kernel_tests/tx/test_faucet.rs +++ b/crates/miden-testing/src/kernel_tests/tx/test_faucet.rs @@ -400,10 +400,6 @@ async fn test_burn_fungible_asset_succeeds() -> anyhow::Result<()> { push.{FUNGIBLE_ASSET_KEY} call.mock_faucet::burn - # assert the correct asset is returned - push.{FUNGIBLE_ASSET_VALUE} - assert_eqw.err="burnt asset does not match expected asset" - # assert the input vault has been updated exec.memory::get_input_vault_root_ptr @@ -565,10 +561,7 @@ async fn test_burn_non_fungible_asset_succeeds() -> anyhow::Result<()> { push.{NON_FUNGIBLE_ASSET_VALUE} push.{NON_FUNGIBLE_ASSET_KEY} call.mock_faucet::burn - - # assert the correct asset is returned - push.{NON_FUNGIBLE_ASSET_VALUE} - assert_eqw.err="burnt asset does not match expected asset" + dropw # assert the input vault has been updated and does not have the burnt asset exec.memory::get_input_vault_root_ptr diff --git a/crates/miden-testing/tests/scripts/faucet.rs b/crates/miden-testing/tests/scripts/faucet.rs index 0e98207033..675bdada2d 100644 --- a/crates/miden-testing/tests/scripts/faucet.rs +++ b/crates/miden-testing/tests/scripts/faucet.rs @@ -298,10 +298,7 @@ async fn prove_burning_fungible_asset_on_existing_faucet_succeeds() -> anyhow::R # => [] call.::miden::standards::faucets::basic_fungible::burn - # => [ASSET_VALUE] - - # truncate the stack - dropw + # => [pad(16)] end "; @@ -364,10 +361,7 @@ async fn faucet_burn_fungible_asset_fails_amount_exceeds_token_supply() -> anyho # => [] call.::miden::standards::faucets::basic_fungible::burn - # => [ASSET_VALUE] - - # truncate the stack - dropw + # => [pad(16)] end "; diff --git a/docs/src/protocol_library.md b/docs/src/protocol_library.md index 3076434d5c..7981bba1d7 100644 --- a/docs/src/protocol_library.md +++ b/docs/src/protocol_library.md @@ -67,7 +67,7 @@ Native account procedures can be used to write to storage, add or remove assets | `set_item` | Sets an item in the native account storage.

**Inputs:** `[slot_id_suffix, slot_id_prefix, VALUE]`
**Outputs:** `[OLD_VALUE]` | Native & Account | | `set_map_item` | Sets VALUE under the specified KEY within the map contained in the given native account storage slot.

**Inputs:** `[slot_id_suffix, slot_id_prefix, KEY, VALUE]`
**Outputs:** `[OLD_VALUE]` | Native & Account | | `add_asset` | Adds the specified asset to the vault. For fungible assets, returns the total after addition.

**Inputs:** `[ASSET_KEY, ASSET_VALUE]`
**Outputs:** `[ASSET_VALUE']` | Native & Account | -| `remove_asset` | Removes the specified asset from the vault.

**Inputs:** `[ASSET_KEY, ASSET_VALUE]`
**Outputs:** `[ASSET_VALUE]` | Native & Account | +| `remove_asset` | Removes the specified asset from the vault and returns the remaining asset value.

**Inputs:** `[ASSET_KEY, ASSET_VALUE]`
**Outputs:** `[REMAINING_ASSET_VALUE]` | Native & Account | | `was_procedure_called` | Returns 1 if a native account procedure was called during transaction execution, and 0 otherwise.

**Inputs:** `[PROC_ROOT]`
**Outputs:** `[was_called]` | Any | ## Active Note Procedures (`miden::protocol::active_note`) @@ -153,7 +153,7 @@ Faucet procedures allow reading and writing to faucet accounts to mint and burn | `create_fungible_asset` | Creates a fungible asset for the faucet the transaction is being executed against.

**Inputs:** `[amount]`
**Outputs:** `[ASSET_KEY, ASSET_VALUE]` | Faucet | | `create_non_fungible_asset` | Creates a non-fungible asset for the faucet the transaction is being executed against.

**Inputs:** `[DATA_HASH]`
**Outputs:** `[ASSET_KEY, ASSET_VALUE]` | Faucet | | `mint` | Mint an asset from the faucet the transaction is being executed against.

**Inputs:** `[ASSET_KEY, ASSET_VALUE]`
**Outputs:** `[NEW_ASSET_VALUE]` | Native & Account & Faucet | -| `burn` | Burn an asset from the faucet the transaction is being executed against.

**Inputs:** `[ASSET_KEY, ASSET_VALUE]`
**Outputs:** `[ASSET_VALUE]` | Native & Account & Faucet | +| `burn` | Burn an asset from the faucet the transaction is being executed against.

**Inputs:** `[ASSET_KEY, ASSET_VALUE]`
**Outputs:** `[]` | Native & Account & Faucet | | `has_callbacks` | Returns whether the active account defines callbacks.

**Inputs:** `[]`
**Outputs:** `[has_callbacks]` | Any | ## Asset Procedures (`miden::protocol::asset`)