diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/ghost.bas b/ghost.bas index ca16fd6..699b11c 100644 --- a/ghost.bas +++ b/ghost.bas @@ -15,11 +15,14 @@ ////////////////////////////////////// Function Initialize() Uint64 + 01 IF EXISTS("owner") == 0 THEN GOTO 10 + 02 GOTO 666 10 STORE("owner", SIGNER()) 20 STORE("feeTo", SIGNER()) 30 STORE("nameHdr", "Ghost Exchange") 40 STORE("descrHdr", "Phantom-powered finance") - 50 RETURN 0 + 50 RETURN 0 + 666 RETURN 1 End Function // Provided liquidity will be tracked using BOO tokens. @@ -38,7 +41,7 @@ Function AddLiquidity(asset_address String, min_liquidity Uint64) Uint64 02 LET SYS_MAX_VALUE = 18446744073709551 // Uint64.Max/1000 to protect from infinite supply tokens 03 LET dero_deposited = DEROVALUE() 04 LET asset_deposited = ASSETVALUE(HEXDECODE(asset_address)) - 10 IF (asset_deposited > 0 & dero_deposited > 0 ) THEN GOTO 30 + 10 IF (asset_deposited > 0 && dero_deposited > 0 ) THEN GOTO 30 20 GOTO 666 30 LET total_liquidity = get_supply_per_asset(asset_address) // Pair already exists @@ -52,7 +55,7 @@ Function AddLiquidity(asset_address String, min_liquidity Uint64) Uint64 47 LET total_liquidity = get_supply_per_asset(asset_address) // Must be defined again since totalSupply can update in mintFee 48 LET asset_amount = mult_div(dero_deposited, asset_reserve , dero_reserve + 1) 49 LET liquidity_minted = mult_div(dero_deposited, total_liquidity, dero_reserve) - 50 IF asset_deposited >= asset_amount & liquidity_minted >= min_liquidity & (asset_reserve + asset_deposited <= SYS_MAX_VALUE) THEN GOTO 52 + 50 IF asset_deposited >= asset_amount && liquidity_minted >= min_liquidity && (asset_reserve + asset_deposited <= SYS_MAX_VALUE) THEN GOTO 52 51 GOTO 666 52 increase_provider_liquidity_by(SIGNER(), liquidity_minted, asset_address) 53 set_supply_per_asset(total_liquidity + liquidity_minted, asset_address) @@ -68,7 +71,7 @@ Function AddLiquidity(asset_address String, min_liquidity Uint64) Uint64 59 GOTO 70 // else // Creating pair - 60 IF dero_deposited >= 1000 & asset_deposited <= SYS_MAX_VALUE THEN GOTO 62 + 60 IF dero_deposited >= 1000 && asset_deposited <= SYS_MAX_VALUE THEN GOTO 62 61 GOTO 666 // Initialize the asset reserve record for this asset 62 set_asset_reserve(asset_deposited, asset_address) @@ -91,7 +94,7 @@ End Function // {asset_address} The deposited asset's SCID Function RemoveLiquidity(amount Uint64, min_dero Uint64, min_assets Uint64, asset_address String) Uint64 01 DIM total_liquidity, dero_reserve, asset_reserve, dero_amount, asset_amount as Uint64 - 10 IF amount > 0 & (min_dero > 0 & min_assets > 0) & ( get_provider_liquidity(SIGNER(), asset_address) >= amount ) THEN GOTO 30 + 10 IF amount > 0 && (min_dero > 0 && min_assets > 0) && ( get_provider_liquidity(SIGNER(), asset_address) >= amount ) THEN GOTO 30 20 GOTO 666 30 LET total_liquidity = get_supply_per_asset(asset_address) 40 IF total_liquidity > 0 THEN GOTO 60 @@ -102,7 +105,7 @@ Function RemoveLiquidity(amount Uint64, min_dero Uint64, min_assets Uint64, asse 90 LET total_liquidity = get_supply_per_asset(asset_address) // Must be defined again since totalSupply can update in mintFee 100 LET dero_amount = mult_div(amount, dero_reserve, total_liquidity) 110 LET asset_amount = mult_div(amount, asset_reserve, total_liquidity) - 120 IF dero_amount >= min_dero & asset_amount >= min_assets THEN GOTO 140 + 120 IF dero_amount >= min_dero && asset_amount >= min_assets THEN GOTO 140 130 GOTO 666 140 decrease_provider_liquidity_by(SIGNER(), amount, asset_address) 150 set_supply_per_asset(total_liquidity - amount, asset_address) @@ -121,14 +124,10 @@ End Function // {input_reserve} Amount of DERO or Assets (input type) in exchange reserves. // {output_reserve} Amount of DERO or Assets (output type) in exchange reserves. Function getInputPrice(input_amount Uint64, input_reserve Uint64, output_reserve Uint64) Uint64 - 01 DIM SYS_MAX_VALUE as Uint64 - 02 LET SYS_MAX_VALUE = 18446744073709551 - 10 IF input_reserve > 0 & output_reserve > 0 & input_amount <= SYS_MAX_VALUE THEN GOTO 30 - 20 PANIC 30 DIM input_amount_with_fee as Uint64 40 LET input_amount_with_fee = input_amount * 997 50 IF will_addition_overflow(input_reserve * 1000, input_amount * 1000) == 0 THEN GOTO 70 - 60 PANIC // Infinite supply token attack + 60 PANIC // Infinite supply token attack, attackers assets can burn in hell 70 RETURN mult_div(input_amount_with_fee, output_reserve, (input_reserve * 1000) + input_amount_with_fee) End Function @@ -137,20 +136,21 @@ End Function // {input_reserve} Amount of DERO or Assets (input type) in exchange reserves. // {output_reserve} Amount of DERO or Assets (output type) in exchange reserves. Function getOutputPrice(output_amount Uint64, input_reserve Uint64, output_reserve Uint64) Uint64 - 10 IF input_reserve > 0 && output_reserve > 0 && output_reserve > output_amount THEN GOTO 30 - 20 PANIC 30 RETURN mult_div(input_reserve * 1000, output_amount, (output_reserve - output_amount) * 997 + 1) End Function Function deroToAssetInput(dero_sold Uint64, min_assets Uint64, asset_address String) Uint64 - 10 IF (dero_sold > 0 & min_assets > 0) THEN GOTO 30 - 20 PANIC - 30 DIM assets_bought, asset_reserve, dero_reserve as Uint64 + 10 IF (dero_sold > 0 && min_assets > 0) THEN GOTO 30 + 20 RETURN 1 + 30 DIM assets_bought, asset_reserve, dero_reserve, SYS_MAX_VALUE as Uint64 40 LET asset_reserve = get_asset_reserve(asset_address) 50 LET dero_reserve = get_dero_reserve_per_asset(asset_address) + 51 LET SYS_MAX_VALUE = 18446744073709551 + 52 IF dero_reserve > 0 && asset_reserve > 0 && dero_sold <= SYS_MAX_VALUE THEN GOTO 60 + 53 RETURN 1 60 LET assets_bought = getInputPrice(dero_sold, dero_reserve, asset_reserve) 70 IF assets_bought >= min_assets THEN GOTO 90 - 80 PANIC + 80 RETURN 1 90 SEND_ASSET_TO_ADDRESS(SIGNER(), assets_bought, HEXDECODE(asset_address)) 100 set_asset_reserve(asset_reserve - assets_bought, asset_address) 110 set_dero_reserve_per_asset(dero_reserve + dero_sold, asset_address) @@ -174,14 +174,16 @@ Function DeroToAssetSwapInputMin(min_assets Uint64, asset_address String) Uint64 End Function Function deroToAssetOutput(assets_bought Uint64, max_dero Uint64, asset_address String) Uint64 - 10 IF (assets_bought > 0 & max_dero > 0) THEN GOTO 30 - 20 PANIC + 10 IF (assets_bought > 0 && max_dero > 0) THEN GOTO 30 + 20 RETURN 1 30 DIM asset_reserve, dero_reserve, dero_sold, dero_refund as Uint64 40 LET asset_reserve = get_asset_reserve(asset_address) 41 LET dero_reserve = get_dero_reserve_per_asset(asset_address) + 42 IF dero_reserve > 0 && asset_reserve > 0 && asset_reserve > assets_bought THEN GOTO 50 + 43 RETURN 1 50 LET dero_sold = getOutputPrice(assets_bought, dero_reserve, asset_reserve) 60 IF dero_sold > max_dero THEN GOTO 61 ELSE GOTO 70 - 61 PANIC + 61 RETURN 1 70 LET dero_refund = max_dero - dero_sold 80 IF dero_refund == 0 THEN GOTO 100 90 SEND_DERO_TO_ADDRESS(SIGNER(), dero_refund) @@ -200,15 +202,19 @@ Function DeroToAssetSwapOutput(assets_bought Uint64, asset_address String) Uint6 End Function Function assetToDeroInput(assets_sold Uint64, min_dero Uint64, asset_address String) Uint64 - 10 IF (assets_sold > 0 & min_dero > 0) THEN GOTO 30 - 20 PANIC - 30 DIM asset_reserve, dero_bought as Uint64 + 10 IF (assets_sold > 0 && min_dero > 0) THEN GOTO 30 + 20 RETURN 1 + 30 DIM asset_reserve, dero_reserve, dero_bought, SYS_MAX_VALUE as Uint64 40 LET asset_reserve = get_asset_reserve(asset_address) - 50 LET dero_bought = getInputPrice(assets_sold, asset_reserve, get_dero_reserve_per_asset(asset_address)) + 41 LET dero_reserve = get_dero_reserve_per_asset(asset_address) + 42 LET SYS_MAX_VALUE = 18446744073709551 + 43 IF asset_reserve > 0 && dero_reserve > 0 && assets_sold <= SYS_MAX_VALUE THEN GOTO 50 + 44 RETURN 1 + 50 LET dero_bought = getInputPrice(assets_sold, asset_reserve, dero_reserve) 60 IF dero_bought >= min_dero THEN GOTO 80 - 70 PANIC + 70 RETURN 1 80 SEND_DERO_TO_ADDRESS(SIGNER(),dero_bought) - 90 set_dero_reserve_per_asset(get_dero_reserve_per_asset(asset_address) - dero_bought, asset_address) + 90 set_dero_reserve_per_asset(dero_reserve - dero_bought, asset_address) 100 set_asset_reserve(asset_reserve + assets_sold, asset_address) 110 RETURN 0 End Function @@ -224,18 +230,21 @@ End Function Function assetToDeroOutput(dero_bought Uint64, max_assets Uint64 , asset_address String) Uint64 10 IF dero_bought > 0 THEN GOTO 30 - 20 PANIC - 30 DIM asset_reserve, assets_sold, asset_refund as Uint64 + 20 RETURN 1 + 30 DIM asset_reserve, dero_reserve, assets_sold, asset_refund as Uint64 40 LET asset_reserve = get_asset_reserve(asset_address) - 50 LET assets_sold = getOutputPrice(dero_bought, asset_reserve, get_dero_reserve_per_asset(asset_address)) + 41 LET dero_reserve = get_dero_reserve_per_asset(asset_address) + 42 IF asset_reserve > 0 && dero_reserve > 0 && dero_reserve > dero_bought THEN GOTO 50 + 43 RETURN 1 + 50 LET assets_sold = getOutputPrice(dero_bought, asset_reserve, dero_reserve) // assets_sold is always > zero 60 IF max_assets >= assets_sold THEN GOTO 80 - 70 PANIC + 70 RETURN 1 80 SEND_DERO_TO_ADDRESS(SIGNER(), dero_bought) 90 LET asset_refund = max_assets - assets_sold 100 IF asset_refund == 0 THEN GOTO 120 110 SEND_ASSET_TO_ADDRESS(SIGNER(), asset_refund, HEXDECODE(asset_address)) - 120 set_dero_reserve_per_asset(get_dero_reserve_per_asset(asset_address) - dero_bought, asset_address) + 120 set_dero_reserve_per_asset(dero_reserve - dero_bought, asset_address) 130 set_asset_reserve(asset_reserve + assets_sold, asset_address) 140 RETURN 0 End Function @@ -248,74 +257,34 @@ Function AssetToDeroSwapOutput(dero_bought Uint64, asset_address String) Uint64 10 RETURN assetToDeroOutput(dero_bought, ASSETVALUE(HEXDECODE(asset_address)), asset_address) End Function -// Public price function for DERO to Asset trades with an exact input. -// {dero_sold} Amount of DERO sold. -// {asset_address} Address of the asset to trade. -// @returns Amount of Assets that can be bought with input DERO. -Function GetDeroToAssetInputPrice(dero_sold Uint64, asset_address String) Uint64 - 10 IF dero_sold > 0 THEN GOTO 30 - 20 RETURN 0 - 30 RETURN getInputPrice(dero_sold, get_dero_reserve_per_asset(asset_address), get_asset_reserve(asset_address)) -End Function - -// Public price function for DERO to Asset trades with an exact output. -// {assets_bought} Amount of Assets bought. -// {asset_address} Address of the asset to trade. -// @returns Amount of DERO needed to buy output Assets. -Function GetDeroToAssetOutputPrice(assets_bought Uint64, asset_address String) Uint64 - 10 IF assets_bought > 0 THEN GOTO 30 - 20 RETURN 0 - 30 RETURN getOutputPrice(assets_bought, get_dero_reserve_per_asset(asset_address), get_asset_reserve(asset_address)) -End Function - -// Public price function for Asset to DERO trades with an exact input. -// {assets_sold} Amount of Assets sold. -// {asset_address} Address of the asset to trade. -// @returns Amount of DERO that can be bought with input Assets. -Function GetAssetToDeroInputPrice(assets_sold Uint64, asset_address String) Uint64 - 10 IF assets_sold > 0 THEN GOTO 30 - 20 RETURN 0 - 30 RETURN getInputPrice(assets_sold, get_asset_reserve(asset_address), get_dero_reserve_per_asset(asset_address)) -End Function - -// Public price function for Asset to DERO trades with an exact output. -// {dero_bought} Amount of output DERO. -// {asset_address} Address of the asset to trade. -// @returns Amount of Assets needed to buy output DERO. -Function GetAssetToDeroOutputPrice(dero_bought Uint64, asset_address String) Uint64 - 10 IF dero_bought > 0 THEN GOTO 30 - 20 RETURN 0 - 30 RETURN getOutputPrice(dero_bought, get_asset_reserve(asset_address), get_dero_reserve_per_asset(asset_address)) -End Function - -Function mintFee(reserve0 Uint64, reserve1 Uint64, asset_address String) +Function mintFee(reserve0 Uint64, reserve1 Uint64, asset_address String) Uint64 10 DIM feeTo as String 11 DIM rootKLast as Uint64 20 LET feeTo = LOAD("feeTo") // Get the last root k for the asset 30 LET rootKLast = LOAD(asset_address+":rootKLast") 40 IF rootKLast != 0 THEN GOTO 50 - 41 RETURN + 41 RETURN 0 50 DIM rootK as Uint64 60 LET rootK = sqrt(reserve0) * sqrt(reserve1) 70 IF rootK > rootKLast THEN GOTO 80 - 71 RETURN + 71 RETURN 0 80 DIM supply, liquidity_minted as Uint64 90 LET supply = get_supply_per_asset(asset_address) 100 LET liquidity_minted = mult_div(supply, rootK - rootKLast, rootK * 5 + rootKLast) 110 IF liquidity_minted > 0 THEN GOTO 111 ELSE GOTO 120 111 increase_provider_liquidity_by(feeTo, liquidity_minted, asset_address) 112 set_supply_per_asset(supply + liquidity_minted, asset_address) - 120 RETURN + 120 RETURN 0 End Function // Helper functions // Encapsulated to better understand what's happening and absctract BOO storage schema // from main code. -Function set_supply_per_asset(amount Uint64, asset_address String) +Function set_supply_per_asset(amount Uint64, asset_address String) Uint64 10 STORE(asset_address+":BOO", amount) - 20 RETURN + 20 RETURN 0 End Function Function get_supply_per_asset(asset_address String) Uint64 @@ -324,35 +293,35 @@ Function get_supply_per_asset(asset_address String) Uint64 30 RETURN LOAD(asset_address+":BOO") End Function -Function set_dero_reserve_per_asset(amount Uint64, asset_address String) +Function set_dero_reserve_per_asset(amount Uint64, asset_address String) Uint64 10 STORE(asset_address+":DERO", amount) - 20 RETURN + 20 RETURN 0 End Function Function get_dero_reserve_per_asset(asset_address String) Uint64 10 RETURN LOAD(asset_address+":DERO") End Function -Function set_asset_reserve(amount Uint64, asset_address String) +Function set_asset_reserve(amount Uint64, asset_address String) Uint64 10 STORE(asset_address, amount) - 20 RETURN + 20 RETURN 0 End Function Function get_asset_reserve(asset_address String) Uint64 20 RETURN LOAD(asset_address) End Function -Function increase_provider_liquidity_by(provider_address String, amount Uint64, asset_address String) +Function increase_provider_liquidity_by(provider_address String, amount Uint64, asset_address String) Uint64 10 IF EXISTS(ADDRESS_STRING(provider_address)+":BOO:"+asset_address) THEN GOTO 40 20 STORE(ADDRESS_STRING(provider_address)+":BOO:"+asset_address, amount) - 30 RETURN - 40 STORE(ADDRESS_STRING(provider_address)+":BOO:"+asset_address, get_provider_liquidity(provider_address, asset_address) + amount) - 50 RETURN + 30 RETURN 0 + 40 STORE(ADDRESS_STRING(provider_address)+":BOO:"+asset_address, get_provider_liquidity(provider_address, asset_address) + amount) + 50 RETURN 0 End Function -Function decrease_provider_liquidity_by(provider_address String, amount Uint64, asset_address String) +Function decrease_provider_liquidity_by(provider_address String, amount Uint64, asset_address String) Uint64 10 STORE(ADDRESS_STRING(provider_address)+":BOO:"+asset_address, get_provider_liquidity(provider_address, asset_address) - amount) - 20 RETURN + 20 RETURN 0 End Function Function get_provider_liquidity(provider_address String, asset_address String) Uint64 @@ -368,66 +337,66 @@ End Function // From Pieswap // lossless (a * b ) / c Function mult_div(a Uint64, b Uint64, c Uint64) Uint64 - 10 DIM base, maxdiv AS Uint64 - 20 LET base = 4294967296 // (1<<32) - 30 LET maxdiv = (base-1)*base + (base-1) - - 50 DIM res AS Uint64 - 60 LET res = (a/c) * b + (a%c) * (b/c) - 70 LET a = a % c - 80 LET b = b % c - 90 IF (a == 0 || b == 0) THEN GOTO 1000 - - 100 IF (c >= base) THEN GOTO 200 - 110 LET res = res + (a*b/c) - 120 GOTO 1000 - - 200 DIM norm AS Uint64 - 210 LET norm = maxdiv/c - 220 LET c = c * norm - 230 LET a = a * norm - - 300 DIM ah, al, bh, bl, ch, cl AS Uint64 - 310 LET ah = a / base - 320 LET al = a % base - 330 LET bh = b / base - 340 LET bl = b % base - 350 LET ch = c / base - 360 LET cl = c % base - - 400 DIM p0, p1, p2 AS Uint64 - 410 LET p0 = al*bl - 420 LET p1 = p0 / base + al*bh - 430 LET p0 = p0 % base - 440 LET p2 = p1 / base + ah*bh - 450 LET p1 = (p1 % base) + ah*bl - 460 LET p2 = p2 + p1 / base - 470 LET p1 = p1 % base - - 500 DIM q0, q1, rhat AS Uint64 - 510 LET p2 = p2 % c - 520 LET q1 = p2 / ch - 530 LET rhat = p2 % ch - - 600 IF (q1 < base && (rhat >= base || q1*cl <= rhat*base+p1)) THEN GOTO 700 - 610 LET q1 = q1 - 1 - 620 LET rhat = rhat + ch - 630 GOTO 600 - - 700 LET p1 = ((p2 % base) * base + p1) - q1 * cl - 710 LET p2 = (p2 / base * base + p1 / base) - q1 * ch - 720 LET p1 = (p1 % base) + (p2 % base) * base - 730 LET q0 = p1 / ch - 740 LET rhat = p1 % ch - - 800 IF (q0 < base && (rhat >= base || q0*cl <= rhat*base+p0)) THEN GOTO 900 - 810 LET q0 = q0 - 1 - 820 LET rhat = rhat + ch - 830 GOTO 800 - - 900 LET res = res + q0 + q1 * base - - 1000 RETURN res + 10 DIM base, maxdiv AS Uint64 + 20 LET base = 4294967296 // (1<<32) + 30 LET maxdiv = (base-1)*base + (base-1) + + 50 DIM res AS Uint64 + 60 LET res = (a/c) * b + (a%c) * (b/c) + 70 LET a = a % c + 80 LET b = b % c + 90 IF (a == 0 || b == 0) THEN GOTO 1000 + + 100 IF (c >= base) THEN GOTO 200 + 110 LET res = res + (a*b/c) + 120 GOTO 1000 + + 200 DIM norm AS Uint64 + 210 LET norm = maxdiv/c + 220 LET c = c * norm + 230 LET a = a * norm + + 300 DIM ah, al, bh, bl, ch, cl AS Uint64 + 310 LET ah = a / base + 320 LET al = a % base + 330 LET bh = b / base + 340 LET bl = b % base + 350 LET ch = c / base + 360 LET cl = c % base + + 400 DIM p0, p1, p2 AS Uint64 + 410 LET p0 = al*bl + 420 LET p1 = p0 / base + al*bh + 430 LET p0 = p0 % base + 440 LET p2 = p1 / base + ah*bh + 450 LET p1 = (p1 % base) + ah*bl + 460 LET p2 = p2 + p1 / base + 470 LET p1 = p1 % base + + 500 DIM q0, q1, rhat AS Uint64 + 510 LET p2 = p2 % c + 520 LET q1 = p2 / ch + 530 LET rhat = p2 % ch + + 600 IF (q1 < base && (rhat >= base || q1*cl <= rhat*base+p1)) THEN GOTO 700 + 610 LET q1 = q1 - 1 + 620 LET rhat = rhat + ch + 630 GOTO 600 + + 700 LET p1 = ((p2 % base) * base + p1) - q1 * cl + 710 LET p2 = (p2 / base * base + p1 / base) - q1 * ch + 720 LET p1 = (p1 % base) + (p2 % base) * base + 730 LET q0 = p1 / ch + 740 LET rhat = p1 % ch + + 800 IF (q0 < base && (rhat >= base || q0*cl <= rhat*base+p0)) THEN GOTO 900 + 810 LET q0 = q0 - 1 + 820 LET rhat = rhat + ch + 830 GOTO 800 + + 900 LET res = res + q0 + q1 * base + + 1000 RETURN res End Function // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) diff --git a/ghost_min.bas b/ghost_min.bas new file mode 100644 index 0000000..cffc42c --- /dev/null +++ b/ghost_min.bas @@ -0,0 +1,304 @@ +Function Initialize() Uint64 +1 IF EXISTS("owner")==0 THEN GOTO 10 +2 GOTO 666 +10 STORE("owner",SIGNER()) +20 STORE("feeTo",SIGNER()) +30 STORE("nameHdr","Ghost Exchange") +40 STORE("descrHdr","Phantom-powered finance") +50 RETURN 0 +666 RETURN 1 +End Function +Function AddLiquidity(t String,u Uint64) Uint64 +1 DIM w2,r1,s1,t1,u1,v1,w1,x1 AS Uint64 +2 LET x1 = 18446744073709551 +3 LET v1 = DEROVALUE() +4 LET w1 = ASSETVALUE(HEXDECODE(t)) +10 IF (w1>0)&&(v1>0) THEN GOTO 30 +20 GOTO 666 +30 LET w2 = i(t) +40 IF w2>0 THEN GOTO 41 ELSE GOTO 60 +41 IF u>0 THEN GOTO 43 +42 GOTO 666 +43 LET r1 = k(t) +44 LET s1 = m(t) +45 IF q(s1,w1)==1 THEN GOTO 666 +46 g(r1,s1,t) +47 LET w2 = i(t) +48 LET t1 = r(v1,s1,r1+1) +49 LET u1 = r(v1,w2,r1) +50 IF ((w1>=t1)&&(u1>=u))&&((s1+w1)<=x1) THEN GOTO 52 +51 GOTO 666 +52 n(SIGNER(),u1,t) +53 h(w2+u1,t) +54 IF w1==t1 THEN GOTO 56 +55 SEND_ASSET_TO_ADDRESS(SIGNER(),w1-t1,HEXDECODE(t)) +56 j(r1+v1,t) +57 l(s1+t1,t) +58 STORE(t+":rootKLast",s(r1+v1)*s(s1+t1)) +59 GOTO 70 +60 IF (v1>=1000)&&(w1<=x1) THEN GOTO 62 +61 GOTO 666 +62 l(w1,t) +63 DIM y1 AS Uint64 +64 LET y1 = v1 +65 h(y1,t) +66 j(v1,t) +67 STORE(t+":rootKLast",s(w1)*s(v1)) +68 n(SIGNER(),y1,t) +70 RETURN 0 +666 RETURN 1 +End Function +Function RemoveLiquidity(v Uint64,w Uint64,y2 Uint64,t String) Uint64 +1 DIM w2,r1,s1,z1,t1 AS Uint64 +10 IF ((v>0)&&((w>0)&&(y2>0)))&&(p(SIGNER(),t)>=v) THEN GOTO 30 +20 GOTO 666 +30 LET w2 = i(t) +40 IF w2>0 THEN GOTO 60 +50 GOTO 666 +60 LET s1 = m(t) +70 LET r1 = k(t) +80 g(r1,s1,t) +90 LET w2 = i(t) +100 LET z1 = r(v,r1,w2) +110 LET t1 = r(v,s1,w2) +120 IF (z1>=w)&&(t1>=y2) THEN GOTO 140 +130 GOTO 666 +140 o(SIGNER(),v,t) +150 h(w2-v,t) +160 j(r1-z1,t) +170 l(s1-t1,t) +180 STORE(t+":rootKLast",s(r1-z1)*s(s1-t1)) +190 SEND_DERO_TO_ADDRESS(SIGNER(),z1) +200 SEND_ASSET_TO_ADDRESS(SIGNER(),t1,HEXDECODE(t)) +210 RETURN 0 +666 RETURN 1 +End Function +Function l1(o1 Uint64,z2 Uint64,a1 Uint64) Uint64 +30 DIM b2 AS Uint64 +40 LET b2 = o1*997 +50 IF q(z2*1000,o1*1000)==0 THEN GOTO 70 +60 PANIC +70 RETURN r(b2,a1,(z2*1000)+b2) +End Function +Function m1(b1 Uint64,z2 Uint64,a1 Uint64) Uint64 +30 RETURN r(z2*1000,b1,((a1-b1)*997)+1) +End Function +Function n1(c1 Uint64,y2 Uint64,t String) Uint64 +10 IF (c1>0)&&(y2>0) THEN GOTO 30 +20 RETURN 1 +30 DIM d1,s1,r1,x1 AS Uint64 +40 LET s1 = m(t) +50 LET r1 = k(t) +51 LET x1 = 18446744073709551 +52 IF ((r1>0)&&(s1>0))&&(c1<=x1) THEN GOTO 60 +53 RETURN 1 +60 LET d1 = l1(c1,r1,s1) +70 IF d1>=y2 THEN GOTO 90 +80 RETURN 1 +90 SEND_ASSET_TO_ADDRESS(SIGNER(),d1,HEXDECODE(t)) +100 l(s1-d1,t) +110 j(r1+c1,t) +120 RETURN 0 +End Function +Function DeroToAssetSwapInput(asset_address String) Uint64 +10 RETURN n1(DEROVALUE(),1,asset_address) +End Function +Function DeroToAssetSwapInputMin(min_assets Uint64,asset_address String) Uint64 +10 RETURN n1(DEROVALUE(),min_assets,asset_address) +End Function +Function d(d1 Uint64,e1 Uint64,t String) Uint64 +10 IF (d1>0)&&(e1>0) THEN GOTO 30 +20 RETURN 1 +30 DIM s1,r1,c1,c2 AS Uint64 +40 LET s1 = m(t) +41 LET r1 = k(t) +42 IF ((r1>0)&&(s1>0))&&(s1>d1) THEN GOTO 50 +43 RETURN 1 +50 LET c1 = m1(d1,r1,s1) +60 IF c1>e1 THEN GOTO 61 ELSE GOTO 70 +61 RETURN 1 +70 LET c2 = e1-c1 +80 IF c2==0 THEN GOTO 100 +90 SEND_DERO_TO_ADDRESS(SIGNER(),c2) +100 SEND_ASSET_TO_ADDRESS(SIGNER(),d1,HEXDECODE(t)) +110 l(s1-d1,t) +120 j(r1+c1,t) +130 RETURN 0 +End Function +Function DeroToAssetSwapOutput(assets_bought Uint64,asset_address String) Uint64 +10 RETURN d(assets_bought,DEROVALUE(),asset_address) +End Function +Function e(f1 Uint64,w Uint64,t String) Uint64 +10 IF (f1>0)&&(w>0) THEN GOTO 30 +20 RETURN 1 +30 DIM s1,r1,g1,x1 AS Uint64 +40 LET s1 = m(t) +41 LET r1 = k(t) +42 LET x1 = 18446744073709551 +43 IF ((s1>0)&&(r1>0))&&(f1<=x1) THEN GOTO 50 +44 RETURN 1 +50 LET g1 = l1(f1,s1,r1) +60 IF g1>=w THEN GOTO 80 +70 RETURN 1 +80 SEND_DERO_TO_ADDRESS(SIGNER(),g1) +90 j(r1-g1,t) +100 l(s1+f1,t) +110 RETURN 0 +End Function +Function AssetToDeroSwapInput(min_dero Uint64,asset_address String) Uint64 +10 RETURN e(ASSETVALUE(HEXDECODE(asset_address)),min_dero,asset_address) +End Function +Function f(g1 Uint64,h1 Uint64,t String) Uint64 +10 IF g1>0 THEN GOTO 30 +20 RETURN 1 +30 DIM s1,r1,f1,d2 AS Uint64 +40 LET s1 = m(t) +41 LET r1 = k(t) +42 IF ((s1>0)&&(r1>0))&&(r1>g1) THEN GOTO 50 +43 RETURN 1 +50 LET f1 = m1(g1,s1,r1)// assets_sold is always > zero +60 IF h1>=f1 THEN GOTO 80 +70 RETURN 1 +80 SEND_DERO_TO_ADDRESS(SIGNER(),g1) +90 LET d2 = h1-f1 +100 IF d2==0 THEN GOTO 120 +110 SEND_ASSET_TO_ADDRESS(SIGNER(),d2,HEXDECODE(t)) +120 j(r1-g1,t) +130 l(s1+f1,t) +140 RETURN 0 +End Function +Function AssetToDeroSwapOutput(dero_bought Uint64,asset_address String) Uint64 +10 RETURN f(dero_bought,ASSETVALUE(HEXDECODE(asset_address)),asset_address) +End Function +Function g(i1 Uint64,j1 Uint64,t String) Uint64 +10 DIM e2 AS String +11 DIM f2 AS Uint64 +20 LET e2 = LOAD("feeTo") +30 LET f2 = LOAD(t+":rootKLast") +40 IF f2!=0 THEN GOTO 50 +41 RETURN 0 +50 DIM g2 AS Uint64 +60 LET g2 = s(i1)*s(j1) +70 IF g2>f2 THEN GOTO 80 +71 RETURN 0 +80 DIM h2,u1 AS Uint64 +90 LET h2 = i(t) +100 LET u1 = r(h2,g2-f2,(g2*5)+f2) +110 IF u1>0 THEN GOTO 111 ELSE GOTO 120 +111 n(e2,u1,t) +112 h(h2+u1,t) +120 RETURN 0 +End Function +Function h(v Uint64,t String) Uint64 +10 STORE(t+":BOO",v) +20 RETURN 0 +End Function +Function i(t String) Uint64 +10 IF EXISTS(t+":BOO") THEN GOTO 30 +20 RETURN 0 +30 RETURN LOAD(t+":BOO") +End Function +Function j(v Uint64,t String) Uint64 +10 STORE(t+":DERO",v) +20 RETURN 0 +End Function +Function k(t String) Uint64 +10 RETURN LOAD(t+":DERO") +End Function +Function l(v Uint64,t String) Uint64 +10 STORE(t,v) +20 RETURN 0 +End Function +Function m(t String) Uint64 +20 RETURN LOAD(t) +End Function +Function n(k1 String,v Uint64,t String) Uint64 +10 IF EXISTS((ADDRESS_STRING(k1)+":BOO:")+t) THEN GOTO 40 +20 STORE((ADDRESS_STRING(k1)+":BOO:")+t,v) +30 RETURN 0 +40 STORE((ADDRESS_STRING(k1)+":BOO:")+t,p(k1,t)+v) +50 RETURN 0 +End Function +Function o(k1 String,v Uint64,t String) Uint64 +10 STORE((ADDRESS_STRING(k1)+":BOO:")+t,p(k1,t)-v) +20 RETURN 0 +End Function +Function p(k1 String,t String) Uint64 +10 RETURN LOAD((ADDRESS_STRING(k1)+":BOO:")+t) +End Function +Function q(l1 Uint64,m1 Uint64) Uint64 +10 IF l1>(18446744073709551615-m1) THEN GOTO 100 +20 RETURN 0 +100 RETURN 1 +End Function +Function r(l1 Uint64,m1 Uint64,n1 Uint64) Uint64 +10 DIM i2,j2 AS Uint64 +20 LET i2 = 4294967296 +30 LET j2 = ((i2-1)*i2)+(i2-1) +50 DIM k2 AS Uint64 +60 LET k2 = ((l1/n1)*m1)+((l1%n1)*(m1/n1)) +70 LET l1 = l1%n1 +80 LET m1 = m1%n1 +90 IF (l1==0)||(m1==0) THEN GOTO 1000 +100 IF n1>=i2 THEN GOTO 200 +110 LET k2 = k2+((l1*m1)/n1) +120 GOTO 1000 +200 DIM l2 AS Uint64 +210 LET l2 = j2/n1 +220 LET n1 = n1*l2 +230 LET l1 = l1*l2 +300 DIM m2,n2,o2,u3,q2,r2 AS Uint64 +310 LET m2 = l1/i2 +320 LET n2 = l1%i2 +330 LET o2 = m1/i2 +340 LET u3 = m1%i2 +350 LET q2 = n1/i2 +360 LET r2 = n1%i2 +400 DIM s2,t2,u2 AS Uint64 +410 LET s2 = n2*u3 +420 LET t2 = (s2/i2)+(n2*o2) +430 LET s2 = s2%i2 +440 LET u2 = (t2/i2)+(m2*o2) +450 LET t2 = (t2%i2)+(m2*u3) +460 LET u2 = u2+(t2/i2) +470 LET t2 = t2%i2 +500 DIM v2,w2,x2 AS Uint64 +510 LET u2 = u2%n1 +520 LET w2 = u2/q2 +530 LET x2 = u2%q2 +600 IF (w2=i2)||((w2*r2)<=((x2*i2)+t2))) THEN GOTO 700 +610 LET w2 = w2-1 +620 LET x2 = x2+q2 +630 GOTO 600 +700 LET t2 = (((u2%i2)*i2)+t2)-(w2*r2) +710 LET u2 = (((u2/i2)*i2)+(t2/i2))-(w2*q2) +720 LET t2 = (t2%i2)+((u2%i2)*i2) +730 LET v2 = t2/q2 +740 LET x2 = t2%q2 +800 IF (v2=i2)||((v2*r2)<=((x2*i2)+s2))) THEN GOTO 900 +810 LET v2 = v2-1 +820 LET x2 = x2+q2 +830 GOTO 800 +900 LET k2 = (k2+v2)+(w2*i2) +1000 RETURN k2 +End Function +Function s(o1 Uint64) Uint64 +10 IF o1>3 THEN GOTO 20 ELSE GOTO 90 +20 DIM y2,z2 AS Uint64 +30 LET z2 = o1 +40 LET y2 = (o1/2)+1 +50 IF y2AddLiquidity
- curl -X POST http://127.0.0.1:10103/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"bb8714fefca6187c914872ff138fcf4bf883d2ba81dfa73ea19265a2012f3cd0","ringsize":2,"sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"asset_address","datatype":"S","value":"ASSET_SCID_HERE"},{"name":"min_liquidity","datatype":"U","value":MIN_LIQUIDITY_HERE}],"transfers":[{"burn":"DERO_AMOUNT_HERE","destination":"RANDOM_DESTINATION_ADDRESS_HERE"},{"scid":"ASSET_SCID_HERE","burn":"ASSET_AMOUNT_HERE"}]}}' -H 'Content-Type: application/json' + curl -X POST http://127.0.0.1:10103/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"bb8714fefca6187c914872ff138fcf4bf883d2ba81dfa73ea19265a2012f3cd0","ringsize":2,"sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"ASSET_SCID_HERE"},{"name":"u","datatype":"U","value":MIN_LIQUIDITY_HERE}],"transfers":[{"burn":"DERO_AMOUNT_HERE","destination":"RANDOM_DESTINATION_ADDRESS_HERE"},{"scid":"ASSET_SCID_HERE","burn":"ASSET_AMOUNT_HERE"}]}}' -H 'Content-Type: application/json'
@@ -151,7 +151,7 @@

