Skip to content

Commit

Permalink
Add a time-based operation and a view to auction and the corresponding
Browse files Browse the repository at this point in the history
tests.
  • Loading branch information
aguillon committed Jul 25, 2023
1 parent 86ed556 commit bb6991e
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 23 deletions.
55 changes: 47 additions & 8 deletions examples/auction/src/auction_sc.mligo
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,63 @@
SOFTWARE. *)

type current_leader = {
current_leader_address: address
; current_leader_amount: tez
current_leader_address: address;
current_leader_amount: tez;
start_time: timestamp
}

type storage = current_leader option

let bid (storage: storage) (quantity: tez) (user_address: address) : storage =
if quantity <= 0tez then failwith "Amount cannot be null"
let bid (storage: storage) (quantity: tez) (user_address: address) (time: timestamp) : storage =
if quantity = 0tez then failwith "Amount cannot be null"
else match storage with
| None -> Some { current_leader_address = user_address; current_leader_amount = quantity }
| Some { current_leader_address; current_leader_amount } ->
| None ->
Some {
current_leader_address = user_address;
current_leader_amount = quantity;
start_time = time
}
| Some { current_leader_address; current_leader_amount; start_time } ->
let () = if current_leader_address = user_address then failwith "Same leader" in
let () = if current_leader_amount >= quantity then failwith "Amount should be greater" in
Some { current_leader_address = user_address; current_leader_amount = quantity }
Some {
current_leader_address = user_address;
current_leader_amount = quantity;
start_time = start_time
}

let claim (storage: storage) (user_address: address) (time: timestamp) : operation * storage =
let one_day = 86_400 in
let current_leader = Option.unopt_with_error storage "No bid received" in
let () = if current_leader.start_time + one_day >= time then
failwith "Auction is not complete"
in
let () = if current_leader.current_leader_address <> user_address then
failwith "Not the leader"
in
(* We don't have any asset to send to the winning bidder, so we just emit an
event instead. *)
let op = Tezos.emit "%claim" user_address in
let new_storage = None in
(op, new_storage)

[@entry]
let bid (_, storage: unit * storage) : operation list * storage =
let quantity = Tezos.get_amount () in
let user_address = Tezos.get_sender () in
([], bid storage quantity user_address)
let current_time = Tezos.get_now () in
([], bid storage quantity user_address current_time)

[@entry]
let claim (_, storage: unit * storage) : operation list * storage =
let user_address = Tezos.get_sender () in
let current_time = Tezos.get_now () in
let operation, storage = claim storage user_address current_time in
([operation], storage)

[@view]
let is_claimable (_, storage: unit * storage) : bool =
match storage with
| None -> false
| Some current_leader ->
current_leader.start_time + 86_400 < Tezos.get_now ()
69 changes: 58 additions & 11 deletions examples/auction/test/test_auction_sc.mligo
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#import "../../../lib/lib.mligo" "Breath"
#import "util.mligo" "Util"

let case_happy_path =
let bid_happy_path =
Breath.Model.case
"bid"
"when everything is ok, it should upgrade the leader"
Expand All @@ -34,6 +34,7 @@ let case_happy_path =
let contract = Util.originate level in

let alice_action = Breath.Context.act_as alice (Util.bid contract 1tez) in
let start_time = Tezos.get_now () in
let bob_action = Breath.Context.act_as bob (Util.bid contract 2tez) in
let carol_action = Breath.Context.act_as carol (Util.bid contract 3tez) in

Expand All @@ -45,10 +46,10 @@ let case_happy_path =
; bob_action
; carol_action
; Breath.Assert.is_equal "balance" balance 6tez
; Util.expect_storage storage carol 3tez
; Util.expect_storage storage carol start_time 3tez
])

let case_leader_try_to_be_upgraded_twice =
let bid_leader_try_to_be_upgraded_twice =
Breath.Model.case
"bid"
"when the leader try to reupgrade the storage it should raise an error"
Expand All @@ -57,6 +58,7 @@ let case_leader_try_to_be_upgraded_twice =
let contract = Util.originate level in

let alice_fst_action = Breath.Context.act_as alice (Util.bid contract 1tez) in
let start_time = Tezos.get_now () in
let alice_snd_action = Breath.Context.act_as alice (Util.bid contract 2tez) in

let storage = Breath.Contract.storage_of contract in
Expand All @@ -66,10 +68,10 @@ let case_leader_try_to_be_upgraded_twice =
alice_fst_action
; Breath.Expect.fail_with_message "Same leader" alice_snd_action
; Breath.Assert.is_equal "balance" balance 1tez
; Util.expect_storage storage alice 1tez
; Util.expect_storage storage alice start_time 1tez
])

