Skip to content

Commit

Permalink
Implemented create_with_range function (#13)
Browse files Browse the repository at this point in the history
* Implemented create_with_range function

* Minor change

* feat : update test for create_with_range

* feat : Updated snforge version in yaml

* feat : Added path manually in the test.yaml

* feat : Added new test.yml - Tested on local

* feat : Removed installing dependencies from yml

* feat : Removed installing dependencies from yml
  • Loading branch information
Akashneelesh authored Jan 22, 2024
1 parent 511c355 commit 8f046e2
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 32 deletions.
13 changes: 10 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Test
on: [push, pull_request]

env:
STARKNET_FOUNDRY_VERSION: 0.9.1
STARKNET_FOUNDRY_VERSION: 0.12.0

jobs:
check:
Expand All @@ -14,6 +14,13 @@ jobs:
with:
scarb-version: "2.3.1"
- name: Install starknet foundry
run: curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh -s -- -v ${STARKNET_FOUNDRY_VERSION}
run: |
curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh -s -- -v ${STARKNET_FOUNDRY_VERSION}
echo "/root/.local/bin" >> $GITHUB_PATH
echo "Listing /root/.local/bin:"
ls -al /root/.local/bin
- name: Run cairo tests
run: snforge test
run: |
export PATH="/root/.local/bin:$PATH"
echo "Current PATH: $PATH"
/root/.local/bin/snforge test || echo "snforge not found in /root/.local/bin"
Empty file.
2 changes: 1 addition & 1 deletion Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = 1
[[package]]
name = "snforge_std"
version = "0.1.0"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.9.1#da085bd11e1b151d0592f43917136560d9b70d37"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.12.0#0c3d2fe4ab31aa4484fa216417408ae65a149efe"

[[package]]
name = "tokei"
Expand Down
2 changes: 1 addition & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ sierra-replace-ids = true

[dependencies]
starknet = ">=2.3.1"
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.9.1" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.12.0" }


