conflict fixed

This commit is contained in:
fiftyeightandeight
2021-09-16 22:52:22 +08:00
15 changed files with 3808 additions and 183 deletions

View File

@@ -50,6 +50,6 @@
;; return the loan + fee
(unwrap! (contract-call? token transfer amount-with-fee tx-sender (as-contract tx-sender) none) post-loan-transfer-failed-err)
(ok true)
(ok amount-with-fee)
)
)

View File

@@ -107,14 +107,35 @@
(if (is-eq (+ weight-x weight-y) ONE_8)
(let
(
(denominator (unwrap-panic (contract-call? .math-fixed-point mul-up balance-y weight-x)))
(numerator (unwrap-panic (contract-call? .math-fixed-point mul-down balance-x weight-y)))
(denominator (unwrap-panic (contract-call? .math-fixed-point mul-up balance-y weight-x)))
(spot (unwrap-panic (contract-call? .math-fixed-point div-down numerator denominator)))
(base (unwrap-panic (contract-call? .math-fixed-point div-up price spot)))
(power (unwrap-panic (contract-call? .math-fixed-point pow-down base weight-y)))
)
(asserts! (> price spot) no-liquidity-err)
(contract-call? .math-fixed-point mul-up balance-x (unwrap-panic (contract-call? .math-fixed-point sub-fixed power ONE_8)))
)
weight-sum-err
)
)
;; TODO: not very accurate
(define-read-only (get-y-given-price (balance-x uint) (balance-y uint) (weight-x uint) (weight-y uint) (price uint))
(if (is-eq (+ weight-x weight-y) ONE_8)
(let
(
(numerator (unwrap-panic (contract-call? .math-fixed-point mul-down balance-x weight-y)))
(denominator (unwrap-panic (contract-call? .math-fixed-point mul-up balance-y weight-x)))
(spot (unwrap-panic (contract-call? .math-fixed-point div-down numerator denominator)))
(base (unwrap-panic (contract-call? .math-fixed-point div-up price spot)))
(power (unwrap-panic (contract-call? .math-fixed-point pow-down base weight-y)))
(ratio (unwrap-panic (contract-call? .math-fixed-point sub-fixed power ONE_8)))
)
(contract-call? .math-fixed-point mul-up balance-x ratio)
(asserts! (< price spot) no-liquidity-err)
(get-y-given-x balance-x balance-y weight-x weight-y
(unwrap-panic (contract-call? .math-fixed-point mul-up balance-x
(unwrap-panic (contract-call? .math-fixed-point sub-fixed ONE_8 power)))))
)
weight-sum-err
)

View File

@@ -490,6 +490,20 @@
)
)
(define-read-only (get-y-given-price (token-x-trait <ft-trait>) (token-y-trait <ft-trait>) (weight-x uint) (weight-y uint) (price uint))
(let
(
(token-x (contract-of token-x-trait))
(token-y (contract-of token-y-trait))
(pool (unwrap! (map-get? pools-data-map { token-x: token-x, token-y: token-y, weight-x: weight-x, weight-y: weight-y }) invalid-pool-err))
(balance-x (get balance-x pool))
(balance-y (get balance-y pool))
)
(contract-call? .weighted-equation get-y-given-price balance-x balance-y weight-x weight-y price)
)
)
(define-read-only (get-token-given-position (token-x-trait <ft-trait>) (token-y-trait <ft-trait>) (weight-x uint) (weight-y uint) (dx uint) (dy uint))
(let
(

View File

@@ -8,7 +8,7 @@
(get-balance (<ft-trait>) (response uint uint))
;; flash loan currently supports single token loan
(flash-loan (<flash-loan-user-trait> <ft-trait> uint) (response bool uint))
(flash-loan (<flash-loan-user-trait> <ft-trait> uint) (response uint uint))
)
)

View File

@@ -23,6 +23,8 @@ const keywbtc79760Address = "ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.key-wbtc-
const ytpyieldwbtc79760Address = "ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.ytp-yield-wbtc-79760-wbtc"
const multisigncrpwbtc79760Address = "ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.multisig-crp-wbtc-79760-usda"
const multisigytpyieldwbtc79760 = "ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.multisig-ytp-yield-wbtc-79760-wbtc"
const vaultAddress = "ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.alex-vault"
const reserveAddress = "ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.alex-reserve-pool"
const ONE_8 = 100000000
const expiry = 59760 * ONE_8
@@ -32,8 +34,8 @@ const conversion_ltv = 0.95 * ONE_8
const bs_vol = 0.8 * ONE_8
const moving_average = 0 * ONE_8 // for testing only
const wbtcPrice = 50000
const usdaPrice = 1
const wbtcPrice = 50000*ONE_8
const usdaPrice = 1*ONE_8
const weightX = 0.5 * ONE_8
const weightY = 0.5 * ONE_8
@@ -62,13 +64,13 @@ Clarinet.test({
oracleresult = Oracle.updatePrice(deployer,"USDA","nothing",usdaPrice);
oracleresult.expectOk()
let result = FWPTest.createPool(deployer, wbtcAddress, usdaAddress, weightX, weightY, fwpwbtcusdaAddress, multisigfwpAddress, wbtcQ, wbtcPrice * wbtcQ);
let result = FWPTest.createPool(deployer, wbtcAddress, usdaAddress, weightX, weightY, fwpwbtcusdaAddress, multisigfwpAddress, wbtcQ, Math.round(wbtcPrice * wbtcQ / ONE_8));
result.expectOk().expectBool(true);
let call = await FWPTest.getPoolDetails(wbtcAddress, usdaAddress, weightX, weightY);
let position:any = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(wbtcQ);
position['balance-y'].expectUint(wbtcQ * wbtcPrice);
position['balance-y'].expectUint(Math.round(wbtcQ * wbtcPrice / ONE_8));
result = YTPTest.createPool(deployer, yieldwbtc59760Address, wbtcAddress, ytpyieldwbtc59760Address, multisigytpyieldwbtc59760, wbtcQ / 10, wbtcQ / 10);
result.expectOk().expectBool(true);
@@ -78,11 +80,11 @@ Clarinet.test({
result.expectOk().expectBool(true);
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(100110900);
call.result.expectOk().expectUint(100111426);
// ltv-0 is 80%, but injecting liquidity pushes up LTV
call = await CRPTest.getLtv(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(80717843);
call.result.expectOk().expectUint(80717419);
// Check pool details and print
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry);
@@ -115,7 +117,7 @@ Clarinet.test({
// remember, the first sell creates profit to LP
result = CRPTest.addToPositionAndSwitch(deployer, wbtcAddress, usdaAddress, yieldwbtc59760Address, keywbtc59760Address, 5000 * ONE_8);
position = result.expectOk().expectTuple();
position['dy'].expectUint(8073663);
position['dy'].expectUint(8073635);
position['dx'].expectUint(8127823);
// supply increased
@@ -123,22 +125,22 @@ Clarinet.test({
position = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(3629288282941);
position['balance-y'].expectUint(36901635);
position['yield-supply'].expectUint(88881023);
position['key-supply'].expectUint(88881023);
position['yield-supply'].expectUint(88880995);
position['key-supply'].expectUint(88880995);
// pool value increases after adding positions
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(109485635);
call.result.expectOk().expectUint(109487400);
call = await CRPTest.getPoolValueInCollateral(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(5474288282941)
call.result.expectOk().expectUint(5474370032941)
// let's check what is the weight to wbtc (token)
call = await CRPTest.getWeightY(wbtcAddress, usdaAddress, expiry, 50000 * ONE_8, bs_vol);
call.result.expectOk().expectUint(33465993);
// wbtc (token) falls by 20% vs usda (collateral)
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing",wbtcPrice * 0.8);
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing", Math.round(wbtcPrice * 0.8));
oracleresult.expectOk()
// move forward by one day
@@ -159,8 +161,8 @@ Clarinet.test({
position = call.result.expectOk().expectTuple();
position['weight-y'].expectUint(25427001);
position['weight-x'].expectUint(ONE_8 - 25427001);
position['yield-supply'].expectUint(88881023);
position['key-supply'].expectUint(88881023);
position['yield-supply'].expectUint(88880995);
position['key-supply'].expectUint(88880995);
// simulate to half way to expiry
chain.mineEmptyBlockUntil((expiry / ONE_8) / 2)
@@ -184,23 +186,23 @@ Clarinet.test({
position = call.result.expectOk().expectTuple();
position['weight-y'].expectUint(73683600);
position['weight-x'].expectUint(ONE_8 - 73683600);
position['yield-supply'].expectUint(88881023);
position['key-supply'].expectUint(88881023);
position['yield-supply'].expectUint(88880995);
position['key-supply'].expectUint(88880995);
// simulate to 3 / 4 to expiry
chain.mineEmptyBlockUntil((expiry / ONE_8) * 3 / 4)
// what if wbtc rises then by another 10%
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing",wbtcPrice * 0.8 * 1.5 * 1.1);
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing", Math.round(wbtcPrice * 0.8 * 1.5 * 1.1));
oracleresult.expectOk();
// we hold over 60% in usda, so pool value in wbtc goes down
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(91697065);
call.result.expectOk().expectUint(91698402);
// and ltv crossed conversion_ltv
call = await CRPTest.getLtv(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(96928972);
call.result.expectOk().expectUint(96927528);
// crossing convertion_ltv triggers 100% allocation to collateral
call = await CRPTest.getWeightY(wbtcAddress, usdaAddress, expiry, 50000 * ONE_8, bs_vol);
@@ -217,8 +219,8 @@ Clarinet.test({
position = call.result.expectOk().expectTuple();
position['weight-y'].expectUint(99900000);
position['weight-x'].expectUint(ONE_8 - 99900000);
position['yield-supply'].expectUint(88881023);
position['key-supply'].expectUint(88881023);
position['yield-supply'].expectUint(88880995);
position['key-supply'].expectUint(88880995);
position['balance-x'].expectUint(3659288282941);
position['balance-y'].expectUint(36370594);
@@ -243,14 +245,14 @@ Clarinet.test({
position = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(3659288282941);
position['balance-y'].expectUint(36370594);
position['yield-supply'].expectUint(88881023);
position['key-supply'].expectUint(88881023);
position['yield-supply'].expectUint(88880995);
position['key-supply'].expectUint(88880995);
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(91813018);
call.result.expectOk().expectUint(91814355);
call = await CRPTest.getLtv(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(96806558);
call.result.expectOk().expectUint(96805118);
// deployer holds less than total supply because he sold some yield-wbtc for wbtc
result = CRPTest.reducePositionYield(deployer, wbtcAddress, usdaAddress, yieldwbtc59760Address, ONE_8);
@@ -262,39 +264,39 @@ Clarinet.test({
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry);
position = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(0);
position['balance-y'].expectUint(9951298);
position['yield-supply'].expectUint(8073663);
position['key-supply'].expectUint(88881023);
position['balance-y'].expectUint(9951267);
position['yield-supply'].expectUint(8073635);
position['key-supply'].expectUint(88880995);
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(9951298);
call.result.expectOk().expectUint(9951267);
call = await CRPTest.getPositionGivenBurnKey(wbtcAddress, usdaAddress, expiry, ONE_8);
position = call.result.expectOk().expectTuple();
position['dx'].expectUint(0);
position['dy'].expectUint(2112526);
position['dy'].expectUint(2112523);
call = chain.callReadOnlyFn("key-wbtc-59760-usda", "get-balance",
[types.principal(deployer.address)
], deployer.address);
call.result.expectOk().expectUint(88881023);
call.result.expectOk().expectUint(88880995);
call = chain.callReadOnlyFn("key-wbtc-59760-usda", "get-total-supply",
[], deployer.address);
call.result.expectOk().expectUint(88881023);
call.result.expectOk().expectUint(88880995);
// also remove all key tokens
result = CRPTest.reducePositionKey(deployer, wbtcAddress, usdaAddress, keywbtc59760Address, ONE_8);
position = result.expectOk().expectTuple();
position['dx'].expectUint(0);
position['dy'].expectUint(1877634);
position['dy'].expectUint(1877631);
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry);
position = call.result.expectOk().expectTuple();
position['yield-supply'].expectUint(8073663);
position['yield-supply'].expectUint(8073635);
position['key-supply'].expectUint(0);
position['balance-x'].expectUint(0);
position['balance-y'].expectUint(8073664);
position['balance-y'].expectUint(8073636);
},
});
@@ -314,13 +316,59 @@ Clarinet.test({
oracleresult = Oracle.updatePrice(deployer,"USDA","nothing",usdaPrice);
oracleresult.expectOk()
let result = FWPTest.createPool(deployer, wbtcAddress, usdaAddress, weightX, weightY, fwpwbtcusdaAddress, multisigfwpAddress, wbtcQ, wbtcPrice * wbtcQ);
let result = FWPTest.createPool(deployer, wbtcAddress, usdaAddress, weightX, weightY, fwpwbtcusdaAddress, multisigfwpAddress, wbtcQ, Math.round(wbtcPrice * wbtcQ / ONE_8));
result.expectOk().expectBool(true);
let call = await FWPTest.getPoolDetails(wbtcAddress, usdaAddress, weightX, weightY);
let position:any = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(wbtcQ);
position['balance-y'].expectUint(wbtcQ * wbtcPrice);
position['balance-y'].expectUint(Math.round(wbtcQ * wbtcPrice / ONE_8));
result = YTPTest.createPool(deployer, yieldwbtc59760Address, wbtcAddress, ytpyieldwbtc59760Address, multisigytpyieldwbtc59760, wbtcQ / 10, wbtcQ / 10);
result.expectOk().expectBool(true);
//Deployer creating a pool, initial tokens injected to the pool
result = CRPTest.createPool(deployer, wbtcAddress, usdaAddress, yieldwbtc59760Address, keywbtc59760Address, multisigncrpwbtc59760Address, ltv_0, conversion_ltv, bs_vol, moving_average, 50000 * ONE_8);
result.expectOk().expectBool(true);
// simulate to half way to expiry
chain.mineEmptyBlockUntil((expiry / ONE_8) / 2)
// wbtc rises then by 50%
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing", Math.round(wbtcPrice * 0.8 * 1.5));
oracleresult.expectOk();
result = YTPTest.createPool(deployer, yieldwbtc79760Address, wbtcAddress, ytpyieldwbtc79760Address, multisigytpyieldwbtc79760, wbtcQ / 10, wbtcQ / 10);
result.expectOk().expectBool(true);
//Deployer creating a pool, initial tokens injected to the pool
result = CRPTest.createPool(deployer, wbtcAddress, usdaAddress, yieldwbtc79760Address, keywbtc79760Address, multisigncrpwbtc79760Address, ltv_0, conversion_ltv, bs_vol, moving_average, 50000 * ONE_8);
result.expectOk().expectBool(true);
},
});
Clarinet.test({
name: "CRP : working with reserve pool",
async fn(chain: Chain, accounts: Map<string, Account>) {
let deployer = accounts.get("deployer")!;
let CRPTest = new CRPTestAgent1(chain, deployer);
let FWPTest = new FWPTestAgent1(chain, deployer);
let YTPTest = new YTPTestAgent1(chain, deployer);
let Oracle = new OracleManager(chain, deployer);
let oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing",wbtcPrice);
oracleresult.expectOk()
oracleresult = Oracle.updatePrice(deployer,"USDA","nothing",usdaPrice);
oracleresult.expectOk()
let result = FWPTest.createPool(deployer, wbtcAddress, usdaAddress, weightX, weightY, fwpwbtcusdaAddress, multisigfwpAddress, wbtcQ, Math.round(wbtcQ*wbtcPrice/ONE_8));
result.expectOk().expectBool(true);
let call = await FWPTest.getPoolDetails(wbtcAddress, usdaAddress, weightX, weightY);
let position:any = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(wbtcQ);
position['balance-y'].expectUint(Math.round(wbtcQ*wbtcPrice/ONE_8));
result = YTPTest.createPool(deployer, yieldwbtc59760Address, wbtcAddress, ytpyieldwbtc59760Address, multisigytpyieldwbtc59760, wbtcQ / 10, wbtcQ / 10);
result.expectOk().expectBool(true);
@@ -330,11 +378,7 @@ Clarinet.test({
result.expectOk().expectBool(true);
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(100110900);
// ltv-0 is 80%, but injecting liquidity pushes up LTV
call = await CRPTest.getLtv(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(80717843);
call.result.expectOk().expectUint(100111426);
// Check pool details and print
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry);
@@ -349,101 +393,97 @@ Clarinet.test({
position['ltv-0'].expectUint(ltv_0);
position['bs-vol'].expectUint(bs_vol);
position['conversion-ltv'].expectUint(conversion_ltv);
position['moving-average'].expectUint(moving_average);
position['moving-average'].expectUint(moving_average);
// arbtrageur selling 100 usda for wbtc
result = CRPTest.swapXForY(deployer, wbtcAddress, usdaAddress, expiry, 100 * ONE_8);
// wbtc (token) rises by 50% vs usda (collateral)
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing",wbtcPrice * 1.5);
oracleresult.expectOk()
call = await FWPTest.getPoolDetails(wbtcAddress, usdaAddress, weightX, weightY);
position = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(9966423100);
position['balance-y'].expectUint(501673273700000);
call = await FWPTest.getYgivenPrice(wbtcAddress, usdaAddress, weightX, weightY, Math.round(ONE_8 / ((wbtcPrice / ONE_8) * 1.5)));
call.result.expectOk().expectUint(76790325328021);
result = FWPTest.swapYForX(deployer, wbtcAddress, usdaAddress, weightX, weightY, 76790325328021 + 15773799942279)
position = result.expectOk().expectTuple();
position['dx'].expectUint(100 * ONE_8);
position['dy'].expectUint(199764);
position['dy'].expectUint(76790325328021 + 15773799942279);
position['dx'].expectUint(2254979469);
// arbtrageur selling 0.002 wbtc for usda
result = CRPTest.swapYForX(deployer, wbtcAddress, usdaAddress, expiry, 0.002 * ONE_8);
position = result.expectOk().expectTuple();
position['dx'].expectUint(40109352059);
position['dy'].expectUint(0.002 * ONE_8);
// not accurate enough
call = await FWPTest.getXgivenPrice(wbtcAddress, usdaAddress, weightX, weightY, Math.round(ONE_8 / ((wbtcPrice / ONE_8) * 1.5)));
call.result.expectOk().expectUint(106287676);
// simulate to expiry + 1
chain.mineEmptyBlockUntil((expiry / ONE_8) + 1)
// borrow $5,000 more and convert to wbtc
// remember, the first sell creates profit to LP
result = CRPTest.addToPositionAndSwitch(deployer, wbtcAddress, usdaAddress, yieldwbtc59760Address, keywbtc59760Address, 5000 * ONE_8);
position = result.expectOk().expectTuple();
position['dy'].expectUint(8073663);
position['dx'].expectUint(8127823);
// supply increased
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry);
position = call.result.expectOk().expectTuple();
position['balance-x'].expectUint(3629288282941);
position['balance-y'].expectUint(36901635);
position['yield-supply'].expectUint(88881023);
position['key-supply'].expectUint(88881023);
position['balance-x'].expectUint(3326726300000);
position['balance-y'].expectUint(33576900);
position['yield-supply'].expectUint(80807360);
position['key-supply'].expectUint(80807360);
// pool value increases after adding positions
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(109485635);
call.result.expectOk().expectUint(77933250);
call = await CRPTest.getPoolValueInCollateral(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(5474288282941)
// let's check what is the weight to wbtc (token)
call = await CRPTest.getWeightY(wbtcAddress, usdaAddress, expiry, 50000 * ONE_8, bs_vol);
call.result.expectOk().expectUint(33465993);
call = await CRPTest.getLtv(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(103687912);
// wbtc (token) falls by 20% vs usda (collateral)
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing",wbtcPrice * 0.8);
oracleresult.expectOk()
call = await CRPTest.getBalance("token-usda", reserveAddress);
call.result.expectOk().expectUint(10000000000000)
// move forward by one day
chain.mineEmptyBlockUntil(144);
// with wbtc (token) falling, weight to wbtc (token) should decrease
call = await CRPTest.getWeightY(wbtcAddress, usdaAddress, expiry, 50000 * ONE_8, bs_vol);
call.result.expectOk().expectUint(25427001);
// arbtrageur selling 100 usda for wbtc
result = CRPTest.swapXForY(deployer, wbtcAddress, usdaAddress, expiry, 100 * ONE_8);
// let's burn some yield token
result = CRPTest.reducePositionYield(deployer, wbtcAddress, usdaAddress, yieldwbtc59760Address, ONE_8);
position = result.expectOk().expectTuple();
position['dx'].expectUint(100 * ONE_8);
position['dy'].expectUint(201315);
position['dx'].expectUint(0);
position['dy'].expectUint(80807360);
// swap triggers weight change
// ltv > 100%, so we dip into reserve pool
// the shortfall is about 0.0287411 BTC ~= 2155.5825 USD
call = await CRPTest.getBalance("token-usda", reserveAddress);
call.result.expectOk().expectUint(9702705872037)
// the actual decrease was 2972.94127963 USD, makes sense given AMM slippage
// most of yield-token burnt, but key-token remains
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry);
position = call.result.expectOk().expectTuple();
position['weight-y'].expectUint(25427001);
position['weight-x'].expectUint(ONE_8 - 25427001);
position['yield-supply'].expectUint(88881023);
position['key-supply'].expectUint(88881023);
// simulate to half way to expiry
chain.mineEmptyBlockUntil((expiry / ONE_8) / 2)
position['balance-x'].expectUint(0);
position['balance-y'].expectUint(0);
position['yield-supply'].expectUint(0);
position['key-supply'].expectUint(80807360);
// wbtc rises then by 50%
oracleresult = Oracle.updatePrice(deployer,"WBTC","nothing",wbtcPrice * 0.8 * 1.5);
oracleresult.expectOk();
//
result = YTPTest.createPool(deployer, yieldwbtc79760Address, wbtcAddress, ytpyieldwbtc79760Address, multisigytpyieldwbtc79760, wbtcQ / 10, wbtcQ / 10);
result.expectOk().expectBool(true);
//Deployer creating a pool, initial tokens injected to the pool
result = CRPTest.createPool(deployer, wbtcAddress, usdaAddress, yieldwbtc79760Address, keywbtc79760Address, multisigncrpwbtc79760Address, ltv_0, conversion_ltv, bs_vol, moving_average, 50000 * ONE_8);
result.expectOk().expectBool(true);
call = await CRPTest.getPoolValueInToken(wbtcAddress, usdaAddress, expiry);
call.result.expectOk().expectUint(0);
// Check pool details and print
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry79760);
call = await CRPTest.getPositionGivenBurnKey(wbtcAddress, usdaAddress, expiry, ONE_8);
position = call.result.expectOk().expectTuple();
position['yield-supply'].expectUint(80210834);
position['key-supply'].expectUint(80210834);
position['weight-x'].expectUint(65179620);
position['weight-y'].expectUint(ONE_8 - 65179620);
position['balance-x'].expectUint(3258981000000);
position['balance-y'].expectUint(34684037);
position['strike'].expectUint(60000 * ONE_8);
position['ltv-0'].expectUint(ltv_0);
position['bs-vol'].expectUint(bs_vol);
position['conversion-ltv'].expectUint(conversion_ltv);
position['moving-average'].expectUint(moving_average);
position['dx'].expectUint(0);
position['dy'].expectUint(0);
call = chain.callReadOnlyFn("key-wbtc-59760-usda", "get-balance",
[types.principal(deployer.address)
], deployer.address);
call.result.expectOk().expectUint(80807360);
call = chain.callReadOnlyFn("key-wbtc-59760-usda", "get-total-supply",
[], deployer.address);
call.result.expectOk().expectUint(80807360);
// also remove all key tokens
result = CRPTest.reducePositionKey(deployer, wbtcAddress, usdaAddress, keywbtc59760Address, ONE_8);
position = result.expectOk().expectTuple();
position['dx'].expectUint(0);
position['dy'].expectUint(0);
call = await CRPTest.getPoolDetails(wbtcAddress, usdaAddress, expiry);
position = call.result.expectOk().expectTuple();
position['yield-supply'].expectUint(0);
position['key-supply'].expectUint(0);
position['balance-x'].expectUint(0);
position['balance-y'].expectUint(0);
},
});

View File

@@ -4,7 +4,7 @@ import {
Clarinet,
Tx,
types,
} from "https://deno.land/x/clarinet@v0.13.0/index.ts";
} from "https://deno.land/x/clarinet@v0.14.0/index.ts";
class CRPTestAgent1 {
chain: Chain;
@@ -269,6 +269,24 @@ import {
]);
return block.receipts[0].result;
}
transfer(user: Account, token: string, amount: number, sender: string, recipient: string, memo: ArrayBuffer) {
let block = this.chain.mineBlock([Tx.contractCall(token, "transfer", [
types.uint(amount),
types.principal(sender),
types.principal(recipient),
types.some(types.buff(memo))
], user.address),
]);
return block.receipts[0].result;
}
getBalance(token: string, owner: string) {
return this.chain.callReadOnlyFn(token, "get-balance", [
types.principal(owner)
], this.deployer.address);
}
}
export { CRPTestAgent1 };

View File

@@ -4,7 +4,7 @@ import {
Clarinet,
Tx,
types,
} from "https://deno.land/x/clarinet@v0.13.0/index.ts";
} from "https://deno.land/x/clarinet@v0.14.0/index.ts";
class FWPTestAgent1 {
chain: Chain;
@@ -94,19 +94,26 @@ import {
]);
return block.receipts[0].result;
}
getYgivenX(user: Account, tokenX: string, tokenY: string, weightX: number, weightY: number, dX: number) {
let block = this.chain.mineBlock([
Tx.contractCall("fixed-weight-pool", "get-y-given-x", [
types.principal(tokenX),
types.principal(tokenY),
types.uint(weightX),
types.uint(weightY),
types.uint(dX)
], user.address),
]);
return block.receipts[0].result;
}
getXgivenPrice(tokenX: string, tokenY: string, weightX: number, weightY: number, price: number) {
return this.chain.callReadOnlyFn("fixed-weight-pool", "get-x-given-price", [
types.principal(tokenX),
types.principal(tokenY),
types.uint(weightX),
types.uint(weightY),
types.uint(price)
], this.deployer.address);
}
getYgivenPrice(tokenX: string, tokenY: string, weightX: number, weightY: number, price: number) {
return this.chain.callReadOnlyFn("fixed-weight-pool", "get-y-given-price", [
types.principal(tokenX),
types.principal(tokenY),
types.uint(weightX),
types.uint(weightY),
types.uint(price)
], this.deployer.address);
}
setFeetoAddress(user: Account, tokenX: string, tokenY: string, weightX: number, weightY: number, address: string) {
let block = this.chain.mineBlock([

View File

@@ -4,7 +4,7 @@ import {
Clarinet,
Tx,
types,
} from "https://deno.land/x/clarinet@v0.10.0/index.ts";
} from "https://deno.land/x/clarinet@v0.14.0/index.ts";
class OracleManager {

View File

@@ -4,7 +4,7 @@ import {
Clarinet,
Tx,
types,
} from "https://deno.land/x/clarinet@v0.13.0/index.ts";
} from "https://deno.land/x/clarinet@v0.14.0/index.ts";
class YTPTestAgent1 {
chain: Chain;

View File

@@ -1,15 +1,53 @@
require('dotenv').config();
const {initCoinPrice, setOpenOracle, getOpenOracle} = require('./oracles').default
const { createFWP, createCRP,createYTP } = require('./pools')
const {
fwpCreate,
fwpGetXGivenPrice,
fwpGetPoolDetails,
crpCreate,
crpAddToPostionAndSwitch,
crpGetLtv,
crpGetPoolDetails,
crpGetPoolValueInToken,
ytpCreate,
ytpSwapXforY,
ytpSwapYforX
} = require('./pools')
async function run(){
const {usdc, btc} = await initCoinPrice()
const ONE_8 = 100000000
const expiry = 79760 * ONE_8
const ltv_0 = 0.8 * ONE_8
const conversion_ltv = 0.95 * ONE_8
const bs_vol = 0.8 * ONE_8
const moving_average = 0.95 * ONE_8
const weightX = 0.5 * ONE_8
const weightY = 0.5 * ONE_8
const wbtcQ = 100*ONE_8
const wbtcPrice = 50000
// const {usdc, btc} = await initCoinPrice()
//Need to call it one by one, or you'll receive 'ConflictingNonceInMempool' Error
// await setOpenOracle('WBTC','CoinGecko', btc);
// await setOpenOracle('USDA','CoinGecko', usdc);
//await createFWP()
//await createCRP('yield-usda-59760','key-usda-wbtc-59760');
//await createYTP('yield-usda-59760','token-wbtc', 'pool-token-usda-59760-usda');
//await getOpenOracle('nothing', 'WBTC');
//await getOpenOracle('nothing', 'USDA');
// await setOpenOracle('WBTC','nothing', btc);
// await setOpenOracle('USDA','nothing', usdc);
await getOpenOracle('nothing', 'WBTC');
await getOpenOracle('nothing', 'USDA');
// await crpGetLtv('token-wbtc', 'token-usda', 59760e+8);
// await crpGetPoolValueInToken('token-wbtc', 'token-usda', 59760e+8);
// await crpGetPoolDetails('token-wbtc', 'token-usda', 59760e+8);
// await fwpCreate('token-wbtc', 'token-usda', 5e+7, 5e+7, 'fwp-wbtc-usda-50-50', 'multisig-fwp-wbtc-usda-50-50', wbtcQ, wbtcPrice * wbtcQ);
// await ytpCreate('yield-wbtc-79760', 'token-wbtc', 'ytp-yield-wbtc-79760-wbtc', 'multisig-ytp-yield-wbtc-79760-wbtc', wbtcQ / 10, wbtcQ / 10);
// await crpCreate('token-wbtc', 'token-usda', 'yield-wbtc-79760', 'key-wbtc-79760-usda', 'multisig-crp-wbtc-79760-usda', ltv_0, conversion_ltv, bs_vol, moving_average, 50000 * ONE_8);
await fwpGetXGivenPrice('token-wbtc', 'token-usda', weightX, weightY, 4846200000000)
//await fwpGetPoolDetails('token-wbtc', 'token-usda', weightX, weightY);
// await crpGetLtv('token-wbtc', 'token-usda', expiry);
// await crpGetPoolValueInToken('token-wbtc', 'token-usda', expiry);
// await crpGetPoolDetails('token-wbtc', 'token-usda', expiry);
}
run();

View File

@@ -2,10 +2,12 @@ const CoinGecko = require('coingecko-api');
const CoinGeckoClient = new CoinGecko();
const {
makeContractCall,
callReadOnlyFunction,
AnchorMode,
stringAsciiCV,
uintCV,
broadcastTransaction
broadcastTransaction,
bufferCVFromString
} = require('@stacks/transactions');
@@ -64,9 +66,8 @@ const setOpenOracle = async (symbol, src, price) => {
//Call open-oracle to get price
const getOpenOracle = async (src, symbol) => {
console.log('Getting oracle...', src, symbol);
const privateKey = await getPK();
const txOptions = {
const options = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'open-oracle',
functionName: 'get-price',
@@ -74,15 +75,12 @@ const getOpenOracle = async (src, symbol) => {
stringAsciiCV(src),
stringAsciiCV(symbol)
],
senderKey: privateKey,
validateWithAbi: true,
network,
anchorMode: AnchorMode.Any,
network: network,
senderAddress: process.env.ACCOUNT_ADDRESS,
};
try {
const transaction = await makeContractCall(txOptions);
const broadcastResponse = await broadcastTransaction(transaction, network);
console.log(broadcastResponse);
const result = await callReadOnlyFunction(options);
console.log(result);
} catch (error) {
console.log(error);
}

3252
init-js-tool/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,27 +3,31 @@ const {
} = require('./wallet');
const {
makeContractCall,
callReadOnlyFunction,
AnchorMode,
PostConditionMode,
uintCV,
contractPrincipalCV,
broadcastTransaction
broadcastTransaction,
ClarityType
} = require('@stacks/transactions');
const { principalCV } = require('@stacks/transactions/dist/clarity/types/principalCV');
const createFWP = async () => {
const fwpCreate = async (tokenX, tokenY, weightX, weightY, poolToken, multiSig, dx, dy) => {
const privateKey = await getPK();
const txOptions = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'fixed-weight-pool',
functionName: 'create-pool',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, 'token-wbtc'),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, 'token-usda'),
uintCV(5*1e7),
uintCV(5*1e7),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS,'pool-token-usda-59760-usda'),
uintCV(5*1e11),
uintCV(1e11),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, tokenX),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, tokenY),
uintCV(weightX),
uintCV(weightY),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, poolToken),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, multiSig),
uintCV(dx),
uintCV(dy),
],
senderKey: privateKey,
validateWithAbi: true,
@@ -39,20 +43,23 @@ const createFWP = async () => {
console.log(error);
}
}
const createCRP = async (yiedToken, keyToken) => {
const crpCreate = async (token, collateral, yiedToken, keyToken, multiSig, ltv_0, conversion_ltv, bs_vol, moving_average, dx) => {
const privateKey = await getPK();
const txOptions = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'collateral-rebalancing-pool',
functionName: 'create-pool',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, 'token-wbtc'),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, 'token-usda'),
// contractPrincipalCV(process.env.ACCOUNT_ADDRESS, 'yield-usda-59760'),
// contractPrincipalCV(process.env.ACCOUNT_ADDRESS, 'key-usda-wbtc-59760'),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, collateral),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, yiedToken),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, keyToken),
uintCV(10*1e8),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, multiSig),
uintCV(ltv_0),
uintCV(conversion_ltv),
uintCV(bs_vol),
uintCV(moving_average),
uintCV(dx),
],
senderKey: privateKey,
validateWithAbi: true,
@@ -68,7 +75,7 @@ const createCRP = async (yiedToken, keyToken) => {
console.log(error);
}
}
const createYTP = async (yiedToken, token, poolToken) => {
const ytpCreate = async (yiedToken, token, poolToken, multiSig, dx, dy) => {
const privateKey = await getPK();
const txOptions = {
contractAddress: process.env.ACCOUNT_ADDRESS,
@@ -78,8 +85,9 @@ const createYTP = async (yiedToken, token, poolToken) => {
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, yiedToken),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, poolToken),
uintCV(10*1e8),
uintCV(10*1e8),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, multiSig),
uintCV(dx),
uintCV(dy),
],
senderKey: privateKey,
validateWithAbi: true,
@@ -95,6 +103,231 @@ const createYTP = async (yiedToken, token, poolToken) => {
console.log(error);
}
}
exports.createFWP = createFWP;
exports.createCRP = createCRP;
exports.createYTP = createYTP;
const crpAddToPostionAndSwitch = async (token, collateral, yiedToken, keyToken, multiSig, ltv_0, conversion_ltv, bs_vol, moving_average, dx) => {
const privateKey = await getPK();
const txOptions = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'collateral-rebalancing-pool',
functionName: 'add-to-position-and-switch',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, collateral),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, yiedToken),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, keyToken),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, multiSig),
uintCV(ltv_0),
uintCV(conversion_ltv),
uintCV(bs_vol),
uintCV(moving_average),
uintCV(dx),
],
senderKey: privateKey,
validateWithAbi: true,
network,
anchorMode: AnchorMode.Any,
postConditionMode: PostConditionMode.Allow,
};
try {
const transaction = await makeContractCall(txOptions);
const broadcastResponse = await broadcastTransaction(transaction, network);
console.log(broadcastResponse);
} catch (error) {
console.log(error);
}
}
const ytpSwapXforY = async (yiedToken, token, dx) => {
const privateKey = await getPK();
const txOptions = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'yield-token-pool',
functionName: 'swap-x-for-y',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, yiedToken),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
uintCV(dx)
],
senderKey: privateKey,
validateWithAbi: true,
network,
anchorMode: AnchorMode.Any,
postConditionMode: PostConditionMode.Allow,
};
try {
const transaction = await makeContractCall(txOptions);
const broadcastResponse = await broadcastTransaction(transaction, network);
console.log(broadcastResponse);
} catch (error) {
console.log(error);
}
}
const ytpSwapYforX = async (yiedToken, token, dy) => {
const privateKey = await getPK();
const txOptions = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'yield-token-pool',
functionName: 'swap-y-for-x',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, yiedToken),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
uintCV(dy)
],
senderKey: privateKey,
validateWithAbi: true,
network,
anchorMode: AnchorMode.Any,
postConditionMode: PostConditionMode.Allow,
};
try {
const transaction = await makeContractCall(txOptions);
const broadcastResponse = await broadcastTransaction(transaction, network);
console.log(broadcastResponse);
} catch (error) {
console.log(error);
}
}
const crpGetLtv = async (token, collateral, expiry) => {
console.log('Getting LTV...', token, collateral, expiry);
const options = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'collateral-rebalancing-pool',
functionName: 'get-ltv',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, collateral),
uintCV(expiry)
],
network: network,
senderAddress: process.env.ACCOUNT_ADDRESS,
};
try {
const result = await callReadOnlyFunction(options);
console.log(result);
} catch (error) {
console.log(error);
}
};
const crpGetPoolValueInToken = async (token, collateral, expiry) => {
console.log('Getting CRP Pool Value in Token...', token, collateral, expiry);
const options = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'collateral-rebalancing-pool',
functionName: 'get-pool-value-in-token',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, collateral),
uintCV(expiry)
],
network: network,
senderAddress: process.env.ACCOUNT_ADDRESS,
};
try {
const result = await callReadOnlyFunction(options);
console.log(result);
} catch (error) {
console.log(error);
}
};
const crpGetPoolDetails = async (token, collateral, expiry) => {
console.log('Getting CRP Pool Details...', token, collateral, expiry);
const options = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'collateral-rebalancing-pool',
functionName: 'get-pool-details',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, token),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, collateral),
uintCV(expiry)
],
network: network,
senderAddress: process.env.ACCOUNT_ADDRESS,
};
try {
const result = await callReadOnlyFunction(options);
printResult(result);
} catch (error) {
console.log(error);
}
};
const printResult = (result)=>{
if(result.type === ClarityType.ResponseOk){
if(result.value.type == ClarityType.UInt){
console.log(result.value);
}else if(result.value.type == ClarityType.Tuple){
console.log('|');
for (const key in result.value.data) {
console.log('---',key,':',result.value.data[key]);
}
}
}
}
const fwpGetXGivenPrice = async (tokenX, tokenY, weightX, weightY, price) => {
console.log('[FWP] For given price, what is X...', tokenX, tokenY, weightX, weightY, price);
const options = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'fixed-weight-pool',
functionName: 'get-x-given-price',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, tokenX),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, tokenY),
uintCV(weightX),
uintCV(weightY),
uintCV(price)
],
network: network,
senderAddress: process.env.ACCOUNT_ADDRESS,
};
try {
const result = await callReadOnlyFunction(options);
console.log(result);
} catch (error) {
console.log(error);
}
};
const fwpGetPoolDetails = async (tokenX, tokenY, weightX, weightY) => {
console.log('Getting FWP Pool Details...', tokenX, tokenY, weightX, weightY);
const options = {
contractAddress: process.env.ACCOUNT_ADDRESS,
contractName: 'fixed-weight-pool',
functionName: 'get-pool-details',
functionArgs: [
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, tokenX),
contractPrincipalCV(process.env.ACCOUNT_ADDRESS, tokenY),
uintCV(weightX),
uintCV(weightY)
],
network: network,
senderAddress: process.env.ACCOUNT_ADDRESS,
};
try {
const result = await callReadOnlyFunction(options);
printResult(result);
} catch (error) {
console.log(error);
}
};
exports.fwpCreate = fwpCreate;
exports.crpCreate = crpCreate;
exports.ytpCreate = ytpCreate;
exports.crpAddToPostionAndSwitch = crpAddToPostionAndSwitch;
exports.ytpSwapXforY = ytpSwapXforY;
exports.ytpSwapYforX = ytpSwapYforX;
exports.crpGetLtv = crpGetLtv;
exports.crpGetPoolDetails = crpGetPoolDetails;
exports.crpGetPoolValueInToken = crpGetPoolValueInToken;
exports.fwpGetXGivenPrice = fwpGetXGivenPrice;
exports.fwpGetPoolDetails = fwpGetPoolDetails;

View File

@@ -1,6 +1,7 @@
const { generateWallet } = require('@stacks/wallet-sdk');
const {
StacksRegtest
StacksRegtest,
StacksMocknet
} = require('@stacks/network');
const getPK = async ()=>{
const wallet = await generateWallet({
@@ -10,6 +11,9 @@ const getPK = async ()=>{
const privateKey = wallet.accounts[0].stxPrivateKey
return privateKey
}
const network = new StacksRegtest();
//const network = new StacksRegtest();
const network = new StacksMocknet({
url:'https://regtest-2.alexgo.io'
})
exports.getPK = getPK
exports.network = network;