-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbase_contract-1.aes
116 lines (104 loc) · 4.78 KB
/
base_contract-1.aes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
* Aegora Base Contract
*
* Author: Craig Everett <[email protected]>
* Copyright: Tsuriai Corporation (2022)
* License: GPLv3
* Version: 1
*
* This is the base contract for the market.
* It is responsible for:
* - A library of valid contracts by type (sales offers, auctions, etc.)
* - Managing the authorized key list of market masters
* - Providing a single known endpoint to discover deployed, active contracts
* - Managing the lifecycle of a contract
*
* Lifecycle of a sales offer:
* 1. The seller calls AegoraBase.post_sale() to create his SalesOffer
* 2. Sale proceeds
* IF it is succesful, the contract calls AegoraBase.close()
* IF it is revoked by seller, the contract calls AegoraBase.close()
* IF it times out or is killed by the maester, one calls AegoraBase.kill()
*
* Calls to this contract can come from one of five sources:
* 1. The Maester (essentially the administrator)
* - init(template : SalesOffer // Posts the initial contract
* maester : address // with a reference to a template
* tsuriai : address)
* - update_template(contract : SalesOffer) // Update the template address
* - epstein(id : bool) // Force a contract to close
* 2. Sellers
* - post_sale(id : int, price : int) // Create a new sale contract clone
* 3. The Aegora site (or anyone really, but mainly useful for the site backend)
* - lookup(id) // Looks up a sale contract's address
* - template() // Looks up the current sales contract template
* 4. A sales contract
* - close(id : int) // A closing sale contract may call to remove itself from the active index
* 5. The Tsuriai master Key
* - update_maester(key : address) // Change the Maester key for operational reasons
*/
@compiler == 7.0.1
payable contract interface SalesOffer =
entrypoint init : (address, address, address, int, address, int, int) => void
payable entrypoint do_a_backflip : () => bool
contract AegoraBase =
record state =
{contracts : map(int, SalesOffer),
template : SalesOffer,
maester : address,
tsuriai : address}
stateful entrypoint init(template : SalesOffer,
maester : address,
tsuriai : address) : state =
{contracts = {},
template = template,
maester = maester,
tsuriai = tsuriai}
public entrypoint template() : SalesOffer =
state.template
public stateful entrypoint update_template(source : SalesOffer) : unit =
require(Call.caller == state.maester, "Nuh, uh uh! You didn't say the magic word!")
put(state{template = source})
public entrypoint lookup(id: int) : SalesOffer =
switch(Map.lookup(id, state.contracts))
Some(target) =>
target
None =>
abort("Bad ID!")
public stateful entrypoint post_sale(agent : address, portion : int, seller : address, id: int, price: int) : SalesOffer =
require(price > 0, "You cannot pay someone to buy things, Mr. Keynes.")
require(!Map.member(id, state.contracts), "People don't think it be like it is, but it do.")
switch(Chain.clone(ref = state.template,
protected = true,
state.tsuriai,
Contract.address,
agent,
portion,
seller,
id,
price))
Some(posted) =>
put(state{contracts = state.contracts{[id] = posted}})
posted
None =>
abort("Bad sale!")
public stateful entrypoint close(id: int) : bool =
switch(Map.lookup(id, state.contracts))
Some(target) =>
require(target.address == Call.caller, "Bad caller")
put(state{contracts = Map.delete(id, state.contracts)})
true
None =>
false
public stateful entrypoint update_maester(key: address) : unit =
require(Call.caller == state.tsuriai, "Nuh, uh uh! You didn't say the magic word!")
put(state{maester = key})
public stateful entrypoint epstein(id: int) : bool =
require(Call.caller == state.maester, "C'mon, man! You only got the husband and son!")
switch(Map.lookup(id, state.contracts))
Some(target) =>
put(state{contracts = Map.delete(id, state.contracts)})
target.do_a_backflip()
true
None =>
false