RemoveLiquidity

- curl -X POST http://127.0.0.1:10103/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"bb8714fefca6187c914872ff138fcf4bf883d2ba81dfa73ea19265a2012f3cd0","ringsize":2,"sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"amount","datatype":"U","value":AMOUNT_HERE},{"name":"min_dero","datatype":"U","value":MIN_DERO_HERE},{"name":"min_assets","datatype":"U","value":MIN_ASSETS_HERE},{"name":"asset_address","datatype":"S","value":"ASSET_SCID_HERE"}]}}' -H 'Content-Type: application/json' + curl -X POST http://127.0.0.1:10103/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"bb8714fefca6187c914872ff138fcf4bf883d2ba81dfa73ea19265a2012f3cd0","ringsize":2,"sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"v","datatype":"U","value":AMOUNT_HERE},{"name":"w","datatype":"U","value":MIN_DERO_HERE},{"name":"y2","datatype":"U","value":MIN_ASSETS_HERE},{"name":"t","datatype":"S","value":"ASSET_SCID_HERE"}]}}' -H 'Content-Type: application/json'

diff --git a/test_min.sh b/test_min.sh new file mode 100644 index 0000000..0ffb53b --- /dev/null +++ b/test_min.sh @@ -0,0 +1,167 @@ +#!/usr/bin/env bash + +#set -x # to enable debug and verbose printing of each and every command + +# the SC will trigger panic and but cannot return the funds to sender since ringsize > 2, instead deposits to SC + +CURDIR=`/bin/pwd` +BASEDIR=$(dirname $0) +ABSPATH=$(readlink -f $0) +ABSDIR=$(dirname $ABSPATH) + +command -v curl >/dev/null 2>&1 || { echo "I require curl but it's not installed. Aborting." >&2; exit 1; } +command -v jq >/dev/null 2>&1 || { echo "I require jq but it's not installed. Aborting." >&2; exit 1; } + +baseasset="0000000000000000000000000000000000000000000000000000000000000000" + +daemon_rpc_port="20000" # daemon rpc is listening on this port + +function balance(){ + curl --silent http://127.0.0.1:$1/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getbalance"}' -H 'Content-Type: application/json'| jq -r ".result.balance" +} + +function scassetbalance(){ + curl --silent http://127.0.0.1:$daemon_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getsc","params":{ "scid":"'"$1"'" , "code":false, "variables":true}}' -H 'Content-Type: application/json'| jq -r '.result.balances."'$2'"' +} + +function tokenbalance(){ + curl --silent http://127.0.0.1:$1/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getbalance" , "params":{ "scid":"'"$2"'" }}' -H 'Content-Type: application/json'| jq -r ".result.balance" +} + +owner_rpc_port="30000" +user1_rpc_port="30001" +user2_rpc_port="30002" + +owner_address=$(curl --silent http://127.0.0.1:$owner_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getaddress"}' -H 'Content-Type: application/json'| jq -r ".result.address") +user1_address=$(curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getaddress"}' -H 'Content-Type: application/json'| jq -r ".result.address") +user2_address=$(curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getaddress"}' -H 'Content-Type: application/json'| jq -r ".result.address") + +echo "owner address" $owner_address +echo "user1 address" $user1_address +echo "user2 address" $user2_address + +echo "Address 1 DERO balance" $(balance $user1_rpc_port ) +echo "Address 2 DERO balance" $(balance $user2_rpc_port ) + +# use owner wallet to load/install an Ghost sc to chain +ghostscid=$(curl --silent --request POST --data-binary @ghost_min.bas http://127.0.0.1:$owner_rpc_port/install_sc| jq -r ".txid") +echo "Ghost SCID" $ghostscid +sleep 2 + +asset1scid=$(curl --silent --request POST --data-binary @asset.bas http://127.0.0.1:$owner_rpc_port/install_sc| jq -r ".txid") +echo "asset1 SCID" $asset1scid +sleep 2 + + +asset2scid=$(curl --silent --request POST --data-binary @asset.bas http://127.0.0.1:$owner_rpc_port/install_sc| jq -r ".txid") +echo "asset2 SCID" $asset2scid +sleep 2 + +echo -n "user 1 minting 20000000000 asset1 " +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":100000,"scid":"'"$asset1scid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"IssueAsset"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 minting 20000000000 asset1 " +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":100000,"scid":"'"$asset1scid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"IssueAsset"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 creating trading pair for asset1 " +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"u","datatype":"U","value":1}], "transfers": [{"burn":1234,"destination":"'"$user2_address"'"},{"scid":"'"$asset1scid"'", "burn":1234}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 doubling liquidity for the asset1 pair" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"u","datatype":"U","value":1}], "transfers": [{"burn":1234,"destination":"'"$user2_address"'"},{"scid":"'"$asset1scid"'", "burn":5000}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 adding liquidity for the asset1 pair" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"u","datatype":"U","value":1}], "transfers": [{"burn":1234,"destination":"'"$user1_address"'"},{"scid":"'"$asset1scid"'", "burn":5000}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 removing all liquidity for the asset1 pair" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"v","datatype":"U","value":2468},{"name":"w","datatype":"U","value":1},{"name":"y2","datatype":"U","value":1}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 removing all liquidity for the asset1 pair" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"v","datatype":"U","value":1234},{"name":"w","datatype":"U","value":1},{"name":"y2","datatype":"U","value":1}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +printf "rebuilding liquidity for asset1" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"u","datatype":"U","value":1}], "transfers": [{"burn":10000,"destination":"'"$user2_address"'"},{"scid":"'"$asset1scid"'", "burn":10000}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"u","datatype":"U","value":1}], "transfers": [{"burn":1234,"destination":"'"$user1_address"'"},{"scid":"'"$asset1scid"'", "burn":5000}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 minting 20000000000 asset2 " +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":100000,"scid":"'"$asset2scid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"IssueAsset"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 minting 20000000000 asset2 " +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":100000,"scid":"'"$asset2scid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"IssueAsset"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "building liquidity for asset2"; +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"'"$asset2scid"'"},{"name":"u","datatype":"U","value":1}], "transfers": [{"burn":10000,"destination":"'"$user2_address"'"},{"scid":"'"$asset2scid"'", "burn":10000}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AddLiquidity"},{"name":"t","datatype":"S","value":"'"$asset2scid"'"},{"name":"u","datatype":"U","value":1}], "transfers": [{"burn":1234,"destination":"'"$user1_address"'"},{"scid":"'"$asset2scid"'", "burn":5000}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 swaps 1000 dero for asset2 " +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":1000,"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"DeroToAssetSwapInput"},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 swaps 5000 dero for asset2 " +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":5000,"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"DeroToAssetSwapInput"},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "Fails when user 1 swaps 1000 dero for asset2 and receives less than the min specified" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":1000,"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"DeroToAssetSwapInputMin"},{"name":"min_assets","datatype":"U","value":401},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 swaps 1000 dero for asset2 specifying min assets to receive" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":1000,"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"DeroToAssetSwapInputMin"},{"name":"min_assets","datatype":"U","value":400},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "Fails when user 1 buys 100 asset2 and pays more dero than the max specified" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":266,"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"DeroToAssetSwapOutput"},{"name":"assets_bought","datatype":"U","value":100},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 buys 100 asset2 specifying max dero to pay" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"sc_dero_deposit":267,"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"DeroToAssetSwapOutput"},{"name":"assets_bought","datatype":"U","value":100},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "Fails when user 2 sells 100 asset2 and receives less than the min specified" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AssetToDeroSwapInput"},{"name":"min_dero","datatype":"U","value":267},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}], "transfers": [{"scid":"'"$asset2scid"'", "burn":100}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 sells 100 asset2 specifying min dero to receive" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AssetToDeroSwapInput"},{"name":"min_dero","datatype":"U","value":266},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}], "transfers": [{"scid":"'"$asset2scid"'", "burn":100}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "fails when user 2 spends more than the max of asset2 specified for sell to receive a specific dero amount" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AssetToDeroSwapOutput"},{"name":"dero_bought","datatype":"U","value":100},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}], "transfers": [{"scid":"'"$asset2scid"'", "burn":37}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 specifies a max of asset2 to sell to receive a specific dero amount" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"AssetToDeroSwapOutput"},{"name":"dero_bought","datatype":"U","value":100},{"name":"asset_address","datatype":"S","value":"'"$asset2scid"'"}], "transfers": [{"scid":"'"$asset2scid"'", "burn":38}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 removing all liquidity for the asset1 pair" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"v","datatype":"U","value":10000},{"name":"w","datatype":"U","value":1},{"name":"y2","datatype":"U","value":1}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 1 removing all liquidity for the asset2 pair" +curl --silent http://127.0.0.1:$user1_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"t","datatype":"S","value":"'"$asset2scid"'"},{"name":"v","datatype":"U","value":10000},{"name":"w","datatype":"U","value":1},{"name":"y2","datatype":"U","value":1}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 removing all liquidity for the asset1 pair" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"t","datatype":"S","value":"'"$asset1scid"'"},{"name":"v","datatype":"U","value":1234},{"name":"w","datatype":"U","value":1},{"name":"y2","datatype":"U","value":1}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo -n "user 2 removing all liquidity for the asset1 pair" +curl --silent http://127.0.0.1:$user2_rpc_port/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"'"$ghostscid"'","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"RemoveLiquidity"},{"name":"t","datatype":"S","value":"'"$asset2scid"'"},{"name":"v","datatype":"U","value":1234},{"name":"w","datatype":"U","value":1},{"name":"y2","datatype":"U","value":1}] }}' -H 'Content-Type: application/json' | jq -r ".result.txid" +sleep 2 + +echo "SC DERO balance" $(scassetbalance $ghostscid $baseasset ) +echo "SC Asset1 balance" $(scassetbalance $ghostscid $asset1scid ) +echo "SC Asset2 balance" $(scassetbalance $ghostscid $asset2scid ) +exit 0 \ No newline at end of file