Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simple_vault test implementation #220

Merged
merged 1 commit into from
Jul 19, 2024
Merged
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
1 change: 1 addition & 0 deletions listings/applications/simple_vault/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = '2023_11'

[dependencies]
starknet.workspace = true
erc20 = { path = "../erc20" }

[scripts]
test.workspace = true
Expand Down
1 change: 1 addition & 0 deletions listings/applications/simple_vault/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod simple_vault;


#[cfg(test)]
mod tests;
162 changes: 145 additions & 17 deletions listings/applications/simple_vault/src/simple_vault.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,34 @@ use starknet::ContractAddress;
// we need to have the interface of the remote ERC20 contract defined to import the Dispatcher.
#[starknet::interface]
pub trait IERC20<TContractState> {
fn name(self: @TContractState) -> felt252;
fn symbol(self: @TContractState) -> felt252;
fn decimals(self: @TContractState) -> u8;
fn total_supply(self: @TContractState) -> u256;
fn balance_of(self: @TContractState, account: ContractAddress) -> u256;
fn allowance(self: @TContractState, owner: ContractAddress, spender: ContractAddress) -> u256;
fn transfer(ref self: TContractState, recipient: ContractAddress, amount: u256) -> bool;
fn get_name(self: @TContractState) -> felt252;
fn get_symbol(self: @TContractState) -> felt252;
fn get_decimals(self: @TContractState) -> u8;
fn get_total_supply(self: @TContractState) -> felt252;
fn balance_of(self: @TContractState, account: ContractAddress) -> felt252;
fn allowance(
self: @TContractState, owner: ContractAddress, spender: ContractAddress
) -> felt252;
fn transfer(ref self: TContractState, recipient: ContractAddress, amount: felt252);
fn transfer_from(
ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256
) -> bool;
fn approve(ref self: TContractState, spender: ContractAddress, amount: u256) -> bool;
ref self: TContractState,
sender: ContractAddress,
recipient: ContractAddress,
amount: felt252
);
fn approve(ref self: TContractState, spender: ContractAddress, amount: felt252);
fn increase_allowance(ref self: TContractState, spender: ContractAddress, added_value: felt252);
fn decrease_allowance(
ref self: TContractState, spender: ContractAddress, subtracted_value: felt252
);
}

#[starknet::interface]
pub trait ISimpleVault<TContractState> {
fn deposit(ref self: TContractState, amount: u256);
fn withdraw(ref self: TContractState, shares: u256);
fn user_balance_of(ref self: TContractState, account: ContractAddress) -> u256;
fn contract_total_supply(ref self: TContractState) -> u256;
}

#[starknet::contract]
Expand Down Expand Up @@ -51,11 +62,22 @@ pub mod SimpleVault {
self.total_supply.write(self.total_supply.read() - shares);
self.balance_of.write(from, self.balance_of.read(from) - shares);
}

}