[tool.snforge]
Expand Down
43 changes: 30 additions & 13 deletions src/core/lockup_linear.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ mod TokeiLockupLinear {
use tokei::types::lockup_linear::{Range, Broker, LockupLinearStream};
use tokei::types::lockup::LockupAmounts;
use tokei::tokens::erc721::{ERC721, IERC721};
use tokei::tokens::erc20::{ERC20, IERC20, IERC20Dispatcher, IERC20DispatcherTrait};

use tokei::libraries::helpers;

// *************************************************************************
Expand All @@ -88,6 +90,8 @@ mod TokeiLockupLinear {
streams: LegacyMap<u64, LockupLinearStream>,
}

const MAX_FEE: u128 = 100000000000000000;

// *************************************************************************
// EVENTS
// *************************************************************************
Expand Down Expand Up @@ -165,26 +169,28 @@ mod TokeiLockupLinear {
// Safe Interactions: query the protocol fee. This is safe because it's a known Tokei contract that does
// not call other unknown contracts.
// TODO: implement.
let protocol_fee = 0;

// TODO: Handle MAX_FEE as a constant, with handlign of fixed point numbers.
let MAX_FEE = 100;
let caller = get_caller_address();
let this = get_contract_address();

// Checks: check the fees and calculate the fee amounts.
let create_amounts = helpers::check_and_calculate_fees(
total_amount, protocol_fee, broker.fee, MAX_FEE
);
// Checks: validate the user-provided parameters.
// Sanity checks

assert(sender != Zeroable::zero(), 'Invalid Sender Address');
assert(recipient != Zeroable::zero(), 'Invalid Recipient Address');
assert(broker.account != Zeroable::zero(), 'Invalid broker Address');
assert(asset != Zeroable::zero(), 'Invalid asset Address');
assert(total_amount != Zeroable::zero(), 'Invalid total Amount');

// TODO: Handle MAX_FEE as a constant, with handlign of fixed point numbers.
// let MAX_FEE = 100000000000000000;

// Read the next stream id from storage.
let stream_id = self.next_stream_id.read();

// Checks: check the fees and calculate the fee amounts.
// TODO: implement.
let deposited_amount = total_amount - broker.fee;

// Checks: validate the user-provided parameters.
// TODO: implement.

let amounts: LockupAmounts = LockupAmounts {
deposited: deposited_amount, withdrawn: 0, refunded: 0,
};
Expand All @@ -210,10 +216,17 @@ mod TokeiLockupLinear {
IERC721::mint(ref state, recipient, stream_id.into());

// Interactions: transfer the deposit and the protocol fee.
// TODO: implement.
// Casting u128 to u256 for the transfer from function
let deposit_u256: u256 = amounts.deposited.into();

IERC20Dispatcher { contract_address: asset }.transfer_from(caller, this, deposit_u256);

// Interactions: pay the broker fee, if not zero.
// TODO: implement.
if (broker.fee > 0) {
let broker_fee_u256: u256 = broker.fee.into();
IERC20Dispatcher { contract_address: asset }
.transfer_from(caller, broker.account, broker_fee_u256);
}

// Emit an event for the newly created stream.
self
Expand All @@ -236,6 +249,10 @@ mod TokeiLockupLinear {
}
}

#[generate_trait]
impl TokeinInternalImpl of TokeiInternalTrait {}


#[external(v0)]
impl TokeiLockupLinearERC721 of IERC721<ContractState> {
fn initializer(
Expand Down
51 changes: 37 additions & 14 deletions tests/test_lockup_linear.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ use starknet::{
use debug::PrintTrait;

// Starknet Foundry imports.
use snforge_std::{declare, start_prank, stop_prank, ContractClassTrait};
use snforge_std::{
declare, ContractClassTrait, start_prank, stop_prank, RevertedTransaction, CheatTarget,
TxInfoMock,
};

use tokei::tokens::erc20::{IERC20Dispatcher, IERC20DispatcherTrait};


// Local imports.
use tokei::core::lockup_linear::{
ITokeiLockupLinearSafeDispatcher, ITokeiLockupLinearSafeDispatcherTrait
};
use tokei::core::lockup_linear::{ITokeiLockupLinearDispatcher, ITokeiLockupLinearDispatcherTrait};
use tokei::types::lockup_linear::{Range, Broker};
use tokei::tokens::erc721::{IERC721SafeDispatcher, IERC721SafeDispatcherTrait};

Expand All @@ -35,6 +38,13 @@ fn given_normal_conditions_when_create_with_range_then_expected_results() {
let caller_address = contract_address_const::<'caller'>();

let (tokei) = setup(caller_address);
let (token_dispatcher, token) = deploy_setup_erc20(
'Ethereum', 'ETH', 100000_u256, caller_address
);
start_prank(CheatTarget::One(token), caller_address);
token_dispatcher.approve(tokei.contract_address, 1000_u256);
stop_prank(CheatTarget::One(token));

// *********************************************************************************************
// * TEST LOGIC *
// *********************************************************************************************
Expand All @@ -43,7 +53,7 @@ fn given_normal_conditions_when_create_with_range_then_expected_results() {
let sender = caller_address;
let recipient = contract_address_const::<'recipient'>();
let total_amount = 1000;
let asset = contract_address_const::<'asset'>();
let asset = token;
let cancelable = true;
let start = 10;
let cliff = 100;
Expand All @@ -53,10 +63,10 @@ fn given_normal_conditions_when_create_with_range_then_expected_results() {
let broker_fee = 0;
let broker = Broker { account: broker_account, fee: broker_fee, };

prepare_contracts(caller_address, tokei);
// Actual test.
let stream_id = tokei
.create_with_range(sender, recipient, total_amount, asset, cancelable, range, broker,)
.unwrap();
.create_with_range(sender, recipient, total_amount, asset, cancelable, range, broker,);

// Assertions.
assert(stream_id == 1, 'wrong stream id');
Expand All @@ -74,7 +84,7 @@ fn given_normal_conditions_when_create_with_range_then_expected_results() {
}

/// Utility function to setup the test environment.
fn setup(caller_address: ContractAddress) -> (ITokeiLockupLinearSafeDispatcher,) {
fn setup(caller_address: ContractAddress) -> (ITokeiLockupLinearDispatcher,) {
// Setup the contracts.
let (tokei,) = setup_contracts(caller_address);
// Prank the caller address.
Expand All @@ -84,23 +94,23 @@ fn setup(caller_address: ContractAddress) -> (ITokeiLockupLinearSafeDispatcher,)
}

// Utility function to prank the caller address
fn prepare_contracts(caller_address: ContractAddress, tokei: ITokeiLockupLinearSafeDispatcher,) {
fn prepare_contracts(caller_address: ContractAddress, tokei: ITokeiLockupLinearDispatcher,) {
// Prank the caller address for calls to `TokeiLockupLinear` contract.
start_prank(tokei.contract_address, caller_address);
start_prank(CheatTarget::One(tokei.contract_address), caller_address);
}

/// Utility function to teardown the test environment.
fn teardown(tokei: ITokeiLockupLinearSafeDispatcher,) {
stop_prank(tokei.contract_address);
fn teardown(tokei: ITokeiLockupLinearDispatcher,) {
stop_prank(CheatTarget::One(tokei.contract_address));
}

/// Setup required contracts.
fn setup_contracts(caller_address: ContractAddress) -> (ITokeiLockupLinearSafeDispatcher,) {
fn setup_contracts(caller_address: ContractAddress) -> (ITokeiLockupLinearDispatcher,) {
// Deploy the role store contract.
let tokei_address = deploy_tokei(caller_address);

// Create a role store dispatcher.
let tokei = ITokeiLockupLinearSafeDispatcher { contract_address: tokei_address };
let tokei = ITokeiLockupLinearDispatcher { contract_address: tokei_address };

// Return the caller address and the contract interfaces.
(tokei,)
Expand All @@ -114,3 +124,16 @@ fn deploy_tokei(initial_admin: ContractAddress) -> ContractAddress {
tokei_contract.deploy(@constructor_calldata).unwrap()
}

fn deploy_setup_erc20(
name: felt252, symbol: felt252, initial_supply: u256, recipient: ContractAddress
) -> (IERC20Dispatcher, ContractAddress) {
let token_contract = declare('ERC20');
let mut calldata = array![name, symbol];
Serde::serialize(@initial_supply, ref calldata);
Serde::serialize(@recipient, ref calldata);
let token_addr = token_contract.deploy(@calldata).unwrap();
let token_dispatcher = IERC20Dispatcher { contract_address: token_addr };

(token_dispatcher, token_addr)
}

0 comments on commit 8f046e2

Please sign in to comment.