diff --git a/contracts/account/src/contract/account.cairo b/contracts/account/src/contract/account.cairo index 87542e0..e0a2a24 100644 --- a/contracts/account/src/contract/account.cairo +++ b/contracts/account/src/contract/account.cairo @@ -16,7 +16,6 @@ mod Account { use starknet::{ClassHash, ContractAddress, get_caller_address}; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; - component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); component!(path: SRC9Component, storage: src9, event: SRC9Event); @@ -66,6 +65,8 @@ mod Account { #[flat] UpgradeableEvent: UpgradeableComponent::Event, TokenApproved: TokenApproved, + FiatDeposit: FiatDeposit, + FiatWithdrawal: FiatWithdrawal, } #[derive(Drop, starknet::Event)] @@ -76,6 +77,21 @@ mod Account { pub amount: u128, } + #[derive(Drop, starknet::Event)] + pub struct FiatDeposit { + pub user: ContractAddress, + pub currency: felt252, + pub amount: u128, + } + + #[derive(Drop, starknet::Event)] + pub struct FiatWithdrawal { + pub account_address: ContractAddress, + pub currency: felt252, + pub amount: u128, + pub recipient: ContractAddress, + } + #[constructor] fn constructor(ref self: ContractState, public_key: felt252) { self.account.initializer(public_key); @@ -94,7 +110,6 @@ mod Account { } } - // contract impl #[abi(embed_v0)] impl AccountImpl of Iaccount { @@ -159,6 +174,24 @@ mod Account { fn get_initialized_status(self: @ContractState) -> bool { self.initialized.read() } + + // -- New functions added here -- + + fn deposit_fiat(ref self: ContractState, currency: felt252, amount: u128) { + assert(amount > 0, 'Amount must be > 0'); + let caller = get_caller_address(); + let current_balance = self.fiat_balance.read((caller, currency)); + self.fiat_balance.write((caller, currency), current_balance + amount); + self.emit(FiatDeposit { user: caller, currency, amount }); + } + + fn withdraw_fiat(ref self: ContractState, currency: felt252, amount: u128, recipient: ContractAddress) { + assert(amount > 0, 'Amount must be > 0'); + let caller = get_caller_address(); + let balance = self.fiat_balance.read((caller, currency)); + assert(balance >= amount, 'Insufficient balance'); + self.fiat_balance.write((caller, currency), balance - amount); + self.emit(FiatWithdrawal { account_address: caller, currency, amount, recipient }); + } } } - diff --git a/contracts/account/tests/test_account.cairo b/contracts/account/tests/test_account.cairo index 779f8e4..98a049a 100644 --- a/contracts/account/tests/test_account.cairo +++ b/contracts/account/tests/test_account.cairo @@ -12,13 +12,13 @@ fn setup() -> (ContractAddress, ContractAddress) { let public_key: felt252 = 'TEST_PUBLIC_KEY'; let declare_result = declare("Account"); - assert(declare_result.is_ok(), 'contract decleration failed'); + assert(declare_result.is_ok(), "contract declaration failed"); let contract_class = declare_result.unwrap().contract_class(); let mut calldata = array![public_key]; let deploy_result = contract_class.deploy(@calldata); - assert(deploy_result.is_ok(), 'contract deployment failed'); + assert(deploy_result.is_ok(), "contract deployment failed"); let (contract_address, _) = deploy_result.unwrap(); @@ -34,13 +34,13 @@ fn test_initialize() { dispatcher.initialize(1, 2.try_into().unwrap()); let liquidity_bridge = dispatcher.get_liquidity_bridge(); - assert(liquidity_bridge == 2.try_into().unwrap(), 'Invalid liquidity bridge'); + assert(liquidity_bridge == 2.try_into().unwrap(), "Invalid liquidity bridge"); let public_key = dispatcher.get_key_public(); - assert(public_key == 1, 'Invalid public key'); + assert(public_key == 1, "Invalid public key"); let initialized = dispatcher.get_initialized_status(); - assert(initialized, 'Invalid initialized'); + assert(initialized, "Invalid initialized"); } #[test] @@ -60,5 +60,54 @@ fn test_approve_token() { stop_cheat_caller_address(contract_address); let approved_token = dispatcher.get_approved_token('STRK'); - assert(approved_token == token_address, 'Invalid approved token'); + assert(approved_token == token_address, "Invalid approved token"); +} + +#[test] +fn test_deposit_fiat() { + let (contract_address, _) = setup(); + let dispatcher = IaccountDispatcher { contract_address }; + + dispatcher.initialize(1, 2.try_into().unwrap()); + + // Deposit 1000 units of currency '1' + dispatcher.deposit_fiat(1, 1000); + + let balance = dispatcher.get_balance(); + assert(balance == 1000.try_into().unwrap(), "Balance should be 1000 after deposit"); + + // Deposit zero should fail + let deposit_zero_result = std::panic::catch_unwind(|| { + dispatcher.deposit_fiat(1, 0); + }); + assert(deposit_zero_result.is_err(), "Deposit of 0 should fail"); +} + +#[test] +fn test_withdraw_fiat() { + let (contract_address, _) = setup(); + let dispatcher = IaccountDispatcher { contract_address }; + + dispatcher.initialize(1, 2.try_into().unwrap()); + + // Deposit 1000 so withdrawal can succeed + dispatcher.deposit_fiat(1, 1000); + + // Withdraw 500 + dispatcher.withdraw_fiat(1, 500, contract_address); + + let balance = dispatcher.get_balance(); + assert(balance == 500.try_into().unwrap(), "Balance should be 500 after withdrawal"); + + // Withdraw zero should fail + let withdraw_zero_result = std::panic::catch_unwind(|| { + dispatcher.withdraw_fiat(1, 0, contract_address); + }); + assert(withdraw_zero_result.is_err(), "Withdraw of 0 should fail"); + + // Withdraw more than balance should fail + let withdraw_too_much_result = std::panic::catch_unwind(|| { + dispatcher.withdraw_fiat(1, 1000, contract_address); + }); + assert(withdraw_too_much_result.is_err(), "Withdraw more than balance should fail"); }