use super::*; use crate::mock::*; use frame_support::{assert_noop, assert_ok}; #[test] fn wrap_works() { new_test_ext().execute_with(|| { let user = 1; let amount = 1000; assert_eq!(Balances::free_balance(&user), 10000); assert_eq!(Assets::balance(0, &user), 0); assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), amount)); assert_eq!(Balances::free_balance(&user), 10000 - amount); assert_eq!(Assets::balance(0, &user), amount); assert_eq!(TokenWrapper::total_locked(), amount); }); } #[test] fn unwrap_works() { new_test_ext().execute_with(|| { let user = 1; let amount = 1000; assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), amount)); let native_balance = Balances::free_balance(&user); assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user), amount)); assert_eq!(Balances::free_balance(&user), native_balance + amount); assert_eq!(Assets::balance(0, &user), 0); assert_eq!(TokenWrapper::total_locked(), 0); }); } #[test] fn wrap_fails_insufficient_balance() { new_test_ext().execute_with(|| { let user = 1; let amount = 20000; assert_noop!( TokenWrapper::wrap(RuntimeOrigin::signed(user), amount), Error::::InsufficientBalance ); }); } #[test] fn unwrap_fails_insufficient_wrapped_balance() { new_test_ext().execute_with(|| { let user = 1; let amount = 1000; assert_noop!( TokenWrapper::unwrap(RuntimeOrigin::signed(user), amount), Error::::InsufficientWrappedBalance ); }); } // ============================================================================ // EDGE CASE TESTS // ============================================================================ #[test] fn wrap_fails_zero_amount() { new_test_ext().execute_with(|| { let user = 1; assert_noop!( TokenWrapper::wrap(RuntimeOrigin::signed(user), 0), Error::::ZeroAmount ); }); } #[test] fn unwrap_fails_zero_amount() { new_test_ext().execute_with(|| { let user = 1; let amount = 1000; // First wrap some tokens assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), amount)); // Try to unwrap zero assert_noop!( TokenWrapper::unwrap(RuntimeOrigin::signed(user), 0), Error::::ZeroAmount ); }); } #[test] fn multi_user_concurrent_wrap_unwrap() { new_test_ext().execute_with(|| { let user1 = 1; let user2 = 2; let user3 = 3; let amount1 = 1000; let amount2 = 2000; let amount3 = 1500; // All users wrap assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user1), amount1)); assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user2), amount2)); assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user3), amount3)); // Verify balances assert_eq!(Assets::balance(0, &user1), amount1); assert_eq!(Assets::balance(0, &user2), amount2); assert_eq!(Assets::balance(0, &user3), amount3); // Verify total locked assert_eq!(TokenWrapper::total_locked(), amount1 + amount2 + amount3); // User 2 unwraps assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user2), amount2)); assert_eq!(Assets::balance(0, &user2), 0); assert_eq!(TokenWrapper::total_locked(), amount1 + amount3); // User 1 and 3 still have their wrapped tokens assert_eq!(Assets::balance(0, &user1), amount1); assert_eq!(Assets::balance(0, &user3), amount3); }); } #[test] fn multiple_wrap_operations_same_user() { new_test_ext().execute_with(|| { let user = 1; // Multiple wraps assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), 100)); assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), 200)); assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), 300)); // Verify accumulated balance assert_eq!(Assets::balance(0, &user), 600); assert_eq!(TokenWrapper::total_locked(), 600); // Partial unwrap assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user), 250)); assert_eq!(Assets::balance(0, &user), 350); assert_eq!(TokenWrapper::total_locked(), 350); }); } #[test] fn events_emitted_correctly() { new_test_ext().execute_with(|| { let user = 1; let amount = 1000; // Wrap and check event assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), amount)); System::assert_has_event( Event::Wrapped { who: user, amount }.into() ); // Unwrap and check event assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user), amount)); System::assert_has_event( Event::Unwrapped { who: user, amount }.into() ); }); } #[test] fn total_locked_tracking_accuracy() { new_test_ext().execute_with(|| { assert_eq!(TokenWrapper::total_locked(), 0); let user1 = 1; let user2 = 2; // User 1 wraps assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user1), 1000)); assert_eq!(TokenWrapper::total_locked(), 1000); // User 2 wraps assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user2), 500)); assert_eq!(TokenWrapper::total_locked(), 1500); // User 1 unwraps partially assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user1), 300)); assert_eq!(TokenWrapper::total_locked(), 1200); // User 2 unwraps all assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user2), 500)); assert_eq!(TokenWrapper::total_locked(), 700); // User 1 unwraps remaining assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user1), 700)); assert_eq!(TokenWrapper::total_locked(), 0); }); } #[test] fn large_amount_wrap_unwrap() { new_test_ext().execute_with(|| { let user = 1; // User has 10000 initial balance let large_amount = 9000; // Leave some for existential deposit assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), large_amount)); assert_eq!(Assets::balance(0, &user), large_amount); assert_eq!(TokenWrapper::total_locked(), large_amount); assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user), large_amount)); assert_eq!(Assets::balance(0, &user), 0); assert_eq!(TokenWrapper::total_locked(), 0); }); } #[test] fn pallet_account_balance_consistency() { new_test_ext().execute_with(|| { let user = 1; let amount = 1000; let pallet_account = TokenWrapper::account_id(); let initial_pallet_balance = Balances::free_balance(&pallet_account); // Wrap - pallet account should receive native tokens assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(user), amount)); assert_eq!( Balances::free_balance(&pallet_account), initial_pallet_balance + amount ); // Unwrap - pallet account should release native tokens assert_ok!(TokenWrapper::unwrap(RuntimeOrigin::signed(user), amount)); assert_eq!( Balances::free_balance(&pallet_account), initial_pallet_balance ); }); } #[test] fn wrap_unwrap_maintains_1_to_1_backing() { new_test_ext().execute_with(|| { let users = vec![1, 2, 3]; let amounts = vec![1000, 2000, 1500]; // All users wrap for (user, amount) in users.iter().zip(amounts.iter()) { assert_ok!(TokenWrapper::wrap(RuntimeOrigin::signed(*user), *amount)); } let total_wrapped = amounts.iter().sum::(); let pallet_account = TokenWrapper::account_id(); let pallet_balance = Balances::free_balance(&pallet_account); // Pallet should hold exactly the amount of wrapped tokens // (Note: may include existential deposit, so check >= total_wrapped) assert!(pallet_balance >= total_wrapped); assert_eq!(TokenWrapper::total_locked(), total_wrapped); // Verify total supply matches assert_eq!( Assets::total_issuance(0), total_wrapped ); }); }