#[abi(embed_v0)]
impl SimpleVault of super::ISimpleVault<ContractState> {
fn deposit(ref self: ContractState, amount: u256) {

fn user_balance_of(ref self: ContractState, account: ContractAddress) -> u256 {
self.balance_of.read(account)
}

fn contract_total_supply(ref self: ContractState) -> u256 {
self.total_supply.read()
}


fn deposit(ref self: ContractState, amount: u256){
// a = amount
// B = balance of token before deposit
// T = total supply
Expand All @@ -71,12 +93,15 @@ pub mod SimpleVault {
if self.total_supply.read() == 0 {
shares = amount;
} else {
let balance = self.token.read().balance_of(this);
let balance: u256 = self.token.read().balance_of(this).try_into()
.unwrap();
shares = (amount * self.total_supply.read()) / balance;
}

PrivateFunctions::_mint(ref self, caller, shares);
self.token.read().transfer_from(caller, this, amount);

PrivateFunctions::_mint(ref self, caller, shares);

let amount_felt252: felt252 = amount.low.into();
self.token.read().transfer_from(caller, this, amount_felt252);
}

fn withdraw(ref self: ContractState, shares: u256) {
Expand All @@ -91,11 +116,114 @@ pub mod SimpleVault {
let caller = get_caller_address();
let this = get_contract_address();

let balance = self.token.read().balance_of(this);
let balance = self.user_balance_of(this);
let amount = (shares * balance) / self.total_supply.read();
PrivateFunctions::_burn(ref self, caller, shares);
self.token.read().transfer(caller, amount);
let amount_felt252: felt252 = amount.low.into();
self.token.read().transfer(caller, amount_felt252);
}
}
}
// ANCHOR_END: simple_vault

#[cfg(test)]
mod tests {
use core::traits::Into;
use super::{
SimpleVault, ISimpleVaultDispatcher, ISimpleVaultDispatcherTrait, IERC20Dispatcher,
IERC20DispatcherTrait
};

// use erc20::token::IERC20;
use erc20::token::{IERC20DispatcherTrait as IERC20DispatcherTrait_token,
IERC20Dispatcher as IERC20Dispatcher_token
};

use core::num::traits::Zero;

use starknet::testing::{set_contract_address, set_account_contract_address};
use starknet::{
ContractAddress, SyscallResultTrait, syscalls::deploy_syscall, get_caller_address,
contract_address_const
};

const token_name: felt252 = 'myToken';
const decimals: u8 = 18;
const initial_supply: felt252 = 100000;
const symbols: felt252 = 'mtk';

fn deploy() -> (ISimpleVaultDispatcher, ContractAddress, IERC20Dispatcher_token) {
let _token_address: ContractAddress = contract_address_const::<'token_address'>();
let caller = contract_address_const::<'caller'>();

let (token_contract_address, _) = deploy_syscall(
erc20::token::erc20::TEST_CLASS_HASH.try_into().unwrap(),
caller.into(),
array![caller.into(), 'myToken', '8', '1000'.into(), 'MYT'].span(),
false
)
.unwrap_syscall();

let (contract_address, _) = deploy_syscall(
SimpleVault::TEST_CLASS_HASH.try_into().unwrap(),
0,
array![token_contract_address.into()].span(),
false
)
.unwrap_syscall();

(
ISimpleVaultDispatcher { contract_address },
contract_address,
IERC20Dispatcher_token { contract_address: token_contract_address }
)
}

#[test]
fn test_deposit() {
let caller = contract_address_const::<'caller'>();
let (dispatcher, vault_address, token_dispatcher) = deploy();

// Approve the vault to transfer tokens on behalf of the caller
let amount: felt252 = 10.into();
token_dispatcher.approve(vault_address.into(), amount);
set_contract_address(caller);

// Deposit tokens into the vault
let amount: u256 = 10.into();
let _deposit = dispatcher.deposit(amount);
println!("deposit :{:?}", _deposit);

// Check balances and total supply
let balance_of_caller = dispatcher.user_balance_of(caller);
let total_supply = dispatcher.contract_total_supply();

assert(balance_of_caller == amount, 'Deposit failed');
assert(total_supply == amount, 'total supply mismatch');

}

#[test]
fn test_deposit_withdraw() {
let caller = contract_address_const::<'caller'>();
let (dispatcher, vault_address, token_dispatcher) = deploy();

// Approve the vault to transfer tokens on behalf of the caller
let amount: felt252 = 10.into();
token_dispatcher.approve(vault_address.into(), amount);
set_contract_address(caller);
set_account_contract_address(vault_address);

// Deposit tokens into the vault
let amount: u256 = 10.into();
dispatcher.deposit(amount);
dispatcher.withdraw(amount);

// Check balances of user in the vault after withdraw
let balance_of_caller = dispatcher.user_balance_of(caller);

assert(balance_of_caller == 0.into(), 'withdraw failed');
}


}