Skip to content

Commit 884ce48

Browse files
committed
More Torus tests and error checking
1 parent 22fd9d4 commit 884ce48

File tree

3 files changed

+69
-11
lines changed

3 files changed

+69
-11
lines changed

convex-core/src/main/cvx/torus/exchange.cvx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
[amount]
9797

9898
(let [amount (int amount)
99+
_ (cond (< amount 0) (fail :ARGUMENT "Cannot buy negative coin quantity"))
99100
required-tokens (or (buy-cvx-quote amount)
100101
(fail :LIQUIDITY "Pool cannot supply this amount of CVX"))]
101102
(asset/accept *caller*
@@ -115,7 +116,10 @@
115116
^{:callable true}
116117
[amount]
117118
;; Security: check pool can provide.
118-
(when-not (<= 0 amount *balance*) (return nil))
119+
(cond
120+
(< amount 0) (return nil)
121+
(>= amount *balance*) (return nil))
122+
119123
(let [;; Computes pool and fees/
120124
cvx-balance *balance*
121125
pool (* (double token-balance) cvx-balance)
@@ -128,14 +132,14 @@
128132
amount))
129133
token-balance))))))
130134

131-
132135
(defn buy-tokens
133136

134137
^{:callable true}
135138

136139
[amount]
137140

138141
(let [amount (int amount)
142+
_ (cond (< amount 0) (fail :ARGUMENT "Cannot buy negative token quantity"))
139143
required-cvx (or (buy-tokens-quote amount)
140144
(fail :LIQUIDITY "Pool cannot supply this amount of tokens"))]
141145
(core/accept required-cvx)
@@ -157,7 +161,9 @@
157161
[amount]
158162

159163
;; Security: check pool can provide.
160-
(when-not (<= 0 amount token-balance) (return nil))
164+
(cond
165+
(< amount 0) (return nil)
166+
(>= amount token-balance) (return nil))
161167

162168
(let [;; Computes pool and fees.
163169
cvx-balance *balance*
@@ -199,7 +205,7 @@
199205

200206
(let [amount (int amount)
201207
gained-tokens (or (sell-cvx-quote amount)
202-
(fail "Cannot sell this amount into pool"))]
208+
(fail :ARGUMENT "Cannot sell negative coin amount"))]
203209
(core/accept amount)
204210
(def token-balance
205211
(- token-balance
@@ -220,7 +226,8 @@
220226

221227
;; Security: check amount is positive.
222228
;;
223-
(when (<= amount 0) (return nil))
229+
(cond (< amount 0) (return nil))
230+
224231
(let [;; Computes pool and fees.
225232
cvx-balance *balance*
226233
pool (* (double token-balance)
@@ -244,7 +251,7 @@
244251

245252
(let [amount (int amount)
246253
gained-cvx (or (sell-tokens-quote amount)
247-
(fail "Cannot sell this amount into pool"))]
254+
(fail :ARGUMENT "Cannot sell this negative token amount"))]
248255
(asset/accept *caller*
249256
[token
250257
amount])
@@ -265,7 +272,7 @@
265272
[amount]
266273

267274
;; Security: check amount is positive.
268-
(when-not (<= 0 amount) (return nil))
275+
(cond (< amount 0) (return nil))
269276

270277
(let [;; Computes pool and fees.
271278
cvx-balance *balance*

convex-core/src/main/java/convex/core/ErrorCodes.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,5 +213,10 @@ public class ErrorCodes {
213213
*/
214214
public static final Keyword SYNTAX = Keyword.create("SYNTAX");
215215

216+
/**
217+
* Error code indicating insufficient liquidity in state for a Torus or other trade
218+
*/
219+
public static final Keyword LIQUIDITY = Keyword.create("LIQUIDITY");
220+
216221

217222
}

convex-core/src/test/java/convex/actors/TorusTest.java

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package convex.actors;
22

3-
import static convex.test.Assertions.assertCVMEquals;
4-
import static convex.test.Assertions.assertError;
3+
import static convex.test.Assertions.*;
54
import static org.junit.jupiter.api.Assertions.assertEquals;
65
import static org.junit.jupiter.api.Assertions.assertNotNull;
76
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -10,6 +9,7 @@
109

1110
import org.junit.jupiter.api.Test;
1211

12+
import convex.core.ErrorCodes;
1313
import convex.core.data.AVector;
1414
import convex.core.data.Address;
1515
import convex.core.data.prim.CVMDouble;
@@ -56,23 +56,69 @@ public class TorusTest extends ACVMTest {
5656
long STK=1000000;
5757
Context baseContext=context();
5858
baseContext=exec(baseContext,"(torus/add-liquidity USD "+STK+" "+STK+")");
59+
long USDBAL = evalL(baseContext,"(fun/balance USD)");
60+
assertEquals(USDBAL,SUPPLY-STK);
61+
5962
{ // Buy 100 USD
6063
Context ctx=baseContext;
6164
ctx=exec(ctx,"(torus/buy-tokens USD 100)");
6265
assertEquals(101L,RT.ensureLong(ctx.getResult()).longValue()); ;; // price should be 101
63-
assertEquals(1000000000-STK+100,evalL(ctx,"(fun/balance USD)")); // should have gained 100 USD
66+
assertEquals(USDBAL+100,evalL(ctx,"(fun/balance USD)")); // should have gained 100 USD
6467
assertEquals(STK,evalL(ctx,"(fun/balance USDM)")); // market shares unchanged
6568
assertTrue(evalB(ctx,"(< 1.0 (torus/price USD))")); // price has increased
6669
}
6770

71+
{ // Buy whole pool
72+
Context ctx=baseContext;
73+
ctx=step(ctx,"(torus/buy-tokens USD "+STK+")");
74+
assertEquals(ErrorCodes.LIQUIDITY,ctx.getErrorCode());
75+
}
76+
6877
{ // Buy 0 USD
6978
Context ctx=baseContext;
7079
ctx=exec(ctx,"(torus/buy-tokens USD 0)");
7180
assertEquals(0L,RT.ensureLong(ctx.getResult()).longValue()); ;; // price should be 0
72-
assertEquals(1000000000-STK,evalL(ctx,"(fun/balance USD)")); // should have gained 100 USD
81+
assertEquals(USDBAL,evalL(ctx,"(fun/balance USD)")); // no balance change
82+
assertEquals(STK,evalL(ctx,"(fun/balance USDM)")); // market shares unchanged
83+
assertTrue(evalB(ctx,"(= 1.0 (torus/price USD))")); // price should be unchanged
84+
}
85+
86+
{ // Buy -100 USD
87+
Context ctx=baseContext;
88+
ctx=step(ctx,"(torus/buy-tokens USD -100)");
89+
assertArgumentError(ctx);
90+
}
91+
92+
{ // Sell 100 USD
93+
Context ctx=baseContext;
94+
ctx=exec(ctx,"(torus/sell-tokens USD 100)");
95+
assertEquals(99L,RT.ensureLong(ctx.getResult()).longValue()); ;; // price should be 99
96+
assertEquals(USDBAL-100,evalL(ctx,"(fun/balance USD)")); // should have gained 100 USD
97+
assertEquals(STK,evalL(ctx,"(fun/balance USDM)")); // market shares unchanged
98+
assertTrue(evalB(ctx,"(> 1.0 (torus/price USD))")); // price has decreased
99+
}
100+
101+
{ // Sell whole USD holding
102+
Context ctx=baseContext;
103+
ctx=step(ctx,"(torus/sell-tokens USD (fun/balance USD))");
104+
assertEquals(0,evalL(ctx,"(fun/balance USD)")); // should have no USD left
105+
}
106+
107+
{ // Sell 0 USD
108+
Context ctx=baseContext;
109+
ctx=exec(ctx,"(torus/sell-tokens USD 0)");
110+
assertEquals(0L,RT.ensureLong(ctx.getResult()).longValue()); ;; // price should be 0
111+
assertEquals(USDBAL,evalL(ctx,"(fun/balance USD)")); // no balance change
73112
assertEquals(STK,evalL(ctx,"(fun/balance USDM)")); // market shares unchanged
74113
assertTrue(evalB(ctx,"(= 1.0 (torus/price USD))")); // price should be unchanged
75114
}
115+
116+
{ // Sell -100 USD
117+
Context ctx=baseContext;
118+
ctx=step(ctx,"(torus/sell-tokens USD -100)");
119+
assertArgumentError(ctx);
120+
}
121+
76122
}
77123

78124
@Test public void testMissingMarket() {

0 commit comments

Comments
 (0)