1+ /////////////////////////////
2+ // Alexander Trefonas //
3+ // 7/9/2021 //
4+ // Copyright Algodev Inc //
5+ // All Rights Reserved. //
6+ /////////////////////////////
7+
8+ const AsaOrderbookTeal = {
9+
10+ getClearProgram : function getClearProgram ( ) {
11+ const clearProgram =
12+ `
13+ #pragma version 2
14+ // This program clears program state.
15+ // This will clear local state for any escrow accounts that call this from a ClearState transaction,
16+ // the logic of which is contained within the stateless contracts as part of a Close Out (Cancel Order) operation.
17+ // We use ClearState instead of CloseOut so that the order book cannot prevent an escrow from closing out.
18+ int 1
19+ `
20+ ;
21+ return clearProgram ;
22+ } ,
23+
24+ getASAOrderBookApprovalProgram : function getASAOrderBookApprovalProgram ( ) {
25+ // stateful DEX contract
26+ // This is for the order book
27+ return `
28+ ////////////////////////////////////////////////
29+ // STATEFUL CONTRACT /
30+ // ORDER BOOK FOR ASA ESCROWS (SELL ORDERS) /
31+ ////////////////////////////////////////////////
32+ #pragma version 4
33+ // check if the app is being created
34+ // if so save creator
35+ int 0
36+ txn ApplicationID
37+ ==
38+ bz not_creation
39+ byte "Creator"
40+ txn Sender
41+ app_global_put
42+ int 1
43+ return
44+ not_creation:
45+ int DeleteApplication
46+ txn OnCompletion
47+ ==
48+ bz not_deletion
49+ byte "Creator" // verify creator is deleting app
50+ app_global_get
51+ txn Sender
52+ ==
53+ assert
54+ int 1
55+ return
56+
57+ not_deletion:
58+
59+ int UpdateApplication // check if this is update
60+ txn OnCompletion
61+ ==
62+ bz not_update
63+
64+ byte "Creator" // verify that the creator is making the call
65+ app_global_get
66+ txn Sender
67+ ==
68+ assert
69+ int 1
70+ return
71+ not_update:
72+ txna ApplicationArgs 0
73+ byte "open"
74+ ==
75+ bnz open
76+ txna ApplicationArgs 0
77+ byte "execute"
78+ ==
79+ bnz execute
80+ txna ApplicationArgs 0
81+ byte "execute_with_closeout"
82+ ==
83+ bnz execute_with_closeout
84+ err
85+ // function to check for ASA opt in transaction
86+ check_asa_optin:
87+ gtxn 2 TypeEnum
88+ int axfer
89+ ==
90+ gtxn 2 AssetAmount
91+ int 0
92+ ==
93+ &&
94+ gtxn 2 Sender
95+ gtxn 2 AssetReceiver
96+ ==
97+ &&
98+ gtxn 2 AssetCloseTo
99+ global ZeroAddress
100+ ==
101+ &&
102+ gtxn 2 Sender
103+ txn Sender // Sender must come from the user's wallet, not the escrow
104+ != // should *not* be originating from escrow
105+ &&
106+ store 0 //this will store the next transaction offset depending if opt in exists
107+ load 0
108+ int 2
109+ +
110+ store 2 // store offset of transaction 2, depending on if opt-in exists
111+ load 0
112+ int 3
113+ +
114+ store 3 // store offset of transaction 3, depending on if opt-in exists
115+ retsub
116+
117+ ///////////////////////////////////////////////////////////////////////
118+ // OPEN - ORDER BOOK OPT IN & REGISTRATION
119+ // Placing an ASA Escrow Order. The escrow opts into the order book.
120+ ///////////////////////////////////////////////////////////////////////
121+ // TXN 0 - SELLER TO ESCROW: pay transaction into escrow
122+ // TXN 1 - ESCROW TO ORDERBOOK: application opt in
123+ // TXN 2 - ESCROW TO ESCROW: asset opt in
124+ // TXN 3 - SELLER TO ESCROW: asset transfer
125+ open:
126+ int OptIn
127+ txn OnCompletion
128+ ==
129+ global GroupSize
130+ int 4
131+ ==
132+ &&
133+ assert
134+
135+ gtxn 0 Sender
136+ gtxn 3 Sender
137+ ==
138+ assert
139+ int 0 //address index. This is the Sender of this transaction.
140+ txn ApplicationID //current smart contract
141+ txna ApplicationArgs 1 // 2nd txn app arg is order number
142+ app_local_get_ex
143+ bnz ret_success // if the value already exists return without setting anything
144+ pop
145+ int 0 //address index. This is the Sender of this transaction.
146+ txna ApplicationArgs 1 //order number
147+ int 1 // value - just set to 1
148+ app_local_put // store the ordernumber as the key
149+ int 0 //address index. This is the Sender of this transaction.
150+ byte "creator" //creator key
151+ gtxn 0 Sender // store creator as value. This is the sender of the pay transaction
152+ app_local_put
153+ int 0 //address index. This is the Sender of this transaction.
154+ byte "version" //store version
155+ txna ApplicationArgs 2 //version
156+ int 0
157+ getbyte
158+ app_local_put // store the version
159+ ret_success:
160+ int 1
161+ return
162+ //////////////////////////////////////////////////////////////////////////////
163+ // EXECUTE (partial)
164+ // Partial execution of an ASA escrow, where an ASA balance remains in it
165+ //////////////////////////////////////////////////////////////////////////////
166+ // TXN 0 - ESCROW TO ORDERBOOK: Application call to execute
167+ // TXN 1 - BUYER TO SELLER: Pay transaction (from buyer/executor to escrow owner)
168+ // TXN 2 - BUYER TO BUYER: (Optional) asset opt-in transaction (for buyer/executor)
169+ // TXN 2/3 - ESCROW TO BUYER: Asset transfer (from escrow to buyer/executor)
170+ // TXN 3/4 - BUYER TO ESCROW: Pay transaction for fee refund (from buyer/executor to escrow)
171+ execute:
172+ txn OnCompletion //FIXME check OnCompletion of each individual transaction
173+ int CloseOut
174+ ==
175+ txn OnCompletion
176+ int NoOp
177+ ==
178+ ||
179+ assert
180+
181+ callsub check_asa_optin // this will store transaction offsets into registers if the asa opt-in exists or not
182+ txn Sender
183+ int 0 // foreign asset id 0
184+ asset_holding_get AssetBalance // pushes 1 for success, then asset onto stack
185+ assert //make sure asset exists
186+ load 2
187+ gtxns AssetAmount
188+ > // The asset balance should be greater than or equal to the amount transferred. Otherwise should be with closeout
189+ assert
190+ global GroupSize
191+ int 4
192+ ==
193+ global GroupSize //group size can be 5 for asset opt-in
194+ int 5
195+ ==
196+ ||
197+ assert
198+ gtxn 0 TypeEnum // First Transaction must be a call to a stateful contract
199+ int appl
200+ ==
201+ gtxn 1 TypeEnum // The second transaction must be a payment transaction
202+ int pay
203+ ==
204+ &&
205+ assert
206+
207+ load 2
208+ gtxns TypeEnum //The next transaction must be an asset transfer
209+ int axfer
210+ ==
211+ assert
212+ load 3
213+ gtxns TypeEnum
214+ int pay
215+ ==
216+ assert
217+ int 0 // Escrow account containing order. This is the Sender of this transaction.
218+ txn ApplicationID // Current stateful smart contract
219+ txna ApplicationArgs 1 // 2nd argument is order number
220+ app_local_get_ex
221+ assert // If the value doesnt exists fail
222+ pop
223+ int 0 // Escrow account containing order. This is the Sender of this transaction.
224+ txn ApplicationID // Current stateful smart contract
225+ byte "creator"
226+ app_local_get_ex // returns if it exists and the creator
227+ assert // If the value doesnt exist fail
228+ txna Accounts 1 // account arg is order creator
229+ ==
230+ assert
231+ global ZeroAddress
232+ gtxn 1 CloseRemainderTo
233+ ==
234+ assert
235+ int 1
236+ return
237+ /////////////////////////////////////////////////////////////////////////////////////////////////
238+ // EXECUTE WITH CLOSE
239+ // Full order execution where the remaining minimum algo balance is closed to the escrow owner
240+ /////////////////////////////////////////////////////////////////////////////////////////////////
241+ // TXN 0 - ESCROW TO ORDERBOOK: Application call to execute
242+ // TXN 1 - BUYER TO SELLER: Pay transaction (from buyer/executor to escrow owner)
243+ // TXN 2 - BUYER TO BUYER: (Optional) asset opt-in transaction (for buyer/executor)
244+ // TXN 2/3 - ESCROW TO BUYER: Asset transfer (from escrow to buyer/executor)
245+ // - closes out any remaining ASA to seller (escrow owner) as well
246+ // TXN 3/4 - ESCROW TO SELLER: Pay transaction to close out to escrow owner
247+ execute_with_closeout:
248+ txn OnCompletion
249+ int CloseOut
250+ ==
251+ bz fail2
252+ callsub check_asa_optin // this will store transaction offsets into registers if the asa opt-in exists or not
253+ txn Sender
254+ int 0 // foreign asset id 0
255+ asset_holding_get AssetBalance // pushes 1 for success, then asset onto stack
256+ assert //make sure asset exists
257+ load 2
258+ gtxns AssetAmount
259+ == // Check we are going to transfer the entire ASA amount to the buyer. Otherwise should be a partial execute
260+ assert
261+ global GroupSize
262+ int 4
263+ ==
264+ global GroupSize //group size can be 5 for asset opt-in
265+ int 5
266+ ==
267+ ||
268+ assert
269+ gtxn 0 TypeEnum // First Transaction must be a call to a stateful contract
270+ int appl
271+ ==
272+ gtxn 1 TypeEnum // The second transaction must be a payment transaction
273+ int pay
274+ ==
275+ &&
276+ assert
277+ load 2
278+ gtxns TypeEnum //The next transaction must be an asset transfer
279+ int axfer
280+ ==
281+ assert
282+ load 3 // The last transaction must be a payment transfer
283+ gtxns TypeEnum
284+ int pay
285+ ==
286+ assert
287+ int 0 // Escrow account containing order. This is the Sender of this transaction.
288+ txn ApplicationID // Current stateful smart contract
289+ txna ApplicationArgs 1 // 2nd argument is order number
290+ app_local_get_ex
291+ bz fail2 // If the value doesnt exist fail
292+ pop
293+ int 0 // Escrow account containing order. This is the Sender of this transaction.
294+ txn ApplicationID // Current stateful smart contract
295+ byte "creator"
296+ app_local_get_ex // returns if it exists and the creator
297+ assert // If the value doesnt exist fail
298+ txna Accounts 1 // account arg is order creator
299+ ==
300+ assert
301+ int 0 // Escrow account containing order. This is the Sender of this transaction.
302+ txn ApplicationID // Current stateful smart contract
303+ byte "version"
304+ app_local_get_ex
305+ assert // If the value doesnt exists fail
306+ pop
307+ global ZeroAddress
308+ gtxn 1 CloseRemainderTo
309+ ==
310+ bnz ret_success3
311+ int 0 //escrow account containing order. This is the Sender of this transaction.
312+ txna ApplicationArgs 1 // order details
313+ app_local_del // Delete the ordernumber
314+ int 0 // escrow account containing order
315+ byte "creator"
316+ app_local_del // Delete the creator
317+ int 0 // escrow account containing order
318+ byte "version" // Delete the version
319+ app_local_del
320+ ret_success3:
321+ int 1
322+ return
323+ fail2:
324+ int 0
325+ return
326+
327+
328+
329+ ` ;
330+
331+ }
332+ } ;
333+
334+ module . exports = AsaOrderbookTeal ;
0 commit comments