let case_try_to_upgrade_with_a_lower_amount =
let bid_try_to_upgrade_with_a_lower_amount =
Breath.Model.case
"bid"
"when a challenger try to upgrade the storage with a lower amount it should raise an error"
Expand All @@ -78,6 +80,7 @@ let case_try_to_upgrade_with_a_lower_amount =
let contract = Util.originate level in

let alice_action = Breath.Context.act_as alice (Util.bid contract 2tez) in
let start_time = Tezos.get_now () in
let bob_action = Breath.Context.act_as bob (Util.bid contract 1tez) in

let storage = Breath.Contract.storage_of contract in
Expand All @@ -87,10 +90,10 @@ let case_try_to_upgrade_with_a_lower_amount =
alice_action
; Breath.Expect.fail_with_message "Amount should be greater" bob_action
; Breath.Assert.is_equal "balance" balance 2tez
; Util.expect_storage storage alice 2tez
; Util.expect_storage storage alice start_time 2tez
])

let case_try_to_upgrade_with_a_null_amount =
let bid_try_to_upgrade_with_a_null_amount =
Breath.Model.case
"bid"
"when a challenger try to upgrade the storage without tez, it should raise an error"
Expand All @@ -108,13 +111,57 @@ let case_try_to_upgrade_with_a_null_amount =
; Breath.Assert.is_none "The storage should be empty" storage
])

let claim_leader_can_claim =
Breath.Model.case
"claim"
"the leader of the auction can call claim one day after the start"
(fun (level: Breath.Logger.level) ->
let (_, (alice, bob, _)) = Breath.Context.init_default () in
let contract = Util.originate level in

let alice_bid = Breath.Context.act_as alice (Util.bid contract 1tez) in
let bob_bid = Breath.Context.act_as bob (Util.bid contract 2tez) in

Breath.Result.reduce [
alice_bid
; bob_bid
; Breath.Assert.is_equal
"should not claimable before waiting"
(Tezos.call_view "is_claimable" () contract.originated_address)
(Some false)
; Breath.Context.wait_for 86_400n
(* Notice how we have to call the contract after waiting, unlike
* what we did for the two calls to Bid. *)
; Breath.Assert.is_equal
"should be claimable after waiting"
(Tezos.call_view "is_claimable" () contract.originated_address)
(Some true)
; Breath.Context.call_as bob contract Claim
])


let claim_try_when_empty =
Breath.Model.case
"claim"
"when someone tries to claim an empty auction, it should fail"
(fun (level: Breath.Logger.level) ->
let (_, (alice, _, _)) = Breath.Context.init_default () in
let contract = Util.originate level in

let alice_action = Breath.Context.call_as alice contract Claim in

Breath.Result.reduce [
Breath.Expect.fail_with_message "No bid received" alice_action
])

let () =
Breath.Model.run_suites Trace [
Breath.Model.suite "Suite for [auction_sc]" [
case_happy_path
; case_leader_try_to_be_upgraded_twice
; case_try_to_upgrade_with_a_lower_amount
; case_try_to_upgrade_with_a_null_amount
bid_happy_path
; bid_leader_try_to_be_upgraded_twice
; bid_try_to_upgrade_with_a_lower_amount
; bid_try_to_upgrade_with_a_null_amount
; claim_leader_can_claim
; claim_try_when_empty
]
]
12 changes: 8 additions & 4 deletions examples/auction/test/util.mligo
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,17 @@ let bid (contract : (Auction parameter_of, Auction.storage) originated) (qty: te
let expect_storage
(storage : Auction.storage)
(actor: Breath.Context.actor)
(time: timestamp)
(expected_amount: tez) : Breath.Result.result =
Breath.Assert.is_some_and
"The storage should be filled"
(fun ({ current_leader_address; current_leader_amount} : Auction.current_leader) ->
(fun ({ current_leader_address; current_leader_amount; start_time } : Auction.current_leader) ->
let expected_leader =
Breath.Assert.is_equal "leader" current_leader_address actor.address in
Breath.Assert.is_equal "leader" current_leader_address actor.address in
let expected_amount =
Breath.Assert.is_equal "amount" current_leader_amount expected_amount in
Breath.Result.and_then expected_leader expected_amount)
Breath.Assert.is_equal "amount" current_leader_amount expected_amount in
let expected_start_time =
Breath.Assert.is_equal "start_time" start_time time in
Breath.Result.and_then expected_start_time
(Breath.Result.and_then expected_leader expected_amount))
storage

0 comments on commit bb6991e

Please sign in to comment.