diff --git a/convex-core/src/main/cvx/convex/lab/distributor.cvx b/convex-core/src/main/cvx/convex/lab/distributor.cvx index 9bc3a93d9..ef3f59a06 100644 --- a/convex-core/src/main/cvx/convex/lab/distributor.cvx +++ b/convex-core/src/main/cvx/convex/lab/distributor.cvx @@ -15,26 +15,38 @@ ;; Set the amount of available coins. Only a trusted allocator can do this (defn ^:callable set-available [amount] - (when (> amount *balance*) - (fail :STATE "Insufficient balance")) + (if (not (trust/trusted? allocator *caller* :set-available amount)) + (fail :TRUST "Not authorised as allocator")) - (when-not (trust/trusted? allocator *caller* :set-available amount) - (fail :TRUST "Not authorised as allocator")) + (if (< amount 0) + (fail :ARGUMENT "Negative amount!")) - (set! available-coins amount)) + (set! available-coins (int amount))) -;; Distribute coins coins. Only a trusted distributor can do this +;; Distribute coins. Only a trusted distributor can do this (defn ^:callable distribute [receiver amount] - (cond - (not (int? amount)) - (fail :ARGUMENT "amount must be an integer") - (not (trust/trusted? distributor *caller* :distribute amount)) - (fail :TRUST "Not authorised to distribute") - (> amount available-coins) - (fail :FUNDS "Insufficient available coins") - (do - (set! available-coins (- available-coins amount)) - (transfer receiver amount)))) + (if (not (int? amount)) + (fail :ARGUMENT "amount must be an integer")) + + (if (not (trust/trusted? distributor *caller* :distribute amount)) + (fail :TRUST "Not authorised to distribute")) + + (if (> amount available-coins) + (fail :FUNDS "Insufficient available coins")) + + ;; Every check passed, so: + ;; 1. reduce available coins (Effect) + ;; 2. Make an external transfer (interaction) + (do + (set! available-coins (- available-coins amount)) + (transfer receiver amount))) (defn ^:callable receive-coin [_ _ _] - (accept *offer*)) \ No newline at end of file + (accept *offer*)) + +(defn ^:callable withdraw [amount] + (if (not (trust/trusted? allocator *caller* :withdraw amount)) + (fail :TRUST "Not authorised to withdraw")) + + ;; Transfer the withdrawn amount back to the caller + (transfer *caller* amount)) \ No newline at end of file diff --git a/convex-core/src/test/java/convex/actors/DistributorTest.java b/convex-core/src/test/java/convex/actors/DistributorTest.java index fd68c9322..1739e790c 100644 --- a/convex-core/src/test/java/convex/actors/DistributorTest.java +++ b/convex-core/src/test/java/convex/actors/DistributorTest.java @@ -41,13 +41,11 @@ public class DistributorTest extends ACVMTest { assertArgumentError(step(c,"(call DIST (distribute *address* nil))")); assertArgumentError(step(c,"(call DIST (distribute *address* -1))")); assertCastError(step(c,"(call DIST (distribute :foo 0))")); - - // initially no actor balance, so can't set available coins greater than 0 - assertStateError(step(c,"(call DIST (set-available 1))")); // zero distribution is OK c=exec(c,"(call DIST (distribute *address* 0))"); + assertTrustError(step(c,"(query-as #0 `(call ~DIST (set-available 1000)))")); } @Test public void testDistributuion() { @@ -70,4 +68,18 @@ public class DistributorTest extends ACVMTest { assertEquals(700000L,evalL(c,"DIST/available-coins")); } + + @Test public void testWithdraw() { + Context c=context(); + + // set available coins works after transferring in some coins + c=exec(c,"(transfer DIST 3000000)"); + assertEquals(3000000L,evalL(c,"(balance DIST)")); + + c=exec(c,"(call DIST (withdraw 1000000))"); + assertEquals(2000000L,evalL(c,"(balance DIST)")); + + // withdraw more than is left = :FUNDS error + assertFundsError(step(c,"(call DIST (withdraw 2000001))")); + } }