From 1c693ef966d1b0eafe5777b8bd7bffbc48906b69 Mon Sep 17 00:00:00 2001 From: Illia Likhoshva Date: Tue, 28 Feb 2023 14:59:56 +0200 Subject: [PATCH 1/5] Move all strategy calculation to strategy contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnedeed code Add «Approve» method for pool tokens --- contract_lambdas/Admin_lambdas.json | 6 +- contract_lambdas/Strategy_lambdas.json | 12 -- contracts/compiled/dex4factory.tz | 221 +++++++---------------- contracts/partials/admin/lambdas.ligo | 21 +++ contracts/partials/admin/methods.ligo | 5 +- contracts/partials/admin/types.ligo | 8 + contracts/partials/constants.ligo | 6 +- contracts/partials/dex_core/helpers.ligo | 12 +- contracts/partials/dex_core/lambdas.ligo | 81 +++++---- contracts/partials/dex_core/math.ligo | 14 +- contracts/partials/dex_core/storage.ligo | 2 +- contracts/partials/errors.ligo | 2 + contracts/partials/factory/helpers.ligo | 5 +- contracts/partials/strategy/helpers.ligo | 178 ++++++++---------- contracts/partials/strategy/lambdas.ligo | 140 +++----------- contracts/partials/strategy/methods.ligo | 5 +- contracts/partials/strategy/types.ligo | 57 +----- 17 files changed, 267 insertions(+), 508 deletions(-) diff --git a/contract_lambdas/Admin_lambdas.json b/contract_lambdas/Admin_lambdas.json index fb8d7e5..7efd66b 100644 --- a/contract_lambdas/Admin_lambdas.json +++ b/contract_lambdas/Admin_lambdas.json @@ -29,10 +29,14 @@ }, { "index": 7, - "name": "add_pool" + "name": "approve_spending" }, { "index": 8, + "name": "add_pool" + }, + { + "index": 9, "name": "set_strategy_factory" } ] diff --git a/contract_lambdas/Strategy_lambdas.json b/contract_lambdas/Strategy_lambdas.json index 1514335..97295af 100644 --- a/contract_lambdas/Strategy_lambdas.json +++ b/contract_lambdas/Strategy_lambdas.json @@ -5,18 +5,6 @@ }, { "index": 1, - "name": "connect_token_to_strategy" - }, - { - "index": 2, - "name": "update_token_strategy_params" - }, - { - "index": 3, - "name": "set_rebalance" - }, - { - "index": 4, "name": "strategy_rebalance" } ] diff --git a/contracts/compiled/dex4factory.tz b/contracts/compiled/dex4factory.tz index 7d6b3d5..b312261 100644 --- a/contracts/compiled/dex4factory.tz +++ b/contracts/compiled/dex4factory.tz @@ -2,31 +2,21 @@ (or (or (or %factory_action (big_map %copy_dex_function nat bytes) (unit %freeze)) (or %use_admin (or (or (pair %add_rem_managers (bool %add) (address %candidate)) - (pair %claim_developer - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (pair %approve_spending + (nat %pool_id) + (nat %token_id) + (address %spender) (nat %amount))) - (or (pair %ramp_A (nat %pool_id) (nat %future_A) (timestamp %future_time)) - (address %set_admin))) - (or (or (address %set_default_referral) - (pair %set_fees (nat %pool_id) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)))) - (nat %stop_ramp_A)))) + (or (pair %claim_developer + (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (nat %amount)) + (pair %ramp_A (nat %pool_id) (nat %future_A) (timestamp %future_time)))) + (or (or (address %set_admin) (address %set_default_referral)) + (or (pair %set_fees (nat %pool_id) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f))) + (nat %stop_ramp_A))))) (or (or %use_strategy - (or (or (pair %connect_strategy (nat %pool_id) (option %strategy_contract address)) - (pair %connect_token_strategy - (nat %pool_id) - (nat %pool_token_id) - (nat %lending_market_id))) - (or (pair %rebalance (nat %pool_id) (set %pool_token_ids nat)) - (pair %set_token_strategy - (nat %pool_id) - (nat %pool_token_id) - (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest)))) - (pair %set_token_strategy_rebalance - (nat %pool_id) - (nat %pool_token_id) - (bool %flag))) + (pair %connect_strategy (nat %pool_id) (option %strategy_contract address)) + (pair %rebalance (nat %pool_id) (set %pool_token_ids nat))) (or %user_action (or %use_dex (or (or (pair %claim_referral @@ -104,16 +94,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -194,8 +175,6 @@ COMPARE ; EQ ; IF { DROP } { FAILWITH } } - { DIG 5 ; DROP 2 } } - { IF_LEFT { DROP ; DIG 4 ; DUP 3 ; @@ -204,7 +183,9 @@ SENDER ; COMPARE ; EQ ; - IF { DROP } { FAILWITH } } + IF { DROP } { FAILWITH } } } + { IF_LEFT + { DIG 5 ; DROP 2 } { DROP ; DIG 4 ; DUP 3 ; @@ -234,25 +215,35 @@ COMPARE ; EQ ; IF { DROP } { FAILWITH } } } - { DROP ; - DIG 4 ; - DUP 3 ; - CAR ; - CAR ; - SENDER ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } } } ; + { IF_LEFT + { DROP ; + DIG 4 ; + DUP 3 ; + CAR ; + CAR ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } } + { DROP ; + DIG 4 ; + DUP 3 ; + CAR ; + CAR ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } } } } ; DUP 2 ; GET 5 ; DUP 2 ; IF_LEFT { IF_LEFT - { IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 2 } } - { IF_LEFT { DROP ; PUSH nat 3 } { DROP ; PUSH nat 1 } } } + { IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 7 } } + { IF_LEFT { DROP ; PUSH nat 2 } { DROP ; PUSH nat 3 } } } { IF_LEFT - { IF_LEFT { DROP ; PUSH nat 6 } { DROP ; PUSH nat 5 } } - { DROP ; PUSH nat 4 } } ; + { IF_LEFT { DROP ; PUSH nat 1 } { DROP ; PUSH nat 6 } } + { IF_LEFT { DROP ; PUSH nat 5 } { DROP ; PUSH nat 4 } } } ; GET ; IF_NONE { DIG 3 ; FAILWITH } { DIG 4 ; DROP } ; DIG 3 ; @@ -260,14 +251,18 @@ UNPACK (lambda (pair (or (or (or (pair %add_rem_managers (bool %add) (address %candidate)) - (pair %claim_developer - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (pair %approve_spending + (nat %pool_id) + (nat %token_id) + (address %spender) (nat %amount))) - (or (pair %ramp_A (nat %pool_id) (nat %future_A) (timestamp %future_time)) - (address %set_admin))) - (or (or (address %set_default_referral) - (pair %set_fees (nat %pool_id) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)))) - (nat %stop_ramp_A))) + (or (pair %claim_developer + (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (nat %amount)) + (pair %ramp_A (nat %pool_id) (nat %future_A) (timestamp %future_time)))) + (or (or (address %set_admin) (address %set_default_referral)) + (or (pair %set_fees (nat %pool_id) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f))) + (nat %stop_ramp_A)))) (address %admin) (address %default_referral) (set %managers address) @@ -286,16 +281,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -336,16 +322,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -399,33 +376,15 @@ DUP 2 ; GET 10 ; DUP 2 ; - IF_LEFT - { IF_LEFT - { IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 1 } } - { IF_LEFT { DROP ; PUSH nat 4 } { DROP ; PUSH nat 2 } } } - { DROP ; PUSH nat 3 } ; + IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 2 } ; GET ; IF_NONE { DIG 3 ; FAILWITH } { DIG 4 ; DROP } ; DIG 3 ; SWAP ; UNPACK (lambda - (pair (or (or (or (pair %connect_strategy (nat %pool_id) (option %strategy_contract address)) - (pair %connect_token_strategy - (nat %pool_id) - (nat %pool_token_id) - (nat %lending_market_id))) - (or (pair %rebalance (nat %pool_id) (set %pool_token_ids nat)) - (pair %set_token_strategy - (nat %pool_id) - (nat %pool_token_id) - (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest)))) - (pair %set_token_strategy_rebalance - (nat %pool_id) - (nat %pool_token_id) - (bool %flag))) + (pair (or (pair %connect_strategy (nat %pool_id) (option %strategy_contract address)) + (pair %rebalance (nat %pool_id) (set %pool_token_ids nat))) (address %admin) (address %default_referral) (set %managers address) @@ -444,16 +403,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -494,16 +444,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -621,16 +562,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -671,16 +603,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -763,16 +686,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -819,16 +733,7 @@ nat (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %strategy - (option %strat_contract address) - (map %configuration - nat - (pair (nat %des_reserves_rate_f) - (nat %delta_rate_f) - (nat %min_invest) - (nat %strategy_reserves) - (bool %is_rebalance) - (bool %connected)))) + (option %strategy address) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -958,7 +863,7 @@ timestamp (map nat (pair nat nat nat)) (pair nat nat nat) - (pair (option address) (map nat (pair nat nat nat nat bool bool))) + (option address) (pair (map nat nat) (map nat nat) nat) nat)) nat diff --git a/contracts/partials/admin/lambdas.ligo b/contracts/partials/admin/lambdas.ligo index 01d5594..a00f0b8 100644 --- a/contracts/partials/admin/lambdas.ligo +++ b/contracts/partials/admin/lambdas.ligo @@ -143,3 +143,24 @@ function claim_dev( ] } with (operations, s) +(* [Dis-]Approve spending of pool tokens *) +function approve_spending( + const p : admin_action_t; + var s : storage_t) + : return_t is + block { + var operations: list(operation) := Constants.no_operations; + case p of [ + | Approve_spending(params) -> { + const tokens : tokens_map_t = unwrap(s.tokens[params.pool_id], Errors.Dex.pool_not_listed); + + operations := typed_approve( + Tezos.get_self_address(), + params.spender, + params.amount, + unwrap(tokens[params.token_id], Errors.Dex.wrong_index) + ) # operations; + } + | _ -> unreachable(Unit) + ] + } with (operations, s) \ No newline at end of file diff --git a/contracts/partials/admin/methods.ligo b/contracts/partials/admin/methods.ligo index 7e8310f..fe52d34 100644 --- a/contracts/partials/admin/methods.ligo +++ b/contracts/partials/admin/methods.ligo @@ -25,9 +25,10 @@ | Stop_ramp_A(_) -> 4n | Set_fees(_) -> 5n | Set_default_referral(_) -> 6n + | Approve_spending(_) -> 7n #if !FACTORY - | Add_pool(_) -> 7n - | Set_strategy_factory(_) -> 8n + | Add_pool(_) -> 8n + | Set_strategy_factory(_) -> 9n #endif ]; diff --git a/contracts/partials/admin/types.ligo b/contracts/partials/admin/types.ligo index 5e0c73b..b90a703 100644 --- a/contracts/partials/admin/types.ligo +++ b/contracts/partials/admin/types.ligo @@ -23,6 +23,13 @@ type init_param_t is [@layout:comb] record [ ] #endif +type approve_spending_param_t is [@layout:comb] record [ + pool_id : nat; + token_id : nat; + spender : address; + amount : nat; +] + type admin_action_t is | Add_rem_managers of set_cand_param_t | Set_admin of address @@ -31,6 +38,7 @@ type admin_action_t is | Stop_ramp_A of nat | Set_fees of set_fee_param_t | Set_default_referral of address +| Approve_spending of approve_spending_param_t #if !FACTORY | Add_pool of init_param_t (* sets initial liquidity *) | Set_strategy_factory of set_cand_param_t diff --git a/contracts/partials/constants.ligo b/contracts/partials/constants.ligo index 2cb5d63..776f47b 100644 --- a/contracts/partials/constants.ligo +++ b/contracts/partials/constants.ligo @@ -4,11 +4,11 @@ const dex_func_count : nat = 7n; const dev_func_count : nat = 2n; const token_func_count : nat = 5n; -const strat_func_count : nat = 5n; +const strat_func_count : nat = 2n; #if !FACTORY -const admin_func_count : nat = 9n; +const admin_func_count : nat = 10n; #else -const admin_func_count : nat = 7n; +const admin_func_count : nat = 8n; #endif (* StableSwap constants *) diff --git a/contracts/partials/dex_core/helpers.ligo b/contracts/partials/dex_core/helpers.ligo index 1d6db40..600f18a 100644 --- a/contracts/partials/dex_core/helpers.ligo +++ b/contracts/partials/dex_core/helpers.ligo @@ -216,10 +216,7 @@ function get_pool_info( ref_f = 0n; stakers_f = 0n; ]; - strategy = record [ - strat_contract = (None: option(address)); - configuration = (map []: map(token_pool_idx_t, strategy_storage_t)); - ]; + strategy = (None: option(address)); staker_accumulator = record [ accumulator_f = (map []: map(token_pool_idx_t, nat)); total_fees = (map []: map(token_pool_idx_t, nat)); @@ -249,4 +246,9 @@ function check_shares_and_reserves( then failwith(Errors.Dex.supply_drained) else if pool.total_supply > 0n and reserves_sum = 0n then failwith(Errors.Dex.reserves_drained) - else Unit; \ No newline at end of file + else Unit; + +[@inline] function map_reserves( + const tokens_info : map(token_pool_idx_t, token_info_t)) + : map(token_pool_idx_t, nat) is + Map.map(function (const _:token_pool_idx_t; const v: token_info_t) is v.reserves, tokens_info); \ No newline at end of file diff --git a/contracts/partials/dex_core/lambdas.ligo b/contracts/partials/dex_core/lambdas.ligo index 538e716..05d7025 100644 --- a/contracts/partials/dex_core/lambdas.ligo +++ b/contracts/partials/dex_core/lambdas.ligo @@ -20,8 +20,10 @@ function swap( require(i < tokens_count and j < tokens_count, Errors.Dex.wrong_index); const receiver = unwrap_or(params.receiver, Tezos.get_sender()); var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); + // dy - tokens from swap i to j calculation const dy = perform_swap(i, j, dx, pool); const pool_total_staked = pool.staker_accumulator.total_staked; + // slice swap fees const after_fees = slice_fee(dy, pool.fee, get_dev_fee(s), pool_total_staked); var to_stakers_f := 0n; if pool_total_staked > 0n @@ -52,29 +54,34 @@ function swap( token_info_j.reserves := nat_or_error(token_info_j.reserves - after_fees.dy, Errors.Dex.no_liquidity); pool.tokens_info[i] := token_info_i; pool.tokens_info[j] := token_info_j; + + // transfer tokens to user (operations stack, reverse ordering) operations := typed_transfer( Tezos.get_self_address(), receiver, after_fees.dy, token_j ) # operations; - const rebalance = operate_with_strategy( - map[ - i -> token_info_i; - j -> token_info_j - ], - s.tokens[params.pool_id], - pool.strategy, - False - ); - operations := concat_lists(rebalance.0, operations); + + // check and rebalance if needed before sending to user (operations stack, reverse ordering) + operations := case check_rebalansing_strategy( + pool.strategy, + map [ + i -> token_info_i.reserves; + j -> token_info_j.reserves + ] + ) of [ + | Some(op) -> op # operations + | None -> operations + ]; + + // transfer tokens from user (operations stack, reverse ordering) operations := typed_transfer( Tezos.get_sender(), Tezos.get_self_address(), dx, unwrap(tokens[i], Errors.Dex.no_token) ) # operations; - pool.strategy := rebalance.1; s.pools[params.pool_id] := pool; const event_params: swap_event_t = record[ pool_id = params.pool_id; @@ -85,6 +92,7 @@ function swap( receiver = receiver; referral = referral; ]; + // emit swap event operations := emit_event(SwapEvent(event_params)) # operations; } | _ -> unreachable(Unit) @@ -163,17 +171,14 @@ function divest_liquidity( const tokens : tokens_map_t = unwrap(s.tokens[params.pool_id], Errors.Dex.pool_not_listed); const res = Map.fold(divest_reserves, tokens, record [ tok_inf = pool.tokens_info; op = operations; outs = (map[]: map(token_pool_idx_t, nat)) ]); pool.tokens_info := res.tok_inf; - const rebalance = operate_with_strategy( - pool.tokens_info, - s.tokens[params.pool_id], - pool.strategy, - False - ); - operations := concat_lists( - rebalance.0, - res.op - ); - pool.strategy := rebalance.1; + operations := case check_rebalansing_strategy( + pool.strategy, + map_reserves(pool.tokens_info) + ) of [ + | Some(op) -> op # res.op + | None -> res.op + ]; + pool.total_supply := nat_or_error(pool.total_supply - params.shares, Errors.Dex.low_total_supply); const key = (Tezos.get_sender(), params.pool_id); @@ -303,14 +308,13 @@ function divest_imbalanced( total_supply = nat_or_error(token_supply - burn_amount, Errors.Math.nat_error); ]; check_shares_and_reserves(pool); - const rebalance = operate_with_strategy( - balanced.tokens_info, - s.tokens[params.pool_id], - pool.strategy, - False - ); - operations := concat_lists(rebalance.0, operations); - pool.strategy := rebalance.1; + operations := case check_rebalansing_strategy( + pool.strategy, + map_reserves(balanced.tokens_info) + ) of [ + | Some(op) -> op # operations + | None -> operations + ]; s.pools[params.pool_id] := pool; s.ledger[(Tezos.get_sender(), params.pool_id)] := new_shares; const event_params: divest_imb_event_t = record[ @@ -384,22 +388,19 @@ function divest_one_coin( pool.total_supply := result.ts; check_shares_and_reserves(pool); const receiver = unwrap_or(params.receiver, Tezos.get_sender()); - - operations := typed_transfer( Tezos.get_self_address(), receiver, result.dy, token ) # operations; - const rebalance = operate_with_strategy( - map[ params.token_index -> info ], - s.tokens[params.pool_id], - pool.strategy, - False - ); - operations := concat_lists(rebalance.0, operations); - pool.strategy := rebalance.1; + operations := case check_rebalansing_strategy( + pool.strategy, + map [params.token_index -> info.reserves] + ) of [ + | Some(op) -> op # operations + | None -> operations + ]; s.pools[params.pool_id] := pool; const account_bal = unwrap_or(s.ledger[sender_key], 0n); diff --git a/contracts/partials/dex_core/math.ligo b/contracts/partials/dex_core/math.ligo index a2c042a..211f848 100644 --- a/contracts/partials/dex_core/math.ligo +++ b/contracts/partials/dex_core/math.ligo @@ -412,13 +412,13 @@ function add_liq( else operations; pool.total_supply := pool.total_supply + mint_amount; - const (rebalance_ops, strategy_store) = operate_with_strategy( - pool.tokens_info, - tokens[params.pool_id], - pool.strategy, - False - ); - pool.strategy := strategy_store; + const rebalance_ops = case check_rebalansing_strategy( + pool.strategy, + map_reserves(pool.tokens_info) + ) of [ + | Some(op) -> op # Constants.no_operations + | None -> Constants.no_operations + ]; s.pools[params.pool_id] := pool; const receiver = unwrap_or(params.receiver, Tezos.get_sender()); diff --git a/contracts/partials/dex_core/storage.ligo b/contracts/partials/dex_core/storage.ligo index 54c6982..1476e48 100644 --- a/contracts/partials/dex_core/storage.ligo +++ b/contracts/partials/dex_core/storage.ligo @@ -49,7 +49,7 @@ type pool_t is [@layout:comb] record [ tokens_info : map(token_pool_idx_t, token_info_t); fee : fees_storage_t; - strategy : strategy_full_storage_t; + strategy : option(address); staker_accumulator : staker_accum_t; diff --git a/contracts/partials/errors.ligo b/contracts/partials/errors.ligo index 1f7b7cc..eddc284 100644 --- a/contracts/partials/errors.ligo +++ b/contracts/partials/errors.ligo @@ -73,4 +73,6 @@ module Strategy is { const wrong_params : string = "wrong-connect-params-strategy"; const already_connected : string = "token-strategy-connected"; const nothing_to_rebalance : string = "nothing-to-rebalance"; + const no_deposit_view : string = "no-deposit-view"; + const no_should_rebalance_view : string = "no-should-rebalance-view"; } \ No newline at end of file diff --git a/contracts/partials/factory/helpers.ligo b/contracts/partials/factory/helpers.ligo index 36d3bed..3f94cac 100644 --- a/contracts/partials/factory/helpers.ligo +++ b/contracts/partials/factory/helpers.ligo @@ -130,10 +130,7 @@ function form_pool_storage( future_A_time = Tezos.get_now(); tokens_info = tokens_info; fee = fees; - strategy = record[ - strat_contract = (None: option(address)); - configuration = (map[]: map(token_pool_idx_t, strategy_storage_t)); - ]; + strategy = (None: option(address)); staker_accumulator = record [ accumulator_f = (map []: map(token_pool_idx_t, nat)); total_fees = (map []: map(token_pool_idx_t, nat)); diff --git a/contracts/partials/strategy/helpers.ligo b/contracts/partials/strategy/helpers.ligo index 9ef5fc8..72f98b3 100644 --- a/contracts/partials/strategy/helpers.ligo +++ b/contracts/partials/strategy/helpers.ligo @@ -1,134 +1,98 @@ -function check_strategy_bounds( - const reserves : nat; - const virtual_reserves: nat; - const desired_rate_f : nat; - const delta_rate_f : nat) - : bool is - block { - const rate_f = virtual_reserves * Constants.precision / reserves; - } with abs(rate_f - desired_rate_f) < delta_rate_f - -function calculate_desired_reserves( - const reserves : nat; - const strat_token_conf: strategy_storage_t) - : nat is - block { - const desired_reserves : nat = reserves * strat_token_conf.des_reserves_rate_f / Constants.precision; - // require(check_strategy_bounds( - // reserves, - // desired_reserves, - // strat_token_conf.des_reserves_rate_f, - // strat_token_conf.delta_rate_f - // ), Errors.Strategy.out_of_delta_bounds); - } with if desired_reserves > strat_token_conf.min_invest - then desired_reserves - else 0n - -[@inline] function get_prepare_entrypoint( - const strategy_address: address) - : contract(list(nat)) is - unwrap( - (Tezos.get_entrypoint_opt("%prepare", strategy_address): option(contract(list(nat)))), - Errors.Strategy.no_prepare_entrypoint - ); [@inline] function get_update_state_entrypoint( const strategy_address: address) - : contract(upd_strat_state_t) is + : contract(upd_state_t) is unwrap( - (Tezos.get_entrypoint_opt("%update_token_state", strategy_address): option(contract(upd_strat_state_t))), + (Tezos.get_entrypoint_opt("%update_state", strategy_address): option(contract(upd_state_t))), Errors.Strategy.no_update_state_entrypoint ); -[@inline] function get_update_token_info_entrypoint( +[@inline] function get_virtual_reserves_map( const strategy_address: address) - : contract(strat_upd_info_t) is + : map(token_pool_idx_t, nat) is unwrap( - (Tezos.get_entrypoint_opt("%update_token_info", strategy_address): option(contract(strat_upd_info_t))), - Errors.Strategy.no_update_state_entrypoint + (Tezos.call_view("deposit_map", Unit, strategy_address): option(map(token_pool_idx_t, nat))), + Errors.Strategy.no_deposit_view ); +function zero_reserves_guard(const strategy: address) is + block { + // call strategy view for deposited reserves + const virtual_reserves = get_virtual_reserves_map(strategy); + } with Map.iter( + function (const _: token_pool_idx_t; const deposited_reserves: nat): unit is + require(deposited_reserves = 0n, Errors.Strategy.unclaimed_reserves), + virtual_reserves + ); + function check_strategy_pool_params( const pool_id : nat; + const tokens: tokens_map_t; const strategy: address): bool is block { const expected: strat_pool_data_t = record[ pool_contract = Tezos.get_self_address(); - pool_id = pool_id + pool_id = pool_id; + token_map = tokens ]; + const response: strat_pool_data_t = unwrap( (Tezos.call_view("get_pool_data", Unit, strategy): option(strat_pool_data_t)), Errors.Strategy.wrong_params ); - } with response = expected + const match_tokens = Map.fold( + function (const acc: bool; const entry: token_pool_idx_t * token_t): bool is + block { + const (token_id, response_token) = entry; + const expected_token = unwrap(expected.token_map[token_id], Errors.Strategy.wrong_params); + const is_same = response_token = expected_token; + } with acc and is_same, + response.token_map, + True + ); + + const match = response.pool_contract = expected.pool_contract + and response.pool_id = expected.pool_id + and match_tokens; + } with match + +function get_should_rebalance( + const strategy: address; + const tokens : map(token_pool_idx_t, nat)) + : bool is + unwrap( + (Tezos.call_view("should_rebalance", tokens, strategy): option(bool)), + Errors.Strategy.no_should_rebalance_view + ) function operate_with_strategy( - const token_infos : map(token_pool_idx_t, token_info_t); - const tokens_map_entry: option(tokens_map_t); - var strategy : strategy_full_storage_t; + const tokens : map(token_pool_idx_t, nat); + const strategy : address; const manual : bool) - : list(operation) * strategy_full_storage_t is - block { - var ops := Constants.no_operations; - case strategy.strat_contract of [ - Some(contract) -> { - var rebalance_params: upd_strat_state_t := list[]; - var prepare_params: list(nat) := list[]; - var send_ops: list(operation) := list[]; - for token_id -> info in map token_infos { - case strategy.configuration[token_id] of [ - Some(config) -> { - var new_s_reserves := config.strategy_reserves; - const in_bounds = check_strategy_bounds( - info.reserves, - config.strategy_reserves, - config.des_reserves_rate_f, - config.delta_rate_f - ); - if (config.is_rebalance or manual) and not in_bounds - then { - new_s_reserves := calculate_desired_reserves(info.reserves, config); - rebalance_params := record[ - pool_token_id = token_id; - new_balance = new_s_reserves - ] # rebalance_params; - prepare_params := token_id # prepare_params; - case is_nat(new_s_reserves - config.strategy_reserves) of [ - | Some(value) -> { - // send additional reserves to Yupana through Strategy - if value > 0n - then send_ops := typed_transfer( - Tezos.get_self_address(), - contract, - value, - get_token_by_id(token_id, tokens_map_entry) - ) # send_ops; - } - | _ -> skip - ]; - }; - strategy.configuration[token_id] := config with record[ - strategy_reserves = new_s_reserves - ]; - } - | _ -> skip - ] - }; - if List.size(rebalance_params) > 0n - then { - ops := list [ - Tezos.transaction(prepare_params, 0mutez, get_prepare_entrypoint(contract)); - Tezos.transaction(rebalance_params, 0mutez, get_update_state_entrypoint(contract)); - ]; - if List.size(send_ops) > 0n - then ops := concat_lists( - send_ops, - ops - ); - } - } - | None -> skip - ] - } with (ops, strategy) \ No newline at end of file + : operation is + Tezos.transaction( + (record[ + tokens = tokens; + manual = manual + ]: upd_state_t), + 0mutez, + get_update_state_entrypoint(strategy) + ) + + +function check_rebalansing_strategy( + const strategy : option(address); + const tokens_to_rebalance : map(token_pool_idx_t, nat)) + : option(operation) is + case strategy of [ + | Some(strategy) -> if get_should_rebalance(strategy, tokens_to_rebalance) + then Some(operate_with_strategy( + tokens_to_rebalance, + strategy, + False + )) + else None + | None -> None + ]; \ No newline at end of file diff --git a/contracts/partials/strategy/lambdas.ligo b/contracts/partials/strategy/lambdas.ligo index 42bde0f..f6b73b3 100644 --- a/contracts/partials/strategy/lambdas.ligo +++ b/contracts/partials/strategy/lambdas.ligo @@ -1,12 +1,3 @@ -const default_strategy_configuration = record [ - des_reserves_rate_f = 0n; - delta_rate_f = 0n; - min_invest = 0n; - strategy_reserves = 0n; - is_rebalance = True; - connected = False; -] - function connect_strategy( const p : strategy_action_t; var s : storage_t) @@ -16,19 +7,24 @@ function connect_strategy( case p of [ | Connect_strategy(params) -> { var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); - function check_reserves( - const _token_id : token_pool_idx_t; - const config : strategy_storage_t) - : unit is - require(config.strategy_reserves = 0n, Errors.Strategy.unclaimed_reserves); - Map.iter(check_reserves, pool.strategy.configuration); - pool.strategy.strat_contract := case params.strategy_contract of [ - | Some(addr) -> { - const is_registered_strategy = check_is_registered_strategy(addr, s); - const is_pool_params_correct = check_strategy_pool_params(params.pool_id, addr); + const tokens = unwrap(s.tokens[params.pool_id], Errors.Dex.pool_not_listed); + // check pool for existing strategy + case pool.strategy of [ + | Some(strategy) -> zero_reserves_guard(strategy) + | None -> skip + ]; + + pool.strategy := case params.strategy_contract of [ + // set new strategy address + | Some(strategy) -> { + // check that one of factories know about new strategy contract + const is_registered_strategy = check_is_registered_strategy(strategy, s); + // check that new strategy contract has correct pool configuration + const is_pool_params_correct = check_strategy_pool_params(params.pool_id, tokens, strategy); require(is_registered_strategy, Errors.Strategy.not_registered); require(is_pool_params_correct, Errors.Strategy.wrong_params); } with params.strategy_contract + // or remove old | None -> params.strategy_contract ]; s.pools[params.pool_id] := pool; @@ -37,86 +33,6 @@ function connect_strategy( ] } with (operations, s) -function connect_token_to_strategy( - const p : strategy_action_t; - var s : storage_t) - : return_t is - block { - var operations: list(operation) := Constants.no_operations; - case p of [ - | Connect_token_strategy(params) -> { - var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); - var token_config := unwrap( - pool.strategy.configuration[params.pool_token_id], - Errors.Strategy.unknown_token - ); - require(not token_config.connected, Errors.Strategy.already_connected); - const token = get_token_by_id( - params.pool_token_id, - s.tokens[params.pool_id] - ); - const strategy = unwrap(pool.strategy.strat_contract, Errors.Strategy.no_connected_strategy); - const connect_token_params: strat_upd_info_t = record[ - token = token; - pool_token_id = params.pool_token_id; - lending_market_id = params.lending_market_id - ]; - operations := Tezos.transaction( - connect_token_params, - 0mutez, - get_update_token_info_entrypoint(strategy) - ) # operations; - token_config.connected := True; - pool.strategy.configuration[params.pool_token_id] := token_config; - s.pools[params.pool_id] := pool; - } - | _ -> unreachable(Unit) - ] - } with (operations, s) - -function update_token_strategy_params( - const p : strategy_action_t; - var s : storage_t) - : return_t is - block { - case p of [ - | Set_token_strategy(params) -> { - var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); - require(params.des_reserves_rate_f + params.delta_rate_f < Constants.precision, Errors.Math.percent_overflow); - pool.strategy.configuration[params.pool_token_id] := unwrap_or( - pool.strategy.configuration[params.pool_token_id], - default_strategy_configuration - ) with record [ - des_reserves_rate_f = params.des_reserves_rate_f; - delta_rate_f = params.delta_rate_f; - min_invest = params.min_invest; - ]; - s.pools[params.pool_id] := pool; - } - | _ -> unreachable(Unit) - ] - } with (Constants.no_operations, s) - -function set_rebalance( - const p : strategy_action_t; - var s : storage_t) - : return_t is - block { - case p of [ - | Set_token_strategy_rebalance(params) -> { - var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); - pool.strategy.configuration[params.pool_token_id] := unwrap( - pool.strategy.configuration[params.pool_token_id], - Errors.Strategy.unknown_token - ) with record [ - is_rebalance = params.flag; - ]; - s.pools[params.pool_id] := pool; - } - | _ -> unreachable(Unit) - ] - } with (Constants.no_operations, s) - function strategy_rebalance( const p : strategy_action_t; var s : storage_t) @@ -126,22 +42,20 @@ function set_rebalance( case p of [ | Rebalance(params) -> { const pool : pool_t = unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); + const strategy = unwrap(pool.strategy, Errors.Strategy.no_connected_strategy); function map_ids( - const acc : map(token_pool_idx_t, token_info_t); + const acc : map(token_pool_idx_t, nat); const i : nat) - : map(token_pool_idx_t, token_info_t) is - Map.add(i, get_token_info(i, pool.tokens_info), acc); - const infos = Set.fold(map_ids, params.pool_token_ids, (map[]: map(token_pool_idx_t, token_info_t))); - const (rebalance_ops, strategy_store) = operate_with_strategy( - infos, - s.tokens[params.pool_id], - pool.strategy, - True - ); - operations := rebalance_ops; - s.pools[params.pool_id] := pool with record[ - strategy = strategy_store - ]; + : map(token_pool_idx_t, nat) is + block { + const info = get_token_info(i, pool.tokens_info); + } with Map.add(i, info.reserves, acc); + const infos = Set.fold(map_ids, params.pool_token_ids, (map[]: map(token_pool_idx_t, nat))); + operations := operate_with_strategy( + infos, + strategy, + True + ) # operations } | _ -> unreachable(Unit) ] diff --git a/contracts/partials/strategy/methods.ligo b/contracts/partials/strategy/methods.ligo index 366944e..5d118c5 100644 --- a/contracts/partials/strategy/methods.ligo +++ b/contracts/partials/strategy/methods.ligo @@ -8,10 +8,7 @@ require(Tezos.get_sender() = dev_address, Errors.Dex.not_developer); const idx : nat = case p of [ | Connect_strategy(_) -> 0n - | Connect_token_strategy(_) -> 1n - | Set_token_strategy(_) -> 2n - | Set_token_strategy_rebalance(_) -> 3n - | Rebalance(_) -> 4n + | Rebalance(_) -> 2n ]; const lambda_bytes : bytes = unwrap(s.strat_lambdas[idx], Errors.Dex.unknown_func); diff --git a/contracts/partials/strategy/types.ligo b/contracts/partials/strategy/types.ligo index da24658..646d1b1 100644 --- a/contracts/partials/strategy/types.ligo +++ b/contracts/partials/strategy/types.ligo @@ -1,20 +1,7 @@ -type strategy_storage_t is [@layout:comb] record[ - des_reserves_rate_f : nat; - delta_rate_f : nat; - min_invest : nat; - strategy_reserves : nat; - is_rebalance : bool; - connected : bool; -]; - -type strategy_full_storage_t is [@layout:comb] record [ - strat_contract : option(address); - configuration : map(token_pool_idx_t, strategy_storage_t) -] - type strat_pool_data_t is [@layout:comb] record[ - pool_contract: address; - pool_id: nat; + pool_contract : address; + pool_id : nat; + token_map : tokens_map_t; ] type conn_strategy_param is [@layout:comb] record [ @@ -22,48 +9,16 @@ type conn_strategy_param is [@layout:comb] record [ strategy_contract : option(address); ] -type conn_tok_strat_param is [@layout:comb] record [ - pool_id : pool_id_t; - pool_token_id : token_pool_idx_t; - lending_market_id : nat; -]; - -type set_tok_strat_param is [@layout:comb] record [ - pool_id : pool_id_t; - pool_token_id : token_pool_idx_t; - des_reserves_rate_f : nat; - delta_rate_f : nat; - min_invest : nat; -] - -type tok_strat_upd_fl_param is [@layout:comb] record [ - pool_id : pool_id_t; - pool_token_id : token_pool_idx_t; - flag : bool; -] - -type upd_state_prm is [@layout:comb] record [ - pool_token_id : nat; - new_balance : nat; +type upd_state_t is [@layout:comb] record [ + tokens : map(token_pool_idx_t, nat); + manual : bool; ] -type upd_strat_state_t is list(upd_state_prm) - type rebalance_param is [@layout:comb] record [ pool_id : pool_id_t; pool_token_ids : set(nat); ] -type strat_upd_info_t is [@layout:comb] record [ - token : token_t; - pool_token_id : token_pool_idx_t; - lending_market_id : nat; -] - - type strategy_action_t is | Connect_strategy of conn_strategy_param -| Connect_token_strategy of conn_tok_strat_param -| Set_token_strategy of set_tok_strat_param -| Set_token_strategy_rebalance of tok_strat_upd_fl_param | Rebalance of rebalance_param \ No newline at end of file From f67471bc6e124c08af89b1a33bc615a6e096482d Mon Sep 17 00:00:00 2001 From: Illia Likhoshva Date: Wed, 1 Mar 2023 14:20:30 +0200 Subject: [PATCH 2/5] Fix method numeric key --- contracts/partials/strategy/methods.ligo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/partials/strategy/methods.ligo b/contracts/partials/strategy/methods.ligo index 5d118c5..0ddda6d 100644 --- a/contracts/partials/strategy/methods.ligo +++ b/contracts/partials/strategy/methods.ligo @@ -8,7 +8,7 @@ require(Tezos.get_sender() = dev_address, Errors.Dex.not_developer); const idx : nat = case p of [ | Connect_strategy(_) -> 0n - | Rebalance(_) -> 2n + | Rebalance(_) -> 1n ]; const lambda_bytes : bytes = unwrap(s.strat_lambdas[idx], Errors.Dex.unknown_func); From a3f90c5d26c66012ec812d005c459787eda5f0d6 Mon Sep 17 00:00:00 2001 From: Illia Likhoshva Date: Mon, 13 Mar 2023 16:06:02 +0200 Subject: [PATCH 3/5] rename strategy view to rebalance_enabled --- contracts/partials/dex_core/lambdas.ligo | 8 ++++---- contracts/partials/dex_core/math.ligo | 2 +- contracts/partials/strategy/helpers.ligo | 8 ++++---- storage/factory.ts | 2 +- test/Factory/API/factoryAPI.ts | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/contracts/partials/dex_core/lambdas.ligo b/contracts/partials/dex_core/lambdas.ligo index 05d7025..83c64ce 100644 --- a/contracts/partials/dex_core/lambdas.ligo +++ b/contracts/partials/dex_core/lambdas.ligo @@ -64,7 +64,7 @@ function swap( ) # operations; // check and rebalance if needed before sending to user (operations stack, reverse ordering) - operations := case check_rebalansing_strategy( + operations := case check_rebalancing_strategy( pool.strategy, map [ i -> token_info_i.reserves; @@ -171,7 +171,7 @@ function divest_liquidity( const tokens : tokens_map_t = unwrap(s.tokens[params.pool_id], Errors.Dex.pool_not_listed); const res = Map.fold(divest_reserves, tokens, record [ tok_inf = pool.tokens_info; op = operations; outs = (map[]: map(token_pool_idx_t, nat)) ]); pool.tokens_info := res.tok_inf; - operations := case check_rebalansing_strategy( + operations := case check_rebalancing_strategy( pool.strategy, map_reserves(pool.tokens_info) ) of [ @@ -308,7 +308,7 @@ function divest_imbalanced( total_supply = nat_or_error(token_supply - burn_amount, Errors.Math.nat_error); ]; check_shares_and_reserves(pool); - operations := case check_rebalansing_strategy( + operations := case check_rebalancing_strategy( pool.strategy, map_reserves(balanced.tokens_info) ) of [ @@ -394,7 +394,7 @@ function divest_one_coin( result.dy, token ) # operations; - operations := case check_rebalansing_strategy( + operations := case check_rebalancing_strategy( pool.strategy, map [params.token_index -> info.reserves] ) of [ diff --git a/contracts/partials/dex_core/math.ligo b/contracts/partials/dex_core/math.ligo index 211f848..7b625b8 100644 --- a/contracts/partials/dex_core/math.ligo +++ b/contracts/partials/dex_core/math.ligo @@ -412,7 +412,7 @@ function add_liq( else operations; pool.total_supply := pool.total_supply + mint_amount; - const rebalance_ops = case check_rebalansing_strategy( + const rebalance_ops = case check_rebalancing_strategy( pool.strategy, map_reserves(pool.tokens_info) ) of [ diff --git a/contracts/partials/strategy/helpers.ligo b/contracts/partials/strategy/helpers.ligo index 72f98b3..a864224 100644 --- a/contracts/partials/strategy/helpers.ligo +++ b/contracts/partials/strategy/helpers.ligo @@ -57,12 +57,12 @@ function check_strategy_pool_params( and match_tokens; } with match -function get_should_rebalance( +function is_strategy_enabled( const strategy: address; const tokens : map(token_pool_idx_t, nat)) : bool is unwrap( - (Tezos.call_view("should_rebalance", tokens, strategy): option(bool)), + (Tezos.call_view("rebalance_enabled", tokens, strategy): option(bool)), Errors.Strategy.no_should_rebalance_view ) @@ -82,12 +82,12 @@ function operate_with_strategy( ) -function check_rebalansing_strategy( +function check_rebalancing_strategy( const strategy : option(address); const tokens_to_rebalance : map(token_pool_idx_t, nat)) : option(operation) is case strategy of [ - | Some(strategy) -> if get_should_rebalance(strategy, tokens_to_rebalance) + | Some(strategy) -> if is_strategy_enabled(strategy, tokens_to_rebalance) then Some(operate_with_strategy( tokens_to_rebalance, strategy, diff --git a/storage/factory.ts b/storage/factory.ts index c3d94e7..d8067bb 100644 --- a/storage/factory.ts +++ b/storage/factory.ts @@ -47,7 +47,7 @@ const factoryDefaultStorage: FactoryStorage = { quipu_rewards: new BigNumber("0"), whitelist: [] as TezosAddress[], deployers: new MichelsonMap(), - strategy_factory: "tz1ZZZZZZZZZZZZZZZZZZZZZZZZZZZZNkiRg", + strategy_factory: [] as TezosAddress[], } as InnerFactoryStore, admin_lambdas: new MichelsonMap(), dex_lambdas: new MichelsonMap(), diff --git a/test/Factory/API/factoryAPI.ts b/test/Factory/API/factoryAPI.ts index 216fc8e..8ed6d68 100644 --- a/test/Factory/API/factoryAPI.ts +++ b/test/Factory/API/factoryAPI.ts @@ -49,7 +49,7 @@ export class DexFactory implements DevEnabledContract, StrategyFactorySetter { factoryAddress, "Admin", 8, - admin_lambdas_comp.filter((value) => value.args[1].int !== "7") + admin_lambdas_comp.filter((value) => value.args[1].int !== "8") ); // await setFunctionBatchCompilled( // tezos, From 95abaece05984e977a6c109dcbdc01170b20e8bd Mon Sep 17 00:00:00 2001 From: Illia Likhoshva Date: Tue, 14 Mar 2023 15:35:01 +0200 Subject: [PATCH 4/5] Revert view name --- contracts/partials/strategy/helpers.ligo | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/partials/strategy/helpers.ligo b/contracts/partials/strategy/helpers.ligo index a864224..b44462b 100644 --- a/contracts/partials/strategy/helpers.ligo +++ b/contracts/partials/strategy/helpers.ligo @@ -57,12 +57,12 @@ function check_strategy_pool_params( and match_tokens; } with match -function is_strategy_enabled( +function get_should_rebalance( const strategy: address; const tokens : map(token_pool_idx_t, nat)) : bool is unwrap( - (Tezos.call_view("rebalance_enabled", tokens, strategy): option(bool)), + (Tezos.call_view("should_rebalance", tokens, strategy): option(bool)), Errors.Strategy.no_should_rebalance_view ) @@ -87,7 +87,7 @@ function check_rebalancing_strategy( const tokens_to_rebalance : map(token_pool_idx_t, nat)) : option(operation) is case strategy of [ - | Some(strategy) -> if is_strategy_enabled(strategy, tokens_to_rebalance) + | Some(strategy) -> if get_should_rebalance(strategy, tokens_to_rebalance) then Some(operate_with_strategy( tokens_to_rebalance, strategy, From 38aff13ccf69b5c8c20e5c5c0f29e53e36fc1cc9 Mon Sep 17 00:00:00 2001 From: Illia Likhoshva Date: Thu, 16 Mar 2023 20:53:48 +0200 Subject: [PATCH 5/5] Fix tests with new strategy contracts --- contracts/compiled/dex4factory.tz | 2 +- scenario/initial_storage.py | 10 +- scenario/test_strategy.py | 78 +- test/00_Dex.test.ts | 240 ++-- test/Dex/API/dexAPI.ts | 86 +- test/Dex/API/types.ts | 2 +- test/Dex/cases/strategy/auto_rebalance.ts | 265 ++-- test/Dex/cases/strategy/before.ts | 96 +- .../cofigure-token/configure_strategy.ts | 67 - .../strategy/cofigure-token/connect_token.ts | 98 -- .../cases/strategy/cofigure-token/index.ts | 3 - .../strategy/cofigure-token/is_rebalance.ts | 29 - .../strategy/cofigure-token/rebalance.ts | 75 +- test/Dex/cases/strategy/connect.ts | 10 +- test/Strategy/API/strategy.types.ts | 86 ++ test/Strategy/API/strategy_factory.types.ts | 50 + test/Strategy/API/type-aliases.ts | 115 ++ test/Strategy/API/type-utils.ts | 58 + test/utils/mocks/artifacts/strategy.tz | 1187 +++++++++------- .../utils/mocks/artifacts/strategy_factory.tz | 1230 +++++++++-------- test/utils/mocks/artifacts/yupana.tz | 73 +- 21 files changed, 2119 insertions(+), 1741 deletions(-) delete mode 100644 test/Dex/cases/strategy/cofigure-token/configure_strategy.ts delete mode 100644 test/Dex/cases/strategy/cofigure-token/connect_token.ts delete mode 100644 test/Dex/cases/strategy/cofigure-token/is_rebalance.ts create mode 100644 test/Strategy/API/strategy.types.ts create mode 100644 test/Strategy/API/strategy_factory.types.ts create mode 100644 test/Strategy/API/type-aliases.ts create mode 100644 test/Strategy/API/type-utils.ts diff --git a/contracts/compiled/dex4factory.tz b/contracts/compiled/dex4factory.tz index b312261..81c9a0f 100644 --- a/contracts/compiled/dex4factory.tz +++ b/contracts/compiled/dex4factory.tz @@ -376,7 +376,7 @@ DUP 2 ; GET 10 ; DUP 2 ; - IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 2 } ; + IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 1 } ; GET ; IF_NONE { DIG 3 ; FAILWITH } { DIG 4 ; DROP } ; DIG 3 ; diff --git a/scenario/initial_storage.py b/scenario/initial_storage.py index 0a425eb..bf81bdd 100644 --- a/scenario/initial_storage.py +++ b/scenario/initial_storage.py @@ -13,8 +13,8 @@ def parse_lambdas(path): return lambdas -admin_lambdas = parse_lambdas("./build/lambdas/Admin_lambdas.json") -dex_lambdas = parse_lambdas("./build/lambdas/Dex_lambdas.json") -token_lambdas = parse_lambdas("./build/lambdas/Token_lambdas.json") -dev_lambdas = parse_lambdas("./build/lambdas/Dev_lambdas.json") -strat_lambdas = parse_lambdas("./build/lambdas/Strategy_lambdas.json") \ No newline at end of file +admin_lambdas = parse_lambdas(os.path.normpath(os.path.dirname(__file__) + "/../build/lambdas/Admin_lambdas.json")) +dex_lambdas = parse_lambdas(os.path.normpath(os.path.dirname(__file__) + "/../build/lambdas/Dex_lambdas.json")) +token_lambdas = parse_lambdas(os.path.normpath(os.path.dirname(__file__) + "/../build/lambdas/Token_lambdas.json")) +dev_lambdas = parse_lambdas(os.path.normpath(os.path.dirname(__file__) + "/../build/lambdas/Dev_lambdas.json")) +strat_lambdas = parse_lambdas(os.path.normpath(os.path.dirname(__file__) + "/../build/lambdas/Strategy_lambdas.json")) \ No newline at end of file diff --git a/scenario/test_strategy.py b/scenario/test_strategy.py index a5aaf79..693c09b 100644 --- a/scenario/test_strategy.py +++ b/scenario/test_strategy.py @@ -11,6 +11,7 @@ from pytezos import ContractInterface, MichelsonRuntimeError from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, strat_lambdas, dev_lambdas +# Tests of Strategy moved to strategy repo as mockup client class DexStrategyTest(TestCase): @classmethod @@ -37,83 +38,6 @@ def setUpClass(cls): cls.init_storage = storage - def test_set_token_params(self): - chain = LocalChain(storage=self.init_storage) - - add_pool = self.dex.add_pool(100_000, [token_a, token_b], form_pool_rates(1_000_000, 1_000_000), { "lp_f": 0, "stakers_f": 0, "ref_f": 0}) - chain.execute(add_pool, sender=admin) - pool_id = 0 - - rates = { - 0: { - "des_reserves_rate_f": Decimal("0.3") * Decimal("1e18"), - "delta_rate_f": Decimal("0.05") * Decimal("1e18"), - "min_invest": 30000 - }, - 1: { - "des_reserves_rate_f": Decimal("0.2") * Decimal("1e18"), - "delta_rate_f": Decimal("0.02") * Decimal("1e18"), - "min_invest": 10000 - } - } - - for token_pool_id, config in rates.items(): - set_strat = self.dex.set_token_strategy( - pool_id, - token_pool_id, - int(config['des_reserves_rate_f']), - int(config['delta_rate_f']), - config['min_invest']) - res = chain.execute(set_strat, sender=dev) - conneced_config = res.storage['storage']['pools'][pool_id]['strategy']['configuration'][token_pool_id] - self.assertEqual(conneced_config, - { - "is_rebalance": True, - "strategy_reserves": 0, - "connected": False, - **config - }) - - def test_set_token_rebalance_flag(self): - chain = LocalChain(storage=self.init_storage) - - add_pool = self.dex.add_pool(100_000, [token_a, token_b], form_pool_rates(1_000_000, 1_000_000), { "lp_f": 0, "stakers_f": 0, "ref_f": 0}) - chain.execute(add_pool, sender=admin) - pool_id = 0 - token_pool_id = 0 - config = { - "des_reserves_rate_f": Decimal("0.3") * Decimal("1e18"), - "delta_rate_f": Decimal("0.05") * Decimal("1e18"), - "min_invest": 30000 - } - set_strat = self.dex.set_token_strategy( - pool_id, - token_pool_id, - int(config['des_reserves_rate_f']), - int(config['delta_rate_f']), - config['min_invest']) - res = chain.execute(set_strat, sender=dev) - conneced_config = res.storage['storage']['pools'][pool_id]['strategy']['configuration'][token_pool_id] - self.assertEqual(conneced_config, - { - "is_rebalance": True, - "strategy_reserves": 0, - "connected": False, - **config - }) - set_reb = self.dex.set_token_strategy_rebalance( - pool_id, - token_pool_id, - False) - res = chain.execute(set_reb, sender=dev) - conneced_config = res.storage['storage']['pools'][pool_id]['strategy']['configuration'][token_pool_id] - self.assertEqual(conneced_config, - { - "is_rebalance": False, - "strategy_reserves": 0, - "connected": False, - **config - }) def test_connect_strategy(self): pytest.skip("Can't simulate intercontract on-chain view calls") diff --git a/test/00_Dex.test.ts b/test/00_Dex.test.ts index 8fbf405..f627199 100644 --- a/test/00_Dex.test.ts +++ b/test/00_Dex.test.ts @@ -19,17 +19,25 @@ import { AmountsMap, IndexMap, TokensMap } from "./utils/types"; import { TokenFA12, TokenFA2 } from "./Token"; import { defaultTokenId } from "./Token/token"; import { Contract } from "@taquito/taquito"; +import { tas } from "./Strategy/API/type-aliases"; +import { StrategyContractType } from "./Strategy/API/strategy.types"; +import { StrategyFactoryContractType } from "./Strategy/API/strategy_factory.types"; describe("00. Standalone Dex", () => { const aliceAddress: TezosAddress = accounts.alice.pkh; const bobAddress: TezosAddress = accounts.bob.pkh; const eveAddress: TezosAddress = accounts.eve.pkh; - const new_admin = eveAddress; - const new_dev = bobAddress; - const manager = aliceAddress; - const staker = bobAddress; - const referral = eveAddress; + const developerName = "bob", + adminName = "eve", + managerName = "alice", + stakerName = "bob", + referralName = "eve"; + const new_admin = accounts[adminName].pkh; + const new_dev = accounts[developerName].pkh; + const manager = accounts[managerName].pkh; + const staker = accounts[stakerName].pkh; + const referral = accounts[referralName].pkh; let tokens: TokensMap; @@ -958,34 +966,82 @@ describe("00. Standalone Dex", () => { let pool_id: BigNumber; let yupana: Contract; let price_feed: Contract; - let strategy_factory: Contract; - let strategy: Contract; + let strategy_factory: StrategyFactoryContractType; + let strategy: StrategyContractType; let yup_ordering: IndexMap; let pool_ordering: IndexMap; beforeAll(async () => { - pool_id = dex.storage.storage.pools_count.minus(new BigNumber(1)); - await dex.updateStorage({ tokens: [pool_id.toString()] }); + const config = await prepareProviderOptions(developerName); + Tezos.setProvider(config); ({ yupana, ordering: yup_ordering, price_feed, } = await TInit.setupYupanaMocks(tokens, Tezos)); + await dex.updateStorage(); + pool_id = dex.storage.storage.pools_count.minus(new BigNumber(1)); + await dex.updateStorage({ tokens: [pool_id.toString()] }); + pool_ordering = mapTokensToIdx( + dex.storage.storage.tokens[pool_id.toString()], + tokens + ); ({ strategy_factory, strategy } = await TInit.originateStrategy( dex, pool_id, + pool_ordering, yupana, - price_feed, + yup_ordering, Tezos )); - pool_ordering = mapTokensToIdx( - dex.storage.storage.tokens[pool_id.toString()], - tokens + await tokens.kUSD.transfer( + new BigNumber(0), + new_dev, + strategy.address, + new BigNumber("1") ); + await ( + await strategy.methods + .approve_token([ + { + pool_token_id: tas.nat(pool_ordering.kUSD.toString()), + spender: tas.address(yupana.address), + amount: tas.nat(new BigNumber("10").pow(256).toString()), + }, + { + pool_token_id: tas.nat(pool_ordering.uUSD.toString()), + spender: tas.address(yupana.address), + amount: tas.nat(new BigNumber("10").pow(256).toString()), + }, + ]) + .send() + ).confirmation(); // eslint-disable-next-line jest/no-standalone-expect await expect(strategy.storage()).resolves.toMatchObject({ factory: strategy_factory.address, }); + const configUser = await prepareProviderOptions(adminName); + Tezos.setProvider(configUser); + const appoveDexTokens = await Tezos.contract + .batch() + .withContractCall( + dex.contract.methods.approve_spending( + pool_id, + pool_ordering.kUSD, + strategy.address, + new BigNumber("1e256").toString() + ) + ) + .withContractCall( + dex.contract.methods.approve_spending( + pool_id, + pool_ordering.uUSD, + strategy.address, + new BigNumber("1e256") + ) + ) + .send(); + await appoveDexTokens.confirmation(); }); describe("as a developer", () => { @@ -1017,6 +1073,8 @@ describe("00. Standalone Dex", () => { let idx_map: IndexMap; beforeAll(async () => { + const config = await prepareProviderOptions("bob"); + Tezos.setProvider(config); ({ pool_id, min_amounts, idx_map } = await TPool.PoolDivest.setupMinTokenMapping(dex, tokens, outputs)); imb_amounts = new Map() @@ -1031,8 +1089,6 @@ describe("00. Standalone Dex", () => { .set(idx_map.USDtz, new BigNumber(1)) .set(idx_map.kUSD, new BigNumber(1)) .set(idx_map.uUSD, new BigNumber(1)); - const config = await prepareProviderOptions("bob"); - Tezos.setProvider(config); await dex.investLiquidity( pool_id, invest_amounts, @@ -1051,46 +1107,6 @@ describe("00. Standalone Dex", () => { it("should connect new strategy factory", async () => TMng.addStrategyFactorySuccessCase(dex, strategy_factory.address)); - it("should fail when set rebalance flag to non cofigured token", async () => - failCase( - "bob", - dex.setTokenStrategyRebalance( - pool_id, - new BigNumber(pool_ordering.kUSD), - false - ), - "no-token-strategy-set" - )); - - it("should configure new strategy for token", async () => - TStrategy.token.configureTokenStrategy - .setStrategyParamsSuccessCase( - dex, - pool_id, - new BigNumber(pool_ordering.kUSD), - new BigNumber("0.3").multipliedBy("1e18"), - new BigNumber("0.005").multipliedBy("1e18"), - new BigNumber("300").multipliedBy(decimals.kUSD) - ) - .then(() => - TStrategy.token.configureTokenStrategy.setStrategyParamsSuccessCase( - dex, - pool_id, - new BigNumber(pool_ordering.uUSD), - new BigNumber("0.15").multipliedBy("1e18"), - new BigNumber("0.003").multipliedBy("1e18"), - new BigNumber("1500").multipliedBy(decimals.uUSD) - ) - )); - - it("should fail connect token to NO strategy", async () => - TStrategy.token.connectTokenToStrategy.connectTokenStrategyFailCaseNoStrategy( - dex, - pool_id, - new BigNumber(pool_ordering.kUSD), - new BigNumber(yup_ordering.kUSD) - )); - it("should connect new strategy", async () => TStrategy.connect.setStrategyAddrSuccessCase( dex, @@ -1098,31 +1114,6 @@ describe("00. Standalone Dex", () => { strategy.address )); - it("should connect token to strategy", async () => - TStrategy.token.connectTokenToStrategy - .connectTokenStrategySuccessCase( - dex, - pool_id, - new BigNumber(pool_ordering.kUSD), - new BigNumber(yup_ordering.kUSD) - ) - .then(() => - TStrategy.token.connectTokenToStrategy.connectTokenStrategySuccessCase( - dex, - pool_id, - new BigNumber(pool_ordering.uUSD), - new BigNumber(yup_ordering.uUSD) - ) - )); - - it("should fail connect same token to strategy", async () => - TStrategy.token.connectTokenToStrategy.connectTokenStrategyFailCaseAdded( - dex, - pool_id, - new BigNumber(pool_ordering.kUSD), - new BigNumber(yup_ordering.kUSD) - )); - it("should call manual rebalance", async () => TStrategy.token.manualRebalanceToken.manualRebalanceSuccessCase( dex, @@ -1177,14 +1168,6 @@ describe("00. Standalone Dex", () => { min_out_amount )); - it("should set is rebalance flag for token", async () => - TStrategy.token.setStrategyRebalance.setIsRebalanceSuccessCase( - dex, - pool_id, - new BigNumber(pool_ordering.kUSD), - false - )); - it("should auto-rebalance when divest", async () => { const sender = await Tezos.signer.publicKeyHash(); const request: { owner: TezosAddress; token_id: number } = { @@ -1207,33 +1190,42 @@ describe("00. Standalone Dex", () => { ); }); - it("should configure strategy for token to zero", async () => - TStrategy.token.configureTokenStrategy - .setStrategyParamsToZeroSuccessCase( - dex, - pool_id, - new BigNumber(pool_ordering.kUSD) + it("should call manual rebalance after set to zero", async () => + Tezos.contract + .batch() + .withContractCall( + strategy.methodsObject.update_token_config({ + pool_token_id: tas.nat(pool_ordering.kUSD), + desired_reserves_rate_f: tas.nat(0), + delta_rate_f: tas.nat(0), + min_invest: tas.nat(0), + enabled: true, + }) + ) + .withContractCall( + strategy.methodsObject.update_token_config({ + pool_token_id: tas.nat(pool_ordering.uUSD), + desired_reserves_rate_f: tas.nat(0), + delta_rate_f: tas.nat(0), + min_invest: tas.nat(0), + enabled: true, + }) ) + .send() + .then((op) => op.confirmation()) .then(() => - TStrategy.token.configureTokenStrategy.setStrategyParamsToZeroSuccessCase( + TStrategy.token.manualRebalanceToken.manualRebalanceSuccessCase( dex, + yupana, + strategy, pool_id, - new BigNumber(pool_ordering.uUSD) + new Set([ + new BigNumber(pool_ordering.kUSD), + new BigNumber(pool_ordering.uUSD), + ]) ) )); - it("should call manual rebalance after set to zero", async () => - TStrategy.token.manualRebalanceToken.manualRebalanceSuccessCase( - dex, - yupana, - strategy, - pool_id, - new Set([ - new BigNumber(pool_ordering.kUSD), - new BigNumber(pool_ordering.uUSD), - ]) - )); - it("should disconnect strategy", async () => TStrategy.connect.removeStrategyAddrSuccessCase(dex, pool_id)); }); @@ -1246,43 +1238,11 @@ describe("00. Standalone Dex", () => { // eslint-disable-next-line jest/prefer-expect-assertions it("should fail when non-developer call the stategy EP", async () => { - await failCase( - "eve", - async () => - await dex.setTokenStrategyRebalance( - pool_id, - new BigNumber(pool_ordering.kUSD), - false - ), - "not-developer" - ); await failCase( "eve", async () => await dex.connectStrategy(pool_id, strategy.address), "not-developer" ); - await failCase( - "eve", - async () => - await dex.connectTokenStrategy( - pool_id, - new BigNumber(pool_ordering.kUSD), - new BigNumber(0) - ), - "not-developer" - ); - await failCase( - "eve", - async () => - await dex.setTokenStrategy( - pool_id, - new BigNumber(pool_ordering.kUSD), - new BigNumber("0.3").multipliedBy("1e18"), - new BigNumber("0.05").multipliedBy("1e18"), - new BigNumber("300").multipliedBy("1e6") - ), - "not-developer" - ); const set = new Set([new BigNumber(pool_ordering.kUSD)]); await failCase( "eve", diff --git a/test/Dex/API/dexAPI.ts b/test/Dex/API/dexAPI.ts index 53634b1..198c020 100644 --- a/test/Dex/API/dexAPI.ts +++ b/test/Dex/API/dexAPI.ts @@ -397,55 +397,6 @@ export class Dex return operation; } - async setTokenStrategy( - poolId: BigNumber, - poolTokenId: BigNumber, - desiredReservesRate_f: BigNumber, - deltaRate_f: BigNumber, - minInvestment: BigNumber - ): Promise { - await this.updateStorage({}); - const operation = await this.contract.methodsObject - .set_token_strategy({ - pool_id: poolId.toString(), - pool_token_id: poolTokenId.toString(), - des_reserves_rate_f: desiredReservesRate_f.toString(), - delta_rate_f: deltaRate_f.toString(), - min_invest: minInvestment.toString(), - }) - .send(); - - await operation.confirmation(2); - // await confirmOperation(tezos, operation.hash); - return operation; - } - - async setTokenStrategyRebalance( - poolId: BigNumber, - poolTokenId: BigNumber, - flag: boolean - ): Promise { - await this.updateStorage({}); - const operation = await this.contract.methods - .set_token_strategy_rebalance( - poolId.toString(), - poolTokenId.toString(), - flag - ) - .send(); - - await operation.confirmation(2); - // await confirmOperation(tezos, operation.hash); - return operation; - } - - setIsRebalanceStrategy = ( - poolId: BigNumber, - poolTokenId: BigNumber, - flag: boolean - ): Promise => - this.setTokenStrategyRebalance(poolId, poolTokenId, flag); - async rebalance( poolId: BigNumber, poolTokenIds: Set @@ -468,25 +419,6 @@ export class Dex poolTokenIds: Set ): Promise => this.rebalance(poolId, poolTokenIds); - async connectTokenStrategy( - poolId: BigNumber, - poolTokenId: BigNumber, - lendingMarketId: BigNumber - ): Promise { - await this.updateStorage({}); - const operation = await this.contract.methodsObject - .connect_token_strategy({ - pool_id: poolId.toString(), - pool_token_id: poolTokenId.toString(), - lending_market_id: lendingMarketId.toString(), - }) - .send(); - - await operation.confirmation(2); - // await confirmOperation(tezos, operation.hash); - return operation; - } - async setFees( pool_id: BigNumber, fees: FeeType @@ -519,8 +451,7 @@ export class Dex address: string ): Promise { await this.updateStorage(); - const token = await this.Tezos.contract.at(tokenAddress); - const operation = await token.methods + const operation = await this.contract.methods .update_operators([ { [tokenAmount ? "add_operator" : "remove_operator"]: { @@ -535,6 +466,21 @@ export class Dex return operation; } + async approveUnderlying( + poolId: BigNumber, + tokenId: BigNumber, + spender: string, + amount: BigNumber + + ): Promise { + await this.updateStorage(); + const operation = await this.contract.methods + .approve_spending(poolId, tokenId, spender, amount) + .send(); + await operation.confirmation(); + return operation; + } + async approveFA12Token( tokenAddress: string, tokenAmount: number, diff --git a/test/Dex/API/types.ts b/test/Dex/API/types.ts index 777f282..2ddacaf 100644 --- a/test/Dex/API/types.ts +++ b/test/Dex/API/types.ts @@ -45,7 +45,7 @@ export declare type PairInfo = { tokens_info: MichelsonMap; fee: FeeType; - strategy: StrategyStoreType; + strategy?: string; staker_accumulator: { accumulator_f: MichelsonMap; total_staked: BigNumber; diff --git a/test/Dex/cases/strategy/auto_rebalance.ts b/test/Dex/cases/strategy/auto_rebalance.ts index 02d6872..05ed6c2 100644 --- a/test/Dex/cases/strategy/auto_rebalance.ts +++ b/test/Dex/cases/strategy/auto_rebalance.ts @@ -1,39 +1,50 @@ import BigNumber from "bignumber.js"; -import { Contract, OpKind, TransactionOperation } from "@taquito/taquito"; +import { + BatchOperation, + Contract, + OpKind, + TransactionOperation, +} from "@taquito/taquito"; import { OperationContentsAndResultTransaction, InternalOperationResult, } from "@taquito/rpc"; import Dex from "../../API"; import { PairInfo } from "../../API/types"; +import { + Storage as StrategyStorage, + StrategyContractType, +} from "../../../Strategy/API/strategy.types"; +import { tas } from "../../../Strategy/API/type-aliases"; +import { MichelsonMap } from '@taquito/taquito'; async function autoRebalanceCheck( dex: Dex, yupana: Contract, strategy: Contract, pool_id: BigNumber, - operation: TransactionOperation + operation: BatchOperation ) { await dex.updateStorage({ pools: [pool_id.toString()] }); const pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; + const strategyStorage = (await strategy.storage()) as StrategyStorage; const internals = ( - operation.results[0] as OperationContentsAndResultTransaction + operation.results[operation.results.length -1] as OperationContentsAndResultTransaction ).metadata.internal_operation_results; - console.debug(internals); - expect( - internals.find( - (x: InternalOperationResult) => - x.kind === OpKind.TRANSACTION && - x.parameters?.entrypoint === "prepare" && - x.destination == strategy.address && - x.source === dex.contract.address - ) - ).toMatchObject({ result: { status: "applied" } }); + // expect( + // internals.find( + // (x: InternalOperationResult) => + // x.kind === OpKind.TRANSACTION && + // x.parameters?.entrypoint === "prepare" && + // x.destination == strategy.address && + // x.source === dex.contract.address + // ) + // ).toMatchObject({ result: { status: "applied" } }); expect( internals.find( (x) => x.kind === OpKind.TRANSACTION && - x.parameters?.entrypoint === "update_token_state" && + x.parameters?.entrypoint === "update_state" && x.destination == strategy.address && x.source === dex.contract.address ) @@ -48,24 +59,25 @@ async function autoRebalanceCheck( x.source === strategy.address ) .forEach((y) => expect(y).toMatchObject({ result: { status: "applied" } })); - pool.strategy.configuration.forEach((value, key) => { - const on_strat = value.strategy_reserves; - const full_res = pool.tokens_info.get(key).reserves; - const expected_rate = value.des_reserves_rate_f.div("1e18"); + strategyStorage.token_map.forEach((value, key) => { + const on_strat = value.invested_tokens; + const full_res = pool.tokens_info.get(key.toString()).reserves; + const expected_rate = value.desired_reserves_rate_f.div("1e18"); const delta = value.delta_rate_f.div("1e18"); const real_rate = on_strat.div(full_res); - if (value.is_rebalance) { + if (value.enabled) { expect(real_rate.toNumber()).toBeLessThanOrEqual( - expected_rate.plus(delta).toNumber() + value.min_invest.lte(on_strat) ?expected_rate.plus(delta).toNumber() : 0 ); expect(real_rate.toNumber()).toBeGreaterThanOrEqual( - expected_rate.minus(delta).toNumber() + value.min_invest.lte(on_strat) ? + expected_rate.minus(delta).toNumber() : 0 ); } console.debug( `[STRATEGY] Auto Rebalance [${key.toString()}] - full: ${full_res}, on strategy: ${on_strat} (${on_strat .div(full_res) - .multipliedBy(100)}%). Auto rebalance enabled: ${value.is_rebalance}` + .multipliedBy(100)}%). Auto rebalance enabled: ${value.enabled}` ); }); } @@ -73,7 +85,7 @@ async function autoRebalanceCheck( export async function swapRebalanceSuccessCase( dex: Dex, yupana: Contract, - strategy: Contract, + strategy: StrategyContractType, pool_id: BigNumber, route: { i: BigNumber; @@ -83,32 +95,47 @@ export async function swapRebalanceSuccessCase( await dex.updateStorage({ pools: [pool_id.toString()] }); const pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - expect(strategyStore.strat_contract).toBeDefined(); - await dex.rebalance(pool_id, new Set([route.i, route.j])); - + const strategy_addr = pool.strategy; + expect(strategy_addr).toBeDefined(); + // await dex.rebalance(pool_id, new Set([route.i, route.j])); const reserves_i = pool.tokens_info.get(route.i.toString()).reserves; - const conf_i = strategyStore.configuration.get(route.i.toString()); + const stratStore = (await strategy.storage()) as StrategyStorage; + const conf_i = stratStore.token_map.get(tas.nat(route.i)); const amount_to_swap_to_slash = reserves_i - .multipliedBy(conf_i.des_reserves_rate_f.plus(conf_i.delta_rate_f)) + .multipliedBy(conf_i.desired_reserves_rate_f.plus(conf_i.delta_rate_f)) .idiv("1e18") .plus(1_500_000); console.debug(`[STRATEGY] Auto Rebalance Swap`); - const operation = await dex.swap( - pool_id, - route.i, - route.j, - amount_to_swap_to_slash, - new BigNumber(1), - new Date(Date.now() + 1000 * 60 * 60 * 24) + let operation = await dex.Tezos.contract.batch(); + const stratTokenConf = await (await strategy.storage()).token_map; + for (const id of [route.i, route.j]) { + const lid = stratTokenConf.get(tas.nat(id))?.lending_market_id; + if (lid) + operation = operation.withContractCall( + yupana.methods.updateInterest(lid) + ); + } + operation = operation.withContractCall( + dex.contract.methodsObject.swap({ + pool_id, + idx_from: route.i, + idx_to: route.j, + amount: amount_to_swap_to_slash, + min_amount_out: 1, + deadline: tas.timestamp(new Date(Date.now() + 1000 * 60 * 60 * 24)), + receiver: null, + referral: null, + }) ); - await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); + const sent = await operation.send(); + await sent.confirmation(); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, sent); } export async function investRebalanceSuccessCase( dex: Dex, yupana: Contract, - strategy: Contract, + strategy: StrategyContractType, pool_id: BigNumber, amounts: Map ) { @@ -118,28 +145,44 @@ export async function investRebalanceSuccessCase( }); const pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - expect(strategyStore.strat_contract).toBeDefined(); - await dex.rebalance( - pool_id, - new Set(dex.storage.storage.tokens[pool_id.toString()].keys()) - ); + const strategy_addr = pool.strategy; + expect(strategy_addr).toBeDefined(); + // await dex.rebalance( + // pool_id, + // new Set(dex.storage.storage.tokens[pool_id.toString()].keys()) + // ); console.debug(`[STRATEGY] Auto Rebalance invest`); - - const operation = await dex.investLiquidity( - pool_id, - amounts, - new BigNumber(1), - new Date(Date.now() + 1000 * 60 * 60 * 24) + let operation = await dex.Tezos.contract.batch(); + const stratTokenConf = await (await strategy.storage()).token_map; + const inp = new MichelsonMap() + for (const [id, value] of amounts.entries()) { + const lid = stratTokenConf.get(tas.nat(id))?.lending_market_id; + inp.set(id, value); + if (lid) + operation = operation.withContractCall( + yupana.methods.updateInterest(lid) + ); + } + operation = operation.withContractCall( + dex.contract.methodsObject.invest({ + pool_id, + shares: 1, + in_amounts: inp, + deadline: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), + receiver: null, + referral: null, + }) ); - await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); + const sent = await operation.send(); + await sent.confirmation(); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, sent); } export async function divestRebalanceSuccessCase( dex: Dex, yupana: Contract, - strategy: Contract, + strategy: StrategyContractType, pool_id: BigNumber, min_amounts: Map, shares: BigNumber @@ -150,28 +193,42 @@ export async function divestRebalanceSuccessCase( }); const pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - expect(strategyStore.strat_contract).toBeDefined(); - await dex.rebalance( - pool_id, - new Set(dex.storage.storage.tokens[pool_id.toString()].keys()) - ); + const strategy_addr = pool.strategy; + expect(strategy_addr).toBeDefined(); + // await dex.rebalance( + // pool_id, + // new Set(dex.storage.storage.tokens[pool_id.toString()].keys()) + // ); console.debug(`[STRATEGY] Auto Rebalance divest`); - - const operation = await dex.divestLiquidity( - pool_id, - min_amounts, - shares, - new Date(Date.now() + 1000 * 60 * 60 * 24) + let operation = await dex.Tezos.contract.batch(); + const stratTokenConf = await (await strategy.storage()).token_map; + const map = new MichelsonMap(); + for (const [id, value] of min_amounts.entries()) { + const lid = stratTokenConf.get(tas.nat(id))?.lending_market_id; + map.set(id, value); + if (lid) + operation = operation.withContractCall( + yupana.methods.updateInterest(lid) + ); + } + operation = operation.withContractCall( + dex.contract.methodsObject.divest({ + pool_id, + min_amounts_out: map, + shares, + deadline: tas.timestamp(new Date(Date.now() + 1000 * 60 * 60 * 24)), + }) ); - await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); + const sent = await operation.send(); + await sent.confirmation(); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, sent); } export async function divestOneRebalanceSuccessCase( dex: Dex, yupana: Contract, - strategy: Contract, + strategy: StrategyContractType, pool_id: BigNumber, i: BigNumber, output: BigNumber, @@ -180,24 +237,39 @@ export async function divestOneRebalanceSuccessCase( await dex.updateStorage({ pools: [pool_id.toString()] }); const pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - expect(strategyStore.strat_contract).toBeDefined(); - await dex.rebalance(pool_id, new Set([i])); + const strategy_addr = pool.strategy; + expect(strategy_addr).toBeDefined(); + // await dex.rebalance(pool_id, new Set([i])); console.debug(`[STRATEGY] Auto Rebalance divest one`); - const operation = await dex.divestOneCoin( - pool_id, - shares, - i, - output, - new Date(Date.now() + 1000 * 60 * 60 * 24) + let operation = await dex.Tezos.contract.batch(); + const stratTokenConf = await (await strategy.storage()).token_map; + for (const id of [i]) { + const lid = stratTokenConf.get(tas.nat(id))?.lending_market_id; + if (lid) + operation = operation.withContractCall( + yupana.methods.updateInterest(lid) + ); + } + operation = operation.withContractCall( + dex.contract.methodsObject.divest_one_coin({ + pool_id, + shares, + token_index: i, + deadline: tas.timestamp(new Date(Date.now() + 1000 * 60 * 60 * 24)), + min_amount_out: output, + receiver: null, + referral: null, + }) ); - await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); + const sent = await operation.send(); + await sent.confirmation(); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, sent); } export async function divestImbalanceRebalanceSuccessCase( dex: Dex, yupana: Contract, - strategy: Contract, + strategy: StrategyContractType, pool_id: BigNumber, outputs: Map, shares: BigNumber @@ -208,18 +280,33 @@ export async function divestImbalanceRebalanceSuccessCase( }); const pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - expect(strategyStore.strat_contract).toBeDefined(); - await dex.rebalance( - pool_id, - new Set(dex.storage.storage.tokens[pool_id.toString()].keys()) - ); + const strategy_addr = pool.strategy; + expect(strategy_addr).toBeDefined(); + // await dex.rebalance( + // pool_id, + // new Set(dex.storage.storage.tokens[pool_id.toString()].keys()) + // ); console.debug(`[STRATEGY] Auto Rebalance divest imb`); - const operation = await dex.divestImbalanced( - pool_id, - outputs, - shares, - new Date(Date.now() + 1000 * 60 * 60 * 24) + let operation = await dex.Tezos.contract.batch(); + const stratTokenConf = await (await strategy.storage()).token_map; + const map = new MichelsonMap(); + for (const [id, value] of outputs.entries()) { + const lid = stratTokenConf.get(tas.nat(id))?.lending_market_id; + map.set(id, value) + if (lid) + operation = operation.withContractCall( + yupana.methods.updateInterest(lid) + ); + } + operation = operation.withContractCall( + dex.contract.methodsObject.divest_imbalanced({ + pool_id, + amounts_out: map, + max_shares: shares, + deadline: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), + }) ); - await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); + const sent = await operation.send(); + await sent.confirmation(); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, sent); } diff --git a/test/Dex/cases/strategy/before.ts b/test/Dex/cases/strategy/before.ts index e71ceb9..15e2b24 100644 --- a/test/Dex/cases/strategy/before.ts +++ b/test/Dex/cases/strategy/before.ts @@ -8,6 +8,11 @@ import { BigNumber } from "bignumber.js"; import { IndexMap, TokensMap } from "../../../utils/types"; import { getMichelsonCode } from "../../../utils/mocks/getMichelsonCode"; import { Dex } from "../../API/dexAPI"; +import { DexStorage } from "../../API/types"; +import { StrategyContractType } from "../../../Strategy/API/strategy.types"; +import { tas, TokenType } from "../../../Strategy/API/type-aliases"; +import { decimals } from "../../../../utils/constants"; +import { StrategyFactoryContractType } from "../../../Strategy/API/strategy_factory.types"; export async function setupYupanaMocks( tokens: TokensMap, @@ -132,40 +137,45 @@ export async function setupYupanaMocks( export async function originateStrategy( dex: Dex, pool_id: BigNumber, + pool_ordering: IndexMap, yupana: Contract, - price_feed: Contract, + yupana_ordering: IndexMap, Tezos: TezosToolkit ): Promise<{ - strategy_factory: Contract; - strategy: Contract; + strategy_factory: StrategyFactoryContractType; + strategy: StrategyContractType; }> { const dev_address = await Tezos.signer.publicKeyHash(); - const strategy_factory_origination = await Tezos.contract.originate({ - code: getMichelsonCode("strategy_factory"), - storage: { - dev: { - dev_address: dev_address, - temp_dev_address: null, + const strategy_factory_origination = + await Tezos.contract.originate({ + code: getMichelsonCode("strategy_factory"), + storage: { + dev: { + dev_address: tas.address(dev_address), + temp_dev_address: null, + }, + deployed_strategies: tas.bigMap([]), + connected_pools: tas.bigMap([]), + lending_contract: tas.address(yupana.address), }, - deployed_strategies: new MichelsonMap(), - connected_pools: new MichelsonMap(), - }, - }); + }); await strategy_factory_origination.confirmation(1); const strategy_factory = await strategy_factory_origination.contract(); + const dexStore = (await dex.contract.storage()) as DexStorage; + const token_map = await dexStore.storage.tokens.get(pool_id.toString()); console.debug("[STRATEGY] Strategy Factory: ", strategy_factory.address); const poolInfo = { - pool_contract: dex.contract.address, - pool_id: pool_id, + pool_contract: tas.address(dex.contract.address), + pool_id: tas.nat(pool_id), + token_map: tas.map( + [...token_map.entries()].map(([key, value]) => ({ + key: tas.nat(key), + value: value as TokenType, + })) + ), }; const deploy_strategy_request = await strategy_factory.methodsObject - .deploy_strategy({ - pool_info: poolInfo, - lending_data: { - lending_contract: yupana.address, - price_feed_contract: price_feed.address, - }, - }) + .deploy_strategy(poolInfo) .send(); await deploy_strategy_request.confirmation(2); const deployed_strategy = ( @@ -175,12 +185,52 @@ export async function originateStrategy( ).metadata.internal_operation_results[0] .result as OperationResultOrigination ).originated_contracts[0]; - const strategy = await Tezos.contract.at(deployed_strategy); + const strategy = await Tezos.contract.at( + deployed_strategy + ); console.debug( "[STRATEGY] Deployed Strategy for ", poolInfo.pool_contract + `[${poolInfo.pool_id.toString()}]`, " is ", strategy.address ); + await ( + await Tezos.contract + .batch() + .withContractCall( + strategy.methodsObject.connect_token_to_lending({ + pool_token_id: tas.nat(pool_ordering.uUSD), + lending_market_id: tas.nat(yupana_ordering.uUSD), + }) + ) + .withContractCall( + strategy.methodsObject.connect_token_to_lending({ + pool_token_id: tas.nat(pool_ordering.kUSD), + lending_market_id: tas.nat(yupana_ordering.kUSD), + }) + ) + .withContractCall( + strategy.methodsObject.update_token_config({ + pool_token_id: tas.nat(pool_ordering.kUSD), + desired_reserves_rate_f: tas.nat(tas.nat("0.3").multipliedBy("1e18")), + delta_rate_f: tas.nat(tas.nat("0.005").multipliedBy("1e18")), + min_invest: tas.nat(tas.nat("300").multipliedBy(decimals.kUSD)), + enabled: true, + }) + ) + .withContractCall( + strategy.methodsObject.update_token_config({ + pool_token_id: tas.nat(pool_ordering.uUSD), + desired_reserves_rate_f: tas.nat( + tas.nat("0.15").multipliedBy("1e18") + ), + delta_rate_f: tas.nat(tas.nat("0.003").multipliedBy("1e18")), + min_invest: tas.nat(tas.nat("500").multipliedBy(decimals.uUSD)), + enabled: true, + }) + ) + .send() + ).confirmation(); + console.debug("[STRATEGY] Config set, approved, connected."); return { strategy_factory, strategy }; } diff --git a/test/Dex/cases/strategy/cofigure-token/configure_strategy.ts b/test/Dex/cases/strategy/cofigure-token/configure_strategy.ts deleted file mode 100644 index 5e9da81..0000000 --- a/test/Dex/cases/strategy/cofigure-token/configure_strategy.ts +++ /dev/null @@ -1,67 +0,0 @@ -import BigNumber from "bignumber.js"; -import { TezosToolkit } from "@taquito/taquito"; -import Dex from "../../../API"; -import { PairInfo } from "../../../API/types"; - -export async function setStrategyParamsSuccessCase( - dex: Dex, - pool_id: BigNumber, - pool_token_id: BigNumber, - des_reserves_rate_f: BigNumber, - delta_rate_f: BigNumber, - min_invest: BigNumber -) { - await dex.updateStorage({ pools: [pool_id.toString()] }); - let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; - expect(pool).toBeDefined(); - - await dex.setTokenStrategy( - pool_id, - pool_token_id, - des_reserves_rate_f, - delta_rate_f, - min_invest - ); - - await dex.updateStorage({ pools: [pool_id.toString()] }); - pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(updatedConfiguration).toMatchObject({ - des_reserves_rate_f: des_reserves_rate_f, - delta_rate_f: delta_rate_f, - min_invest: min_invest, - }); -} - -export async function setStrategyParamsToZeroSuccessCase( - dex: Dex, - pool_id: BigNumber, - pool_token_id: BigNumber -) { - await dex.updateStorage({ pools: [pool_id.toString()] }); - let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; - expect(pool).toBeDefined(); - - await dex.setTokenStrategy( - pool_id, - pool_token_id, - new BigNumber(0), - new BigNumber(0), - new BigNumber(0) - ); - - await dex.updateStorage({ pools: [pool_id.toString()] }); - pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(updatedConfiguration).toMatchObject({ - des_reserves_rate_f: new BigNumber(0), - delta_rate_f: new BigNumber(0), - min_invest: new BigNumber(0), - }); - - // TODO: Remove liquidity from old Strategy checks -} diff --git a/test/Dex/cases/strategy/cofigure-token/connect_token.ts b/test/Dex/cases/strategy/cofigure-token/connect_token.ts deleted file mode 100644 index 9e545d1..0000000 --- a/test/Dex/cases/strategy/cofigure-token/connect_token.ts +++ /dev/null @@ -1,98 +0,0 @@ -import BigNumber from "bignumber.js"; -import { TezosToolkit } from "@taquito/taquito"; -import Dex from "../../../API"; -import { PairInfo } from "../../../API/types"; - -export async function connectTokenStrategySuccessCase( - dex: Dex, - pool_id: BigNumber, - pool_token_id: BigNumber, - lending_market_id: BigNumber -) { - await dex.updateStorage({ pools: [pool_id.toString()] }); - let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; - expect(pool).toBeDefined(); - const beforeConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(beforeConfiguration).toBeDefined(); - expect(beforeConfiguration).toMatchObject({ - connected: false, - }); - - await dex.connectTokenStrategy(pool_id, pool_token_id, lending_market_id); - - await dex.updateStorage({ pools: [pool_id.toString()] }); - pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(updatedConfiguration).toMatchObject({ - connected: true, - }); -} - -export async function connectTokenStrategyFailCaseAdded( - dex: Dex, - pool_id: BigNumber, - pool_token_id: BigNumber, - lending_market_id: BigNumber -) { - await dex.updateStorage({ pools: [pool_id.toString()] }); - let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; - expect(pool).toBeDefined(); - const beforeConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(beforeConfiguration).toBeDefined(); - expect(beforeConfiguration).toMatchObject({ - connected: true, - }); - - await expect( - dex.connectTokenStrategy(pool_id, pool_token_id, lending_market_id) - ).rejects.toMatchObject({ - message: "token-strategy-connected", - }); - await dex.updateStorage({ pools: [pool_id.toString()] }); - pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(updatedConfiguration).toMatchObject({ - connected: true, - }); -} - -export async function connectTokenStrategyFailCaseNoStrategy( - dex: Dex, - pool_id: BigNumber, - pool_token_id: BigNumber, - lending_market_id: BigNumber -) { - await dex.updateStorage({ pools: [pool_id.toString()] }); - let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; - expect(pool).toBeDefined(); - expect(pool.strategy.strat_contract).toBeNull(); - const beforeConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(beforeConfiguration).toBeDefined(); - expect(beforeConfiguration).toMatchObject({ - connected: false, - }); - - await expect( - dex.connectTokenStrategy(pool_id, pool_token_id, lending_market_id) - ).rejects.toMatchObject({ - message: "no-connected-strategy", - }); - await dex.updateStorage({ pools: [pool_id.toString()] }); - pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(updatedConfiguration).toMatchObject({ - connected: false, - }); -} \ No newline at end of file diff --git a/test/Dex/cases/strategy/cofigure-token/index.ts b/test/Dex/cases/strategy/cofigure-token/index.ts index 546c873..8a2e9cf 100644 --- a/test/Dex/cases/strategy/cofigure-token/index.ts +++ b/test/Dex/cases/strategy/cofigure-token/index.ts @@ -1,4 +1 @@ -export * as configureTokenStrategy from "./configure_strategy"; -export * as connectTokenToStrategy from "./connect_token"; -export * as setStrategyRebalance from "./is_rebalance"; export * as manualRebalanceToken from "./rebalance"; \ No newline at end of file diff --git a/test/Dex/cases/strategy/cofigure-token/is_rebalance.ts b/test/Dex/cases/strategy/cofigure-token/is_rebalance.ts deleted file mode 100644 index bc99a99..0000000 --- a/test/Dex/cases/strategy/cofigure-token/is_rebalance.ts +++ /dev/null @@ -1,29 +0,0 @@ -import BigNumber from "bignumber.js"; -import { TezosToolkit } from "@taquito/taquito"; -import Dex from "../../../API"; -import { PairInfo } from "../../../API/types"; - -export async function setIsRebalanceSuccessCase( - dex: Dex, - pool_id: BigNumber, - pool_token_id: BigNumber, - isRebalance: boolean -) { - await dex.updateStorage({ pools: [pool_id.toString()] }); - let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; - expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - const initConfiguration = strategyStore.configuration.get( - pool_token_id.toString() - ); - expect(initConfiguration).not.toMatchObject({ is_rebalance: isRebalance }); - - await dex.setIsRebalanceStrategy(pool_id, pool_token_id, isRebalance); - - await dex.updateStorage({ pools: [pool_id.toString()] }); - pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedConfiguration = pool.strategy.configuration.get( - pool_token_id.toString() - ); - expect(updatedConfiguration).toMatchObject({ is_rebalance: isRebalance }); -} diff --git a/test/Dex/cases/strategy/cofigure-token/rebalance.ts b/test/Dex/cases/strategy/cofigure-token/rebalance.ts index ba163f4..280da0f 100644 --- a/test/Dex/cases/strategy/cofigure-token/rebalance.ts +++ b/test/Dex/cases/strategy/cofigure-token/rebalance.ts @@ -6,40 +6,61 @@ import { } from "@taquito/rpc"; import Dex from "../../../API"; import { PairInfo } from "../../../API/types"; +import { + Storage as StrategyStorage, + StrategyContractType, +} from "../../../../Strategy/API/strategy.types"; +import { tas } from "../../../../Strategy/API/type-aliases"; export async function manualRebalanceSuccessCase( dex: Dex, yupana: Contract, - strategy: Contract, + strategy: StrategyContractType, pool_id: BigNumber, pool_token_ids: Set ) { await dex.updateStorage({ pools: [pool_id.toString()] }); let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - expect(strategyStore.strat_contract).toBeDefined(); - - const operation = await dex.rebalance(pool_id, pool_token_ids); + const strategy_addr = pool.strategy; + expect(strategy_addr).toBeDefined(); + let operation = await dex.Tezos.contract.batch(); + const stratTokenConf = await (await strategy.storage()).token_map; + for (const id of pool_token_ids) { + const lid = stratTokenConf.get(tas.nat(id))?.lending_market_id; + if (lid) + operation = operation.withContractCall( + yupana.methods.updateInterest(lid) + ); + } + operation = operation.withContractCall( + dex.contract.methods.rebalance( + pool_id.toString(), + Array.from(pool_token_ids).map((x) => x.toNumber()) + ) + ); + const sent = await operation.send(); + await sent.confirmation(); await dex.updateStorage({ pools: [pool_id.toString()] }); + const strategyStorage = (await strategy.storage()) as StrategyStorage; + pool = dex.storage.storage.pools[pool_id.toString()]; - const internals = ( - operation.results[0] as OperationContentsAndResultTransaction - ).metadata.internal_operation_results; - expect( - internals.find( - (x) => - x.kind === OpKind.TRANSACTION && - x.parameters?.entrypoint === "prepare" && - x.destination == strategy.address && - x.source === dex.contract.address - ) - ).toMatchObject({ result: { status: "applied" } }); + const internals = (sent.results[2] as OperationContentsAndResultTransaction) + .metadata.internal_operation_results; + // expect( + // internals.find( + // (x) => + // x.kind === OpKind.TRANSACTION && + // x.parameters?.entrypoint === "prepare" && + // x.destination == strategy.address && + // x.source === dex.contract.address + // ) + // ).toMatchObject({ result: { status: "applied" } }); expect( internals.find( (x) => x.kind === OpKind.TRANSACTION && - x.parameters?.entrypoint === "update_token_state" && + x.parameters?.entrypoint === "update_state" && x.destination == strategy.address && x.source === dex.contract.address ) @@ -54,12 +75,20 @@ export async function manualRebalanceSuccessCase( x.source === strategy.address ) .forEach((y) => expect(y).toMatchObject({ result: { status: "applied" } })); - pool.strategy.configuration.forEach((value, key) => { - const on_strat = value.strategy_reserves; - const full_res = pool.tokens_info.get(key).reserves; - const expected_rate = value.des_reserves_rate_f.div("1e18"); + strategyStorage.token_map.forEach((value, key) => { + const on_strat = value.invested_tokens; + const full_res = pool.tokens_info.get(key.toString()).reserves; + const expected_rate = value.desired_reserves_rate_f.div("1e18"); + const delta = value.delta_rate_f.div("1e18"); const real_rate = on_strat.div(full_res); - expect(real_rate.toNumber()).toBeCloseTo(expected_rate.toNumber(), 9); + expect(real_rate.toNumber()).toBeLessThanOrEqual( + value.min_invest.lte(on_strat) ? + expected_rate.plus(delta).toNumber() : 0 + ); + expect(real_rate.toNumber()).toBeGreaterThanOrEqual( + value.min_invest.lte(on_strat) ? + expected_rate.minus(delta).toNumber() : 0 + ); console.debug( `[STRATEGY] Rebalance [${key.toString()}] - full: ${full_res}, on strategy: ${on_strat} (${on_strat .div(full_res) diff --git a/test/Dex/cases/strategy/connect.ts b/test/Dex/cases/strategy/connect.ts index aa3888b..e8422dd 100644 --- a/test/Dex/cases/strategy/connect.ts +++ b/test/Dex/cases/strategy/connect.ts @@ -11,15 +11,14 @@ export async function setStrategyAddrSuccessCase( await dex.updateStorage({ pools: [pool_id.toString()] }); let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - const initStrat = strategyStore.strat_contract; + const initStrat = pool.strategy; expect(strategy).not.toStrictEqual(initStrat); await dex.connectStrategy(pool_id, strategy); await dex.updateStorage({ pools: [pool_id.toString()] }); pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedStrat = pool.strategy.strat_contract; + const updatedStrat = pool.strategy; expect(strategy).toStrictEqual(updatedStrat); } @@ -30,15 +29,14 @@ export async function removeStrategyAddrSuccessCase( await dex.updateStorage({ pools: [pool_id.toString()] }); let pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; expect(pool).toBeDefined(); - const strategyStore = pool.strategy; - const initStrat = strategyStore.strat_contract; + const initStrat = pool.strategy; expect(initStrat).not.toBeNull(); await dex.connectStrategy(pool_id, null); await dex.updateStorage({ pools: [pool_id.toString()] }); pool = dex.storage.storage.pools[pool_id.toString()]; - const updatedStrat = pool.strategy.strat_contract; + const updatedStrat = pool.strategy; expect(updatedStrat).toBeNull(); // TODO: Remove liquidity from old Strategy checks diff --git a/test/Strategy/API/strategy.types.ts b/test/Strategy/API/strategy.types.ts new file mode 100644 index 0000000..3912b2f --- /dev/null +++ b/test/Strategy/API/strategy.types.ts @@ -0,0 +1,86 @@ +import { + ContractAbstractionFromContractType, + WalletContractAbstractionFromContractType, +} from "./type-utils"; +import { address, MMap, nat, TokenType } from "./type-aliases"; + +export type TokenMapType = { + lending_market_id: nat; + desired_reserves_rate_f: nat; + delta_rate_f: nat; + min_invest: nat; + enabled: boolean; + invested_tokens: nat; +}; + +export type PoolDataType = { + pool_contract: address; + pool_id: nat; + token_map: MMap; +}; + +export type Storage = { + factory: address; + pool_data: PoolDataType; + token_map: MMap; +}; + +type Methods = { + approve_token: ( + param: Array<{ + pool_token_id: nat; + spender: address; + amount: nat; + }> + ) => Promise; + claim_rewards: (pool_token_ids: Array) => Promise; + connect_token_to_lending: ( + pool_token_id: nat, + lending_market_id: nat + ) => Promise; + update_token_config: ( + pool_token_id: nat, + desired_reserves_rate_f: nat, + delta_rate_f: nat, + min_invest: nat, + enabled: boolean + ) => Promise; + update_state: (tokens: MMap, manual: boolean) => Promise; +}; + +type MethodsObject = { + approve_token: ( + param: Array<{ + pool_token_id: nat; + spender: address; + amount: nat; + }> + ) => Promise; + claim_rewards: (pool_token_ids: Array) => Promise; + connect_token_to_lending: (params: { + pool_token_id: nat; + lending_market_id: nat; + }) => Promise; + update_token_config: (params: { + pool_token_id: nat; + desired_reserves_rate_f: nat; + delta_rate_f: nat; + min_invest: nat; + enabled: boolean; + }) => Promise; + update_state: (params: { + tokens: MMap; + manual: boolean; + }) => Promise; +}; + +type contractTypes = { + methods: Methods; + methodsObject: MethodsObject; + storage: Storage; + code: { __type: "StrategyCode"; protocol: string; code: object[] }; +}; +export type StrategyContractType = + ContractAbstractionFromContractType; +export type StrategyWalletType = + WalletContractAbstractionFromContractType; diff --git a/test/Strategy/API/strategy_factory.types.ts b/test/Strategy/API/strategy_factory.types.ts new file mode 100644 index 0000000..18ca1c0 --- /dev/null +++ b/test/Strategy/API/strategy_factory.types.ts @@ -0,0 +1,50 @@ +import { + ContractAbstractionFromContractType, + WalletContractAbstractionFromContractType, +} from "./type-utils"; +import { address, BigMap, MMap, nat, TokenType } from "./type-aliases"; +import { PoolDataType } from "./strategy.types"; + +export type PoolInfo = { + pool_contract: address; + pool_id: nat; +}; + +export type PoolInfoParam = PoolDataType; + +export type Storage = { + dev: { + dev_address: address; + temp_dev_address?: address; + }; + lending_contract: address; + deployed_strategies: BigMap; + connected_pools: BigMap; +}; + +type Methods = { + deploy_strategy: ( + pool_contract: address, + pool_id: nat, + token_map: MMap + ) => Promise; + approve_developer: () => Promise; + change_developer: (param: address) => Promise; +}; + +type MethodsObject = { + deploy_strategy: (params: PoolInfoParam) => Promise; + approve_developer: () => Promise; + change_developer: (param: address) => Promise; +}; + +type contractTypes = { + methods: Methods; + methodsObject: MethodsObject; + storage: Storage; + code: { __type: "StrategyFactoryCode"; protocol: string; code: object[] }; +}; +export type StrategyFactoryContractType = + ContractAbstractionFromContractType; +export type StrategyFactoryWalletType = + WalletContractAbstractionFromContractType; diff --git a/test/Strategy/API/type-aliases.ts b/test/Strategy/API/type-aliases.ts new file mode 100644 index 0000000..d0d9062 --- /dev/null +++ b/test/Strategy/API/type-aliases.ts @@ -0,0 +1,115 @@ +import { + assertMichelsonInstruction, + Expr, + MichelsonCode, +} from "@taquito/michel-codec"; +import { MichelsonMap } from "@taquito/taquito"; +import { BigNumber } from "bignumber.js"; + +export type Instruction = MichelsonCode; + +export declare type FA2 = { token_address: address; token_id: nat }; +export declare type FA12 = address; + +export declare type TokenType = { fa12: FA12 } | { fa2: FA2 }; + +export type unit = (true | undefined) & { __type: "unit" }; + +export type address = string & { __type: "address" }; +export type bytes = string & { __type: "bytes" }; +export type contract = string & { __type: "contract" }; +export type operation = string & { __type: "operation" }; +export type key = string & { __type: "key" }; +export type key_hash = string & { __type: "key_hash" }; +export type signature = string & { __type: "signature" }; +export type ticket = string & { __type: "ticket" }; + +export type timestamp = string & { __type: "timestamp" }; + +export type int = BigNumber & { __type: "int" }; +export type nat = BigNumber & { __type: "nat" }; + +export type mutez = BigNumber & { __type: "mutez" }; +export type tez = BigNumber & { __type: "tez" }; + +type MapKey = Array | object | string | boolean | number; +export type MMap = Omit, "get"> & { + get: (key: K) => V; +}; +export type BigMap = Omit, "get"> & { + get: (key: K) => Promise; +}; + +export type chest = string & { __type: "chest" }; +export type chest_key = string & { __type: "chest_key" }; + +const createStringTypeTas = () => { + return (value: string): T => value as T; +}; + +const createBigNumberTypeTas = () => { + return (value: number | BigNumber | string): T => new BigNumber(value) as T; +}; + +type asMapParamOf = K extends string + ? { [key: string]: V } | Array<{ key: K; value: V }> + : K extends number + ? { [key: number]: V } | Array<{ key: K; value: V }> + : Array<{ key: K; value: V }>; + +function asMap(value: asMapParamOf): MMap { + const m = new MichelsonMap(); + if (Array.isArray(value)) { + const vArray = value as Array<{ key: K; value: V }>; + vArray.forEach((x) => m.set(x.key, x.value)); + } else { + const vObject = value as { [key: string]: V }; + Object.keys(vObject).forEach((key) => + m.set(key as unknown as K, vObject[key]) + ); + } + return m as MMap; +} +const asBigMap = (value: asMapParamOf) => + asMap(value) as unknown as BigMap; + +function add(a: T, b: T): T { + return a.plus(b) as T; +} +function subtract(a: T, b: T): T { + return a.minus(b) as T; +} + +function createLambdaTypeTas(expr: Expr): MichelsonCode { + assertMichelsonInstruction(expr); + return expr as MichelsonCode; +} + +/** tas: Tezos 'as' casting for strict types */ +export const tas = { + address: createStringTypeTas
(), + bytes: createStringTypeTas(), + contract: createStringTypeTas(), + chest: createStringTypeTas(), + chest_key: createStringTypeTas(), + timestamp: (value: string | Date): timestamp => + new Date(value).toISOString() as timestamp, + + int: createBigNumberTypeTas(), + nat: createBigNumberTypeTas(), + mutez: createBigNumberTypeTas(), + tez: createBigNumberTypeTas(), + + map: asMap, + bigMap: asBigMap, + + // Operations + add, + subtract, + + lambda: createLambdaTypeTas, + + // To number + number: (value: string | BigNumber) => Number(value + ""), + unit: () => true as unit, +}; diff --git a/test/Strategy/API/type-utils.ts b/test/Strategy/API/type-utils.ts new file mode 100644 index 0000000..ee64f37 --- /dev/null +++ b/test/Strategy/API/type-utils.ts @@ -0,0 +1,58 @@ +import { + ContractAbstraction, + ContractMethod, + ContractMethodObject, + ContractProvider, + Wallet, +} from "@taquito/taquito"; + +type BaseContractType = { + methods: unknown; + methodsObject: unknown; + storage: unknown; +}; + +type ContractMethodsOf< + T extends ContractProvider | Wallet, + TContract extends BaseContractType +> = { + [M in keyof TContract["methods"]]: TContract["methods"][M] extends ( + ...args: infer A + ) => unknown + ? (...args: A) => ContractMethod + : never; +}; +type ContractMethodsObjectsOf< + T extends ContractProvider | Wallet, + TContract extends BaseContractType +> = { + [M in keyof TContract["methodsObject"]]: TContract["methodsObject"][M] extends ( + ...args: infer A + ) => unknown + ? (...args: A) => ContractMethodObject + : never; +}; +type ContractStorageOf = + TContract["storage"]; + +export type ContractAbstractionFromContractType< + TContract extends BaseContractType +> = ContractAbstraction< + ContractProvider, + ContractMethodsOf, + ContractMethodsObjectsOf, + {}, + {}, + ContractStorageOf +>; + +export type WalletContractAbstractionFromContractType< + TContract extends BaseContractType +> = ContractAbstraction< + Wallet, + ContractMethodsOf, + ContractMethodsObjectsOf, + {}, + {}, + ContractStorageOf +>; diff --git a/test/utils/mocks/artifacts/strategy.tz b/test/utils/mocks/artifacts/strategy.tz index 4192b72..b304423 100644 --- a/test/utils/mocks/artifacts/strategy.tz +++ b/test/utils/mocks/artifacts/strategy.tz @@ -1,26 +1,31 @@ { parameter - (or (or (or %dev_part - (list %claim_rewards nat) - (pair %update_lending (address %lending_contract) (address %price_feed_contract))) - (or %dex_part - (pair %update_token_info - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (or (or %dev_part + (or (list %approve_token (pair (nat %pool_token_id) (address %spender) (nat %amount))) + (list %claim_rewards nat)) + (or (pair %connect_token_to_lending (nat %pool_token_id) (nat %lending_market_id)) + (pair %update_token_config (nat %pool_token_id) - (nat %lending_market_id)) - (list %update_token_state (pair (nat %pool_token_id) (nat %new_balance))))) - (list %prepare nat)) ; + (nat %desired_reserves_rate_f) + (nat %delta_rate_f) + (nat %min_invest) + (bool %enabled)))) + (pair %update_state (map %tokens nat nat) (bool %manual))) ; storage (pair (address %factory) - (pair %lending_data (address %lending_contract) (address %price_feed_contract)) - (pair %pool_data (address %pool_contract) (nat %pool_id)) + (pair %pool_data + (address %pool_contract) + (nat %pool_id) + (map %token_map + nat + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) (map %token_map nat - (pair (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - (nat %lending_market_id) - (nat %invested_tokens) - (timestamp %upd_time) - (bool %approved) - (timestamp %prepared_time)))) ; + (pair (nat %lending_market_id) + (nat %desired_reserves_rate_f) + (nat %delta_rate_f) + (nat %min_invest) + (bool %enabled) + (nat %invested_tokens)))) ; code { LAMBDA (pair (pair (pair nat nat) address bool) bool) nat @@ -39,28 +44,41 @@ VIEW "convert" (pair (nat %amount) (timestamp %interestUpdateTime) (timestamp %priceUpdateTime)) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH string "'Update interest' for market should be called" ; + NOW ; + DUP 3 ; + GET 3 ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; CAR } ; - PUSH string "Factory has no suited dev_address view" ; + LAMBDA + (pair (pair (list nat) address) bool) + (map nat nat) + { UNPAIR ; + UNPAIR ; + PUSH string "Lending has no suited balanceOf view" ; + DIG 2 ; + DIG 3 ; + DIG 3 ; + MAP { SELF_ADDRESS ; PAIR } ; + PAIR ; + VIEW "balanceOf" + (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + EMPTY_MAP nat nat ; + SWAP ; + ITER { SWAP ; DUP 2 ; CDR ; SOME ; DIG 2 ; CAR ; CDR ; UPDATE } } ; PUSH string "No Token yet" ; + PUSH string "Not DEX pool token or wrong id" ; PUSH string "Contract hasn't update_operators/approve entrypoint" ; PUSH string "Contract has no transfer entrypoint" ; - PUSH string "'Update interest' and 'get price' for market should be called" ; - LAMBDA - (pair (option address) string) - address - { UNPAIR ; IF_NONE { FAILWITH } { SWAP ; DROP } } ; + PUSH string "No balance for token returned in balance response" ; LAMBDA int nat { ISNAT ; IF_NONE { PUSH string "Value is not natural" ; FAILWITH } {} } ; - PUSH timestamp 946684800 ; - PUSH bool False ; - NOW ; - PUSH nat 0 ; - PUSH nat 0 ; - PUSH address "tz1ZZZZZZZZZZZZZZZZZZZZZZZZZZZZNkiRg" ; - LEFT (pair address nat) ; - PAIR 6 ; + PUSH nat 1000000000000000000 ; DIG 9 ; UNPAIR ; SWAP ; @@ -71,581 +89,704 @@ IF { PUSH string "Sending XTZ not allowed here" ; FAILWITH } {} ; SWAP ; IF_LEFT - { IF_LEFT - { DIG 2 ; - DIG 7 ; - DROP 2 ; - PUSH string "Only developer is allowed here" ; - DUP 9 ; - DUP 4 ; - CAR ; - UNIT ; - VIEW "dev_address" address ; - PAIR ; - DUP 6 ; - SWAP ; - EXEC ; - SENDER ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; - IF_LEFT - { SWAP ; - NIL operation ; - DUP 2 ; - GET 6 ; - PUSH bool True ; - DUP 4 ; - GET 3 ; - CAR ; - DUP 6 ; - MAP { DUP 4 ; SWAP ; GET ; IF_NONE { DUP 11 ; FAILWITH } {} ; GET 3 } ; - DIG 3 ; - DROP ; - PUSH string "Lending has no suited balanceOf view" ; - DIG 2 ; - DIG 3 ; + { DIG 2 ; + DROP ; + PUSH string "Only developer is allowed here" ; + PUSH string "Factory has no suited dev_address view" ; + DUP 4 ; + CAR ; + UNIT ; + VIEW "dev_address" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + IF_LEFT + { IF_LEFT + { DIG 2 ; DIG 3 ; - MAP { SELF_ADDRESS ; PAIR } ; - PAIR ; - VIEW "balanceOf" - (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - EMPTY_MAP nat nat ; + DIG 4 ; + DIG 7 ; + DIG 8 ; + DIG 9 ; + DROP 6 ; SWAP ; - ITER { SWAP ; DUP 2 ; CDR ; SOME ; DIG 2 ; CAR ; CDR ; UPDATE } ; - DIG 3 ; - ITER { DUP 9 ; - DUP 5 ; - GET 6 ; - DUP 3 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 8 ; - NOW ; - DUP 3 ; - GET 10 ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; - PUSH nat 1 ; - DUP 4 ; - DIG 3 ; - GET ; - IF_NONE - { PUSH string "No balance for token returned in balance response" ; FAILWITH } - {} ; - SUB ; - DUP 6 ; - SWAP ; - EXEC ; - PUSH bool True ; - PUSH bool False ; - DUP 7 ; - GET 3 ; - CAR ; - PAIR ; + NIL operation ; + DIG 2 ; + ITER { DUP 5 ; DUP 4 ; GET 3 ; - DIG 3 ; - PAIR ; - PAIR ; - PAIR ; - DUP 12 ; - SWAP ; - EXEC ; - DUP 2 ; - GET 5 ; - SWAP ; - SUB ; - DUP 6 ; - SWAP ; - EXEC ; - DIG 3 ; + GET 4 ; DUP 3 ; CAR ; - DUP 3 ; - PAIR ; - DUP 6 ; - CAR ; - DUP 13 ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DIG 2 ; SWAP ; - UNIT ; - VIEW "dev_address" address ; + DUP 3 ; + GET 4 ; PAIR ; - DUP 9 ; - SWAP ; - EXEC ; + DIG 2 ; + GET 3 ; SELF_ADDRESS ; DIG 2 ; UNPAIR ; SWAP ; IF_LEFT - { DUP 13 ; + { DIG 2 ; + DROP ; + DUP 6 ; SWAP ; - CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; + CONTRACT %approve (pair (address %spender) (nat %value)) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; DIG 2 ; - DIG 4 ; - PAIR ; DIG 3 ; PAIR ; TRANSFER_TOKENS } - { DUP 13 ; + { DUP 7 ; DUP 2 ; CAR ; - CONTRACT %transfer - (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + CONTRACT %update_operators + (list (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) + (pair %remove_operator (address %owner) (address %operator) (nat %token_id)))) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; - NIL (pair address (list (pair address nat nat))) ; - NIL (pair address nat nat) ; - DIG 5 ; + NIL (or (pair address address nat) (pair address address nat)) ; + PUSH nat 0 ; DIG 5 ; - CDR ; - DIG 7 ; - PAIR 3 ; - CONS ; - DIG 4 ; - PAIR ; + COMPARE ; + GT ; + IF { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; LEFT (pair address address nat) } + { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; RIGHT (pair address address nat) } ; CONS ; TRANSFER_TOKENS } ; - CONS ; - DUP 5 ; + CONS } ; + DIG 2 ; + DIG 3 ; + DROP 2 } + { DIG 5 ; + DROP ; + SWAP ; + NIL operation ; + DUP 2 ; + GET 4 ; + DUP 3 ; + CAR ; + PUSH string "Factory has no suited lending_contract view" ; + SWAP ; + UNIT ; + VIEW "lending_contract" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH bool False ; + DUP 2 ; + DUP 7 ; + MAP { DUP 5 ; SWAP ; GET ; IF_NONE { DUP 12 ; FAILWITH } {} ; CAR } ; + DIG 4 ; + DROP ; + PAIR ; + PAIR ; + DIG 10 ; + SWAP ; + EXEC ; + NIL (pair nat int nat) ; + DIG 5 ; + ITER { DUP 10 ; + DUP 7 ; GET 3 ; - CDR ; - PUSH string "Lending has no suited redeem entrypoint" ; - SWAP ; - CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + GET 4 ; + DUP 3 ; + GET ; IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; + DUP 12 ; + DUP 8 ; + GET 4 ; DUP 4 ; - DIG 4 ; - DIG 5 ; - GET 3 ; - PAIR 3 ; - TRANSFER_TOKENS ; - CONS ; - SWAP } ; - DIG 3 ; - DIG 4 ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH nat 1 ; + DUP 6 ; + DUP 3 ; + CAR ; + GET ; + IF_NONE { DUP 11 ; FAILWITH } {} ; + SUB ; + DUP 10 ; + SWAP ; + EXEC ; + PUSH bool True ; + PUSH bool False ; + DUP 9 ; + PAIR ; + DUP 4 ; + CAR ; + DIG 3 ; + PAIR ; + PAIR ; + PAIR ; + DUP 15 ; + SWAP ; + EXEC ; + DUP 2 ; + GET 10 ; + DUP 2 ; + SUB ; + DUP 3 ; + GET 10 ; + DUP 3 ; + COMPARE ; + GT ; + IF { DIG 5 ; + DUP 4 ; + CAR ; + DIG 2 ; + DIG 6 ; + PAIR 3 ; + CONS ; + DUG 3 ; + DUP 2 ; + GET 10 ; + SWAP ; + SUB ; + DUP 9 ; + SWAP ; + EXEC ; + DIG 6 ; + DIG 3 ; + DUP 3 ; + PAIR ; + DUP 8 ; + CAR ; + PUSH string "Factory has no suited dev_address view" ; + SWAP ; + UNIT ; + VIEW "dev_address" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + SELF_ADDRESS ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DUP 14 ; + SWAP ; + CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 2 ; + DIG 4 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS } + { DUP 14 ; + DUP 2 ; + CAR ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + NIL (pair address (list (pair address nat nat))) ; + NIL (pair address nat nat) ; + DIG 5 ; + DIG 5 ; + CDR ; + DIG 7 ; + PAIR 3 ; + CONS ; + DIG 4 ; + PAIR ; + CONS ; + TRANSFER_TOKENS } ; + CONS ; + PUSH string "Lending has no suited redeem entrypoint" ; + DUP 7 ; + CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DUP 4 ; + DIG 4 ; + DIG 5 ; + CAR ; + PAIR 3 ; + TRANSFER_TOKENS ; + CONS ; + DUG 3 } + { DROP 5 } } ; + SWAP ; + DIG 2 ; DIG 5 ; DIG 6 ; DIG 7 ; DIG 8 ; DIG 9 ; - DROP 8 } - { DIG 2 ; - DIG 3 ; - DIG 4 ; - DIG 5 ; - DIG 6 ; - DIG 7 ; - DIG 8 ; - DROP 7 ; - UPDATE 3 ; - NIL operation } } - { DIG 4 ; + DIG 10 ; + DROP 8 ; + EMIT %claim_rewards + (list (pair (nat %pool_token_id) (int %reward) (nat %lending_market_id))) ; + CONS } } + { DIG 2 ; + DIG 3 ; + DIG 4 ; + DIG 5 ; + DIG 8 ; DIG 9 ; - DROP 2 ; - PUSH string "Only dex is allowed here" ; - DUP 3 ; - GET 5 ; - CAR ; - SENDER ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; + DROP 6 ; IF_LEFT { DIG 3 ; - DIG 4 ; - DIG 5 ; - DIG 6 ; - DIG 7 ; - DIG 8 ; - DROP 6 ; + DROP ; SWAP ; - PUSH string "Token already added" ; + DIG 2 ; DUP 2 ; - GET 6 ; - DUP 4 ; GET 3 ; + GET 4 ; + DUP 4 ; + CAR ; MEM ; - NOT ; IF { DROP } { FAILWITH } ; - DUP ; - GET 6 ; - DIG 3 ; + PUSH nat 0 ; + PUSH bool False ; + PUSH nat 0 ; + PUSH nat 0 ; + PUSH nat 0 ; + PUSH nat 0 ; + PAIR 6 ; + DUP 2 ; + GET 4 ; DUP 4 ; CAR ; + GET ; + IF_NONE {} { SWAP ; DROP } ; + PUSH nat 0 ; + DUP 2 ; + GET 10 ; + COMPARE ; + EQ ; + IF {} { PUSH string "Unclaimed reserves from Yupana" ; FAILWITH } ; + DUP 2 ; + DIG 2 ; + GET 4 ; + DIG 2 ; + DUP 4 ; + CDR ; UPDATE 1 ; + SOME ; + DIG 3 ; + CAR ; + UPDATE ; + UPDATE 4 } + { SWAP ; + DIG 2 ; + DUP 2 ; + GET 3 ; + GET 4 ; DUP 4 ; + CAR ; + MEM ; + IF { DROP } { FAILWITH } ; + DIG 2 ; + DUP 2 ; GET 4 ; - UPDATE 3 ; - DIG 3 ; + DUP 4 ; + CAR ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 2 ; + DIG 2 ; + GET 4 ; + DIG 2 ; + DUP 4 ; GET 3 ; - SWAP ; + UPDATE 3 ; + DUP 4 ; + GET 5 ; + UPDATE 5 ; + DUP 4 ; + GET 7 ; + UPDATE 7 ; + DUP 4 ; + GET 8 ; + UPDATE 9 ; SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - NIL operation } - { DIG 2 ; - DROP ; - SWAP ; - NIL operation ; - EMPTY_MAP - nat - (pair (pair (or address (pair address nat)) nat nat timestamp bool timestamp) nat) ; - DIG 3 ; - ITER { DUP 9 ; - DUP 5 ; - GET 6 ; - DUP 3 ; - CAR ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 7 ; - NOW ; - DUP 3 ; - GET 10 ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; - DUP ; - GET 5 ; - DUP 3 ; - CDR ; - SUB ; - ISNAT ; - IF_NONE - { DUP 2 ; - CDR ; - DUP 2 ; - GET 5 ; - SUB ; - DUP 7 ; - SWAP ; - EXEC ; - DIG 4 ; - DUP 3 ; - CAR ; - DUP 3 ; - PAIR ; - DUP 7 ; - GET 5 ; - CAR ; - SELF_ADDRESS ; - DIG 2 ; - UNPAIR ; - SWAP ; - IF_LEFT - { DUP 13 ; - SWAP ; - CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DIG 2 ; - DIG 4 ; - PAIR ; - DIG 3 ; - PAIR ; - TRANSFER_TOKENS } - { DUP 13 ; - DUP 2 ; - CAR ; - CONTRACT %transfer - (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - NIL (pair address (list (pair address nat nat))) ; - NIL (pair address nat nat) ; - DIG 5 ; - DIG 5 ; - CDR ; - DIG 7 ; - PAIR 3 ; - CONS ; - DIG 4 ; - PAIR ; - CONS ; - TRANSFER_TOKENS } ; - CONS ; - DUP 6 ; - GET 3 ; - CAR ; - PUSH string "Lending has no suited redeem entrypoint" ; - SWAP ; - CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DUP 4 ; - DIG 4 ; - DUP 6 ; - GET 3 ; - PAIR 3 ; - TRANSFER_TOKENS ; - CONS ; - DUG 3 } - { PUSH bool False ; - PUSH bool True ; - DUP 8 ; - GET 3 ; - CAR ; - PAIR ; - DUP 4 ; - GET 3 ; - DUP 4 ; - PAIR ; - PAIR ; - PAIR ; - DUP 13 ; - SWAP ; - EXEC ; - PUSH nat 0 ; - DUP 2 ; - COMPARE ; - GT ; - PUSH nat 0 ; - DUP 4 ; - COMPARE ; - GT ; - AND ; - IF { DIG 5 ; - DUP 7 ; - GET 3 ; - CAR ; - PUSH string "Lending has no suited mint entrypoint" ; - SWAP ; - CONTRACT %mint (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DIG 3 ; - DUP 5 ; - DUP 7 ; - GET 3 ; - PAIR 3 ; - TRANSFER_TOKENS ; - CONS ; - DUG 4 ; - DIG 3 ; - SWAP ; - DUP 3 ; - PAIR ; - DUP 4 ; - CAR ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - DUG 2 } - { DROP 2 } } ; - DUP 5 ; - DIG 5 ; - GET 6 ; - DIG 2 ; - DUP 4 ; - CDR ; - UPDATE 5 ; - NOW ; - UPDATE 7 ; - DIG 3 ; - CAR ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - DUG 2 } ; DIG 3 ; - DIG 4 ; - DIG 5 ; - DIG 8 ; - DROP 4 ; - DUP 3 ; - GET 3 ; CAR ; - SWAP ; - EMPTY_MAP nat bool ; - NIL operation ; - PAIR ; - SWAP ; - ITER { SWAP ; - DUP 2 ; - CDR ; - DUP ; - CAR ; - GET 9 ; - NOT ; - IF { DUP 2 ; - DIG 2 ; + UPDATE ; + UPDATE 4 } ; + NIL operation } } + { DIG 6 ; + DIG 8 ; + DROP 2 ; + DUP 2 ; + GET 3 ; + CAR ; + PUSH string "Only dex is allowed here" ; + SWAP ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + SWAP ; + NIL operation ; + NIL (pair nat int nat) ; + DUP 3 ; + CAR ; + PUSH string "Factory has no suited lending_contract view" ; + SWAP ; + UNIT ; + VIEW "lending_contract" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 5 ; + CAR ; + ITER { UNPAIR ; + DUP 12 ; + DUP 7 ; + GET 3 ; + GET 4 ; + DUP 3 ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 7 ; + GET 4 ; + DUP 3 ; + GET ; + IF_NONE + { DROP 3 } + { PUSH nat 0 ; + DUP 2 ; + GET 10 ; + COMPARE ; + NEQ ; + PUSH nat 0 ; + DUP 6 ; + COMPARE ; + EQ ; + AND ; + IF { PUSH bool True } + { DUP 4 ; + DUP 11 ; + DUP 3 ; + GET 10 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 2 ; + GET 5 ; + DUP 3 ; + GET 3 ; + DIG 2 ; + SUB ; + ABS ; + COMPARE ; + LT ; + NOT } ; + DUP 2 ; + GET 9 ; + DUP 11 ; + CDR ; + OR ; + AND ; + IF { DUP 10 ; + DUP 2 ; + GET 3 ; + DIG 5 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 2 ; + GET 7 ; + DUP 2 ; + COMPARE ; + GT ; + IF {} { DROP ; PUSH nat 0 } ; + DUP 2 ; + GET 10 ; + DUP 2 ; + SUB ; + DUP ; + ISNAT ; + IF_NONE + { DUP ; + ABS ; + PUSH bool False ; + DUP 8 ; + NIL nat ; + DUP 7 ; CAR ; - DUP 3 ; + CONS ; + PAIR ; + PAIR ; + DUP 18 ; + SWAP ; + EXEC ; + DUP 5 ; CAR ; + GET ; + IF_NONE { DUP 14 ; FAILWITH } {} ; + PUSH bool True ; + PUSH bool False ; + DUP 10 ; + PAIR ; + DUP 7 ; CAR ; - DUP 4 ; - CDR ; + DIG 3 ; PAIR ; - DUP 6 ; + PAIR ; + PAIR ; + DUP 19 ; + SWAP ; + EXEC ; + DUP 2 ; + SWAP ; + COMPARE ; + LT ; + IF { PUSH nat 1 ; + SWAP ; + SUB ; + DUP 13 ; + SWAP ; + EXEC ; + PUSH nat 1 ; + DIG 3 ; + ADD ; + DUG 2 ; + PUSH nat 1 ; + DIG 2 ; + ADD ; + SWAP } + {} ; + DIG 8 ; + DIG 5 ; + DUP 3 ; + PAIR ; + DUP 10 ; + GET 3 ; + CAR ; SELF_ADDRESS ; DIG 2 ; UNPAIR ; SWAP ; IF_LEFT - { DIG 2 ; - DROP ; - DUP 11 ; + { DUP 18 ; SWAP ; - CONTRACT %approve (pair (address %spender) (nat %value)) ; + CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; DIG 2 ; + DIG 4 ; + PAIR ; DIG 3 ; PAIR ; TRANSFER_TOKENS } - { DUP 12 ; + { DUP 18 ; DUP 2 ; CAR ; - CONTRACT %update_operators - (list (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) - (pair %remove_operator (address %owner) (address %operator) (nat %token_id)))) ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; - NIL (or (pair address address nat) (pair address address nat)) ; - PUSH nat 0 ; + NIL (pair address (list (pair address nat nat))) ; + NIL (pair address nat nat) ; + DIG 5 ; DIG 5 ; - COMPARE ; - GT ; - IF { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; LEFT (pair address address nat) } - { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; RIGHT (pair address address nat) } ; + CDR ; + DIG 7 ; + PAIR 3 ; + CONS ; + DIG 4 ; + PAIR ; CONS ; TRANSFER_TOKENS } ; CONS ; - UPDATE 1 ; - SWAP } - {} ; - DUP ; - CAR ; - CAR ; - IF_LEFT - { SWAP ; DIG 3 ; DROP 3 } - { DROP ; - CAR ; - GET 9 ; - NOT ; - IF { DUP ; - CDR ; - PUSH bool True ; - DIG 3 ; - CAR ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 2 } - { SWAP ; DROP } } } ; - SWAP ; - DIG 4 ; - DROP 2 ; - DUP ; - CDR ; - ITER { UNPAIR ; - DUP 5 ; - DUP 6 ; - GET 6 ; - DUP 8 ; - DIG 7 ; - GET 6 ; - DUP 5 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 4 ; - UPDATE 9 ; - DIG 3 ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - DUG 2 } ; - DIG 3 ; - DROP ; - CAR ; - NIL operation ; - SWAP ; - ITER { CONS } ; - ITER { CONS } } } } - { DIG 2 ; - DIG 3 ; + DUG 7 ; + DUP ; + DUP 5 ; + CAR ; + PAIR 3 ; + DIG 7 ; + PUSH string "Lending has no suited redeem entrypoint" ; + DUP 8 ; + CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 3 ; + TRANSFER_TOKENS ; + CONS ; + DUG 6 } + { PUSH bool False ; + PUSH bool True ; + DUP 9 ; + PAIR ; + DUP 6 ; + CAR ; + DUP 4 ; + PAIR ; + PAIR ; + PAIR ; + DUP 19 ; + SWAP ; + EXEC ; + PUSH nat 0 ; + DUP 2 ; + COMPARE ; + GT ; + PUSH nat 0 ; + DUP 4 ; + COMPARE ; + GT ; + AND ; + IF { DIG 9 ; + PUSH string "Lending has no suited mint entrypoint" ; + DUP 10 ; + CONTRACT %mint (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 3 ; + DUP 5 ; + DUP 9 ; + CAR ; + PAIR 3 ; + TRANSFER_TOKENS ; + CONS ; + DIG 5 ; + DIG 2 ; + PAIR ; + SELF_ADDRESS ; + DUP 10 ; + GET 3 ; + CAR ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DUP 17 ; + SWAP ; + CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 2 ; + DIG 4 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS } + { DUP 17 ; + DUP 2 ; + CAR ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + NIL (pair address (list (pair address nat nat))) ; + NIL (pair address nat nat) ; + DIG 5 ; + DIG 5 ; + CDR ; + DIG 7 ; + PAIR 3 ; + CONS ; + DIG 4 ; + PAIR ; + CONS ; + TRANSFER_TOKENS } ; + CONS ; + DUG 6 } + { SWAP ; DIG 5 ; DROP 3 } } ; + DUP 8 ; + DIG 8 ; + GET 4 ; + DUP 5 ; + DIG 4 ; + UPDATE 10 ; + DUP 6 ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 4 ; + DUG 6 ; + SWAP ; + CAR ; + SWAP ; + DIG 2 ; + PAIR 3 ; + DIG 2 ; + SWAP ; + CONS ; + SWAP } + { DROP 4 } } } ; DIG 4 ; DIG 5 ; DIG 6 ; DIG 7 ; + DIG 8 ; DIG 9 ; DIG 10 ; - DROP 8 ; - SWAP ; - NIL operation ; - EMPTY_SET nat ; - DIG 3 ; - ITER { DUP 5 ; - DUP 5 ; - GET 6 ; - DUP 3 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 2 ; - DUP 2 ; - GET 3 ; - PUSH bool True ; - SWAP ; - UPDATE ; - DUG 2 ; - DIG 3 ; - DUP 5 ; - GET 3 ; - CAR ; - PUSH string "Lending has no suited updateInterest entrypoint" ; - SWAP ; - CONTRACT %updateInterest nat ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DUP 4 ; - GET 3 ; - TRANSFER_TOKENS ; - CONS ; - DUG 3 ; - DUP 5 ; - DIG 5 ; - GET 6 ; - DIG 2 ; - NOW ; - UPDATE 10 ; - DIG 3 ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - DUG 2 } ; - DIG 3 ; - DROP ; - SWAP ; - DUP 3 ; - GET 3 ; - CDR ; - PUSH string "Lending's PriceFeed has no suited getPrice entrypoint" ; - SWAP ; - CONTRACT %getPrice (set nat) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DIG 3 ; - TRANSFER_TOKENS ; - CONS } ; + DIG 11 ; + DROP 9 ; + PUSH nat 0 ; + DUP 2 ; + SIZE ; + COMPARE ; + GT ; + IF { EMIT %rebalance + (list (pair (nat %pool_token_id) (int %rebalanced) (nat %lending_market_id))) ; + CONS } + { DROP } } ; PAIR } ; view "get_pool_data" unit - (pair (address %pool_contract) (nat %pool_id)) - { CDR ; GET 5 } } + (pair (address %pool_contract) + (nat %pool_id) + (map %token_map + nat + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + { CDR ; GET 3 } ; + view "should_rebalance" + (map nat nat) + bool + { UNPAIR ; + PUSH bool True ; + SWAP ; + ITER { UNPAIR ; + DUP 4 ; + GET 4 ; + SWAP ; + GET ; + IF_NONE + { DROP } + { PUSH nat 0 ; + DUP 2 ; + GET 10 ; + COMPARE ; + NEQ ; + PUSH nat 0 ; + DUP 4 ; + COMPARE ; + EQ ; + AND ; + IF { DROP 2 ; PUSH bool False } + { SWAP ; + PUSH nat 1000000000000000000 ; + DUP 3 ; + GET 10 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 2 ; + GET 5 ; + DIG 2 ; + GET 3 ; + DIG 2 ; + SUB ; + ABS ; + COMPARE ; + LT } ; + AND } } ; + SWAP ; + DROP ; + NOT } ; + view "deposit_map" unit (map nat nat) { CDR ; GET 4 ; MAP { CDR ; GET 10 } } } diff --git a/test/utils/mocks/artifacts/strategy_factory.tz b/test/utils/mocks/artifacts/strategy_factory.tz index aa03621..9e59b2f 100644 --- a/test/utils/mocks/artifacts/strategy_factory.tz +++ b/test/utils/mocks/artifacts/strategy_factory.tz @@ -1,10 +1,14 @@ { parameter (or (pair %deploy_strategy - (pair %pool_info (address %pool_contract) (nat %pool_id)) - (pair %lending_data (address %lending_contract) (address %price_feed_contract))) + (address %pool_contract) + (nat %pool_id) + (map %token_map + nat + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) (or %use_dev (unit %approve_developer) (address %change_developer))) ; storage (pair (pair %dev (address %dev_address) (option %temp_dev_address address)) + (address %lending_contract) (big_map %deployed_strategies (pair (address %pool_contract) (nat %pool_id)) address) @@ -29,13 +33,10 @@ COMPARE ; EQ ; IF { DROP } { FAILWITH } ; - EMPTY_MAP nat (pair (or address (pair address nat)) nat nat timestamp bool timestamp) ; + EMPTY_MAP nat (pair nat nat nat nat bool nat) ; DUP 3 ; - CAR ; - DUP 4 ; - CDR ; SELF_ADDRESS ; - PAIR 4 ; + PAIR 3 ; PUSH mutez 0 ; NONE key_hash ; PAIR ; @@ -43,28 +44,33 @@ UNPPAIIR ; CREATE_CONTRACT { parameter - (or (or (or %dev_part - (list %claim_rewards nat) - (pair %update_lending (address %lending_contract) (address %price_feed_contract))) - (or %dex_part - (pair %update_token_info - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (or (or %dev_part + (or (list %approve_token (pair (nat %pool_token_id) (address %spender) (nat %amount))) + (list %claim_rewards nat)) + (or (pair %connect_token_to_lending (nat %pool_token_id) (nat %lending_market_id)) + (pair %update_token_config (nat %pool_token_id) - (nat %lending_market_id)) - (list %update_token_state (pair (nat %pool_token_id) (nat %new_balance))))) - (list %prepare nat)) ; + (nat %desired_reserves_rate_f) + (nat %delta_rate_f) + (nat %min_invest) + (bool %enabled)))) + (pair %update_state (map %tokens nat nat) (bool %manual))) ; storage (pair (address %factory) - (pair %lending_data (address %lending_contract) (address %price_feed_contract)) - (pair %pool_data (address %pool_contract) (nat %pool_id)) + (pair %pool_data + (address %pool_contract) + (nat %pool_id) + (map %token_map + nat + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) (map %token_map nat - (pair (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - (nat %lending_market_id) - (nat %invested_tokens) - (timestamp %upd_time) - (bool %approved) - (timestamp %prepared_time)))) ; + (pair (nat %lending_market_id) + (nat %desired_reserves_rate_f) + (nat %delta_rate_f) + (nat %min_invest) + (bool %enabled) + (nat %invested_tokens)))) ; code { LAMBDA (pair (pair (pair nat nat) address bool) bool) nat @@ -83,28 +89,41 @@ VIEW "convert" (pair (nat %amount) (timestamp %interestUpdateTime) (timestamp %priceUpdateTime)) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH string "'Update interest' for market should be called" ; + NOW ; + DUP 3 ; + GET 3 ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; CAR } ; - PUSH string "Factory has no suited dev_address view" ; + LAMBDA + (pair (pair (list nat) address) bool) + (map nat nat) + { UNPAIR ; + UNPAIR ; + PUSH string "Lending has no suited balanceOf view" ; + DIG 2 ; + DIG 3 ; + DIG 3 ; + MAP { SELF_ADDRESS ; PAIR } ; + PAIR ; + VIEW "balanceOf" + (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + EMPTY_MAP nat nat ; + SWAP ; + ITER { SWAP ; DUP 2 ; CDR ; SOME ; DIG 2 ; CAR ; CDR ; UPDATE } } ; PUSH string "No Token yet" ; + PUSH string "Not DEX pool token or wrong id" ; PUSH string "Contract hasn't update_operators/approve entrypoint" ; PUSH string "Contract has no transfer entrypoint" ; - PUSH string "'Update interest' and 'get price' for market should be called" ; - LAMBDA - (pair (option address) string) - address - { UNPAIR ; IF_NONE { FAILWITH } { SWAP ; DROP } } ; + PUSH string "No balance for token returned in balance response" ; LAMBDA int nat { ISNAT ; IF_NONE { PUSH string "Value is not natural" ; FAILWITH } {} } ; - PUSH timestamp 946684800 ; - PUSH bool False ; - NOW ; - PUSH nat 0 ; - PUSH nat 0 ; - PUSH address "tz1ZZZZZZZZZZZZZZZZZZZZZZZZZZZZNkiRg" ; - LEFT (pair address nat) ; - PAIR 6 ; + PUSH nat 1000000000000000000 ; DIG 9 ; UNPAIR ; SWAP ; @@ -115,606 +134,732 @@ IF { PUSH string "Sending XTZ not allowed here" ; FAILWITH } {} ; SWAP ; IF_LEFT - { IF_LEFT - { DIG 2 ; - DIG 7 ; - DROP 2 ; - PUSH string "Only developer is allowed here" ; - DUP 9 ; - DUP 4 ; - CAR ; - UNIT ; - VIEW "dev_address" address ; - PAIR ; - DUP 6 ; - SWAP ; - EXEC ; - SENDER ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; - IF_LEFT - { SWAP ; - NIL operation ; - DUP 2 ; - GET 6 ; - PUSH bool True ; - DUP 4 ; - GET 3 ; - CAR ; - DUP 6 ; - MAP { DUP 4 ; SWAP ; GET ; IF_NONE { DUP 11 ; FAILWITH } {} ; GET 3 } ; - DIG 3 ; - DROP ; - PUSH string "Lending has no suited balanceOf view" ; - DIG 2 ; - DIG 3 ; + { DIG 2 ; + DROP ; + PUSH string "Only developer is allowed here" ; + PUSH string "Factory has no suited dev_address view" ; + DUP 4 ; + CAR ; + UNIT ; + VIEW "dev_address" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + IF_LEFT + { IF_LEFT + { DIG 2 ; DIG 3 ; - MAP { SELF_ADDRESS ; PAIR } ; - PAIR ; - VIEW "balanceOf" - (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - EMPTY_MAP nat nat ; + DIG 4 ; + DIG 7 ; + DIG 8 ; + DIG 9 ; + DROP 6 ; SWAP ; - ITER { SWAP ; DUP 2 ; CDR ; SOME ; DIG 2 ; CAR ; CDR ; UPDATE } ; - DIG 3 ; - ITER { DUP 9 ; - DUP 5 ; - GET 6 ; - DUP 3 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 8 ; - NOW ; - DUP 3 ; - GET 10 ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; - PUSH nat 1 ; - DUP 4 ; - DIG 3 ; - GET ; - IF_NONE - { PUSH string "No balance for token returned in balance response" ; FAILWITH } - {} ; - SUB ; - DUP 6 ; - SWAP ; - EXEC ; - PUSH bool True ; - PUSH bool False ; - DUP 7 ; - GET 3 ; - CAR ; - PAIR ; + NIL operation ; + DIG 2 ; + ITER { DUP 5 ; DUP 4 ; GET 3 ; - DIG 3 ; - PAIR ; - PAIR ; - PAIR ; - DUP 12 ; - SWAP ; - EXEC ; - DUP 2 ; - GET 5 ; - SWAP ; - SUB ; - DUP 6 ; - SWAP ; - EXEC ; - DIG 3 ; - DUP 3 ; - CAR ; + GET 4 ; DUP 3 ; - PAIR ; - DUP 6 ; CAR ; - DUP 13 ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DIG 2 ; SWAP ; - UNIT ; - VIEW "dev_address" address ; + DUP 3 ; + GET 4 ; PAIR ; - DUP 9 ; - SWAP ; - EXEC ; + DIG 2 ; + GET 3 ; SELF_ADDRESS ; DIG 2 ; UNPAIR ; SWAP ; IF_LEFT - { DUP 13 ; + { DIG 2 ; + DROP ; + DUP 6 ; SWAP ; - CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; + CONTRACT %approve (pair (address %spender) (nat %value)) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; DIG 2 ; - DIG 4 ; - PAIR ; DIG 3 ; PAIR ; TRANSFER_TOKENS } - { DUP 13 ; + { DUP 7 ; DUP 2 ; CAR ; - CONTRACT %transfer - (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + CONTRACT %update_operators + (list (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) + (pair %remove_operator (address %owner) (address %operator) (nat %token_id)))) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; - NIL (pair address (list (pair address nat nat))) ; - NIL (pair address nat nat) ; - DIG 5 ; + NIL (or (pair address address nat) (pair address address nat)) ; + PUSH nat 0 ; DIG 5 ; - CDR ; - DIG 7 ; - PAIR 3 ; - CONS ; - DIG 4 ; - PAIR ; + COMPARE ; + GT ; + IF { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; LEFT (pair address address nat) } + { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; RIGHT (pair address address nat) } ; CONS ; TRANSFER_TOKENS } ; - CONS ; - DUP 5 ; + CONS } ; + DIG 2 ; + DIG 3 ; + DROP 2 } + { DIG 5 ; + DROP ; + SWAP ; + NIL operation ; + DUP 2 ; + GET 4 ; + DUP 3 ; + CAR ; + PUSH string "Factory has no suited lending_contract view" ; + SWAP ; + UNIT ; + VIEW "lending_contract" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH bool False ; + DUP 2 ; + DUP 7 ; + MAP { DUP 5 ; SWAP ; GET ; IF_NONE { DUP 12 ; FAILWITH } {} ; CAR } ; + DIG 4 ; + DROP ; + PAIR ; + PAIR ; + DIG 10 ; + SWAP ; + EXEC ; + NIL (pair nat int nat) ; + DIG 5 ; + ITER { DUP 10 ; + DUP 7 ; GET 3 ; - CDR ; - PUSH string "Lending has no suited redeem entrypoint" ; - SWAP ; - CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + GET 4 ; + DUP 3 ; + GET ; IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; + DUP 12 ; + DUP 8 ; + GET 4 ; DUP 4 ; - DIG 4 ; - DIG 5 ; - GET 3 ; - PAIR 3 ; - TRANSFER_TOKENS ; - CONS ; - SWAP } ; - DIG 3 ; - DIG 4 ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH nat 1 ; + DUP 6 ; + DUP 3 ; + CAR ; + GET ; + IF_NONE { DUP 11 ; FAILWITH } {} ; + SUB ; + DUP 10 ; + SWAP ; + EXEC ; + PUSH bool True ; + PUSH bool False ; + DUP 9 ; + PAIR ; + DUP 4 ; + CAR ; + DIG 3 ; + PAIR ; + PAIR ; + PAIR ; + DUP 15 ; + SWAP ; + EXEC ; + DUP 2 ; + GET 10 ; + DUP 2 ; + SUB ; + DUP 3 ; + GET 10 ; + DUP 3 ; + COMPARE ; + GT ; + IF { DIG 5 ; + DUP 4 ; + CAR ; + DIG 2 ; + DIG 6 ; + PAIR 3 ; + CONS ; + DUG 3 ; + DUP 2 ; + GET 10 ; + SWAP ; + SUB ; + DUP 9 ; + SWAP ; + EXEC ; + DIG 6 ; + DIG 3 ; + DUP 3 ; + PAIR ; + DUP 8 ; + CAR ; + PUSH string "Factory has no suited dev_address view" ; + SWAP ; + UNIT ; + VIEW "dev_address" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + SELF_ADDRESS ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DUP 14 ; + SWAP ; + CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 2 ; + DIG 4 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS } + { DUP 14 ; + DUP 2 ; + CAR ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + NIL (pair address (list (pair address nat nat))) ; + NIL (pair address nat nat) ; + DIG 5 ; + DIG 5 ; + CDR ; + DIG 7 ; + PAIR 3 ; + CONS ; + DIG 4 ; + PAIR ; + CONS ; + TRANSFER_TOKENS } ; + CONS ; + PUSH string "Lending has no suited redeem entrypoint" ; + DUP 7 ; + CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DUP 4 ; + DIG 4 ; + DIG 5 ; + CAR ; + PAIR 3 ; + TRANSFER_TOKENS ; + CONS ; + DUG 3 } + { DROP 5 } } ; + SWAP ; + DIG 2 ; DIG 5 ; DIG 6 ; DIG 7 ; DIG 8 ; DIG 9 ; - DROP 8 } - { DIG 2 ; - DIG 3 ; - DIG 4 ; - DIG 5 ; - DIG 6 ; - DIG 7 ; - DIG 8 ; - DROP 7 ; - UPDATE 3 ; - NIL operation } } - { DIG 4 ; + DIG 10 ; + DROP 8 ; + EMIT %claim_rewards + (list (pair (nat %pool_token_id) (int %reward) (nat %lending_market_id))) ; + CONS } } + { DIG 2 ; + DIG 3 ; + DIG 4 ; + DIG 5 ; + DIG 8 ; DIG 9 ; - DROP 2 ; - PUSH string "Only dex is allowed here" ; - DUP 3 ; - GET 5 ; - CAR ; - SENDER ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; + DROP 6 ; IF_LEFT { DIG 3 ; - DIG 4 ; - DIG 5 ; - DIG 6 ; - DIG 7 ; - DIG 8 ; - DROP 6 ; + DROP ; SWAP ; - PUSH string "Token already added" ; + DIG 2 ; DUP 2 ; - GET 6 ; - DUP 4 ; GET 3 ; + GET 4 ; + DUP 4 ; + CAR ; MEM ; - NOT ; IF { DROP } { FAILWITH } ; - DUP ; - GET 6 ; - DIG 3 ; + PUSH nat 0 ; + PUSH bool False ; + PUSH nat 0 ; + PUSH nat 0 ; + PUSH nat 0 ; + PUSH nat 0 ; + PAIR 6 ; + DUP 2 ; + GET 4 ; DUP 4 ; CAR ; + GET ; + IF_NONE {} { SWAP ; DROP } ; + PUSH nat 0 ; + DUP 2 ; + GET 10 ; + COMPARE ; + EQ ; + IF {} { PUSH string "Unclaimed reserves from Yupana" ; FAILWITH } ; + DUP 2 ; + DIG 2 ; + GET 4 ; + DIG 2 ; + DUP 4 ; + CDR ; UPDATE 1 ; + SOME ; + DIG 3 ; + CAR ; + UPDATE ; + UPDATE 4 } + { SWAP ; + DIG 2 ; + DUP 2 ; + GET 3 ; + GET 4 ; DUP 4 ; + CAR ; + MEM ; + IF { DROP } { FAILWITH } ; + DIG 2 ; + DUP 2 ; GET 4 ; - UPDATE 3 ; - DIG 3 ; + DUP 4 ; + CAR ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 2 ; + DIG 2 ; + GET 4 ; + DIG 2 ; + DUP 4 ; GET 3 ; - SWAP ; + UPDATE 3 ; + DUP 4 ; + GET 5 ; + UPDATE 5 ; + DUP 4 ; + GET 7 ; + UPDATE 7 ; + DUP 4 ; + GET 8 ; + UPDATE 9 ; SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - NIL operation } - { DIG 2 ; - DROP ; - SWAP ; - NIL operation ; - EMPTY_MAP - nat - (pair (pair (or address (pair address nat)) nat nat timestamp bool timestamp) nat) ; DIG 3 ; - ITER { DUP 9 ; - DUP 5 ; - GET 6 ; - DUP 3 ; - CAR ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 7 ; - NOW ; - DUP 3 ; - GET 10 ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; - DUP ; - GET 5 ; - DUP 3 ; - CDR ; - SUB ; - ISNAT ; - IF_NONE - { DUP 2 ; - CDR ; - DUP 2 ; - GET 5 ; - SUB ; - DUP 7 ; - SWAP ; - EXEC ; - DIG 4 ; - DUP 3 ; - CAR ; - DUP 3 ; - PAIR ; - DUP 7 ; - GET 5 ; - CAR ; - SELF_ADDRESS ; - DIG 2 ; - UNPAIR ; - SWAP ; - IF_LEFT - { DUP 13 ; - SWAP ; - CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DIG 2 ; - DIG 4 ; - PAIR ; - DIG 3 ; - PAIR ; - TRANSFER_TOKENS } - { DUP 13 ; - DUP 2 ; - CAR ; - CONTRACT %transfer - (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - NIL (pair address (list (pair address nat nat))) ; - NIL (pair address nat nat) ; - DIG 5 ; - DIG 5 ; - CDR ; - DIG 7 ; - PAIR 3 ; - CONS ; - DIG 4 ; - PAIR ; - CONS ; - TRANSFER_TOKENS } ; - CONS ; - DUP 6 ; - GET 3 ; - CAR ; - PUSH string "Lending has no suited redeem entrypoint" ; - SWAP ; - CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DUP 4 ; - DIG 4 ; - DUP 6 ; - GET 3 ; - PAIR 3 ; - TRANSFER_TOKENS ; - CONS ; - DUG 3 } - { PUSH bool False ; - PUSH bool True ; - DUP 8 ; - GET 3 ; - CAR ; - PAIR ; - DUP 4 ; - GET 3 ; - DUP 4 ; - PAIR ; - PAIR ; - PAIR ; - DUP 13 ; - SWAP ; - EXEC ; - PUSH nat 0 ; - DUP 2 ; - COMPARE ; - GT ; - PUSH nat 0 ; - DUP 4 ; - COMPARE ; - GT ; - AND ; - IF { DIG 5 ; - DUP 7 ; - GET 3 ; - CAR ; - PUSH string "Lending has no suited mint entrypoint" ; - SWAP ; - CONTRACT %mint (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DIG 3 ; - DUP 5 ; - DUP 7 ; - GET 3 ; - PAIR 3 ; - TRANSFER_TOKENS ; - CONS ; - DUG 4 ; - DIG 3 ; - SWAP ; - DUP 3 ; - PAIR ; - DUP 4 ; - CAR ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - DUG 2 } - { DROP 2 } } ; - DUP 5 ; - DIG 5 ; - GET 6 ; - DIG 2 ; - DUP 4 ; - CDR ; - UPDATE 5 ; - NOW ; - UPDATE 7 ; - DIG 3 ; - CAR ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - DUG 2 } ; - DIG 3 ; - DIG 4 ; - DIG 5 ; - DIG 8 ; - DROP 4 ; - DUP 3 ; - GET 3 ; CAR ; - SWAP ; - EMPTY_MAP nat bool ; - NIL operation ; - PAIR ; - SWAP ; - ITER { SWAP ; - DUP 2 ; - CDR ; - DUP ; - CAR ; - GET 9 ; - NOT ; - IF { DUP 2 ; - DIG 2 ; + UPDATE ; + UPDATE 4 } ; + NIL operation } } + { DIG 6 ; + DIG 8 ; + DROP 2 ; + DUP 2 ; + GET 3 ; + CAR ; + PUSH string "Only dex is allowed here" ; + SWAP ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + SWAP ; + NIL operation ; + NIL (pair nat int nat) ; + DUP 3 ; + CAR ; + PUSH string "Factory has no suited lending_contract view" ; + SWAP ; + UNIT ; + VIEW "lending_contract" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 5 ; + CAR ; + ITER { UNPAIR ; + DUP 12 ; + DUP 7 ; + GET 3 ; + GET 4 ; + DUP 3 ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 7 ; + GET 4 ; + DUP 3 ; + GET ; + IF_NONE + { DROP 3 } + { PUSH nat 0 ; + DUP 2 ; + GET 10 ; + COMPARE ; + NEQ ; + PUSH nat 0 ; + DUP 6 ; + COMPARE ; + EQ ; + AND ; + IF { PUSH bool True } + { DUP 4 ; + DUP 11 ; + DUP 3 ; + GET 10 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 2 ; + GET 5 ; + DUP 3 ; + GET 3 ; + DIG 2 ; + SUB ; + ABS ; + COMPARE ; + LT ; + NOT } ; + DUP 2 ; + GET 9 ; + DUP 11 ; + CDR ; + OR ; + AND ; + IF { DUP 10 ; + DUP 2 ; + GET 3 ; + DIG 5 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 2 ; + GET 7 ; + DUP 2 ; + COMPARE ; + GT ; + IF {} { DROP ; PUSH nat 0 } ; + DUP 2 ; + GET 10 ; + DUP 2 ; + SUB ; + DUP ; + ISNAT ; + IF_NONE + { DUP ; + ABS ; + PUSH bool False ; + DUP 8 ; + NIL nat ; + DUP 7 ; CAR ; - DUP 3 ; + CONS ; + PAIR ; + PAIR ; + DUP 18 ; + SWAP ; + EXEC ; + DUP 5 ; CAR ; + GET ; + IF_NONE { DUP 14 ; FAILWITH } {} ; + PUSH bool True ; + PUSH bool False ; + DUP 10 ; + PAIR ; + DUP 7 ; CAR ; - DUP 4 ; - CDR ; + DIG 3 ; PAIR ; - DUP 6 ; + PAIR ; + PAIR ; + DUP 19 ; + SWAP ; + EXEC ; + DUP 2 ; + SWAP ; + COMPARE ; + LT ; + IF { PUSH nat 1 ; + SWAP ; + SUB ; + DUP 13 ; + SWAP ; + EXEC ; + PUSH nat 1 ; + DIG 3 ; + ADD ; + DUG 2 ; + PUSH nat 1 ; + DIG 2 ; + ADD ; + SWAP } + {} ; + DIG 8 ; + DIG 5 ; + DUP 3 ; + PAIR ; + DUP 10 ; + GET 3 ; + CAR ; SELF_ADDRESS ; DIG 2 ; UNPAIR ; SWAP ; IF_LEFT - { DIG 2 ; - DROP ; - DUP 11 ; + { DUP 18 ; SWAP ; - CONTRACT %approve (pair (address %spender) (nat %value)) ; + CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; DIG 2 ; + DIG 4 ; + PAIR ; DIG 3 ; PAIR ; TRANSFER_TOKENS } - { DUP 12 ; + { DUP 18 ; DUP 2 ; CAR ; - CONTRACT %update_operators - (list (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) - (pair %remove_operator (address %owner) (address %operator) (nat %token_id)))) ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; PUSH mutez 0 ; - NIL (or (pair address address nat) (pair address address nat)) ; - PUSH nat 0 ; + NIL (pair address (list (pair address nat nat))) ; + NIL (pair address nat nat) ; + DIG 5 ; DIG 5 ; - COMPARE ; - GT ; - IF { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; LEFT (pair address address nat) } - { DIG 3 ; CDR ; DIG 5 ; DIG 5 ; PAIR 3 ; RIGHT (pair address address nat) } ; + CDR ; + DIG 7 ; + PAIR 3 ; + CONS ; + DIG 4 ; + PAIR ; CONS ; TRANSFER_TOKENS } ; CONS ; - UPDATE 1 ; - SWAP } - {} ; - DUP ; - CAR ; - CAR ; - IF_LEFT - { SWAP ; DIG 3 ; DROP 3 } - { DROP ; - CAR ; - GET 9 ; - NOT ; - IF { DUP ; - CDR ; - PUSH bool True ; - DIG 3 ; - CAR ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 2 } - { SWAP ; DROP } } } ; - SWAP ; - DIG 4 ; - DROP 2 ; - DUP ; - CDR ; - ITER { UNPAIR ; - DUP 5 ; - DUP 6 ; - GET 6 ; - DUP 8 ; - DIG 7 ; - GET 6 ; - DUP 5 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 4 ; - UPDATE 9 ; - DIG 3 ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - DUG 2 } ; - DIG 3 ; - DROP ; - CAR ; - NIL operation ; - SWAP ; - ITER { CONS } ; - ITER { CONS } } } } - { DIG 2 ; - DIG 3 ; + DUG 7 ; + DUP ; + DUP 5 ; + CAR ; + PAIR 3 ; + DIG 7 ; + PUSH string "Lending has no suited redeem entrypoint" ; + DUP 8 ; + CONTRACT %redeem (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 3 ; + TRANSFER_TOKENS ; + CONS ; + DUG 6 } + { PUSH bool False ; + PUSH bool True ; + DUP 9 ; + PAIR ; + DUP 6 ; + CAR ; + DUP 4 ; + PAIR ; + PAIR ; + PAIR ; + DUP 19 ; + SWAP ; + EXEC ; + PUSH nat 0 ; + DUP 2 ; + COMPARE ; + GT ; + PUSH nat 0 ; + DUP 4 ; + COMPARE ; + GT ; + AND ; + IF { DIG 9 ; + PUSH string "Lending has no suited mint entrypoint" ; + DUP 10 ; + CONTRACT %mint (pair (nat %tokenId) (nat %amount) (nat %minReceived)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 3 ; + DUP 5 ; + DUP 9 ; + CAR ; + PAIR 3 ; + TRANSFER_TOKENS ; + CONS ; + DIG 5 ; + DIG 2 ; + PAIR ; + SELF_ADDRESS ; + DUP 10 ; + GET 3 ; + CAR ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DUP 17 ; + SWAP ; + CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 2 ; + DIG 4 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS } + { DUP 17 ; + DUP 2 ; + CAR ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + NIL (pair address (list (pair address nat nat))) ; + NIL (pair address nat nat) ; + DIG 5 ; + DIG 5 ; + CDR ; + DIG 7 ; + PAIR 3 ; + CONS ; + DIG 4 ; + PAIR ; + CONS ; + TRANSFER_TOKENS } ; + CONS ; + DUG 6 } + { SWAP ; DIG 5 ; DROP 3 } } ; + DUP 8 ; + DIG 8 ; + GET 4 ; + DUP 5 ; + DIG 4 ; + UPDATE 10 ; + DUP 6 ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 4 ; + DUG 6 ; + SWAP ; + CAR ; + SWAP ; + DIG 2 ; + PAIR 3 ; + DIG 2 ; + SWAP ; + CONS ; + SWAP } + { DROP 4 } } } ; DIG 4 ; DIG 5 ; DIG 6 ; DIG 7 ; + DIG 8 ; DIG 9 ; DIG 10 ; - DROP 8 ; - SWAP ; - NIL operation ; - EMPTY_SET nat ; - DIG 3 ; - ITER { DUP 5 ; - DUP 5 ; - GET 6 ; - DUP 3 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 2 ; - DUP 2 ; - GET 3 ; - PUSH bool True ; - SWAP ; - UPDATE ; - DUG 2 ; - DIG 3 ; - DUP 5 ; - GET 3 ; - CAR ; - PUSH string "Lending has no suited updateInterest entrypoint" ; - SWAP ; - CONTRACT %updateInterest nat ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DUP 4 ; - GET 3 ; - TRANSFER_TOKENS ; - CONS ; - DUG 3 ; - DUP 5 ; - DIG 5 ; - GET 6 ; - DIG 2 ; - NOW ; - UPDATE 10 ; - DIG 3 ; - SWAP ; - SOME ; - SWAP ; - UPDATE ; - UPDATE 6 ; - DUG 2 } ; - DIG 3 ; - DROP ; - SWAP ; - DUP 3 ; - GET 3 ; - CDR ; - PUSH string "Lending's PriceFeed has no suited getPrice entrypoint" ; - SWAP ; - CONTRACT %getPrice (set nat) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH mutez 0 ; - DIG 3 ; - TRANSFER_TOKENS ; - CONS } ; + DIG 11 ; + DROP 9 ; + PUSH nat 0 ; + DUP 2 ; + SIZE ; + COMPARE ; + GT ; + IF { EMIT %rebalance + (list (pair (nat %pool_token_id) (int %rebalanced) (nat %lending_market_id))) ; + CONS } + { DROP } } ; PAIR } ; view "get_pool_data" unit - (pair (address %pool_contract) (nat %pool_id)) - { CDR ; GET 5 } } ; - DUP 3 ; - DIG 3 ; - GET 3 ; + (pair (address %pool_contract) + (nat %pool_id) + (map %token_map + nat + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + { CDR ; GET 3 } ; + view "should_rebalance" + (map nat nat) + bool + { UNPAIR ; + PUSH bool True ; + SWAP ; + ITER { UNPAIR ; + DUP 4 ; + GET 4 ; + SWAP ; + GET ; + IF_NONE + { DROP } + { PUSH nat 0 ; + DUP 2 ; + GET 10 ; + COMPARE ; + NEQ ; + PUSH nat 0 ; + DUP 4 ; + COMPARE ; + EQ ; + AND ; + IF { DROP 2 ; PUSH bool False } + { SWAP ; + PUSH nat 1000000000000000000 ; + DUP 3 ; + GET 10 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 2 ; + GET 5 ; + DIG 2 ; + GET 3 ; + DIG 2 ; + SUB ; + ABS ; + COMPARE ; + LT } ; + AND } } ; + SWAP ; + DROP ; + NOT } ; + view "deposit_map" unit (map nat nat) { CDR ; GET 4 ; MAP { CDR ; GET 10 } } } ; DUP 4 ; - DUP 6 ; + GET 3 ; + DIG 4 ; CAR ; + PAIR ; + DUP 4 ; + DIG 4 ; + GET 5 ; + DUP 5 ; + DUP 4 ; SWAP ; SOME ; SWAP ; UPDATE ; - UPDATE 3 ; - DUG 2 ; - DUP 3 ; - DIG 3 ; - GET 4 ; + UPDATE 5 ; + DUG 3 ; + DUP 4 ; DIG 4 ; - CAR ; + GET 6 ; + DIG 2 ; DIG 4 ; SWAP ; SOME ; SWAP ; UPDATE ; - UPDATE 4 ; + UPDATE 6 ; NIL operation ; DIG 2 ; CONS } @@ -750,5 +895,6 @@ NIL operation } ; PAIR } ; view "dev_address" unit address { CDR ; CAR ; CAR } ; - view "is_registered" address bool { UNPAIR ; SWAP ; GET 4 ; SWAP ; MEM } } + view "is_registered" address bool { UNPAIR ; SWAP ; GET 6 ; SWAP ; MEM } ; + view "lending_contract" unit address { CDR ; GET 3 } } diff --git a/test/utils/mocks/artifacts/yupana.tz b/test/utils/mocks/artifacts/yupana.tz index f99b7ab..b2f24fd 100644 --- a/test/utils/mocks/artifacts/yupana.tz +++ b/test/utils/mocks/artifacts/yupana.tz @@ -21,10 +21,6 @@ (pair (option (contract (list (pair address (list (pair address nat nat)))))) string) (contract (list (pair address (list (pair address nat nat))))) { UNPAIR ; IF_NONE { FAILWITH } { SWAP ; DROP } } ; - LAMBDA - int - nat - { ISNAT ; IF_NONE { PUSH string "Value is not natural" ; FAILWITH } {} } ; PUSH nat 1000000 ; PUSH string "No market on lending" ; LAMBDA @@ -44,7 +40,7 @@ DUP 2 ; GET 3 ; GET ; - IF_NONE { PUSH string "No Token yet" ; FAILWITH } {} ; + IF_NONE { PUSH string "No Token yet1" ; FAILWITH } {} ; DUP ; GET 11 ; DUP 3 ; @@ -111,16 +107,14 @@ PAIR 3 } ; DUP 3 ; APPLY ; - DIG 6 ; + DIG 5 ; UNPAIR ; SWAP ; NIL operation ; DIG 2 ; IF_LEFT { IF_LEFT - { DIG 6 ; - DROP ; - IF_LEFT + { IF_LEFT { DIG 4 ; DUP 4 ; GET 3 ; @@ -297,38 +291,31 @@ COMPARE ; EQ ; IF { DROP } { FAILWITH } ; - PUSH string "TIMEOUT" ; - DUP 2 ; - GET 5 ; - NOW ; - COMPARE ; - EQ ; - IF { DROP } { FAILWITH } ; DUP 4 ; DIG 4 ; GET 3 ; DUP 3 ; - DUP 8 ; - DUP 6 ; + PUSH string "Low TOTAL SUPPLY" ; + DUP 9 ; + DUP 7 ; GET 3 ; MUL ; - DUP 5 ; + DUP 6 ; GET 9 ; SUB ; - DUP 10 ; - SWAP ; - EXEC ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; UPDATE 9 ; - DIG 7 ; - DUP 6 ; + PUSH string "Low LIQUIDITY" ; + DIG 8 ; + DUP 7 ; GET 3 ; MUL ; - DUP 5 ; + DUP 6 ; GET 11 ; SUB ; - DUP 9 ; - SWAP ; - EXEC ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; UPDATE 11 ; DUP 5 ; CAR ; @@ -363,9 +350,9 @@ UNPAIR ; SWAP ; IF_LEFT - { DIG 10 ; + { DIG 9 ; DROP ; - DIG 10 ; + DIG 9 ; SWAP ; CONTRACT %transfer (pair (address %from) (address %to) (nat %value)) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; @@ -376,13 +363,13 @@ DIG 3 ; PAIR ; TRANSFER_TOKENS } - { DIG 11 ; + { DIG 10 ; DUP 2 ; CAR ; CONTRACT %transfer (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; PAIR ; - DIG 11 ; + DIG 10 ; SWAP ; EXEC ; PUSH mutez 0 ; @@ -403,20 +390,20 @@ DUP 5 ; DUP 6 ; CAR ; - DIG 3 ; + PUSH string "Low shares balance" ; + DIG 4 ; CAR ; - DIG 6 ; + DIG 7 ; CAR ; - DUP 6 ; + DUP 7 ; CAR ; - DUP 6 ; + DUP 7 ; PAIR ; GET ; IF_NONE { PUSH nat 0 } {} ; SUB ; - DIG 6 ; - SWAP ; - EXEC ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; DIG 4 ; CAR ; DIG 4 ; @@ -430,8 +417,7 @@ DIG 5 ; DIG 6 ; DIG 7 ; - DIG 8 ; - DROP 5 ; + DROP 4 ; DUP 3 ; DUP 4 ; GET 3 ; @@ -456,8 +442,7 @@ DIG 5 ; DIG 6 ; DIG 7 ; - DIG 8 ; - DROP 5 ; + DROP 4 ; IF_LEFT { DIG 3 ; DROP ; DIG 2 ; SWAP ; UPDATE 4 } { DUP 3 ; @@ -518,7 +503,7 @@ DUP 2 ; GET 3 ; GET ; - IF_NONE { PUSH string "No Token yet" ; FAILWITH } {} ; + IF_NONE { PUSH string "No Token yet1" ; FAILWITH } {} ; DUP ; GET 11 ; DUP 3 ;