-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #363 from phklive/aswap
Add `Swap` script
- Loading branch information
Showing
3 changed files
with
238 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
use.miden::sat::note | ||
use.miden::wallets::basic->wallet | ||
|
||
# Swap script: adds an asset from the note into consumers account and | ||
# creates a note consumable by note issuer containing requested ASSET. | ||
# | ||
# Requires that the account exposes: | ||
# | ||
# Inputs: [SCRIPT_ROOT] | ||
# Outputs: [] | ||
# | ||
# Note inputs are assumed to be as follows: | ||
# - RECIPIENT | ||
# - ASSET | ||
# - TAG = [tag, 0, 0, 0] | ||
# | ||
# FAILS if: | ||
# - Account does not expose miden::wallets::basic::receive_asset procedure | ||
# - Account does not expose miden::wallets::basic::send_asset procedure | ||
# - Account vault does not contain the requested asset | ||
# - Adding a fungible asset would result in amount overflow, i.e., the total amount would be | ||
# greater than 2^63 | ||
begin | ||
# drop the transaction script root | ||
dropw | ||
# => [] | ||
|
||
# store asset into memory at address 3 | ||
push.3 exec.note::get_assets assert | ||
# => [ptr] | ||
|
||
# load the asset and add it to the account | ||
mem_loadw call.wallet::receive_asset dropw | ||
# => [] | ||
|
||
# store note inputs into memory starting at address 0 | ||
push.0 exec.note::get_inputs | ||
# => [inputs_ptr] | ||
|
||
# load recipient | ||
drop padw mem_loadw | ||
# => [RECIPIENT] | ||
|
||
padw mem_loadw.1 | ||
# => [ASSET, RECIPIENT] | ||
|
||
padw mem_loadw.2 | ||
# => [0, 0, 0, tag, ASSET, RECIPIENT] | ||
|
||
drop drop drop movdn.4 | ||
# => [ASSET, tag, RECIPIENT] | ||
|
||
# create a note using inputs | ||
call.wallet::send_asset dropw dropw | ||
# => [] | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
use common::{ | ||
get_account_with_default_account_code, get_new_key_pair_with_advice_map, MockDataStore, | ||
}; | ||
use miden_lib::notes::{create_note, Script}; | ||
use miden_objects::{ | ||
accounts::{Account, AccountId, AccountVault, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN}, | ||
assembly::ProgramAst, | ||
assets::{Asset, FungibleAsset, NonFungibleAsset, NonFungibleAssetDetails}, | ||
notes::{NoteMetadata, NoteStub, NoteVault}, | ||
Felt, | ||
}; | ||
use miden_tx::TransactionExecutor; | ||
use mock::constants::{ | ||
ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN, | ||
ACCOUNT_ID_SENDER, | ||
}; | ||
use vm_processor::Digest; | ||
|
||
mod common; | ||
|
||
#[test] | ||
fn test_swap_script() { | ||
// Create assets | ||
let faucet_id = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN).unwrap(); | ||
let fungible_asset: Asset = FungibleAsset::new(faucet_id, 100).unwrap().into(); | ||
|
||
let faucet_id_2 = AccountId::try_from(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN).unwrap(); | ||
let non_fungible_asset: Asset = NonFungibleAsset::new( | ||
&NonFungibleAssetDetails::new(faucet_id_2, vec![1, 2, 3, 4]).unwrap(), | ||
) | ||
.unwrap() | ||
.into(); | ||
|
||
// Create sender and target account | ||
let sender_account_id = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap(); | ||
|
||
let target_account_id = | ||
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN).unwrap(); | ||
let (target_pub_key, target_sk_felt) = get_new_key_pair_with_advice_map(); | ||
let target_account = get_account_with_default_account_code( | ||
target_account_id, | ||
target_pub_key.clone(), | ||
Some(non_fungible_asset), | ||
); | ||
|
||
// Create the note | ||
let aswap_script = Script::SWAP { | ||
asset: non_fungible_asset, | ||
serial_num: [Felt::new(6), Felt::new(7), Felt::new(8), Felt::new(9)], | ||
}; | ||
|
||
let note = create_note( | ||
aswap_script, | ||
vec![fungible_asset], | ||
sender_account_id, | ||
None, | ||
[Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)], | ||
) | ||
.unwrap(); | ||
|
||
// CONSTRUCT AND EXECUTE TX (Success) | ||
// -------------------------------------------------------------------------------------------- | ||
let data_store = | ||
MockDataStore::with_existing(Some(target_account.clone()), Some(vec![note.clone()]), None); | ||
|
||
let mut executor = TransactionExecutor::new(data_store.clone()); | ||
executor.load_account(target_account_id).unwrap(); | ||
|
||
let block_ref = data_store.block_header.block_num(); | ||
let note_origins = | ||
data_store.notes.iter().map(|note| note.origin().clone()).collect::<Vec<_>>(); | ||
|
||
let tx_script_code = ProgramAst::parse( | ||
format!( | ||
" | ||
use.miden::auth::basic->auth_tx | ||
begin | ||
call.auth_tx::auth_tx_rpo_falcon512 | ||
end | ||
" | ||
) | ||
.as_str(), | ||
) | ||
.unwrap(); | ||
let tx_script_target = executor | ||
.compile_tx_script(tx_script_code.clone(), vec![(target_pub_key, target_sk_felt)], vec![]) | ||
.unwrap(); | ||
|
||
// Execute the transaction | ||
let transaction_result = executor | ||
.execute_transaction(target_account_id, block_ref, ¬e_origins, Some(tx_script_target)) | ||
.unwrap(); | ||
|
||
// target account vault delta | ||
let target_account_after: Account = Account::new( | ||
target_account.id(), | ||
AccountVault::new(&vec![fungible_asset]).unwrap(), | ||
target_account.storage().clone(), | ||
target_account.code().clone(), | ||
Felt::new(2), | ||
); | ||
|
||
// Check that the target account has received the asset from the note | ||
assert!(transaction_result.final_account_hash() == target_account_after.hash()); | ||
|
||
// Check if only one `Note` has been created | ||
assert!(transaction_result.created_notes().notes().len() == 1); | ||
|
||
// Check if the created `Note` is what we expect | ||
let recipient = Digest::new([ | ||
Felt::new(403044469077705077), | ||
Felt::new(5814218301633521607), | ||
Felt::new(3036312160134047413), | ||
Felt::new(9100684949500007517), | ||
]); | ||
|
||
let note_metadata = | ||
NoteMetadata::new(target_account_id, sender_account_id.into(), Felt::new(1)); | ||
|
||
let note_vault = NoteVault::new(&[non_fungible_asset]).unwrap(); | ||
|
||
let requested_note = NoteStub::new(recipient, note_vault, note_metadata).unwrap(); | ||
|
||
let created_note = &transaction_result.created_notes().notes()[0]; | ||
|
||
assert!(created_note == &requested_note); | ||
} |