Skip to content

Commit

Permalink
Add info about tests to README, fix dummy test
Browse files Browse the repository at this point in the history
  • Loading branch information
Chepelau committed Dec 11, 2023
1 parent 764957f commit 753ad22
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 33 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,24 @@ The AMM is currently built on Cairo version 2.3.0. However while OpenZeppelin wa
- src/tokens/lptoken.cairo
- src/tokens/option_token.cairo

## Tests
Unit tests are located in files containing relevant code, while integration tests are located in `tests` folder. Currently there are integration tests for:
- Depositing liquidity
- Withdrawing liquidity
- Opening trade
- Closing trade
- Settling trade
- View functions
- Sandwich guard

Most of the tests also contain a couple of different scenarios.

Folder `src/testing` contains various utilities for writing tests:
- `setup.cairo` - Contains function that will fully deploy the AMM (along with tokens representing ETH, USDC), set it up, add liquidity etc. The function is called `deploy_setup` and it returns a tuple of two structs, where the first one is `Ctx` (context) which contains information needed for tests - addresses (AMM, tokens, LP tokens, OP tokens, admin...) strike, expiry etc. The second struct, `Dispatchers`, provides dispatcher for every contract that is deployed in the tests (it's more convenient than having to create them in the test manually).
- `test_utils.cairo` provides utilities for fetching all the information about current AMM state (plus some user balances etc.). To fetch the `Stats` struct, call the `new` method on it with `Ctx` and `Dispatchers` as args. `Stats` also implement `PrintTrait` for more convenient debugging.

You can look into `tests/test_dummy.cairo` to see an example of how to write a new test - how to deploy the setup, prank the AMM, mock the Pragma price, fetch the AMM state etc.

## Deployment - Zero to Hero
Deployment described using `starkli`, version `0.1.20 (e4d2307)`.

Expand Down
129 changes: 96 additions & 33 deletions tests/test_dummy.cairo
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
// Example test

use starknet::ContractAddress;
use carmine_protocol::amm_core::peripheries::view::View;
use carmine_protocol::testing::setup::{deploy_setup, _add_expired_option};
use array::ArrayTrait;
use debug::PrintTrait;
use carmine_protocol::amm_interface::{IAMMDispatcher, IAMMDispatcherTrait};
use carmine_protocol::types::option_::{Option_Trait, Option_};
use cubit::f128::types::{Fixed, FixedTrait};
use snforge_std::{start_prank, stop_prank, start_warp, stop_warp, start_mock_call, stop_mock_call};
use traits::{TryInto, Into};
use option::OptionTrait;
use debug::PrintTrait;

use snforge_std::{start_prank, stop_prank, start_warp, stop_warp, start_mock_call, stop_mock_call};
use cubit::f128::types::{Fixed, FixedTrait};

use carmine_protocol::testing::test_utils::{Stats, StatsTrait};
use carmine_protocol::testing::setup::deploy_setup;

use carmine_protocol::amm_interface::IAMMDispatcherTrait;
use carmine_protocol::amm_core::oracles::pragma::Pragma::PRAGMA_ORACLE_ADDRESS;
use carmine_protocol::amm_core::oracles::pragma::PragmaUtils::{
PragmaPricesResponse, Checkpoint, AggregationMode
};


#[test]
fn test_dummy() {
// Deploying setup
// It returns the context with all the needed information (addresses, strike, expiry etc)
// and Dispatchers (dispatchers for all the contracts deployed in the tests)
let (ctx, dsps) = deploy_setup();

// Some token amounts for trading etc
let five_tokens: u256 = 5000000000000000000; // with 18 decimals
let five_k_tokens: u256 = 5000000000; // with 6 decimals
let one_int = 1000000000000000000; // 1*10**18

// Warping
start_warp(ctx.amm_address, 1000000000);

// Pranking the AMM to call it from user address
start_prank(ctx.amm_address, ctx.admin_address);

// Mocking Pragma to return ETH price of 1.4k
start_mock_call(
PRAGMA_ORACLE_ADDRESS.try_into().unwrap(),
'get_data',
Expand All @@ -36,6 +49,8 @@ fn test_dummy() {
}
);

// Opening LONG CALL trade using the Dispatchers struct
// NOTE: You still have to import IAMMDispatcherTrait for it to work
let long_call_premia = dsps
.amm
.trade_open(
Expand All @@ -50,21 +65,48 @@ fn test_dummy() {
99999999999 // Disable this check
);

let long_put_premia = dsps
// Opening SHORT CALL trade using the Dispatchers struct
let long_call_premia = dsps
.amm
.trade_open(
1, // Put
0, // Call
ctx.strike_price,
ctx.expiry,
0, // Long
1, // Short
one_int,
ctx.usdc_address,
ctx.eth_address,
FixedTrait::from_unscaled_felt(100_000), // Disable this check
FixedTrait::from_felt(1), // Disable this check
99999999999 // Disable this check
);

// You can fetch some information about the directly:

// Fetching AMM long call option position
let call_pos_long = dsps
.amm
.get_option_position(ctx.call_lpt_address, 0, ctx.expiry, ctx.strike_price);

// Fetching AMM short call option position
let call_pos_short = dsps
.amm
.get_option_position(ctx.call_lpt_address, 1, ctx.expiry, ctx.strike_price);

// But you can also fetch all the AMM state at once with Stats
let stats_1 = StatsTrait::new(ctx, dsps);

// Printing the Stats struct:
// stats_1.print();

// It already contains the information about the AMM position in all the options:
assert(call_pos_long == stats_1.opt_pos_lc, 'This should not fail');
assert(call_pos_short == stats_1.opt_pos_sc, 'This should not fail');

// Now let's warp past the expiry and try to settle an option
start_warp(ctx.amm_address, 1000000000 + 60 * 60 * 24 + 1);

// AMM calls get_last_checkpoint_before function in Pragma oracle, so we
// need to mock it ie at price of 1.4k per ETH
start_mock_call(
PRAGMA_ORACLE_ADDRESS.try_into().unwrap(),
'get_last_checkpoint_before',
Expand All @@ -78,31 +120,52 @@ fn test_dummy() {
1
)
);
start_mock_call(PRAGMA_ORACLE_ADDRESS.try_into().unwrap(), 'get_decimals', 8);

// let call_pos = dsps.amm.get_option_position(
// ctx.call_lpt_address,
// 1,
// ctx.expiry,
// ctx.strike_price
// );
// Same goes for get_decimals function
start_mock_call(PRAGMA_ORACLE_ADDRESS.try_into().unwrap(), 'get_decimals', 8);

// let put_pos = dsps.amm.get_option_position(
// ctx.put_lpt_address,
// 1,
// ctx.expiry,
// ctx.strike_price
// );
// Expire Call pool
dsps
.amm
.expire_option_token_for_pool(
ctx.call_lpt_address, 0, // Long
ctx.strike_price, ctx.expiry
);
dsps
.amm
.expire_option_token_for_pool(
ctx.call_lpt_address, 1, // Short
ctx.strike_price, ctx.expiry
);

// let call_val = dsps.amm.get_value_of_pool_position(
// ctx.call_lpt_address
// );
// Settle trades on user side
dsps
.amm
.trade_settle(
0, // Call
ctx.strike_price,
ctx.expiry,
0, // Long
one_int,
ctx.usdc_address,
ctx.eth_address,
);

// let put_val = dsps.amm.get_value_of_pool_position(
// ctx.put_lpt_address
// );
dsps
.amm
.trade_settle(
0, // Call
ctx.strike_price,
ctx.expiry,
1, // Short
one_int,
ctx.usdc_address,
ctx.eth_address,
);

let call_val = dsps.amm.get_value_of_pool_expired_position(ctx.call_lpt_address);
// Fetch the AMM state again
let stats_2 = StatsTrait::new(ctx, dsps);

let put_val = dsps.amm.get_value_of_pool_expired_position(ctx.put_lpt_address);
// Assert some stuff
assert(stats_2.locked_capital_c == 0, 'Call pool should have no locked');
}

0 comments on commit 753ad22

Please sign in to comment.