mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-08-26 20:01:16 +00:00
* feat(lee): store deployed programs as Account-shaped state, keyed by AccountId Program-as-Account migration, first slice: V03State.programs becomes HashMap<AccountId, Account> instead of HashMap<ProgramId, Program>, with the elf held directly in Account.data. The map key is derived from ProgramId via a new 1:1 From<ProgramId> for AccountId conversion (both types are exactly 32 bytes) rather than a hash, since ProgramId is already content-derived from the elf. Account.program_owner stays ProgramId-typed everywhere - this only changes how deployed programs are stored and looked up host-side, not the dispatch/authorization model any guest program logic depends on. Dispatch resolves a ChainedCall's program_id by converting to AccountId, fetching the Account, and reconstructing a Program via new_unchecked for execution. DATA_MAX_LENGTH is raised from 100 KiB to 700 KiB to fit real program elfs (observed 375 KB-631 KB) directly in Account.data; noted in its docstring as a rough placeholder pending real transaction/block-size budget analysis. * fix(lee): store deployed programs as Account-shaped state, correct SeenShard cap Corrects lee/state_machine internals for the Program-as-Account migration and fixes SeenShard::MAX_DELIVERIES, which was still calibrated for the old 100 KiB DATA_MAX_LENGTH instead of the current 700 KiB cap. Rebuilds program artifacts and the sequencer test fixture to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * address PR #720 review nits - Use FIXME instead of TODO for the temporary ProgramId->AccountId conversion, per review convention for patches guaranteed to be fixed later. - Derive cross_zone_inbox's MAX_DELIVERIES from DATA_MAX_LENGTH instead of a hand-recomputed literal, so it stays in sync automatically the next time the cap changes. * feat(lee): migrate Account.program_owner from ProgramId to AccountId Account.program_owner is now AccountId-typed instead of ProgramId, via a new bijective From<ProgramId> for AccountId / From<AccountId> for ProgramId conversion pair (pure byte reinterpretation, not a hash - both types are exactly 32 bytes). Adds DEFAULT_PROGRAM_OWNER as the AccountId-typed counterpart to DEFAULT_PROGRAM_ID, used at every program_owner comparison/claim site instead of an inline AccountId::default(). Touches every call site across lee_core, lee (including the guest-side privacy-preserving circuit), all 16 deployed guest programs, wallet/wallet-ffi, indexer_ffi/indexer_service/ indexer_service_protocol, sequencer_core, testnet_initial_state, system_accounts, cross_zone, storage, cycle_bench, and integration_tests - mostly mechanical .into() conversions, plus two simplifications: wallet's manual base58 encode/decode of program_owner was dead code once it's AccountId (which already has Display/FromStr), and the FFI crates' program_owner field now reuses the existing generic FfiBytes32 wrapper instead of the now-unused FfiProgramId one. Rebuilds every guest ELF artifact and the prebuilt sequencer test fixture via just build-artifacts, since execute_and_prove runs against the checked-in precompiled privacy_preserving_circuit.bin, which isn't rebuilt automatically by cargo test/check. * chore(lee): rebuild artifacts after rebase, drop unused base58 dep Rebases marvin/program-as-account-2 onto the updated marvin/program-as-account (SeenShard cap fix), regenerating program and circuit artifacts plus the sequencer test fixture to match. Also removes lez/wallet's now-unused base58 dependency, dead since AccountId gained its own Display/FromStr base58 encoding. * docs(lee): trim DEFAULT_PROGRAM_OWNER and From<AccountId> for ProgramId docs * test(lee): add known-answer tests for ProgramId/AccountId conversion, rebuild artifacts * fix(lee): apply program_owner AccountId migration to code added after rebase dev grew new program_owner call sites (sequencer_stake genesis/config handling, committee_discovery, a new selective_pda_delegator test program, and related tests) after this branch's ProgramId->AccountId migration commit was originally written, so they predated the .into() sweep and didn't conflict during the rebase - they just still assumed the old ProgramId-typed field. Converts all of them, fixes a stray unseparated hex literal clippy caught along the way, and rebuilds artifacts against the fixed source. * chore(lee): regenerate test fixture after rebasing onto dev --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1049 lines
34 KiB
Rust
1049 lines
34 KiB
Rust
#![cfg(test)]
|
|
#![expect(
|
|
clippy::shadow_unrelated,
|
|
clippy::arithmetic_side_effects,
|
|
reason = "We don't care about it in tests"
|
|
)]
|
|
|
|
use lee_core::{
|
|
account::{Account, AccountId, AccountWithMetadata, Data},
|
|
program::Claim,
|
|
};
|
|
use token_core::{
|
|
MetadataStandard, NewTokenDefinition, NewTokenMetadata, TokenDefinition, TokenHolding,
|
|
};
|
|
|
|
use crate::{
|
|
burn::burn,
|
|
mint::mint,
|
|
new_definition::{new_definition_with_metadata, new_fungible_definition},
|
|
print_nft::print_nft,
|
|
transfer::transfer,
|
|
};
|
|
|
|
// TODO: Move tests to a proper modules like burn, mint, transfer, etc, so that they are more
|
|
// unit-test.
|
|
|
|
struct BalanceForTests;
|
|
struct IdForTests;
|
|
|
|
struct AccountForTests;
|
|
|
|
impl AccountForTests {
|
|
fn definition_account_auth() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: BalanceForTests::init_supply(),
|
|
metadata_id: None,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn definition_account_without_auth() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: BalanceForTests::init_supply(),
|
|
metadata_id: None,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: false,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_different_definition() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id_diff(),
|
|
balance: BalanceForTests::holding_balance(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_same_definition_with_authorization() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::holding_balance(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_same_definition_without_authorization() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::holding_balance(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: false,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_same_definition_without_authorization_overflow() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::init_supply(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: false,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn definition_account_post_burn() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: BalanceForTests::init_supply_burned(),
|
|
metadata_id: None,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_post_burn() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::holding_balance_burned(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: false,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_uninit() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: false,
|
|
account_id: IdForTests::holding_id_2(),
|
|
}
|
|
}
|
|
|
|
fn init_mint() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [0_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::mint_success(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: false,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_same_definition_mint() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::holding_balance_mint(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn definition_account_mint() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: BalanceForTests::init_supply_mint(),
|
|
metadata_id: None,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_same_definition_with_authorization_and_large_balance() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::mint_overflow(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn definition_account_with_authorization_nonfungible() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenDefinition::NonFungible {
|
|
name: String::from("test"),
|
|
printable_supply: BalanceForTests::printable_copies(),
|
|
metadata_id: AccountId::new([0; 32]),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn definition_account_uninit() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: false,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_init() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::init_supply(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn definition_account_unclaimed() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [0_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: BalanceForTests::init_supply(),
|
|
metadata_id: None,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::pool_definition_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_unclaimed() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [0_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::init_supply(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account2_init() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::init_supply(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id_2(),
|
|
}
|
|
}
|
|
|
|
fn holding_account2_init_post_transfer() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::recipient_post_transfer(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id_2(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_init_post_transfer() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::Fungible {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
balance: BalanceForTests::sender_post_transfer(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_master_nft() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::NftMaster {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
print_balance: BalanceForTests::printable_copies(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_master_nft_insufficient_balance() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::NftMaster {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
print_balance: 1,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_master_nft_after_print() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::NftMaster {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
print_balance: BalanceForTests::printable_copies() - 1,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_printed_nft() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [0_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::NftPrintedCopy {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
owned: true,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: false,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_with_master_nft_transferred_to() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [0_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::NftMaster {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
print_balance: BalanceForTests::printable_copies(),
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id_2(),
|
|
}
|
|
}
|
|
|
|
fn holding_account_master_nft_post_transfer() -> AccountWithMetadata {
|
|
AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [5_u32; 8].into(),
|
|
balance: 0_u128,
|
|
data: Data::from(&TokenHolding::NftMaster {
|
|
definition_id: IdForTests::pool_definition_id(),
|
|
print_balance: 0,
|
|
}),
|
|
nonce: 0_u128.into(),
|
|
},
|
|
is_authorized: true,
|
|
account_id: IdForTests::holding_id(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BalanceForTests {
|
|
fn init_supply() -> u128 {
|
|
100_000
|
|
}
|
|
|
|
fn holding_balance() -> u128 {
|
|
1_000
|
|
}
|
|
|
|
fn init_supply_burned() -> u128 {
|
|
99_500
|
|
}
|
|
|
|
fn holding_balance_burned() -> u128 {
|
|
500
|
|
}
|
|
|
|
fn burn_success() -> u128 {
|
|
500
|
|
}
|
|
|
|
fn burn_insufficient() -> u128 {
|
|
1_500
|
|
}
|
|
|
|
fn mint_success() -> u128 {
|
|
50_000
|
|
}
|
|
|
|
fn holding_balance_mint() -> u128 {
|
|
51_000
|
|
}
|
|
|
|
fn mint_overflow() -> u128 {
|
|
u128::MAX - 40_000
|
|
}
|
|
|
|
fn init_supply_mint() -> u128 {
|
|
150_000
|
|
}
|
|
|
|
fn sender_post_transfer() -> u128 {
|
|
95_000
|
|
}
|
|
|
|
fn recipient_post_transfer() -> u128 {
|
|
105_000
|
|
}
|
|
|
|
fn transfer_amount() -> u128 {
|
|
5_000
|
|
}
|
|
|
|
fn printable_copies() -> u128 {
|
|
10
|
|
}
|
|
}
|
|
|
|
impl IdForTests {
|
|
fn pool_definition_id() -> AccountId {
|
|
AccountId::new([15; 32])
|
|
}
|
|
|
|
fn pool_definition_id_diff() -> AccountId {
|
|
AccountId::new([16; 32])
|
|
}
|
|
|
|
fn holding_id() -> AccountId {
|
|
AccountId::new([17; 32])
|
|
}
|
|
|
|
fn holding_id_2() -> AccountId {
|
|
AccountId::new([42; 32])
|
|
}
|
|
}
|
|
|
|
#[should_panic(expected = "Definition target account must have default values")]
|
|
#[test]
|
|
fn new_definition_non_default_first_account_should_fail() {
|
|
let definition_account = AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [1, 2, 3, 4, 5, 6, 7, 8].into(),
|
|
..Account::default()
|
|
},
|
|
is_authorized: true,
|
|
account_id: AccountId::new([1; 32]),
|
|
};
|
|
let holding_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([2; 32]),
|
|
};
|
|
let _post_states = new_fungible_definition(
|
|
definition_account,
|
|
holding_account,
|
|
String::from("test"),
|
|
10,
|
|
);
|
|
}
|
|
|
|
#[should_panic(expected = "Holding target account must have default values")]
|
|
#[test]
|
|
fn new_definition_non_default_second_account_should_fail() {
|
|
let definition_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([1; 32]),
|
|
};
|
|
let holding_account = AccountWithMetadata {
|
|
account: Account {
|
|
program_owner: [1, 2, 3, 4, 5, 6, 7, 8].into(),
|
|
..Account::default()
|
|
},
|
|
is_authorized: true,
|
|
account_id: AccountId::new([2; 32]),
|
|
};
|
|
let _post_states = new_fungible_definition(
|
|
definition_account,
|
|
holding_account,
|
|
String::from("test"),
|
|
10,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn new_definition_with_valid_inputs_succeeds() {
|
|
let definition_account = AccountForTests::definition_account_uninit();
|
|
let holding_account = AccountForTests::holding_account_uninit();
|
|
|
|
let post_states = new_fungible_definition(
|
|
definition_account,
|
|
holding_account,
|
|
String::from("test"),
|
|
BalanceForTests::init_supply(),
|
|
);
|
|
|
|
let [definition_account, holding_account] = post_states.try_into().unwrap();
|
|
assert_eq!(
|
|
*definition_account.account(),
|
|
AccountForTests::definition_account_unclaimed().account
|
|
);
|
|
|
|
assert_eq!(
|
|
*holding_account.account(),
|
|
AccountForTests::holding_account_unclaimed().account
|
|
);
|
|
}
|
|
|
|
#[should_panic(expected = "Sender and recipient definition id mismatch")]
|
|
#[test]
|
|
fn transfer_with_different_definition_ids_should_fail() {
|
|
let sender = AccountForTests::holding_same_definition_with_authorization();
|
|
let recipient = AccountForTests::holding_different_definition();
|
|
let _post_states = transfer(sender, recipient, 10);
|
|
}
|
|
|
|
#[should_panic(expected = "Insufficient balance")]
|
|
#[test]
|
|
fn transfer_with_insufficient_balance_should_fail() {
|
|
let sender = AccountForTests::holding_same_definition_with_authorization();
|
|
let recipient = AccountForTests::holding_account_same_definition_mint();
|
|
// Attempt to transfer more than balance
|
|
let _post_states = transfer(sender, recipient, BalanceForTests::burn_insufficient());
|
|
}
|
|
|
|
#[should_panic(expected = "Sender authorization is missing")]
|
|
#[test]
|
|
fn transfer_without_sender_authorization_should_fail() {
|
|
let sender = AccountForTests::holding_same_definition_without_authorization();
|
|
let recipient = AccountForTests::holding_account_uninit();
|
|
let _post_states = transfer(sender, recipient, 37);
|
|
}
|
|
|
|
#[test]
|
|
fn transfer_with_valid_inputs_succeeds() {
|
|
let sender = AccountForTests::holding_account_init();
|
|
let recipient = AccountForTests::holding_account2_init();
|
|
let post_states = transfer(sender, recipient, BalanceForTests::transfer_amount());
|
|
let [sender_post, recipient_post] = post_states.try_into().unwrap();
|
|
|
|
assert_eq!(
|
|
*sender_post.account(),
|
|
AccountForTests::holding_account_init_post_transfer().account
|
|
);
|
|
assert_eq!(
|
|
*recipient_post.account(),
|
|
AccountForTests::holding_account2_init_post_transfer().account
|
|
);
|
|
}
|
|
|
|
#[should_panic(expected = "Invalid balance for NFT Master transfer")]
|
|
#[test]
|
|
fn transfer_with_master_nft_invalid_balance() {
|
|
let sender = AccountForTests::holding_account_master_nft();
|
|
let recipient = AccountForTests::holding_account_uninit();
|
|
let _post_states = transfer(sender, recipient, BalanceForTests::transfer_amount());
|
|
}
|
|
|
|
#[should_panic(expected = "Invalid balance in recipient account for NFT transfer")]
|
|
#[test]
|
|
fn transfer_with_master_nft_invalid_recipient_balance() {
|
|
let sender = AccountForTests::holding_account_master_nft();
|
|
let recipient = AccountForTests::holding_account_with_master_nft_transferred_to();
|
|
let _post_states = transfer(sender, recipient, BalanceForTests::printable_copies());
|
|
}
|
|
|
|
#[test]
|
|
fn transfer_with_master_nft_success() {
|
|
let sender = AccountForTests::holding_account_master_nft();
|
|
let recipient = AccountForTests::holding_account_uninit();
|
|
let post_states = transfer(sender, recipient, BalanceForTests::printable_copies());
|
|
let [sender_post, recipient_post] = post_states.try_into().unwrap();
|
|
|
|
assert_eq!(
|
|
*sender_post.account(),
|
|
AccountForTests::holding_account_master_nft_post_transfer().account
|
|
);
|
|
assert_eq!(
|
|
*recipient_post.account(),
|
|
AccountForTests::holding_account_with_master_nft_transferred_to().account
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn token_initialize_account_succeeds() {
|
|
let sender = AccountForTests::holding_account_init();
|
|
let recipient = AccountForTests::holding_account2_init();
|
|
let post_states = transfer(sender, recipient, BalanceForTests::transfer_amount());
|
|
let [sender_post, recipient_post] = post_states.try_into().unwrap();
|
|
|
|
assert_eq!(
|
|
*sender_post.account(),
|
|
AccountForTests::holding_account_init_post_transfer().account
|
|
);
|
|
assert_eq!(
|
|
*recipient_post.account(),
|
|
AccountForTests::holding_account2_init_post_transfer().account
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Mismatch Token Definition and Token Holding")]
|
|
fn burn_mismatch_def() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_different_definition();
|
|
let _post_states = burn(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::burn_success(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Authorization is missing")]
|
|
fn burn_missing_authorization() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_same_definition_without_authorization();
|
|
let _post_states = burn(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::burn_success(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Insufficient balance to burn")]
|
|
fn burn_insufficient_balance() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_same_definition_with_authorization();
|
|
let _post_states = burn(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::burn_insufficient(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Total supply underflow")]
|
|
fn burn_total_supply_underflow() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account =
|
|
AccountForTests::holding_same_definition_with_authorization_and_large_balance();
|
|
let _post_states = burn(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_overflow(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn burn_success() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_same_definition_with_authorization();
|
|
let post_states = burn(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::burn_success(),
|
|
);
|
|
|
|
let [def_post, holding_post] = post_states.try_into().unwrap();
|
|
|
|
assert_eq!(
|
|
*def_post.account(),
|
|
AccountForTests::definition_account_post_burn().account
|
|
);
|
|
assert_eq!(
|
|
*holding_post.account(),
|
|
AccountForTests::holding_account_post_burn().account
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Holding account must be valid")]
|
|
fn mint_not_valid_holding_account() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::definition_account_without_auth();
|
|
let _post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_success(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Definition account must be valid")]
|
|
fn mint_not_valid_definition_account() {
|
|
let definition_account = AccountForTests::holding_same_definition_with_authorization();
|
|
let holding_account = AccountForTests::holding_same_definition_without_authorization();
|
|
let _post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_success(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Definition authorization is missing")]
|
|
fn mint_missing_authorization() {
|
|
let definition_account = AccountForTests::definition_account_without_auth();
|
|
let holding_account = AccountForTests::holding_same_definition_without_authorization();
|
|
let _post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_success(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Mismatch Token Definition and Token Holding")]
|
|
fn mint_mismatched_token_definition() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_different_definition();
|
|
let _post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_success(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn mint_success() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_same_definition_without_authorization();
|
|
let post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_success(),
|
|
);
|
|
|
|
let [def_post, holding_post] = post_states.try_into().unwrap();
|
|
|
|
assert_eq!(
|
|
*def_post.account(),
|
|
AccountForTests::definition_account_mint().account
|
|
);
|
|
assert_eq!(
|
|
*holding_post.account(),
|
|
AccountForTests::holding_account_same_definition_mint().account
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn mint_uninit_holding_success() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_account_uninit();
|
|
let post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_success(),
|
|
);
|
|
|
|
let [def_post, holding_post] = post_states.try_into().unwrap();
|
|
|
|
assert_eq!(
|
|
*def_post.account(),
|
|
AccountForTests::definition_account_mint().account
|
|
);
|
|
assert_eq!(
|
|
*holding_post.account(),
|
|
AccountForTests::init_mint().account
|
|
);
|
|
assert_eq!(holding_post.required_claim(), Some(Claim::Authorized));
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Total supply overflow")]
|
|
fn mint_total_supply_overflow() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_same_definition_without_authorization();
|
|
let _post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_overflow(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Balance overflow on minting")]
|
|
fn mint_holding_account_overflow() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let holding_account = AccountForTests::holding_same_definition_without_authorization_overflow();
|
|
let _post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_overflow(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Cannot mint additional supply for Non-Fungible Tokens")]
|
|
fn mint_cannot_mint_unmintable_tokens() {
|
|
let definition_account = AccountForTests::definition_account_with_authorization_nonfungible();
|
|
let holding_account = AccountForTests::holding_account_master_nft();
|
|
let _post_states = mint(
|
|
definition_account,
|
|
holding_account,
|
|
BalanceForTests::mint_success(),
|
|
);
|
|
}
|
|
|
|
#[should_panic(expected = "Definition target account must have default values")]
|
|
#[test]
|
|
fn call_new_definition_metadata_with_init_definition() {
|
|
let definition_account = AccountForTests::definition_account_auth();
|
|
let metadata_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([2; 32]),
|
|
};
|
|
let holding_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([3; 32]),
|
|
};
|
|
let new_definition = NewTokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: 15_u128,
|
|
};
|
|
let metadata = NewTokenMetadata {
|
|
standard: MetadataStandard::Simple,
|
|
uri: "test_uri".to_owned(),
|
|
creators: "test_creators".to_owned(),
|
|
};
|
|
let _post_states = new_definition_with_metadata(
|
|
definition_account,
|
|
metadata_account,
|
|
holding_account,
|
|
new_definition,
|
|
metadata,
|
|
);
|
|
}
|
|
|
|
#[should_panic(expected = "Metadata target account must have default values")]
|
|
#[test]
|
|
fn call_new_definition_metadata_with_init_metadata() {
|
|
let definition_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([1; 32]),
|
|
};
|
|
let holding_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([3; 32]),
|
|
};
|
|
let metadata_account = AccountForTests::holding_account_same_definition_mint();
|
|
let new_definition = NewTokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: 15_u128,
|
|
};
|
|
let metadata = NewTokenMetadata {
|
|
standard: MetadataStandard::Simple,
|
|
uri: "test_uri".to_owned(),
|
|
creators: "test_creators".to_owned(),
|
|
};
|
|
let _post_states = new_definition_with_metadata(
|
|
definition_account,
|
|
holding_account,
|
|
metadata_account,
|
|
new_definition,
|
|
metadata,
|
|
);
|
|
}
|
|
|
|
#[should_panic(expected = "Holding target account must have default values")]
|
|
#[test]
|
|
fn call_new_definition_metadata_with_init_holding() {
|
|
let definition_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([1; 32]),
|
|
};
|
|
let metadata_account = AccountWithMetadata {
|
|
account: Account::default(),
|
|
is_authorized: true,
|
|
account_id: AccountId::new([2; 32]),
|
|
};
|
|
let holding_account = AccountForTests::holding_account_same_definition_mint();
|
|
let new_definition = NewTokenDefinition::Fungible {
|
|
name: String::from("test"),
|
|
total_supply: 15_u128,
|
|
};
|
|
let metadata = NewTokenMetadata {
|
|
standard: MetadataStandard::Simple,
|
|
uri: "test_uri".to_owned(),
|
|
creators: "test_creators".to_owned(),
|
|
};
|
|
let _post_states = new_definition_with_metadata(
|
|
definition_account,
|
|
holding_account,
|
|
metadata_account,
|
|
new_definition,
|
|
metadata,
|
|
);
|
|
}
|
|
|
|
#[should_panic(expected = "Master NFT Account must be authorized")]
|
|
#[test]
|
|
fn print_nft_master_account_must_be_authorized() {
|
|
let master_account = AccountForTests::holding_account_uninit();
|
|
let printed_account = AccountForTests::holding_account_uninit();
|
|
let _post_states = print_nft(master_account, printed_account);
|
|
}
|
|
|
|
#[should_panic(expected = "Printed Account must be uninitialized")]
|
|
#[test]
|
|
fn print_nft_print_account_initialized() {
|
|
let master_account = AccountForTests::holding_account_master_nft();
|
|
let printed_account = AccountForTests::holding_account_init();
|
|
let _post_states = print_nft(master_account, printed_account);
|
|
}
|
|
|
|
#[should_panic(expected = "Invalid Token Holding data")]
|
|
#[test]
|
|
fn print_nft_master_nft_invalid_token_holding() {
|
|
let master_account = AccountForTests::definition_account_auth();
|
|
let printed_account = AccountForTests::holding_account_uninit();
|
|
let _post_states = print_nft(master_account, printed_account);
|
|
}
|
|
|
|
#[should_panic(expected = "Invalid Token Holding provided as NFT Master Account")]
|
|
#[test]
|
|
fn print_nft_master_nft_not_nft_master_account() {
|
|
let master_account = AccountForTests::holding_account_init();
|
|
let printed_account = AccountForTests::holding_account_uninit();
|
|
let _post_states = print_nft(master_account, printed_account);
|
|
}
|
|
|
|
#[should_panic(expected = "Insufficient balance to print another NFT copy")]
|
|
#[test]
|
|
fn print_nft_master_nft_insufficient_balance() {
|
|
let master_account = AccountForTests::holding_account_master_nft_insufficient_balance();
|
|
let printed_account = AccountForTests::holding_account_uninit();
|
|
let _post_states = print_nft(master_account, printed_account);
|
|
}
|
|
|
|
#[test]
|
|
fn print_nft_success() {
|
|
let master_account = AccountForTests::holding_account_master_nft();
|
|
let printed_account = AccountForTests::holding_account_uninit();
|
|
let post_states = print_nft(master_account, printed_account);
|
|
|
|
let [post_master_nft, post_printed] = post_states.try_into().unwrap();
|
|
|
|
assert_eq!(
|
|
*post_master_nft.account(),
|
|
AccountForTests::holding_account_master_nft_after_print().account
|
|
);
|
|
assert_eq!(
|
|
*post_printed.account(),
|
|
AccountForTests::holding_account_printed_nft().account
|
|
);
|
|
}
|