diff --git a/contracts/inheritance-contract/src/lib.rs b/contracts/inheritance-contract/src/lib.rs index 9caa369ba..98fe9f375 100644 --- a/contracts/inheritance-contract/src/lib.rs +++ b/contracts/inheritance-contract/src/lib.rs @@ -6,6 +6,8 @@ use soroban_sdk::{ const MAX_BENEFICIARIES: u32 = 100; const PLAN_TTL_THRESHOLD: u32 = 500; const PLAN_TTL_LEEWAY: u32 = 100; +const BRIDGE_FEE_BPS: u32 = 100; // 1% bridge fee +const STELLAR_CHAIN: &str = "Stellar"; #[contracterror] #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -20,6 +22,10 @@ pub enum Error { TooManyBeneficiaries = 8, TimelockNotExpired = 9, PayoutNotTriggered = 10, + UnsupportedToken = 11, + InvalidBridgeMetadata = 12, + MathOverflow = 13, + AlreadyInitialized = 14, } #[contracttype] @@ -28,6 +34,8 @@ pub struct Beneficiary { pub address: Address, pub allocation_bps: u32, pub fiat_anchor_info: String, + pub destination_chain: String, + pub destination_address: String, } #[contracttype] @@ -43,15 +51,33 @@ pub struct Plan { pub yield_rate_bps: u32, pub is_active: bool, pub timelock_duration: u64, + pub source_chain: String, + pub source_tx_hash: String, } pub type InheritancePlan = Plan; +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct BridgePayoutEvent { + pub owner: Address, + pub token: Address, + pub beneficiary: Address, + pub destination_chain: String, + pub destination_address: String, + pub gross_amount: i128, + pub fee_amount: i128, + pub net_amount: i128, + pub source_chain: String, + pub source_tx_hash: String, +} + #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] pub enum DataKey { Plan(Address), ClaimStatus(Address), + SupportedWrappedToken(Address), } #[contracttype] @@ -69,6 +95,22 @@ impl InheritanceContract { .persistent() .extend_ttl(key, PLAN_TTL_LEEWAY, PLAN_TTL_THRESHOLD); } + + fn emit_bridge_payout_event(env: &Env, event: BridgePayoutEvent) { + let topic = (symbol_short!("BridgePay"), env.current_contract_address()); + env.events().publish(topic, event); + } + + fn is_stellar_chain(chain: &String, env: &Env) -> bool { + let stellar = String::from_str(env, STELLAR_CHAIN); + chain == &stellar + } + + fn supported_wrapped_token(env: &Env, token: &Address) -> bool { + env.storage() + .persistent() + .has(&DataKey::SupportedWrappedToken(token.clone())) + } } #[contractimpl] @@ -87,6 +129,8 @@ impl InheritanceContract { earn_yield: bool, yield_rate_bps: u32, timelock_duration: u64, + source_chain: String, + source_tx_hash: String, ) -> Result<(), Error> { owner.require_auth(); @@ -106,11 +150,25 @@ impl InheritanceContract { let mut total_bps: u32 = 0; for beneficiary in beneficiaries.iter() { total_bps += beneficiary.allocation_bps; + let empty = String::from_str(&env, ""); + if beneficiary.destination_chain == empty || beneficiary.destination_address == empty { + return Err(Error::InvalidBridgeMetadata); + } } if total_bps != 10000 { return Err(Error::InvalidBasisPoints); } + let empty = String::from_str(&env, ""); + if source_chain == empty || source_tx_hash == empty { + return Err(Error::InvalidBridgeMetadata); + } + + let stellarchain = String::from_str(&env, STELLAR_CHAIN); + if source_chain != stellarchain && !Self::supported_wrapped_token(&env, &token) { + return Err(Error::UnsupportedToken); + } + let token_client = soroban_sdk::token::Client::new(&env, &token); let balance = token_client.balance(&owner); if balance < amount { @@ -130,6 +188,8 @@ impl InheritanceContract { yield_rate_bps, is_active: true, timelock_duration, + source_chain: source_chain.clone(), + source_tx_hash: source_tx_hash.clone(), }; env.storage().persistent().set(&key, &plan); @@ -160,6 +220,52 @@ impl InheritanceContract { Ok(()) } + pub fn initialize(env: Env, admin: Address) -> Result<(), Error> { + let admin_key = InstanceDataKey::Admin; + if env.storage().instance().has(&admin_key) { + return Err(Error::AlreadyInitialized); + } + env.storage().instance().set(&admin_key, &admin); + Ok(()) + } + + fn require_admin(env: &Env, admin: &Address) -> Result<(), Error> { + let admin_key = InstanceDataKey::Admin; + let configured_admin: Address = env + .storage() + .instance() + .get(&admin_key) + .ok_or(Error::Unauthorized)?; + if &configured_admin != admin { + return Err(Error::Unauthorized); + } + Ok(()) + } + + pub fn register_supported_wrapped_token( + env: Env, + admin: Address, + token: Address, + ) -> Result<(), Error> { + admin.require_auth(); + Self::require_admin(&env, &admin)?; + let key = DataKey::SupportedWrappedToken(token); + env.storage().persistent().set(&key, &true); + Ok(()) + } + + pub fn unregister_wrapped_token(env: Env, admin: Address, token: Address) -> Result<(), Error> { + admin.require_auth(); + Self::require_admin(&env, &admin)?; + let key = DataKey::SupportedWrappedToken(token); + env.storage().persistent().remove(&key); + Ok(()) + } + + pub fn is_supported_wrapped_token(env: Env, token: Address) -> Result { + Ok(Self::supported_wrapped_token(&env, &token)) + } + /// Claim payout once the plan owner has been inactive beyond the grace period. /// Contributors: Calculate final yield-bearing payout, split assets among beneficiaries, /// emit payout events, and trigger anchor event emissions for fiat recipients. @@ -306,11 +412,41 @@ impl InheritanceContract { remaining -= amount; amount }; + + let destination_stellar = Self::is_stellar_chain(&beneficiary.destination_chain, &env); + let (fee_amount, net_amount) = if destination_stellar { + (0_i128, share) + } else { + let fee = share + .checked_mul(BRIDGE_FEE_BPS as i128) + .ok_or(Error::MathOverflow)? + .checked_div(10000) + .ok_or(Error::MathOverflow)?; + let net = share.checked_sub(fee).ok_or(Error::MathOverflow)?; + (fee, net) + }; + token_client.transfer( &env.current_contract_address(), &beneficiary.address, - &share, + &net_amount, ); + + if !destination_stellar { + let event = BridgePayoutEvent { + owner: plan.owner.clone(), + token: plan.token.clone(), + beneficiary: beneficiary.address.clone(), + destination_chain: beneficiary.destination_chain.clone(), + destination_address: beneficiary.destination_address.clone(), + gross_amount: share, + fee_amount, + net_amount, + source_chain: plan.source_chain.clone(), + source_tx_hash: plan.source_tx_hash.clone(), + }; + Self::emit_bridge_payout_event(&env, event); + } } Ok(()) diff --git a/contracts/inheritance-contract/src/test.rs b/contracts/inheritance-contract/src/test.rs index 96cc6af67..68cf68fa1 100644 --- a/contracts/inheritance-contract/src/test.rs +++ b/contracts/inheritance-contract/src/test.rs @@ -48,6 +48,8 @@ fn test_create_plan_success() { address: beneficiary_address.clone(), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; client.create_plan( @@ -59,6 +61,8 @@ fn test_create_plan_success() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Verify balances @@ -98,6 +102,8 @@ fn test_ping_updates_last_ping_and_emits_event() { address: Address::generate(&env), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; token_client.mint(&owner, &2000); @@ -114,6 +120,8 @@ fn test_ping_updates_last_ping_and_emits_event() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); assert_eq!(client.get_plan(&owner).last_ping, start); @@ -158,6 +166,8 @@ fn test_ping_requires_owner_auth() { yield_rate_bps: 0, is_active: true, timelock_duration: 86400, + source_chain: String::from_str(&env, "Stellar"), + source_tx_hash: String::from_str(&env, "SRC_TX_HASH"), }; env.as_contract(&contract_id, || { @@ -185,6 +195,8 @@ fn test_create_plan_insufficient_balance() { address: Address::generate(&env), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; // Attempting to create plan for 1500 (owner only has 1000) @@ -197,6 +209,8 @@ fn test_create_plan_insufficient_balance() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); assert_eq!(result, Err(Ok(Error::InsufficientBalance))); @@ -220,6 +234,8 @@ fn test_create_plan_negative_or_zero_amount() { address: Address::generate(&env), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; // Amount = 0 @@ -232,6 +248,8 @@ fn test_create_plan_negative_or_zero_amount() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); assert_eq!(result_zero, Err(Ok(Error::NegativeAmount))); @@ -245,6 +263,8 @@ fn test_create_plan_negative_or_zero_amount() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); assert_eq!(result_neg, Err(Ok(Error::NegativeAmount))); } @@ -267,12 +287,16 @@ fn test_create_plan_invalid_basis_points() { address: Address::generate(&env), allocation_bps: 4000, fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let beneficiary2 = Beneficiary { address: Address::generate(&env), allocation_bps: 5000, // Total = 9000 BPS (less than 10000) fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let result = client.try_create_plan( @@ -284,6 +308,8 @@ fn test_create_plan_invalid_basis_points() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); assert_eq!(result, Err(Ok(Error::InvalidBasisPoints))); @@ -307,6 +333,8 @@ fn test_create_plan_already_exists() { address: Address::generate(&env), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; // First creation @@ -319,6 +347,8 @@ fn test_create_plan_already_exists() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Second creation on same owner @@ -331,6 +361,8 @@ fn test_create_plan_already_exists() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); assert_eq!(result2, Err(Ok(Error::PlanAlreadyExists))); } @@ -355,6 +387,8 @@ fn test_trigger_payout_single_beneficiary() { address: beneficiary.clone(), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let start = 1_000_000; @@ -369,6 +403,8 @@ fn test_trigger_payout_single_beneficiary() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate plan to start grace period @@ -413,16 +449,22 @@ fn test_trigger_payout_multiple_beneficiaries() { address: alice.clone(), allocation_bps: 5000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bob_bene = Beneficiary { address: bob.clone(), allocation_bps: 3000, fiat_anchor_info: String::from_str(&env, "EUR_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let charlie_bene = Beneficiary { address: charlie.clone(), allocation_bps: 2000, fiat_anchor_info: String::from_str(&env, "GBP_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -436,6 +478,8 @@ fn test_trigger_payout_multiple_beneficiaries() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate plan to start grace period @@ -476,11 +520,15 @@ fn test_trigger_payout_dust_goes_to_last_beneficiary() { address: a.clone(), allocation_bps: 3333, fiat_anchor_info: String::from_str(&env, ""), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bene_b = Beneficiary { address: b.clone(), allocation_bps: 6667, fiat_anchor_info: String::from_str(&env, ""), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -494,6 +542,8 @@ fn test_trigger_payout_dust_goes_to_last_beneficiary() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate plan to start grace period @@ -531,6 +581,8 @@ fn test_trigger_payout_plan_still_active() { address: beneficiary.clone(), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, ""), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -544,6 +596,8 @@ fn test_trigger_payout_plan_still_active() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Plan is still active — deactivate_plan_for_testing was never called @@ -573,6 +627,8 @@ fn test_trigger_payout_grace_period_not_met() { address: beneficiary.clone(), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, ""), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -586,6 +642,8 @@ fn test_trigger_payout_grace_period_not_met() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate plan to start grace period @@ -618,6 +676,8 @@ fn test_trigger_payout_double_payout_prevented() { address: beneficiary.clone(), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, ""), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -631,6 +691,8 @@ fn test_trigger_payout_double_payout_prevented() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate plan to start grace period @@ -682,6 +744,8 @@ fn test_cancel_claim_success() { address: beneficiary.clone(), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, ""), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let start = 1_000_000; @@ -696,6 +760,8 @@ fn test_cancel_claim_success() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate plan to start grace period @@ -734,6 +800,8 @@ fn test_reclaim_success() { address: beneficiary.clone(), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, ""), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let start = 1_000_000; @@ -748,6 +816,8 @@ fn test_reclaim_success() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Owner reclaims before claim @@ -780,6 +850,8 @@ fn test_ping_success_from_owner_updates_timestamp() { address: Address::generate(&env), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; token_client.mint(&owner, &5000); @@ -796,6 +868,8 @@ fn test_ping_success_from_owner_updates_timestamp() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Verify initial ping timestamp @@ -833,6 +907,8 @@ fn test_ping_from_third_party_fails() { address: Address::generate(&env), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; token_client.mint(&owner, &5000); @@ -849,6 +925,8 @@ fn test_ping_from_third_party_fails() { &true, &500, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Try to ping as third party without auth @@ -896,11 +974,15 @@ fn test_close_plan_refunds_all_tokens_and_deletes_storage() { address: beneficiary1, allocation_bps: 5000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bene2 = Beneficiary { address: beneficiary2, allocation_bps: 5000, fiat_anchor_info: String::from_str(&env, "EUR_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -914,6 +996,8 @@ fn test_close_plan_refunds_all_tokens_and_deletes_storage() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Verify tokens are transferred to contract @@ -949,6 +1033,8 @@ fn test_close_plan_requires_owner_auth() { address: Address::generate(&env), allocation_bps: 10000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; token_client.mint(&owner, &5000); @@ -964,6 +1050,8 @@ fn test_close_plan_requires_owner_auth() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Try to close plan as unauthorized user @@ -1017,26 +1105,36 @@ fn test_trigger_payout_5_beneficiaries_with_equal_allocations() { address: b1.clone(), allocation_bps: 2000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bene2 = Beneficiary { address: b2.clone(), allocation_bps: 2000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bene3 = Beneficiary { address: b3.clone(), allocation_bps: 2000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bene4 = Beneficiary { address: b4.clone(), allocation_bps: 2000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bene5 = Beneficiary { address: b5.clone(), allocation_bps: 2000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -1050,6 +1148,8 @@ fn test_trigger_payout_5_beneficiaries_with_equal_allocations() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate, claim, and payout @@ -1103,6 +1203,8 @@ fn test_trigger_payout_10_beneficiaries_unequal_allocations() { address: beneficiary.clone(), allocation_bps: 1000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; bene_array.push_back(b); } @@ -1119,6 +1221,8 @@ fn test_trigger_payout_10_beneficiaries_unequal_allocations() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate, claim, and payout @@ -1159,16 +1263,22 @@ fn test_trigger_payout_rounding_with_3_beneficiaries() { address: bene1.clone(), allocation_bps: 3333, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let b2 = Beneficiary { address: bene2.clone(), allocation_bps: 3333, fiat_anchor_info: String::from_str(&env, "EUR_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let b3 = Beneficiary { address: bene3.clone(), allocation_bps: 3334, fiat_anchor_info: String::from_str(&env, "GBP_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; env.ledger().set_timestamp(1_000_000); @@ -1182,6 +1292,8 @@ fn test_trigger_payout_rounding_with_3_beneficiaries() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); deactivate_plan_for_testing(&env, &contract_id, &owner); @@ -1221,11 +1333,15 @@ fn test_trigger_payout_after_grace_period_and_timelock_expiry() { address: alice.clone(), allocation_bps: 6000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bob_bene = Beneficiary { address: bob.clone(), allocation_bps: 4000, fiat_anchor_info: String::from_str(&env, "EUR_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let grace_period = 7200; // 2 hours @@ -1243,6 +1359,8 @@ fn test_trigger_payout_after_grace_period_and_timelock_expiry() { &false, &0, &timelock_duration, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Deactivate plan @@ -1294,6 +1412,8 @@ fn test_trigger_payout_with_single_beneficiary_receives_all() { address: sole_beneficiary.clone(), allocation_bps: 10000, // 100% fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let plan_amount = 55555; @@ -1308,6 +1428,8 @@ fn test_trigger_payout_with_single_beneficiary_receives_all() { &false, &0, &86400, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); deactivate_plan_for_testing(&env, &contract_id, &owner); @@ -1349,11 +1471,15 @@ fn test_create_plan_stores_all_fields_with_multiple_beneficiaries() { address: alice.clone(), allocation_bps: 7000, fiat_anchor_info: String::from_str(&env, "USD_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let bob_bene = Beneficiary { address: bob.clone(), allocation_bps: 3000, fiat_anchor_info: String::from_str(&env, "EUR_BANK"), + destination_chain: String::from_str(&env, "Stellar"), + destination_address: String::from_str(&env, "GDESTADDR"), }; let start = 2_000_000u64; @@ -1368,6 +1494,8 @@ fn test_create_plan_stores_all_fields_with_multiple_beneficiaries() { &true, &300, &172800, + &String::from_str(&env, "Stellar"), + &String::from_str(&env, "SRC_TX_HASH"), ); // Tokens are transferred: owner balance reduced, contract holds the amount