lib/order/teal/templates/ALGO_Delegate_v7.template.teal.js

  1. // ///////////////////////////
  2. // Alexander Trefonas //
  3. // 7/9/2021 //
  4. // Copyright Algodev Inc //
  5. // All Rights Reserved. //
  6. // ///////////////////////////
  7. /**
  8. * # Algodex Buy Orderbook Delegate
  9. *
  10. * > Escrow limit order to BUY ASAs. These limit orders contain only algos
  11. *
  12. * Stateful smart contract, TODO: Describe in detail with
  13. * {@link makeApplicationCreateTxn}
  14. *
  15. *
  16. * @type {string}
  17. * @memberOf module:teal
  18. */
  19. module.exports = `
  20. #pragma version 4
  21. //////////////////////////////////////////////////////////////////////////////
  22. // ALGO (NON-ASA) ESCROW (BUY ORDER) VERSION 4
  23. // Escrow limit order to BUY ASAs. These limit orders contain only algos.
  24. //////////////////////////////////////////////////////////////////////////////
  25. /////////////////////////////////
  26. // CHECKS THAT APPLY TO ALL TXNS
  27. ////////////////////////////////
  28. global GroupSize
  29. int 4
  30. <=
  31. assert
  32. txn Fee
  33. global MinTxnFee
  34. ==
  35. assert
  36. int 0
  37. store 9
  38. checkAllTxns: // This is basically a for loop that checks all transactions
  39. load 9
  40. gtxns RekeyTo
  41. global ZeroAddress
  42. ==
  43. assert
  44. load 9
  45. gtxns AssetCloseTo
  46. global ZeroAddress
  47. ==
  48. assert
  49. load 9
  50. gtxns AssetSender
  51. global ZeroAddress
  52. ==
  53. assert
  54. load 9
  55. int 1
  56. +
  57. store 9
  58. load 9
  59. global GroupSize
  60. <
  61. bnz checkAllTxns
  62. ///////////////////////////
  63. /// OPEN - ORDER BOOK OPT IN & REGISTRATION
  64. // Placing an Algo Escrow Order
  65. //////////////////////////
  66. // TXN 0 - BUYER TO ESCROW: Pay from order creator to escrow account
  67. // TXN 1 - ESCROW TO ORDERBOOK: Stateful app opt-in to order book
  68. // TXN 2 - BUYER TO BUYER: (Optional) ASA opt-in for the order creator's original wallet account.
  69. global GroupSize
  70. int 2
  71. ==
  72. global GroupSize
  73. int 3
  74. ==
  75. ||
  76. gtxn 0 TypeEnum
  77. int pay
  78. ==
  79. &&
  80. gtxn 1 TypeEnum
  81. int appl
  82. ==
  83. &&
  84. gtxn 0 Amount
  85. int 500000 // Must be funded with at least 0.5 algo.
  86. >=
  87. &&
  88. gtxn 1 Amount // amount sent from escrow for this txn should always be 0
  89. int 0
  90. ==
  91. &&
  92. gtxn 0 CloseRemainderTo
  93. global ZeroAddress
  94. ==
  95. &&
  96. gtxn 1 CloseRemainderTo
  97. global ZeroAddress
  98. ==
  99. &&
  100. gtxn 0 OnCompletion
  101. int NoOp //Check OnCompletion is OptIn or NoOp
  102. ==
  103. &&
  104. gtxn 1 OnCompletion
  105. int OptIn //Check OnCompletion is OptIn or NoOp
  106. ==
  107. &&
  108. gtxn 1 ApplicationID
  109. int <orderBookId> // stateful contract app id. orderBookId
  110. ==
  111. &&
  112. gtxn 0 Sender // must originate from buyer
  113. addr <contractWriterAddr> // contractWriterAddr (order creator)
  114. ==
  115. &&
  116. gtxn 1 Sender
  117. txn Sender // escrow account
  118. ==
  119. &&
  120. gtxn 0 Receiver // recipient of pay
  121. txn Sender // escrow account
  122. ==
  123. &&
  124. store 0
  125. global GroupSize // Third transaction is an optional asset opt-in
  126. int 2
  127. ==
  128. store 1
  129. load 1
  130. bnz notThreeTxns
  131. gtxn 2 TypeEnum// Third transaction.
  132. int axfer
  133. ==
  134. gtxn 2 AssetAmount
  135. int 0
  136. ==
  137. &&
  138. gtxn 2 Sender
  139. addr <contractWriterAddr> // contractWriterAddr (order creator)
  140. ==
  141. &&
  142. gtxn 2 Sender
  143. gtxn 2 AssetReceiver // required to be the same for ASA opt-in
  144. ==
  145. &&
  146. gtxn 2 OnCompletion
  147. int NoOp
  148. ==
  149. &&
  150. int <assetid> // asset id to trade for
  151. gtxn 2 XferAsset
  152. ==
  153. &&
  154. store 1
  155. notThreeTxns:
  156. load 0
  157. load 1 // Both should now be set to 1 if this is an open order transaction
  158. && // If either of the above are set to 0, this is *not* a place order transaction, so check other types
  159. bz notOptInOrOrderReg // Jump if either is 0
  160. int 1 // Otherwise it is a valid Opt-in so return early
  161. return
  162. ////////////////////////////////////////
  163. //// CLOSEOUT (ORDER CANCELLED) ////////
  164. ////////////////////////////////////////
  165. // TXN 0 - ESCROW TO ORDERBOOK: application call to order book contract for closeout
  166. // TXN 1 - ESCROW TO BUYER: pay txn close out call
  167. // TXN 2 - BUYER TO BUYER: send transaction for proof that closeout sender owns the escrow
  168. notOptInOrOrderReg:
  169. // Check for close out transaction (without execution)
  170. global GroupSize
  171. int 3
  172. ==
  173. gtxn 0 ApplicationID
  174. int <orderBookId> // stateful contract app id. orderBookId
  175. ==
  176. &&
  177. gtxn 0 CloseRemainderTo
  178. global ZeroAddress // This is an app call so should be set to 0 address
  179. ==
  180. &&
  181. gtxn 1 CloseRemainderTo
  182. addr <contractWriterAddr> // contractWriterAddr
  183. ==
  184. &&
  185. gtxn 2 CloseRemainderTo
  186. global ZeroAddress
  187. ==
  188. &&
  189. gtxn 0 Sender // first transaction must come from the escrow
  190. txn Sender
  191. ==
  192. &&
  193. gtxn 1 Sender // second transaction must come from the escrow
  194. txn Sender
  195. ==
  196. &&
  197. gtxn 2 Sender // proof the close is coming from sender
  198. addr <contractWriterAddr> // contractWriterAddr
  199. ==
  200. &&
  201. gtxn 0 TypeEnum
  202. int appl
  203. ==
  204. &&
  205. gtxn 1 TypeEnum
  206. int pay
  207. ==
  208. &&
  209. gtxn 2 TypeEnum
  210. int pay
  211. ==
  212. &&
  213. gtxn 0 Amount
  214. int 0 //Check all the funds are being sent to the CloseRemainderTo address
  215. ==
  216. &&
  217. gtxn 1 Amount
  218. int 0 //Check all the funds are being sent to the CloseRemainderTo address
  219. ==
  220. &&
  221. gtxn 2 Amount
  222. int 0 // This is just a proof so amount should be 0
  223. ==
  224. &&
  225. gtxn 0 OnCompletion
  226. int ClearState // App Call OnCompletion needs to be ClearState (OptOut), which will clear from the order book
  227. ==
  228. &&
  229. gtxn 1 OnCompletion
  230. int NoOp //pay transaction
  231. ==
  232. &&
  233. gtxn 2 OnCompletion
  234. int NoOp //proof pay transaction
  235. ==
  236. &&
  237. bz checkPayWithCloseout // If the above are not true, this is a pay transaction. Otherwise it is CloseOut so ret success
  238. int 1
  239. return
  240. ///////////////////////////////
  241. // EXECUTE (ORDER EXECUTION)
  242. // WITH CLOSEOUT
  243. /////////////////////////////////
  244. // TXN 0 - ESCROW TO ORDERBOOK: transaction must be a call to a stateful contract
  245. // TXN 1 - ESCROW TO SELLER: Payment transaction from this escrow to seller, with closeout to owner (buyer)
  246. // TXN 2 - SELLER TO BUYER: Asset transfer from seller to owner of this escrow (buyer)
  247. checkPayWithCloseout:
  248. gtxn 1 CloseRemainderTo
  249. global ZeroAddress
  250. ==
  251. bnz partialPayTxn // Jump to here if close remainder is a zero address. This is *not* a close-out
  252. // We should be here only if this is a full execution with closeout
  253. gtxn 0 OnCompletion // The application call must be
  254. int CloseOut // A general application call or a closeout
  255. ==
  256. global GroupSize // this delegate is only used on an execute order
  257. int 3
  258. ==
  259. &&
  260. gtxn 0 TypeEnum // The first transaction must be an Application Call (i.e. call stateful smart contract)
  261. int appl
  262. ==
  263. &&
  264. gtxn 1 TypeEnum // The second transaction must be a payment tx
  265. int pay
  266. ==
  267. &&
  268. gtxn 2 TypeEnum // The third transaction must be an asset xfer tx
  269. int axfer
  270. ==
  271. &&
  272. gtxn 0 ApplicationID // The specific Order Book App ID must be called
  273. int <orderBookId> // stateful contract app id. orderBookId
  274. ==
  275. &&
  276. gtxn 0 Sender
  277. txn Sender // escrow account
  278. ==
  279. &&
  280. gtxn 1 Sender
  281. txn Sender // escrow account
  282. ==
  283. &&
  284. gtxn 2 Sender
  285. txn Sender // escrow account
  286. != // should *not* be originating from escrow
  287. &&
  288. gtxn 1 Receiver // Receiver of the pay transaction from this escrow
  289. gtxn 2 Sender // Sender of the asset transfer (person trading)
  290. ==
  291. &&
  292. gtxn 2 AssetReceiver // Receiver of asset transfer
  293. addr <contractWriterAddr> // contractWriterAddr must receive the asset
  294. ==
  295. &&
  296. gtxn 0 CloseRemainderTo
  297. global ZeroAddress
  298. ==
  299. &&
  300. gtxn 1 CloseRemainderTo
  301. addr <contractWriterAddr> // contractWriterAddr
  302. ==
  303. &&
  304. gtxn 2 CloseRemainderTo
  305. global ZeroAddress
  306. ==
  307. &&
  308. gtxn 2 AssetCloseTo
  309. global ZeroAddress
  310. ==
  311. &&
  312. assert
  313. b handle_rate_check
  314. ///////////////////////////////////
  315. // EXECUTE
  316. // (PARTIAL ORDER EXECUTION)
  317. /////////////////////////////////
  318. // TXN 0 - ESCROW TO ORDERBOOK: Transaction must be a call to a stateful contract
  319. // TXN 1 - ESCROW TO SELLER: Payment transaction from this escrow to seller
  320. // TXN 2 - SELLER TO BUYER: Asset transfer from seller to owner of this escrow (buyer)
  321. // TXN 3 - SELLER TO ESCROW: Pay fee refund transaction
  322. partialPayTxn:
  323. global MinTxnFee
  324. global MinTxnFee
  325. +
  326. store 8 // store 2x minimum fee
  327. gtxn 0 OnCompletion // The application call must be a NoOp
  328. int NoOp
  329. ==
  330. txn CloseRemainderTo //all transactions from this escrow must not have closeouts
  331. global ZeroAddress
  332. ==
  333. &&
  334. global GroupSize // this delegate is only used on an execute order
  335. int 4
  336. ==
  337. &&
  338. gtxn 0 TypeEnum // The first transaction must be an ApplicationCall (ie call stateful smart contract)
  339. int appl
  340. ==
  341. &&
  342. gtxn 1 TypeEnum // The second transaction must be a payment tx
  343. int pay
  344. ==
  345. &&
  346. gtxn 2 TypeEnum // The third transaction must be an asset xfer tx
  347. int axfer
  348. ==
  349. &&
  350. gtxn 3 TypeEnum // The fourth transaction must be a payment tx for transaction fee reimbursement //FIXME check amount
  351. int pay
  352. ==
  353. &&
  354. gtxn 3 Amount // Refund amount must be 2x min amount
  355. load 8
  356. ==
  357. &&
  358. gtxn 3 Receiver // Fee refund recipient
  359. txn Sender // The escrow address
  360. ==
  361. &&
  362. gtxn 3 Sender // The fee sender must be the ASA seller
  363. gtxn 1 Receiver
  364. ==
  365. &&
  366. gtxn 0 Sender
  367. txn Sender // escrow account
  368. ==
  369. &&
  370. gtxn 1 Sender
  371. txn Sender // escrow account
  372. ==
  373. &&
  374. gtxn 2 Sender
  375. txn Sender // escrow account
  376. != // should *not* be originating from escrow
  377. &&
  378. gtxn 3 Sender
  379. txn Sender // escrow account
  380. != // should *not* be originating from escrow
  381. &&
  382. gtxn 0 ApplicationID // The specific App ID for the Algo escrow order book must be called
  383. int <orderBookId> //stateful contract app id orderBookId
  384. ==
  385. &&
  386. gtxn 1 Sender // Sender of the pay transaction must be this escrow
  387. txn Sender // Escrow address
  388. ==
  389. &&
  390. gtxn 1 Receiver // Receiver of the pay transaction from this escrow
  391. gtxn 2 Sender // Sender of the asset transfer (person trading)
  392. ==
  393. &&
  394. gtxn 2 AssetReceiver // Receiver of asset transfer
  395. addr <contractWriterAddr> // contractWriterAddr must receive the asset
  396. ==
  397. &&
  398. gtxn 0 CloseRemainderTo
  399. global ZeroAddress
  400. ==
  401. &&
  402. gtxn 1 CloseRemainderTo
  403. global ZeroAddress
  404. ==
  405. &&
  406. gtxn 2 CloseRemainderTo
  407. global ZeroAddress
  408. ==
  409. &&
  410. gtxn 3 CloseRemainderTo
  411. global ZeroAddress
  412. ==
  413. &&
  414. assert
  415. handle_rate_check:
  416. gtxn 1 Amount
  417. int 1 // must be at least one
  418. //int <min> NOTE** - leave this commented. We have intentionally disabled the custom min amount check
  419. >=
  420. gtxn 2 AssetAmount
  421. int 1 // must be at least one
  422. >=
  423. &&
  424. int <assetid> // asset id to trade for
  425. gtxn 2 XferAsset
  426. ==
  427. &&
  428. assert
  429. // handle the rate
  430. // BUY ORDER
  431. // gtxn[2].AssetAmount * D >= gtxn[1].Amount * N
  432. //
  433. // D/N is the price of the asset. For example, if D/N = 0.25, then with 5 microAlgos you can buy 20 of the ASA in base units
  434. //
  435. // N units of the asset per D microAlgos
  436. gtxn 2 AssetAmount
  437. int <D> // put D value here
  438. mulw // AssetAmount * D => (high 64 bits, low 64 bits)
  439. store 2 // move aside low 64 bits
  440. store 1 // move aside high 64 bits
  441. gtxn 1 Amount
  442. int <N> // put N value here
  443. mulw
  444. store 4 // move aside low 64 bits
  445. store 3 // move aside high 64 bits
  446. // compare high bits to high bits
  447. load 1
  448. load 3
  449. >
  450. bnz done2
  451. load 1
  452. load 3
  453. ==
  454. load 2
  455. load 4
  456. >=
  457. && // high bits are equal and low bits are ok
  458. bnz done2
  459. err
  460. done2:
  461. int 1
  462. return
  463. `;
  464. JAVASCRIPT
    Copied!