diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d736ba4..75df35f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,56 +6,115 @@ on: - main - develop pull_request: - branches: - - main - - develop + jobs: + compile: + name: Compile contracts + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - uses: actions/cache@v3 + id: contracts-build + with: + path: | + build + contracts/compiled + key: compiled-contracts-${{ runner.os }}-${{ hashFiles('contracts/**/*.ligo') }} + - name: Setup dependencies + uses: actions/setup-node@v3 + with: + node-version: "18" + cache: 'yarn' + cache-dependency-path: './yarn.lock' + - name: Install modules + if: steps.contracts-build.outputs.cache-hit != 'true' + run: yarn install --immutable --immutable-cache --check-cache + - name: Compile contracts and test + if: steps.contracts-build.outputs.cache-hit != 'true' + run: yarn compile + compile-test: + name: Compile contracts for tests + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - uses: actions/cache@v3 + id: contracts-build + with: + path: | + build + contracts/compiled + key: compiled-test-contracts-${{ runner.os }}-jest-${{ hashFiles('contracts/**/*.ligo') }} + - name: Setup dependencies + uses: actions/setup-node@v3 + with: + node-version: "18" + cache: 'yarn' + cache-dependency-path: './yarn.lock' + - name: Install modules + if: steps.contracts-build.outputs.cache-hit != 'true' + run: yarn install --immutable --immutable-cache --check-cache + - name: Compile contracts and test + if: steps.contracts-build.outputs.cache-hit != 'true' + run: yarn compile-for-test jest: + needs: compile-test name: Jest tests runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup dependencies - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: "14" + node-version: "18" cache: 'yarn' cache-dependency-path: './yarn.lock' - - name: Install Git - run: sudo apt install git -y - name: Install modules - run: yarn install - - name: Compile contracts for tests - run: yarn compile-for-test - - name: Start sandbox and wait for initialization - run: yarn start-sandbox && sleep 10s + run: yarn install --immutable --immutable-cache --check-cache + - uses: actions/cache@v3 + id: contracts-build + with: + path: | + build + contracts/compiled + key: compiled-test-contracts-${{ runner.os }}-jest-${{ hashFiles('contracts/**/*.ligo') }} + - name: Start sandbox + run: yarn start-sandbox + - name: Wait for Sandbox endpoint + uses: emilioschepis/wait-for-endpoint@v1.0.3 + with: + url: http://localhost:20000/chains/main/blocks/head + - name: sleep for 10s + run: sleep 10s - name: Test the contracts run: yarn test - name: Stop sandbox run: yarn stop-sandbox pytest: + needs: compile name: Pytest tests runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: "14" - cache: 'yarn' - cache-dependency-path: './yarn.lock' - - name: Set up Python - run: sudo apt install python pip + uses: actions/checkout@v3 - name: Install crypto libs run: sudo apt install libsodium-dev libsecp256k1-dev libgmp-dev + - uses: actions/cache@v3 + id: contracts-build + with: + path: | + build + contracts/compiled + key: compiled-contracts-${{ runner.os }}-${{ hashFiles('contracts/**/*.ligo') }} + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + cache: 'pip' - name: Install pytezos and pytest - run: pip install pytezos pytest - - name: Install node modules - run: yarn install - - name: Compile contracts - run: yarn compile + run: pip install -r scenario/requirements.txt - name: Run scenario tests run: pytest -s -v diff --git a/config.ts b/config.ts index f9864e5..52b61cd 100644 --- a/config.ts +++ b/config.ts @@ -5,13 +5,13 @@ dotenv.config(); export const config = { repoName: "quipuswap-stable-core", - ligoVersion: "0.41.0", + ligoVersion: "0.56.0", preferredLigoFlavor: "pascaligo", networks: { sandbox: { - host: "http://localhost", + host: "http://127.0.0.1", port: 20000, - protocol: TezosProtocols.ITHACA, + protocol: TezosProtocols.KATHMANDU, genesisBlockHash: "random", defaultSignerSK: "edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq", accounts: { @@ -33,12 +33,12 @@ export const config = { }, }, testnet: { - host: "https://ithacanet.ecadinfra.com", + host: "https://rpc.ghostnet.testnets.xyz", port: 443, faucet: null, }, mainnet: { - host: "https://mainnet-tezos.giganode.io", + host: "https://mainnet-node.madfish.solutions", port: 443, }, }, @@ -49,8 +49,9 @@ export const config = { contractsDirectory: "contracts/main", outputDirectory: "build", migrationsDir: "migrations", + lambdasDir: "contract_lambdas", dockerizedLigo: true, - ligoLocalPath: "./ligo", + ligoLocalPath: "ligo", }; export default config; diff --git a/test/lambdas/Admin_lambdas.json b/contract_lambdas/Admin_lambdas.json similarity index 87% rename from test/lambdas/Admin_lambdas.json rename to contract_lambdas/Admin_lambdas.json index 8c8fbec..fb8d7e5 100644 --- a/test/lambdas/Admin_lambdas.json +++ b/contract_lambdas/Admin_lambdas.json @@ -30,5 +30,9 @@ { "index": 7, "name": "add_pool" + }, + { + "index": 8, + "name": "set_strategy_factory" } ] diff --git a/test/lambdas/Dev_lambdas.json b/contract_lambdas/Dev_lambdas.json similarity index 100% rename from test/lambdas/Dev_lambdas.json rename to contract_lambdas/Dev_lambdas.json diff --git a/test/lambdas/Dex_lambdas.json b/contract_lambdas/Dex_lambdas.json similarity index 100% rename from test/lambdas/Dex_lambdas.json rename to contract_lambdas/Dex_lambdas.json diff --git a/contract_lambdas/Strategy_lambdas.json b/contract_lambdas/Strategy_lambdas.json new file mode 100644 index 0000000..1514335 --- /dev/null +++ b/contract_lambdas/Strategy_lambdas.json @@ -0,0 +1,22 @@ +[ + { + "index": 0, + "name": "connect_strategy" + }, + { + "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/test/lambdas/Token_lambdas.json b/contract_lambdas/Token_lambdas.json similarity index 100% rename from test/lambdas/Token_lambdas.json rename to contract_lambdas/Token_lambdas.json diff --git a/contracts/compiled/dex4factory.tz b/contracts/compiled/dex4factory.tz index 8c27f16..7d6b3d5 100644 --- a/contracts/compiled/dex4factory.tz +++ b/contracts/compiled/dex4factory.tz @@ -10,63 +10,80 @@ (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 %user_action - (or %use_dex - (or (or (pair %claim_referral - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - (nat %amount)) - (pair %divest + (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))) + (or %user_action + (or %use_dex + (or (or (pair %claim_referral + (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (nat %amount)) + (pair %divest + (nat %pool_id) + (map %min_amounts_out nat nat) + (nat %shares) + (timestamp %deadline) + (option %receiver address))) + (or (pair %divest_imbalanced + (nat %pool_id) + (map %amounts_out nat nat) + (nat %max_shares) + (timestamp %deadline) + (option %receiver address) + (option %referral address)) + (pair %divest_one_coin + (nat %pool_id) + (nat %shares) + (nat %token_index) + (nat %min_amount_out) + (timestamp %deadline) + (option %receiver address) + (option %referral address)))) + (or (or (pair %invest + (nat %pool_id) + (nat %shares) + (map %in_amounts nat nat) + (timestamp %deadline) + (option %receiver address) + (option %referral address)) + (or %stake + (pair %add (nat %pool_id) (nat %amount)) + (pair %remove (nat %pool_id) (nat %amount)))) + (pair %swap (nat %pool_id) - (map %min_amounts_out nat nat) - (nat %shares) - (timestamp %deadline) - (option %receiver address))) - (or (pair %divest_imbalanced - (nat %pool_id) - (map %amounts_out nat nat) - (nat %max_shares) - (timestamp %deadline) - (option %receiver address) - (option %referral address)) - (pair %divest_one_coin - (nat %pool_id) - (nat %shares) - (nat %token_index) + (nat %idx_from) + (nat %idx_to) + (nat %amount) (nat %min_amount_out) (timestamp %deadline) (option %receiver address) (option %referral address)))) - (or (or (pair %invest - (nat %pool_id) - (nat %shares) - (map %in_amounts nat nat) - (timestamp %deadline) - (option %receiver address) - (option %referral address)) - (or %stake - (pair %add (nat %pool_id) (nat %amount)) - (pair %remove (nat %pool_id) (nat %amount)))) - (pair %swap - (nat %pool_id) - (nat %idx_from) - (nat %idx_to) - (nat %amount) - (nat %min_amount_out) - (timestamp %deadline) - (option %receiver address) - (option %referral address)))) - (or %use_token - (or (or (pair %balance_of - (list %requests (pair (address %owner) (nat %token_id))) - (contract %callback - (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))))) - (pair %total_supply (nat %token_id) (contract %receiver nat))) - (or (list %transfer - (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) - (pair %update_metadata (nat %token_id) (map %token_info string bytes)))) - (list %update_operators - (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) - (pair %remove_operator (address %owner) (address %operator) (nat %token_id))))))) ; + (or %use_token + (or (or (pair %balance_of + (list %requests (pair (address %owner) (nat %token_id))) + (contract %callback + (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))))) + (pair %total_supply (nat %token_id) (contract %receiver nat))) + (or (list %transfer + (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) + (pair %update_metadata (nat %token_id) (map %token_info string bytes)))) + (list %update_operators + (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) + (pair %remove_operator (address %owner) (address %operator) (nat %token_id)))))))) ; storage (pair (pair %storage (address %admin) @@ -87,6 +104,16 @@ 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)))) (pair %staker_accumulator (map %accumulator_f nat nat) (map %total_fees nat nat) @@ -111,31 +138,32 @@ (big_map %metadata string bytes) (big_map %admin_lambdas nat bytes) (big_map %dex_lambdas nat bytes) - (big_map %token_lambdas nat bytes)) ; + (big_map %token_lambdas nat bytes) + (big_map %strat_lambdas nat bytes)) ; code { PUSH string "not-contract-admin" ; PUSH string "not-started" ; PUSH string "function-not-set" ; PUSH string "cant-unpack-use-lambda" ; DIG 4 ; UNPAIR ; - DUP ; + SWAP ; + DUP 2 ; IF_LEFT { IF_LEFT - { DIG 2 ; + { SWAP ; DUP ; - DUG 2 ; CAR ; GET 29 ; SENDER ; COMPARE ; EQ ; IF {} { PUSH string "failed assertion" ; FAILWITH } ; + SWAP ; IF_LEFT { UPDATE 7 } { DROP ; DUP ; - DUP ; - DUG 2 ; + DUP 2 ; CAR ; DIG 2 ; CAR ; @@ -143,17 +171,16 @@ NOT ; UPDATE 30 ; UPDATE 1 } } - { DROP ; SWAP } } - { DROP ; SWAP } ; + { DROP } } + { IF_LEFT { DROP } { DROP } } ; SWAP ; IF_LEFT { IF_LEFT - { DIG 2 ; DIG 3 ; DIG 4 ; DIG 5 ; DROP 5 ; NIL operation ; PAIR } - { DIG 4 ; - DUP 3 ; + { DIG 2 ; DIG 3 ; DIG 4 ; DIG 5 ; DROP 5 ; NIL operation } + { DUP 2 ; CAR ; GET 30 ; - IF { DROP } { FAILWITH } ; + IF { DIG 4 ; DROP } { DIG 4 ; FAILWITH } ; DUP ; IF_LEFT { IF_LEFT @@ -166,8 +193,8 @@ SENDER ; COMPARE ; EQ ; - IF { DROP ; UNIT } { FAILWITH } } - { DIG 5 ; DROP 2 ; UNIT } } + IF { DROP } { FAILWITH } } + { DIG 5 ; DROP 2 } } { IF_LEFT { DROP ; DIG 4 ; @@ -177,7 +204,7 @@ SENDER ; COMPARE ; EQ ; - IF { DROP ; UNIT } { FAILWITH } } + IF { DROP } { FAILWITH } } { DROP ; DIG 4 ; DUP 3 ; @@ -186,7 +213,7 @@ SENDER ; COMPARE ; EQ ; - IF { DROP ; UNIT } { FAILWITH } } } } + IF { DROP } { FAILWITH } } } } { IF_LEFT { IF_LEFT { DROP ; @@ -197,7 +224,7 @@ SENDER ; COMPARE ; EQ ; - IF { DROP ; UNIT } { FAILWITH } } + IF { DROP } { FAILWITH } } { DROP ; DIG 4 ; DUP 3 ; @@ -206,7 +233,7 @@ SENDER ; COMPARE ; EQ ; - IF { DROP ; UNIT } { FAILWITH } } } + IF { DROP } { FAILWITH } } } { DROP ; DIG 4 ; DUP 3 ; @@ -215,12 +242,10 @@ SENDER ; COMPARE ; EQ ; - IF { DROP ; UNIT } { FAILWITH } } } ; - DROP ; - DIG 3 ; - DUP 3 ; + IF { DROP } { FAILWITH } } } ; + DUP 2 ; GET 5 ; - DUP 3 ; + DUP 2 ; IF_LEFT { IF_LEFT { IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 2 } } @@ -229,7 +254,7 @@ { IF_LEFT { DROP ; PUSH nat 6 } { DROP ; PUSH nat 5 } } { DROP ; PUSH nat 4 } } ; GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; + IF_NONE { DIG 3 ; FAILWITH } { DIG 4 ; DROP } ; DIG 3 ; SWAP ; UNPACK @@ -243,85 +268,105 @@ (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))) - (pair (address %admin) - (address %default_referral) - (set %managers address) - (nat %pools_count) - (big_map %tokens - nat - (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) - (big_map %pool_to_id bytes nat) - (big_map %pools - nat - (pair (nat %initial_A_f) - (timestamp %initial_A_time) - (nat %future_A_f) - (timestamp %future_A_time) - (map %tokens_info - nat - (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) - (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %staker_accumulator - (map %accumulator_f nat nat) - (map %total_fees nat nat) - (nat %total_staked)) - (nat %total_supply))) - (big_map %ledger (pair address nat) nat) - (big_map %allowances (pair address nat) (set address)) - (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) - (big_map %dev_rewards - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - nat) - (big_map %referral_rewards - (pair address - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - nat) - (big_map %stakers_balance - (pair address nat) - (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) - (pair %quipu_token (address %token_address) (nat %token_id)) - (address %factory_address) - (bool %started))) + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started)) (pair (list operation) - (pair (address %admin) - (address %default_referral) - (set %managers address) - (nat %pools_count) - (big_map %tokens - nat - (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) - (big_map %pool_to_id bytes nat) - (big_map %pools - nat - (pair (nat %initial_A_f) - (timestamp %initial_A_time) - (nat %future_A_f) - (timestamp %future_A_time) - (map %tokens_info - nat - (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) - (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %staker_accumulator - (map %accumulator_f nat nat) - (map %total_fees nat nat) - (nat %total_staked)) - (nat %total_supply))) - (big_map %ledger (pair address nat) nat) - (big_map %allowances (pair address nat) (set address)) - (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) - (big_map %dev_rewards - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - nat) - (big_map %referral_rewards - (pair address - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - nat) - (big_map %stakers_balance - (pair address nat) - (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) - (pair %quipu_token (address %token_address) (nat %token_id)) - (address %factory_address) - (bool %started)))) ; + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started))) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; DUP 3 ; CAR ; @@ -331,461 +376,804 @@ UNPAIR ; DUG 2 ; UPDATE 1 ; - SWAP ; - PAIR } } + SWAP } ; + PAIR } { DIG 5 ; DROP ; IF_LEFT { DIG 4 ; + DROP ; + PUSH string "no-address" ; DUP 3 ; CAR ; - GET 30 ; + GET 29 ; + UNIT ; + VIEW "dev_address" address ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH string "not-developer" ; + SWAP ; + SENDER ; + COMPARE ; + EQ ; IF { DROP } { FAILWITH } ; - DIG 3 ; - DUP 3 ; - GET 7 ; - DUP 3 ; + DUP 2 ; + GET 10 ; + DUP 2 ; IF_LEFT { IF_LEFT - { IF_LEFT { DROP ; PUSH nat 5 } { DROP ; PUSH nat 2 } } - { IF_LEFT { DROP ; PUSH nat 3 } { DROP ; PUSH nat 4 } } } - { IF_LEFT - { IF_LEFT { DROP ; PUSH nat 1 } { DROP ; PUSH nat 6 } } - { DROP ; PUSH nat 0 } } ; + { IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 1 } } + { IF_LEFT { DROP ; PUSH nat 4 } { DROP ; PUSH nat 2 } } } + { DROP ; PUSH nat 3 } ; GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; + IF_NONE { DIG 3 ; FAILWITH } { DIG 4 ; DROP } ; DIG 3 ; SWAP ; UNPACK (lambda - (pair (or (or (or (pair %claim_referral - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - (nat %amount)) - (pair %divest - (nat %pool_id) - (map %min_amounts_out nat nat) - (nat %shares) - (timestamp %deadline) - (option %receiver address))) - (or (pair %divest_imbalanced - (nat %pool_id) - (map %amounts_out nat nat) - (nat %max_shares) - (timestamp %deadline) - (option %receiver address) - (option %referral address)) - (pair %divest_one_coin + (pair (or (or (or (pair %connect_strategy (nat %pool_id) (option %strategy_contract address)) + (pair %connect_token_strategy (nat %pool_id) - (nat %shares) - (nat %token_index) - (nat %min_amount_out) - (timestamp %deadline) - (option %receiver address) - (option %referral address)))) - (or (or (pair %invest + (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 %shares) - (map %in_amounts nat nat) - (timestamp %deadline) - (option %receiver address) - (option %referral address)) - (or %stake - (pair %add (nat %pool_id) (nat %amount)) - (pair %remove (nat %pool_id) (nat %amount)))) - (pair %swap - (nat %pool_id) - (nat %idx_from) - (nat %idx_to) - (nat %amount) - (nat %min_amount_out) - (timestamp %deadline) - (option %receiver address) - (option %referral address)))) - (pair (address %admin) - (address %default_referral) - (set %managers address) - (nat %pools_count) - (big_map %tokens - nat - (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) - (big_map %pool_to_id bytes nat) - (big_map %pools - nat - (pair (nat %initial_A_f) - (timestamp %initial_A_time) - (nat %future_A_f) - (timestamp %future_A_time) - (map %tokens_info - nat - (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) - (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %staker_accumulator - (map %accumulator_f nat nat) - (map %total_fees nat nat) - (nat %total_staked)) - (nat %total_supply))) - (big_map %ledger (pair address nat) nat) - (big_map %allowances (pair address nat) (set address)) - (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) - (big_map %dev_rewards - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - nat) - (big_map %referral_rewards - (pair address - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - nat) - (big_map %stakers_balance - (pair address nat) - (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) - (pair %quipu_token (address %token_address) (nat %token_id)) - (address %factory_address) - (bool %started))) + (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))) + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started)) (pair (list operation) - (pair (address %admin) - (address %default_referral) - (set %managers address) - (nat %pools_count) - (big_map %tokens - nat - (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) - (big_map %pool_to_id bytes nat) - (big_map %pools - nat - (pair (nat %initial_A_f) - (timestamp %initial_A_time) - (nat %future_A_f) - (timestamp %future_A_time) - (map %tokens_info - nat - (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) - (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %staker_accumulator - (map %accumulator_f nat nat) - (map %total_fees nat nat) - (nat %total_staked)) - (nat %total_supply))) - (big_map %ledger (pair address nat) nat) - (big_map %allowances (pair address nat) (set address)) - (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) - (big_map %dev_rewards - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - nat) - (big_map %referral_rewards - (pair address - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - nat) - (big_map %stakers_balance - (pair address nat) - (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) - (pair %quipu_token (address %token_address) (nat %token_id)) - (address %factory_address) - (bool %started)))) ; + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started))) ; IF_NONE { FAILWITH } { SWAP ; DROP } ; DUP 3 ; CAR ; DIG 2 ; PAIR ; EXEC ; - DUP ; + UNPAIR ; DUG 2 ; - CDR ; UPDATE 1 ; SWAP ; - CAR ; PAIR } - { DIG 4 ; - DUP 3 ; - CAR ; - GET 30 ; - IF { DROP } { FAILWITH } ; - DIG 3 ; - DUP 3 ; - GET 8 ; - DUP 3 ; - IF_LEFT - { IF_LEFT - { IF_LEFT { DROP ; PUSH nat 1 } { DROP ; PUSH nat 4 } } - { IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 3 } } } - { DROP ; PUSH nat 2 } ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 3 ; - SWAP ; - UNPACK - (lambda - (pair (or (or (or (pair %balance_of - (list %requests (pair (address %owner) (nat %token_id))) - (contract %callback - (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))))) - (pair %total_supply (nat %token_id) (contract %receiver nat))) - (or (list %transfer - (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) - (pair %update_metadata (nat %token_id) (map %token_info string bytes)))) - (list %update_operators - (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) - (pair %remove_operator (address %owner) (address %operator) (nat %token_id))))) - (pair (pair %storage - (address %admin) - (address %default_referral) - (set %managers address) - (nat %pools_count) - (big_map %tokens - nat - (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) - (big_map %pool_to_id bytes nat) - (big_map %pools - nat - (pair (nat %initial_A_f) - (timestamp %initial_A_time) - (nat %future_A_f) - (timestamp %future_A_time) - (map %tokens_info - nat - (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) - (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %staker_accumulator - (map %accumulator_f nat nat) - (map %total_fees nat nat) - (nat %total_staked)) - (nat %total_supply))) - (big_map %ledger (pair address nat) nat) - (big_map %allowances (pair address nat) (set address)) - (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) - (big_map %dev_rewards - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - nat) - (big_map %referral_rewards - (pair address - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - nat) - (big_map %stakers_balance - (pair address nat) - (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) - (pair %quipu_token (address %token_address) (nat %token_id)) - (address %factory_address) - (bool %started)) - (big_map %metadata string bytes) - (big_map %admin_lambdas nat bytes) - (big_map %dex_lambdas nat bytes) - (big_map %token_lambdas nat bytes))) - (pair (list operation) - (pair (pair %storage - (address %admin) - (address %default_referral) - (set %managers address) - (nat %pools_count) - (big_map %tokens - nat - (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) - (big_map %pool_to_id bytes nat) - (big_map %pools - nat - (pair (nat %initial_A_f) - (timestamp %initial_A_time) - (nat %future_A_f) - (timestamp %future_A_time) - (map %tokens_info - nat - (pair (nat %rate_f) (nat %precision_multiplier_f) (nat %reserves))) - (pair %fee (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - (pair %staker_accumulator - (map %accumulator_f nat nat) - (map %total_fees nat nat) - (nat %total_staked)) - (nat %total_supply))) - (big_map %ledger (pair address nat) nat) - (big_map %allowances (pair address nat) (set address)) - (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) - (big_map %dev_rewards - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) - nat) - (big_map %referral_rewards - (pair address - (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - nat) - (big_map %stakers_balance - (pair address nat) - (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) - (pair %quipu_token (address %token_address) (nat %token_id)) - (address %factory_address) - (bool %started)) - (big_map %metadata string bytes) - (big_map %admin_lambdas nat bytes) - (big_map %dex_lambdas nat bytes) - (big_map %token_lambdas nat bytes)))) ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUG 2 ; - PAIR ; - EXEC } } } ; - view "calc_token_amount" - (pair (nat %pool_id) (map %amounts nat nat) (bool %is_deposit)) + { IF_LEFT + { SWAP ; + DIG 4 ; + DUP 2 ; + CAR ; + GET 30 ; + IF { DROP } { FAILWITH } ; + DIG 3 ; + DUP 2 ; + GET 7 ; + DUP 4 ; + IF_LEFT + { IF_LEFT + { IF_LEFT { DROP ; PUSH nat 5 } { DROP ; PUSH nat 2 } } + { IF_LEFT { DROP ; PUSH nat 3 } { DROP ; PUSH nat 4 } } } + { IF_LEFT + { IF_LEFT { DROP ; PUSH nat 1 } { DROP ; PUSH nat 6 } } + { DROP ; PUSH nat 0 } } ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DIG 3 ; + SWAP ; + UNPACK + (lambda + (pair (or (or (or (pair %claim_referral + (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (nat %amount)) + (pair %divest + (nat %pool_id) + (map %min_amounts_out nat nat) + (nat %shares) + (timestamp %deadline) + (option %receiver address))) + (or (pair %divest_imbalanced + (nat %pool_id) + (map %amounts_out nat nat) + (nat %max_shares) + (timestamp %deadline) + (option %receiver address) + (option %referral address)) + (pair %divest_one_coin + (nat %pool_id) + (nat %shares) + (nat %token_index) + (nat %min_amount_out) + (timestamp %deadline) + (option %receiver address) + (option %referral address)))) + (or (or (pair %invest + (nat %pool_id) + (nat %shares) + (map %in_amounts nat nat) + (timestamp %deadline) + (option %receiver address) + (option %referral address)) + (or %stake + (pair %add (nat %pool_id) (nat %amount)) + (pair %remove (nat %pool_id) (nat %amount)))) + (pair %swap + (nat %pool_id) + (nat %idx_from) + (nat %idx_to) + (nat %amount) + (nat %min_amount_out) + (timestamp %deadline) + (option %receiver address) + (option %referral address)))) + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started)) + (pair (list operation) + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 2 ; + CAR ; + DIG 3 ; + PAIR ; + EXEC ; + SWAP ; + DUP 2 ; + CDR ; + UPDATE 1 ; + SWAP ; + CAR ; + PAIR } + { DUP 2 ; + CAR ; + GET 30 ; + IF { DIG 4 ; DROP } { DIG 4 ; FAILWITH } ; + DUP 2 ; + GET 9 ; + DUP 2 ; + IF_LEFT + { IF_LEFT + { IF_LEFT { DROP ; PUSH nat 1 } { DROP ; PUSH nat 4 } } + { IF_LEFT { DROP ; PUSH nat 0 } { DROP ; PUSH nat 3 } } } + { DROP ; PUSH nat 2 } ; + GET ; + IF_NONE { DIG 3 ; FAILWITH } { DIG 4 ; DROP } ; + DIG 3 ; + SWAP ; + UNPACK + (lambda + (pair (or (or (or (pair %balance_of + (list %requests (pair (address %owner) (nat %token_id))) + (contract %callback + (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))))) + (pair %total_supply (nat %token_id) (contract %receiver nat))) + (or (list %transfer + (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) + (pair %update_metadata (nat %token_id) (map %token_info string bytes)))) + (list %update_operators + (or (pair %add_operator (address %owner) (address %operator) (nat %token_id)) + (pair %remove_operator (address %owner) (address %operator) (nat %token_id))))) + (pair %storage + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started)) + (big_map %metadata string bytes) + (big_map %admin_lambdas nat bytes) + (big_map %dex_lambdas nat bytes) + (big_map %token_lambdas nat bytes) + (big_map %strat_lambdas nat bytes)) + (pair (list operation) + (pair %storage + (address %admin) + (address %default_referral) + (set %managers address) + (nat %pools_count) + (big_map %tokens + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (big_map %pool_to_id bytes nat) + (big_map %pools + nat + (pair (nat %initial_A_f) + (timestamp %initial_A_time) + (nat %future_A_f) + (timestamp %future_A_time) + (map %tokens_info + 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)))) + (pair %staker_accumulator + (map %accumulator_f nat nat) + (map %total_fees nat nat) + (nat %total_staked)) + (nat %total_supply))) + (big_map %ledger (pair address nat) nat) + (big_map %allowances (pair address nat) (set address)) + (big_map %token_metadata nat (pair (nat %token_id) (map %token_info string bytes))) + (big_map %dev_rewards + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + nat) + (big_map %referral_rewards + (pair address + (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + nat) + (big_map %stakers_balance + (pair address nat) + (pair (nat %balance) (map %earnings nat (pair (nat %reward_f) (nat %former_f))))) + (pair %quipu_token (address %token_address) (nat %token_id)) + (address %factory_address) + (bool %started)) + (big_map %metadata string bytes) + (big_map %admin_lambdas nat bytes) + (big_map %dex_lambdas nat bytes) + (big_map %token_lambdas nat bytes) + (big_map %strat_lambdas nat bytes))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUG 2 ; + PAIR ; + EXEC } } } } ; + view "get_balance" + (list (pair (address %owner) (nat %token_id))) + (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))) + { UNPAIR ; + MAP { DUP 2 ; + CAR ; + GET 7 ; + DUP 2 ; + CDR ; + COMPARE ; + LT ; + IF {} { PUSH string "FA2_TOKEN_UNDEFINED" ; FAILWITH } ; + DUP 2 ; + CAR ; + GET 15 ; + DUP 2 ; + CDR ; + DUP 3 ; + CAR ; + PAIR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + SWAP ; + PAIR } ; + SWAP ; + DROP } ; + view "get_total_supply" + nat + nat + { UNPAIR ; + SWAP ; + CAR ; + GET 13 ; + SWAP ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + GET 16 } ; + view "get_reserves" + nat + (map nat nat) + { UNPAIR ; + SWAP ; + CAR ; + GET 13 ; + SWAP ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + GET 9 ; + MAP { CDR ; GET 4 } } ; + view "get_token_map" + nat + (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + { UNPAIR ; + SWAP ; + CAR ; + GET 9 ; + SWAP ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} } ; + view "get_tok_per_share" + nat + (map nat nat) + { UNPAIR ; + SWAP ; + CAR ; + GET 13 ; + SWAP ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + DUP ; + GET 9 ; + MAP { CDR ; + DUP 2 ; + GET 16 ; + PUSH nat 1000000000000000000 ; + DIG 2 ; + GET 4 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } ; + SWAP ; + DROP } ; + view "calc_divest_one_coin" + (pair (nat %pool_id) (nat %token_amount) (nat %i)) nat { PUSH nat 100 ; PUSH string "timestamp-error" ; + PUSH string "wrong-index" ; PUSH string "value-not-natural" ; - DIG 2 ; LAMBDA - (pair nat (pair (map nat (pair nat nat nat)) nat)) + (pair (pair string string nat) + (pair (pair (pair nat nat) (map nat nat) nat) + nat + timestamp + nat + timestamp + (map nat (pair nat nat nat)) + (pair nat nat nat) + (pair (option address) (map nat (pair nat nat nat nat bool bool))) + (pair (map nat nat) (map nat nat) nat) + nat)) nat { UNPAIR ; - SWAP ; + UNPAIR 3 ; + DIG 3 ; UNPAIR ; - MAP { CDR ; - PUSH nat 1000000000000000000 ; - SWAP ; - DUP ; - DUG 2 ; - GET 4 ; - DIG 2 ; - CAR ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR } ; - PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; - ITER { CDR ; ADD } ; - SWAP ; - DUP ; - DUG 2 ; + UNPAIR ; + UNPAIR ; + DIG 2 ; + UNPAIR ; + DUP 5 ; + GET 9 ; SIZE ; DUP ; + DUP 6 ; + COMPARE ; + LT ; + IF { DIG 7 ; DROP } { DIG 7 ; FAILWITH } ; + DUP ; DIG 4 ; MUL ; PUSH nat 0 ; - DUP 4 ; + PUSH nat 1 ; + DUP 6 ; + PAIR ; PAIR ; - LEFT (pair nat nat) ; - LOOP_LEFT - { PUSH nat 1 ; - SWAP ; - DUP ; - DUG 2 ; - CDR ; - DUP 3 ; - CAR ; - SUB ; - ABS ; - COMPARE ; - GT ; - IF { PUSH nat 1 ; - SWAP ; - DUP ; - DUG 2 ; - CAR ; - PAIR ; - DUP 6 ; - ITER { SWAP ; - DUP 5 ; - DIG 2 ; - CDR ; - MUL ; - SWAP ; - DUP ; - DUG 2 ; - CDR ; - MUL ; - DUP 3 ; - CAR ; - DIG 2 ; - CAR ; - MUL ; - PAIR } ; - UNPAIR ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - SWAP ; - DUP ; - CAR ; - UPDATE 2 ; - DUP ; - DUP 3 ; - PUSH nat 1 ; - DUP 7 ; - ADD ; - MUL ; - DUP 9 ; - DUP 4 ; - CAR ; - PUSH string "wrong-precision" ; - DUP 12 ; - DUP 9 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - ADD ; - DIG 2 ; - CAR ; - DUP 6 ; - DIG 4 ; - MUL ; - DUP 9 ; - DUP 8 ; - DUP 7 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - ADD ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - UPDATE 1 ; - LEFT (pair nat nat) } - { RIGHT (pair nat nat) } } ; - SWAP ; - DIG 2 ; DIG 3 ; - DIG 4 ; - DIG 5 ; - DROP 5 ; - CAR } ; - SWAP ; - APPLY ; - DIG 3 ; - UNPAIR ; - PUSH string "not-launched" ; - DIG 2 ; - CAR ; - GET 13 ; - DUP 3 ; - CAR ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP ; - GET 5 ; - SWAP ; - DUP ; - DUG 2 ; - GET 7 ; - PAIR ; - SWAP ; + ITER { SWAP ; + DUP 6 ; + DUP 3 ; + CAR ; + COMPARE ; + NEQ ; + IF { SWAP ; + CDR ; + DUP 2 ; + DUP 2 ; + DIG 3 ; + CDR ; + ADD ; + SWAP ; + CAR ; + PAIR ; + SWAP ; + DUP 2 ; + CDR ; + DUP 3 ; + CAR ; + CDR ; + DUP 7 ; + DIG 4 ; + CAR ; + CAR ; + MUL ; + PAIR ; + PAIR ; + SWAP ; + DUP 2 ; + CDR ; + DUP 3 ; + CAR ; + DUP 6 ; + DIG 3 ; + MUL ; + DIG 3 ; + CAR ; + CDR ; + MUL ; + SWAP ; + CAR ; + PAIR ; + PAIR } + { SWAP ; DROP } } ; + DIG 2 ; + DIG 4 ; + DROP 2 ; + DUP ; + CAR ; + CDR ; + DUP 2 ; + CAR ; + CAR ; + EDIV ; + IF_NONE + { PUSH string "ediv-error" ; FAILWITH } + { PUSH nat 0 ; + DUP 2 ; + CDR ; + COMPARE ; + GT ; + IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; + DIG 4 ; + GET 9 ; + SIZE ; + DUP 4 ; + MUL ; + DUP 7 ; + DUP 6 ; + DIG 3 ; + MUL ; + MUL ; + EDIV ; + IF_NONE + { PUSH string "ediv-error" ; FAILWITH } + { PUSH nat 0 ; + DUP 2 ; + CDR ; + COMPARE ; + GT ; + IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; + DIG 2 ; + DIG 5 ; + DUP 5 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 2 ; + CDR ; + ADD ; + DUP 3 ; + PUSH nat 0 ; + PAIR ; + PUSH bool True ; + LOOP { PUSH nat 1 ; + DUP 2 ; + CAR ; + DUP 3 ; + CDR ; + SUB ; + ABS ; + COMPARE ; + GT ; + DUP ; + IF { DUP 2 ; + CDR ; + DIG 2 ; + CDR ; + PAIR ; + SWAP ; + DUP 2 ; + DUP 7 ; + DUP 7 ; + DUP 6 ; + DUP 6 ; + CDR ; + PUSH int 2 ; + MUL ; + ADD ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 6 ; + DUP 5 ; + CDR ; + DIG 5 ; + CDR ; + MUL ; + ADD ; + EDIV ; + IF_NONE + { PUSH string "ediv-error" ; FAILWITH } + { PUSH nat 0 ; + DUP 2 ; + CDR ; + COMPARE ; + GT ; + IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; + SWAP ; + CAR ; + PAIR ; + SWAP } + {} } ; + SWAP ; + DIG 2 ; + DIG 3 ; + DIG 4 ; + DROP 4 ; + CDR } ; + DUP 5 ; + DUP 4 ; + DUP 4 ; + PAIR 3 ; + APPLY ; + DIG 5 ; + UNPAIR ; + DUP 2 ; + CAR ; + GET 13 ; + DUP 2 ; + CAR ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; DUP ; - DUG 2 ; CAR ; - DUP 3 ; + DUP 2 ; GET 3 ; - DIG 2 ; - UNPAIR ; - DUP ; + DUP 3 ; + GET 5 ; + DUP 4 ; + GET 7 ; + DUP 2 ; + DUP 2 ; NOW ; COMPARE ; LT ; - IF { DUP 9 ; + IF { DROP ; + DUP 11 ; DUP 4 ; NOW ; SUB ; ISNAT ; IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 9 ; + DIG 11 ; DIG 4 ; DIG 3 ; SUB ; @@ -806,353 +1194,426 @@ COMPARE ; GT ; IF { ADD } { SWAP ; SUB ; ABS } } - { DIG 2 ; DIG 3 ; DIG 8 ; DROP 4 } ; - DUP ; - DUP 3 ; - GET 9 ; - PAIR ; - DUP 5 ; - SWAP ; - EXEC ; - DUP 3 ; - GET 9 ; - MAP { UNPAIR ; - PUSH nat 0 ; - DUP 7 ; - GET 3 ; - DIG 2 ; - GET ; - IF_NONE {} { SWAP ; DROP } ; - DUP 6 ; - GET 4 ; - IF { SWAP ; DUP ; DUG 2 ; GET 4 ; ADD } - { DUP 8 ; - SWAP ; - DUP 3 ; - GET 4 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } } ; - UPDATE 4 } ; - DIG 2 ; + { SWAP ; DIG 2 ; DIG 3 ; DIG 4 ; DIG 11 ; DROP 5 } ; SWAP ; - PAIR ; + PUSH string "no-fee-view" ; DIG 4 ; - SWAP ; - EXEC ; - DIG 3 ; + CAR ; + GET 29 ; + UNIT ; + VIEW "dev_fee" nat ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 4 ; GET 4 ; - IF { DIG 3 ; - DUP 3 ; - DIG 2 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } } - { DIG 3 ; - SWAP ; - DUP 3 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } } ; - SWAP ; - DIG 2 ; - GET 14 ; + PAIR ; + DIG 3 ; + GET 3 ; + DIG 3 ; DIG 2 ; + UNPAIR ; + DUP 5 ; + GET 9 ; + SIZE ; + DUP 6 ; + GET 9 ; + MAP { CDR ; + PUSH nat 1000000000000000000 ; + DUP 2 ; + GET 4 ; + DIG 2 ; + CAR ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } ; + PUSH nat 0 ; + DUP 2 ; + ITER { CDR ; ADD } ; + DUP 2 ; + SIZE ; + DUP ; + DUP 8 ; MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR } ; - view "get_referral_rewards" - (list (pair (address %user) - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) - (list (pair (pair %request - (address %user) - (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - (nat %reward))) - { UNPAIR ; - NIL (pair (pair address (or address (pair address nat))) nat) ; - SWAP ; - NIL (pair address (or address (pair address nat))) ; - SWAP ; - ITER { CONS } ; - ITER { SWAP ; - PUSH nat 0 ; - DUP 4 ; - CAR ; - GET 23 ; - DUP 4 ; + PUSH nat 0 ; + DUP 4 ; + PAIR ; + PUSH bool True ; + LOOP { PUSH nat 1 ; + DUP 2 ; CDR ; - DUP 5 ; + DUP 3 ; CAR ; - PAIR ; - GET ; - IF_NONE {} { SWAP ; DROP } ; - DIG 2 ; - PAIR ; - CONS } ; - SWAP ; - DROP } ; - view "get_staker_info" - (list (pair (address %user) (nat %pool_id))) - (list (pair (pair %request (address %user) (nat %pool_id)) - (pair %info (nat %balance) (map %rewards nat nat)))) - { UNPAIR ; - MAP { PUSH string "not-launched" ; - DUP 3 ; - CAR ; - GET 13 ; - DUP 3 ; - CDR ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - EMPTY_MAP nat (pair nat nat) ; - PUSH nat 0 ; - PAIR ; - DUP 4 ; - CAR ; - GET 25 ; - DUP 4 ; - CDR ; - DUP 5 ; - CAR ; - PAIR ; - GET ; - IF_NONE {} { SWAP ; DROP } ; - DUP ; - CDR ; - MAP { UNPAIR ; - PUSH nat 0 ; + SUB ; + ABS ; + COMPARE ; + GT ; + DUP ; + IF { DUP 2 ; + CAR ; + PUSH nat 1 ; + DUP 4 ; + CAR ; + PAIR ; + DUP 8 ; + LAMBDA + (pair (pair nat nat) (pair (pair nat nat) nat nat)) + (pair nat nat) + { UNPAIR ; + UNPAIR ; + DIG 2 ; + UNPAIR ; + DIG 3 ; + DIG 2 ; + CDR ; + MUL ; + DUP 2 ; + CDR ; + MUL ; + DUG 2 ; + CAR ; + MUL ; + PAIR } ; + DUP 8 ; DUP 5 ; - GET 13 ; + PAIR ; + APPLY ; + DIG 3 ; + DROP ; + DUG 2 ; + ITER { SWAP ; PAIR ; DUP 2 ; SWAP ; EXEC } ; + SWAP ; + DROP ; + UNPAIR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; CAR ; - DIG 2 ; - GET ; - IF_NONE {} { SWAP ; DROP } ; DUP 3 ; + DIG 3 ; CAR ; - MUL ; - PUSH nat 10000000000 ; + UPDATE 2 ; + DUG 2 ; DUP 3 ; - CDR ; - DIG 2 ; + DUP 2 ; + PUSH nat 1 ; + DUP 8 ; + ADD ; + MUL ; + DUP 19 ; + DUP 6 ; + CAR ; + PUSH string "wrong-precision" ; + DUP 22 ; + DUP 10 ; SUB ; - ABS ; - DIG 2 ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; CAR ; ADD ; + DIG 4 ; + CAR ; + DUP 7 ; + DIG 4 ; + MUL ; + DUP 19 ; + DUP 9 ; + DUP 8 ; + MUL ; EDIV ; IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR } ; - DIG 2 ; - DROP ; - SWAP ; - CAR ; - PAIR ; - SWAP ; - PAIR } ; - SWAP ; - DROP } ; - view "get_fees" - nat - (pair (nat %lp_f) (nat %stakers_f) (nat %ref_f)) - { UNPAIR ; - PUSH string "not-launched" ; - DIG 2 ; - CAR ; - GET 13 ; - DIG 2 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - GET 11 } ; - view "view_A" - nat - nat - { PUSH string "timestamp-error" ; + CAR ; + ADD ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + UPDATE 1 ; + SWAP } + {} } ; SWAP ; - UNPAIR ; - PUSH string "not-launched" ; DIG 2 ; + DIG 3 ; + DIG 14 ; + DROP 4 ; CAR ; - GET 13 ; - DIG 2 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH nat 100 ; + DUP 8 ; + GET 16 ; + DUP 11 ; SWAP ; - DUP ; - DUG 2 ; - GET 5 ; - DUP 3 ; - GET 7 ; - PAIR ; DUP 3 ; - CAR ; - DIG 3 ; - GET 3 ; - DIG 2 ; - UNPAIR ; - DUP ; - NOW ; - COMPARE ; - LT ; - IF { DUP 6 ; - DUP 4 ; - NOW ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 6 ; - DIG 4 ; - DIG 3 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 4 ; - DUP 4 ; - SUB ; - ABS ; - SWAP ; - DUG 2 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - DUP 3 ; - DIG 2 ; - COMPARE ; - GT ; - IF { ADD } { SWAP ; SUB ; ABS } } - { DIG 2 ; DIG 3 ; DIG 5 ; DROP 4 } ; + DUP 10 ; + MUL ; EDIV ; IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR } ; - view "get_dy" - (pair (nat %pool_id) (nat %i) (nat %j) (nat %dx)) - nat - { PUSH nat 1000000000000000000 ; - PUSH nat 100 ; - PUSH string "timestamp-error" ; - PUSH string "wrong-index" ; - PUSH string "value-not-natural" ; - PUSH string "ediv-error" ; - DIG 6 ; - UNPAIR ; - PUSH string "not-launched" ; - DUP 3 ; CAR ; - GET 13 ; DUP 3 ; - CAR ; - GET ; + SUB ; + ISNAT ; IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP ; - DUP 3 ; - GET 6 ; + DUP 2 ; + DUP 2 ; + COMPARE ; + LT ; + IF {} { PUSH string "zero-amount-in" ; FAILWITH } ; + DUP 9 ; + DUP 2 ; + DUP 5 ; + PAIR ; + DUP 7 ; + DUP 10 ; + PAIR ; PAIR ; + PAIR ; + DUP 11 ; + SWAP ; + EXEC ; + DUP 10 ; + GET 11 ; + DIG 7 ; + DUP 2 ; + GET 4 ; DUP 3 ; - GET 5 ; - DIG 3 ; GET 3 ; - DIG 2 ; - UNPAIR ; - SWAP ; - DUP ; - DUG 2 ; - GET 9 ; - MAP { CDR ; - DUP 13 ; + DIG 3 ; + CAR ; + ADD ; + ADD ; + ADD ; + DUP 5 ; + MAP { UNPAIR ; + DUP 9 ; SWAP ; - DUP ; - DUG 2 ; - GET 4 ; - DIG 2 ; + COMPARE ; + EQ ; + IF { DUP 13 ; + DUP 4 ; + DUP 7 ; + DUP 7 ; + DUP 5 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } } + { DUP 13 ; + DUP 6 ; + DUP 6 ; + DUP 4 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 3 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } } ; + DUP 14 ; + PUSH nat 10000000000 ; + PUSH string "wrong-tokens-count" ; + PUSH nat 1 ; + DUP 12 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH nat 4 ; + MUL ; + DUP 11 ; + DUP 7 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; CAR ; + DIG 3 ; MUL ; EDIV ; IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR } ; - DUP 10 ; + CAR ; + DIG 2 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } } ; SWAP ; + DIG 4 ; + DIG 6 ; + DROP 3 ; DUP ; - DUG 2 ; DUP 6 ; GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; + IF_NONE { DUP 11 ; FAILWITH } {} ; DUP 11 ; - DUP 3 ; - DUP 8 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 12 ; - DUP 6 ; - GET 9 ; - DUP 8 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 12 ; - DUP 7 ; - GET 9 ; DUP 10 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 16 ; + DIG 5 ; + DIG 4 ; + PAIR ; + DUP 7 ; + DIG 8 ; + PAIR ; + PAIR ; + PAIR ; + DIG 8 ; + SWAP ; + EXEC ; DIG 2 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 6 ; + GET 9 ; + DUP 5 ; + GET ; + IF_NONE { DUP 8 ; FAILWITH } {} ; + PUSH string "low-reserves" ; + DUP 2 ; + GET 4 ; + DUP 4 ; + COMPARE ; + LT ; + IF { DROP } { FAILWITH } ; + GET 3 ; + DIG 3 ; + DIG 4 ; + GET ; + IF_NONE { DIG 6 ; FAILWITH } { DIG 7 ; DROP } ; + DUP 2 ; + DIG 3 ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; CAR ; - DIG 6 ; - MUL ; + DUG 2 ; + SWAP ; + DUP 7 ; + DIG 4 ; + DIG 3 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; EDIV ; IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; CAR ; + PUSH string "low-total-supply" ; DIG 3 ; - ADD ; - DIG 4 ; DIG 4 ; + GET 16 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUG 2 ; + DIG 3 ; + DUP 3 ; DIG 2 ; - PAIR ; - DIG 5 ; - DIG 5 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; DIG 2 ; + SWAP ; + DIG 2 ; + PAIR 3 ; + CAR } ; + view "get_dy" + (pair (nat %pool_id) (nat %i) (nat %j) (nat %dx)) + nat + { PUSH nat 1000000000000000000 ; + PUSH nat 100 ; + PUSH string "timestamp-error" ; + PUSH string "wrong-index" ; + PUSH string "value-not-natural" ; + DIG 5 ; UNPAIR ; - DUP 5 ; + DUP 2 ; + CAR ; + GET 13 ; + DUP 2 ; + CAR ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + DUP 2 ; + GET 5 ; + DUP 3 ; + GET 3 ; + DUP 3 ; GET 9 ; - SIZE ; + MAP { CDR ; + DUP 11 ; + DUP 2 ; + GET 4 ; + DIG 2 ; + CAR ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } ; + DUP ; + DUP 3 ; + GET ; + IF_NONE { DUP 8 ; FAILWITH } {} ; + DUP 2 ; DUP 5 ; + GET ; + IF_NONE { DUP 9 ; FAILWITH } {} ; + DUP 6 ; + GET 9 ; DUP 5 ; + GET ; + IF_NONE { DUP 10 ; FAILWITH } {} ; + DUP 7 ; + GET 9 ; + DUP 7 ; + GET ; + IF_NONE { DIG 10 ; FAILWITH } { DIG 11 ; DROP } ; + DUP 14 ; + DIG 2 ; + CAR ; + DIG 9 ; + GET 6 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 3 ; + ADD ; + DUP 7 ; + GET 9 ; + SIZE ; + DUP 7 ; + DUP 7 ; COMPARE ; NEQ ; IF {} { PUSH string "failed assertion" ; FAILWITH } ; DUP ; - DUP 6 ; + DUP 8 ; COMPARE ; LT ; IF {} { PUSH string "failed assertion" ; FAILWITH } ; DUP ; - DUP 5 ; + DUP 7 ; COMPARE ; LT ; IF {} { PUSH string "failed assertion" ; FAILWITH } ; - DUP 6 ; - GET 5 ; - DUP 7 ; - GET 7 ; - PAIR ; - DUP 7 ; - CAR ; DUP 8 ; + CAR ; + DUP 9 ; GET 3 ; - DIG 2 ; - UNPAIR ; - DUP ; + DUP 10 ; + GET 5 ; + DUP 11 ; + GET 7 ; + DUP 2 ; + DUP 2 ; NOW ; COMPARE ; LT ; - IF { DUP 17 ; + IF { DROP ; + DUP 15 ; DUP 4 ; NOW ; SUB ; ISNAT ; IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 17 ; + DIG 15 ; DIG 4 ; DIG 3 ; SUB ; @@ -1173,24 +1634,14 @@ COMPARE ; GT ; IF { ADD } { SWAP ; SUB ; ABS } } - { DIG 2 ; DIG 3 ; DIG 16 ; DROP 4 } ; - SWAP ; - DUP ; - DUG 2 ; - SWAP ; - DUP ; - DUG 2 ; + { SWAP ; DIG 2 ; DIG 3 ; DIG 4 ; DIG 15 ; DROP 5 } ; + DUP 2 ; + DUP 2 ; MUL ; - SWAP ; - DUP 5 ; PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; + DUP 8 ; ITER { CDR ; ADD } ; - SWAP ; - DUP ; - DUG 2 ; + DUP 8 ; SIZE ; DUP ; DIG 4 ; @@ -1198,278 +1649,268 @@ PUSH nat 0 ; DUP 4 ; PAIR ; - LEFT (pair nat nat) ; - LOOP_LEFT - { PUSH nat 1 ; - SWAP ; - DUP ; - DUG 2 ; - CDR ; - DUP 3 ; - CAR ; - SUB ; - ABS ; - COMPARE ; - GT ; - IF { PUSH nat 1 ; - SWAP ; - DUP ; - DUG 2 ; - CAR ; - PAIR ; - DUP 6 ; - ITER { SWAP ; - DUP 5 ; + PUSH bool True ; + LOOP { PUSH nat 1 ; + DUP 2 ; + CDR ; + DUP 3 ; + CAR ; + SUB ; + ABS ; + COMPARE ; + GT ; + DUP ; + IF { DUP 2 ; + CAR ; + PUSH nat 1 ; + DUP 4 ; + CAR ; + PAIR ; + DUP 13 ; + LAMBDA + (pair (pair nat nat) (pair (pair nat nat) nat nat)) + (pair nat nat) + { UNPAIR ; + UNPAIR ; + DIG 2 ; + UNPAIR ; + DIG 3 ; DIG 2 ; CDR ; MUL ; - SWAP ; - DUP ; - DUG 2 ; + DUP 2 ; CDR ; MUL ; - DUP 3 ; - CAR ; - DIG 2 ; + DUG 2 ; CAR ; MUL ; PAIR } ; - UNPAIR ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - SWAP ; - DUP ; - CAR ; - UPDATE 2 ; - DUP ; - DUP 3 ; - PUSH nat 1 ; - DUP 7 ; - ADD ; - MUL ; - DUP 22 ; - DUP 4 ; - CAR ; - PUSH string "wrong-precision" ; - DUP 25 ; - DUP 9 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - ADD ; - DIG 2 ; - CAR ; - DUP 6 ; - DIG 4 ; - MUL ; - DUP 22 ; - DUP 8 ; - DUP 7 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - ADD ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - UPDATE 1 ; - LEFT (pair nat nat) } - { RIGHT (pair nat nat) } } ; + DUP 8 ; + DUP 5 ; + PAIR ; + APPLY ; + DIG 3 ; + DROP ; + DUG 2 ; + ITER { SWAP ; PAIR ; DUP 2 ; SWAP ; EXEC } ; + SWAP ; + DROP ; + UNPAIR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 3 ; + DIG 3 ; + CAR ; + UPDATE 2 ; + DUG 2 ; + DUP 3 ; + DUP 2 ; + PUSH nat 1 ; + DUP 8 ; + ADD ; + MUL ; + DUP 20 ; + DUP 6 ; + CAR ; + PUSH string "wrong-precision" ; + DUP 23 ; + DUP 10 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + ADD ; + DIG 4 ; + CAR ; + DUP 7 ; + DIG 4 ; + MUL ; + DUP 20 ; + DUP 9 ; + DUP 8 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + ADD ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + UPDATE 1 ; + SWAP } + {} } ; SWAP ; DIG 2 ; DIG 3 ; - DIG 4 ; - DROP 4 ; + DROP 3 ; CAR ; PUSH nat 0 ; PUSH nat 1 ; DUP 3 ; PAIR ; PAIR ; - DIG 5 ; - ITER { DUP ; - DUG 2 ; + DIG 7 ; + ITER { SWAP ; + DUP 2 ; CAR ; - DUP 9 ; - SWAP ; - DUP ; - DUG 2 ; + DUP 11 ; + DUP 2 ; COMPARE ; NEQ ; - IF { DUP 8 ; + IF { DUP 10 ; SWAP ; COMPARE ; EQ ; IF { SWAP ; DROP ; DUP 5 } { SWAP ; CDR } ; - DUP ; - DUP 3 ; + DUP 2 ; + DUP 2 ; + DIG 3 ; CDR ; ADD ; - DIG 2 ; + SWAP ; CAR ; PAIR ; - DUP ; - CDR ; SWAP ; - DUP ; - DUG 2 ; + DUP 2 ; + CDR ; + DUP 3 ; CAR ; CDR ; DUP 5 ; - DIG 3 ; + DIG 4 ; CAR ; CAR ; MUL ; PAIR ; PAIR ; - DUP ; + SWAP ; + DUP 2 ; CDR ; - DUP 6 ; - DUP 4 ; - MUL ; DUP 3 ; CAR ; - CDR ; + DUP 7 ; + DIG 3 ; MUL ; - DIG 2 ; + DIG 3 ; CAR ; + CDR ; + MUL ; + SWAP ; CAR ; PAIR ; - PAIR ; - SWAP ; PAIR } - { DIG 2 ; DROP 2 ; PUSH nat 0 ; PAIR } ; - CDR } ; + { DIG 2 ; DROP 2 } } ; DIG 3 ; DIG 4 ; - DIG 5 ; - DIG 6 ; + DIG 7 ; + DIG 8 ; DROP 4 ; DUP ; CAR ; CDR ; - SWAP ; - DUP ; - DUG 2 ; + DUP 2 ; CAR ; CAR ; EDIV ; IF_NONE - { DUP 9 ; FAILWITH } + { PUSH string "ediv-error" ; FAILWITH } { PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; + DUP 2 ; CDR ; COMPARE ; GT ; IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; - DIG 4 ; - DIG 3 ; - DIG 3 ; - CDR ; - PAIR ; - DIG 3 ; - DIG 3 ; - DIG 2 ; - UNPAIR ; - DIG 4 ; + DUP 7 ; GET 9 ; SIZE ; DUP 5 ; MUL ; - DUP 12 ; - DUP 4 ; - DIG 5 ; + DUP 11 ; + DUP 5 ; + DIG 3 ; MUL ; MUL ; EDIV ; IF_NONE - { DUP 8 ; FAILWITH } + { PUSH string "ediv-error" ; FAILWITH } { PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; + DUP 2 ; CDR ; COMPARE ; GT ; IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; DIG 3 ; - DIG 10 ; + DIG 9 ; DUP 5 ; MUL ; EDIV ; IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; CAR ; DIG 2 ; + CDR ; ADD ; DUP 3 ; PUSH nat 0 ; PAIR ; - LEFT (pair nat nat) ; - LOOP_LEFT - { PUSH nat 1 ; - SWAP ; - DUP ; - DUG 2 ; - CAR ; - DUP 3 ; - CDR ; - SUB ; - ABS ; - COMPARE ; - GT ; - IF { DUP ; - CDR ; - SWAP ; - CDR ; - PAIR ; - DUP 10 ; - DUP 5 ; - DUP 4 ; - DUP 4 ; - CDR ; - PUSH int 2 ; - MUL ; - ADD ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 4 ; - DUP 3 ; - CDR ; - DUP 4 ; - CDR ; - MUL ; - ADD ; - EDIV ; - IF_NONE - { DUP 9 ; FAILWITH } - { PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; - CDR ; - COMPARE ; - GT ; - IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; - SWAP ; - CAR ; - PAIR ; - LEFT (pair nat nat) } - { RIGHT (pair nat nat) } } ; + PUSH bool True ; + LOOP { PUSH nat 1 ; + DUP 2 ; + CAR ; + DUP 3 ; + CDR ; + SUB ; + ABS ; + COMPARE ; + GT ; + DUP ; + IF { DUP 2 ; + CDR ; + DIG 2 ; + CDR ; + PAIR ; + SWAP ; + DUP 2 ; + DUP 11 ; + DUP 7 ; + DUP 6 ; + DUP 6 ; + CDR ; + PUSH int 2 ; + MUL ; + ADD ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 6 ; + DUP 5 ; + CDR ; + DIG 5 ; + CDR ; + MUL ; + ADD ; + EDIV ; + IF_NONE + { PUSH string "ediv-error" ; FAILWITH } + { PUSH nat 0 ; + DUP 2 ; + CDR ; + COMPARE ; + GT ; + IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; + SWAP ; + CAR ; + PAIR ; + SWAP } + {} } ; SWAP ; DIG 2 ; DIG 3 ; - DIG 8 ; - DROP 4 ; + DROP 3 ; CDR ; DIG 5 ; SWAP ; @@ -1477,9 +1918,7 @@ SUB ; ISNAT ; IF_NONE { FAILWITH } { SWAP ; DROP } ; - SWAP ; - DUP ; - DUG 2 ; + DUP 2 ; CAR ; DIG 5 ; DIG 2 ; @@ -1495,9 +1934,7 @@ LT ; IF { DROP } { FAILWITH } ; PUSH nat 10000000000 ; - SWAP ; - DUP ; - DUG 2 ; + DUP 2 ; PUSH string "no-fee-view" ; DIG 5 ; CAR ; @@ -1507,8 +1944,8 @@ IF_NONE { FAILWITH } { SWAP ; DROP } ; DIG 4 ; GET 11 ; - DUP ; - DUG 2 ; + SWAP ; + DUP 2 ; GET 4 ; DUP 3 ; GET 3 ; @@ -1527,267 +1964,40 @@ SUB ; ISNAT ; IF_NONE { FAILWITH } { SWAP ; DROP } } ; - view "calc_divest_one_coin" - (pair (nat %pool_id) (nat %token_amount) (nat %i)) + view "view_A" nat - { PUSH nat 100 ; - PUSH string "timestamp-error" ; - PUSH string "wrong-index" ; - PUSH string "value-not-natural" ; - PUSH string "ediv-error" ; - DUP 5 ; - DUP 4 ; - DUP 4 ; - DIG 3 ; - PAIR 4 ; - LAMBDA - (pair (pair string (pair string (pair string nat))) - (pair (pair (pair nat nat) (pair (map nat nat) nat)) - (pair nat - timestamp - nat - timestamp - (map nat (pair nat nat nat)) - (pair nat nat nat) - (pair (map nat nat) (map nat nat) nat) - nat))) - nat - { UNPAIR ; - UNPAIR 4 ; - DIG 4 ; - UNPAIR ; - UNPAIR ; - UNPAIR ; - DIG 2 ; - UNPAIR ; - DUP 5 ; - GET 9 ; - SIZE ; - DIG 8 ; - SWAP ; - DUP ; - DUG 2 ; - DUP 7 ; - COMPARE ; - LT ; - IF { DROP } { FAILWITH } ; - DUP ; - DIG 4 ; - MUL ; - PUSH nat 0 ; - PUSH nat 1 ; - DUP 6 ; - PAIR ; - PAIR ; - DIG 3 ; - ITER { SWAP ; - DUP 6 ; - DUP 3 ; - CAR ; - COMPARE ; - NEQ ; - IF { SWAP ; - CDR ; - DUP ; - DUP 3 ; - CDR ; - ADD ; - DIG 2 ; - CAR ; - PAIR ; - DUP ; - CDR ; - SWAP ; - DUP ; - DUG 2 ; - CAR ; - CDR ; - DUP 7 ; - DIG 3 ; - CAR ; - CAR ; - MUL ; - PAIR ; - PAIR ; - DUP ; - CDR ; - DUP 5 ; - DUP 4 ; - MUL ; - DUP 3 ; - CAR ; - CDR ; - MUL ; - DIG 2 ; - CAR ; - CAR ; - PAIR ; - PAIR ; - SWAP ; - PAIR } - { SWAP ; DROP ; PUSH nat 0 ; PAIR } ; - CDR } ; - DIG 2 ; - DIG 4 ; - DROP 2 ; - DUP ; - CAR ; - CDR ; - SWAP ; - DUP ; - DUG 2 ; - CAR ; - CAR ; - EDIV ; - IF_NONE - { DUP 5 ; FAILWITH } - { PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; - CDR ; - COMPARE ; - GT ; - IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; - DIG 4 ; - DIG 4 ; - DIG 3 ; - CDR ; - PAIR ; - DIG 3 ; - DIG 3 ; - DIG 2 ; - UNPAIR ; - DIG 4 ; - GET 9 ; - SIZE ; - DUP 5 ; - MUL ; - DUP 8 ; - DUP 4 ; - DIG 5 ; - MUL ; - MUL ; - EDIV ; - IF_NONE - { DUP 4 ; FAILWITH } - { PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; - CDR ; - COMPARE ; - GT ; - IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; - DIG 3 ; - DIG 6 ; - DUP 5 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - DIG 2 ; - ADD ; - DUP 3 ; - PUSH nat 0 ; - PAIR ; - LEFT (pair nat nat) ; - LOOP_LEFT - { PUSH nat 1 ; - SWAP ; - DUP ; - DUG 2 ; - CAR ; - DUP 3 ; - CDR ; - SUB ; - ABS ; - COMPARE ; - GT ; - IF { DUP ; - CDR ; - SWAP ; - CDR ; - PAIR ; - DUP 6 ; - DUP 5 ; - DUP 4 ; - DUP 4 ; - CDR ; - PUSH int 2 ; - MUL ; - ADD ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 4 ; - DUP 3 ; - CDR ; - DUP 4 ; - CDR ; - MUL ; - ADD ; - EDIV ; - IF_NONE - { DUP 5 ; FAILWITH } - { PUSH nat 0 ; - SWAP ; - DUP ; - DUG 2 ; - CDR ; - COMPARE ; - GT ; - IF { PUSH nat 1 ; SWAP ; CAR ; ADD } { CAR } } ; - SWAP ; - CAR ; - PAIR ; - LEFT (pair nat nat) } - { RIGHT (pair nat nat) } } ; - SWAP ; - DIG 2 ; - DIG 3 ; - DIG 4 ; - DIG 5 ; - DROP 5 ; - CDR } ; + nat + { PUSH string "timestamp-error" ; SWAP ; - APPLY ; - DIG 5 ; UNPAIR ; - PUSH string "not-launched" ; - DUP 3 ; + SWAP ; CAR ; GET 13 ; - DUP 3 ; - CAR ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP ; - GET 5 ; - SWAP ; - DUP ; - DUG 2 ; - GET 7 ; - PAIR ; SWAP ; - DUP ; - DUG 2 ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + PUSH nat 100 ; + DUP 2 ; CAR ; DUP 3 ; GET 3 ; - DIG 2 ; - UNPAIR ; - DUP ; + DUP 4 ; + GET 5 ; + DIG 4 ; + GET 7 ; + DUP 2 ; + DUP 2 ; NOW ; COMPARE ; LT ; - IF { DUP 11 ; + IF { DROP ; + DUP 6 ; DUP 4 ; NOW ; SUB ; ISNAT ; IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 11 ; + DIG 6 ; DIG 4 ; DIG 3 ; SUB ; @@ -1808,421 +2018,346 @@ COMPARE ; GT ; IF { ADD } { SWAP ; SUB ; ABS } } - { DIG 2 ; DIG 3 ; DIG 10 ; DROP 4 } ; + { SWAP ; DIG 2 ; DIG 3 ; DIG 4 ; DIG 6 ; DROP 5 } ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } ; + view "get_fees" + nat + (pair (nat %lp_f) (nat %stakers_f) (nat %ref_f)) + { UNPAIR ; SWAP ; - PUSH string "no-fee-view" ; - DIG 4 ; CAR ; - GET 29 ; - UNIT ; - VIEW "dev_fee" nat ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 4 ; - GET 4 ; - PAIR ; - DIG 3 ; - GET 3 ; - DIG 3 ; - DIG 2 ; - UNPAIR ; - DUP 5 ; - GET 9 ; - MAP { CDR ; - PUSH nat 1000000000000000000 ; + GET 13 ; + SWAP ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + GET 11 } ; + view "get_staker_info" + (list (pair (address %user) (nat %pool_id))) + (list (pair (pair %request (address %user) (nat %pool_id)) + (pair %info (nat %balance) (map %rewards nat nat)))) + { UNPAIR ; + MAP { DUP 2 ; + CAR ; + GET 13 ; + DUP 2 ; + CDR ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + DUP 3 ; + CAR ; + GET 25 ; + DUP 3 ; + CDR ; + DUP 4 ; + CAR ; + PAIR ; + GET ; + IF_NONE { EMPTY_MAP nat (pair nat nat) ; PUSH nat 0 ; PAIR } {} ; SWAP ; - DUP ; - DUG 2 ; - GET 4 ; - DIG 2 ; + GET 15 ; CAR ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR } ; - DUP 4 ; + MAP { UNPAIR ; + DUP 3 ; + CDR ; + SWAP ; + GET ; + IF_NONE { PUSH nat 0 ; PUSH nat 0 ; PAIR } {} ; + SWAP ; + DUP 3 ; + CAR ; + MUL ; + PUSH nat 10000000000 ; + DUP 3 ; + CDR ; + DIG 2 ; + SUB ; + ABS ; + DIG 2 ; + CAR ; + ADD ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } ; + SWAP ; + CAR ; + PAIR ; + SWAP ; + PAIR } ; SWAP ; - DUP ; - DUG 2 ; - PUSH nat 0 ; + DROP } ; + view "get_referral_rewards" + (list (pair (address %user) + (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))))) + (list (pair (pair %request + (address %user) + (or %token (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) + (nat %reward))) + { UNPAIR ; + NIL (pair (pair address (or address (pair address nat))) nat) ; SWAP ; - DUP ; - DUG 2 ; - ITER { CDR ; ADD } ; + NIL (pair address (or address (pair address nat))) ; SWAP ; - DUP ; - DUG 2 ; - SIZE ; - DUP ; - DIG 4 ; - MUL ; - PUSH nat 0 ; - DUP 4 ; - PAIR ; - LEFT (pair nat nat) ; - LOOP_LEFT - { PUSH nat 1 ; + ITER { CONS } ; + ITER { SWAP ; + DUP 3 ; + CAR ; + GET 23 ; + DUP 3 ; + CDR ; + DUP 4 ; + CAR ; + PAIR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + DIG 2 ; + PAIR ; + CONS } ; + SWAP ; + DROP } ; + view "calc_token_amount" + (pair (nat %pool_id) (map %amounts nat nat) (bool %is_deposit)) + nat + { PUSH nat 100 ; + PUSH string "timestamp-error" ; + PUSH string "value-not-natural" ; + LAMBDA + (pair nat (pair (map nat (pair nat nat nat)) nat)) + nat + { UNPAIR ; SWAP ; + UNPAIR ; + MAP { CDR ; + PUSH nat 1000000000000000000 ; + DUP 2 ; + GET 4 ; + DIG 2 ; + CAR ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } ; + PUSH nat 0 ; + DUP 2 ; + ITER { CDR ; ADD } ; + DUP 2 ; + SIZE ; DUP ; - DUG 2 ; - CDR ; - DUP 3 ; - CAR ; - SUB ; - ABS ; - COMPARE ; - GT ; - IF { PUSH nat 1 ; - SWAP ; - DUP ; - DUG 2 ; - CAR ; - PAIR ; - DUP 6 ; - ITER { SWAP ; + DIG 4 ; + MUL ; + PUSH nat 0 ; + DUP 4 ; + PAIR ; + PUSH bool True ; + LOOP { PUSH nat 1 ; + DUP 2 ; + CDR ; + DUP 3 ; + CAR ; + SUB ; + ABS ; + COMPARE ; + GT ; + DUP ; + IF { DUP 2 ; + CAR ; + PUSH nat 1 ; + DUP 4 ; + CAR ; + PAIR ; + DUP 8 ; + LAMBDA + (pair (pair nat nat) (pair (pair nat nat) nat nat)) + (pair nat nat) + { UNPAIR ; + UNPAIR ; + DIG 2 ; + UNPAIR ; + DIG 3 ; + DIG 2 ; + CDR ; + MUL ; + DUP 2 ; + CDR ; + MUL ; + DUG 2 ; + CAR ; + MUL ; + PAIR } ; + DUP 8 ; DUP 5 ; - DIG 2 ; - CDR ; - MUL ; + PAIR ; + APPLY ; + DIG 3 ; + DROP ; + DUG 2 ; + ITER { SWAP ; PAIR ; DUP 2 ; SWAP ; EXEC } ; SWAP ; - DUP ; + DROP ; + UNPAIR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 3 ; + DIG 3 ; + CAR ; + UPDATE 2 ; DUG 2 ; - CDR ; - MUL ; DUP 3 ; + DUP 2 ; + PUSH nat 1 ; + DUP 8 ; + ADD ; + MUL ; + DUP 10 ; + DUP 6 ; CAR ; - DIG 2 ; + PUSH string "wrong-precision" ; + DUP 13 ; + DUP 10 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + ADD ; + DIG 4 ; CAR ; + DUP 7 ; + DIG 4 ; MUL ; - PAIR } ; - UNPAIR ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - SWAP ; - DUP ; - CAR ; - UPDATE 2 ; - DUP ; - DUP 3 ; - PUSH nat 1 ; - DUP 7 ; - ADD ; - MUL ; - DUP 18 ; - DUP 4 ; - CAR ; - PUSH string "wrong-precision" ; - DUP 21 ; - DUP 9 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - ADD ; - DIG 2 ; - CAR ; - DUP 6 ; - DIG 4 ; - MUL ; - DUP 18 ; - DUP 8 ; - DUP 7 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - ADD ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - UPDATE 1 ; - LEFT (pair nat nat) } - { RIGHT (pair nat nat) } } ; - SWAP ; - DIG 2 ; + DUP 10 ; + DUP 9 ; + DUP 8 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + ADD ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + UPDATE 1 ; + SWAP } + {} } ; + SWAP ; + DIG 2 ; + DIG 3 ; + DIG 4 ; + DIG 5 ; + DROP 5 ; + CAR } ; + DUP 4 ; + APPLY ; DIG 3 ; - DIG 4 ; - DIG 14 ; - DROP 5 ; + DROP ; + DIG 3 ; + UNPAIR ; + SWAP ; CAR ; - DUP 9 ; - DUP 8 ; - GET 14 ; - DUP 3 ; - DUP 9 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + GET 13 ; + DUP 2 ; CAR ; + GET ; + IF_NONE { PUSH string "not-launched" ; FAILWITH } {} ; + DUP ; + CAR ; + DUP 2 ; + GET 3 ; DUP 3 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH string "zero-amount-in" ; - DUP 3 ; - DUP 3 ; + GET 5 ; + DUP 4 ; + GET 7 ; + DUP 2 ; + DUP 2 ; + NOW ; COMPARE ; LT ; - IF { DROP } { FAILWITH } ; - DUP 8 ; - SWAP ; + IF { DROP ; + DUP 9 ; + DUP 4 ; + NOW ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DIG 9 ; + DIG 4 ; + DIG 3 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 4 ; + DUP 4 ; + SUB ; + ABS ; + SWAP ; + DUG 2 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP 3 ; + DIG 2 ; + COMPARE ; + GT ; + IF { ADD } { SWAP ; SUB ; ABS } } + { SWAP ; DIG 2 ; DIG 3 ; DIG 4 ; DIG 9 ; DROP 5 } ; DUP ; - DUG 2 ; - DUP 5 ; - PAIR ; - DUP 6 ; - DUP 9 ; - PAIR ; - PAIR ; + DUP 3 ; + GET 9 ; PAIR ; - DUP 10 ; + DUP 5 ; SWAP ; EXEC ; - DIG 5 ; - DUP 9 ; - GET 11 ; - DUP ; - DUG 2 ; - GET 4 ; DUP 3 ; - GET 3 ; - DIG 3 ; - CAR ; - ADD ; - ADD ; - ADD ; - DUP 5 ; + GET 9 ; MAP { UNPAIR ; - DUP 8 ; + DUP 6 ; + GET 3 ; SWAP ; - COMPARE ; - EQ ; - IF { DUP 12 ; - DUP 4 ; - DUP 7 ; - DUP 7 ; - DUP 5 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } } - { DUP 12 ; - DUP 6 ; - DUP 6 ; - DUP 4 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + DUP 6 ; + GET 4 ; + IF { DUP 2 ; GET 4 ; ADD } + { DUP 8 ; + SWAP ; DUP 3 ; + GET 4 ; SUB ; ISNAT ; IF_NONE { FAILWITH } { SWAP ; DROP } } ; - DUP 13 ; - PUSH nat 10000000000 ; - DUP 13 ; - GET 9 ; - SIZE ; - DUP 6 ; - PUSH string "wrong-tokens-count" ; - PUSH nat 1 ; - DUP 4 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH nat 4 ; - MUL ; - DUG 2 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - DIG 3 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - DIG 2 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } } ; - SWAP ; - DIG 4 ; - DROP 2 ; - DUP 11 ; + UPDATE 4 } ; + DIG 2 ; SWAP ; - DUP ; - DUG 2 ; - DUP 7 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 11 ; - DUP 10 ; - DIG 5 ; - DIG 4 ; PAIR ; - DUP 7 ; - DIG 8 ; - PAIR ; - PAIR ; - PAIR ; - DIG 8 ; + DIG 4 ; SWAP ; EXEC ; - DIG 2 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP 8 ; - DUP 7 ; - GET 9 ; - DUP 6 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - PUSH string "low-reserves" ; - SWAP ; - DUP ; - DUG 2 ; + DIG 3 ; GET 4 ; - DUP 4 ; - COMPARE ; - LT ; - IF { DROP } { FAILWITH } ; - GET 3 ; - DIG 8 ; - DIG 4 ; - DIG 5 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; + IF { DIG 3 ; + DUP 3 ; + DIG 2 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } } + { DIG 3 ; + SWAP ; + DUP 3 ; + SUB ; + ISNAT ; + IF_NONE { FAILWITH } { SWAP ; DROP } } ; SWAP ; - DUP ; - DUG 2 ; - DIG 3 ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; DIG 2 ; - DUP 7 ; - DIG 4 ; - DIG 4 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; + GET 16 ; + DIG 2 ; + MUL ; EDIV ; IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR ; - PUSH string "low-total-supply" ; - DIG 3 ; - DIG 4 ; - GET 14 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 3 ; - DUP 4 ; - DIG 3 ; - SUB ; - ISNAT ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DIG 2 ; - PAIR 3 ; - CAR } ; - view "get_tok_per_share" - nat - (map nat nat) - { UNPAIR ; - PUSH string "not-launched" ; - DIG 2 ; - CAR ; - GET 13 ; - DIG 2 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - DUP ; - GET 9 ; - MAP { CDR ; - SWAP ; - DUP ; - DUG 2 ; - GET 14 ; - PUSH nat 1000000000000000000 ; - DIG 2 ; - GET 4 ; - MUL ; - EDIV ; - IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; - CAR } ; - SWAP ; - DROP } ; - view "get_token_map" - nat - (map nat (or (address %fa12) (pair %fa2 (address %token_address) (nat %token_id)))) - { UNPAIR ; - PUSH string "not-launched" ; - DIG 2 ; - CAR ; - GET 9 ; - DIG 2 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } } ; - view "get_reserves" - nat - (map nat nat) - { UNPAIR ; - PUSH string "not-launched" ; - DIG 2 ; - CAR ; - GET 13 ; - DIG 2 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - GET 9 ; - MAP { CDR ; GET 4 } } ; - view "get_total_supply" - nat - nat - { UNPAIR ; - PUSH string "not-launched" ; - DIG 2 ; - CAR ; - GET 13 ; - DIG 2 ; - GET ; - IF_NONE { FAILWITH } { SWAP ; DROP } ; - GET 14 } ; - view "get_balance" - (list (pair (address %owner) (nat %token_id))) - (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))) - { UNPAIR ; - MAP { PUSH string "FA2_TOKEN_UNDEFINED" ; - DUP 3 ; - CAR ; - GET 7 ; - DUP 3 ; - CDR ; - COMPARE ; - LT ; - IF { DROP } { FAILWITH } ; - PUSH nat 0 ; - DUP 3 ; - CAR ; - GET 15 ; - DUP 3 ; - CDR ; - DUP 4 ; - CAR ; - PAIR ; - GET ; - IF_NONE {} { SWAP ; DROP } ; - SWAP ; - PAIR } ; - SWAP ; - DROP } } + CAR } } diff --git a/contracts/main/dex.ligo b/contracts/main/dex.ligo index f8563ad..05f8753 100644 --- a/contracts/main/dex.ligo +++ b/contracts/main/dex.ligo @@ -9,6 +9,7 @@ #include "../partials/common_types.ligo" #include "../partials/fa12/types.ligo" #include "../partials/fa2/types.ligo" +#include "../partials/strategy/types.ligo" #if !FACTORY #include "../partials/dev/types.ligo" #else @@ -16,6 +17,7 @@ #include "../partials/dex_core/storage.ligo" #include "../partials/admin/types.ligo" #include "../partials/dex_core/types.ligo" +#include "../partials/dex_core/events.ligo" (* Helpers and functions *) #include "../partials/utils.ligo" #if FACTORY @@ -25,10 +27,12 @@ #endif #include "../partials/dex_core/helpers.ligo" #include "../partials/fa2/helpers.ligo" +#include "../partials/strategy/helpers.ligo" #include "../partials/dex_core/math.ligo" (* Lambda entrypoints *) #include "../partials/admin/lambdas.ligo" #include "../partials/fa2/lambdas.ligo" +#include "../partials/strategy/lambdas.ligo" #include "../partials/dex_core/lambdas.ligo" #if !FACTORY #include "../partials/dev/lambdas.ligo" @@ -39,6 +43,7 @@ #endif #include "../partials/admin/methods.ligo" #include "../partials/fa2/methods.ligo" +#include "../partials/strategy/methods.ligo" #include "../partials/dex_core/methods.ligo" (* View methods *) #include "../partials/fa2/views.ligo" @@ -51,18 +56,20 @@ function main( block { case p of [ #if !FACTORY - | Set_dex_function(params) -> s := set_function(FDex, params, s) - | Set_admin_function(params) -> s := set_function(FAdmin, params, s) - | Set_token_function(params) -> s := set_function(FToken, params, s) - | Set_dev_function(params) -> s := set_function(FDev, params, s) - | Use_dev(params) -> s.storage.dev_store := call_dev(params, s.storage.dev_store) + | Set_dex_function(params) -> s := set_function(FDex, params, s) + | Set_admin_function(params) -> s := set_function(FAdmin, params, s) + | Set_token_function(params) -> s := set_function(FToken, params, s) + | Set_dev_function(params) -> s := set_function(FDev, params, s) + | Set_strategy_function(params) -> s := set_function(FStrat, params, s) + | Use_dev(params) -> s.storage.dev_store := call_dev(params, s.storage.dev_store) #else - | Factory_action(params) -> s := factory_action(params, s) + | Factory_action(params) -> s := factory_action(params, s) #endif | _ -> skip ] } with case p of [ | User_action(params) -> call_user_action(params, s) | Use_admin(params) -> call_admin(params, s) + | Use_strategy(params) -> call_strategy(params, s) | _ -> (Constants.no_operations, s) ] \ No newline at end of file diff --git a/contracts/main/factory.ligo b/contracts/main/factory.ligo index 3e78897..7b03576 100644 --- a/contracts/main/factory.ligo +++ b/contracts/main/factory.ligo @@ -4,6 +4,7 @@ #define FACTORY #include "../partials/fa12/types.ligo" #include "../partials/fa2/types.ligo" +#include "../partials/strategy/types.ligo" #include "../partials/dex_core/storage.ligo" #include "../partials/admin/types.ligo" #include "../partials/dex_core/types.ligo" @@ -24,12 +25,13 @@ function main( : fact_return_t is block { case p of [ - | Set_init_function(params) -> s.init_func := set_init_function(params, s) - | Set_dev_function(params) -> s := set_function(FDev, params, s) - | Set_admin_function(params) -> s := set_function(FAdmin, params, s) - | Set_dex_function(params) -> s := set_function(FDex, params, s) - | Set_token_function(params) -> s := set_function(FToken, params, s) - | Use_dev(params) -> s.storage.dev_store := call_dev(params, s.storage.dev_store) + | Set_init_function(params) -> s.init_func := set_init_function(params, s) + | Set_dev_function(params) -> s := set_function(FDev, params, s) + | Set_admin_function(params) -> s := set_function(FAdmin, params, s) + | Set_dex_function(params) -> s := set_function(FDex, params, s) + | Set_token_function(params) -> s := set_function(FToken, params, s) + | Set_strategy_function(params) -> s := set_function(FStrat, params, s) + | Use_dev(params) -> s.storage.dev_store := call_dev(params, s.storage.dev_store) | _ -> skip ] } with case p of [ diff --git a/contracts/partials/admin/lambdas.ligo b/contracts/partials/admin/lambdas.ligo index 5a0feca..01d5594 100644 --- a/contracts/partials/admin/lambdas.ligo +++ b/contracts/partials/admin/lambdas.ligo @@ -42,10 +42,10 @@ function ramp_A( case p of [ | Ramp_A(params) -> { require((params.future_A > 0n) and (params.future_A <= Constants.max_a), Errors.Dex.a_limit); - require(params.future_time >= Tezos.now + Constants.min_ramp_time, Errors.Dex.timestamp_error); // dev: insufficient time + require(params.future_time >= Tezos.get_now() + Constants.min_ramp_time, Errors.Dex.timestamp_error); // dev: insufficient time var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); - require(Tezos.now >= pool.initial_A_time + Constants.min_ramp_time, Errors.Dex.timestamp_error); + require(Tezos.get_now() >= pool.initial_A_time + Constants.min_ramp_time, Errors.Dex.timestamp_error); const initial_A_f: nat = get_A( pool.initial_A_time, @@ -62,7 +62,7 @@ function ramp_A( s.pools[params.pool_id] := pool with record [ initial_A_f = initial_A_f; future_A_f = future_A_f; - initial_A_time = Tezos.now; + initial_A_time = Tezos.get_now(); future_A_time = params.future_time; ]; } @@ -88,8 +88,8 @@ function stop_ramp_A( s.pools[pool_id] := pool with record [ initial_A_f = current_A_f; future_A_f = current_A_f; - initial_A_time = Tezos.now; - future_A_time = Tezos.now; + initial_A_time = Tezos.get_now(); + future_A_time = Tezos.get_now(); ]; } | _ -> unreachable(Unit) @@ -125,7 +125,7 @@ function claim_dev( | Claim_developer(params) -> { require(params.amount > 0n, Errors.Dex.zero_in); const dev_address = get_dev_address(s); - require(Tezos.sender = dev_address, Errors.Dex.not_developer); + require(Tezos.get_sender() = dev_address, Errors.Dex.not_developer); const bal = unwrap_or(s.dev_rewards[params.token], 0n); @@ -133,7 +133,7 @@ function claim_dev( operations := typed_transfer( - Tezos.self_address, + Tezos.get_self_address(), dev_address, params.amount, params.token diff --git a/contracts/partials/admin/methods.ligo b/contracts/partials/admin/methods.ligo index ee115f2..7e8310f 100644 --- a/contracts/partials/admin/methods.ligo +++ b/contracts/partials/admin/methods.ligo @@ -10,7 +10,10 @@ case p of [ | Claim_developer(_) -> skip // Claim_developer has own inner check for developer address - | _ -> require(Tezos.sender = s.storage.admin, Errors.Dex.not_contract_admin) +#if !FACTORY + | Set_strategy_factory(_)-> skip +#endif + | _ -> require(Tezos.get_sender() = s.storage.admin, Errors.Dex.not_contract_admin) ]; const idx : nat = case p of [ @@ -24,6 +27,7 @@ | Set_default_referral(_) -> 6n #if !FACTORY | Add_pool(_) -> 7n + | Set_strategy_factory(_) -> 8n #endif ]; diff --git a/contracts/partials/admin/standalone/lambdas.ligo b/contracts/partials/admin/standalone/lambdas.ligo index 652d3c0..3de04d6 100644 --- a/contracts/partials/admin/standalone/lambdas.ligo +++ b/contracts/partials/admin/standalone/lambdas.ligo @@ -60,8 +60,8 @@ function add_pool( const pool = pool_i with record [ initial_A_f = params.a_constant * Constants.a_precision; future_A_f = params.a_constant * Constants.a_precision; - initial_A_time = Tezos.now; - future_A_time = Tezos.now; + initial_A_time = Tezos.get_now(); + future_A_time = Tezos.get_now(); tokens_info = tokens_info; fee = params.fees; ]; @@ -72,7 +72,7 @@ function add_pool( pool = pool; inputs = inputs; min_mint_amount = 1n; - receiver = Some(Tezos.sender) + receiver = Some(Tezos.get_sender()) ], s); operations := res.op; s := res.s; @@ -80,3 +80,19 @@ function add_pool( | _ -> unreachable(Unit) ] } with (operations, s) + +function set_strategy_factory( + const p : admin_action_t; + var s : storage_t) + : return_t is + block { + var operations: list(operation) := Constants.no_operations; + case p of [ + | Set_strategy_factory(params) -> { + const dev_address = get_dev_address(s); + require(Tezos.get_sender() = dev_address, Errors.Dex.not_developer); + s.strategy_factory := add_rem_candidate(params, s.strategy_factory); + } + | _ -> unreachable(Unit) + ] + } with (operations, s) diff --git a/contracts/partials/admin/types.ligo b/contracts/partials/admin/types.ligo index 107afea..5e0c73b 100644 --- a/contracts/partials/admin/types.ligo +++ b/contracts/partials/admin/types.ligo @@ -1,4 +1,4 @@ -type set_man_param_t is [@layout:comb] record [ +type set_cand_param_t is [@layout:comb] record [ add : bool; candidate : address; ] @@ -24,7 +24,7 @@ type init_param_t is [@layout:comb] record [ #endif type admin_action_t is -| Add_rem_managers of set_man_param_t +| Add_rem_managers of set_cand_param_t | Set_admin of address | Claim_developer of claim_by_token_param_t | Ramp_A of ramp_a_param_t @@ -33,4 +33,5 @@ type admin_action_t is | Set_default_referral of address #if !FACTORY | Add_pool of init_param_t (* sets initial liquidity *) +| Set_strategy_factory of set_cand_param_t #endif diff --git a/contracts/partials/constants.ligo b/contracts/partials/constants.ligo index a34971b..2cb5d63 100644 --- a/contracts/partials/constants.ligo +++ b/contracts/partials/constants.ligo @@ -4,8 +4,9 @@ const dex_func_count : nat = 7n; const dev_func_count : nat = 2n; const token_func_count : nat = 5n; +const strat_func_count : nat = 5n; #if !FACTORY -const admin_func_count : nat = 8n; +const admin_func_count : nat = 9n; #else const admin_func_count : nat = 7n; #endif diff --git a/contracts/partials/dev/methods.ligo b/contracts/partials/dev/methods.ligo index f883b98..f988a81 100644 --- a/contracts/partials/dev/methods.ligo +++ b/contracts/partials/dev/methods.ligo @@ -5,7 +5,7 @@ : dev_storage_t is block { - require(Tezos.sender = s.dev_address, Errors.Dex.not_developer); + require(Tezos.get_sender() = s.dev_address, Errors.Dex.not_developer); const idx : nat = case p of [ | Set_dev_address(_) -> 0n diff --git a/contracts/partials/dex_core/events.ligo b/contracts/partials/dex_core/events.ligo new file mode 100644 index 0000000..94b02f4 --- /dev/null +++ b/contracts/partials/dex_core/events.ligo @@ -0,0 +1,73 @@ +type swap_event_t is [@layout:comb] record [ + pool_id : pool_id_t; + i : token_pool_idx_t; + j : token_pool_idx_t; + amount_in : nat; + amount_out : nat; + receiver : address; + referral : address; +] + +type invest_event_t is [@layout:comb] record [ + pool_id : pool_id_t; + inputs : map(token_pool_idx_t, nat); + shares_minted : nat; + receiver : address; + referral : address; +] + +type divest_event_t is [@layout:comb] record [ + pool_id : pool_id_t; + shares_burned : nat; + outputs : map(token_pool_idx_t, nat); + receiver : address; +] + +type divest_one_event_t is [@layout:comb] record [ + pool_id : pool_id_t; + i : token_pool_idx_t; + shares_burned : nat; + amount_out : nat; + receiver : address; + referral : address; +] + +type divest_imb_event_t is [@layout:comb] record [ + pool_id : pool_id_t; + shares_burned : nat; + outputs : map(token_pool_idx_t, nat); + receiver : address; + referral : address; +] + +type txs_event_t is [@layout:comb] record [ + token_id : pool_id_t; + amount : nat; + receiver : address; +] + +type transfer_event_t is [@layout:comb] record [ + owner : address; + caller : address; + txs : list(txs_event_t) +] + +type event_t is +| TransferEvent of transfer_event_t +| InvestEvent of invest_event_t +| SwapEvent of swap_event_t +| DivestEvent of divest_event_t +| DivestOneEvent of divest_one_event_t +| DivestImbalanceEvent of divest_imb_event_t + +[@inline] function emit_event( + const p : event_t) + : operation is + case p of [ + TransferEvent(params) -> Tezos.emit("%transfer", params) + | InvestEvent(params) -> Tezos.emit("%invest", params) + | SwapEvent(params) -> Tezos.emit("%swap", params) + | DivestEvent(params) -> Tezos.emit("%divest", params) + | DivestOneEvent(params) -> Tezos.emit("%divest_one", params) + | DivestImbalanceEvent(params) -> Tezos.emit("%divest_imbalance", params) + ]; \ No newline at end of file diff --git a/contracts/partials/dex_core/factory/helpers.ligo b/contracts/partials/dex_core/factory/helpers.ligo index c1314c0..e9014a8 100644 --- a/contracts/partials/dex_core/factory/helpers.ligo +++ b/contracts/partials/dex_core/factory/helpers.ligo @@ -3,6 +3,12 @@ function get_dev_fee( : nat is unwrap((Tezos.call_view("dev_fee", Unit, s.factory_address): option(nat)), Errors.Factory.no_fee) +function check_is_registered_strategy( + const strategy : address; + const s : storage_t) + : bool is + unwrap((Tezos.call_view("is_registered_strategy", strategy, s.factory_address): option(bool)), Errors.Factory.no_strategy_factory) + function get_dev_address( const s : storage_t) : address is diff --git a/contracts/partials/dex_core/helpers.ligo b/contracts/partials/dex_core/helpers.ligo index 2965982..1d6db40 100644 --- a/contracts/partials/dex_core/helpers.ligo +++ b/contracts/partials/dex_core/helpers.ligo @@ -73,8 +73,8 @@ function harvest_staker_rewards( Constants.accum_precision); if reward_amt > 0n then accum.op := typed_transfer( - Tezos.self_address, - Tezos.sender, + Tezos.get_self_address(), + Tezos.get_sender(), reward_amt, get_token_by_id(i, tokens) ) # accum.op @@ -110,15 +110,15 @@ function update_former_and_transfer( ) = case param of [ | Add(p) -> ( staker_accum.balance + p.amount, - Tezos.sender, - Tezos.self_address, + Tezos.get_sender(), + Tezos.get_self_address(), pool_stake_accum.total_staked + p.amount, p.amount ) | Remove(p) -> ( nat_or_error(staker_accum.balance - p.amount, Errors.Dex.wrong_shares_out), - Tezos.self_address, - Tezos.sender, + Tezos.get_self_address(), + Tezos.get_sender(), nat_or_error(pool_stake_accum.total_staked - p.amount, Errors.Dex.wrong_shares_out), p.amount ) @@ -165,7 +165,7 @@ function update_stake( | Remove(p) -> (p.pool_id, p.amount) ]; var operations: list(operation) := Constants.no_operations; - const staker_key = (Tezos.sender, pool_id); + const staker_key = (Tezos.get_sender(), pool_id); var staker_accum := unwrap_or( s.stakers_balance[staker_key], default_staker_info @@ -208,14 +208,18 @@ function get_pool_info( const pool : pool_t = unwrap_or(pools[token_id], record [ initial_A_f = 0n; future_A_f = 0n; - initial_A_time = Tezos.now; - future_A_time = Tezos.now; + initial_A_time = Tezos.get_now(); + future_A_time = Tezos.get_now(); tokens_info = (map []: map(token_pool_idx_t, token_info_t)); fee = record [ lp_f = 0n; ref_f = 0n; stakers_f = 0n; ]; + strategy = record [ + strat_contract = (None: option(address)); + configuration = (map []: map(token_pool_idx_t, strategy_storage_t)); + ]; 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/dex_core/lambdas.ligo b/contracts/partials/dex_core/lambdas.ligo index 95bc0ca..538e716 100644 --- a/contracts/partials/dex_core/lambdas.ligo +++ b/contracts/partials/dex_core/lambdas.ligo @@ -18,7 +18,7 @@ function swap( const i = params.idx_from; const j = params.idx_to; require(i < tokens_count and j < tokens_count, Errors.Dex.wrong_index); - const receiver = unwrap_or(params.receiver, Tezos.sender); + const receiver = unwrap_or(params.receiver, Tezos.get_sender()); var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); const dy = perform_swap(i, j, dx, pool); const pool_total_staked = pool.staker_accumulator.total_staked; @@ -52,19 +52,40 @@ 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; - s.pools[params.pool_id] := pool; operations := typed_transfer( - Tezos.self_address, + 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); operations := typed_transfer( - Tezos.sender, - Tezos.self_address, + 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; + i = i; + j = j; + amount_in = dx; + amount_out = after_fees.dy; + receiver = receiver; + referral = referral; + ]; + operations := emit_event(SwapEvent(event_params)) # operations; } | _ -> unreachable(Unit) ] @@ -114,13 +135,13 @@ function divest_liquidity( require(params.shares =/= 0n, Errors.Dex.zero_in); var pool : pool_t := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); - const receiver = unwrap_or(params.receiver, Tezos.sender); + const receiver = unwrap_or(params.receiver, Tezos.get_sender()); const total_supply : nat = pool.total_supply; function divest_reserves( - var accum : record [ tok_inf: map(token_pool_idx_t, token_info_t); op: list(operation) ]; + var accum : record [ tok_inf: map(token_pool_idx_t, token_info_t); op: list(operation); outs: map(token_pool_idx_t, nat); ]; const entry : (token_pool_idx_t * token_t)) - : record [ tok_inf: map(token_pool_idx_t, token_info_t); op: list(operation) ] is + : record [ tok_inf: map(token_pool_idx_t, token_info_t); op: list(operation); outs: map(token_pool_idx_t, nat) ] is block { var token_info := unwrap(accum.tok_inf[entry.0], Errors.Dex.no_token_info); const min_amount_out = unwrap_or(params.min_amounts_out[entry.0], 1n); @@ -129,27 +150,44 @@ function divest_liquidity( require(value >= min_amount_out, Errors.Dex.high_min_out); require(value =/= 0n, Errors.Dex.dust_out); accum.op := typed_transfer( - Tezos.self_address, + Tezos.get_self_address(), receiver, value, entry.1 ) # accum.op; + accum.outs[entry.0] := value; token_info.reserves := nat_or_error(token_info.reserves - value, Errors.Dex.low_reserves); accum.tok_inf[entry.0] := token_info; } with accum; 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 ]); - + 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; pool.total_supply := nat_or_error(pool.total_supply - params.shares, Errors.Dex.low_total_supply); - const key = (Tezos.sender, params.pool_id); + const key = (Tezos.get_sender(), params.pool_id); const share = unwrap_or(s.ledger[key], 0n); s.ledger[key] := nat_or_error(share - params.shares, Errors.Dex.insufficient_lp); s.pools[params.pool_id] := pool; - operations := res.op; + const event_params: divest_event_t = record[ + pool_id = params.pool_id; + shares_burned = params.shares; + outputs = res.outs; + receiver = receiver; + ]; + operations := emit_event(DivestEvent(event_params)) # operations; } | _ -> unreachable(Unit) ] @@ -169,8 +207,9 @@ function divest_imbalanced( check_deadline(params.deadline); require(params.max_shares > 0n, Errors.Dex.zero_in); - const receiver = unwrap_or(params.receiver, Tezos.sender); - const key = (Tezos.sender, params.pool_id); + const receiver = unwrap_or(params.receiver, Tezos.get_sender()); + const referral = unwrap_or(params.referral, s.default_referral); + const key = (Tezos.get_sender(), params.pool_id); const share = unwrap_or(s.ledger[key], 0n); @@ -204,7 +243,7 @@ function divest_imbalanced( accum.tokens_info[value.0] := t_i; if value.1 > 0n then accum.operations := typed_transfer( - Tezos.self_address, + Tezos.get_self_address(), receiver, value.1, unwrap(tokens[value.0], Errors.Dex.wrong_index) @@ -234,7 +273,7 @@ function divest_imbalanced( tokens, pool.fee, get_dev_fee(s), - unwrap_or(params.referral, s.default_referral), + referral, record[ dev_rewards = s.dev_rewards; referral_rewards = s.referral_rewards; @@ -264,8 +303,24 @@ 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; s.pools[params.pool_id] := pool; - s.ledger[(Tezos.sender, params.pool_id)] := new_shares; + s.ledger[(Tezos.get_sender(), params.pool_id)] := new_shares; + const event_params: divest_imb_event_t = record[ + pool_id = params.pool_id; + shares_burned = burn_amount; + outputs = params.amounts_out; + receiver = receiver; + referral = referral; + ]; + operations := emit_event(DivestImbalanceEvent(event_params)) # operations; } | _ -> unreachable(Unit) ]; @@ -286,7 +341,7 @@ function divest_one_coin( var pool := unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); require(params.token_index < Map.size(pool.tokens_info), Errors.Dex.wrong_index); - const sender_key = (Tezos.sender, params.pool_id); + const sender_key = (Tezos.get_sender(), params.pool_id); const token = get_token_by_id(params.token_index, s.tokens[params.pool_id]); @@ -328,24 +383,41 @@ function divest_one_coin( pool.tokens_info[params.token_index] := info; 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; s.pools[params.pool_id] := pool; const account_bal = unwrap_or(s.ledger[sender_key], 0n); - s.ledger[sender_key] := unwrap(is_nat(account_bal - params.shares), Errors.FA2.insufficient_balance); + s.ledger[sender_key] := unwrap(is_nat(account_bal - params.shares), Errors.Dex.insufficient_lp); s.dev_rewards[token] := unwrap_or(s.dev_rewards[token], 0n) + dev_fee; const referral: address = unwrap_or(params.referral, s.default_referral); s.referral_rewards[(referral, token)] := unwrap_or(s.referral_rewards[(referral, token)], 0n) + ref_fee; - - const receiver = unwrap_or(params.receiver, Tezos.sender); - - operations := typed_transfer( - Tezos.self_address, - receiver, - result.dy, - token - ) # operations; + const event_params: divest_one_event_t = record[ + pool_id = params.pool_id; + i = params.token_index; + shares_burned = params.shares; + amount_out = result.dy; + receiver = receiver; + referral = referral; + ]; + operations := emit_event(DivestOneEvent(event_params)) # operations; } | _ -> unreachable(Unit) ]; @@ -362,15 +434,15 @@ function claim_ref( | Claim_referral(params) -> { require(params.amount > 0n, Errors.Dex.zero_in); - const key = (Tezos.sender, params.token); + const key = (Tezos.get_sender(), params.token); const bal = unwrap_or(s.referral_rewards[key], 0n); s.referral_rewards[key] := nat_or_error(bal - params.amount, Errors.Dex.balance_overflow); operations := typed_transfer( - Tezos.self_address, - Tezos.sender, + Tezos.get_self_address(), + Tezos.get_sender(), params.amount, params.token ) # operations; diff --git a/contracts/partials/dex_core/math.ligo b/contracts/partials/dex_core/math.ligo index aec0fbf..a2c042a 100644 --- a/contracts/partials/dex_core/math.ligo +++ b/contracts/partials/dex_core/math.ligo @@ -23,9 +23,9 @@ function get_A( : nat is block { var a := a1; - if Tezos.now < t1 + if Tezos.get_now() < t1 then { - const t_num = nat_or_error(Tezos.now - t0, Errors.Dex.timestamp_error); + const t_num = nat_or_error(Tezos.get_now() - t0, Errors.Dex.timestamp_error); const t_den = nat_or_error(t1 - t0, Errors.Dex.timestamp_error); const diff = abs(a1 - a0); const value = diff * t_num / t_den; @@ -342,7 +342,7 @@ function add_liq( const init_tokens_info = pool.tokens_info; const d0 = get_D_mem(init_tokens_info, amp_f); const token_supply = pool.total_supply; - + const referral = unwrap_or(params.referral, s.default_referral); function add_inputs( const key : token_pool_idx_t; var token_info : token_info_t) @@ -370,7 +370,7 @@ function add_liq( unwrap(s.tokens[params.pool_id], Errors.Dex.pool_not_listed), pool.fee, get_dev_fee(s), - unwrap_or(params.referral, s.default_referral), + referral, record [ dev_rewards = s.dev_rewards; referral_rewards = s.referral_rewards; @@ -404,20 +404,33 @@ function add_liq( : list(operation) is if input.1 > 0n then typed_transfer( - Tezos.sender, - Tezos.self_address, + Tezos.get_sender(), + Tezos.get_self_address(), input.1, get_token_by_id(input.0, tokens[params.pool_id]) ) # operations 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; + s.pools[params.pool_id] := pool; - const receiver = unwrap_or(params.receiver, Tezos.sender); + const receiver = unwrap_or(params.receiver, Tezos.get_sender()); const user_key = (receiver, params.pool_id); const share = unwrap_or(s.ledger[user_key], 0n); const new_shares = share + mint_amount; - s.ledger[user_key] := new_shares; - s.pools[params.pool_id] := pool; - } with record[ op = Map.fold(transfer_to_pool, params.inputs, Constants.no_operations); s = s ] + const event_params: invest_event_t = record[ + pool_id = params.pool_id; + inputs = params.inputs; + shares_minted = mint_amount; + receiver = receiver; + referral = referral; + ]; + } with record[ op = emit_event(InvestEvent(event_params)) # Map.fold(transfer_to_pool, params.inputs, rebalance_ops); s = s ] diff --git a/contracts/partials/dex_core/methods.ligo b/contracts/partials/dex_core/methods.ligo index 9c4d417..c127afe 100644 --- a/contracts/partials/dex_core/methods.ligo +++ b/contracts/partials/dex_core/methods.ligo @@ -47,7 +47,7 @@ based on the argument type. var s : full_storage_t) : full_storage_t is block { - assert(Tezos.sender = s.storage.factory_address); + assert(Tezos.get_sender() = s.storage.factory_address); case p of [ | Copy_dex_function(lambda) -> s.dex_lambdas := lambda | Freeze -> s.storage.started := not s.storage.started diff --git a/contracts/partials/dex_core/standalone/helpers.ligo b/contracts/partials/dex_core/standalone/helpers.ligo index d36cc00..eb2917a 100644 --- a/contracts/partials/dex_core/standalone/helpers.ligo +++ b/contracts/partials/dex_core/standalone/helpers.ligo @@ -7,3 +7,10 @@ function get_dev_address( const s : storage_t) : address is s.dev_store.dev_address + +function check_is_registered_strategy( + const strategy : address; + const s : storage_t) + : bool is + check_strategy_factory(strategy, s.strategy_factory) + diff --git a/contracts/partials/dex_core/storage.ligo b/contracts/partials/dex_core/storage.ligo index ffa253e..54c6982 100644 --- a/contracts/partials/dex_core/storage.ligo +++ b/contracts/partials/dex_core/storage.ligo @@ -49,6 +49,8 @@ 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; + staker_accumulator : staker_accum_t; (* LP data *) @@ -83,6 +85,7 @@ type storage_t is [@layout:comb] record [ factory_address : address; started : bool; #else + strategy_factory : set(address); dev_store : dev_storage_t; #endif ] @@ -96,7 +99,11 @@ type full_storage_t is [@layout:comb] record [ admin_lambdas : big_map(nat, bytes); (* map with admin-related functions code *) dex_lambdas : big_map(nat, bytes); (* map with exchange-related functions code *) token_lambdas : big_map(nat, bytes); (* map with token-related functions code *) + strat_lambdas : big_map(nat, bytes); (* map with strategy-related functions code *) ] type return_t is list(operation) * storage_t + +type strat_func_t is (strategy_action_t * storage_t) -> return_t + type full_return_t is list(operation) * full_storage_t diff --git a/contracts/partials/dex_core/types.ligo b/contracts/partials/dex_core/types.ligo index fba497f..2de0564 100644 --- a/contracts/partials/dex_core/types.ligo +++ b/contracts/partials/dex_core/types.ligo @@ -1,4 +1,4 @@ -type func_entry_t is FAdmin | FDex | FToken | FDev +type func_entry_t is FAdmin | FDex | FToken | FDev | FStrat type staker_info_req_t is [@layout:comb] record [ user : address; @@ -149,6 +149,7 @@ type factory_action_t is type full_action_t is | Use_admin of admin_action_t +| Use_strategy of strategy_action_t | User_action of user_action_t #if !FACTORY | Use_dev of dev_action_t @@ -159,6 +160,7 @@ type full_action_t is | Set_token_function of set_lambda_func_t (* sets the FA function, is used before the whole system is launched *) | Set_dev_function of set_lambda_func_t +| Set_strategy_function of set_lambda_func_t #else | Factory_action of factory_action_t #endif diff --git a/contracts/partials/dex_core/views.ligo b/contracts/partials/dex_core/views.ligo index fd74ab3..f02302c 100644 --- a/contracts/partials/dex_core/views.ligo +++ b/contracts/partials/dex_core/views.ligo @@ -105,16 +105,16 @@ const info = unwrap_or(s.storage.stakers_balance[key], default_staker_info); function get_rewards( const key : token_pool_idx_t; - const value : account_reward_t) + const value : nat) : nat is block { - const pool_accum_f = unwrap_or(pool_accumulator_f[key], 0n); - const new_former_f = info.balance * pool_accum_f; - const reward_amt = (value.reward_f + abs(new_former_f - value.former_f)) / Constants.accum_precision; + const earning = unwrap_or(info.earnings[key], record[reward_f=0n;former_f=0n]); + const new_former_f = info.balance * value; + const reward_amt = (earning.reward_f + abs(new_former_f - earning.former_f)) / Constants.accum_precision; } with reward_amt; const rew_info: staker_res = record [ balance = info.balance; - rewards = Map.map(get_rewards, info.earnings); + rewards = Map.map(get_rewards, pool_accumulator_f); ]; } with record [ request = params; diff --git a/contracts/partials/errors.ligo b/contracts/partials/errors.ligo index ac8faf1..1f7b7cc 100644 --- a/contracts/partials/errors.ligo +++ b/contracts/partials/errors.ligo @@ -18,7 +18,7 @@ module Dex is { const not_started : string = "not-started"; const pool_listed : string = "pool-exist"; const pool_not_listed : string = "not-launched"; - const reserves_drained : string = "zero-reserves-when-positive-shares"; + const reserves_drained : string = "zero-reserves-when-positive-shares"; const supply_drained : string = "positive-reserves-when-zero-shares"; const time_expired : string = "time-expired"; const timestamp_error : string = "timestamp-error"; @@ -46,6 +46,7 @@ module FA2 is { module Math is { const nat_error : string = "value-not-natural"; const ediv_error : string = "ediv-error"; + const percent_overflow : string = "percent-overflow"; } module Factory is { @@ -55,4 +56,21 @@ module Factory is { const not_deployer : string = "not-deployer-of-pool"; const not_dex : string = "not-dex"; const burn_rate_overflow : string = "burn-rate-overflow"; + const no_strategy_factory : string = "no-strategy-factory-view"; +} + +module Strategy is { + const out_of_delta_bounds : string = "out-of-delta-bounds"; + const no_update_state_entrypoint: string = "no-update-state-EP"; + const no_update_info_entrypoint : string = "no-update-info-EP"; + const not_registered : string = "strategy-not-registered-on-factory"; + const no_is_registered : string = "no-is-registered-view"; + const no_prepare_entrypoint : string = "no-prepare-EP"; + const unknown_token : string = "no-token-strategy-set"; + const unclaimed_reserves : string = "strategy-unclaimed-reserves"; + const no_pool_data_view : string = "no-pool-data-view"; + const no_connected_strategy : string = "no-connected-strategy"; + const wrong_params : string = "wrong-connect-params-strategy"; + const already_connected : string = "token-strategy-connected"; + const nothing_to_rebalance : string = "nothing-to-rebalance"; } \ No newline at end of file diff --git a/contracts/partials/fa2/helpers.ligo b/contracts/partials/fa2/helpers.ligo index 1b0fdcb..151cd8b 100644 --- a/contracts/partials/fa2/helpers.ligo +++ b/contracts/partials/fa2/helpers.ligo @@ -3,7 +3,7 @@ const from_account : address; const allowances : set(address)) : unit is - require(from_account = Tezos.sender or (allowances contains Tezos.sender), Errors.FA2.not_operator); + require(from_account = Tezos.get_sender() or (allowances contains Tezos.get_sender()), Errors.FA2.not_operator); [@inline] function get_allowances( const key : address * pool_id_t; @@ -13,29 +13,41 @@ (* Perform transfers from one owner *) [@inline] function iterate_transfer( - var s : full_storage_t; + var accum : list(operation) * full_storage_t; const user_trx_params : transfer_fa2_param_t) - : full_storage_t is + : list(operation) * full_storage_t is block { function make_transfer( - var s : full_storage_t; + var acc : list(txs_event_t) * full_storage_t; const transfer : transfer_fa2_dst_t) - : full_storage_t is + : list(txs_event_t) * full_storage_t is block { - require(transfer.token_id < s.storage.pools_count, Errors.FA2.undefined); + require(transfer.token_id < acc.1.storage.pools_count, Errors.FA2.undefined); const sender_key = (user_trx_params.from_, transfer.token_id); - var sender_balance := unwrap_or(s.storage.ledger[sender_key], 0n); - var sender_allowance := get_allowances(sender_key, s.storage.allowances); + var sender_balance := unwrap_or(acc.1.storage.ledger[sender_key], 0n); + var sender_allowance := get_allowances(sender_key, acc.1.storage.allowances); check_permissions(user_trx_params.from_, sender_allowance); sender_balance := nat_or_error(sender_balance - transfer.amount, Errors.FA2.insufficient_balance); - s.storage.ledger[sender_key] := sender_balance; + acc.1.storage.ledger[sender_key] := sender_balance; const dest_key = (transfer.to_, transfer.token_id); - var dest_account := unwrap_or(s.storage.ledger[dest_key], 0n); + var dest_account := unwrap_or(acc.1.storage.ledger[dest_key], 0n); dest_account := dest_account + transfer.amount; - s.storage.ledger[dest_key] := dest_account; - } with s; -} with List.fold(make_transfer, user_trx_params.txs, s) + acc.1.storage.ledger[dest_key] := dest_account; + acc.0 := (record[ + token_id = transfer.token_id; + amount = transfer.amount; + receiver = transfer.to_; + ]: txs_event_t) # acc.0; + } with acc; + const result = List.fold(make_transfer, user_trx_params.txs, ((list[]:list(txs_event_t)), accum.1)); + accum.1 := result.1; + accum.0 := emit_event(TransferEvent(record[ + owner = user_trx_params.from_; + caller = Tezos.get_sender(); + txs = result.0; + ])) # accum.0; +} with accum (* Perform single operator update *) [@inline] function iterate_update_operator( @@ -48,7 +60,7 @@ | Remove_operator(param) -> (param, False) ]; require(param.operator =/= param.owner, Errors.FA2.owner_as_operator); - require(Tezos.sender = param.owner, Errors.FA2.not_owner); + require(Tezos.get_sender() = param.owner, Errors.FA2.not_owner); require(param.token_id < s.storage.pools_count, Errors.Dex.pool_not_listed); const owner_key = (param.owner, param.token_id); diff --git a/contracts/partials/fa2/lambdas.ligo b/contracts/partials/fa2/lambdas.ligo index 76cc042..a03d863 100644 --- a/contracts/partials/fa2/lambdas.ligo +++ b/contracts/partials/fa2/lambdas.ligo @@ -4,7 +4,7 @@ function transfer_ep( var s : full_storage_t) : full_return_t is case p of [ - | Transfer(params) -> (Constants.no_operations, List.fold(iterate_transfer, params, s)) + | Transfer(params) -> List.fold(iterate_transfer, params, (Constants.no_operations, s)) | _ -> unreachable(Unit) ] @@ -27,7 +27,7 @@ function update_token_metadata( var operations := Constants.no_operations; case p of [ | Update_metadata(params) -> { - require(s.storage.managers contains Tezos.sender, Errors.Dex.not_manager); + require(s.storage.managers contains Tezos.get_sender(), Errors.Dex.not_manager); s.storage.token_metadata[params.token_id] := params } | _ -> unreachable(Unit) diff --git a/contracts/partials/factory/helpers.ligo b/contracts/partials/factory/helpers.ligo index fdb3b3f..36d3bed 100644 --- a/contracts/partials/factory/helpers.ligo +++ b/contracts/partials/factory/helpers.ligo @@ -51,7 +51,7 @@ var s : full_storage_t) : option(bytes) is block { - require(Tezos.sender = s.storage.dev_store.dev_address, Errors.Dex.not_developer); + require(Tezos.get_sender() = s.storage.dev_store.dev_address, Errors.Dex.not_developer); case s.init_func of [ | Some(_) -> failwith(Errors.Dex.func_set) | None -> skip @@ -84,18 +84,18 @@ function manage_startup_charges( var quipu_rewards : nat) : record [ ops: list(operation); rewards: nat ] is block { - if not (wl contains Tezos.sender) + if not (wl contains Tezos.get_sender()) then { const to_burn = price * burn_rate_f / Constants.burn_rate_precision; const to_factory = abs(price - to_burn); operations := typed_transfer( - Tezos.sender, - Tezos.self_address, + Tezos.get_sender(), + Tezos.get_self_address(), to_factory, Fa2(quipu_token) ) # operations; operations := typed_transfer( - Tezos.sender, + Tezos.get_sender(), Constants.burn_address, to_burn, Fa2(quipu_token) @@ -118,27 +118,32 @@ function form_pool_storage( const managers : set(address); const quipu_token : fa2_token_t; const a_lambdas : big_map(nat, bytes); - const t_lambdas : big_map(nat, bytes)) + const t_lambdas : big_map(nat, bytes); + const s_lambdas : big_map(nat, bytes)) : pool_f_storage_t is block { const default_token_id = 0n; - const pool = record [ + const pool: pool_t = (record [ initial_A_f = a_constant * Constants.a_precision; future_A_f = a_constant * Constants.a_precision; - initial_A_time = Tezos.now; - future_A_time = Tezos.now; + initial_A_time = Tezos.get_now(); + 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)); + ]; staker_accumulator = record [ accumulator_f = (map []: map(token_pool_idx_t, nat)); total_fees = (map []: map(token_pool_idx_t, nat)); total_staked = 0n; ]; total_supply = 0n; - ]; + ]: pool_t); - const pool_storage: storage_t = record[ - admin = Tezos.sender; + const pool_storage: storage_t = (record[ + admin = Tezos.get_sender(); default_referral = default_referral; managers = managers; pools_count = 1n; @@ -157,10 +162,10 @@ function form_pool_storage( referral_rewards = (big_map[]: big_map((address * token_t), nat)); stakers_balance = (big_map[]: big_map((address * pool_id_t), staker_info_t)); quipu_token = quipu_token; - factory_address = Tezos.self_address; + factory_address = Tezos.get_self_address(); started = False; - ]; - } with record [ + ]: storage_t); + } with (record [ storage = pool_storage; metadata = big_map[ "" -> 0x74657a6f732d73746f726167653a646578; @@ -169,4 +174,5 @@ function form_pool_storage( admin_lambdas = a_lambdas; dex_lambdas = (big_map[]: big_map(nat, bytes)); // too large for injection in one operation token_lambdas = t_lambdas; - ] \ No newline at end of file + strat_lambdas = s_lambdas; + ]: pool_f_storage_t) \ No newline at end of file diff --git a/contracts/partials/factory/lambdas.ligo b/contracts/partials/factory/lambdas.ligo index 86971e0..6dcd769 100644 --- a/contracts/partials/factory/lambdas.ligo +++ b/contracts/partials/factory/lambdas.ligo @@ -22,7 +22,7 @@ function add_pool( const result: tmp_tokens_map_t = Set.fold(get_tokens_from_param, params.input_tokens, default_tmp_tokens); const tokens : tokens_map_t = result.tokens; - const pool_key : bytes = pack_pool_key(Tezos.sender, tokens); + const pool_key : bytes = pack_pool_key(Tezos.get_sender(), tokens); check_pool(pool_key, s.storage.pool_to_address); function set_reserves( @@ -49,7 +49,8 @@ function add_pool( params.managers, s.storage.quipu_token, s.admin_lambdas, - s.token_lambdas + s.token_lambdas, + s.strat_lambdas ) ); const pool_address = deploy.1; diff --git a/contracts/partials/factory/methods.ligo b/contracts/partials/factory/methods.ligo index ecbaef4..9549f4a 100644 --- a/contracts/partials/factory/methods.ligo +++ b/contracts/partials/factory/methods.ligo @@ -20,17 +20,17 @@ function start_dex_func( ) ); const pool_address = unwrap( - s.storage.pool_to_address[pack_pool_key(Tezos.sender, tokens)], + s.storage.pool_to_address[pack_pool_key(Tezos.get_sender(), tokens)], Errors.Factory.pool_not_listed ); - const param = record [ + const param: invest_param_t = (record [ pool_id = 0n; shares = 1n; in_amounts = amounts; - deadline = Tezos.now + 300; - receiver = Some(Tezos.sender); + deadline = Tezos.get_now() + 300; + receiver = Some(Tezos.get_sender()); referral = (None: option(address)); - ]; + ]: invest_param_t); var operations: list(operation) := list[ set_lambd_dex(s.dex_lambdas, pool_address); unfreeze_dex(pool_address); @@ -41,11 +41,11 @@ function start_dex_func( const input : nat * nat) : list(operation) is block { - const token = unwrap(tokens[input.0], Errors.Dex.wrong_index); + const token: token_t = unwrap(tokens[input.0], Errors.Dex.wrong_index); case token of [ | Fa2(_) -> operations := concat_lists(operations, list[ typed_approve( - Tezos.self_address, + Tezos.get_self_address(), pool_address, 0n, token @@ -56,14 +56,14 @@ function start_dex_func( if input.1 > 0n then { operations := typed_approve( - Tezos.self_address, + Tezos.get_self_address(), pool_address, input.1, token ) # operations; operations := typed_transfer( - Tezos.sender, - Tezos.self_address, + Tezos.get_sender(), + Tezos.get_self_address(), input.1, token ) # operations; @@ -79,7 +79,7 @@ function claim_quipu( block { const operations = list[ typed_transfer( - Tezos.self_address, + Tezos.get_self_address(), s.storage.dev_store.dev_address, s.storage.quipu_rewards, Fa2(s.storage.quipu_token) @@ -93,16 +93,17 @@ function use_factory( var s : full_storage_t) : fact_return_t is block { - require(Tezos.sender = s.storage.dev_store.dev_address, Errors.Dex.not_developer); + require(Tezos.get_sender() = s.storage.dev_store.dev_address, Errors.Dex.not_developer); case params of [ - | Set_burn_rate(rate) -> if rate <= Constants.burn_rate_precision - then s.storage.burn_rate_f := rate - else failwith(Errors.Factory.burn_rate_overflow) - | Set_price(price) -> s.storage.init_price := price - | Set_whitelist(params) -> s.storage.whitelist := add_rem_candidate(params, s.storage.whitelist) - | _ -> skip + | Set_burn_rate(rate) -> if rate <= Constants.burn_rate_precision + then s.storage.burn_rate_f := rate + else failwith(Errors.Factory.burn_rate_overflow) + | Set_strategy_factory(params)-> s.storage.strategy_factory := add_rem_candidate(params, s.storage.strategy_factory) + | Set_price(price) -> s.storage.init_price := price + | Set_whitelist(params) -> s.storage.whitelist := add_rem_candidate(params, s.storage.whitelist) + | _ -> skip ] } with case params of [ - | Claim_rewards -> claim_quipu(s) - | _ -> (Constants.no_operations, s) + | Claim_rewards -> claim_quipu(s) + | _ -> (Constants.no_operations, s) ] diff --git a/contracts/partials/factory/storage.ligo b/contracts/partials/factory/storage.ligo index ab3708b..ffb2016 100644 --- a/contracts/partials/factory/storage.ligo +++ b/contracts/partials/factory/storage.ligo @@ -23,7 +23,7 @@ type pool_init_param_t is [@layout:comb] record [ tokens_info : map(token_pool_idx_t, token_prec_info_t); default_referral : address; managers : set(address); - fees : fees_storage_t + fees : fees_storage_t; ] type inner_store_t is [@layout:comb] record[ @@ -36,6 +36,7 @@ type inner_store_t is [@layout:comb] record[ quipu_token : fa2_token_t; quipu_rewards : nat; whitelist : set(address); + strategy_factory : set(address); ] type full_storage_t is [@layout:comb] record [ @@ -43,12 +44,14 @@ type full_storage_t is [@layout:comb] record [ admin_lambdas : big_map(nat, bytes); (* map with admin-related functions code *) dex_lambdas : big_map(nat, bytes); (* map with exchange-related functions code *) token_lambdas : big_map(nat, bytes); (* map with token-related functions code *) + strat_lambdas : big_map(nat, bytes); (* map with strategy-related functions code *) init_func : option(bytes); metadata : big_map(string, bytes); (* TZIP-16 metadata *) ] type use_factory_t is -| Set_whitelist of set_man_param_t +| Set_whitelist of set_cand_param_t +| Set_strategy_factory of set_cand_param_t | Set_burn_rate of nat | Set_price of nat | Claim_rewards of unit @@ -60,6 +63,8 @@ type fact_action_t is | Set_dev_function of set_lambda_func_t | Set_admin_function of set_lambda_func_t (* sets the admin specific function, is used before the whole system is launched *) +| Set_strategy_function of set_lambda_func_t +(* sets the strategy connectors functions, is used before the whole system is launched *) | Set_dex_function of set_lambda_func_t (* sets the dex specific function, is used before the whole system is launched *) | Set_token_function of set_lambda_func_t diff --git a/contracts/partials/factory/views.ligo b/contracts/partials/factory/views.ligo index 23ed6c8..bcec021 100644 --- a/contracts/partials/factory/views.ligo +++ b/contracts/partials/factory/views.ligo @@ -10,8 +10,16 @@ : address is s.storage.dev_store.dev_address +[@view] function is_registered_strategy( + const strategy : address; + const s : full_storage_t) + : bool is + check_strategy_factory(strategy, s.storage.strategy_factory) + + + [@view] function get_pool( - const params : record [ tokens:set(token_t); deployer:address ]; + const params : record[ tokens: set(token_t); deployer:address ]; const s : full_storage_t) : option(address) is block { diff --git a/contracts/partials/strategy/helpers.ligo b/contracts/partials/strategy/helpers.ligo new file mode 100644 index 0000000..9ef5fc8 --- /dev/null +++ b/contracts/partials/strategy/helpers.ligo @@ -0,0 +1,134 @@ +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 + unwrap( + (Tezos.get_entrypoint_opt("%update_token_state", strategy_address): option(contract(upd_strat_state_t))), + Errors.Strategy.no_update_state_entrypoint + ); + +[@inline] function get_update_token_info_entrypoint( + const strategy_address: address) + : contract(strat_upd_info_t) is + unwrap( + (Tezos.get_entrypoint_opt("%update_token_info", strategy_address): option(contract(strat_upd_info_t))), + Errors.Strategy.no_update_state_entrypoint + ); + +function check_strategy_pool_params( + const pool_id : nat; + const strategy: address): bool is + block { + const expected: strat_pool_data_t = record[ + pool_contract = Tezos.get_self_address(); + pool_id = pool_id + ]; + 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 + + + +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 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 diff --git a/contracts/partials/strategy/lambdas.ligo b/contracts/partials/strategy/lambdas.ligo new file mode 100644 index 0000000..42bde0f --- /dev/null +++ b/contracts/partials/strategy/lambdas.ligo @@ -0,0 +1,148 @@ +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) + : return_t is + block { + var operations: list(operation) := Constants.no_operations; + 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); + require(is_registered_strategy, Errors.Strategy.not_registered); + require(is_pool_params_correct, Errors.Strategy.wrong_params); + } with params.strategy_contract + | None -> params.strategy_contract + ]; + s.pools[params.pool_id] := pool; + } + | _ -> unreachable(Unit) + ] + } 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) + : return_t is + block { + var operations: list(operation) := Constants.no_operations; + case p of [ + | Rebalance(params) -> { + const pool : pool_t = unwrap(s.pools[params.pool_id], Errors.Dex.pool_not_listed); + function map_ids( + const acc : map(token_pool_idx_t, token_info_t); + 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 + ]; + } + | _ -> unreachable(Unit) + ] + } with (operations, s) diff --git a/contracts/partials/strategy/methods.ligo b/contracts/partials/strategy/methods.ligo new file mode 100644 index 0000000..366944e --- /dev/null +++ b/contracts/partials/strategy/methods.ligo @@ -0,0 +1,20 @@ +(* This methods called only by dev and modifies only `storage` property of full storage *) +[@inline] function call_strategy( + const p : strategy_action_t; + var s : full_storage_t) + : full_return_t is + block { + const dev_address = get_dev_address(s.storage); + 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 + ]; + + const lambda_bytes : bytes = unwrap(s.strat_lambdas[idx], Errors.Dex.unknown_func); + const func: strat_func_t = unwrap((Bytes.unpack(lambda_bytes) : option(strat_func_t)), Errors.Dex.wrong_use_function); + const (operations, storage) = func(p, s.storage); + } with (operations, s with record[ storage = storage ]) \ No newline at end of file diff --git a/contracts/partials/strategy/types.ligo b/contracts/partials/strategy/types.ligo new file mode 100644 index 0000000..da24658 --- /dev/null +++ b/contracts/partials/strategy/types.ligo @@ -0,0 +1,69 @@ +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; +] + +type conn_strategy_param is [@layout:comb] record [ + pool_id : pool_id_t; + 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_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 diff --git a/contracts/partials/utils.ligo b/contracts/partials/utils.ligo index 3797998..cfb36cb 100644 --- a/contracts/partials/utils.ligo +++ b/contracts/partials/utils.ligo @@ -145,7 +145,7 @@ ]; [@inline] function add_rem_candidate( - const params : set_man_param_t; + const params : set_cand_param_t; var whitelist : set(address)) : set(address) is Set.update(params.candidate, params.add, whitelist) @@ -170,7 +170,7 @@ [@inline] function check_deadline( const exp : timestamp) : unit is - require(exp >= Tezos.now, Errors.Dex.time_expired); + require(exp >= Tezos.get_now(), Errors.Dex.time_expired); function set_func_or_fail( const params : set_lambda_func_t; @@ -221,15 +221,16 @@ function get_token_by_id( #if FACTORY #if !INSIDE_DEX - require(Tezos.sender = s.storage.dev_store.dev_address, Errors.Dex.not_developer); + require(Tezos.get_sender() = s.storage.dev_store.dev_address, Errors.Dex.not_developer); #endif #else - require(Tezos.sender = s.storage.admin, Errors.Dex.not_contract_admin); + require(Tezos.get_sender() = s.storage.admin, Errors.Dex.not_contract_admin); #endif case f_type of [ | FAdmin -> s.admin_lambdas := set_func_or_fail(params, Constants.admin_func_count, s.admin_lambdas) | FDex -> s.dex_lambdas := set_func_or_fail(params, Constants.dex_func_count, s.dex_lambdas) | FToken -> s.token_lambdas := set_func_or_fail(params, Constants.token_func_count, s.token_lambdas) + | FStrat -> s.strat_lambdas := set_func_or_fail(params, Constants.strat_func_count, s.strat_lambdas) #if !INSIDE_DEX | FDev -> s.storage.dev_store.dev_lambdas := set_func_or_fail(params, Constants.dev_func_count, s.storage.dev_store.dev_lambdas) #else @@ -248,3 +249,16 @@ function get_tokens_from_param( } with result; +function check_strategy_factory( + const strategy : address; + const factories : set(address)) + : bool is + block { + function call_check_view( + const accumulator : bool; + const entry : address): bool is + accumulator or unwrap( + (Tezos.call_view("is_registered", strategy, entry): option(bool)), + Errors.Factory.no_strategy_factory + ) + } with Set.fold(call_check_view, factories, False) diff --git a/migrations/00_dex.ts b/migrations/00_dex.ts index 210c303..53b9564 100644 --- a/migrations/00_dex.ts +++ b/migrations/00_dex.ts @@ -15,6 +15,7 @@ import dex_lambdas_comp from "../build/lambdas/Dex_lambdas.json"; import dev_lambdas_comp from "../build/lambdas/Dev_lambdas.json"; import token_lambdas_comp from "../build/lambdas/Token_lambdas.json"; import admin_lambdas_comp from "../build/lambdas/Admin_lambdas.json"; +import strat_lambdas_comp from "../build/lambdas/Strategy_lambdas.json"; import { Dex } from "../test/Dex/API/dexAPI"; import { DevStorage } from "../test/Developer/API/storage"; import chalk from "chalk"; @@ -37,7 +38,6 @@ module.exports = async (tezos: TezosToolkit, network: NetworkLiteral) => { storage.storage.dev_store.dev_lambdas = await setupLambdasToStorage( dev_lambdas_comp ); - const contractAddress: TezosAddress = await migrate( tezos, config.outputDirectory, @@ -67,9 +67,16 @@ module.exports = async (tezos: TezosToolkit, network: NetworkLiteral) => { tezos, contractAddress, "Dex", - 8, + 5, dex_lambdas_comp ); + await setFunctionBatchCompilled( + tezos, + contractAddress, + "Strategy", + 8, + strat_lambdas_comp + ); console.log( `DEX (${chalk.bold.bgRed.underline("standalone")}) is ${chalk.green( "online" diff --git a/migrations/01_factory.ts b/migrations/01_factory.ts index 298300c..45aa214 100644 --- a/migrations/01_factory.ts +++ b/migrations/01_factory.ts @@ -9,6 +9,7 @@ import { } from "../utils/helpers"; import { validateAddress, validateContractAddress } from "@taquito/utils"; import dev_lambdas_comp from "../build/lambdas/Dev_lambdas.json"; +import strat_lambdas_comp from "../build/lambdas/Strategy_lambdas.json"; import { DexFactoryAPI as DexFactory } from "../test/Factory/API"; import chalk from "chalk"; import storage from "../storage/factory"; @@ -34,6 +35,7 @@ module.exports = async (tezos: TezosToolkit, network: NetworkLiteral) => { storage.storage.dev_store.dev_lambdas = await setupLambdasToStorage( dev_lambdas_comp ); + storage.strat_lambdas = await setupLambdasToStorage(strat_lambdas_comp); const contractAddress: TezosAddress = await migrate( tezos, config.outputDirectory, @@ -44,8 +46,6 @@ module.exports = async (tezos: TezosToolkit, network: NetworkLiteral) => { console.log( `Factory contract: ${chalk.bgYellow.bold.redBright(contractAddress)}` ); - const dex_f: DexFactory = await DexFactory.init(tezos, contractAddress); - await dex_f.setDevAddress(process.env.ADMIN_ADDRESS, tezos); console.log( `Factory is ${chalk.green( "online" diff --git a/migrations/02_factory_pools.ts b/migrations/02_factory_pools.ts index 6a3e709..b04e816 100644 --- a/migrations/02_factory_pools.ts +++ b/migrations/02_factory_pools.ts @@ -1,4 +1,4 @@ -import { MichelsonMap, TezosToolkit } from "@taquito/taquito"; +import { MichelsonMap, OpKind, TezosToolkit } from "@taquito/taquito"; import config from "../config"; import { FA12TokenType, @@ -6,19 +6,16 @@ import { NetworkLiteral, TezosAddress, } from "../utils/helpers"; -import { DexFactoryAPI as DexFactory } from "../test/Factory/API"; import factoryInfo from "../build/factory.json"; import pools from "../storage/pairConfig.json"; import { Token, TokenFA2, TokenFA12 } from "../test/Token"; import BigNumber from "bignumber.js"; import { confirmOperation } from "../utils/confirmation"; -const tokensAmount = new BigNumber("100000"); - module.exports = async (tezos: TezosToolkit, network: NetworkLiteral) => { - await new Promise((r) => setTimeout(r, 10000)); const factoryAddress: TezosAddress = factoryInfo.networks[network].factory; const factory = await tezos.contract.at(factoryAddress); + const sender_addr = await tezos.signer.publicKeyHash(); let poolData; for (const pair of pools) { console.log("Pool", pair.name); @@ -78,10 +75,10 @@ module.exports = async (tezos: TezosToolkit, network: NetworkLiteral) => { fees: pair.fees, }) .send(); - await confirmOperation(tezos, op.hash); + await op.confirmation(2); console.log("Add_pool ", op.hash); op = await factory.methods.start_dex(inputs).send(); - await confirmOperation(tezos, op.hash); + await op.confirmation(2); console.log("Start_dex ", op.hash); for (const index in poolData) { const value = pair.tokensInfo[index]; @@ -102,6 +99,25 @@ module.exports = async (tezos: TezosToolkit, network: NetworkLiteral) => { " disapproved" ); } + const dex_address: TezosAddress = await factory.contractViews + .get_pool({ + tokens: pair.tokensInfo.map((token) => token.token), + deployer: sender_addr, + }) + .executeView({ viewCaller: sender_addr }); + const dex = await tezos.contract.at(dex_address); + op = await dex.methods.set_admin(process.env.ADMIN_ADDRESS).send(); + await op.confirmation(2); + console.log("Admin set ", process.env.ADMIN_ADDRESS); console.log(`Dex of ${pair.name} started`); } + let operation = await factory.methods + .set_whitelist(false, sender_addr) + .send(); + await operation.confirmation(2); + console.log("Removed from whitelist ", sender_addr); + operation = await factory.methods + .set_dev_address(process.env.ADMIN_ADDRESS) + .send(); + await operation.confirmation(2); }; diff --git a/package.json b/package.json index b5a7f69..e87854d 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,11 @@ "bugs": "https://github.com/madfish-solutions/quipuswap-stable-core/issues", "description": "Token2Token DEX for equal-price tokens based on StableSwap algos on top of Tezos. This package installs dependencies for testing and deployment purposes", "author": "Illia Likhoshva (https://www.madfish.solutions/)", + "license": "MIT", "private": true, "dependencies": { - "@taquito/signer": "^11.1.0", - "@taquito/taquito": "^11.1.0", + "@taquito/signer": "^14.0.0", + "@taquito/taquito": "^14.0.0", "@types/jest": "^27.0.2", "chalk": "<5.0.0", "commander": "^8.3.0", @@ -29,33 +30,46 @@ "help": "yarn cli --help", "start-sandbox": "yarn cli sandbox --up", "stop-sandbox": "yarn cli sandbox --down", - "setup-pre-compiled": "yarn cli compile -F tz -c dex4factory", - "compile": "yarn compile-contract -c dex && yarn compile-lambda-all && yarn compile-factory", "compile-contract": "yarn cli compile -F json", - "compile-lambda": "yarn cli compile-lambda", - "compile-lambda-all": "yarn compile-lambda-admin && yarn compile-lambda-dex && yarn compile-lambda-dev && yarn compile-lambda-token", - "compile-lambda-standalone": "yarn -s compile-lambda -C ./contracts/main/dex.ligo", - "compile-lambda-dex": "yarn -s compile-lambda-standalone -T Dex -J ./test/lambdas/Dex_lambdas.json", - "compile-lambda-dev": "yarn -s compile-lambda-standalone -T Dev -J ./test/lambdas/Dev_lambdas.json", - "compile-lambda-token": " yarn -s compile-lambda-standalone -T Token -J ./test/lambdas/Token_lambdas.json", - "compile-lambda-admin": "yarn -s compile-lambda-standalone -T Admin -J ./test/lambdas/Admin_lambdas.json", - "compile-factory": "yarn setup-pre-compiled && yarn compile-lambda-all-factory && yarn compile-contract -c factory && yarn cli compile-factory-lambda -F add_pool", - "compile-lambda-all-factory": "yarn compile-lambda-admin-factory && yarn compile-lambda-dex-factory && yarn compile-lambda-token-factory", - "compile-dex-lambda-factory": "yarn -s compile-lambda -C ./contracts/main/dex4factory.ligo", - "compile-lambda-dex-factory": "yarn -s compile-dex-lambda-factory -T Dex -J ./test/lambdas/Dex_lambdas.json", - "compile-lambda-token-factory": "yarn -s compile-dex-lambda-factory -T Token -J ./test/lambdas/Token_lambdas.json", - "compile-lambda-admin-factory": "yarn -s compile-dex-lambda-factory -T Admin -J ./test/lambdas/Admin_lambdas.json", - "compile-for-test": "yarn compile-contract -c dex_test && yarn compile-lambda-all-test && yarn compile-factory", - "compile-lambda-test": "yarn -s compile-lambda -C ./contracts/main/dex_test.ligo", - "compile-lambda-all-test": "yarn compile-lambda-admin-test && yarn compile-lambda-dex-test && yarn compile-lambda-dev-test && yarn compile-lambda-token-test", - "compile-lambda-dex-test": "yarn -s compile-lambda-test -T Dex -J ./test/lambdas/Dex_lambdas.json", - "compile-lambda-dev-test": "yarn -s compile-lambda-test -T Dev -J ./test/lambdas/Dev_lambdas.json", - "compile-lambda-token-test": "yarn -s compile-lambda-test -T Token -J ./test/lambdas/Token_lambdas.json", - "compile-lambda-admin-test": "yarn -s compile-lambda-test -T Admin -J ./test/lambdas/Admin_lambdas.json", - "recompile": "yarn clear-build && yarn compile-contract && yarn compile-lambda-all && yarn compile-factory", + + "compile-lambda-standalone": "yarn -s cli compile-lambda -C ./contracts/main/dex.ligo", + "compile-lambda-dex": "yarn -s compile-lambda-standalone -J ./contract_lambdas/Dex_lambdas.json", + "compile-lambda-dev": "yarn -s compile-lambda-standalone -J ./contract_lambdas/Dev_lambdas.json", + "compile-lambda-token": " yarn -s compile-lambda-standalone -J ./contract_lambdas/Token_lambdas.json", + "compile-lambda-admin": "yarn -s compile-lambda-standalone -J ./contract_lambdas/Admin_lambdas.json", + "compile-lambda-strategy": " yarn -s compile-lambda-standalone -J ./contract_lambdas/Strategy_lambdas.json", + + "compile-lambda-factory": "yarn -s cli compile-lambda -C ./contracts/main/dex4factory.ligo", + "compile-lambda-dex-factory": "yarn -s compile-lambda-factory -J ./contract_lambdas/Dex_lambdas.json", + "compile-lambda-token-factory": "yarn -s compile-lambda-factory -J ./contract_lambdas/Token_lambdas.json", + "compile-lambda-admin-factory": "yarn -s compile-lambda-factory -J ./contract_lambdas/Admin_lambdas.json", + "compile-lambda-strategy-factory": " yarn -s compile-lambda-factory -J ./contract_lambdas/Strategy_lambdas.json", + + "compile-lambda-test": "yarn -s cli compile-lambda -C ./contracts/main/dex_test.ligo", + "compile-lambda-dex-test": "yarn -s compile-lambda-test -J ./contract_lambdas/Dex_lambdas.json", + "compile-lambda-dev-test": "yarn -s compile-lambda-test -J ./contract_lambdas/Dev_lambdas.json", + "compile-lambda-token-test": "yarn -s compile-lambda-test -J ./contract_lambdas/Token_lambdas.json", + "compile-lambda-admin-test": "yarn -s compile-lambda-test -J ./contract_lambdas/Admin_lambdas.json", + "compile-lambda-strategy-test": " yarn -s compile-lambda-test -J ./contract_lambdas/Strategy_lambdas.json", + + "precompile-dex": "yarn compile-lambda-standalone", + "compile-dex": "yarn compile-contract -c dex", + + "precompile-factory": "yarn cli compile -F tz -c dex4factory && yarn compile-lambda-factory && yarn cli compile-factory-lambda -F add_pool", + "compile-factory": "yarn compile-contract -c factory", + + "compile": "yarn compile-dex && yarn compile-factory", + "recompile": "yarn clear-build && yarn compile", + + "precompile-for-test": "yarn compile-lambda-test", + "compile-for-test": "yarn compile-contract -c dex_test && yarn compile-factory", + "migrate": "yarn cli migrate", "test": "jest", - "compile-n-test": "yarn compile-for-test && yarn start-sandbox && sleep 10 && yarn test && yarn stop-sandbox", + + "precompile-n-test": "yarn compile-for-test && yarn start-sandbox && sleep 10", + "compile-n-test": "yarn test", + "postcompile-n-test": "yarn stop-sandbox", "clear-build": "rm -rf ./build", "lint": "eslint --ext .ts .", "fix": "eslint --ext .ts --fix ." diff --git a/scenario/constants.py b/scenario/constants.py index d2b7df7..3d677b5 100644 --- a/scenario/constants.py +++ b/scenario/constants.py @@ -24,6 +24,7 @@ factory = "KT1LzyPS8rN375tC31WPAVHaQ4HyBvTSLwBu" quipu_token = "KT1LzyPS8rN375tC31WPAVHaQ4HyBvTSLwBu" price_feed = "KT1Qf46j2x37sAN4t2MKRQRVt9gc4FZ5duMs" +strategy_address = "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" fee_collector = "tz1MDhGTfMQjtMYFXeasKzRWzkQKPtXEkSEw" dummy_sig = "sigY3oZknG7z2N9bj5aWVtdZBakTviKnwbSYTecbbT2gwQDrnLRNhP5KDcLroggq71AjXWkx27nSLfS8rodS4DYn14FyueS5" diff --git a/scenario/generate_graphs.py b/scenario/generate_graphs.py index 42a5cf2..128bd45 100644 --- a/scenario/generate_graphs.py +++ b/scenario/generate_graphs.py @@ -6,7 +6,7 @@ from helpers import * from pytezos import ContractInterface, pytezos, MichelsonRuntimeError -from initial_storage import admin_lambdas, dex_lambdas, token_lambdas +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, start_lambdas import matplotlib.pyplot as plt import matplotlib.ticker @@ -40,6 +40,7 @@ def __init__(cls): storage = cls.dex.storage.dummy() storage["token_lambdas"] = token_lambdas storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas storage["admin_lambdas"] = admin_lambdas storage["storage"]["admin"] = admin cls.init_storage = storage diff --git a/scenario/initial_storage.py b/scenario/initial_storage.py index abc39f8..0a425eb 100644 --- a/scenario/initial_storage.py +++ b/scenario/initial_storage.py @@ -1,5 +1,5 @@ import json - +import os def parse_lambdas(path): lambdas = {} entries = json.load(open(path)) @@ -9,11 +9,12 @@ def parse_lambdas(path): lbytes = args[0]["bytes"] lambdas[i] = lbytes - assert int(args[1]["int"]) == i + assert int(args[1]["int"]) == i 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") \ No newline at end of file +dev_lambdas = parse_lambdas("./build/lambdas/Dev_lambdas.json") +strat_lambdas = parse_lambdas("./build/lambdas/Strategy_lambdas.json") \ No newline at end of file diff --git a/scenario/requirements.txt b/scenario/requirements.txt new file mode 100644 index 0000000..35a49a2 --- /dev/null +++ b/scenario/requirements.txt @@ -0,0 +1,2 @@ +pytezos==3.7.2 +pytest==7.2.0 \ No newline at end of file diff --git a/scenario/test_admin.py b/scenario/test_admin.py index 11b0043..a30ac02 100644 --- a/scenario/test_admin.py +++ b/scenario/test_admin.py @@ -7,7 +7,7 @@ from helpers import * from pytezos import ContractInterface, MichelsonRuntimeError -from initial_storage import admin_lambdas, dex_lambdas, token_lambdas +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, strat_lambdas class StableSwapTest(TestCase): @@ -23,6 +23,7 @@ def setUpClass(cls): storage = cls.dex.storage.dummy() storage["token_lambdas"] = token_lambdas storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas storage["admin_lambdas"] = admin_lambdas storage["storage"]["admin"] = admin diff --git a/scenario/test_divests.py b/scenario/test_divests.py index bff08ce..43361a8 100644 --- a/scenario/test_divests.py +++ b/scenario/test_divests.py @@ -8,7 +8,7 @@ from helpers import * from pytezos import ContractInterface, MichelsonRuntimeError -from initial_storage import admin_lambdas, dex_lambdas, token_lambdas +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, strat_lambdas class DivestsTest(TestCase): @@ -24,6 +24,7 @@ def setUpClass(cls): storage = cls.dex.storage.dummy() storage["token_lambdas"] = token_lambdas storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas storage["admin_lambdas"] = admin_lambdas storage["storage"]["admin"] = admin diff --git a/scenario/test_fees.py b/scenario/test_fees.py index 0abbe65..dc0bfc4 100644 --- a/scenario/test_fees.py +++ b/scenario/test_fees.py @@ -7,7 +7,7 @@ from helpers import * from pytezos import ContractInterface, MichelsonRuntimeError -from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, dev_lambdas +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, dev_lambdas, strat_lambdas class StableSwapTest(TestCase): @@ -23,6 +23,7 @@ def setUpClass(cls): storage = cls.dex.storage.dummy() storage["token_lambdas"] = token_lambdas storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas storage["admin_lambdas"] = admin_lambdas storage["storage"]["admin"] = admin storage["storage"]["dev_store"]["dev_address"] = dev diff --git a/scenario/test_staking.py b/scenario/test_staking.py index 2469fc6..5b90ff5 100644 --- a/scenario/test_staking.py +++ b/scenario/test_staking.py @@ -8,7 +8,7 @@ from helpers import * from pytezos import ContractInterface, MichelsonRuntimeError -from initial_storage import admin_lambdas, dex_lambdas, token_lambdas +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, strat_lambdas class StableStakingTest(TestCase): @@ -24,6 +24,7 @@ def setUpClass(cls): storage = cls.dex.storage.dummy() storage["token_lambdas"] = token_lambdas storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas storage["admin_lambdas"] = admin_lambdas storage["storage"]["admin"] = admin storage["storage"]["quipu_token"] = { diff --git a/scenario/test_strategy.py b/scenario/test_strategy.py new file mode 100644 index 0000000..a5aaf79 --- /dev/null +++ b/scenario/test_strategy.py @@ -0,0 +1,259 @@ + +from unittest import TestCase +import pytest +import json +from pprint import pprint +from constants import * +from decimal import Decimal + +from helpers import * + +from pytezos import ContractInterface, MichelsonRuntimeError +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, strat_lambdas, dev_lambdas + +class DexStrategyTest(TestCase): + + @classmethod + def setUpClass(cls): + cls.maxDiff = None + + text = open("./build/dex.json").read() + code = json.loads(text) + + cls.dex = ContractInterface.from_micheline(code["michelson"]) + + storage = cls.dex.storage.dummy() + storage["token_lambdas"] = token_lambdas + storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas + storage["admin_lambdas"] = admin_lambdas + storage["storage"]["admin"] = admin + storage["storage"]["dev_store"]["dev_address"] = dev + storage["storage"]["dev_store"]["dev_lambdas"] = dev_lambdas + storage["storage"]["quipu_token"] = { + "token_address" : quipu_token, + "token_id": 0, + } + + 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") + 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) + + # connect new strategy address + connect = self.dex.connect_strategy(0, strategy_address) + res = chain.execute(connect, sender=dev) + + conneced_strategy = res.storage['storage']['pools'][0]['strategy']['strat_contract'] + self.assertEqual(conneced_strategy, strategy_address) + + # disconect strategy + connect = self.dex.connect_strategy(0, None) + res = chain.execute(connect, sender=dev) + conneced_strategy = res.storage['storage']['pools'][0]['strategy']['strat_contract'] + self.assertIsNone(conneced_strategy) + + def test_connect_token_to_strategy(self): + pytest.skip("Intercontract calls and changes") + 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 + + connect = self.dex.connect_strategy(pool_id, strategy_address) + res = chain.execute(connect, sender=dev) + + conneced_strategy = res.storage['storage']['pools'][0]['strategy']['strat_contract'] + self.assertEqual(conneced_strategy, strategy_address) + 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 + }) + conn_tok_strat = self.dex.connect_token_strategy( + pool_id, + token_pool_id, + lending_pool_id + ) + res = chain.execute(conn_tok_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": True, + **config + }) + + def test_manual_rebalance(self): + pytest.skip("Intercontract calls and changes") + 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 + + connect = self.dex.connect_strategy(pool_id, strategy_address) + res = chain.execute(connect, sender=dev) + + conneced_strategy = res.storage['storage']['pools'][0]['strategy']['strat_contract'] + self.assertEqual(conneced_strategy, strategy_address) + 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 + }) + conn_tok_strat = self.dex.connect_token_strategy( + pool_id, + token_pool_id, + lending_pool_id + ) + res = chain.execute(conn_tok_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": True, + **config + }) + rebalance = self.dex.rebalance(pool_id, rates.keys()) + res = chain.execute(rebalance, sender=dev) + for token_id in rates.keys(): + token_config = res.storage['storage']['pools'][pool_id]['strategy']['configuration'][token_id] + token_reserves = res.storage['storage']['pools'][pool_id]['tokens_info'][token_id]['reserves']; + self.assertAlmostEqual(token_config["strategy_reserves"], + token_reserves * rates[token_id]['des_reserves_rate_f'] / Decimal("1e18")) \ No newline at end of file diff --git a/scenario/test_swap.py b/scenario/test_swap.py index 73fd49c..dc1963b 100644 --- a/scenario/test_swap.py +++ b/scenario/test_swap.py @@ -7,7 +7,7 @@ from helpers import * from pytezos import ContractInterface, MichelsonRuntimeError -from initial_storage import admin_lambdas, dex_lambdas, token_lambdas +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, strat_lambdas class StableSwapTest(TestCase): @@ -23,6 +23,7 @@ def setUpClass(cls): storage = cls.dex.storage.dummy() storage["token_lambdas"] = token_lambdas storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas storage["admin_lambdas"] = admin_lambdas storage["storage"]["admin"] = admin diff --git a/scenario/test_token_to_token_transfer.py b/scenario/test_token_to_token_transfer.py index c398b2c..67bf744 100644 --- a/scenario/test_token_to_token_transfer.py +++ b/scenario/test_token_to_token_transfer.py @@ -8,7 +8,7 @@ from pytezos import ContractInterface, pytezos, MichelsonRuntimeError from pytezos.context.mixin import ExecutionContext -from initial_storage import admin_lambdas, dex_lambdas, token_lambdas +from initial_storage import admin_lambdas, dex_lambdas, token_lambdas, strat_lambdas pair = { "token_a_type" : { @@ -39,6 +39,7 @@ def setUpClass(cls): storage = cls.dex.storage.dummy() storage["token_lambdas"] = token_lambdas storage["dex_lambdas"] = dex_lambdas + storage["strat_lambdas"] = strat_lambdas storage["admin_lambdas"] = admin_lambdas storage["storage"]["admin"] = admin cls.init_storage = storage diff --git a/scripts/commands/compile/index.ts b/scripts/commands/compile/index.ts index b01615d..a6d37b6 100644 --- a/scripts/commands/compile/index.ts +++ b/scripts/commands/compile/index.ts @@ -1,6 +1,7 @@ import { Command } from "commander"; import { compile, compileFactoryLambda, compileLambdas } from "./utils"; import config from "../../../config"; +import { LambdaType } from "../../../utils/helpers"; export const addCompileCommand = (program: Command) => { program @@ -35,15 +36,14 @@ export const addCompileLambdaCommand = (program: Command) => { program .command("compile-lambda") .description("compile lambdas for the specified contract") - .requiredOption("-T, --type ", "Type of contracts lambdas") - .requiredOption( - "-J, --json ", - "input file relative path (with lambdas indexes and names)" - ) .requiredOption( "-C, --contract ", "input file realtive path (with lambdas Ligo code)" ) + .option( + "-J, --json ", + "input file relative path (with lambdas indexes and names)" + ) .option("-d, --docker", "Run compiler in Docker", config.dockerizedLigo) .option( "--no-docker", @@ -51,9 +51,10 @@ export const addCompileLambdaCommand = (program: Command) => { !config.dockerizedLigo ) .showHelpAfterError(true) - .action(async (argv) => { - compileLambdas(argv.json, argv.contract, argv.docker, argv.type); - }); + .action( + async (argv: { json?: string; contract: string; docker: boolean }) => + compileLambdas(argv.contract, argv.docker, argv.json) + ); }; export const addCompileFactoryLambda = (program: Command) => { diff --git a/scripts/commands/compile/utils.ts b/scripts/commands/compile/utils.ts index acc5b20..f3af552 100644 --- a/scripts/commands/compile/utils.ts +++ b/scripts/commands/compile/utils.ts @@ -1,4 +1,4 @@ -import { getLigo } from "../../../utils/helpers"; +import { getLigo, LambdaType } from "../../../utils/helpers"; import config from "../../../config"; import fs from "fs"; import path from "path"; @@ -96,11 +96,12 @@ const _compileFile = async ( "-e", "main", "--protocol", - "ithaca" + "lima" ); if (format === "json") args.push("--michelson-format", "json"); console.debug(`\t🔥 Compiling with LIGO (${ligoVersion})...`); + console.debug(args.reduce((p, c) => p + " " + c, "")); const ligo = spawn(ligo_executable, args, {}); ligo.on("close", async () => { @@ -185,25 +186,24 @@ export const compile = async (options) => { } }; +function getLambdasFiles() { + return fs + .readdirSync(config.lambdasDir) + .filter((file) => file.endsWith(".json")) + .map((file) => path.join(config.lambdasDir, file)); +} + // Run LIGO compiler export const compileLambdas = async ( - json: string, contract: string, isDockerizedLigo = config.dockerizedLigo, - type: "Dex" | "Token" | "Permit" | "Admin" | "Dev" + json?: string ) => { - console.log(`Compiling ${contract} contract lambdas of ${type} type...\n`); - const test_path = contract.toLowerCase().includes("test"); const factory_path = contract.toLowerCase().includes("factory"); const ligo = isDockerizedLigo ? `docker run -v $PWD:$PWD --rm -i -w $PWD ligolang/ligo:${config.ligoVersion}` : config.ligoLocalPath; - const pwd = execSync("echo $PWD").toString(); - const lambdas = JSON.parse( - fs.readFileSync(`${pwd.slice(0, pwd.length - 1)}/${json}`).toString() - ); - const res = []; const version = !isDockerizedLigo ? execSync(`${ligo} version -version`).toString() : config.ligoVersion; @@ -215,60 +215,90 @@ export const compileLambdas = async ( ligo_command = "compile expression"; } const init_file = `$PWD/${contract}`; - try { - for (const lambda of lambdas) { - let func; - if (factory_path) { - if (lambda.name == "add_pool" && factory_path) continue; - func = `Bytes.pack(${lambda.name})`; - } else { - func = `Set_${type.toLowerCase()}_function(record [index=${ - lambda.index - }n; func=Bytes.pack(${lambda.name})])`; - } - const params = `'${func}' --michelson-format json --init-file ${init_file} --protocol ithaca`; - const command = `${ligo} ${ligo_command} ${config.preferredLigoFlavor} ${params}`; - const michelson = execSync(command, { maxBuffer: 1024 * 500 }).toString(); - const bytes = factory_path - ? { - prim: "Pair", - args: [ - { bytes: JSON.parse(michelson).bytes }, - { int: lambda.index.toString() }, - ], - } - : JSON.parse(michelson).args[0].args[0].args[0]; - res.push(bytes); + const lambdaFiles = json ? [json] : getLambdasFiles(); + const queue: { file: string; func: string; index: number; type: string }[] = + []; + for (const file of lambdaFiles) { + const type = file + .slice(file.lastIndexOf("/") + 1, file.length) + .split("_")[0]; - console.log( - lambda.index + - 1 + - "." + - " ".repeat(4 - (lambda.index + 1).toString().length) + - lambda.name + - " ".repeat(21 - lambda.name.length) + - " successfully compiled." - ); - } - let out_path = "/lambdas"; - if (test_path) { - out_path += "/test"; - } - if (factory_path) { - out_path += "/factory"; - } - if (!fs.existsSync(`${config.outputDirectory + out_path}`)) { - fs.mkdirSync(`${config.outputDirectory + out_path}`, { recursive: true }); + const lambdas = JSON.parse(fs.readFileSync(file).toString()); + for (const lambda of lambdas) { + if ( + factory_path && + (lambda.name == "add_pool" || + lambda.name == "set_strategy_factory" || + type.toLowerCase() == "dev") + ) + continue; + + const func = `Bytes.pack(${lambda.name})`; + queue.push({ file, func, index: lambda.index, type }); } - const json_file_path = json.split("/"); - const file_name = json_file_path[json_file_path.length - 1]; - const save_path = `${config.outputDirectory + out_path}/${file_name}`; - fs.writeFileSync(save_path, JSON.stringify(res)); - console.log(`Saved to ${save_path}`); + } + const funcs = queue.map((q) => q.func).join(";"); + const types: string = [ + ...queue.reduce((set, q) => set.add(q.type), new Set()), + ].join(","); + console.log( + `Compiling ${contract} contract lambdas of ${types} type${types.includes(",") ? "s" : "" + }...\n` + ); + let michelson: string; + try { + const params = `--michelson-format json --init-file ${init_file} --protocol lima`; + + const command = `${ligo} ${ligo_command} ${config.preferredLigoFlavor} 'list [${funcs}]' ${params}`; + michelson = execSync(command, { + maxBuffer: 2048 * 2048, + }).toString(); } catch (e) { console.error(e); + throw e; + } + console.log("Compiled successfully"); + const compiledBytesMap = JSON.parse(michelson).map( + (comp_res: { bytes: string }, idx: number) => { + const file = queue[idx].file.slice( + queue[idx].file.lastIndexOf("/") + 1, + queue[idx].file.length + ); + return { ...queue[idx], file, bytes: comp_res.bytes }; + } + ); + const outputs = new Map(); + for (const entry of compiledBytesMap) { + const bytes = { + prim: "Pair", + args: [{ bytes: entry.bytes }, { int: entry.index.toString() }], + }; + if (outputs.has(entry.file)) + outputs.set(entry.file, [...outputs.get(entry.file), bytes]); + else outputs.set(entry.file, [bytes]); } + outputs.forEach((val, filename) => { + try { + let out_path = "/lambdas"; + if (test_path) { + out_path += "/test"; + } + if (factory_path) { + out_path += "/factory"; + } + if (!fs.existsSync(`${config.outputDirectory + out_path}`)) { + fs.mkdirSync(`${config.outputDirectory + out_path}`, { + recursive: true, + }); + } + const save_path = `${config.outputDirectory + out_path}/${filename}`; + fs.writeFileSync(save_path, JSON.stringify(val)); + console.log(`Saved to ${save_path}`); + } catch (e) { + console.error(e); + } + }); }; export const compileFactoryLambda = ( @@ -292,7 +322,7 @@ export const compileFactoryLambda = ( const init_file = `$PWD/${config.contractsDirectory}/factory.ligo`; try { const func = `Bytes.pack(${lambda})`; - const params = `'${func}' --michelson-format json --init-file ${init_file} --protocol ithaca`; + const params = `'${func}' --michelson-format json --init-file ${init_file} --protocol lima`; const command = `${ligo} ${ligo_command} ${config.preferredLigoFlavor} ${params}`; const michelson = execSync(command, { maxBuffer: 1024 * 1000 }).toString(); console.log(lambda + " successfully compiled."); diff --git a/scripts/commands/migrate/utils.ts b/scripts/commands/migrate/utils.ts index 2d7e5fd..50d5c15 100644 --- a/scripts/commands/migrate/utils.ts +++ b/scripts/commands/migrate/utils.ts @@ -66,7 +66,7 @@ export async function migrate( .catch((e) => { throw e; }); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); artifacts.networks[network] = { [contract]: operation.contractAddress, }; diff --git a/scripts/commands/sandbox/types.ts b/scripts/commands/sandbox/types.ts index 3acb369..bb420df 100644 --- a/scripts/commands/sandbox/types.ts +++ b/scripts/commands/sandbox/types.ts @@ -28,6 +28,7 @@ export enum TezosProtocols { HANGZHOU = "hangzhou", ITHACA = "ithaca", JACARTA = "jacarta", + KATHMANDU = "kathmandu", } export declare type FlextesaTezosProtocols = { diff --git a/scripts/commands/sandbox/utils.ts b/scripts/commands/sandbox/utils.ts index 995eed9..a6466b0 100644 --- a/scripts/commands/sandbox/utils.ts +++ b/scripts/commands/sandbox/utils.ts @@ -49,6 +49,11 @@ export const flextesaProtocols: FlextesaTezosProtocols = { prefix: "013-PtJakart", kind: "Jacarta", }, + [TezosProtocols.KATHMANDU]: { + hash: "PtKathmankSpLLDALzWw7CGD2j2MtyveTwboEYokqUCP4a1LxMg", + prefix: "014-PtKathma", + kind: "Kathmandu", + }, }; export async function useSandbox(options: { up?: boolean; down?: boolean }) { @@ -120,12 +125,12 @@ export const createProtocolParams = ( }; // Flextesa image -const FLEXTESA_IMAGE = "oxheadalpha/flextesa:latest"; +const FLEXTESA_IMAGE = "oxheadalpha/flextesa:20221026"; // Name for the running Docker image export const POD_NAME = "flextesa-sandbox"; -const defaultProtocol = TezosProtocols.ITHACA; +const defaultProtocol = TezosProtocols.KATHMANDU; const defaultOptions: FlextesaOptions = config.networks.sandbox; export const startFlextesa = async ( @@ -138,8 +143,11 @@ export const startFlextesa = async ( const options = Object.assign({}, defaultOptions, _options); // Localhost is not a valid host for Docker - const host = options.host.includes("localhost") ? "0.0.0.0" : options.host; - const port = options.port; + const host = + options.host.includes("localhost") || options.host.includes("127.0.0.1") + ? "0.0.0.0" + : options.host; + const port = options.port || "20000"; // Protocol "validity" checks const protocol = @@ -157,7 +165,7 @@ export const startFlextesa = async ( "--name", POD_NAME, "-p", - host + ":" + port + ":20000", + port + ":20000", "--env", "flextesa_node_cors_origin=*", FLEXTESA_IMAGE, diff --git a/storage/dex.ts b/storage/dex.ts index ce42d70..aee2850 100644 --- a/storage/dex.ts +++ b/storage/dex.ts @@ -58,6 +58,7 @@ const storage: DexStorage = { admin_lambdas: new MichelsonMap(), dex_lambdas: new MichelsonMap(), token_lambdas: new MichelsonMap(), + strat_lambdas: new MichelsonMap(), }; export default storage; diff --git a/storage/factory.ts b/storage/factory.ts index c216526..c3d94e7 100644 --- a/storage/factory.ts +++ b/storage/factory.ts @@ -47,10 +47,12 @@ const factoryDefaultStorage: FactoryStorage = { quipu_rewards: new BigNumber("0"), whitelist: [] as TezosAddress[], deployers: new MichelsonMap(), + strategy_factory: "tz1ZZZZZZZZZZZZZZZZZZZZZZZZZZZZNkiRg", } as InnerFactoryStore, admin_lambdas: new MichelsonMap(), dex_lambdas: new MichelsonMap(), token_lambdas: new MichelsonMap(), + strat_lambdas: new MichelsonMap(), metadata: metadata, }; diff --git a/test/00_Dex.test.ts b/test/00_Dex.test.ts index c06ce92..8fbf405 100644 --- a/test/00_Dex.test.ts +++ b/test/00_Dex.test.ts @@ -18,6 +18,7 @@ const { decimals, a_const, accounts, zero_amount, swap_routes, dev_fee } = import { AmountsMap, IndexMap, TokensMap } from "./utils/types"; import { TokenFA12, TokenFA2 } from "./Token"; import { defaultTokenId } from "./Token/token"; +import { Contract } from "@taquito/taquito"; describe("00. Standalone Dex", () => { const aliceAddress: TezosAddress = accounts.alice.pkh; @@ -34,7 +35,6 @@ describe("00. Standalone Dex", () => { let dex: API.DexAPI; let quipuToken: TokenFA2; - let lambdaContractAddress: TezosAddress; const { before: TInit, @@ -42,6 +42,7 @@ describe("00. Standalone Dex", () => { pools: TPool, rewards: TReward, views: TView, + strategy: TStrategy, } = DexTests; // Contract will be deployed before every single test, to make sure we @@ -49,8 +50,7 @@ describe("00. Standalone Dex", () => { beforeAll( async () => - ({ dex, tokens, quipuToken, lambdaContractAddress } = - await TInit.setupDexEnvironment(Tezos)) + ({ dex, tokens, quipuToken } = await TInit.setupDexEnvironment(Tezos)) ); describe("1. Testing Admin endpoints", () => { @@ -58,18 +58,13 @@ describe("00. Standalone Dex", () => { it( "should fail if not admin try to set admin", async () => - await failCase( - "bob", - async () => await dex.setAdmin(new_admin, Tezos), - "not-contract-admin" - ), + failCase("bob", dex.setAdmin(new_admin), "not-contract-admin"), 10000 ); it( "should change admin", - async () => - await TMng.setAdminSuccessCase(dex, "alice", new_admin, Tezos), + async () => TMng.setAdminSuccessCase(dex, "alice", new_admin, Tezos), 50000 ); }); @@ -80,7 +75,7 @@ describe("00. Standalone Dex", () => { async () => await failCase( "bob", - async () => dex.setDevAddress(new_dev, Tezos), + async () => dex.setDevAddress(new_dev), "not-developer" ), 10000 @@ -89,24 +84,19 @@ describe("00. Standalone Dex", () => { it( "should fail if not dev try to set fee", async () => - await failCase( - "bob", - async () => await dex.setDevFee(dev_fee, Tezos), - "not-developer" - ), + failCase("bob", async () => dex.setDevFee(dev_fee), "not-developer"), 20000 ); it( "should change dev address", - async () => - await TMng.setDevAddrSuccessCase(dex, "eve", new_dev, Tezos), + async () => TMng.setDevAddrSuccessCase(dex, "eve", new_dev, Tezos), 20000 ); it( "should change dev fee", - async () => await TMng.setDevFeeSuccessCase(dex, "bob", dev_fee, Tezos), + async () => TMng.setDevFeeSuccessCase(dex, "bob", dev_fee, Tezos), 20000 ); }); @@ -115,9 +105,9 @@ describe("00. Standalone Dex", () => { it( "should fail if not admin try set manager", async () => - await failCase( + failCase( "bob", - async () => dex.addRemManager(true, manager, Tezos), + dex.addRemManager(true, manager), "not-contract-admin" ), 10000 @@ -154,9 +144,9 @@ describe("00. Standalone Dex", () => { it( "should fail if not admin try change default referral", async () => - await failCase( + failCase( "bob", - async () => dex.setDefaultReferral(aliceAddress, Tezos), + dex.setDefaultReferral(aliceAddress), "not-contract-admin" ), 10000 @@ -184,9 +174,9 @@ describe("00. Standalone Dex", () => { it( "should fail if not admin try to add pool", async () => - await failCase( + failCase( "alice", - async () => await dex.addPool(a_const, inputs, false, Tezos), + dex.addPool(a_const, inputs, false), "not-contract-admin" ), 10000 @@ -204,7 +194,7 @@ describe("00. Standalone Dex", () => { false, Tezos ), - 20000 + 30000 ); }); @@ -220,16 +210,15 @@ describe("00. Standalone Dex", () => { it( "should fail if not admin performs ramp A", async () => - await failCase( + failCase( "bob", - async () => - await dex.contract.methods - .ramp_A( - pool_id, - TPool.PoolAdmin.Ramp_A.future_a_const, - TPool.PoolAdmin.Ramp_A.future_a_time - ) - .send(), + dex.contract.methods + .ramp_A( + pool_id, + TPool.PoolAdmin.Ramp_A.future_a_const.toString(), + TPool.PoolAdmin.Ramp_A.future_a_time.toString() + ) + .send(), "not-contract-admin" ), 10000 @@ -238,7 +227,7 @@ describe("00. Standalone Dex", () => { it( "should ramp A", async () => - await prepareProviderOptions("eve").then((config) => { + prepareProviderOptions("eve").then((config) => { Tezos.setProvider(config); return TPool.PoolAdmin.Ramp_A.rampASuccessCase( dex, @@ -253,17 +242,16 @@ describe("00. Standalone Dex", () => { it( "should fail if not admin performs stopping ramp A", async () => - await failCase( + failCase( "bob", - async () => - await dex.contract.methods.stop_ramp_A(pool_id).send(), + dex.contract.methods.stop_ramp_A(pool_id).send(), "not-contract-admin" ), 10000 ); it("should stop ramp A", async () => - await prepareProviderOptions("eve").then((config) => { + prepareProviderOptions("eve").then((config) => { Tezos.setProvider(config); return TPool.PoolAdmin.Ramp_A.stopRampASuccessCase(dex, pool_id); })); @@ -273,10 +261,9 @@ describe("00. Standalone Dex", () => { it( "should fail if not admin try to set new fee", async () => - await failCase( + failCase( "bob", - async () => - await dex.setFees(pool_id, TPool.PoolAdmin.Fee.fees, Tezos), + dex.setFees(pool_id, TPool.PoolAdmin.Fee.fees), "not-contract-admin" ), 10000 @@ -285,7 +272,7 @@ describe("00. Standalone Dex", () => { it( "should change fees", async () => - await TPool.PoolAdmin.Fee.setFeesSuccessCase( + TPool.PoolAdmin.Fee.setFeesSuccessCase( dex, "eve", pool_id, @@ -312,7 +299,7 @@ describe("00. Standalone Dex", () => { it( `should stake ${input.dividedBy(decimals.QUIPU)} QUIPU to pool`, async () => - await TPool.stake.stakeToPoolSuccessCase( + TPool.stake.stakeToPoolSuccessCase( dex, staker, pool_id, @@ -359,18 +346,16 @@ describe("00. Standalone Dex", () => { it( "should fail if zero input", async () => - await failCase( + failCase( sender, - async () => - await dex.investLiquidity( - pool_id, - zero_amounts, - min_shares, - new Date(Date.now() + 1000 * 60 * 60 * 24), - null, - referral, - Tezos - ), + dex.investLiquidity( + pool_id, + zero_amounts, + min_shares, + new Date(Date.now() + 1000 * 60 * 60 * 24), + null, + referral + ), "zero-amount-in" ), 10000 @@ -379,18 +364,16 @@ describe("00. Standalone Dex", () => { it( "should fail if expired", async () => - await failCase( + failCase( sender, - async () => - await dex.investLiquidity( - pool_id, - amounts, - min_shares, - new Date(0), - null, - referral, - Tezos - ), + dex.investLiquidity( + pool_id, + amounts, + min_shares, + new Date(0), + null, + referral + ), "time-expired" ), 10000 @@ -399,17 +382,16 @@ describe("00. Standalone Dex", () => { it( "should fail if wrong indexes", async () => - await failCase( + failCase( sender, async () => - await dex.investLiquidity( + dex.investLiquidity( pool_id, wrong_idx_amounts, min_shares, new Date(Date.now() + 1000 * 60 * 60 * 24), null, - referral, - Tezos + referral ), "zero-amount-in" ), @@ -419,7 +401,7 @@ describe("00. Standalone Dex", () => { it( "should invest liq balanced", async () => - await TPool.PoolInvest.investLiquiditySuccessCase( + TPool.PoolInvest.investLiquiditySuccessCase( dex, sender, pool_id, @@ -432,6 +414,7 @@ describe("00. Standalone Dex", () => { 50000 ); + // eslint-disable-next-line jest/prefer-expect-assertions it("should invest liq imbalanced", async () => { await dex.updateStorage({ tokens: [pool_id.toString()], @@ -439,8 +422,8 @@ describe("00. Standalone Dex", () => { }); const tokens_map = dex.storage.storage.tokens[pool_id.toNumber()]; const idx_map = mapTokensToIdx(tokens_map, tokens); - const USDtz_amt = amounts.get(idx_map.USDtz); - const in_amt = amounts.set(idx_map.USDtz, new BigNumber(0)); + const USDtz_amt = amounts.get(idx_map.USDtz.toString()); + const in_amt = amounts.set(idx_map.USDtz.toString(), new BigNumber(0)); //min_shares = min_shares.multipliedBy(2).dividedToIntegerBy(3); await TPool.PoolInvest.investLiquiditySuccessCase( dex, @@ -453,7 +436,7 @@ describe("00. Standalone Dex", () => { Tezos ); const USDtz_in = new Map().set( - idx_map.USDtz, + idx_map.USDtz.toString(), USDtz_amt ); //min_shares = min_shares.dividedToIntegerBy(2); @@ -493,20 +476,18 @@ describe("00. Standalone Dex", () => { it( "should fail if expired", async () => - await failCase( + failCase( "bob", - async () => - await dex.swap( - pool_id, - new BigNumber(idx_map.uUSD), - new BigNumber(idx_map.kUSD), - decimals.uUSD.multipliedBy(normalized), - new BigNumber(0), - new Date(0), - bobAddress, - referral, - Tezos - ), + dex.swap( + pool_id, + new BigNumber(idx_map.uUSD), + new BigNumber(idx_map.kUSD), + decimals.uUSD.multipliedBy(normalized), + new BigNumber(0), + new Date(0), + bobAddress, + referral + ), "time-expired" ), 10000 @@ -515,20 +496,18 @@ describe("00. Standalone Dex", () => { it.each(swap_routes)( "should fail if zero input [%s, %s]", async (t_in, t_to) => - await failCase( + failCase( "bob", - async () => - await dex.swap( - pool_id, - new BigNumber(idx_map[t_in]), - new BigNumber(idx_map[t_to]), - zero_amount, - new BigNumber(1), - new Date(Date.now() + 1000 * 60 * 60 * 24), - bobAddress, - referral, - Tezos - ), + dex.swap( + pool_id, + new BigNumber(idx_map[t_in]), + new BigNumber(idx_map[t_to]), + zero_amount, + new BigNumber(1), + new Date(Date.now() + 1000 * 60 * 60 * 24), + bobAddress, + referral + ), "zero-amount-in" ), 10000 @@ -537,7 +516,7 @@ describe("00. Standalone Dex", () => { it.each(swap_routes)( `should swap [${normalized.toString()} %s, ~ ${normalized.toString()} %s]`, async (t_in, t_to) => - await TPool.PoolSwap.swapSuccessCase( + TPool.PoolSwap.swapSuccessCase( dex, tokens, sender, @@ -549,7 +528,6 @@ describe("00. Standalone Dex", () => { idx_map, normalized, amounts, - lambdaContractAddress, Tezos ), 40000 @@ -594,17 +572,15 @@ describe("00. Standalone Dex", () => { it( "should fail if zero input", async () => - await failCase( + failCase( "eve", - async () => - await dex.divestLiquidity( - pool_id, - min_amounts, - new BigNumber("0"), - new Date(Date.now() + 1000 * 60 * 60 * 24), - null, - Tezos - ), + dex.divestLiquidity( + pool_id, + min_amounts, + new BigNumber("0"), + new Date(Date.now() + 1000 * 60 * 60 * 24), + null + ), "zero-amount-in" ), 10000 @@ -613,17 +589,15 @@ describe("00. Standalone Dex", () => { it( "should fail if expired", async () => - await failCase( + failCase( "eve", - async () => - await dex.divestLiquidity( - pool_id, - min_amounts, - amount_in, - new Date(0), - null, - Tezos - ), + dex.divestLiquidity( + pool_id, + min_amounts, + amount_in, + new Date(0), + null + ), "time-expired" ), 10000 @@ -632,7 +606,7 @@ describe("00. Standalone Dex", () => { it( "should divest liq balanced", async () => - await TPool.PoolDivest.divestLiquiditySuccessCase( + TPool.PoolDivest.divestLiquiditySuccessCase( dex, "eve", pool_id, @@ -647,7 +621,7 @@ describe("00. Standalone Dex", () => { it( "should divest liq imbalanced", async () => - await TPool.PoolDivest.divestLiquidityImbalanceSuccessCase( + TPool.PoolDivest.divestLiquidityImbalanceSuccessCase( dex, "eve", pool_id, @@ -662,7 +636,7 @@ describe("00. Standalone Dex", () => { it( "should divest liq in one coin", async () => - await TPool.PoolDivest.divestLiquidityOneSuccessCase( + TPool.PoolDivest.divestLiquidityOneSuccessCase( dex, "eve", pool_id, @@ -691,10 +665,9 @@ describe("00. Standalone Dex", () => { it( "should fail if low balance", async () => - await failCase( + failCase( "bob", - async () => - await dex.transfer(pool_id, bobAddress, aliceAddress, amount), + dex.transfer(pool_id, bobAddress, aliceAddress, amount), "FA2_INSUFFICIENT_BALANCE" ), 10000 @@ -703,7 +676,7 @@ describe("00. Standalone Dex", () => { it( "should send from self", async () => - await prepareProviderOptions("alice").then((config) => { + prepareProviderOptions("alice").then((config) => { Tezos.setProvider(config); return dex.transfer(pool_id, aliceAddress, bobAddress, amount); }), @@ -715,10 +688,9 @@ describe("00. Standalone Dex", () => { it( "should fail send if not approved", async () => - await failCase( + failCase( "bob", - async () => - await dex.transfer(pool_id, aliceAddress, bobAddress, amount), + dex.transfer(pool_id, aliceAddress, bobAddress, amount), "FA2_NOT_OPERATOR" ), 10000 @@ -727,7 +699,7 @@ describe("00. Standalone Dex", () => { it( "should update operator", async () => - await prepareProviderOptions("alice").then((config) => { + prepareProviderOptions("alice").then((config) => { Tezos.setProvider(config); return dex.approve(bobAddress, amount); }), @@ -737,7 +709,7 @@ describe("00. Standalone Dex", () => { it( "should send as operator", async () => - await prepareProviderOptions("bob").then((config) => { + prepareProviderOptions("bob").then((config) => { Tezos.setProvider(config); return dex.transfer(pool_id, aliceAddress, bobAddress, amount); }), @@ -767,16 +739,16 @@ describe("00. Standalone Dex", () => { describe("4.1. Dex views", () => { it("should return A", async () => - await TView.pool.getASuccessCase(dex, pool_id)); + TView.pool.getASuccessCase(dex, pool_id)); it("should return fees", async () => - await TView.pool.getFeesSuccessCase(dex, pool_id)); + TView.pool.getFeesSuccessCase(dex, pool_id)); it("should return reserves", async () => - await TView.pool.getReservesSuccessCase(dex, pool_id)); + TView.pool.getReservesSuccessCase(dex, pool_id)); it("should return token map", async () => - await TView.pool.getTokenMapSuccessCase( + TView.pool.getTokenMapSuccessCase( dex, pool_id, tokens, @@ -784,10 +756,10 @@ describe("00. Standalone Dex", () => { )); it("should return dy", async () => - await TView.pool.getDySuccessCase(dex, pool_id, map_tokens_idx)); + TView.pool.getDySuccessCase(dex, pool_id, map_tokens_idx)); it("should fail when return dy because of pool_id", async () => - await failCase( + failCase( "bob", async () => { const params = { @@ -804,10 +776,10 @@ describe("00. Standalone Dex", () => { )); it("should return LP value", async () => - await TView.pool.getLPValueSuccessCase(dex, pool_id, map_tokens_idx)); + TView.pool.getLPValueSuccessCase(dex, pool_id, map_tokens_idx)); it("should return calc divest one", async () => - await TView.pool.calcDivestOneSuccessCase( + TView.pool.calcDivestOneSuccessCase( dex, { pool_id: pool_id, @@ -818,7 +790,7 @@ describe("00. Standalone Dex", () => { )); it("should return referral rewards", async () => - await TView.pool.getRefRewardsSuccessCase(dex, [ + TView.pool.getRefRewardsSuccessCase(dex, [ { user: referral, token: { @@ -839,7 +811,7 @@ describe("00. Standalone Dex", () => { ])); it("should return staker info", async () => - await TView.pool.getStkrInfoSuccessCase(dex, [ + TView.pool.getStkrInfoSuccessCase(dex, [ { user: staker, pool_id: pool_id, @@ -849,7 +821,7 @@ describe("00. Standalone Dex", () => { describe("4.2.Token views", () => { it("should return balance of account", async () => - await dex.contract.views + dex.contract.views .balance_of([ { owner: aliceAddress, @@ -864,7 +836,7 @@ describe("00. Standalone Dex", () => { token_id: pool_id, }, ]) - .read(lambdaContractAddress) + .read() .then((balances) => { expect(balances[0].balance.toNumber()).toBeGreaterThanOrEqual(0); expect(balances[1].balance.toNumber()).toBeGreaterThanOrEqual(0); @@ -872,9 +844,9 @@ describe("00. Standalone Dex", () => { })); it("should return total supply", async () => - await dex.contract.views + dex.contract.views .total_supply(pool_id) - .read(lambdaContractAddress) + .read() .then((total_supply) => { expect(total_supply.toNumber()).toStrictEqual( dex.storage.storage.pools[ @@ -885,7 +857,7 @@ describe("00. Standalone Dex", () => { }); }); - describe("5 Test unstake QUIPU token from pool", () => { + describe("5. Test unstake QUIPU token from pool", () => { const output = new BigNumber(10).pow(7); let pool_id: BigNumber; @@ -901,7 +873,7 @@ describe("00. Standalone Dex", () => { decimals.QUIPU )} QUIPU tokens from pool`, async () => - await TPool.stake.unstakeFromPoolSuccessCase( + TPool.stake.unstakeFromPoolSuccessCase( dex, staker, pool_id, @@ -940,16 +912,15 @@ describe("00. Standalone Dex", () => { it( "should get referral rewards", async () => - await TReward.referral.getReferralRewardsSuccessCase( + TReward.referral.getReferralRewardsSuccessCase( dex, tokens, pool_id, batchTimes, referral, - lambdaContractAddress, Tezos ), - 30000 + 60000 ); }); @@ -957,7 +928,7 @@ describe("00. Standalone Dex", () => { it( "should harvest staking rewards", async () => - await prepareProviderOptions("bob").then((config) => { + prepareProviderOptions("bob").then((config) => { Tezos.setProvider(config); return TReward.staker.harvestFromPoolSuccessCase( dex, @@ -972,15 +943,353 @@ describe("00. Standalone Dex", () => { describe("6.3. Developer reward", () => { it("should get dev rewards", async () => - await TReward.developer.getDeveloperRewardsSuccessCase( + TReward.developer.getDeveloperRewardsSuccessCase( dex, tokens, pool_id, batchTimes, dev_address, - lambdaContractAddress, Tezos )); }); }); + + describe("7. Testing strategy", () => { + let pool_id: BigNumber; + let yupana: Contract; + let price_feed: Contract; + let strategy_factory: Contract; + let strategy: Contract; + 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()] }); + ({ + yupana, + ordering: yup_ordering, + price_feed, + } = await TInit.setupYupanaMocks(tokens, Tezos)); + ({ strategy_factory, strategy } = await TInit.originateStrategy( + dex, + pool_id, + yupana, + price_feed, + Tezos + )); + pool_ordering = mapTokensToIdx( + dex.storage.storage.tokens[pool_id.toString()], + tokens + ); + // eslint-disable-next-line jest/no-standalone-expect + await expect(strategy.storage()).resolves.toMatchObject({ + factory: strategy_factory.address, + }); + }); + + describe("as a developer", () => { + let min_amounts: Map; + let invest_amounts: Map; + let imb_amounts: Map; + const normalized: BigNumber = new BigNumber(10).pow(3); // 3K + const min_out_amount: BigNumber = decimals.kUSD + .multipliedBy(normalized) + .multipliedBy("1e6") + .multipliedBy(3) + .minus( + decimals.kUSD + .multipliedBy(normalized) + .multipliedBy("1e6") + .multipliedBy(3) + .dividedBy(100) + ); + const outputs: AmountsMap = { + kUSD: decimals.kUSD.multipliedBy(normalized), + uUSD: decimals.uUSD.multipliedBy(normalized), + USDtz: decimals.USDtz.multipliedBy(normalized), + }; + const amount_in = new BigNumber(10) + .pow(18) + .multipliedBy(normalized) + .multipliedBy(2) + .multipliedBy("1e6"); + let idx_map: IndexMap; + + beforeAll(async () => { + ({ pool_id, min_amounts, idx_map } = + await TPool.PoolDivest.setupMinTokenMapping(dex, tokens, outputs)); + imb_amounts = new Map() + .set(idx_map.USDtz, outputs.USDtz.multipliedBy("1e5").multipliedBy(5)) + .set(idx_map.kUSD, new BigNumber(0)) + .set(idx_map.uUSD, outputs.uUSD.multipliedBy("1e5").multipliedBy(5)); + invest_amounts = new Map() + .set(idx_map.USDtz, outputs.USDtz.multipliedBy("1e6")) + .set(idx_map.kUSD, outputs.kUSD.multipliedBy("1e6")) + .set(idx_map.uUSD, outputs.uUSD.multipliedBy("1e6")); + min_amounts = new Map() + .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, + new BigNumber(1), + new Date(Date.now() + 1000 * 60 * 60 * 24) + ); + }); + + const test_factory = "tz1ZZZZZZZZZZZZZZZZZZZZZZZZZZZZNkiRg"; + + it("should connect and remove test strategy factory", async () => + TMng.addStrategyFactorySuccessCase(dex, test_factory).then(() => + TMng.removeStrategyFactorySuccessCase(dex, test_factory) + )); + + 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, + pool_id, + 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, + yupana, + strategy, + pool_id, + new Set([ + new BigNumber(pool_ordering.kUSD), + new BigNumber(pool_ordering.uUSD), + ]) + )); + + it("should auto-rebalance when swap", async () => + TStrategy.autoRebalance.swapRebalanceSuccessCase( + dex, + yupana, + strategy, + pool_id, + { + i: new BigNumber(pool_ordering.kUSD), + j: new BigNumber(pool_ordering.uUSD), + } + )); + + it("should auto-rebalance when invest", async () => + TStrategy.autoRebalance.investRebalanceSuccessCase( + dex, + yupana, + strategy, + pool_id, + invest_amounts + )); + + it("should auto-rebalance when divest imbalance", async () => + TStrategy.autoRebalance.divestImbalanceRebalanceSuccessCase( + dex, + yupana, + strategy, + pool_id, + imb_amounts, + amount_in + )); + + it("should auto-rebalance when divest one", async () => + TStrategy.autoRebalance.divestOneRebalanceSuccessCase( + dex, + yupana, + strategy, + pool_id, + new BigNumber(pool_ordering.kUSD), + outputs.kUSD.multipliedBy("1e5").multipliedBy(5), + 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 } = { + owner: sender, + token_id: pool_id.toNumber(), + }; + const lp_balance_response: { + request: typeof request; + balance: BigNumber; + }[] = await dex.contract.contractViews + .get_balance([request]) + .executeView({ viewCaller: sender }); + await TStrategy.autoRebalance.divestRebalanceSuccessCase( + dex, + yupana, + strategy, + pool_id, + min_amounts, + lp_balance_response[0].balance + ); + }); + + it("should configure strategy for token to zero", async () => + TStrategy.token.configureTokenStrategy + .setStrategyParamsToZeroSuccessCase( + dex, + pool_id, + new BigNumber(pool_ordering.kUSD) + ) + .then(() => + TStrategy.token.configureTokenStrategy.setStrategyParamsToZeroSuccessCase( + dex, + pool_id, + 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)); + }); + + describe("as a non-developer", () => { + beforeAll(async () => { + const config = await prepareProviderOptions("eve"); + Tezos.setProvider(config); + }); + + // 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", + async () => await dex.rebalance(pool_id, set), + "not-developer" + ); + }); + }); + }); }); diff --git a/test/01_Factory.test.ts b/test/01_Factory.test.ts index 3acf7ea..b9a828b 100644 --- a/test/01_Factory.test.ts +++ b/test/01_Factory.test.ts @@ -39,16 +39,14 @@ describe("01. Dex Factory", () => { ref_f: new BigNumber("0"), }; let factory: DexFactory; - let lambda: TezosAddress; let quipuToken: TokenFA2; beforeAll( async () => - ({ - factory, - quipuToken, - lambdaContractAddress: lambda, - } = await cases.before.setupFactoryEnvironment(tezos, developer_name)) + ({ factory, quipuToken } = await cases.before.setupFactoryEnvironment( + tezos, + developer_name + )) ); describe("1. Fee", () => { @@ -109,8 +107,7 @@ describe("01. Dex Factory", () => { dex_case.pools.PoolAdmin.Fee.fees, true, quipuToken, - tezos, - lambda + tezos ))); // eslint-disable-next-line jest/prefer-expect-assertions @@ -207,7 +204,6 @@ describe("01. Dex Factory", () => { idx_map, new BigNumber(10).pow(2), amounts, - lambda, Tezos ), 40000 @@ -263,7 +259,6 @@ describe("01. Dex Factory", () => { tokens, pool_id, developer_name, - lambda, Tezos )); }); @@ -324,7 +319,7 @@ describe("01. Dex Factory", () => { it("should deploy without QUIPU token fees", async () => { const init_balance: BigNumber = await quipuToken.contract.views .balance_of([{ owner: accounts.eve.pkh, token_id: "0" }]) - .read(lambda); + .read(); await cases.initPool.initializeExchangeSuccessCase( factory, @@ -337,13 +332,12 @@ describe("01. Dex Factory", () => { zero_fees, true, quipuToken, - tezos, - lambda + tezos ); const upd_balance: BigNumber = await quipuToken.contract.views .balance_of([{ owner: accounts.eve.pkh, token_id: "0" }]) - .read(lambda); + .read(); expect(init_balance[0].balance.toNumber()).toStrictEqual( upd_balance[0].balance.toNumber() ); @@ -401,8 +395,7 @@ describe("01. Dex Factory", () => { zero_fees, true, quipuToken, - tezos, - lambda + tezos )); }); @@ -450,8 +443,7 @@ describe("01. Dex Factory", () => { zero_fees, true, quipuToken, - tezos, - lambda + tezos )); }); diff --git a/test/Dex/API/dexAPI.ts b/test/Dex/API/dexAPI.ts index e563fa0..53634b1 100644 --- a/test/Dex/API/dexAPI.ts +++ b/test/Dex/API/dexAPI.ts @@ -20,11 +20,16 @@ import { dexLambdas, tokenLambdas } from "../../storage/Functions"; import admin_lambdas_comp from "../../../build/lambdas/test/Admin_lambdas.json"; import dex_lambdas_comp from "../../../build/lambdas/test/Dex_lambdas.json"; import dev_lambdas_comp from "../../../build/lambdas/test/Dev_lambdas.json"; +import strat_lambdas_comp from "../../../build/lambdas/test/Strategy_lambdas.json"; import token_lambdas_comp from "../../../build/lambdas/test/Token_lambdas.json"; import { defaultTokenId, TokenFA12, TokenFA2 } from "../../Token"; import { DevEnabledContract } from "../../Developer/API/devAPI"; +import { StrategyFactorySetter } from "../../Strategy/API/strategyFactoryMethod"; -export class Dex extends TokenFA2 implements DevEnabledContract { +export class Dex + extends TokenFA2 + implements DevEnabledContract, StrategyFactorySetter +{ public contract: ContractAbstraction; public storage: DexStorage; @@ -48,23 +53,30 @@ export class Dex extends TokenFA2 implements DevEnabledContract { tezos, dexAddress, "Admin", - 8, + 9, admin_lambdas_comp ); await setFunctionBatchCompilled( tezos, dexAddress, "Token", - 5, + 3, token_lambdas_comp ); await setFunctionBatchCompilled( tezos, dexAddress, "Dex", - 8, + 3, dex_lambdas_comp ); + await setFunctionBatchCompilled( + tezos, + dexAddress, + "Strategy", + 3, + strat_lambdas_comp + ); } return dex; } @@ -81,15 +93,23 @@ export class Dex extends TokenFA2 implements DevEnabledContract { ): Promise { this.storage = (await this.contract.storage()) as DexStorage; for (const key in maps) { - if (["dex_lambdas", "token_lambdas", "admin_lambdas"].includes(key)) + if ( + [ + "dex_lambdas", + "token_lambdas", + "admin_lambdas", + "strat_lambdas", + ].includes(key) + ) continue; this.storage.storage[key] = await maps[key].reduce( async (prev, current) => { try { return { ...(await prev), - [key == "ledger" ? current[0] : current]: - await this.storage.storage[key].get(current), + [key == "ledger" || key == "configuration" + ? current[0] + : current]: await this.storage.storage[key].get(current), }; } catch (ex) { console.error(ex); @@ -102,7 +122,14 @@ export class Dex extends TokenFA2 implements DevEnabledContract { ); } for (const key in maps) { - if (!["dex_lambdas", "token_lambdas", "admin_lambdas"].includes(key)) + if ( + ![ + "dex_lambdas", + "token_lambdas", + "admin_lambdas", + "strat_lambdas", + ].includes(key) + ) continue; this.storage[key] = await maps[key].reduce(async (prev, current) => { try { @@ -120,20 +147,26 @@ export class Dex extends TokenFA2 implements DevEnabledContract { } async addPool( - a_const: BigNumber = new BigNumber("100000"), - token_info: { + aConst: BigNumber = new BigNumber("100000"), + tokenInfo: { asset: TokenFA12 | TokenFA2; in_amount: BigNumber; rate_f: BigNumber; precision_multiplier_f: BigNumber; }[], - approve = true, - tezos: TezosToolkit + approve = true ): Promise { - const tokens_info = new MichelsonMap(); + const tokens_info = new MichelsonMap< + number, + { + rate_f: string; + precision_multiplier_f: string; + reserves: string; + } + >(); const input_tokens: Array = []; - for (let i = 0; i < token_info.length; i++) { - const info = token_info[i]; + for (let i = 0; i < tokenInfo.length; i++) { + const info = tokenInfo[i]; if (approve) { await info.asset.approve(this.contract.address, info.in_amount); } @@ -144,9 +177,9 @@ export class Dex extends TokenFA2 implements DevEnabledContract { precision_multiplier_f: BigNumber; }) => { let result: { - rate_f: BigNumber; - precision_multiplier_f: BigNumber; - reserves: BigNumber; + rate_f: string; + precision_multiplier_f: string; + reserves: string; }; if (input.asset instanceof TokenFA2) { input_tokens.push({ @@ -156,18 +189,18 @@ export class Dex extends TokenFA2 implements DevEnabledContract { }, }); result = { - rate_f: input.rate_f, - precision_multiplier_f: input.precision_multiplier_f, - reserves: input.in_amount, + rate_f: input.rate_f.toString(), + precision_multiplier_f: input.precision_multiplier_f.toString(), + reserves: input.in_amount.toString(), }; } else { input_tokens.push({ fa12: input.asset.contract.address, }); result = { - rate_f: input.rate_f, - precision_multiplier_f: input.precision_multiplier_f, - reserves: input.in_amount, + rate_f: input.rate_f.toString(), + precision_multiplier_f: input.precision_multiplier_f.toString(), + reserves: input.in_amount.toString(), }; } return result; @@ -176,7 +209,7 @@ export class Dex extends TokenFA2 implements DevEnabledContract { } const operation = await this.contract.methodsObject .add_pool({ - a_constant: a_const, + a_constant: aConst.toString(), input_tokens: input_tokens, tokens_info, fees: { @@ -186,7 +219,7 @@ export class Dex extends TokenFA2 implements DevEnabledContract { }, }) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -198,22 +231,23 @@ export class Dex extends TokenFA2 implements DevEnabledContract { minAmountOut: BigNumber, expiration: Date, receiver: string = null, - referral: string = null, - tezos: TezosToolkit + referral: string = null ): Promise { - const operation = await this.contract.methods - .swap( - poolId, - inIdx, - toIdx, - amountIn, - minAmountOut, - new BigNumber(expiration.getTime()).dividedToIntegerBy(1000), - receiver, - referral - ) + const operation = await this.contract.methodsObject + .swap({ + pool_id: poolId.toString(), + idx_from: inIdx.toString(), + idx_to: toIdx.toString(), + amount: amountIn.toString(), + min_amount_out: minAmountOut.toString(), + deadline: new BigNumber(expiration.getTime()) + .dividedToIntegerBy(1000) + .toString(), + receiver: receiver, + referral: referral, + }) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -223,24 +257,23 @@ export class Dex extends TokenFA2 implements DevEnabledContract { minShares: BigNumber, expiration: Date, receiver: TezosAddress = null, - referral: TezosAddress = null, - tezos: TezosToolkit + referral: TezosAddress = null ): Promise { const in_amounts = new MichelsonMap(); tokenAmounts.forEach((value, key) => { - in_amounts.set(key, value.toNumber()); + in_amounts.set(key, value.toString()); }); - const operation = await this.contract.methods - .invest( - poolId, - minShares, - in_amounts, - new BigNumber(expiration.getTime()).dividedToIntegerBy(1000), - receiver, - referral - ) + const operation = await this.contract.methodsObject + .invest({ + pool_id: poolId.toString(), + shares: minShares.toString(), + in_amounts: in_amounts, + deadline: expiration.toISOString(), + receiver: receiver, + referral: referral, + }) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -249,23 +282,24 @@ export class Dex extends TokenFA2 implements DevEnabledContract { mintokenAmounts: Map, sharesBurned: BigNumber, expiration: Date, - receiver: TezosAddress = null, - tezos: TezosToolkit + receiver: TezosAddress = null ): Promise { - const amts = new MichelsonMap(); + const amts = new MichelsonMap(); mintokenAmounts.forEach((value, key) => { - amts.set(key, value); + amts.set(key, value.toString()); }); - const operation = await this.contract.methods - .divest( - poolId, - amts, - sharesBurned, - new BigNumber(expiration.getTime()).dividedToIntegerBy(1000), - receiver - ) + const operation = await this.contract.methodsObject + .divest({ + pool_id: poolId.toString(), + min_amounts_out: amts, + shares: sharesBurned.toString(), + deadline: new BigNumber(expiration.getTime()) + .dividedToIntegerBy(1000) + .toString(), + receiver: receiver, + }) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -275,25 +309,26 @@ export class Dex extends TokenFA2 implements DevEnabledContract { maxSharesBurned: BigNumber, expiration: Date, receiver: TezosAddress = null, - referral: TezosAddress = null, - tezos: TezosToolkit + referral: TezosAddress = null ): Promise { const amts = new MichelsonMap(); tokenAmounts.forEach((value, key) => { amts.set(key, value); }); - const operation = await this.contract.methods - .divest_imbalanced( - poolId, - amts, - maxSharesBurned, - new BigNumber(expiration.getTime()).dividedToIntegerBy(1000), - receiver, - referral - ) + const operation = await this.contract.methodsObject + .divest_imbalanced({ + pool_id: poolId.toString(), + amounts_out: amts, + max_shares: maxSharesBurned.toString(), + deadline: new BigNumber(expiration.getTime()) + .dividedToIntegerBy(1000) + .toString(), + receiver: receiver, + referral: referral, + }) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -304,84 +339,176 @@ export class Dex extends TokenFA2 implements DevEnabledContract { mintokenAmount: BigNumber, expiration: Date, receiver: TezosAddress = null, - referral: TezosAddress = null, - tezos: TezosToolkit + referral: TezosAddress = null ): Promise { - const operation = await this.contract.methods - .divest_one_coin( - poolId, - sharesBurned, - tokenIdx, - mintokenAmount, - new BigNumber(expiration.getTime()).dividedToIntegerBy(1000), - receiver, - referral - ) + const operation = await this.contract.methodsObject + .divest_one_coin({ + pool_id: poolId.toString(), + shares: sharesBurned.toString(), + token_index: tokenIdx.toString(), + min_amount_out: mintokenAmount.toString(), + deadline: new BigNumber(expiration.getTime()) + .dividedToIntegerBy(1000) + .toString(), + receiver: receiver, + referral: referral, + }) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } - async setAdmin( - new_admin: string, - tezos: TezosToolkit - ): Promise { + async setAdmin(newAdmin: string): Promise { await this.updateStorage({}); - const operation = await this.contract.methods.set_admin(new_admin).send(); + const operation = await this.contract.methods.set_admin(newAdmin).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } async addRemManager( add: boolean, - manager: string, - tezos: TezosToolkit + manager: string ): Promise { await this.updateStorage({}); const operation = await this.contract.methods .add_rem_managers(add, manager) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } - async setDevAddress( - dev: string, - tezos: TezosToolkit - ): Promise { + async setDevAddress(dev: string): Promise { await this.updateStorage({}); const operation = await this.contract.methods.set_dev_address(dev).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); + return operation; + } + + async connectStrategy( + poolId: BigNumber, + strategy: string | null = null + ): Promise { + await this.updateStorage({}); + const operation = await this.contract.methods + .connect_strategy(poolId, strategy) + .send(); + + await operation.confirmation(2); + // await confirmOperation(tezos, operation.hash); + 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 + ): Promise { + await this.updateStorage({}); + const operation = await this.contract.methods + .rebalance( + poolId.toString(), + Array.from(poolTokenIds).map((x) => x.toNumber()) + ) + .send(); + + await operation.confirmation(2); + // await confirmOperation(tezos, operation.hash); + return operation; + } + + manualRebalanceStrategy = ( + poolId: BigNumber, + 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, - tezos: TezosToolkit + fees: FeeType ): Promise { const operation = await this.contract.methods .set_fees(pool_id, fees.lp_f, fees.stakers_f, fees.ref_f) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } - async setDevFee( - fee: BigNumber, - tezos: TezosToolkit - ): Promise { + async setDevFee(fee: BigNumber): Promise { const operation = await this.contract.methods.set_dev_fee(fee).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } - async setDefaultReferral( - ref: string, - tezos: TezosToolkit - ): Promise { + async setDefaultReferral(ref: string): Promise { const operation = await this.contract.methods .set_default_referral(ref) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -389,36 +516,55 @@ export class Dex extends TokenFA2 implements DevEnabledContract { tokenAddress: string, tokenId: BigNumber, tokenAmount: number, - address: string, - tezos: TezosToolkit + address: string ): Promise { await this.updateStorage(); - const token = await tezos.contract.at(tokenAddress); + const token = await this.Tezos.contract.at(tokenAddress); const operation = await token.methods .update_operators([ { [tokenAmount ? "add_operator" : "remove_operator"]: { - owner: await tezos.signer.publicKeyHash(), + owner: await this.Tezos.signer.publicKeyHash(), operator: address, token_id: tokenId, }, }, ]) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } async approveFA12Token( tokenAddress: string, tokenAmount: number, - address: string, - tezos: TezosToolkit + address: string ): Promise { await this.updateStorage(); - const token = await tezos.contract.at(tokenAddress); + const token = await this.Tezos.contract.at(tokenAddress); const operation = await token.methods.approve(address, tokenAmount).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } + + async manageStrategyFactories( + strategy_factory: string, + add: boolean + ): Promise { + const op = await this.contract.methods + .set_strategy_factory(add, strategy_factory) + .send(); + await op.confirmation(2); + return op; + } + async addStrategyFactory( + strategy_factory: string + ): Promise { + return this.manageStrategyFactories(strategy_factory, true); + } + async removeStrategyFactory( + strategy_factory: string + ): Promise { + return this.manageStrategyFactories(strategy_factory, false); + } } diff --git a/test/Dex/API/storage.ts b/test/Dex/API/storage.ts index 8e2195b..4bfc655 100644 --- a/test/Dex/API/storage.ts +++ b/test/Dex/API/storage.ts @@ -26,10 +26,12 @@ const dex_storage: DexStorage = { dev_lambdas: new MichelsonMap(), }, factory_address: null as TezosAddress, + strategy_factory: null as TezosAddress[], }, metadata: new MichelsonMap(), admin_lambdas: new MichelsonMap(), dex_lambdas: new MichelsonMap(), token_lambdas: new MichelsonMap(), + strat_lambdas: new MichelsonMap(), }; export default dex_storage; diff --git a/test/Dex/API/types.ts b/test/Dex/API/types.ts index 68f1907..777f282 100644 --- a/test/Dex/API/types.ts +++ b/test/Dex/API/types.ts @@ -24,6 +24,19 @@ export declare type TokenInfo = { reserves: BigNumber; }; +export declare type TokenStrategyConfiguration = { + des_reserves_rate_f: BigNumber; + delta_rate_f: BigNumber; + min_invest: BigNumber; + strategy_reserves: BigNumber; + is_rebalance: boolean; +}; + +export declare type StrategyStoreType = { + strat_contract?: TezosAddress; + configuration: MichelsonMap; +}; + export declare type PairInfo = { initial_A_f: BigNumber; initial_A_time: Date; @@ -32,6 +45,7 @@ export declare type PairInfo = { tokens_info: MichelsonMap; fee: FeeType; + strategy: StrategyStoreType; staker_accumulator: { accumulator_f: MichelsonMap; total_staked: BigNumber; @@ -71,6 +85,7 @@ export declare type DexMainStorage = { >; dev_store?: DevStorage; factory_address?: TezosAddress; + strategy_factory?: TezosAddress[]; }; export declare type DexStorage = { @@ -79,6 +94,7 @@ export declare type DexStorage = { admin_lambdas: MichelsonMap; dex_lambdas: MichelsonMap; token_lambdas: MichelsonMap; + strat_lambdas: MichelsonMap; }; export declare type RewardsType = { diff --git a/test/Dex/cases/admin.ts b/test/Dex/cases/admin.ts index 07113fd..285b483 100644 --- a/test/Dex/cases/admin.ts +++ b/test/Dex/cases/admin.ts @@ -8,6 +8,10 @@ export { setDevAddrSuccessCase, setDevFeeSuccessCase, } from "../../Developer/cases"; +export { + addStrategyFactorySuccessCase, + removeStrategyFactorySuccessCase, +} from "../../Strategy/cases"; export async function setAdminSuccessCase( dex: Dex, @@ -24,7 +28,7 @@ export async function setAdminSuccessCase( expect(admin).not.toStrictEqual(initAdmin); expect(sender_address).toStrictEqual(initAdmin); - await dex.setAdmin(admin, Tezos); + await dex.setAdmin(admin); await dex.updateStorage({}); const updatedAdmin = dex.storage.storage.admin; @@ -46,7 +50,7 @@ export async function updateManagersSuccessCase( // initManagers includes manager if want to remove and not includes if add expect(initManagers.includes(manager)).not.toBe(add); - await dex.addRemManager(add, manager, Tezos); + await dex.addRemManager(add, manager); await dex.updateStorage({}); const updatedManagers = dex.storage.storage.managers; @@ -66,7 +70,7 @@ export async function setDefaultRefSuccessCase( const initRef = dex.storage.storage.default_referral; expect(ref).not.toStrictEqual(initRef); - await dex.setDefaultReferral(ref, Tezos); + await dex.setDefaultReferral(ref); await dex.updateStorage({}); const updatedDev = dex.storage.storage.default_referral; diff --git a/test/Dex/cases/admin/fees.ts b/test/Dex/cases/admin/fees.ts index 8d934f9..63aae9b 100644 --- a/test/Dex/cases/admin/fees.ts +++ b/test/Dex/cases/admin/fees.ts @@ -30,7 +30,7 @@ export async function setFeesSuccessCase( expect(initFee[key].toNumber()).not.toStrictEqual(fees[key].toNumber()); } - await dex.setFees(pool_id, fees, Tezos); + await dex.setFees(pool_id, fees); await dex.updateStorage({ pools: [pool_id.toString()] }); const updStorage: DexStorage = await dex.contract.storage(); diff --git a/test/Dex/cases/admin/rampA.ts b/test/Dex/cases/admin/rampA.ts index 210d1c8..1c33baf 100644 --- a/test/Dex/cases/admin/rampA.ts +++ b/test/Dex/cases/admin/rampA.ts @@ -25,8 +25,10 @@ export async function rampASuccessCase( ft_time = new BigNumber(Date.now()) .plus(ft_time.multipliedBy(1000)) .dividedToIntegerBy(1000); - const op = await dex.contract.methods.ramp_A(pool_id, ft_a, ft_time).send(); - await confirmOperation(Tezos, op.hash); + const op = await dex.contract.methods + .ramp_A(pool_id, ft_a.toString(), ft_time.toString()) + .send(); + await op.confirmation(2); await dex.updateStorage({ pools: [pool_id.toString()] }); const upd: PairInfo = dex.storage.storage.pools[pool_id.toString()]; const { @@ -52,7 +54,7 @@ export async function stopRampASuccessCase(dex: Dex, pool_id: BigNumber) { initial_A_time: init_in_A_t, } = init; const op = await dex.contract.methods.stop_ramp_A(pool_id).send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); await dex.updateStorage({ pools: [pool_id.toString()] }); const upd: PairInfo = dex.storage.storage.pools[pool_id.toString()]; const { diff --git a/test/Dex/cases/before.ts b/test/Dex/cases/before.ts index 811779f..b432e02 100644 --- a/test/Dex/cases/before.ts +++ b/test/Dex/cases/before.ts @@ -10,6 +10,7 @@ import dev_lambdas_comp from "../../../build/lambdas/test/Dev_lambdas.json"; import dex_lambdas_comp from "../../../build/lambdas/test/Dex_lambdas.json"; import token_lambdas_comp from "../../../build/lambdas/test/Token_lambdas.json"; import admin_lambdas_comp from "../../../build/lambdas/test/Admin_lambdas.json"; +import strat_lambdas_comp from "../../../build/lambdas/test/Strategy_lambdas.json"; import { accounts } from "../../../utils/constants"; import { DexAPI as Dex, defaultDexStorage as storage } from "../API"; @@ -22,17 +23,10 @@ export async function setupDexEnvironment(Tezos: TezosToolkit): Promise<{ dex: Dex; tokens: TokensMap; quipuToken: TokenFA2; - lambdaContractAddress: string; }> { const config = await prepareProviderOptions("alice"); Tezos.setProvider(config); - const op = await Tezos.contract.originate({ - code: VIEW_LAMBDA.code, - storage: VIEW_LAMBDA.storage, - }); - await confirmOperation(Tezos, op.hash); const quipuToken = await setupQuipuGovToken(Tezos); - const lambdaContractAddress = op.contractAddress; storage.storage.admin = accounts.alice.pkh; storage.storage.default_referral = accounts.bob.pkh; storage.storage.quipu_token = { @@ -46,11 +40,12 @@ export async function setupDexEnvironment(Tezos: TezosToolkit): Promise<{ storage.storage.dev_store.dev_lambdas = await setupLambdasToStorage( dev_lambdas_comp ); + storage.storage.strategy_factory = []; const dex_op = await Tezos.contract.originate({ code: dex_contract.michelson, storage: storage, }); - await confirmOperation(Tezos, dex_op.hash); + await dex_op.confirmation(2); console.debug( `[${chalk.green("ORIGINATION")}] DEX`, chalk.bold.underline(dex_op.contractAddress) @@ -58,5 +53,5 @@ export async function setupDexEnvironment(Tezos: TezosToolkit): Promise<{ const dex = await Dex.init(Tezos, dex_op.contractAddress); await new Promise((r) => setTimeout(r, 2000)); const tokens = await setupTrioTokens(dex, Tezos, true); - return { dex, tokens, quipuToken, lambdaContractAddress }; + return { dex, tokens, quipuToken }; } diff --git a/test/Dex/cases/index.ts b/test/Dex/cases/index.ts index c9e6c5e..d0ac00c 100644 --- a/test/Dex/cases/index.ts +++ b/test/Dex/cases/index.ts @@ -1,13 +1,17 @@ -import * as before from "./before"; +import * as common_before from "./before"; import * as admin from "./admin"; import * as pools from "./pool_part"; import * as rewards from "./rewards"; import * as views from "./views"; +import strategy from "./strategy"; + +const before = { ...common_before, ...strategy.before }; export const cases = { before, admin, pools, rewards, views, + strategy: strategy.cases, }; export default cases; diff --git a/test/Dex/cases/pool_part/add.ts b/test/Dex/cases/pool_part/add.ts index 69e7863..d2280ec 100644 --- a/test/Dex/cases/pool_part/add.ts +++ b/test/Dex/cases/pool_part/add.ts @@ -78,7 +78,7 @@ export async function addNewPair( const initPairCount = new BigNumber(dex.storage.storage.pools_count); expect(sender_addr).toStrictEqual(dex.storage.storage.admin); - await dex.addPool(a_const, inputs, approve, Tezos); + await dex.addPool(a_const, inputs, approve); await dex.updateStorage({}); await dex.updateStorage({ diff --git a/test/Dex/cases/pool_part/divest.ts b/test/Dex/cases/pool_part/divest.ts index ae2464d..e2413b0 100644 --- a/test/Dex/cases/pool_part/divest.ts +++ b/test/Dex/cases/pool_part/divest.ts @@ -54,14 +54,7 @@ export async function divestLiquiditySuccessCase( (value, key) => (raw_res[key] = value.reserves.toFormat(0).toString()) ); const init_ledger = dex.storage.storage.ledger[accounts[sender].pkh]; - await dex.divestLiquidity( - pool_id, - min_amounts, - shares, - expiration, - null, - Tezos - ); + await dex.divestLiquidity(pool_id, min_amounts, shares, expiration, null); await dex.updateStorage({ pools: [pool_id.toString()], ledger: [[accounts[sender].pkh, pool_id.toNumber()]], @@ -107,8 +100,7 @@ export async function divestLiquidityImbalanceSuccessCase( max_shares, expiration, null, - null, - Tezos + null ); await dex.updateStorage({ pools: [pool_id.toString()], @@ -159,8 +151,7 @@ export async function divestLiquidityOneSuccessCase( min_amount, expiration, null, - null, - Tezos + null ); await dex.updateStorage({ pools: [pool_id.toString()], diff --git a/test/Dex/cases/pool_part/invest.ts b/test/Dex/cases/pool_part/invest.ts index 6d42df0..40da66e 100644 --- a/test/Dex/cases/pool_part/invest.ts +++ b/test/Dex/cases/pool_part/invest.ts @@ -33,8 +33,7 @@ export async function investLiquiditySuccessCase( min_shares, expiration, null, - referral, - Tezos + referral ); await dex.updateStorage({ diff --git a/test/Dex/cases/pool_part/stake.ts b/test/Dex/cases/pool_part/stake.ts index f07ad3d..175eef5 100644 --- a/test/Dex/cases/pool_part/stake.ts +++ b/test/Dex/cases/pool_part/stake.ts @@ -23,7 +23,7 @@ export async function stakeToPoolSuccessCase( .then((balance) => balance.get([staker, pool_id.toString()])) .then((value) => (value ? value.balance : new BigNumber(0))); const op = await dex.contract.methods.stake("add", pool_id, input).send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); await dex.updateStorage({ pools: [pool_id.toString()] }); const upd_total_stake = dex.storage.storage.pools[pool_id.toNumber()].staker_accumulator @@ -59,7 +59,7 @@ export async function unstakeFromPoolSuccessCase( .then((balance) => balance.get([staker, pool_id.toString()])) .then((value) => (value ? value.balance : new BigNumber(0))); const op = await dex.contract.methods.stake("remove", pool_id, output).send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); await dex.updateStorage({ pools: [pool_id.toString()] }); const upd_total_stake = dex.storage.storage.pools[pool_id.toNumber()].staker_accumulator diff --git a/test/Dex/cases/pool_part/swap.ts b/test/Dex/cases/pool_part/swap.ts index cc89274..4351261 100644 --- a/test/Dex/cases/pool_part/swap.ts +++ b/test/Dex/cases/pool_part/swap.ts @@ -45,14 +45,13 @@ export async function swapSuccessCase( tokens: TokensMap, sender: AccountsLiteral, pool_id: BigNumber, - t_in, - t_to, + t_in: string, + t_to: string, exp: Date, referral: string, idx_map: IndexMap, normalized_input: BigNumber, amounts: Map, - lambdaContractAddress: string, Tezos: TezosToolkit ) { const config = await prepareProviderOptions(sender); @@ -76,15 +75,15 @@ export async function swapSuccessCase( let init_in: BigNumber = await (tok_in instanceof TokenFA12 ? t_in_ep(accounts[sender].pkh) : t_in_ep([{ owner: accounts[sender].pkh, token_id: "0" }]) - ).read(lambdaContractAddress); + ).read(); let init_out: BigNumber = await (tok_out instanceof TokenFA12 ? t_out_ep(accounts[sender].pkh) : t_out_ep([{ owner: accounts[sender].pkh, token_id: "0" }]) - ).read(lambdaContractAddress); + ).read(); - const in_amount = amounts.get(i); - let min_out = amounts.get(j); + const in_amount = amounts.get(i.toString()); + let min_out = amounts.get(j.toString()); min_out = min_out.minus(min_out.multipliedBy(1).div(100)); console.debug( @@ -104,14 +103,13 @@ export async function swapSuccessCase( min_out, exp, accounts[sender].pkh, - referral, - Tezos + referral ); await dex.updateStorage({ pools: [pool_id.toString()] }); const upd_reserves = dex.storage.storage.pools[pool_id.toString()].tokens_info; expect(upd_reserves.get(i.toString()).reserves).toStrictEqual( - init_reserves.get(i.toString()).reserves.plus(amounts.get(i)) + init_reserves.get(i.toString()).reserves.plus(amounts.get(i.toString())) ); // Get output from internal transaction @@ -147,11 +145,11 @@ export async function swapSuccessCase( let upd_in = await (tok_in instanceof TokenFA12 ? t_in_ep(accounts[sender].pkh) : t_in_ep([{ owner: accounts[sender].pkh, token_id: "0" }]) - ).read(lambdaContractAddress); + ).read(); let upd_out = await (tok_out instanceof TokenFA12 ? t_out_ep(accounts[sender].pkh) : t_out_ep([{ owner: accounts[sender].pkh, token_id: "0" }]) - ).read(lambdaContractAddress); + ).read(); expect(output.toNumber()).toBeGreaterThanOrEqual(min_out.toNumber()); @@ -279,23 +277,25 @@ export async function batchSwap( for (const [t_in, t_out] of swap_routes) { const i = map_tokens_idx[t_in]; const j = map_tokens_idx[t_out]; - let min_out = amounts.get(j); + let min_out = amounts.get(j.toString()); min_out = min_out.minus(min_out.multipliedBy(1).div(100)); batch.withContractCall( - dex.contract.methods.swap( - poolId, - i, - j, - amounts.get(i), - min_out, - new BigNumber(exp.getTime()), - null, - ref - ) + dex.contract.methodsObject.swap({ + pool_id: poolId.toString(), + idx_from: i.toString(), + idx_to: j.toString(), + amount: amounts.get(i.toString()).toString(), + min_amount_out: min_out.toString(), + deadline: new BigNumber(exp.getTime()) + .dividedToIntegerBy(1000) + .toString(), + receiver: null, + referral: ref, + }) ); } const op = await batch.send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug( `[${chalk.bold.bgWhite.bgBlueBright( "BATCH" diff --git a/test/Dex/cases/rewards/developer.ts b/test/Dex/cases/rewards/developer.ts index 978cf7e..8c6cd20 100644 --- a/test/Dex/cases/rewards/developer.ts +++ b/test/Dex/cases/rewards/developer.ts @@ -15,7 +15,6 @@ export async function getDeveloperRewardsSuccessCase( pool_id: BigNumber, batchTimes: number, developer: string, - lambdaContractAddress: string, Tezos: TezosToolkit ) { const config = await prepareProviderOptions("bob"); @@ -32,13 +31,13 @@ export async function getDeveloperRewardsSuccessCase( }); const initUSDtz = await tokens.USDtz.contract.views .getBalance(developer) - .read(lambdaContractAddress); + .read(); const initkUSD = await tokens.kUSD.contract.views .getBalance(developer) - .read(lambdaContractAddress); + .read(); const inituUSD = await tokens.uUSD.contract.views .balance_of([{ owner: developer, token_id: "0" }]) - .read(lambdaContractAddress); + .read(); const USDtzRewards = await dev_stor.get({ fa12: tokens.USDtz.contract.address, @@ -73,10 +72,13 @@ export async function getDeveloperRewardsSuccessCase( kUSD: kUSDRewards, uUSD: uUSDRewards, }; - let op = await dex.contract.methods - .claim_developer("fa12", tokens.USDtz.contract.address, USDtzRewards) + let op = await dex.contract.methodsObject + .claim_developer({ + token: { fa12: tokens.USDtz.contract.address }, + amount: USDtzRewards.toString(), + }) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:DEVELOPER] USDtz`); await dex.updateStorage({ pools: [pool_id.toString()] }); let upd_dev_stor = await dex.contract @@ -88,10 +90,13 @@ export async function getDeveloperRewardsSuccessCase( fa12: tokens.USDtz.contract.address, }); expect(updUSDtzRewards.toNumber()).toBe(0); - op = await dex.contract.methods - .claim_developer("fa12", tokens.kUSD.contract.address, kUSDRewards) + op = await dex.contract.methodsObject + .claim_developer({ + token: { fa12: tokens.kUSD.contract.address }, + amount: kUSDRewards.toString(), + }) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:DEVELOPER] kUSD`); await dex.updateStorage({ pools: [pool_id.toString()] }); upd_dev_stor = await dex.contract.storage().then((storage: DexStorage) => { @@ -101,15 +106,18 @@ export async function getDeveloperRewardsSuccessCase( fa12: tokens.kUSD.contract.address, }); expect(updkUSDRewards.toNumber()).toBe(0); - op = await dex.contract.methods - .claim_developer( - "fa2", - tokens.uUSD.contract.address, - new BigNumber(defaultTokenId), - uUSDRewards - ) + op = await dex.contract.methodsObject + .claim_developer({ + token: { + fa2: { + token_address: tokens.uUSD.contract.address, + token_id: new BigNumber(defaultTokenId).toString(), + }, + }, + amount: uUSDRewards.toString(), + }) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:DEVELOPER] uUSD`); upd_dev_stor = await dex.contract.storage().then((storage: DexStorage) => { return storage.storage.dev_rewards; @@ -123,13 +131,11 @@ export async function getDeveloperRewardsSuccessCase( expect(upduUSDRewards.toNumber()).toBe(0); const updUSDtz = await tokens.USDtz.contract.views .getBalance(developer) - .read(lambdaContractAddress); - const updkUSD = await tokens.kUSD.contract.views - .getBalance(developer) - .read(lambdaContractAddress); + .read(); + const updkUSD = await tokens.kUSD.contract.views.getBalance(developer).read(); const upduUSD = await tokens.uUSD.contract.views .balance_of([{ owner: developer, token_id: "0" }]) - .read(lambdaContractAddress); + .read(); expect(updUSDtz.minus(initUSDtz).toNumber()).toStrictEqual( init_rewards.USDtz.toNumber() ); diff --git a/test/Dex/cases/rewards/referral.ts b/test/Dex/cases/rewards/referral.ts index 53d5683..d87d1b8 100644 --- a/test/Dex/cases/rewards/referral.ts +++ b/test/Dex/cases/rewards/referral.ts @@ -18,7 +18,6 @@ export async function getReferralRewardsSuccessCase( pool_id: BigNumber, batchSwapTimes: number, referral: AccountsLiteral, - lambdaContractAddress: string, Tezos: TezosToolkit ) { { @@ -40,13 +39,13 @@ export async function getReferralRewardsSuccessCase( }); const initUSDtz = await tokens.USDtz.contract.views .getBalance(ref_address) - .read(lambdaContractAddress); + .read(); const initkUSD = await tokens.kUSD.contract.views .getBalance(ref_address) - .read(lambdaContractAddress); + .read(); const inituUSD = await tokens.uUSD.contract.views .balance_of([{ owner: ref_address, token_id: "0" }]) - .read(lambdaContractAddress); + .read(); const USDtzRewards = await ref_stor.get({ 0: ref_address, @@ -82,10 +81,13 @@ export async function getReferralRewardsSuccessCase( kUSD: kUSDRewards, uUSD: uUSDRewards, }; - let op = await dex.contract.methods - .claim_referral("fa12", tokens.USDtz.contract.address, USDtzRewards) + let op = await dex.contract.methodsObject + .claim_referral({ + token: { fa12: tokens.USDtz.contract.address }, + amount: USDtzRewards.toString(), + }) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:REFERRAL] USDtz`); await dex.updateStorage({ pools: [pool_id.toString()] }); let upd_ref_stor = await dex.contract @@ -98,10 +100,13 @@ export async function getReferralRewardsSuccessCase( 1: { fa12: tokens.USDtz.contract.address }, }); expect(updUSDtzRewards.toNumber()).toBe(0); - op = await dex.contract.methods - .claim_referral("fa12", tokens.kUSD.contract.address, kUSDRewards) + op = await dex.contract.methodsObject + .claim_referral({ + token: { fa12: tokens.kUSD.contract.address }, + amount: kUSDRewards.toString(), + }) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:REFERRAL] kUSD`); await dex.updateStorage({ pools: [pool_id.toString()] }); upd_ref_stor = await dex.contract.storage().then((storage: DexStorage) => { @@ -112,15 +117,18 @@ export async function getReferralRewardsSuccessCase( 1: { fa12: tokens.kUSD.contract.address }, }); expect(updkUSDRewards.toNumber()).toBe(0); - op = await dex.contract.methods - .claim_referral( - "fa2", - tokens.uUSD.contract.address, - new BigNumber(defaultTokenId), - uUSDRewards - ) + op = await dex.contract.methodsObject + .claim_referral({ + token: { + fa2: { + token_address: tokens.uUSD.contract.address, + token_id: new BigNumber(defaultTokenId).toString(), + }, + }, + amount: uUSDRewards.toString(), + }) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:REFERRAL] uUSD`); upd_ref_stor = await dex.contract.storage().then((storage: DexStorage) => { return storage.storage.referral_rewards; @@ -137,13 +145,13 @@ export async function getReferralRewardsSuccessCase( expect(upduUSDRewards.toNumber()).toBe(0); const updUSDtz = await tokens.USDtz.contract.views .getBalance(ref_address) - .read(lambdaContractAddress); + .read(); const updkUSD = await tokens.kUSD.contract.views .getBalance(ref_address) - .read(lambdaContractAddress); + .read(); const upduUSD = await tokens.uUSD.contract.views .balance_of([{ owner: ref_address, token_id: "0" }]) - .read(lambdaContractAddress); + .read(); expect(updUSDtz.minus(initUSDtz).toNumber()).toStrictEqual( init_rewards.USDtz.toNumber() ); diff --git a/test/Dex/cases/rewards/staker.ts b/test/Dex/cases/rewards/staker.ts index 4465c68..b9ed27c 100644 --- a/test/Dex/cases/rewards/staker.ts +++ b/test/Dex/cases/rewards/staker.ts @@ -32,10 +32,14 @@ export async function harvestFromPoolSuccessCase( new BigNumber(0).toNumber() ); }); - const op = await dex.contract.methods - .stake("remove", pool_id, new BigNumber(0)) + const op = await dex.contract.methodsObject + .stake({ + remove: { + pool_id: pool_id, + amount: new BigNumber(0).toString(), + }}) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); await dex.updateStorage({ pools: [pool_id.toString()] }); const upd_total_stake = dex.storage.storage.pools[pool_id.toNumber()].staker_accumulator diff --git a/test/Dex/cases/strategy/auto_rebalance.ts b/test/Dex/cases/strategy/auto_rebalance.ts new file mode 100644 index 0000000..02d6872 --- /dev/null +++ b/test/Dex/cases/strategy/auto_rebalance.ts @@ -0,0 +1,225 @@ +import BigNumber from "bignumber.js"; +import { Contract, OpKind, TransactionOperation } from "@taquito/taquito"; +import { + OperationContentsAndResultTransaction, + InternalOperationResult, +} from "@taquito/rpc"; +import Dex from "../../API"; +import { PairInfo } from "../../API/types"; + +async function autoRebalanceCheck( + dex: Dex, + yupana: Contract, + strategy: Contract, + pool_id: BigNumber, + operation: TransactionOperation +) { + await dex.updateStorage({ pools: [pool_id.toString()] }); + const pool: PairInfo = dex.storage.storage.pools[pool_id.toString()]; + const internals = ( + operation.results[0] 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) => + x.kind === OpKind.TRANSACTION && + x.parameters?.entrypoint === "update_token_state" && + x.destination == strategy.address && + x.source === dex.contract.address + ) + ).toMatchObject({ result: { status: "applied" } }); + internals + .filter( + (x) => + x.kind === OpKind.TRANSACTION && + (x.parameters?.entrypoint === "redeem" || + x.parameters?.entrypoint === "mint") && + x.destination === yupana.address && + 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"); + const delta = value.delta_rate_f.div("1e18"); + const real_rate = on_strat.div(full_res); + if (value.is_rebalance) { + expect(real_rate.toNumber()).toBeLessThanOrEqual( + expected_rate.plus(delta).toNumber() + ); + expect(real_rate.toNumber()).toBeGreaterThanOrEqual( + expected_rate.minus(delta).toNumber() + ); + } + 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}` + ); + }); +} + +export async function swapRebalanceSuccessCase( + dex: Dex, + yupana: Contract, + strategy: Contract, + pool_id: BigNumber, + route: { + i: BigNumber; + j: BigNumber; + } +) { + 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 reserves_i = pool.tokens_info.get(route.i.toString()).reserves; + const conf_i = strategyStore.configuration.get(route.i.toString()); + const amount_to_swap_to_slash = reserves_i + .multipliedBy(conf_i.des_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) + ); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); +} + +export async function investRebalanceSuccessCase( + dex: Dex, + yupana: Contract, + strategy: Contract, + pool_id: BigNumber, + amounts: Map +) { + await dex.updateStorage({ + pools: [pool_id.toString()], + tokens: [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(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) + ); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); +} + +export async function divestRebalanceSuccessCase( + dex: Dex, + yupana: Contract, + strategy: Contract, + pool_id: BigNumber, + min_amounts: Map, + shares: BigNumber +) { + await dex.updateStorage({ + pools: [pool_id.toString()], + tokens: [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(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) + ); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); +} + +export async function divestOneRebalanceSuccessCase( + dex: Dex, + yupana: Contract, + strategy: Contract, + pool_id: BigNumber, + i: BigNumber, + output: BigNumber, + shares: BigNumber +) { + 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])); + 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) + ); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); +} + +export async function divestImbalanceRebalanceSuccessCase( + dex: Dex, + yupana: Contract, + strategy: Contract, + pool_id: BigNumber, + outputs: Map, + shares: BigNumber +) { + await dex.updateStorage({ + pools: [pool_id.toString()], + tokens: [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(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) + ); + await autoRebalanceCheck(dex, yupana, strategy, pool_id, operation); +} diff --git a/test/Dex/cases/strategy/before.ts b/test/Dex/cases/strategy/before.ts new file mode 100644 index 0000000..e71ceb9 --- /dev/null +++ b/test/Dex/cases/strategy/before.ts @@ -0,0 +1,186 @@ +import { TezosToolkit, Contract, MichelsonMap } from "@taquito/taquito"; +import { + OperationContentsAndResultTransaction, + OperationResultOrigination, +} from "@taquito/rpc"; +import { BigNumber } from "bignumber.js"; + +import { IndexMap, TokensMap } from "../../../utils/types"; +import { getMichelsonCode } from "../../../utils/mocks/getMichelsonCode"; +import { Dex } from "../../API/dexAPI"; + +export async function setupYupanaMocks( + tokens: TokensMap, + Tezos: TezosToolkit +): Promise<{ + yupana: Contract; + ordering: IndexMap; + price_feed: Contract; +}> { + const yupanaStorage = { + ledger: new MichelsonMap(), + tokens: MichelsonMap.fromLiteral({ + 0: { + mainToken: { fa12: tokens.USDtz.contract.address }, + interestUpdateTime: "0", + priceUpdateTime: "0", + exchangeRateF: new BigNumber("1e18"), + totalSupplyF: 0, + totalLiquidityF: 0, + lastPrice: 0, + }, + 1: { + mainToken: { fa12: tokens.kUSD.contract.address }, + interestUpdateTime: "0", + priceUpdateTime: "0", + exchangeRateF: new BigNumber("1e18"), + totalSupplyF: 0, + totalLiquidityF: 0, + lastPrice: 0, + }, + 2: { + mainToken: { + fa2: { + token_address: tokens.uUSD.contract.address, + token_id: 0, + }, + }, + interestUpdateTime: "0", + priceUpdateTime: "0", + exchangeRateF: new BigNumber("1e18"), + totalSupplyF: 0, + totalLiquidityF: 0, + lastPrice: 0, + }, + }), + priceFeedProxy: "tz1ZZZZZZZZZZZZZZZZZZZZZZZZZZZZNkiRg", + }; + const ordering = { + USDtz: "0", + kUSD: "1", + uUSD: "2", + }; + const mockYupanaContractOrigination = await Tezos.contract.originate({ + code: getMichelsonCode("yupana"), + storage: yupanaStorage, + }); + await mockYupanaContractOrigination.confirmation(1); + const yupana = await mockYupanaContractOrigination.contract(); + console.debug("[MOCKS] Yupana: ", yupana.address); + const priceFeedStorage = { + yToken: yupana.address, + prices: MichelsonMap.fromLiteral({ + 0: 10_000_000, + 1: 11_000_000, + 2: 12_000_000, + }), + }; + const pfContractOrigination = await Tezos.contract.originate({ + code: getMichelsonCode("pf"), + storage: priceFeedStorage, + }); + await pfContractOrigination.confirmation(1); + const price_feed = await pfContractOrigination.contract(); + console.debug("[MOCKS] Price Feed: ", price_feed.address); + await ( + await yupana.methods.setPriceFeed(price_feed.address).send() + ).confirmation(1); + console.debug("[MOCKS] Price Feed Connected"); + + const mint = await Tezos.contract + .batch() + .withContractCall( + tokens.kUSD.contract.methods.approve(yupana.address, 1_000_000) + ) + .withContractCall( + tokens.uUSD.contract.methodsObject.update_operators([ + { + add_operator: { + owner: await Tezos.signer.publicKeyHash(), + operator: yupana.address, + token_id: 0, + }, + }, + ]) + ) + .withContractCall( + price_feed.methodsObject.getPrice([ordering.kUSD, ordering.uUSD]) + ) + .withContractCall(yupana.methodsObject.updateInterest(ordering.kUSD)) + .withContractCall(yupana.methodsObject.updateInterest(ordering.uUSD)) + .withContractCall( + yupana.methodsObject.mint({ + tokenId: ordering.kUSD, + amount: 1_000_000, + minReceived: 1, + }) + ) + .withContractCall( + yupana.methodsObject.mint({ + tokenId: ordering.uUSD, + amount: 1_000_000, + minReceived: 1, + }) + ) + .send(); + await mint.confirmation(1); + console.debug("[MOCKS] Yupana markets minted"); + + return { yupana, ordering, price_feed }; +} + +export async function originateStrategy( + dex: Dex, + pool_id: BigNumber, + yupana: Contract, + price_feed: Contract, + Tezos: TezosToolkit +): Promise<{ + strategy_factory: Contract; + strategy: Contract; +}> { + 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, + }, + deployed_strategies: new MichelsonMap(), + connected_pools: new MichelsonMap(), + }, + }); + await strategy_factory_origination.confirmation(1); + const strategy_factory = await strategy_factory_origination.contract(); + console.debug("[STRATEGY] Strategy Factory: ", strategy_factory.address); + const poolInfo = { + pool_contract: dex.contract.address, + pool_id: pool_id, + }; + 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, + }, + }) + .send(); + await deploy_strategy_request.confirmation(2); + const deployed_strategy = ( + ( + deploy_strategy_request + .results[0] as OperationContentsAndResultTransaction + ).metadata.internal_operation_results[0] + .result as OperationResultOrigination + ).originated_contracts[0]; + const strategy = await Tezos.contract.at(deployed_strategy); + console.debug( + "[STRATEGY] Deployed Strategy for ", + poolInfo.pool_contract + `[${poolInfo.pool_id.toString()}]`, + " is ", + strategy.address + ); + 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 new file mode 100644 index 0000000..5e9da81 --- /dev/null +++ b/test/Dex/cases/strategy/cofigure-token/configure_strategy.ts @@ -0,0 +1,67 @@ +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 new file mode 100644 index 0000000..9e545d1 --- /dev/null +++ b/test/Dex/cases/strategy/cofigure-token/connect_token.ts @@ -0,0 +1,98 @@ +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 new file mode 100644 index 0000000..546c873 --- /dev/null +++ b/test/Dex/cases/strategy/cofigure-token/index.ts @@ -0,0 +1,4 @@ +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 new file mode 100644 index 0000000..bc99a99 --- /dev/null +++ b/test/Dex/cases/strategy/cofigure-token/is_rebalance.ts @@ -0,0 +1,29 @@ +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 new file mode 100644 index 0000000..ba163f4 --- /dev/null +++ b/test/Dex/cases/strategy/cofigure-token/rebalance.ts @@ -0,0 +1,69 @@ +import BigNumber from "bignumber.js"; +import { TezosToolkit, Contract, OpKind } from "@taquito/taquito"; +import { + OperationContentsAndResultTransaction, + InternalOperationResult, +} from "@taquito/rpc"; +import Dex from "../../../API"; +import { PairInfo } from "../../../API/types"; + +export async function manualRebalanceSuccessCase( + dex: Dex, + yupana: Contract, + strategy: Contract, + 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); + await dex.updateStorage({ pools: [pool_id.toString()] }); + 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" } }); + expect( + internals.find( + (x) => + x.kind === OpKind.TRANSACTION && + x.parameters?.entrypoint === "update_token_state" && + x.destination == strategy.address && + x.source === dex.contract.address + ) + ).toMatchObject({ result: { status: "applied" } }); + internals + .filter( + (x) => + x.kind === OpKind.TRANSACTION && + (x.parameters?.entrypoint === "redeem" || + x.parameters?.entrypoint === "mint") && + x.destination === yupana.address && + 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"); + const real_rate = on_strat.div(full_res); + expect(real_rate.toNumber()).toBeCloseTo(expected_rate.toNumber(), 9); + console.debug( + `[STRATEGY] Rebalance [${key.toString()}] - full: ${full_res}, on strategy: ${on_strat} (${on_strat + .div(full_res) + .multipliedBy(100)}%)` + ); + }); +} diff --git a/test/Dex/cases/strategy/connect.ts b/test/Dex/cases/strategy/connect.ts new file mode 100644 index 0000000..aa3888b --- /dev/null +++ b/test/Dex/cases/strategy/connect.ts @@ -0,0 +1,45 @@ +import BigNumber from "bignumber.js"; +import { TezosToolkit } from "@taquito/taquito"; +import Dex from "../../API"; +import { PairInfo } from "../../API/types"; + +export async function setStrategyAddrSuccessCase( + dex: Dex, + pool_id: BigNumber, + strategy: string +) { + 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; + 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; + expect(strategy).toStrictEqual(updatedStrat); +} + +export async function removeStrategyAddrSuccessCase( + dex: Dex, + pool_id: BigNumber +) { + 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; + 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; + expect(updatedStrat).toBeNull(); + + // TODO: Remove liquidity from old Strategy checks +} diff --git a/test/Dex/cases/strategy/index.ts b/test/Dex/cases/strategy/index.ts new file mode 100644 index 0000000..b74358e --- /dev/null +++ b/test/Dex/cases/strategy/index.ts @@ -0,0 +1,15 @@ +import * as strategyConfigToken from "./cofigure-token"; +import * as strategyConnect from "./connect"; +import * as before from "./before"; +import * as autoRebalance from "./auto_rebalance"; + +export const strategyCases = { + token: strategyConfigToken, + connect: strategyConnect, + autoRebalance, +}; + +export default { + before, + cases: strategyCases, +}; diff --git a/test/Dex/cases/views/pool.ts b/test/Dex/cases/views/pool.ts index 6a37891..579ac60 100644 --- a/test/Dex/cases/views/pool.ts +++ b/test/Dex/cases/views/pool.ts @@ -31,17 +31,17 @@ export async function getTokenMapSuccessCase( idx_map: IndexMap ) { const value = (await dex.contract.contractViews - .get_token_map(pool_id) + .get_token_map(pool_id.toString()) .executeView({ viewCaller: accounts["alice"].pkh })) as MichelsonMap< string, FA12TokenType | FA2TokenType >; value.forEach((value, key) => { - if (key == idx_map.USDtz) { + if (key.toString() == idx_map.USDtz.toString()) { expect(tokens_map.USDtz.contract.address).toStrictEqual( (value as FA12TokenType).fa12 ); - } else if (key == idx_map.kUSD) { + } else if (key.toString() == idx_map.kUSD.toString()) { expect(tokens_map.kUSD.contract.address).toStrictEqual( (value as FA12TokenType).fa12 ); @@ -62,28 +62,26 @@ export async function getLPValueSuccessCase( dex.updateStorage({ pools: [pool_id.toString()] }); const pool_info: PairInfo = dex.storage.storage.pools[pool_id.toString()]; const tokens_info = pool_info.tokens_info; - const view_result = (await dex.contract.contractViews - .get_tok_per_share(pool_id) - .executeView({ viewCaller: accounts["alice"].pkh })) as MichelsonMap< - string, - BigNumber - >; + const view_result = await dex.contract.contractViews + .get_tok_per_share(pool_id.toString()) + .executeView({ viewCaller: accounts["alice"].pkh }); const pp_tks = { USDtz: null, kUSD: null, uUSD: null, }; view_result.forEach((value, key) => { - const token_info = tokens_info.get(key); + const token_info = tokens_info.get(key.toString()); const expected = token_info.reserves .multipliedBy(one_LP) .dividedToIntegerBy(pool_info.total_supply); + value = new BigNumber(value); expect(value.toNumber()).toStrictEqual(expected.toNumber()); - if (key == map_tokens_idx.USDtz) + if (key.toString() == map_tokens_idx.USDtz) pp_tks.USDtz = value.dividedBy(decimals.USDtz); - else if (key == map_tokens_idx.kUSD) + else if (key.toString() == map_tokens_idx.kUSD) pp_tks.kUSD = value.dividedBy(decimals.kUSD); - else if (key == map_tokens_idx.uUSD) + else if (key.toString() == map_tokens_idx.uUSD) pp_tks.uUSD = value.dividedBy(decimals.uUSD); }); console.debug( @@ -128,10 +126,10 @@ export async function getDySuccessCase( const i = token_idxs.uUSD; const j = token_idxs.USDtz; const params = { - pool_id: pool_id, - i: i, - j: j, - dx: dx, + pool_id: pool_id.toString(), + i: i.toString(), + j: j.toString(), + dx: dx.toString(), }; const dy = await dex.contract.contractViews .get_dy(params) diff --git a/test/Factory/API/factoryAPI.ts b/test/Factory/API/factoryAPI.ts index 0d76f84..216fc8e 100644 --- a/test/Factory/API/factoryAPI.ts +++ b/test/Factory/API/factoryAPI.ts @@ -16,17 +16,19 @@ import { FactoryStorage } from "./types"; import admin_lambdas_comp from "../../../build/lambdas/factory/Admin_lambdas.json"; import dex_lambdas_comp from "../../../build/lambdas/factory/Dex_lambdas.json"; import token_lambdas_comp from "../../../build/lambdas/factory/Token_lambdas.json"; +import strat_lambdas_comp from "../../../build/lambdas/test/Strategy_lambdas.json"; import { confirmOperation } from "../../../utils/confirmation"; import BigNumber from "bignumber.js"; import { defaultTokenId, TokenFA12, TokenFA2 } from "../../Token"; import { FeeType, TokenInfo } from "../../Dex/API/types"; import fs from "fs"; import { DevEnabledContract } from "../../Developer/API/devAPI"; +import { StrategyFactorySetter } from "../../Strategy/API/strategyFactoryMethod"; const init_func_bytes = fs .readFileSync("./build/lambdas/factory/add_pool.txt") .toString(); -export class DexFactory implements DevEnabledContract { +export class DexFactory implements DevEnabledContract, StrategyFactorySetter { public contract: ContractAbstraction; public storage: FactoryStorage; @@ -41,7 +43,7 @@ export class DexFactory implements DevEnabledContract { const op = await factory.contract.methods .set_init_function(init_func_bytes) .send(); - await confirmOperation(tezos, op.hash); + await op.confirmation(2); await setFunctionBatchCompilled( tezos, factoryAddress, @@ -60,16 +62,23 @@ export class DexFactory implements DevEnabledContract { tezos, factoryAddress, "Token", - 5, + 3, token_lambdas_comp ); await setFunctionBatchCompilled( tezos, factoryAddress, "Dex", - 8, + 3, dex_lambdas_comp ); + await setFunctionBatchCompilled( + tezos, + factoryAddress, + "Strategy", + 3, + strat_lambdas_comp + ); await factory.updateStorage(); return factory; } @@ -87,6 +96,7 @@ export class DexFactory implements DevEnabledContract { // "dev_lambdas", "token_lambdas", "admin_lambdas", + "strat_lambdas", ].includes(key) ) continue; @@ -114,6 +124,7 @@ export class DexFactory implements DevEnabledContract { // "dev_lambdas", "token_lambdas", "admin_lambdas", + "strat_lambdas", ].includes(key) ) continue; @@ -139,7 +150,7 @@ export class DexFactory implements DevEnabledContract { await this.updateStorage({}); const operation = await this.contract.methods.set_dev_address(dev).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -148,7 +159,7 @@ export class DexFactory implements DevEnabledContract { tezos: TezosToolkit ): Promise { const operation = await this.contract.methods.set_dev_fee(fee).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } async setInitPrice( @@ -156,7 +167,7 @@ export class DexFactory implements DevEnabledContract { tezos: TezosToolkit ): Promise { const operation = await this.contract.methods.set_price(price).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } async setBurnRate( @@ -164,7 +175,7 @@ export class DexFactory implements DevEnabledContract { tezos: TezosToolkit ): Promise { const operation = await this.contract.methods.set_burn_rate(rate).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } async addRemWhitelist( @@ -176,13 +187,13 @@ export class DexFactory implements DevEnabledContract { const operation = await this.contract.methods .set_whitelist(add, candidate) .send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } async claimRewards(tezos: TezosToolkit): Promise { await this.updateStorage({}); const operation = await this.contract.methods.claim_rewards(null).send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); return operation; } async addPool( @@ -256,13 +267,34 @@ export class DexFactory implements DevEnabledContract { fees, }); const operation = await opr.send(); - await confirmOperation(tezos, operation.hash); + await operation.confirmation(2); const inputs = new MichelsonMap(); tokens_info.forEach((value, key) => inputs.set(key, { token: input_tokens[key], value: value.reserves }) ); const op = await this.contract.methods.start_dex(inputs).send(); - await confirmOperation(tezos, op.hash); + await op.confirmation(2); return operation; } + + async manageStrategyFactories( + strategy_factory: string, + add: boolean + ): Promise { + const op = await this.contract.methods + .set_strategy_factory(add, strategy_factory) + .send(); + await op.confirmation(2); + return op; + } + async addStrategyFactory( + strategy_factory: string + ): Promise { + return this.manageStrategyFactories(strategy_factory, true); + } + async removeStrategyFactory( + strategy_factory: string + ): Promise { + return this.manageStrategyFactories(strategy_factory, false); + } } diff --git a/test/Factory/API/storage.ts b/test/Factory/API/storage.ts index 2d9dd2e..a52678e 100644 --- a/test/Factory/API/storage.ts +++ b/test/Factory/API/storage.ts @@ -20,10 +20,12 @@ export const factory_storage: FactoryStorage = { quipu_rewards: new BigNumber(0), whitelist: [] as TezosAddress[], deployers: new MichelsonMap(), + strategy_factory: [] as TezosAddress[], } as InnerFactoryStore, admin_lambdas: new MichelsonMap(), dex_lambdas: new MichelsonMap(), token_lambdas: new MichelsonMap(), + strat_lambdas: new MichelsonMap(), metadata: new MichelsonMap(), }; diff --git a/test/Factory/API/types.ts b/test/Factory/API/types.ts index ac2533c..0ac1602 100644 --- a/test/Factory/API/types.ts +++ b/test/Factory/API/types.ts @@ -14,6 +14,7 @@ export declare type InnerFactoryStore = { quipu_rewards: BigNumber; whitelist: TezosAddress[]; deployers: MichelsonMap; + strategy_factory: TezosAddress[]; }; export declare type FactoryStorage = { @@ -21,6 +22,7 @@ export declare type FactoryStorage = { admin_lambdas: MichelsonMap; dex_lambdas: MichelsonMap; token_lambdas: MichelsonMap; + strat_lambdas: MichelsonMap; init_func?: BytesString; metadata: MichelsonMap; }; diff --git a/test/Factory/cases/before.ts b/test/Factory/cases/before.ts index e31c54b..faaaff3 100644 --- a/test/Factory/cases/before.ts +++ b/test/Factory/cases/before.ts @@ -10,6 +10,7 @@ import dev_lambdas_comp from "../../../build/lambdas/test/Dev_lambdas.json"; import dex_lambdas_comp from "../../../build/lambdas/test/Dex_lambdas.json"; import token_lambdas_comp from "../../../build/lambdas/test/Token_lambdas.json"; import admin_lambdas_comp from "../../../build/lambdas/test/Admin_lambdas.json"; +import strat_lambdas_comp from "../../../build/lambdas/test/Strategy_lambdas.json"; import { defaultTokenId, TokenFA2 } from "../../Token"; import { setupQuipuGovToken } from "../../utils/tokensSetups"; import { accounts, dev_fee } from "../../../utils/constants"; @@ -28,17 +29,10 @@ export async function setupFactoryEnvironment( factory: DexFactory; // tokens: TokensMap; quipuToken: TokenFA2; - lambdaContractAddress: string; }> { const config = await prepareProviderOptions(developer); Tezos.setProvider(config); - const op = await Tezos.contract.originate({ - code: VIEW_LAMBDA.code, - storage: VIEW_LAMBDA.storage, - }); - await confirmOperation(Tezos, op.hash); const quipuToken = await setupQuipuGovToken(Tezos); - const lambdaContractAddress = op.contractAddress; storage.storage.dev_store = { dev_address: accounts[developer].pkh, dev_fee_f: new BigNumber(0), @@ -64,5 +58,5 @@ export async function setupFactoryEnvironment( chalk.bold.underline(fact_op.contractAddress) ); const factory = await DexFactory.init(Tezos, fact_op.contractAddress); - return { factory, quipuToken, lambdaContractAddress }; + return { factory, quipuToken }; } diff --git a/test/Factory/cases/dev.ts b/test/Factory/cases/dev.ts index 00dbd8c..7090d83 100644 --- a/test/Factory/cases/dev.ts +++ b/test/Factory/cases/dev.ts @@ -2,3 +2,7 @@ export { setDevAddrSuccessCase, setDevFeeSuccessCase, } from "../../Developer/cases"; +export { + addStrategyFactorySuccessCase, + removeStrategyFactorySuccessCase, +} from "../../Strategy/cases"; diff --git a/test/Factory/cases/init_pool.ts b/test/Factory/cases/init_pool.ts index 1c39b66..eed5cf1 100644 --- a/test/Factory/cases/init_pool.ts +++ b/test/Factory/cases/init_pool.ts @@ -33,8 +33,7 @@ export async function initializeExchangeSuccessCase( }, approve = false, quipuToken: TokenFA2, - tezos: TezosToolkit, - lambda: TezosAddress + tezos: TezosToolkit ) { const config = await prepareProviderOptions(sender); tezos.setProvider(config); @@ -42,7 +41,7 @@ export async function initializeExchangeSuccessCase( const init_balance = await quipuToken.contract.views .balance_of([{ owner: sender_addr, token_id: "0" }]) - .read(lambda); + .read(); await factory.updateStorage({}); const init_rew: BigNumber = factory.storage.storage.quipu_rewards; @@ -72,7 +71,7 @@ export async function initializeExchangeSuccessCase( await factory.updateStorage({}); const upd_balance: BigNumber = await quipuToken.contract.views .balance_of([{ owner: sender_addr, token_id: "0" }]) - .read(lambda); + .read(); const upd_rew: BigNumber = factory.storage.storage.quipu_rewards; expect(init_balance[0].balance.minus(price).toNumber()).toStrictEqual( diff --git a/test/Factory/cases/rewards.ts b/test/Factory/cases/rewards.ts index 9d955f3..7e23a07 100644 --- a/test/Factory/cases/rewards.ts +++ b/test/Factory/cases/rewards.ts @@ -36,7 +36,6 @@ export async function getDeveloperRewardsDexSuccessCase( tokens: TokensMap, pool_id: BigNumber, developer: AccountsLiteral, - lambdaContractAddress: string, Tezos: TezosToolkit ) { const config = await prepareProviderOptions(developer); @@ -53,13 +52,13 @@ export async function getDeveloperRewardsDexSuccessCase( }); const initUSDtz = await tokens.USDtz.contract.views .getBalance(developer_address) - .read(lambdaContractAddress); + .read(); const initkUSD = await tokens.kUSD.contract.views .getBalance(developer_address) - .read(lambdaContractAddress); + .read(); const inituUSD = await tokens.uUSD.contract.views .balance_of([{ owner: developer_address, token_id: "0" }]) - .read(lambdaContractAddress); + .read(); const USDtzRewards = await dev_stor.get({ fa12: tokens.USDtz.contract.address, @@ -93,7 +92,7 @@ export async function getDeveloperRewardsDexSuccessCase( let op = await dex.contract.methods .claim_developer("fa12", tokens.USDtz.contract.address, USDtzRewards) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:DEVELOPER] USDtz`); await dex.updateStorage({ pools: [pool_id.toString()] }); let upd_dev_stor = await dex.contract @@ -108,7 +107,7 @@ export async function getDeveloperRewardsDexSuccessCase( op = await dex.contract.methods .claim_developer("fa12", tokens.kUSD.contract.address, kUSDRewards) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:DEVELOPER] kUSD`); await dex.updateStorage({ pools: [pool_id.toString()] }); upd_dev_stor = await dex.contract.storage().then((storage: DexStorage) => { @@ -126,7 +125,7 @@ export async function getDeveloperRewardsDexSuccessCase( uUSDRewards ) .send(); - await confirmOperation(Tezos, op.hash); + await op.confirmation(2); console.debug(`[${chalk.bgGreenBright.red("CLAIM")}:DEVELOPER] uUSD`); upd_dev_stor = await dex.contract.storage().then((storage: DexStorage) => { return storage.storage.dev_rewards; @@ -140,13 +139,13 @@ export async function getDeveloperRewardsDexSuccessCase( expect(upduUSDRewards.toNumber()).toBe(0); const updUSDtz = await tokens.USDtz.contract.views .getBalance(developer_address) - .read(lambdaContractAddress); + .read(); const updkUSD = await tokens.kUSD.contract.views .getBalance(developer_address) - .read(lambdaContractAddress); + .read(); const upduUSD = await tokens.uUSD.contract.views .balance_of([{ owner: developer_address, token_id: "0" }]) - .read(lambdaContractAddress); + .read(); expect(updUSDtz.minus(initUSDtz).toNumber()).toStrictEqual( init_rewards.USDtz.toNumber() ); diff --git a/test/Strategy/API/strategyFactoryMethod.ts b/test/Strategy/API/strategyFactoryMethod.ts new file mode 100644 index 0000000..e1b7585 --- /dev/null +++ b/test/Strategy/API/strategyFactoryMethod.ts @@ -0,0 +1,23 @@ +import { Contract } from "../../utils/types"; +import { TezosAddress } from "../../../utils/helpers"; +import { DevStorage } from "../../Developer/API/storage"; +import { TezosToolkit, TransactionOperation } from "@taquito/taquito"; + +export declare interface StrategyFactorySetter extends Contract { + storage: any & { + storage: any & { + dev_store: DevStorage; + strategy_factory: TezosAddress[]; + }; + }; + manageStrategyFactories: ( + strategy_factory: TezosAddress, + add: boolean + ) => Promise; + addStrategyFactory: ( + strategy_factory: TezosAddress + ) => Promise; + removeStrategyFactory: ( + strategy_factory: TezosAddress + ) => Promise; +} diff --git a/test/Strategy/cases/index.ts b/test/Strategy/cases/index.ts new file mode 100644 index 0000000..db5cb7b --- /dev/null +++ b/test/Strategy/cases/index.ts @@ -0,0 +1,34 @@ +import { TezosAddress } from "../../../utils/helpers"; +import { StrategyFactorySetter } from "../API/strategyFactoryMethod"; + +export async function addStrategyFactorySuccessCase( + contract: StrategyFactorySetter, + strategy_factory: TezosAddress +) { + await contract.updateStorage({}); + const factories: Set = + contract.storage.storage.strategy_factory; + expect(factories).not.toContain(strategy_factory); + await contract.addStrategyFactory(strategy_factory); + + await contract.updateStorage({}); + const new_factories: Set = + contract.storage.storage.strategy_factory; + expect(new_factories).toContain(strategy_factory); +} + +export async function removeStrategyFactorySuccessCase( + contract: StrategyFactorySetter, + strategy_factory: TezosAddress +) { + await contract.updateStorage({}); + const factories: Set = + contract.storage.storage.strategy_factory; + expect(factories).toContain(strategy_factory); + await contract.removeStrategyFactory(strategy_factory); + + await contract.updateStorage({}); + const new_factories: Set = + contract.storage.storage.strategy_factory; + expect(new_factories).not.toContain(strategy_factory); +} diff --git a/test/Token/storage/USDtz_storage.ts b/test/Token/storage/USDtz_storage.ts index 895a5d5..81198e5 100644 --- a/test/Token/storage/USDtz_storage.ts +++ b/test/Token/storage/USDtz_storage.ts @@ -8,20 +8,20 @@ const USDtzstorage = { admin: aliceAddress, ledger: MichelsonMap.fromLiteral({ [aliceAddress]: { - balance: "10000000000000", + balance: "10000000000000000", approvals: MichelsonMap.fromLiteral({}), }, [bobAddress]: { - balance: "10000000000000", + balance: "10000000000000000", approvals: MichelsonMap.fromLiteral({}), }, [eveAddress]: { - balance: "10000000000000", + balance: "10000000000000000", approvals: MichelsonMap.fromLiteral({}), }, }), paused: false, - totalSupply: "3000000000000", + totalSupply: "3000000000000000", }; export default USDtzstorage; diff --git a/test/Token/storage/kUSD_storage.ts b/test/Token/storage/kUSD_storage.ts index c4c62e3..8703e54 100644 --- a/test/Token/storage/kUSD_storage.ts +++ b/test/Token/storage/kUSD_storage.ts @@ -8,15 +8,15 @@ const kUSDstorage = { administrator: aliceAddress, balances: MichelsonMap.fromLiteral({ [aliceAddress]: { - balance: "1000000000000000000000000000000", + balance: "1000000000000000000000000000000000", approvals: MichelsonMap.fromLiteral({}), }, [bobAddress]: { - balance: "1000000000000000000000000000000", + balance: "1000000000000000000000000000000000", approvals: MichelsonMap.fromLiteral({}), }, [eveAddress]: { - balance: "1000000000000000000000000000000", + balance: "1000000000000000000000000000000000", approvals: MichelsonMap.fromLiteral({}), }, }), diff --git a/test/Token/storage/uUSD_storage.ts b/test/Token/storage/uUSD_storage.ts index bf4c70e..2cbd15a 100644 --- a/test/Token/storage/uUSD_storage.ts +++ b/test/Token/storage/uUSD_storage.ts @@ -12,7 +12,7 @@ ledger.set( token_id: defaultTokenId, owner: aliceAddress, }, - "1000000000000000000000000" + "1000000000000000000000000000" ); // eslint-disable-next-line jest/require-hook ledger.set( @@ -20,7 +20,7 @@ ledger.set( token_id: defaultTokenId, owner: bobAddress, }, - "1000000000000000000000000" + "1000000000000000000000000000" ); // eslint-disable-next-line jest/require-hook ledger.set( @@ -28,7 +28,7 @@ ledger.set( token_id: defaultTokenId, owner: eveAddress, }, - "1000000000000000000000000" + "1000000000000000000000000000" ); const admins = new MichelsonMap(); // eslint-disable-next-line jest/require-hook diff --git a/test/Token/tokenFA12.ts b/test/Token/tokenFA12.ts index ed0c101..b4ffdab 100644 --- a/test/Token/tokenFA12.ts +++ b/test/Token/tokenFA12.ts @@ -67,7 +67,7 @@ export class TokenFA12 implements Token { const operation = await this.contract.methods .transfer(from, to, amount) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -77,7 +77,7 @@ export class TokenFA12 implements Token { tokenId = "0" ): Promise { const operation = await this.contract.methods.approve(to, amount).send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -88,7 +88,7 @@ export class TokenFA12 implements Token { const operation = await this.contract.methods .getBalance(owner, contract) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -100,7 +100,7 @@ export class TokenFA12 implements Token { const operation = await this.contract.methods .getAllowance(owner, trusted, contract) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -108,7 +108,7 @@ export class TokenFA12 implements Token { const operation = await this.contract.methods .getTotalSupply(null, contract) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } } diff --git a/test/Token/tokenFA2.ts b/test/Token/tokenFA2.ts index 992513c..0268ba6 100644 --- a/test/Token/tokenFA2.ts +++ b/test/Token/tokenFA2.ts @@ -84,7 +84,7 @@ export class TokenFA2 implements Token { ]) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -115,7 +115,7 @@ export class TokenFA2 implements Token { const operation = await this.contract.methods .balance_of({ requests, contract }) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -123,7 +123,7 @@ export class TokenFA2 implements Token { const operation = await this.contract.methods .token_metadata_registry(receiver) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } @@ -146,7 +146,7 @@ export class TokenFA2 implements Token { }) ) .send(); - await confirmOperation(this.Tezos, operation.hash); + await operation.confirmation(2); return operation; } } diff --git a/test/utils/mocks/artifacts/pf.tz b/test/utils/mocks/artifacts/pf.tz new file mode 100644 index 0000000..314ea1e --- /dev/null +++ b/test/utils/mocks/artifacts/pf.tz @@ -0,0 +1,43 @@ +{ parameter + (or (or (unit %default) (set %getPrice nat)) + (pair %setPrice (nat %token_id) (nat %price))) ; + storage (pair (address %yToken) (big_map %prices nat nat)) ; + code { UNPAIR ; + IF_LEFT + { IF_LEFT + { DROP 2 ; PUSH string "42" ; FAILWITH } + { DUP 2 ; + NIL operation ; + DIG 2 ; + ITER { SWAP ; + PUSH string "wrong Yupana pCb entrypoint" ; + DUP 5 ; + CAR ; + CONTRACT %priceCallback (pair (nat %tokenId) (nat %amount)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DUP 6 ; + CDR ; + DUP 5 ; + GET ; + IF_NONE { PUSH nat 1000000 } {} ; + DIG 4 ; + PAIR ; + TRANSFER_TOKENS ; + CONS } ; + DIG 2 ; + DROP ; + PAIR } } + { DUP 2 ; + DIG 2 ; + CDR ; + DUP 3 ; + CDR ; + SOME ; + DIG 3 ; + CAR ; + UPDATE ; + UPDATE 2 ; + NIL operation ; + PAIR } } } + diff --git a/test/utils/mocks/artifacts/strategy.tz b/test/utils/mocks/artifacts/strategy.tz new file mode 100644 index 0000000..4192b72 --- /dev/null +++ b/test/utils/mocks/artifacts/strategy.tz @@ -0,0 +1,651 @@ +{ 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))) + (nat %pool_token_id) + (nat %lending_market_id)) + (list %update_token_state (pair (nat %pool_token_id) (nat %new_balance))))) + (list %prepare nat)) ; + storage + (pair (address %factory) + (pair %lending_data (address %lending_contract) (address %price_feed_contract)) + (pair %pool_data (address %pool_contract) (nat %pool_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)))) ; + code { LAMBDA + (pair (pair (pair nat nat) address bool) bool) + nat + { UNPAIR ; + UNPAIR ; + UNPAIR ; + DIG 2 ; + UNPAIR ; + PUSH string "Lending has no suited convert view" ; + SWAP ; + DIG 5 ; + DIG 4 ; + DIG 5 ; + DIG 5 ; + PAIR 4 ; + VIEW "convert" + (pair (nat %amount) (timestamp %interestUpdateTime) (timestamp %priceUpdateTime)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + CAR } ; + PUSH string "Factory has no suited dev_address view" ; + PUSH string "No Token yet" ; + 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 } } ; + 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 ; + DIG 9 ; + UNPAIR ; + SWAP ; + PUSH mutez 0 ; + AMOUNT ; + COMPARE ; + GT ; + 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 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 } ; + 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 ; + 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 ; + DUP 3 ; + PAIR ; + DUP 6 ; + CAR ; + DUP 13 ; + SWAP ; + UNIT ; + VIEW "dev_address" address ; + PAIR ; + DUP 9 ; + SWAP ; + EXEC ; + 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 5 ; + GET 3 ; + CDR ; + 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 ; + DIG 5 ; + GET 3 ; + PAIR 3 ; + TRANSFER_TOKENS ; + CONS ; + SWAP } ; + DIG 3 ; + DIG 4 ; + 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 9 ; + DROP 2 ; + PUSH string "Only dex is allowed here" ; + DUP 3 ; + GET 5 ; + CAR ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + IF_LEFT + { DIG 3 ; + DIG 4 ; + DIG 5 ; + DIG 6 ; + DIG 7 ; + DIG 8 ; + DROP 6 ; + SWAP ; + PUSH string "Token already added" ; + DUP 2 ; + GET 6 ; + DUP 4 ; + GET 3 ; + MEM ; + NOT ; + IF { DROP } { FAILWITH } ; + DUP ; + GET 6 ; + DIG 3 ; + DUP 4 ; + CAR ; + UPDATE 1 ; + DUP 4 ; + GET 4 ; + UPDATE 3 ; + DIG 3 ; + GET 3 ; + SWAP ; + 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 ; + CAR ; + DUP 3 ; + CAR ; + CAR ; + DUP 4 ; + CDR ; + PAIR ; + DUP 6 ; + SELF_ADDRESS ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DIG 2 ; + DROP ; + DUP 11 ; + SWAP ; + CONTRACT %approve (pair (address %spender) (nat %value)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 2 ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS } + { DUP 12 ; + 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)))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + NIL (or (pair address address nat) (pair address address nat)) ; + PUSH nat 0 ; + 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) } ; + 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 ; + DIG 4 ; + DIG 5 ; + DIG 6 ; + DIG 7 ; + 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 } ; + PAIR } ; + view "get_pool_data" + unit + (pair (address %pool_contract) (nat %pool_id)) + { CDR ; GET 5 } } + diff --git a/test/utils/mocks/artifacts/strategy_factory.tz b/test/utils/mocks/artifacts/strategy_factory.tz new file mode 100644 index 0000000..aa03621 --- /dev/null +++ b/test/utils/mocks/artifacts/strategy_factory.tz @@ -0,0 +1,754 @@ +{ parameter + (or (pair %deploy_strategy + (pair %pool_info (address %pool_contract) (nat %pool_id)) + (pair %lending_data (address %lending_contract) (address %price_feed_contract))) + (or %use_dev (unit %approve_developer) (address %change_developer))) ; + storage + (pair (pair %dev (address %dev_address) (option %temp_dev_address address)) + (big_map %deployed_strategies + (pair (address %pool_contract) (nat %pool_id)) + address) + (big_map %connected_pools address (pair (address %pool_contract) (nat %pool_id)))) ; + code { PUSH string "Only developer is allowed here" ; + SWAP ; + UNPAIR ; + SWAP ; + PUSH mutez 0 ; + AMOUNT ; + COMPARE ; + GT ; + IF { PUSH string "Sending XTZ not allowed here" ; FAILWITH } {} ; + SWAP ; + IF_LEFT + { SWAP ; + DIG 2 ; + DUP 2 ; + CAR ; + CAR ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + EMPTY_MAP nat (pair (or address (pair address nat)) nat nat timestamp bool timestamp) ; + DUP 3 ; + CAR ; + DUP 4 ; + CDR ; + SELF_ADDRESS ; + PAIR 4 ; + PUSH mutez 0 ; + NONE key_hash ; + PAIR ; + PAIR ; + 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))) + (nat %pool_token_id) + (nat %lending_market_id)) + (list %update_token_state (pair (nat %pool_token_id) (nat %new_balance))))) + (list %prepare nat)) ; + storage + (pair (address %factory) + (pair %lending_data (address %lending_contract) (address %price_feed_contract)) + (pair %pool_data (address %pool_contract) (nat %pool_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)))) ; + code { LAMBDA + (pair (pair (pair nat nat) address bool) bool) + nat + { UNPAIR ; + UNPAIR ; + UNPAIR ; + DIG 2 ; + UNPAIR ; + PUSH string "Lending has no suited convert view" ; + SWAP ; + DIG 5 ; + DIG 4 ; + DIG 5 ; + DIG 5 ; + PAIR 4 ; + VIEW "convert" + (pair (nat %amount) (timestamp %interestUpdateTime) (timestamp %priceUpdateTime)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + CAR } ; + PUSH string "Factory has no suited dev_address view" ; + PUSH string "No Token yet" ; + 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 } } ; + 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 ; + DIG 9 ; + UNPAIR ; + SWAP ; + PUSH mutez 0 ; + AMOUNT ; + COMPARE ; + GT ; + 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 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 } ; + 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 ; + 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 ; + DUP 3 ; + PAIR ; + DUP 6 ; + CAR ; + DUP 13 ; + SWAP ; + UNIT ; + VIEW "dev_address" address ; + PAIR ; + DUP 9 ; + SWAP ; + EXEC ; + 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 5 ; + GET 3 ; + CDR ; + 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 ; + DIG 5 ; + GET 3 ; + PAIR 3 ; + TRANSFER_TOKENS ; + CONS ; + SWAP } ; + DIG 3 ; + DIG 4 ; + 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 9 ; + DROP 2 ; + PUSH string "Only dex is allowed here" ; + DUP 3 ; + GET 5 ; + CAR ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + IF_LEFT + { DIG 3 ; + DIG 4 ; + DIG 5 ; + DIG 6 ; + DIG 7 ; + DIG 8 ; + DROP 6 ; + SWAP ; + PUSH string "Token already added" ; + DUP 2 ; + GET 6 ; + DUP 4 ; + GET 3 ; + MEM ; + NOT ; + IF { DROP } { FAILWITH } ; + DUP ; + GET 6 ; + DIG 3 ; + DUP 4 ; + CAR ; + UPDATE 1 ; + DUP 4 ; + GET 4 ; + UPDATE 3 ; + DIG 3 ; + GET 3 ; + SWAP ; + 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 ; + CAR ; + DUP 3 ; + CAR ; + CAR ; + DUP 4 ; + CDR ; + PAIR ; + DUP 6 ; + SELF_ADDRESS ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DIG 2 ; + DROP ; + DUP 11 ; + SWAP ; + CONTRACT %approve (pair (address %spender) (nat %value)) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + DIG 2 ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS } + { DUP 12 ; + 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)))) ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH mutez 0 ; + NIL (or (pair address address nat) (pair address address nat)) ; + PUSH nat 0 ; + 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) } ; + 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 ; + DIG 4 ; + DIG 5 ; + DIG 6 ; + DIG 7 ; + 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 } ; + PAIR } ; + view "get_pool_data" + unit + (pair (address %pool_contract) (nat %pool_id)) + { CDR ; GET 5 } } ; + DUP 3 ; + DIG 3 ; + GET 3 ; + DUP 4 ; + DUP 6 ; + CAR ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 3 ; + DUG 2 ; + DUP 3 ; + DIG 3 ; + GET 4 ; + DIG 4 ; + CAR ; + DIG 4 ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 4 ; + NIL operation ; + DIG 2 ; + CONS } + { DUP 2 ; + DIG 2 ; + CAR ; + DIG 2 ; + IF_LEFT + { DROP ; + PUSH string "No new Admin awaited" ; + DUP 2 ; + CDR ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DIG 3 ; + SENDER ; + DUP 3 ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + UPDATE 1 ; + NONE address ; + UPDATE 2 } + { DIG 3 ; + SENDER ; + DUP 4 ; + CAR ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + SOME ; + UPDATE 2 } ; + UPDATE 1 ; + NIL operation } ; + PAIR } ; + view "dev_address" unit address { CDR ; CAR ; CAR } ; + view "is_registered" address bool { UNPAIR ; SWAP ; GET 4 ; SWAP ; MEM } } + diff --git a/test/utils/mocks/artifacts/yupana.tz b/test/utils/mocks/artifacts/yupana.tz new file mode 100644 index 0000000..f99b7ab --- /dev/null +++ b/test/utils/mocks/artifacts/yupana.tz @@ -0,0 +1,586 @@ +{ parameter + (or (or (or (pair %mint (nat %tokenId) (nat %amount) (nat %minReceived)) + (pair %priceCallback (nat %tokenId) (nat %amount))) + (or (pair %redeem (nat %tokenId) (nat %amount) (nat %minReceived)) + (pair %setExchangeRate (nat %marketId) (nat %rateF)))) + (or (address %setPriceFeed) (nat %updateInterest))) ; + storage + (pair (big_map %ledger (pair address nat) nat) + (big_map %tokens + nat + (pair (or %mainToken (address %fa12) (pair %fa2 (address %token_address) (nat %token_id))) + (timestamp %interestUpdateTime) + (timestamp %priceUpdateTime) + (nat %exchangeRateF) + (nat %totalSupplyF) + (nat %totalLiquidityF) + (nat %lastPrice))) + (address %priceFeedProxy)) ; + code { PUSH string "Contract has no transfer entrypoint" ; + LAMBDA + (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 + (pair nat + (pair (pair bool nat nat bool) + (big_map (pair address nat) nat) + (big_map + nat + (pair (or address (pair address nat)) timestamp timestamp nat nat nat nat)) + address)) + (pair nat timestamp timestamp) + { UNPAIR ; + SWAP ; + UNPAIR ; + SWAP ; + GET 3 ; + DUP 2 ; + GET 3 ; + GET ; + IF_NONE { PUSH string "No Token yet" ; FAILWITH } {} ; + DUP ; + GET 11 ; + DUP 3 ; + GET 5 ; + DUP 4 ; + CAR ; + IF { DIG 3 ; + GET 6 ; + IF { DUP 4 ; SWAP ; MUL } {} ; + PUSH nat 0 ; + DUP 3 ; + COMPARE ; + GT ; + IF { DIG 3 ; + DIG 2 ; + DUP 4 ; + GET 7 ; + DUP 5 ; + GET 9 ; + DIG 4 ; + MUL ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } + { SWAP ; DIG 3 ; DROP 3 ; PUSH nat 0 } } + { PUSH nat 0 ; + DUP 4 ; + GET 9 ; + COMPARE ; + GT ; + IF { DUP 3 ; + GET 7 ; + DUP 4 ; + GET 9 ; + DUP 7 ; + DIG 4 ; + DIG 4 ; + MUL ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } + { DROP 2 ; PUSH nat 0 } ; + DIG 2 ; + GET 6 ; + IF { DIG 2 ; + SWAP ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } + { DIG 2 ; DROP } } ; + DUP 2 ; + GET 5 ; + DIG 2 ; + GET 3 ; + DIG 2 ; + PAIR 3 } ; + DUP 3 ; + APPLY ; + DIG 6 ; + UNPAIR ; + SWAP ; + NIL operation ; + DIG 2 ; + IF_LEFT + { IF_LEFT + { DIG 6 ; + DROP ; + IF_LEFT + { DIG 4 ; + DUP 4 ; + GET 3 ; + DUP 3 ; + CAR ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH string "TIMEOUT" ; + DUP 2 ; + GET 3 ; + NOW ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + DUP 4 ; + DIG 4 ; + GET 3 ; + DUP 3 ; + DUP 8 ; + DUP 6 ; + GET 3 ; + MUL ; + DUP 5 ; + GET 9 ; + ADD ; + UPDATE 9 ; + DIG 7 ; + DUP 6 ; + GET 3 ; + MUL ; + DUP 5 ; + GET 11 ; + ADD ; + UPDATE 11 ; + DUP 5 ; + CAR ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 3 ; + DUG 3 ; + DUP 4 ; + PUSH bool True ; + DUP 4 ; + GET 3 ; + DUP 5 ; + CAR ; + PUSH bool True ; + PAIR 4 ; + PAIR ; + DIG 5 ; + SWAP ; + EXEC ; + SENDER ; + DIG 4 ; + DIG 3 ; + CAR ; + DUP 5 ; + GET 3 ; + PAIR ; + SELF_ADDRESS ; + DUP 4 ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DIG 9 ; + DROP ; + DIG 9 ; + 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 } + { DIG 10 ; + DUP 2 ; + CAR ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + PAIR ; + DIG 10 ; + SWAP ; + EXEC ; + 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 3 ; + DUP 5 ; + DUP 6 ; + CAR ; + DIG 3 ; + CAR ; + DIG 6 ; + CAR ; + DUP 6 ; + CAR ; + DUP 6 ; + PAIR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + ADD ; + DIG 4 ; + CAR ; + DIG 4 ; + PAIR ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 1 } + { DIG 3 ; + DIG 5 ; + DIG 6 ; + DIG 7 ; + DROP 4 ; + PUSH string "Only price feed is allowed here" ; + DUP 4 ; + GET 4 ; + SENDER ; + COMPARE ; + EQ ; + IF { DROP } { FAILWITH } ; + DUP 3 ; + DUP 4 ; + GET 3 ; + DIG 5 ; + DIG 5 ; + GET 3 ; + DUP 5 ; + CAR ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + NOW ; + UPDATE 5 ; + DUP 4 ; + CDR ; + UPDATE 12 ; + DIG 3 ; + CAR ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 3 } } + { IF_LEFT + { DIG 4 ; + DUP 4 ; + GET 3 ; + DUP 3 ; + CAR ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + PUSH string "TIMEOUT" ; + DUP 2 ; + GET 3 ; + NOW ; + 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 ; + GET 3 ; + MUL ; + DUP 5 ; + GET 9 ; + SUB ; + DUP 10 ; + SWAP ; + EXEC ; + UPDATE 9 ; + DIG 7 ; + DUP 6 ; + GET 3 ; + MUL ; + DUP 5 ; + GET 11 ; + SUB ; + DUP 9 ; + SWAP ; + EXEC ; + UPDATE 11 ; + DUP 5 ; + CAR ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 3 ; + DUG 3 ; + DUP 4 ; + PUSH bool True ; + DUP 4 ; + GET 3 ; + DUP 5 ; + CAR ; + PUSH bool True ; + PAIR 4 ; + PAIR ; + DIG 5 ; + SWAP ; + EXEC ; + SENDER ; + DIG 4 ; + DIG 3 ; + CAR ; + DUP 5 ; + GET 3 ; + PAIR ; + DUP 3 ; + SELF_ADDRESS ; + DIG 2 ; + UNPAIR ; + SWAP ; + IF_LEFT + { DIG 10 ; + DROP ; + DIG 10 ; + 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 } + { DIG 11 ; + DUP 2 ; + CAR ; + CONTRACT %transfer + (list (pair (address %from_) (list %txs (pair (address %to_) (nat %token_id) (nat %amount))))) ; + PAIR ; + DIG 11 ; + SWAP ; + EXEC ; + 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 3 ; + DUP 5 ; + DUP 6 ; + CAR ; + DIG 3 ; + CAR ; + DIG 6 ; + CAR ; + DUP 6 ; + CAR ; + DUP 6 ; + PAIR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + SUB ; + DIG 6 ; + SWAP ; + EXEC ; + DIG 4 ; + CAR ; + DIG 4 ; + PAIR ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 1 } + { DIG 3 ; + DIG 5 ; + DIG 6 ; + DIG 7 ; + DIG 8 ; + DROP 5 ; + DUP 3 ; + DUP 4 ; + GET 3 ; + DIG 5 ; + DIG 5 ; + GET 3 ; + DUP 5 ; + CAR ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + DUP 4 ; + CDR ; + UPDATE 7 ; + DIG 3 ; + CAR ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 3 } } } + { DIG 3 ; + DIG 5 ; + DIG 6 ; + DIG 7 ; + DIG 8 ; + DROP 5 ; + IF_LEFT + { DIG 3 ; DROP ; DIG 2 ; SWAP ; UPDATE 4 } + { DUP 3 ; + DUP 4 ; + GET 3 ; + DIG 5 ; + DIG 5 ; + GET 3 ; + DUP 5 ; + GET ; + IF_NONE { FAILWITH } { SWAP ; DROP } ; + NOW ; + UPDATE 3 ; + DIG 3 ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + UPDATE 3 } } ; + SWAP ; + PAIR } ; + view "balanceOf" + (pair (list %requests (pair (address %owner) (nat %token_id))) (bool %precision)) + (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))) + { UNPAIR ; + DUP ; + CAR ; + MAP { DUP 3 ; + CAR ; + DUP 2 ; + CDR ; + DUP 3 ; + CAR ; + PAIR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + DUP 3 ; + CDR ; + IF { PUSH nat 1000000 ; + SWAP ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } + {} ; + SWAP ; + PAIR } ; + SWAP ; + DIG 2 ; + DROP 2 } ; + view "convert" + (pair (bool %toShares) (nat %tokenId) (nat %amount) (bool %precision)) + (pair (nat %amount) (timestamp %interestUpdateTime) (timestamp %priceUpdateTime)) + { PUSH nat 1000000 ; + SWAP ; + UNPAIR ; + SWAP ; + GET 3 ; + DUP 2 ; + GET 3 ; + GET ; + IF_NONE { PUSH string "No Token yet" ; FAILWITH } {} ; + DUP ; + GET 11 ; + DUP 3 ; + GET 5 ; + DUP 4 ; + CAR ; + IF { DIG 3 ; + GET 6 ; + IF { DUP 4 ; SWAP ; MUL } {} ; + PUSH nat 0 ; + DUP 3 ; + COMPARE ; + GT ; + IF { DIG 3 ; + DIG 2 ; + DUP 4 ; + GET 7 ; + DUP 5 ; + GET 9 ; + DIG 4 ; + MUL ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } + { SWAP ; DIG 3 ; DROP 3 ; PUSH nat 0 } } + { PUSH nat 0 ; + DUP 4 ; + GET 9 ; + COMPARE ; + GT ; + IF { DUP 3 ; + GET 7 ; + DUP 4 ; + GET 9 ; + DUP 7 ; + DIG 4 ; + DIG 4 ; + MUL ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } + { DROP 2 ; PUSH nat 0 } ; + DIG 2 ; + GET 6 ; + IF { DIG 2 ; + SWAP ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR } + { DIG 2 ; DROP } } ; + DUP 2 ; + GET 5 ; + DIG 2 ; + GET 3 ; + DIG 2 ; + PAIR 3 } } + diff --git a/test/utils/mocks/getMichelsonCode.ts b/test/utils/mocks/getMichelsonCode.ts new file mode 100644 index 0000000..0155b52 --- /dev/null +++ b/test/utils/mocks/getMichelsonCode.ts @@ -0,0 +1,5 @@ +import { readFileSync } from "fs"; +import * as path from "path"; + +export const getMichelsonCode = (contract: string): string => + readFileSync(path.join(__dirname, "./artifacts", contract + ".tz"), "utf8"); diff --git a/test/utils/tokensSetups.ts b/test/utils/tokensSetups.ts index d54e6ff..e2c3ff3 100644 --- a/test/utils/tokensSetups.ts +++ b/test/utils/tokensSetups.ts @@ -14,13 +14,13 @@ import chalk from "chalk"; async function originateTokens(Tezos: TezosToolkit): Promise { const kUSD = await Tezos.contract.originate(TokenInitValues.kUSD); - await confirmOperation(Tezos, kUSD.hash); + await kUSD.confirmation(2); console.debug(`[${chalk.green("ORIGINATION")}] kUSD`); const USDtz = await Tezos.contract.originate(TokenInitValues.USDtz); - await confirmOperation(Tezos, USDtz.hash); + await USDtz.confirmation(2); console.debug(`[${chalk.green("ORIGINATION")}] USDtz`); const uUSD = await Tezos.contract.originate(TokenInitValues.uUSD); - await confirmOperation(Tezos, uUSD.hash); + await uUSD.confirmation(2); console.debug(`[${chalk.green("ORIGINATION")}] uUSD`); return { kUSD: await TokenFA12.init(Tezos, kUSD.contractAddress), @@ -82,7 +82,7 @@ export async function setupTokenAmounts( if (contract_address) { for (const token in tokens) { if (contract_address == tokens[token].contract.address) { - amounts.set(k, inputs[token]); + amounts.set(k.toString(), inputs[token]); } } } @@ -94,6 +94,6 @@ export async function setupQuipuGovToken( Tezos: TezosToolkit ): Promise { const quipu = await Tezos.contract.originate(TokenInitValues.QUIPU); - await confirmOperation(Tezos, quipu.hash); + await quipu.confirmation(2); return await TokenFA2.init(Tezos, quipu.contractAddress); } diff --git a/utils/helpers.ts b/utils/helpers.ts index 7137993..d129331 100644 --- a/utils/helpers.ts +++ b/utils/helpers.ts @@ -10,6 +10,8 @@ import BigNumber from "bignumber.js"; import chalk from "chalk"; export const tezPrecision = 1e6; +export declare type LambdaType = "Dex" | "Token" | "Admin" | "Dev" | "Strategy"; + function stringLiteralArray(a: T[]) { return a; } @@ -118,7 +120,7 @@ export async function bakeBlocks(count: number) { to: await Tezos.signer.publicKeyHash(), amount: 1, }); - await confirmOperation(Tezos, operation.hash); + await operation.confirmation(2); } } @@ -163,7 +165,7 @@ export async function setupLambdasToStorage( export async function setFunctionBatchCompilled( tezos: TezosToolkit, contract: TezosAddress, - type: "Dex" | "Token" | "Admin" | "Dev", + type: LambdaType, batchBy: number, comp_funcs_map ) { @@ -181,7 +183,7 @@ export async function setFunctionBatchCompilled( idx = idx + 1; if (idx % batchBy == 0 || idx == comp_funcs_map.length) { const batchOp = await batch.send(); - await confirmOperation(tezos, batchOp.hash); + await batchOp.confirmation(2); console.debug( `[${chalk.bold.bgWhite.bgBlueBright( "BATCH" @@ -197,7 +199,7 @@ export async function setFunctionBatchCompilled( export async function setFunctionCompilled( tezos: TezosToolkit, contract: TezosAddress, - type: "Dex" | "Token" | "Admin" | "Dev", + type: LambdaType, comp_funcs_map ) { let idx = 0; @@ -211,7 +213,7 @@ export async function setFunctionCompilled( }, }); idx = idx + 1; - await confirmOperation(tezos, op.hash); + await op.confirmation(2); } } diff --git a/yarn.lock b/yarn.lock index 092ccc4..3dfdd5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -590,6 +590,16 @@ "@stablelib/hash" "^1.0.1" "@stablelib/wipe" "^1.0.1" +"@stablelib/bytes@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/bytes/-/bytes-1.0.1.tgz#0f4aa7b03df3080b878c7dea927d01f42d6a20d8" + integrity sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ== + +"@stablelib/constant-time@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/constant-time/-/constant-time-1.0.1.tgz#bde361465e1cf7b9753061b77e376b0ca4c77e35" + integrity sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg== + "@stablelib/ed25519@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@stablelib/ed25519/-/ed25519-1.0.2.tgz#937a88a2f73a71d9bdc3ea276efe8954776ae0f4" @@ -609,6 +619,32 @@ resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== +"@stablelib/keyagreement@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz#4612efb0a30989deb437cd352cee637ca41fc50f" + integrity sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg== + dependencies: + "@stablelib/bytes" "^1.0.1" + +"@stablelib/nacl@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@stablelib/nacl/-/nacl-1.0.4.tgz#b63e0a1b87eccb13ad91dd46b2382112acfa417e" + integrity sha512-PJ2U/MrkXSKUM8C4qFs87WeCNxri7KQwR8Cdwm9q2sweGuAtTvOJGuW0F3N+zn+ySLPJA98SYWSSpogMJ1gCmw== + dependencies: + "@stablelib/poly1305" "^1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/wipe" "^1.0.1" + "@stablelib/x25519" "^1.0.3" + "@stablelib/xsalsa20" "^1.0.2" + +"@stablelib/poly1305@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/poly1305/-/poly1305-1.0.1.tgz#93bfb836c9384685d33d70080718deae4ddef1dc" + integrity sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA== + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + "@stablelib/random@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.1.tgz#4357a00cb1249d484a9a71e6054bc7b8324a7009" @@ -617,6 +653,23 @@ "@stablelib/binary" "^1.0.1" "@stablelib/wipe" "^1.0.1" +"@stablelib/random@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.2.tgz#2dece393636489bf7e19c51229dd7900eddf742c" + integrity sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/salsa20@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@stablelib/salsa20/-/salsa20-1.0.2.tgz#95177331f89a59d1c90f153f53265c925d4de138" + integrity sha512-nfjKzw0KTKrrKBasEP+j7UP4I8Xudom8lVZIBCp0kQNARXq72IlSic0oabg2FC1NU68L4RdHrNJDd8bFwrphYA== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/constant-time" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + "@stablelib/sha512@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/sha512/-/sha512-1.0.1.tgz#6da700c901c2c0ceacbd3ae122a38ac57c72145f" @@ -631,73 +684,101 @@ resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== -"@taquito/http-utils@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@taquito/http-utils/-/http-utils-11.1.0.tgz#43e53b4f57f4f1aec355c84462ee1839ca6277cf" - integrity sha512-5kig7XKDcWlAxPx0qkGxyaqvS/rcz7DldcqcNvxAq+Z9Bb5viWIXQm4EaBKZ0KDh5PYjSS0HpbpvoGagIGwowQ== +"@stablelib/x25519@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stablelib/x25519/-/x25519-1.0.3.tgz#13c8174f774ea9f3e5e42213cbf9fc68a3c7b7fd" + integrity sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw== dependencies: - xhr2-cookies "^1.1.0" + "@stablelib/keyagreement" "^1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/wipe" "^1.0.1" -"@taquito/michel-codec@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@taquito/michel-codec/-/michel-codec-11.1.0.tgz#a32555ad70d931fd7c2cf3b03d57ba44bf77abe7" - integrity sha512-Gh1ehstk2OOixeQfc3/XQLPrI4Nr/8gJCWm/Zj5FWtn0GTsxGnZR6W4EjqbWF290b4LMO8FrOAc68+I3EvPaFQ== +"@stablelib/xsalsa20@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@stablelib/xsalsa20/-/xsalsa20-1.0.2.tgz#89efc22a7ba432880ef11d876fdeba13529ccdc4" + integrity sha512-7XdBGbcNgBShmuhDXv1G1WPVCkjZdkb1oPMzSidO7Fve0MHntH6TjFkj5bfLI+aRE+61weO076vYpP/jmaAYog== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/salsa20" "^1.0.2" + "@stablelib/wipe" "^1.0.1" -"@taquito/michelson-encoder@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@taquito/michelson-encoder/-/michelson-encoder-11.1.0.tgz#b3cd4d88e140f9a6a1b5d3b01f4806aee381d8df" - integrity sha512-XYoegKuQ2wnlQCMkaghI+QAVKH3xnIt7x3ChJvvnbpcKOHihFgWawK0nx1HKoz8GyW6+ZeOC2DgzP5uW0C6WRw== +"@taquito/http-utils@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/http-utils/-/http-utils-14.0.0.tgz#20470f8e08d33451241742221d416c72a70d881b" + integrity sha512-ZWZzod/+/OEE26b9CnDRjHGfUKBJft3aXv/e/A9bTHAtvRNJqGIhofHcDg/jTaolBMarCF2b3XBYw35aOOSk4A== dependencies: - "@taquito/rpc" "^11.1.0" - "@taquito/utils" "^11.1.0" - bignumber.js "^9.0.1" + axios "^0.26.0" + +"@taquito/local-forging@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/local-forging/-/local-forging-14.0.0.tgz#6844d90fa530d39ce7aaaa8cd11c8723d494a7d9" + integrity sha512-Nm0xGmS1Jzd+tU0a/8Y8XuTghbiPBgHDLo+e4141TK3OAwTzOw0an+w3xK9QVfzvxfIcZBSMjeMZzOwDdiqkJQ== + dependencies: + "@taquito/utils" "^14.0.0" + bignumber.js "^9.0.2" + +"@taquito/michel-codec@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/michel-codec/-/michel-codec-14.0.0.tgz#53d09e956b04359b43ff2a1e8a487c6da20c5a5f" + integrity sha512-ftnBvUVddlHBqvQbGPHEb26KrS4lIcaZ1eIpYJWiz+akb4Pcfyq7j/OEsDZbB7Pl2FP9hqu7ZygOF34zY6Lrtw== + +"@taquito/michelson-encoder@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/michelson-encoder/-/michelson-encoder-14.0.0.tgz#f62a1ef3cb432c4c9163f20161a73d772b98dda1" + integrity sha512-KIS+xl4rKfnd6hf9LUr6W+Pb7gv8F/Qsx0fho9CtM2PodKvdef3YlvkpScBUM9QZntAlvq2XQXUVXcZkbvxygw== + dependencies: + "@taquito/rpc" "^14.0.0" + "@taquito/utils" "^14.0.0" + bignumber.js "^9.0.2" fast-json-stable-stringify "^2.1.0" -"@taquito/rpc@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@taquito/rpc/-/rpc-11.1.0.tgz#ec7bc2de1848330ac69f80f87f22655759d856a7" - integrity sha512-AUP1eUmjwwWzCSY00dIzGA2Xe9riO6kGG364TT3626qjDzEE/PxVy65oCiNC3BiXdtO4memQzdVI3gcKZYS3hA== - dependencies: - "@taquito/http-utils" "^11.1.0" - bignumber.js "^9.0.1" - lodash.get "^4.4.2" - lodash.set "^4.3.2" - -"@taquito/signer@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@taquito/signer/-/signer-11.1.0.tgz#ffb2656b332c477ee486356a6387cbe0ba48fe6a" - integrity sha512-WJLm2tJPb69F5jL/C4keIzJ/AbhmMzupiCS8jx0CXev+YKZmJE0kW7UpUzorLt9Va0grE9/VRxQiQVdAyp+w6A== - dependencies: - "@taquito/taquito" "^11.1.0" - "@taquito/utils" "^11.1.0" - bignumber.js "^9.0.1" - bip39 "^3.0.4" +"@taquito/rpc@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/rpc/-/rpc-14.0.0.tgz#30bd353a485abba0a74477e1b0eac454076b30e9" + integrity sha512-FMfb80sA+VJwNx8OTNN07boDAt2roISqLLCUgmOIwy/cFDqhII7gdS4aYWJWqlKbdPKCPqh3a3ZQD1X/jyQHOA== + dependencies: + "@taquito/http-utils" "^14.0.0" + "@taquito/utils" "^14.0.0" + bignumber.js "^9.0.2" + +"@taquito/signer@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/signer/-/signer-14.0.0.tgz#060318fe1a6f32da87a3f7ad18008ca3ba495ced" + integrity sha512-vDqp/quzAsOiVikUt5MYUKhHI3S9qlasazyXs99xK9qpGLotbx6aseKcfb/dkaTo4/eoMzP4XzTVdnk0AqcCkw== + dependencies: + "@stablelib/blake2b" "^1.0.1" + "@stablelib/ed25519" "^1.0.2" + "@stablelib/nacl" "^1.0.3" + "@taquito/taquito" "^14.0.0" + "@taquito/utils" "^14.0.0" elliptic "^6.5.4" - libsodium-wrappers "0.7.8" pbkdf2 "^3.1.2" typedarray-to-buffer "^4.0.0" -"@taquito/taquito@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@taquito/taquito/-/taquito-11.1.0.tgz#96c86fb6c8b7425b0faccca8150fd5127fe278d8" - integrity sha512-aGibJBTi+kCCEhz3E+wHyJ6Pf/n30Tv/m/ag2ZMoWMYxWzOHepfkYaPQ6nq4eXUcWzAAxEuAtvgJBUB2pkHlog== - dependencies: - "@taquito/http-utils" "^11.1.0" - "@taquito/michel-codec" "^11.1.0" - "@taquito/michelson-encoder" "^11.1.0" - "@taquito/rpc" "^11.1.0" - "@taquito/utils" "^11.1.0" - bignumber.js "^9.0.1" +"@taquito/taquito@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/taquito/-/taquito-14.0.0.tgz#7dc8dccbe164f5ef52d61e40f9a8084da340b172" + integrity sha512-JaXfvqOCF3dkwXxhe00Ravb8WLMC2VqJxerf4GrGUEpJw+NAkwbGEb8k/52+MQQdlxMPepZdPPru/HM3nFG0Tw== + dependencies: + "@taquito/http-utils" "^14.0.0" + "@taquito/local-forging" "^14.0.0" + "@taquito/michel-codec" "^14.0.0" + "@taquito/michelson-encoder" "^14.0.0" + "@taquito/rpc" "^14.0.0" + "@taquito/utils" "^14.0.0" + bignumber.js "^9.0.2" rxjs "^6.6.3" -"@taquito/utils@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@taquito/utils/-/utils-11.1.0.tgz#f179881e0e211dfb2764fbf2ea4fd467ae3426c5" - integrity sha512-65Ms8lRD7Y7E4X9wqDugtoskRhGvonn4MTVfuWCZJEDHR6iKhy5SO/fy31wWvTc8281BsNelvniiItHgLx69wg== +"@taquito/utils@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@taquito/utils/-/utils-14.0.0.tgz#2fdbf0de677b5ef68e8a6d618a6a996195ae170b" + integrity sha512-0RSHn/CzbcbMdldJJIlXyxOvAajwmL6iPKJ6NaRyYJqqLM2CxYjG72KpXVv716pCMV1MbIWsOAr9FKbxW73PsA== dependencies: "@stablelib/blake2b" "^1.0.1" "@stablelib/ed25519" "^1.0.2" - blakejs "^1.1.0" + "@types/bs58check" "^2.1.0" + bignumber.js "^9.0.2" + blakejs "^1.2.1" bs58check "^2.1.2" buffer "^6.0.3" elliptic "^6.5.4" @@ -761,6 +842,13 @@ dependencies: "@babel/types" "^7.3.0" +"@types/bs58check@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/bs58check/-/bs58check-2.1.0.tgz#7d25a8b88fe7a9e315d2647335ee3c43c8fdb0c0" + integrity sha512-OxsysnJQh82vy9DRbOcw9m2j/WiyqZLn0YBhKxdQ+aCwoHj+tWzyCgpwAkr79IfDXZKxc6h7k89T9pwS78CqTQ== + dependencies: + "@types/node" "*" + "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -805,11 +893,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.6.tgz#040a64d7faf9e5d9e940357125f0963012e66f04" integrity sha512-YHUZhBOMTM3mjFkXVcK+WwAcYmyhe1wL4lfqNtzI0b3qAy7yuSetnM7QJazgE5PFmgVTNGiLOgRFfJMqW7XpSQ== -"@types/node@11.11.6": - version "11.11.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" - integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== - "@types/prettier@^2.1.5": version "2.3.2" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" @@ -1033,6 +1116,13 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +axios@^0.26.0: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + babel-jest@^27.2.1: version "27.2.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.2.1.tgz#48edfa5cf8d59ab293da94321a369ccc7b67a4b1" @@ -1111,25 +1201,15 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -bignumber.js@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" - integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== - -bip39@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.4.tgz#5b11fed966840b5e1b8539f0f54ab6392969b2a0" - integrity sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw== - dependencies: - "@types/node" "11.11.6" - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" +bignumber.js@^9.0.2: + version "9.1.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.0.tgz#8d340146107fe3a6cb8d40699643c302e8773b62" + integrity sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A== -blakejs@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" - integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== +blakejs@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== bn.js@^4.11.9: version "4.12.0" @@ -1344,11 +1424,6 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cookiejar@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== - create-hash@^1.1.0, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" @@ -1825,6 +1900,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== +follow-redirects@^1.14.8: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -2698,18 +2778,6 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libsodium-wrappers@0.7.8: - version "0.7.8" - resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.8.tgz#d95cdf3e7236c2aef76844bf8e1929ba9eef3e9e" - integrity sha512-PDhPWXBqd/SaqAFUBgH2Ux7b3VEEJgyD6BQB+VdNFJb9PbExGr/T/myc/MBoSvl8qLzfm0W0IVByOQS5L1MrCg== - dependencies: - libsodium "0.7.8" - -libsodium@0.7.8: - version "0.7.8" - resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.8.tgz#fbd12247b7b1353f88d8de1cbc66bc1a07b2e008" - integrity sha512-/Qc+APf0jbeWSaeEruH0L1/tbbT+sbf884ZL0/zV/0JXaDPBzYkKbyb/wmxMHgAHzm3t6gqe7bOOXAVwfqVikQ== - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -2717,21 +2785,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.set@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" - integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= - lodash@4.x, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -2975,7 +3033,7 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pbkdf2@^3.0.9, pbkdf2@^3.1.2: +pbkdf2@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -3075,13 +3133,6 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -randombytes@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - react-is@^17.0.1: version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" @@ -3165,7 +3216,7 @@ rxjs@^6.6.3: dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3623,13 +3674,6 @@ ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== -xhr2-cookies@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= - dependencies: - cookiejar "^2.1.1" - xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"