diff --git a/contracts/commitment_core/Cargo.toml b/contracts/commitment_core/Cargo.toml index df7c3ab7..4b8efaee 100644 --- a/contracts/commitment_core/Cargo.toml +++ b/contracts/commitment_core/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["cdylib", "rlib"] [features] testutils = ["soroban-sdk/testutils"] benchmark = [] +fuzzing = [] default = [] [dependencies] @@ -17,4 +18,3 @@ shared_utils = { path = "../shared_utils" } [dev-dependencies] soroban-sdk = { version = "21.0.0", features = ["testutils"] } - diff --git a/contracts/commitment_core/src/fee_tests.rs b/contracts/commitment_core/src/fee_tests.rs index e47a6420..233f9aba 100644 --- a/contracts/commitment_core/src/fee_tests.rs +++ b/contracts/commitment_core/src/fee_tests.rs @@ -11,13 +11,47 @@ use crate::{CommitmentCoreContract, CommitmentCoreContractClient, CommitmentRules}; use soroban_sdk::{ - testutils::{Address as _, AuthorizedFunction, AuthorizedInvocation}, - token, Address, Env, IntoVal, String, Symbol, + contract, contractimpl, + testutils::{Address as _, Ledger}, + token, Address, Env, String, }; -fn create_token_contract<'a>(e: &Env, admin: &Address) -> (Address, token::Client<'a>) { - let addr = e.register_stellar_asset_contract(admin.clone()); - (addr.clone(), token::Client::new(e, &addr)) +#[contract] +struct FeeMockNftContract; + +#[contractimpl] +impl FeeMockNftContract { + pub fn mint( + _e: Env, + _caller: Address, + _owner: Address, + _commitment_id: String, + _duration_days: u32, + _max_loss_percent: u32, + _commitment_type: String, + _initial_amount: i128, + _asset_address: Address, + _early_exit_penalty: u32, + ) -> u32 { + 1 + } + + pub fn settle(_e: Env, _caller: Address, _token_id: u32) {} + + pub fn mark_inactive(_e: Env, _caller: Address, _token_id: u32) {} +} + +fn create_token_contract<'a>( + e: &Env, + admin: &Address, +) -> (Address, token::Client<'a>, token::StellarAssetClient<'a>) { + let token_contract = e.register_stellar_asset_contract_v2(admin.clone()); + let addr = token_contract.address(); + ( + addr.clone(), + token::Client::new(e, &addr), + token::StellarAssetClient::new(e, &addr), + ) } fn setup_test() -> ( @@ -33,12 +67,12 @@ fn setup_test() -> ( e.mock_all_auths(); let admin = Address::generate(&e); - let nft_contract = Address::generate(&e); + let nft_contract = e.register_contract(None, FeeMockNftContract); let user = Address::generate(&e); - let (token_address, token_client) = create_token_contract(&e, &admin); + let (token_address, token_client, token_admin_client) = create_token_contract(&e, &admin); // Mint tokens to user - token_client.mint(&user, &10_000_000); + token_admin_client.mint(&user, &10_000_000); let contract_id = e.register_contract(None, CommitmentCoreContract); let client = CommitmentCoreContractClient::new(&e, &contract_id); @@ -221,12 +255,13 @@ fn test_early_exit_penalty_retained_as_fee() { let expected_penalty = 100_000i128; // 10% of 1,000,000 let expected_returned = amount - expected_penalty; + let expected_user_balance = 10_000_000i128 - amount + expected_returned; // Verify penalty was added to collected fees assert_eq!(client.get_collected_fees(&token_address), expected_penalty); // Verify user received net amount - assert_eq!(token_client.balance(&user), expected_returned); + assert_eq!(token_client.balance(&user), expected_user_balance); } #[test] @@ -251,12 +286,13 @@ fn test_early_exit_with_creation_fee_and_penalty() { let exit_penalty = 99_000i128; // 10% of 990,000 let expected_returned = net_amount - exit_penalty; let total_fees = creation_fee + exit_penalty; + let expected_user_balance = 10_000_000i128 - amount + expected_returned; // Verify both fees were collected assert_eq!(client.get_collected_fees(&token_address), total_fees); // Verify user received correct amount - assert_eq!(token_client.balance(&user), expected_returned); + assert_eq!(token_client.balance(&user), expected_user_balance); } // ============================================================================ @@ -442,11 +478,11 @@ fn test_get_collected_fees_multiple_assets() { let (e, admin, _, user, _, _, client) = setup_test(); // Create two different tokens - let (token1, token1_client) = create_token_contract(&e, &admin); - let (token2, token2_client) = create_token_contract(&e, &admin); + let (token1, _token1_client, token1_admin_client) = create_token_contract(&e, &admin); + let (token2, _token2_client, token2_admin_client) = create_token_contract(&e, &admin); - token1_client.mint(&user, &10_000_000); - token2_client.mint(&user, &10_000_000); + token1_admin_client.mint(&user, &10_000_000); + token2_admin_client.mint(&user, &10_000_000); // Set creation fee client.set_creation_fee_bps(&admin, &100); @@ -476,21 +512,22 @@ fn test_fee_collection_with_settle() { let amount = 1_000_000i128; let creation_fee = 10_000i128; let net_amount = amount - creation_fee; + let expected_user_balance = 10_000_000i128 - amount + net_amount; - let mut rules = default_rules(&e); - rules.duration_days = 0; // Expires immediately + let rules = default_rules(&e); let commitment_id = client.create_commitment(&user, &amount, &token_address, &rules); // Settle commitment - e.ledger().with_mut(|li| li.timestamp = li.timestamp + 1); + e.ledger() + .with_mut(|li| li.timestamp = li.timestamp + (rules.duration_days as u64 * 86_400) + 1); client.settle(&commitment_id); // Verify creation fee still collected assert_eq!(client.get_collected_fees(&token_address), creation_fee); // Verify user got back net amount - assert_eq!(token_client.balance(&user), net_amount); + assert_eq!(token_client.balance(&user), expected_user_balance); } #[test] diff --git a/contracts/commitment_core/src/fuzz_tests.rs b/contracts/commitment_core/src/fuzz_tests.rs new file mode 100644 index 00000000..e3a00ef9 --- /dev/null +++ b/contracts/commitment_core/src/fuzz_tests.rs @@ -0,0 +1,141 @@ +#![cfg(test)] + +use crate::{ + fuzzing::{ + classify_generated_commitment_id_bytes, observe_amount, observe_commitment_input, + AmountShape, CommitmentIdShape, + }, + CommitmentCoreContract, CommitmentCoreContractClient, CommitmentRules, +}; +use soroban_sdk::{ + contract, contractimpl, + testutils::Address as _, + token::StellarAssetClient, + Address, Env, String, +}; + +#[contract] +struct FuzzMockNftContract; + +#[contractimpl] +impl FuzzMockNftContract { + pub fn mint( + _e: Env, + _caller: Address, + _owner: Address, + _commitment_id: String, + _duration_days: u32, + _max_loss_percent: u32, + _commitment_type: String, + _initial_amount: i128, + _asset_address: Address, + _early_exit_penalty: u32, + ) -> u32 { + 1 + } + + pub fn settle(_e: Env, _caller: Address, _token_id: u32) {} + + pub fn mark_inactive(_e: Env, _caller: Address, _token_id: u32) {} +} + +fn default_rules(e: &Env) -> CommitmentRules { + CommitmentRules { + duration_days: 30, + max_loss_percent: 10, + commitment_type: String::from_str(e, "safe"), + early_exit_penalty: 15, + min_fee_threshold: 0, + grace_period_days: 0, + } +} + +#[test] +fn test_fuzz_commitment_id_seed_shapes() { + assert_eq!( + classify_generated_commitment_id_bytes(b""), + CommitmentIdShape::Empty + ); + assert_eq!( + classify_generated_commitment_id_bytes(b"user_supplied"), + CommitmentIdShape::InvalidPrefix + ); + assert_eq!( + classify_generated_commitment_id_bytes(b"c_"), + CommitmentIdShape::MissingDigits + ); + assert_eq!( + classify_generated_commitment_id_bytes(b"c_12x"), + CommitmentIdShape::NonDigitSuffix + ); + assert_eq!( + classify_generated_commitment_id_bytes(b"c_18446744073709551615"), + CommitmentIdShape::ValidGenerated + ); +} + +#[test] +fn test_fuzz_commitment_id_rejects_oversized_seed() { + let oversized = *b"c_1234567890123456789012345678901"; + assert_eq!( + classify_generated_commitment_id_bytes(&oversized), + CommitmentIdShape::TooLong + ); +} + +#[test] +fn test_fuzz_amount_seed_shapes() { + assert_eq!(observe_amount(0, 0).shape, AmountShape::NonPositive); + assert_eq!(observe_amount(-1, 0).shape, AmountShape::NonPositive); + assert_eq!(observe_amount(1, 10_001).shape, AmountShape::InvalidFeeBps); + assert_eq!(observe_amount(i128::MAX, 2).shape, AmountShape::FeeOverflow); + + let max_fee = observe_amount(1, 10_000); + assert_eq!(max_fee.shape, AmountShape::Valid); + assert_eq!(max_fee.fee, Some(1)); + assert_eq!(max_fee.net, Some(0)); + + let normal = observe_amount(1_000, 100); + assert_eq!(normal.shape, AmountShape::Valid); + assert_eq!(normal.fee, Some(10)); + assert_eq!(normal.net, Some(990)); +} + +#[test] +fn test_fuzz_observation_combines_id_and_amount_seed() { + let observation = observe_commitment_input(b"c_42", 1_000, 100); + assert_eq!(observation.id_shape, CommitmentIdShape::ValidGenerated); + assert_eq!(observation.amount.shape, AmountShape::Valid); + assert_eq!(observation.amount.fee, Some(10)); + assert_eq!(observation.amount.net, Some(990)); +} + +#[test] +fn test_create_commitment_rejects_fee_math_overflow() { + let e = Env::default(); + e.mock_all_auths_allowing_non_root_auth(); + + let contract_id = e.register_contract(None, CommitmentCoreContract); + let nft_contract = e.register_contract(None, FuzzMockNftContract); + let client = CommitmentCoreContractClient::new(&e, &contract_id); + + let admin = Address::generate(&e); + let owner = Address::generate(&e); + let token_admin = Address::generate(&e); + let amount = i128::MAX; + + let token_contract = e.register_stellar_asset_contract_v2(token_admin); + let asset_address = token_contract.address(); + let token_admin_client = StellarAssetClient::new(&e, &asset_address); + token_admin_client.mint(&owner, &amount); + + client.initialize(&admin, &nft_contract); + client.set_creation_fee_bps(&admin, &2); + + let result = client.try_create_commitment(&owner, &amount, &asset_address, &default_rules(&e)); + + assert!(result.is_err()); + assert_eq!(client.get_total_commitments(), 0); + assert_eq!(client.get_total_value_locked(), 0); + assert_eq!(client.get_collected_fees(&asset_address), 0); +} diff --git a/contracts/commitment_core/src/fuzzing.rs b/contracts/commitment_core/src/fuzzing.rs new file mode 100644 index 00000000..79f44c25 --- /dev/null +++ b/contracts/commitment_core/src/fuzzing.rs @@ -0,0 +1,125 @@ +//! No-std-friendly fuzz helper surfaces for `commitment_core`. +//! +//! These helpers are intentionally pure and allocation-free so a future host-side +//! fuzz target can feed arbitrary bytes and integers into them without needing a +//! Soroban `Env`. The contract tests in this crate use the same helpers as +//! deterministic seed cases. + +use shared_utils::fees::{BPS_MAX, BPS_SCALE}; + +const GENERATED_ID_PREFIX: &[u8] = b"c_"; +const MAX_COMMITMENT_ID_BYTES: usize = 32; + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum CommitmentIdShape { + Empty, + TooLong, + InvalidPrefix, + MissingDigits, + NonDigitSuffix, + ValidGenerated, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum AmountShape { + NonPositive, + InvalidFeeBps, + FeeOverflow, + NetUnderflow, + Valid, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct AmountObservation { + pub shape: AmountShape, + pub fee: Option, + pub net: Option, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct CommitmentInputObservation { + pub id_shape: CommitmentIdShape, + pub amount: AmountObservation, +} + +pub fn classify_generated_commitment_id_bytes(bytes: &[u8]) -> CommitmentIdShape { + if bytes.is_empty() { + return CommitmentIdShape::Empty; + } + + if bytes.len() > MAX_COMMITMENT_ID_BYTES { + return CommitmentIdShape::TooLong; + } + + if !bytes.starts_with(GENERATED_ID_PREFIX) { + return CommitmentIdShape::InvalidPrefix; + } + + let suffix = &bytes[GENERATED_ID_PREFIX.len()..]; + if suffix.is_empty() { + return CommitmentIdShape::MissingDigits; + } + + if suffix.iter().all(u8::is_ascii_digit) { + CommitmentIdShape::ValidGenerated + } else { + CommitmentIdShape::NonDigitSuffix + } +} + +pub fn checked_fee_from_bps(amount: i128, fee_bps: u32) -> Option { + if fee_bps > BPS_MAX { + return None; + } + + amount + .checked_mul(fee_bps as i128)? + .checked_div(BPS_SCALE as i128) +} + +pub fn observe_amount(amount: i128, fee_bps: u32) -> AmountObservation { + if amount <= 0 { + return AmountObservation { + shape: AmountShape::NonPositive, + fee: None, + net: None, + }; + } + + if fee_bps > BPS_MAX { + return AmountObservation { + shape: AmountShape::InvalidFeeBps, + fee: None, + net: None, + }; + } + + let Some(fee) = checked_fee_from_bps(amount, fee_bps) else { + return AmountObservation { + shape: AmountShape::FeeOverflow, + fee: None, + net: None, + }; + }; + + let Some(net) = amount.checked_sub(fee) else { + return AmountObservation { + shape: AmountShape::NetUnderflow, + fee: Some(fee), + net: None, + }; + }; + + AmountObservation { + shape: AmountShape::Valid, + fee: Some(fee), + net: Some(net), + } +} + +pub fn observe_commitment_input(commitment_id: &[u8], amount: i128, fee_bps: u32) -> CommitmentInputObservation { + CommitmentInputObservation { + id_shape: classify_generated_commitment_id_bytes(commitment_id), + amount: observe_amount(amount, fee_bps), + } +} diff --git a/contracts/commitment_core/src/lib.rs b/contracts/commitment_core/src/lib.rs index 95d6cf3a..653987f5 100644 --- a/contracts/commitment_core/src/lib.rs +++ b/contracts/commitment_core/src/lib.rs @@ -21,6 +21,8 @@ use soroban_sdk::{ IntoVal, String, Symbol, Vec, }; +pub mod fuzzing; + #[contracterror] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[repr(u32)] @@ -52,6 +54,8 @@ pub enum CommitmentError { FeeRecipientNotSet = 22, /// Insufficient collected fees to withdraw InsufficientFees = 23, + /// Arithmetic operation overflowed or underflowed + ArithmeticOverflow = 24, } impl CommitmentError { @@ -80,6 +84,7 @@ impl CommitmentError { CommitmentError::InvalidFeeBps => "Invalid fee basis points: must be 0-10000", CommitmentError::FeeRecipientNotSet => "Fee recipient not set; cannot withdraw", CommitmentError::InsufficientFees => "Insufficient collected fees to withdraw", + CommitmentError::ArithmeticOverflow => "Arithmetic overflow or underflow", } } } @@ -383,6 +388,21 @@ impl CommitmentCoreContract { Self::validate_rules(&e, &rules); check_sufficient_balance(&e, &owner, &asset_address, amount); + let creation_fee_bps: u32 = e + .storage() + .instance() + .get(&DataKey::CreationFeeBps) + .unwrap_or(0); + let creation_fee = fuzzing::checked_fee_from_bps(amount, creation_fee_bps) + .unwrap_or_else(|| { + set_reentrancy_guard(&e, false); + fail(&e, CommitmentError::ArithmeticOverflow, "create"); + }); + let net_amount = amount.checked_sub(creation_fee).unwrap_or_else(|| { + set_reentrancy_guard(&e, false); + fail(&e, CommitmentError::ArithmeticOverflow, "create"); + }); + let expires_at = TimeUtils::checked_calculate_expiration(&e, rules.duration_days) .unwrap_or_else(|| { set_reentrancy_guard(&e, false); fail(&e, CommitmentError::ExpirationOverflow, "create") }); @@ -420,7 +440,11 @@ impl CommitmentCoreContract { .instance() .get::<_, i128>(&DataKey::TotalValueLocked) .unwrap_or(0); - e.storage().instance().set(&DataKey::TotalValueLocked, &(tvl + net_amount)); + let updated_tvl = tvl.checked_add(net_amount).unwrap_or_else(|| { + set_reentrancy_guard(&e, false); + fail(&e, CommitmentError::ArithmeticOverflow, "create"); + }); + e.storage().instance().set(&DataKey::TotalValueLocked, &updated_tvl); let mut all_ids = e .storage() @@ -435,30 +459,19 @@ impl CommitmentCoreContract { let contract_address = e.current_contract_address(); transfer_assets(&e, &owner, &contract_address, &asset_address, amount); - // Collect creation fee if configured - let creation_fee_bps: u32 = e - .storage() - .instance() - .get(&DataKey::CreationFeeBps) - .unwrap_or(0); - let creation_fee = if creation_fee_bps > 0 { - fees::fee_from_bps(amount, creation_fee_bps) - } else { - 0 - }; - // Add creation fee to collected fees if creation_fee > 0 { let fee_key = DataKey::CollectedFees(asset_address.clone()); let current_fees: i128 = e.storage().instance().get(&fee_key).unwrap_or(0); + let updated_fees = current_fees.checked_add(creation_fee).unwrap_or_else(|| { + set_reentrancy_guard(&e, false); + fail(&e, CommitmentError::ArithmeticOverflow, "create"); + }); e.storage() .instance() - .set(&fee_key, &(current_fees + creation_fee)); + .set(&fee_key, &updated_fees); } - // Net amount locked in commitment (after fee deduction) - let net_amount = amount - creation_fee; - let nft_token_id = call_nft_mint( &e, &nft_contract, @@ -651,7 +664,11 @@ impl CommitmentCoreContract { set_commitment(&e, &commitment); let tvl = e.storage().instance().get::<_, i128>(&DataKey::TotalValueLocked).unwrap_or(0); - e.storage().instance().set(&DataKey::TotalValueLocked, &(tvl - old_value + new_value)); + let updated_tvl = tvl + .checked_sub(old_value) + .and_then(|value| value.checked_add(new_value)) + .unwrap_or_else(|| fail(&e, CommitmentError::ArithmeticOverflow, "upd")); + e.storage().instance().set(&DataKey::TotalValueLocked, &updated_tvl); } pub fn check_violations(e: Env, commitment_id: String) -> bool { @@ -1127,6 +1144,9 @@ mod emergency_tests; #[cfg(test)] mod fee_tests; +#[cfg(test)] +mod fuzz_tests; + #[cfg(all(test, feature = "benchmark"))] mod benchmarks; diff --git a/contracts/commitment_core/src/test_zero_address.rs b/contracts/commitment_core/src/test_zero_address.rs index 1ecd7991..fce70676 100644 --- a/contracts/commitment_core/src/test_zero_address.rs +++ b/contracts/commitment_core/src/test_zero_address.rs @@ -2,7 +2,10 @@ extern crate std; use crate::*; -use soroban_sdk::{Address, Env, String}; +use soroban_sdk::{ + testutils::Address as _, + Address, Env, String, +}; fn generate_zero_address(env: &Env) -> Address { Address::from_string(&String::from_str( @@ -27,10 +30,12 @@ fn test_create_commitment_zero_owner_fails() { // Corrected field names for the Commitlabs CommitmentRules struct let rules = CommitmentRules { - min_commitment_amount: 0, - max_commitment_amount: i128::MAX, - min_duration: 0, - max_duration: u64::MAX, + duration_days: 30, + max_loss_percent: 10, + commitment_type: String::from_str(&env, "safe"), + early_exit_penalty: 15, + min_fee_threshold: 0, + grace_period_days: 0, }; client.create_commitment(&zero_owner, &amount, &asset_address, &rules); diff --git a/contracts/commitment_core/src/tests.rs b/contracts/commitment_core/src/tests.rs index ff6c11c3..ca2e34d5 100644 --- a/contracts/commitment_core/src/tests.rs +++ b/contracts/commitment_core/src/tests.rs @@ -102,9 +102,14 @@ fn test_create_commitment_i128_max() { e.mock_all_auths(); let contract_id = e.register_contract(None, CommitmentCoreContract); let admin = Address::generate(&e); - let nft_contract = Address::generate(&e); + let nft_contract = e.register_contract(None, MockNftContract); let owner = Address::generate(&e); - let asset_address = Address::generate(&e); + let token_admin = Address::generate(&e); + + let token_contract = e.register_stellar_asset_contract_v2(token_admin); + let asset_address = token_contract.address(); + let token_admin_client = StellarAssetClient::new(&e, &asset_address); + token_admin_client.mint(&owner, &1000); e.as_contract(&contract_id, || { CommitmentCoreContract::initialize(e.clone(), admin.clone(), nft_contract.clone()); @@ -587,9 +592,13 @@ fn test_create_commitment_expiration_overflow() { let contract_id = e.register_contract(None, CommitmentCoreContract); let admin = Address::generate(&e); - let nft_contract = Address::generate(&e); + let nft_contract = e.register_contract(None, MockNftContract); let owner = Address::generate(&e); - let asset_address = Address::generate(&e); + let token_admin = Address::generate(&e); + let token_contract = e.register_stellar_asset_contract_v2(token_admin); + let asset_address = token_contract.address(); + let token_admin_client = StellarAssetClient::new(&e, &asset_address); + token_admin_client.mint(&owner, &1000); e.as_contract(&contract_id, || { CommitmentCoreContract::initialize(e.clone(), admin.clone(), nft_contract.clone()); @@ -1756,6 +1765,7 @@ fn test_allocate_when_settled_fails() { e.as_contract(&contract_id, || { CommitmentCoreContract::allocate( e.clone(), + admin.clone(), String::from_str(&e, commitment_id), target_pool.clone(), 100, @@ -1788,6 +1798,7 @@ fn test_allocate_when_violated_fails() { e.as_contract(&contract_id, || { CommitmentCoreContract::allocate( e.clone(), + admin.clone(), String::from_str(&e, commitment_id), target_pool.clone(), 100, @@ -1820,6 +1831,7 @@ fn test_allocate_when_early_exit_fails() { e.as_contract(&contract_id, || { CommitmentCoreContract::allocate( e.clone(), + admin.clone(), String::from_str(&e, commitment_id), target_pool.clone(), 100, @@ -1858,6 +1870,7 @@ fn test_allocate_when_active_succeeds() { store_commitment(&e, &contract_id, &commitment); client.allocate( + &admin, &String::from_str(&e, commitment_id), &target_pool, &allocation_amount, diff --git a/contracts/commitment_core/test_snapshots/tests/test_allocate_event.1.json b/contracts/commitment_core/test_snapshots/tests/test_allocate_event.1.json index 674a5e83..aa253808 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_allocate_event.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_allocate_event.1.json @@ -1,9 +1,10 @@ { "generators": { - "address": 2, + "address": 4, "nonce": 0 }, "auth": [ + [], [] ], "ledger": { @@ -19,7 +20,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": "ledger_key_contract_instance", "durability": "persistent" } @@ -30,7 +31,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": "ledger_key_contract_instance", "durability": "persistent", "val": { @@ -38,7 +39,111 @@ "executable": { "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, - "storage": null + "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, + { + "key": { + "symbol": "paused" + }, + "val": { + "bool": false + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AllCommitmentIds" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "NftContract" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalCommitments" + } + ] + }, + "val": { + "u64": 0 + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalValueLocked" + } + ] + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + } + ] } } } @@ -84,7 +189,88 @@ "symbol": "fn_call" }, { - "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "symbol": "initialize" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "initialize" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000003" }, { "symbol": "allocate" @@ -92,11 +278,14 @@ ], "data": { "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, { "string": "test_id" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { "i128": { @@ -114,7 +303,7 @@ { "event": { "ext": "v0", - "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", "type_": "contract", "body": { "v0": { @@ -147,7 +336,7 @@ { "event": { "ext": "v0", - "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", "type_": "diagnostic", "body": { "v0": { @@ -161,11 +350,14 @@ { "string": "caught panic 'Commitment not found' from contract function 'Symbol(allocate)'" }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, { "string": "test_id" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { "i128": { @@ -183,7 +375,7 @@ { "event": { "ext": "v0", - "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", "type_": "diagnostic", "body": { "v0": { @@ -232,11 +424,14 @@ }, { "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, { "string": "test_id" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { "i128": { diff --git a/contracts/commitment_core/test_snapshots/tests/test_check_violations_not_found.1.json b/contracts/commitment_core/test_snapshots/tests/test_check_violations_not_found.1.json index ef6f0953..fb487a26 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_check_violations_not_found.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_check_violations_not_found.1.json @@ -88,7 +88,7 @@ "data": { "vec": [ { - "string": "check_violations" + "string": "chk" }, { "string": "Unknown error" diff --git a/contracts/commitment_core/test_snapshots/tests/test_create_commitment_event.1.json b/contracts/commitment_core/test_snapshots/tests/test_create_commitment_event.1.json index 0f62af19..6303a562 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_create_commitment_event.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_create_commitment_event.1.json @@ -39,6 +39,14 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, { "key": { "symbol": "paused" @@ -71,6 +79,18 @@ "vec": [] } }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, { "key": { "vec": [ @@ -83,6 +103,18 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" } }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, { "key": { "vec": [ @@ -177,6 +209,33 @@ }, "failed_call": false }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + }, { "event": { "ext": "v0", diff --git a/contracts/commitment_core/test_snapshots/tests/test_early_exit_event.1.json b/contracts/commitment_core/test_snapshots/tests/test_early_exit_event.1.json index 1e223b1d..0161fef4 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_early_exit_event.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_early_exit_event.1.json @@ -123,7 +123,7 @@ "data": { "vec": [ { - "string": "early_exit" + "string": "exit" }, { "string": "Unknown error" diff --git a/contracts/commitment_core/test_snapshots/tests/test_get_admin.1.json b/contracts/commitment_core/test_snapshots/tests/test_get_admin.1.json index 708c869f..3c5ff991 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_get_admin.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_get_admin.1.json @@ -40,6 +40,14 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, { "key": { "symbol": "paused" @@ -72,6 +80,18 @@ "vec": [] } }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, { "key": { "vec": [ @@ -84,6 +104,18 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, { "key": { "vec": [ @@ -144,5 +176,33 @@ ] ] }, - "events": [] + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + } + ] } \ No newline at end of file diff --git a/contracts/commitment_core/test_snapshots/tests/test_get_nft_contract.1.json b/contracts/commitment_core/test_snapshots/tests/test_get_nft_contract.1.json index 708c869f..3c5ff991 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_get_nft_contract.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_get_nft_contract.1.json @@ -40,6 +40,14 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, { "key": { "symbol": "paused" @@ -72,6 +80,18 @@ "vec": [] } }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, { "key": { "vec": [ @@ -84,6 +104,18 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, { "key": { "vec": [ @@ -144,5 +176,33 @@ ] ] }, - "events": [] + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + } + ] } \ No newline at end of file diff --git a/contracts/commitment_core/test_snapshots/tests/test_get_owner_commitments.1.json b/contracts/commitment_core/test_snapshots/tests/test_get_owner_commitments.1.json index 6f778c52..e902d51a 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_get_owner_commitments.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_get_owner_commitments.1.json @@ -40,6 +40,14 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, { "key": { "symbol": "paused" @@ -72,6 +80,18 @@ "vec": [] } }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, { "key": { "vec": [ @@ -84,6 +104,18 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, { "key": { "vec": [ @@ -144,5 +176,33 @@ ] ] }, - "events": [] + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + } + ] } \ No newline at end of file diff --git a/contracts/commitment_core/test_snapshots/tests/test_get_total_commitments.1.json b/contracts/commitment_core/test_snapshots/tests/test_get_total_commitments.1.json index 708c869f..3c5ff991 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_get_total_commitments.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_get_total_commitments.1.json @@ -40,6 +40,14 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, { "key": { "symbol": "paused" @@ -72,6 +80,18 @@ "vec": [] } }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, { "key": { "vec": [ @@ -84,6 +104,18 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, { "key": { "vec": [ @@ -144,5 +176,33 @@ ] ] }, - "events": [] + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + } + ] } \ No newline at end of file diff --git a/contracts/commitment_core/test_snapshots/tests/test_initialize.1.json b/contracts/commitment_core/test_snapshots/tests/test_initialize.1.json index 908631a0..acd2a443 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_initialize.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_initialize.1.json @@ -39,6 +39,14 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, { "key": { "symbol": "paused" @@ -71,6 +79,18 @@ "vec": [] } }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, { "key": { "vec": [ @@ -83,6 +103,18 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, { "key": { "vec": [ @@ -143,5 +175,33 @@ ] ] }, - "events": [] + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + } + ] } \ No newline at end of file diff --git a/contracts/commitment_core/test_snapshots/tests/test_update_value_event.1.json b/contracts/commitment_core/test_snapshots/tests/test_update_value_event.1.json index bf5218bb..7cd09c25 100644 --- a/contracts/commitment_core/test_snapshots/tests/test_update_value_event.1.json +++ b/contracts/commitment_core/test_snapshots/tests/test_update_value_event.1.json @@ -42,6 +42,14 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "EMG_MODE" + }, + "val": { + "bool": false + } + }, { "key": { "symbol": "paused" @@ -74,6 +82,18 @@ "vec": [] } }, + { + "key": { + "vec": [ + { + "symbol": "AuthorizedUpdaters" + } + ] + }, + "val": { + "vec": [] + } + }, { "key": { "vec": [ @@ -240,6 +260,18 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, + { + "key": { + "vec": [ + { + "symbol": "ReentrancyGuard" + } + ] + }, + "val": { + "bool": false + } + }, { "key": { "vec": [ @@ -301,6 +333,33 @@ ] }, "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "EmgMode" + } + ], + "data": { + "vec": [ + { + "symbol": "EMG_OFF" + }, + { + "u64": 0 + } + ] + } + } + } + }, + "failed_call": false + }, { "event": { "ext": "v0", diff --git a/contracts/shared_utils/src/lib.rs b/contracts/shared_utils/src/lib.rs index b3deb801..16f6ce60 100644 --- a/contracts/shared_utils/src/lib.rs +++ b/contracts/shared_utils/src/lib.rs @@ -40,7 +40,6 @@ pub use emergency::EmergencyControl; pub use error_codes::{category, code, emit_error_event, message_for_code}; pub use errors::ErrorHelper; pub use events::Events; -pub use fees; pub use math::SafeMath; pub use pausable::Pausable; pub use rate_limiting::RateLimiter;