Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions contracts/account/src/contract/account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ mod Account {
use starknet::{ClassHash, ContractAddress, get_caller_address, get_contract_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);
Expand Down Expand Up @@ -69,9 +68,7 @@ mod Account {
#[flat]
UpgradeableEvent: UpgradeableComponent::Event,
TokenApproved: TokenApproved,
PaymentMade: PaymentMade
}

}
#[derive(Drop, starknet::Event)]
pub struct TokenApproved {
pub user: ContractAddress,
Expand All @@ -81,14 +78,6 @@ mod Account {
}

#[derive(Drop, starknet::Event)]
pub struct PaymentMade {
pub from: ContractAddress,
pub to: ContractAddress,
pub currency: felt252,
pub amount: u128,
pub used_bridge: bool,
}

#[constructor]
fn constructor(ref self: ContractState, public_key: felt252) {
self.account.initializer(public_key);
Expand All @@ -107,7 +96,6 @@ mod Account {
}
}


// contract impl
#[abi(embed_v0)]
impl AccountImpl of Iaccount<ContractState> {
Expand Down Expand Up @@ -260,6 +248,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 });
}
}
}

61 changes: 55 additions & 6 deletions contracts/account/tests/test_account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,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();

Expand All @@ -32,13 +32,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]
Expand All @@ -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");
}
113 changes: 113 additions & 0 deletions tests/test_account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use account::interfaces::Iaccount::{
IaccountDispatcher, IaccountDispatcherTrait
};
use snforge_std::{
ContractClassTrait, DeclareResultTrait, declare, start_cheat_caller_address,
stop_cheat_caller_address,
};
use starknet::{ContractAddress, contract_address_const};

fn setup() -> (ContractAddress, ContractAddress) {
let admin_address: ContractAddress = contract_address_const::<'1'>();
let public_key: felt252 = 'TEST_PUBLIC_KEY';

let declare_result = declare("Account");
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");

let (contract_address, _) = deploy_result.unwrap();

(contract_address, admin_address)
}

#[test]
fn test_initialize() {
let (contract_address, _) = setup();

let dispatcher = IaccountDispatcher { contract_address };

dispatcher.initialize(1, 2.try_into().unwrap());

let liquidity_bridge = dispatcher.get_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");

let initialized = dispatcher.get_initialized_status();
assert(initialized, "Invalid initialized");
}

#[test]
fn test_approve_token() {
let (contract_address, _) = setup();

let dispatcher = IaccountDispatcher { contract_address };

let token_address: ContractAddress = contract_address_const::<0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d>();

start_cheat_caller_address(contract_address, contract_address);

dispatcher.initialize(1, 2.try_into().unwrap());

dispatcher.approve_token('STRK', token_address);

stop_cheat_caller_address(contract_address);

let approved_token = dispatcher.get_approved_token('STRK');
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");
}
Loading