lib/order/teal/templates/ASA_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 Sell Orderbook Delegate
  9. *
  10. * > Escrow limit order to SELL ASAs. These limit orders contain a minimum algo balance and then the ASA to sell.
  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. // ASA ESCROW (SELL ORDER) VERSION 4
  23. // Escrow limit order to SELL ASAs. These limit orders contain a minimum algo balance and then the ASA to sell.
  24. //////////////////////////////////////
  25. /////////////////////////////////
  26. // CHECKS THAT APPLY TO ALL TXNS
  27. ////////////////////////////////
  28. global GroupSize
  29. int 5
  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 AssetSender
  46. global ZeroAddress
  47. ==
  48. assert
  49. load 9
  50. int 1
  51. +
  52. store 9
  53. load 9
  54. global GroupSize
  55. <
  56. bnz checkAllTxns
  57. ///////////////////////////////////////////////////////////////////////
  58. // OPEN - ORDER BOOK OPT IN & REGISTRATION
  59. // Placing an ASA Escrow Order. The escrow opts into the order book.
  60. ///////////////////////////////////////////////////////////////////////
  61. // TXN 0 - SELLER TO ESCROW: pay transaction into escrow
  62. // TXN 1 - ESCROW TO ORDERBOOK: application opt in
  63. // TXN 2 - ESCROW TO ESCROW: asset opt in
  64. // TXN 3 - SELLER TO ESCROW: asset transfer
  65. global GroupSize
  66. int 4
  67. ==
  68. gtxn 1 ApplicationID
  69. int <orderBookId> //stateful contract app id. orderBookId
  70. ==
  71. &&
  72. gtxn 0 Sender // escrow address
  73. addr <contractWriterAddr> // contractWriterAddr
  74. ==
  75. &&
  76. gtxn 0 Receiver
  77. txn Sender // escrow address
  78. ==
  79. &&
  80. gtxn 1 Sender
  81. txn Sender // escrow address
  82. ==
  83. &&
  84. gtxn 2 Sender
  85. txn Sender // escrow address
  86. ==
  87. &&
  88. gtxn 2 Sender
  89. gtxn 2 AssetReceiver
  90. ==
  91. &&
  92. txn Sender // escrow address
  93. gtxn 3 AssetReceiver
  94. ==
  95. &&
  96. gtxn 3 Sender // escrow address
  97. addr <contractWriterAddr> // contractWriterAddr
  98. ==
  99. &&
  100. gtxn 0 TypeEnum
  101. int pay
  102. ==
  103. &&
  104. gtxn 1 TypeEnum
  105. int appl
  106. ==
  107. &&
  108. gtxn 2 TypeEnum
  109. int axfer
  110. ==
  111. &&
  112. gtxn 3 TypeEnum
  113. int axfer
  114. ==
  115. &&
  116. gtxn 0 Amount // amount should be higher than 0.5 algo
  117. int 500000
  118. >=
  119. &&
  120. gtxn 1 Amount
  121. int 0
  122. ==
  123. &&
  124. gtxn 2 AssetAmount // this is an optin
  125. int 0
  126. ==
  127. &&
  128. gtxn 3 AssetAmount // this is an optin
  129. int 1 // Needs to put at least one ASA into the account
  130. >=
  131. &&
  132. int <assetid> // asset id to trade for
  133. gtxn 2 XferAsset
  134. ==
  135. &&
  136. int <assetid> // asset id to trade for
  137. gtxn 3 XferAsset
  138. ==
  139. &&
  140. gtxn 0 CloseRemainderTo
  141. global ZeroAddress
  142. ==
  143. &&
  144. gtxn 1 CloseRemainderTo
  145. global ZeroAddress
  146. ==
  147. &&
  148. gtxn 2 CloseRemainderTo
  149. global ZeroAddress
  150. ==
  151. &&
  152. gtxn 3 CloseRemainderTo
  153. global ZeroAddress
  154. ==
  155. &&
  156. gtxn 0 OnCompletion
  157. int NoOp
  158. ==
  159. &&
  160. gtxn 1 OnCompletion
  161. int OptIn
  162. ==
  163. &&
  164. gtxn 2 OnCompletion
  165. int NoOp
  166. ==
  167. &&
  168. gtxn 3 OnCompletion
  169. int NoOp
  170. ==
  171. &&
  172. gtxn 0 AssetCloseTo
  173. global ZeroAddress
  174. ==
  175. &&
  176. gtxn 1 AssetCloseTo
  177. global ZeroAddress
  178. ==
  179. &&
  180. gtxn 2 AssetCloseTo
  181. global ZeroAddress
  182. ==
  183. &&
  184. gtxn 3 AssetCloseTo
  185. global ZeroAddress
  186. ==
  187. &&
  188. bz notOptInOrOrderReg
  189. // If the above are not true, this is a closeout (without order execution) or a trade execution
  190. // Otherwise it is Opt-in so return early
  191. int 1
  192. return
  193. ////////////////////////////////////////////////////////
  194. /// CLOSE ORDER
  195. // Cancelling an order and refunding the amounts
  196. ////////////////////////////////////////////////////////
  197. // TXN 0 - ESCROW TO ORDERBOOK: app call to close order
  198. // TXN 1 - ESCROW TO SELLER: asset transfer (escrow to owner)
  199. // TXN 2 - ESCROW TO SELLER: pay transaction (from escrow to owner)
  200. // TXN 3 - SELLER TO SELLER: proof of ownership pay transaction (owner to owner)
  201. notOptInOrOrderReg:
  202. // Check for close out transaction (without execution)
  203. global GroupSize
  204. int 4
  205. ==
  206. gtxn 0 ApplicationID
  207. int <orderBookId> //stateful contract app id. orderBookId
  208. ==
  209. &&
  210. gtxn 0 CloseRemainderTo
  211. global ZeroAddress // This is an app call so should be set to 0 address
  212. ==
  213. &&
  214. gtxn 0 AssetCloseTo
  215. global ZeroAddress // should not matter, but add just in case
  216. ==
  217. &&
  218. gtxn 1 CloseRemainderTo
  219. global ZeroAddress // should not matter, but add just in case. We are closing ASAs not algos
  220. ==
  221. &&
  222. gtxn 1 AssetCloseTo // asset close transaction
  223. addr <contractWriterAddr> // contractWriterAddr
  224. ==
  225. &&
  226. gtxn 2 CloseRemainderTo // close algo minimum balance transaction
  227. addr <contractWriterAddr> // contractWriterAddr
  228. ==
  229. &&
  230. gtxn 2 AssetCloseTo // should not matter. Third transaction is for closing algos
  231. global ZeroAddress // contractWriterAddr
  232. ==
  233. &&
  234. gtxn 3 CloseRemainderTo // should not matter. Fourth transaction is a proof of ownership
  235. global ZeroAddress
  236. ==
  237. &&
  238. gtxn 3 AssetCloseTo // should not matter. Fourth transaction is a proof of ownership
  239. global ZeroAddress
  240. ==
  241. &&
  242. gtxn 0 Sender
  243. txn Sender // escrow address
  244. ==
  245. &&
  246. gtxn 1 Sender
  247. txn Sender // escrow address
  248. ==
  249. &&
  250. gtxn 2 Sender
  251. txn Sender // escrow address
  252. ==
  253. &&
  254. gtxn 3 Sender // proof the close is coming from sender
  255. addr <contractWriterAddr> // contractWriterAddr
  256. ==
  257. &&
  258. gtxn 0 Receiver
  259. global ZeroAddress // This is an app call, so no receiver
  260. ==
  261. &&
  262. gtxn 1 AssetReceiver
  263. addr <contractWriterAddr> // contractWriterAddr
  264. ==
  265. &&
  266. gtxn 2 Receiver // 0 funds are being transferred, but still expected to be set
  267. addr <contractWriterAddr> // contractWriterAddr
  268. ==
  269. &&
  270. gtxn 3 Receiver // 0 funds are being transferred, but still expected to be set
  271. addr <contractWriterAddr> // contractWriterAddr
  272. ==
  273. &&
  274. gtxn 0 TypeEnum
  275. int appl
  276. ==
  277. &&
  278. gtxn 1 TypeEnum
  279. int axfer
  280. ==
  281. &&
  282. gtxn 2 TypeEnum
  283. int pay
  284. ==
  285. &&
  286. gtxn 3 TypeEnum
  287. int pay
  288. ==
  289. &&
  290. gtxn 0 Amount // Should not matter since this is an app call
  291. int 0 //Check all the funds are being sent to the CloseRemainderTo address
  292. ==
  293. &&
  294. gtxn 1 Amount
  295. int 0 // Should not matter since this is an ASA transfer
  296. ==
  297. &&
  298. gtxn 1 AssetAmount
  299. int 0 //Check all the funds are being sent to the CloseRemainderTo address
  300. ==
  301. &&
  302. gtxn 2 Amount
  303. int 0 //Check all the funds are being sent to the CloseRemainderTo address
  304. ==
  305. &&
  306. gtxn 2 AssetAmount
  307. int 0 //Should not matter since this is a pay transaction
  308. ==
  309. &&
  310. gtxn 3 Amount
  311. int 0 //This is a proof of ownership so the amount should be 0
  312. ==
  313. &&
  314. gtxn 3 AssetAmount
  315. int 0 //Should not matter since this is a pay transaction
  316. ==
  317. &&
  318. gtxn 0 OnCompletion
  319. int ClearState // App Call OnCompletion needs to be ClearState (OptOut), which will clear from the order book
  320. ==
  321. &&
  322. gtxn 1 OnCompletion
  323. int NoOp
  324. ==
  325. &&
  326. gtxn 2 OnCompletion
  327. int NoOp
  328. ==
  329. &&
  330. gtxn 3 OnCompletion
  331. int NoOp
  332. ==
  333. &&
  334. bz anyExecute // If the above are not true, this is a pay transaction. Otherwise it is CloseOut so ret success
  335. int 1
  336. return
  337. ///////////////////////////////////////////////////////
  338. // ANY EXECUTE (with close or not)
  339. // Preamble for any order execution transaction
  340. ///////////////////////////////////////////////////////
  341. // TXN 0 - ESCROW TO ORDERBOOK: Application call to execute
  342. // TXN 1 - BUYER TO SELLER: Pay transaction (from buyer/executor to escrow owner)
  343. // TXN 2 - BUYER TO BUYER: (Optional) asset opt-in transaction (for buyer/executor)
  344. // TXN 2/3 - ESCROW TO BUYER: Asset transfer (from escrow to buyer/executor)
  345. // TXN 3/4 - DEPENDS: don't check this here - different on whether closing or not
  346. // Either: Pay transaction for fee refund (from buyer/executor to escrow)
  347. // OR: Pay transaction to close out to escrow owner (from escrow to escrow owner)
  348. anyExecute:
  349. ///////////////////////
  350. // OPTIONAL ASSET-OPT IN CHECK
  351. // First check if we have the optional asset opt-in transaction for the buyer's wallet
  352. // This happens for both execute and execute_with_close
  353. // If this exists, it's the third transaction (gtxn 2).
  354. gtxn 2 TypeEnum
  355. int axfer
  356. ==
  357. gtxn 2 AssetAmount
  358. int 0
  359. ==
  360. &&
  361. gtxn 2 Sender
  362. gtxn 2 AssetReceiver
  363. ==
  364. &&
  365. gtxn 2 XferAsset
  366. int <assetid> // asset id to trade for
  367. ==
  368. &&
  369. gtxn 2 AssetCloseTo
  370. global ZeroAddress
  371. ==
  372. &&
  373. gtxn 2 Sender
  374. txn Sender // Sender must come from the user's wallet, not the escrow
  375. != // should *not* be originating from escrow
  376. &&
  377. store 0 //this will store the next transaction offset depending if opt in exists
  378. load 0
  379. int 2
  380. +
  381. store 2 // store offset of transaction 2, depending on if opt-in exists
  382. load 0
  383. int 3
  384. +
  385. store 3 // store offset of transaction 3, depending on if opt-in exists
  386. /// END OPTIONAL ASSET OPT IN CHECK
  387. // NOW CHECK TRANSACTIONS
  388. int 4
  389. load 0
  390. +
  391. global GroupSize // GroupSize must be 4 or 5 according to whether optional ASA opt in exists
  392. ==
  393. assert
  394. gtxn 0 Sender
  395. txn Sender // escrow account
  396. ==
  397. gtxn 1 Sender
  398. txn Sender // escrow account
  399. != // should *not* be originating from escrow
  400. &&
  401. load 2
  402. gtxns Sender // Asset transfer comes from escrow account
  403. txn Sender // Escrow account
  404. ==
  405. &&
  406. gtxn 1 Sender // The buyer
  407. load 2
  408. gtxns AssetReceiver // Asset transfer is sent to the buyer
  409. ==
  410. &&
  411. gtxn 1 Receiver
  412. addr <contractWriterAddr> // contractWriterAddr
  413. ==
  414. &&
  415. gtxn 0 TypeEnum // First Transaction must be a call to a stateful contract
  416. int appl
  417. ==
  418. &&
  419. gtxn 1 TypeEnum // The second transaction must be a payment transaction
  420. int pay
  421. ==
  422. &&
  423. gtxn 2 TypeEnum // third transaction must be an asset opt-in/transfer
  424. int axfer
  425. ==
  426. &&
  427. load 2
  428. gtxns TypeEnum //The next transaction must be an asset transfer
  429. int axfer
  430. ==
  431. &&
  432. load 3
  433. gtxns TypeEnum // The last transaction must be a payment transfer
  434. int pay
  435. ==
  436. &&
  437. gtxn 0 ApplicationID // The specific App ID must be called
  438. int <orderBookId> //stateful contract app id. orderBookId
  439. ==
  440. &&
  441. gtxn 0 CloseRemainderTo
  442. global ZeroAddress
  443. ==
  444. &&
  445. gtxn 1 CloseRemainderTo
  446. global ZeroAddress
  447. ==
  448. &&
  449. load 2
  450. gtxns CloseRemainderTo
  451. global ZeroAddress
  452. ==
  453. &&
  454. gtxn 0 AssetCloseTo
  455. global ZeroAddress
  456. ==
  457. &&
  458. gtxn 1 AssetCloseTo
  459. global ZeroAddress
  460. ==
  461. &&
  462. load 2
  463. gtxns XferAsset
  464. int <assetid> // asset id to trade for
  465. ==
  466. &&
  467. assert
  468. //////////////////////////////////////////////////////////////////////////////
  469. // EXECUTE (partial)
  470. // Partial execution of an ASA escrow, where an ASA balance remains in it
  471. //////////////////////////////////////////////////////////////////////////////
  472. // TXN 0 - ESCROW TO ORDERBOOK: Application call to execute
  473. // TXN 1 - BUYER TO SELLER: Pay transaction (from buyer/executor to escrow owner)
  474. // TXN 2 - BUYER TO BUYER: (Optional) asset opt-in transaction (for buyer/executor)
  475. // TXN 2/3 - ESCROW TO BUYER: Asset transfer (from escrow to buyer/executor)
  476. // TXN 3/4 - BUYER TO ESCROW: Pay transaction for fee refund (from buyer/executor to escrow)
  477. gtxna 0 ApplicationArgs 0
  478. byte "execute_with_closeout"
  479. ==
  480. bnz execute_with_closeout
  481. global MinTxnFee
  482. global MinTxnFee
  483. +
  484. store 8 // store 2x minimum fee
  485. gtxn 0 OnCompletion // The application call must be a general application call
  486. int NoOp
  487. ==
  488. load 2
  489. gtxns AssetCloseTo
  490. global ZeroAddress
  491. ==
  492. &&
  493. load 3
  494. gtxns CloseRemainderTo // check fee refund has no close remainder to
  495. global ZeroAddress
  496. ==
  497. &&
  498. load 3
  499. gtxns Fee // check fee refund has no close remainder to
  500. global MinTxnFee
  501. ==
  502. &&
  503. load 3
  504. gtxns Amount // check fee refund amount is 2x minimum fee
  505. load 8
  506. ==
  507. &&
  508. load 3
  509. gtxns Receiver // receiver of fee transaction
  510. txn Sender // escrow addr. check fee must be received by escrow account
  511. ==
  512. &&
  513. load 3
  514. gtxns Sender // The fee sender must be the ASA buyer
  515. gtxn 1 Sender
  516. ==
  517. &&
  518. load 3
  519. gtxns Sender // The fee sender
  520. txn Sender // Escrow account
  521. != // Fee sender should *not* be originating from escrow
  522. &&
  523. assert
  524. b finalExecuteChecks //If the above result is 0, skip next section
  525. /////////////////////////////////////////////////////////////////////////////////////////////////
  526. // EXECUTE WITH CLOSE
  527. // Full order execution where the remaining minimum algo balance is closed to the escrow owner
  528. /////////////////////////////////////////////////////////////////////////////////////////////////
  529. // TXN 0 - ESCROW TO ORDERBOOK: Application call to execute
  530. // TXN 1 - BUYER TO SELLER: Pay transaction (from buyer/executor to escrow owner)
  531. // TXN 2 - BUYER TO BUYER: (Optional) asset opt-in transaction (for buyer/executor)
  532. // TXN 2/3 - ESCROW TO BUYER: Asset transfer (from escrow to buyer/executor)
  533. // - closes out any remaining ASA to seller (escrow owner) as well
  534. // TXN 3/4 - ESCROW TO SELLER: Pay transaction to close out to escrow owner
  535. execute_with_closeout:
  536. // The first transaction must be
  537. // an ApplicationCall (ie call stateful smart contract)
  538. gtxn 0 OnCompletion
  539. int CloseOut
  540. ==
  541. gtxn 1 CloseRemainderTo
  542. global ZeroAddress
  543. ==
  544. &&
  545. load 2
  546. gtxns AssetCloseTo // remainder of ASA escrow is being closed out to escrow owner
  547. addr <contractWriterAddr> // contractWriterAddr
  548. ==
  549. &&
  550. load 3
  551. gtxns CloseRemainderTo
  552. addr <contractWriterAddr> // contractWriterAddr
  553. ==
  554. &&
  555. load 3
  556. gtxns Receiver
  557. addr <contractWriterAddr> // contractWriterAddr
  558. ==
  559. &&
  560. load 3
  561. gtxns Sender // escrow account
  562. txn Sender // escrow account
  563. ==
  564. &&
  565. load 3
  566. gtxns Amount
  567. int 0 // probably shouldn't matter, but the full amount should be in the CloseTo, not the Amount
  568. ==
  569. &&
  570. assert
  571. b finalExecuteChecks
  572. finalExecuteChecks:
  573. gtxn 1 Amount // min algos spent
  574. //int <min> // NOTE** We have intentionally disabled the custom min amount check
  575. int 1 // must be at least one algo spent
  576. >=
  577. load 2
  578. gtxns AssetAmount
  579. int 1 // must be at least one ASA spent
  580. >=
  581. &&
  582. bz fail
  583. /////////////////////////////////////
  584. /// finalizing execution ratio checks
  585. /////////////////////////////////////
  586. // handle the rate
  587. // SELL ORDER
  588. // 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
  589. //
  590. // gtxn[2].AssetAmount * D <= gtxn[1].Amount * N
  591. // N units of the asset per D microAlgos
  592. load 2
  593. gtxns AssetAmount
  594. int <D> // put <D> value here
  595. mulw // AssetAmount * D => (high 64 bits, low 64 bits)
  596. store 2 // move aside low 64 bits
  597. store 1 // move aside high 64 bits
  598. gtxn 1 Amount
  599. int <N> // put <N> value here
  600. mulw
  601. store 4 // move aside low 64 bits
  602. store 3 // move aside high 64 bits
  603. // compare high bits to high bits
  604. load 1
  605. load 3
  606. <
  607. bnz done
  608. load 1
  609. load 3
  610. ==
  611. load 2
  612. load 4
  613. <=
  614. && // high bits are equal and low bits are ok
  615. bnz done
  616. err
  617. done:
  618. int 1
  619. return
  620. fail:
  621. int 0
  622. return
  623. `;
  624. JAVASCRIPT
    Copied!