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
39 changes: 36 additions & 3 deletions contracts/account/src/contract/account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -66,6 +65,8 @@ mod Account {
#[flat]
UpgradeableEvent: UpgradeableComponent::Event,
TokenApproved: TokenApproved,
FiatDeposit: FiatDeposit,
FiatWithdrawal: FiatWithdrawal,
}

#[derive(Drop, starknet::Event)]
Expand All @@ -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);
Expand All @@ -94,7 +110,6 @@ mod Account {
}
}


// contract impl
#[abi(embed_v0)]
impl AccountImpl of Iaccount<ContractState> {
Expand Down Expand Up @@ -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) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert that currency is provided

assert(amount > 0, 'Amount must be > 0');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

let caller = get_caller_address();
let current_balance = self.fiat_balance.read((caller, currency));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to check if the user have sufficient balance

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I have sir

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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert takes in felt252, therefore you should use single quotes.
your test should cover the whole implementation, test every assertion, insufficient balance and more

Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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]
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");
}
Loading