@dev.sail.money/sailor 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/AGENTS.md +111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +337 -0
  4. package/docs/PERMISSION_MODEL.md +93 -0
  5. package/examples/permissions/BoundedBet_Limitless_Base.sol +96 -0
  6. package/examples/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +94 -0
  7. package/examples/permissions/BoundedPerp_GMXv2_Arbitrum.sol +143 -0
  8. package/examples/permissions/BoundedSwap_UniswapV3_Base.sol +113 -0
  9. package/examples/permissions/BoundedSwap_UniswapV4_Unichain.sol +144 -0
  10. package/examples/permissions/BoundedTransfer_ERC20_Ethereum.sol +73 -0
  11. package/examples/permissions/README.md +52 -0
  12. package/examples/permissions/foundry.toml +10 -0
  13. package/examples/permissions/interfaces/IPermission.sol +18 -0
  14. package/package.json +39 -0
  15. package/packages/cli/README.md +34 -0
  16. package/packages/cli/dist/index.cjs +42801 -0
  17. package/packages/cli/dist/server.cjs +51202 -0
  18. package/packages/sdk/README.md +65 -0
  19. package/packages/sdk/dist/abis/MandateFactory.d.ts +140 -0
  20. package/packages/sdk/dist/abis/MandateFactory.d.ts.map +1 -0
  21. package/packages/sdk/dist/abis/MandateFactory.js +93 -0
  22. package/packages/sdk/dist/abis/MandateFactory.js.map +1 -0
  23. package/packages/sdk/dist/abis/SailGovernance.d.ts +57 -0
  24. package/packages/sdk/dist/abis/SailGovernance.d.ts.map +1 -0
  25. package/packages/sdk/dist/abis/SailGovernance.js +52 -0
  26. package/packages/sdk/dist/abis/SailGovernance.js.map +1 -0
  27. package/packages/sdk/dist/abis/SailKernel.d.ts +466 -0
  28. package/packages/sdk/dist/abis/SailKernel.d.ts.map +1 -0
  29. package/packages/sdk/dist/abis/SailKernel.js +311 -0
  30. package/packages/sdk/dist/abis/SailKernel.js.map +1 -0
  31. package/packages/sdk/dist/abis/index.d.ts +4 -0
  32. package/packages/sdk/dist/abis/index.d.ts.map +1 -0
  33. package/packages/sdk/dist/abis/index.js +7 -0
  34. package/packages/sdk/dist/abis/index.js.map +1 -0
  35. package/packages/sdk/dist/capabilities.d.ts +77 -0
  36. package/packages/sdk/dist/capabilities.d.ts.map +1 -0
  37. package/packages/sdk/dist/capabilities.js +158 -0
  38. package/packages/sdk/dist/capabilities.js.map +1 -0
  39. package/packages/sdk/dist/client.d.ts +37 -0
  40. package/packages/sdk/dist/client.d.ts.map +1 -0
  41. package/packages/sdk/dist/client.js +646 -0
  42. package/packages/sdk/dist/client.js.map +1 -0
  43. package/packages/sdk/dist/deployments.d.ts +82 -0
  44. package/packages/sdk/dist/deployments.d.ts.map +1 -0
  45. package/packages/sdk/dist/deployments.js +197 -0
  46. package/packages/sdk/dist/deployments.js.map +1 -0
  47. package/packages/sdk/dist/discovery.d.ts +10 -0
  48. package/packages/sdk/dist/discovery.d.ts.map +1 -0
  49. package/packages/sdk/dist/discovery.js +41 -0
  50. package/packages/sdk/dist/discovery.js.map +1 -0
  51. package/packages/sdk/dist/eip712.d.ts +257 -0
  52. package/packages/sdk/dist/eip712.d.ts.map +1 -0
  53. package/packages/sdk/dist/eip712.js +255 -0
  54. package/packages/sdk/dist/eip712.js.map +1 -0
  55. package/packages/sdk/dist/errors.d.ts +47 -0
  56. package/packages/sdk/dist/errors.d.ts.map +1 -0
  57. package/packages/sdk/dist/errors.js +168 -0
  58. package/packages/sdk/dist/errors.js.map +1 -0
  59. package/packages/sdk/dist/fees.d.ts +16 -0
  60. package/packages/sdk/dist/fees.d.ts.map +1 -0
  61. package/packages/sdk/dist/fees.js +51 -0
  62. package/packages/sdk/dist/fees.js.map +1 -0
  63. package/packages/sdk/dist/index.d.ts +23 -0
  64. package/packages/sdk/dist/index.d.ts.map +1 -0
  65. package/packages/sdk/dist/index.js +16 -0
  66. package/packages/sdk/dist/index.js.map +1 -0
  67. package/packages/sdk/dist/intelligence.d.ts +923 -0
  68. package/packages/sdk/dist/intelligence.d.ts.map +1 -0
  69. package/packages/sdk/dist/intelligence.js +357 -0
  70. package/packages/sdk/dist/intelligence.js.map +1 -0
  71. package/packages/sdk/dist/keyring.d.ts +60 -0
  72. package/packages/sdk/dist/keyring.d.ts.map +1 -0
  73. package/packages/sdk/dist/keyring.js +159 -0
  74. package/packages/sdk/dist/keyring.js.map +1 -0
  75. package/packages/sdk/dist/lifi.d.ts +83 -0
  76. package/packages/sdk/dist/lifi.d.ts.map +1 -0
  77. package/packages/sdk/dist/lifi.js +69 -0
  78. package/packages/sdk/dist/lifi.js.map +1 -0
  79. package/packages/sdk/dist/safe.d.ts +158 -0
  80. package/packages/sdk/dist/safe.d.ts.map +1 -0
  81. package/packages/sdk/dist/safe.js +163 -0
  82. package/packages/sdk/dist/safe.js.map +1 -0
  83. package/packages/sdk/dist/signing.d.ts +106 -0
  84. package/packages/sdk/dist/signing.d.ts.map +1 -0
  85. package/packages/sdk/dist/signing.js +2 -0
  86. package/packages/sdk/dist/signing.js.map +1 -0
  87. package/packages/sdk/dist/templates/ammLiquidity.d.ts +16 -0
  88. package/packages/sdk/dist/templates/ammLiquidity.d.ts.map +1 -0
  89. package/packages/sdk/dist/templates/ammLiquidity.js +60 -0
  90. package/packages/sdk/dist/templates/ammLiquidity.js.map +1 -0
  91. package/packages/sdk/dist/templates/approveAndCallBatch.d.ts +14 -0
  92. package/packages/sdk/dist/templates/approveAndCallBatch.d.ts.map +1 -0
  93. package/packages/sdk/dist/templates/approveAndCallBatch.js +53 -0
  94. package/packages/sdk/dist/templates/approveAndCallBatch.js.map +1 -0
  95. package/packages/sdk/dist/templates/boundedBorrow.d.ts +16 -0
  96. package/packages/sdk/dist/templates/boundedBorrow.d.ts.map +1 -0
  97. package/packages/sdk/dist/templates/boundedBorrow.js +56 -0
  98. package/packages/sdk/dist/templates/boundedBorrow.js.map +1 -0
  99. package/packages/sdk/dist/templates/boundedSwap.d.ts +16 -0
  100. package/packages/sdk/dist/templates/boundedSwap.d.ts.map +1 -0
  101. package/packages/sdk/dist/templates/boundedSwap.js +56 -0
  102. package/packages/sdk/dist/templates/boundedSwap.js.map +1 -0
  103. package/packages/sdk/dist/templates/defiBundle.d.ts +14 -0
  104. package/packages/sdk/dist/templates/defiBundle.d.ts.map +1 -0
  105. package/packages/sdk/dist/templates/defiBundle.js +52 -0
  106. package/packages/sdk/dist/templates/defiBundle.js.map +1 -0
  107. package/packages/sdk/dist/templates/index.d.ts +15 -0
  108. package/packages/sdk/dist/templates/index.d.ts.map +1 -0
  109. package/packages/sdk/dist/templates/index.js +8 -0
  110. package/packages/sdk/dist/templates/index.js.map +1 -0
  111. package/packages/sdk/dist/templates/pendle.d.ts +14 -0
  112. package/packages/sdk/dist/templates/pendle.d.ts.map +1 -0
  113. package/packages/sdk/dist/templates/pendle.js +52 -0
  114. package/packages/sdk/dist/templates/pendle.js.map +1 -0
  115. package/packages/sdk/dist/templates/transferTarget.d.ts +10 -0
  116. package/packages/sdk/dist/templates/transferTarget.d.ts.map +1 -0
  117. package/packages/sdk/dist/templates/transferTarget.js +42 -0
  118. package/packages/sdk/dist/templates/transferTarget.js.map +1 -0
  119. package/packages/sdk/dist/types.d.ts +382 -0
  120. package/packages/sdk/dist/types.d.ts.map +1 -0
  121. package/packages/sdk/dist/types.js +2 -0
  122. package/packages/sdk/dist/types.js.map +1 -0
  123. package/packages/sdk/package.json +52 -0
  124. package/packages/ui/dist/assets/Arc-VDBY7LNS-BChRXCXW.js +1 -0
  125. package/packages/ui/dist/assets/Brave-BRAKJXDS-mq-Xo37j.js +1 -0
  126. package/packages/ui/dist/assets/Browser-76IHF3Y2-BMhRaC5Z.js +1 -0
  127. package/packages/ui/dist/assets/Chrome-65Q5P54Y-DR9MQEVr.js +1 -0
  128. package/packages/ui/dist/assets/Edge-XSPUTORV-DEoZslQE.js +1 -0
  129. package/packages/ui/dist/assets/Firefox-AAHGJQIP-Bp_Hm04m.js +1 -0
  130. package/packages/ui/dist/assets/Linux-OO4TNCLJ-B0aw93n9.js +1 -0
  131. package/packages/ui/dist/assets/Macos-MW4AE7LN-Vvm8Drw3.js +1 -0
  132. package/packages/ui/dist/assets/Opera-KQZLSACL-Cwv5MDFy.js +1 -0
  133. package/packages/ui/dist/assets/Safari-ZPL37GXR-C4Ggg6rz.js +1 -0
  134. package/packages/ui/dist/assets/Windows-PPTHQER6-BlyV2p7Y.js +1 -0
  135. package/packages/ui/dist/assets/add-DaJhwIBV.js +15 -0
  136. package/packages/ui/dist/assets/all-wallets-BUxsqWXi.js +6 -0
  137. package/packages/ui/dist/assets/apechain-SX5YFU6N-q5qBv-mp.js +1 -0
  138. package/packages/ui/dist/assets/app-store-DkltwTqE.js +17 -0
  139. package/packages/ui/dist/assets/apple-owVOeaIT.js +18 -0
  140. package/packages/ui/dist/assets/ar_AR-LIPSOZP5-BQrIDibT.js +1519 -0
  141. package/packages/ui/dist/assets/arbitrum-WURIBY6W-CqVkHBr5.js +1 -0
  142. package/packages/ui/dist/assets/arrow-bottom-D2mmNJve.js +8 -0
  143. package/packages/ui/dist/assets/arrow-bottom-circle-CbNYijx-.js +11 -0
  144. package/packages/ui/dist/assets/arrow-left-DJB61s4C.js +8 -0
  145. package/packages/ui/dist/assets/arrow-right-BBrsQ9R4.js +8 -0
  146. package/packages/ui/dist/assets/arrow-top-Cil6bOc8.js +8 -0
  147. package/packages/ui/dist/assets/assets-Q6ZU7ZJ5-P8HioiAD.js +1 -0
  148. package/packages/ui/dist/assets/avalanche-KOMJD3XY-Dsn_JPR4.js +1 -0
  149. package/packages/ui/dist/assets/bank-CbwEmRo3.js +14 -0
  150. package/packages/ui/dist/assets/base-OAXLRA4F-CoYTVIiL.js +1 -0
  151. package/packages/ui/dist/assets/base-QS6CYWIN-CsjdbWCf.js +1 -0
  152. package/packages/ui/dist/assets/basic-CLNfjw3m.js +2128 -0
  153. package/packages/ui/dist/assets/berachain-NJECWIVC-DumxnFvf.js +1 -0
  154. package/packages/ui/dist/assets/blast-V555OVXZ-BbhJh1tj.js +1 -0
  155. package/packages/ui/dist/assets/browser-B5TtF4Pb.js +14 -0
  156. package/packages/ui/dist/assets/bsc-N647EYR2-B2nLKXWV.js +1 -0
  157. package/packages/ui/dist/assets/card-CO7BVB-C.js +14 -0
  158. package/packages/ui/dist/assets/ccip-2W7K3_J3.js +1 -0
  159. package/packages/ui/dist/assets/celo-GEP4TUHG-CenIBYLU.js +1 -0
  160. package/packages/ui/dist/assets/checkmark-BEtSHq9m.js +11 -0
  161. package/packages/ui/dist/assets/checkmark-bold-D9xGHzPE.js +8 -0
  162. package/packages/ui/dist/assets/chevron-bottom-BDztht6i.js +8 -0
  163. package/packages/ui/dist/assets/chevron-left-EV4GFNbc.js +8 -0
  164. package/packages/ui/dist/assets/chevron-right-B4_bB9oR.js +8 -0
  165. package/packages/ui/dist/assets/chevron-top-D54xPNzF.js +8 -0
  166. package/packages/ui/dist/assets/chrome-store-DYUpAJJq.js +61 -0
  167. package/packages/ui/dist/assets/clock-Ca1T1Soz.js +8 -0
  168. package/packages/ui/dist/assets/close-BZqWjurK.js +8 -0
  169. package/packages/ui/dist/assets/coinPlaceholder-e6fl2XDo.js +8 -0
  170. package/packages/ui/dist/assets/compass-DCLC7zIh.js +8 -0
  171. package/packages/ui/dist/assets/connect-UA7M4XW6-IY3X6Bmr.js +1 -0
  172. package/packages/ui/dist/assets/copy-Th2AaD-O.js +15 -0
  173. package/packages/ui/dist/assets/core-Ckx_cyuH.js +907 -0
  174. package/packages/ui/dist/assets/create-FASO7PVG-D_rvSpre.js +1 -0
  175. package/packages/ui/dist/assets/cronos-HJPAQTAE-BEOvlOC4.js +1 -0
  176. package/packages/ui/dist/assets/cursor-DV7rOqbJ.js +3 -0
  177. package/packages/ui/dist/assets/cursor-transparent-BKHeABKB.js +12 -0
  178. package/packages/ui/dist/assets/de_DE-YE3KOFHU-BRt5ztUe.js +1519 -0
  179. package/packages/ui/dist/assets/degen-FQQ4XGHB-CeHTs88l.js +1 -0
  180. package/packages/ui/dist/assets/desktop-CBjY8t6F.js +9 -0
  181. package/packages/ui/dist/assets/disconnect-DbSs2cli.js +8 -0
  182. package/packages/ui/dist/assets/discord-ZlLOAUkM.js +17 -0
  183. package/packages/ui/dist/assets/es_419-7LMPU7G4-DH7rM0yQ.js +1519 -0
  184. package/packages/ui/dist/assets/ethereum-RGGVA4PY-SWGOlkuk.js +1 -0
  185. package/packages/ui/dist/assets/etherscan-CKUrqWYN.js +6 -0
  186. package/packages/ui/dist/assets/events-CiKP71cK.js +1 -0
  187. package/packages/ui/dist/assets/exclamation-triangle-DA1QzFiO.js +4 -0
  188. package/packages/ui/dist/assets/extension-BVJkmvpJ.js +8 -0
  189. package/packages/ui/dist/assets/external-link-D_bsR7B2.js +8 -0
  190. package/packages/ui/dist/assets/facebook-CmFmhojx.js +26 -0
  191. package/packages/ui/dist/assets/fallback-Ofl6uSnB.js +1 -0
  192. package/packages/ui/dist/assets/farcaster-Co-M3Ss8.js +12 -0
  193. package/packages/ui/dist/assets/filters-B1WwNaFU.js +8 -0
  194. package/packages/ui/dist/assets/flow-5FQJFCTK-CUie2reO.js +1 -0
  195. package/packages/ui/dist/assets/fr_FR-VBJP3ZLL-B-_ocunw.js +1519 -0
  196. package/packages/ui/dist/assets/github-CP4fP6gn.js +18 -0
  197. package/packages/ui/dist/assets/gnosis-37ZC4RBL-B137OtHZ.js +1 -0
  198. package/packages/ui/dist/assets/google-CsOIXJ6V.js +18 -0
  199. package/packages/ui/dist/assets/gravity-J5YQHTYH-Bj6B0uod.js +1 -0
  200. package/packages/ui/dist/assets/hardhat-TX56IT5N-CV1FY-wE.js +1 -0
  201. package/packages/ui/dist/assets/help-circle-DiMkomdF.js +12 -0
  202. package/packages/ui/dist/assets/hi_IN-WBVD5XYI-D73g2UFs.js +1519 -0
  203. package/packages/ui/dist/assets/hyperevm-VKPAA4SA-CHwraEsx.js +1 -0
  204. package/packages/ui/dist/assets/id-lmscL5LX.js +12 -0
  205. package/packages/ui/dist/assets/id_ID-SBYANJ7G-Cjpa4ay6.js +1519 -0
  206. package/packages/ui/dist/assets/image-B-ubJrY5.js +4 -0
  207. package/packages/ui/dist/assets/index-BaukYv-x.js +16 -0
  208. package/packages/ui/dist/assets/index-CF0KMmke.js +395 -0
  209. package/packages/ui/dist/assets/index-CKxgNxS9.css +1 -0
  210. package/packages/ui/dist/assets/index-CZR1Qjhs.js +1 -0
  211. package/packages/ui/dist/assets/index-DVgfCzCo.js +1 -0
  212. package/packages/ui/dist/assets/index-Dbh5V1Z0.js +1 -0
  213. package/packages/ui/dist/assets/index-Q2Yai4Fe.js +2103 -0
  214. package/packages/ui/dist/assets/index.es-C78cE5SI.js +26 -0
  215. package/packages/ui/dist/assets/info-Cqg57EVo.js +3 -0
  216. package/packages/ui/dist/assets/info-circle-DkeSWNKV.js +12 -0
  217. package/packages/ui/dist/assets/ink-FZMYZWHG-62p-5IK5.js +1 -0
  218. package/packages/ui/dist/assets/ja_JP-ZRMWJV3I-DXbifiMm.js +1519 -0
  219. package/packages/ui/dist/assets/kaia-65D2U3PU-JmuLQ4gC.js +1 -0
  220. package/packages/ui/dist/assets/ko_KR-FR54RFUG-upinSHjQ.js +1519 -0
  221. package/packages/ui/dist/assets/lightbulb-DNlO4qKh.js +3 -0
  222. package/packages/ui/dist/assets/linea-QRMVQ5DY-DuI3vv0d.js +1 -0
  223. package/packages/ui/dist/assets/login-UP3DZBGS-Db_wM5oQ.js +1 -0
  224. package/packages/ui/dist/assets/mail-kVQ8Jb9Y.js +8 -0
  225. package/packages/ui/dist/assets/manta-SI27YFEJ-CpVOKa06.js +1 -0
  226. package/packages/ui/dist/assets/mantle-CKIUT334-DR2WgqzU.js +1 -0
  227. package/packages/ui/dist/assets/metaMaskWallet-EI6MED72-D5HFOsnz.js +1 -0
  228. package/packages/ui/dist/assets/metamask-sdk-CBalSvz7.js +542 -0
  229. package/packages/ui/dist/assets/mobile-BEteuhF7.js +9 -0
  230. package/packages/ui/dist/assets/monad-4KWC6TSS-DVXSkpiz.js +1 -0
  231. package/packages/ui/dist/assets/more-DBWmXQli.js +11 -0
  232. package/packages/ui/dist/assets/ms_MY-EZSGYYYQ-4cPLK-3L.js +1519 -0
  233. package/packages/ui/dist/assets/native-CJ5et6AR.js +1 -0
  234. package/packages/ui/dist/assets/network-placeholder-Dg1uUHiL.js +14 -0
  235. package/packages/ui/dist/assets/nftPlaceholder-i3AHSiD9.js +8 -0
  236. package/packages/ui/dist/assets/off-BtMm0fi2.js +8 -0
  237. package/packages/ui/dist/assets/optimism-HAF2GUT7-ec6Nqxs9.js +1 -0
  238. package/packages/ui/dist/assets/parseSignature-Cb5FlWWg.js +1 -0
  239. package/packages/ui/dist/assets/play-store-iKKkXa6a.js +32 -0
  240. package/packages/ui/dist/assets/plus-CA5NaRtb.js +13 -0
  241. package/packages/ui/dist/assets/polygon-WW6ZI7PM-DXlmm4L1.js +1 -0
  242. package/packages/ui/dist/assets/pt_BR-JQFQ3P4L-DOHfdcA2.js +1519 -0
  243. package/packages/ui/dist/assets/qr-code-D2kiqR7h.js +6 -0
  244. package/packages/ui/dist/assets/rainbowWallet-O26YNBMX-DUhYus-9.js +1 -0
  245. package/packages/ui/dist/assets/recycle-horizontal-Dcme7R03.js +9 -0
  246. package/packages/ui/dist/assets/refresh-Dega3sDp.js +8 -0
  247. package/packages/ui/dist/assets/refresh-S4T5V5GX-CwqIaaxK.js +1 -0
  248. package/packages/ui/dist/assets/reown-logo-xNkksyWJ.js +12 -0
  249. package/packages/ui/dist/assets/ronin-EMCPYXZT-N-QBHZdV.js +1 -0
  250. package/packages/ui/dist/assets/ru_RU-Z42UEJBP-Cvb2oWxQ.js +1519 -0
  251. package/packages/ui/dist/assets/safeWallet-5MNKTR5Z-D-5imDLD.js +1 -0
  252. package/packages/ui/dist/assets/sanko-RHQYXGM5-OX010CbN.js +1 -0
  253. package/packages/ui/dist/assets/scan-4UYSQ56Q-CjMz6-XC.js +1 -0
  254. package/packages/ui/dist/assets/scroll-5OBGQVOV-DJFECiai.js +1 -0
  255. package/packages/ui/dist/assets/search-HYl7NO8x.js +8 -0
  256. package/packages/ui/dist/assets/secp256k1-Cxd6_SiH.js +1 -0
  257. package/packages/ui/dist/assets/send-CJU8CUAo.js +15 -0
  258. package/packages/ui/dist/assets/sign-A7IJEUT5-CGsRnPrd.js +1 -0
  259. package/packages/ui/dist/assets/superposition-HG6MMR2Y-bRkgatRO.js +1 -0
  260. package/packages/ui/dist/assets/swapHorizontal-IMUKiUre.js +8 -0
  261. package/packages/ui/dist/assets/swapHorizontalBold-CNYnNJ9-.js +8 -0
  262. package/packages/ui/dist/assets/swapHorizontalMedium-B9VxEYsT.js +16 -0
  263. package/packages/ui/dist/assets/swapHorizontalRoundedBold-Dz33l_Jh.js +8 -0
  264. package/packages/ui/dist/assets/swapVertical-CHUmjVJ0.js +8 -0
  265. package/packages/ui/dist/assets/telegram-kl9S2mbU.js +16 -0
  266. package/packages/ui/dist/assets/th_TH-4YB4VSB2-BUipNP-V.js +1519 -0
  267. package/packages/ui/dist/assets/three-dots-U5lhA1Am.js +5 -0
  268. package/packages/ui/dist/assets/tr_TR-5FKHPPIO-D5jTpIm9.js +1519 -0
  269. package/packages/ui/dist/assets/twitch-KTEUWXEp.js +18 -0
  270. package/packages/ui/dist/assets/twitterIcon-BHiq8mRg.js +6 -0
  271. package/packages/ui/dist/assets/uk_UA-ZD4IBC52-DgnQrpzl.js +1519 -0
  272. package/packages/ui/dist/assets/unichain-C5BWO2ZY-BfguYsnu.js +1 -0
  273. package/packages/ui/dist/assets/verify-CfN-BXNd.js +8 -0
  274. package/packages/ui/dist/assets/verify-filled-DwZccetj.js +8 -0
  275. package/packages/ui/dist/assets/vi_VN-5EVRZKLY-x078672g.js +1519 -0
  276. package/packages/ui/dist/assets/w3m-modal-CS-PFqPE.js +642 -0
  277. package/packages/ui/dist/assets/wallet-DVlGkhOY.js +8 -0
  278. package/packages/ui/dist/assets/wallet-placeholder-CvR_iEWX.js +14 -0
  279. package/packages/ui/dist/assets/walletConnectWallet-YHWKVTDY-D3lyiczV.js +1 -0
  280. package/packages/ui/dist/assets/walletconnect-8pZBDvVI.js +30 -0
  281. package/packages/ui/dist/assets/warning-circle-ylLEE0Yp.js +12 -0
  282. package/packages/ui/dist/assets/x-C_TBsTMj.js +12 -0
  283. package/packages/ui/dist/assets/xdc-KJ3TDBYO-DNV6zchh.js +1 -0
  284. package/packages/ui/dist/assets/zetachain-TLDS5IPW-Udhyw16T.js +1 -0
  285. package/packages/ui/dist/assets/zh_CN-4XK5YJPR-Bt6Yz5Ek.js +1519 -0
  286. package/packages/ui/dist/assets/zh_HK-N4YN2WSI-Cvzl1V16.js +1519 -0
  287. package/packages/ui/dist/assets/zh_TW-CNCRXH6Z-BNelatfN.js +1519 -0
  288. package/packages/ui/dist/assets/zksync-DH7HK5U4-Dt4usFw6.js +1 -0
  289. package/packages/ui/dist/assets/zora-FYL5H3IO-iB4wygST.js +1 -0
  290. package/packages/ui/dist/index.html +14 -0
  291. package/scripts/check-docs.mjs +262 -0
  292. package/scripts/check-init.mjs +109 -0
  293. package/scripts/postinstall.js +366 -0
  294. package/templates/custom-mandate/.sail/contracts/interfaces/IPermission.sol +18 -0
  295. package/templates/custom-mandate/README.md +85 -0
  296. package/templates/custom-mandate/foundry.toml +8 -0
  297. package/templates/custom-mandate/mandates/BoundedCallPermission.sol +35 -0
  298. package/templates/custom-mandate/mandates/README.md +16 -0
  299. package/templates/dca-rebalancer/.cursor/rules +25 -0
  300. package/templates/dca-rebalancer/.env.example +6 -0
  301. package/templates/dca-rebalancer/.github/workflows/agent-tick.yml +32 -0
  302. package/templates/dca-rebalancer/.sail/.gitkeep +0 -0
  303. package/templates/dca-rebalancer/.sail/README.md +13 -0
  304. package/templates/dca-rebalancer/.sail/config.json +10 -0
  305. package/templates/dca-rebalancer/AGENTS.md +246 -0
  306. package/templates/dca-rebalancer/AGENT_PLAYBOOK.md +110 -0
  307. package/templates/dca-rebalancer/CLAUDE.md +2 -0
  308. package/templates/dca-rebalancer/README.md +16 -0
  309. package/templates/dca-rebalancer/_gitignore +13 -0
  310. package/templates/dca-rebalancer/docs/PERMISSION_MODEL.md +93 -0
  311. package/templates/dca-rebalancer/package.json +17 -0
  312. package/templates/dca-rebalancer/src/agent.ts +253 -0
  313. package/templates/dca-rebalancer/src/config.ts +27 -0
  314. package/templates/dca-rebalancer/src/mandate.ts +67 -0
  315. package/templates/dca-rebalancer/tsconfig.json +8 -0
  316. package/templates/dca-rebalancer/ui/README.md +3 -0
  317. package/templates/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +84 -0
  318. package/templates/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +97 -0
  319. package/templates/lifi-permissions/README.md +53 -0
@@ -0,0 +1,94 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Protocol : Aave V3
6
+ // Version : Pool (proxy) — fully on-chain, oracle-based liquidation
7
+ // Chain : Arbitrum mainnet
8
+ // Target : Aave V3 Pool 0x794a61358D6845594F94dc1DB02A252b5b4814aD
9
+ //
10
+ // ENFORCED ON-CHAIN (via kernel evaluate() on every dispatch):
11
+ // borrow(address asset, uint256 amount, uint256 interestRateMode,
12
+ // uint16 referralCode, address onBehalfOf)
13
+ // • target must be AAVE_POOL
14
+ // • asset must be in ALLOWED_ASSETS
15
+ // • amount ≤ MAX_BORROW_AMOUNT
16
+ // • onBehalfOf must equal ctx.account (the SMA — agent cannot borrow on behalf of others)
17
+ // • interestRateMode must be in ALLOWED_RATE_MODES
18
+ // (1 = stable [deprecated in V3.1], 2 = variable; restrict to [2] for V3.1+)
19
+ //
20
+ // NOT ENFORCED (agent code — can change without a new contract):
21
+ // • Health factor management — the kernel cannot check post-borrow health factor
22
+ // • referralCode (informational only, does not affect fund safety)
23
+ // • Repayment timing — agent decides when to repay
24
+ // • Collateral composition — managed by prior deposit permissions
25
+ //
26
+ // VERIFY BEFORE USE:
27
+ // • Confirm Aave V3 Pool address on Arbitrum (0x794a... — verify on Arbiscan).
28
+ // • Selector 0xa415bcad = borrow(address,uint256,uint256,uint16,address).
29
+ // Compute: keccak256("borrow(address,uint256,uint256,uint16,address)")[0:4]
30
+ // and confirm it matches before deploying.
31
+ // • Aave V3.1 deprecated stable-rate borrowing (interestRateMode=1).
32
+ // If using V3.1+, set allowedRateModes = [2] (variable only).
33
+ // • MAX_BORROW_AMOUNT is in the asset's base units (e.g. 6 decimals for USDC).
34
+ // ─────────────────────────────────────────────────────────────────────────────
35
+
36
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
37
+
38
+ contract BoundedBorrow_AaveV3_Arbitrum is IPermission {
39
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedBorrow_AaveV3_Arbitrum");
40
+
41
+ address public immutable AAVE_POOL;
42
+ mapping(address => bool) public isAllowedAsset;
43
+ uint256 public immutable MAX_BORROW_AMOUNT;
44
+ mapping(uint256 => bool) public isAllowedRateMode;
45
+
46
+ // borrow(address,uint256,uint256,uint16,address)
47
+ // VERIFY: keccak256("borrow(address,uint256,uint256,uint16,address)")[0:4] == 0xa415bcad
48
+ bytes4 private constant SEL_BORROW = 0xa415bcad;
49
+
50
+ /// @param aavePool Aave V3 Pool proxy address
51
+ /// @param allowedAssets Assets the agent may borrow
52
+ /// @param maxBorrowAmount Per-call borrow cap in asset base units
53
+ /// @param allowedRateModes Interest rate modes allowed (2 = variable; use [2] for V3.1+)
54
+ constructor(
55
+ address aavePool,
56
+ address[] memory allowedAssets,
57
+ uint256 maxBorrowAmount,
58
+ uint256[] memory allowedRateModes
59
+ ) {
60
+ AAVE_POOL = aavePool;
61
+ MAX_BORROW_AMOUNT = maxBorrowAmount;
62
+ for (uint256 i = 0; i < allowedAssets.length; i++) {
63
+ isAllowedAsset[allowedAssets[i]] = true;
64
+ }
65
+ for (uint256 i = 0; i < allowedRateModes.length; i++) {
66
+ isAllowedRateMode[allowedRateModes[i]] = true;
67
+ }
68
+ }
69
+
70
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
71
+ if (ctx.target != AAVE_POOL) return false;
72
+ if (ctx.selector != SEL_BORROW) return false;
73
+ // borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf)
74
+ // = 5 ABI-encoded 32-byte slots after the 4-byte selector
75
+ if (txData.length < 4 + 5 * 32) return false;
76
+
77
+ (
78
+ address asset,
79
+ uint256 amount,
80
+ uint256 interestRateMode,
81
+ /* uint16 referralCode — not bounded */,
82
+ address onBehalfOf
83
+ ) = abi.decode(txData[4:], (address, uint256, uint256, uint16, address));
84
+
85
+ if (!isAllowedAsset[asset]) return false;
86
+ if (amount > MAX_BORROW_AMOUNT) return false;
87
+ if (onBehalfOf != ctx.account) return false; // agent borrows only for the SMA
88
+ if (!isAllowedRateMode[interestRateMode]) return false;
89
+
90
+ return true;
91
+ }
92
+
93
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
94
+ }
@@ -0,0 +1,143 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Protocol : GMX V2 (gmx-synthetics)
6
+ // Version : ExchangeRouter / OrderHandler — fully on-chain oracle execution
7
+ // NOT Hyperliquid (off-chain order book — permissions cannot bound orders)
8
+ // Chain : Arbitrum mainnet
9
+ // Target : ExchangeRouter 0x7c68c7866a64fa2160f78eeae12217ffbf871fa8
10
+ // (verify on Arbiscan — GMX may redeploy; check their official docs)
11
+ //
12
+ // ENFORCED ON-CHAIN (via kernel evaluate() on every dispatch):
13
+ // createOrder(CreateOrderParams params) selector 0x414577b7
14
+ // • target must be EXCHANGE_ROUTER
15
+ // • market must be in ALLOWED_MARKETS
16
+ // • initialCollateralDeltaAmount ≤ MAX_COLLATERAL_AMOUNT
17
+ // • sizeDeltaUsd ≤ MAX_SIZE_DELTA_USD
18
+ // • isLong must be in ALLOWED_DIRECTIONS (true=long, false=short, or both)
19
+ //
20
+ // NOT ENFORCED — documented limitations:
21
+ // • Leverage ratio: sizeDeltaUsd vs collateralDeltaAmount are bounded separately
22
+ // but their ratio (effective leverage) is not directly enforced here because
23
+ // it depends on collateral price. Add a price-oracle leverage check if needed.
24
+ // • acceptablePrice / triggerPrice: not bounded — agent controls entry price.
25
+ // Add bounds if the strategy requires a price range check.
26
+ // • decreasePositionSwapType, shouldUnwrapNativeToken, autoCancel: not bounded.
27
+ // • swapPath (inside CreateOrderParamAddresses): not bounded — any intermediate
28
+ // tokens in the swap path are allowed. Restrict if needed.
29
+ // • receiver address: not bounded — set to ctx.account in your agent.
30
+ //
31
+ // STRUCT LAYOUT NOTE:
32
+ // This contract defines CreateOrderParams inline. It must match EXACTLY the
33
+ // struct layout in the deployed ExchangeRouter's IBaseOrderUtils. If GMX
34
+ // updates the struct (e.g. adds a field), this permission will misparse calldata
35
+ // and return false (fail closed — safe but non-functional).
36
+ // VERIFY against BaseOrderUtils.sol at:
37
+ // https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/order/BaseOrderUtils.sol
38
+ //
39
+ // VERIFY BEFORE USE:
40
+ // • Confirm ExchangeRouter address on Arbitrum (0x7c68... — verify on Arbiscan).
41
+ // • Selector 0x414577b7 = createOrder(IBaseOrderUtils.CreateOrderParams).
42
+ // Verify against the deployed contract's ABI tab on Arbiscan.
43
+ // • sizeDeltaUsd is in USD with 30 decimals (GMX V2 standard). E.g. $1000 = 1e33.
44
+ // • initialCollateralDeltaAmount is in collateral token base units.
45
+ // • Test with real calldata samples from GMX V2 on Arbitrum testnet before mainnet.
46
+ // ─────────────────────────────────────────────────────────────────────────────
47
+
48
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
49
+
50
+ contract BoundedPerp_GMXv2_Arbitrum is IPermission {
51
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedPerp_GMXv2_Arbitrum");
52
+
53
+ address public immutable EXCHANGE_ROUTER;
54
+ mapping(address => bool) public isAllowedMarket;
55
+ uint256 public immutable MAX_COLLATERAL_AMOUNT;
56
+ /// @dev sizeDeltaUsd uses GMX V2's 30-decimal USD representation. 1 USD = 1e30.
57
+ uint256 public immutable MAX_SIZE_DELTA_USD;
58
+ bool public immutable ALLOW_LONG;
59
+ bool public immutable ALLOW_SHORT;
60
+
61
+ // createOrder(IBaseOrderUtils.CreateOrderParams)
62
+ // VERIFY: keccak256("createOrder(...)")[0:4] == 0x414577b7 on deployed ExchangeRouter
63
+ bytes4 private constant SEL_CREATE_ORDER = 0x414577b7;
64
+
65
+ // ── Inline struct definitions — MUST match IBaseOrderUtils.CreateOrderParams ──
66
+ // Verify against:
67
+ // https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/order/BaseOrderUtils.sol
68
+
69
+ struct CreateOrderParamAddresses {
70
+ address receiver;
71
+ address callbackContract;
72
+ address uiFeeReceiver;
73
+ address market;
74
+ address initialCollateralToken;
75
+ address[] swapPath; // dynamic — makes this struct dynamic
76
+ }
77
+
78
+ struct CreateOrderParamNumbers {
79
+ uint256 sizeDeltaUsd;
80
+ uint256 initialCollateralDeltaAmount;
81
+ uint256 triggerPrice;
82
+ uint256 acceptablePrice;
83
+ uint256 executionFee;
84
+ uint256 callbackGasLimit;
85
+ uint256 minOutputAmount;
86
+ uint256 validFromTime;
87
+ }
88
+
89
+ struct CreateOrderParams {
90
+ CreateOrderParamAddresses addresses;
91
+ CreateOrderParamNumbers numbers;
92
+ uint8 orderType;
93
+ uint8 decreasePositionSwapType;
94
+ bool isLong;
95
+ bool shouldUnwrapNativeToken;
96
+ bool autoCancel;
97
+ bytes32 referralCode;
98
+ }
99
+
100
+ /// @param exchangeRouter GMX V2 ExchangeRouter address
101
+ /// @param allowedMarkets GMX V2 market addresses the agent may trade
102
+ /// @param maxCollateralAmount Per-order collateral cap in collateral token base units
103
+ /// @param maxSizeDeltaUsd Per-order position size cap in GMX USD (30 decimals)
104
+ /// @param allowLong Whether long orders are permitted
105
+ /// @param allowShort Whether short orders are permitted
106
+ constructor(
107
+ address exchangeRouter,
108
+ address[] memory allowedMarkets,
109
+ uint256 maxCollateralAmount,
110
+ uint256 maxSizeDeltaUsd,
111
+ bool allowLong,
112
+ bool allowShort
113
+ ) {
114
+ EXCHANGE_ROUTER = exchangeRouter;
115
+ MAX_COLLATERAL_AMOUNT = maxCollateralAmount;
116
+ MAX_SIZE_DELTA_USD = maxSizeDeltaUsd;
117
+ ALLOW_LONG = allowLong;
118
+ ALLOW_SHORT = allowShort;
119
+ for (uint256 i = 0; i < allowedMarkets.length; i++) {
120
+ isAllowedMarket[allowedMarkets[i]] = true;
121
+ }
122
+ }
123
+
124
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
125
+ if (ctx.target != EXCHANGE_ROUTER) return false;
126
+ if (ctx.selector != SEL_CREATE_ORDER) return false;
127
+ if (txData.length < 4) return false;
128
+
129
+ // abi.decode handles the nested dynamic struct (address[] swapPath) correctly.
130
+ // A malformed calldata or struct layout mismatch causes a revert → false (fail closed).
131
+ CreateOrderParams memory p = abi.decode(txData[4:], (CreateOrderParams));
132
+
133
+ if (!isAllowedMarket[p.addresses.market]) return false;
134
+ if (p.numbers.initialCollateralDeltaAmount > MAX_COLLATERAL_AMOUNT) return false;
135
+ if (p.numbers.sizeDeltaUsd > MAX_SIZE_DELTA_USD) return false;
136
+ if (p.isLong && !ALLOW_LONG) return false;
137
+ if (!p.isLong && !ALLOW_SHORT) return false;
138
+
139
+ return true;
140
+ }
141
+
142
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
143
+ }
@@ -0,0 +1,113 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Protocol : Uniswap V3
6
+ // Version : SwapRouter02 (NOT the older SwapRouter — different selectors)
7
+ // Chain : Base mainnet
8
+ // Target : SwapRouter02 0x2626664c2603336E57B271c5C0b26F421741e481
9
+ //
10
+ // ENFORCED ON-CHAIN (via kernel evaluate() on every dispatch):
11
+ // exactInputSingle path (selector 0x04e45aaf):
12
+ // • target must be SWAP_ROUTER
13
+ // • tokenIn must equal FIXED_TOKEN_IN
14
+ // • tokenOut must be in ALLOWED_TOKENS_OUT
15
+ // • amountIn ≤ MAX_AMOUNT_IN
16
+ // • amountOutMinimum ≥ amountIn × MIN_BPS / 10 000 (slippage floor)
17
+ // approve path (selector 0x095ea7b3):
18
+ // • target must be FIXED_TOKEN_IN (the ERC-20 being approved)
19
+ // • spender must be SWAP_ROUTER
20
+ // • amount ≤ MAX_AMOUNT_IN
21
+ //
22
+ // NOT ENFORCED (agent code — can change without a new contract):
23
+ // • fee tier, sqrtPriceLimitX96, recipient address
24
+ // • swap frequency / cadence
25
+ //
26
+ // VERIFY BEFORE USE:
27
+ // • Confirm SwapRouter02 address on your chain (Base default shown above).
28
+ // • Selector 0x04e45aaf = exactInputSingle((address,address,uint24,address,uint256,uint256,uint160))
29
+ // on SwapRouter02. The older SwapRouter uses a different selector (0x414577b7).
30
+ // • Confirm that amountOutMinimum slippage floor fits your price-impact expectations for the
31
+ // chosen pool. Large amountIn values may trigger price impact beyond MIN_BPS.
32
+ // ─────────────────────────────────────────────────────────────────────────────
33
+
34
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
35
+
36
+ contract BoundedSwap_UniswapV3_Base is IPermission {
37
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedSwap_UniswapV3_Base");
38
+
39
+ address public immutable SWAP_ROUTER;
40
+ address public immutable FIXED_TOKEN_IN;
41
+ mapping(address => bool) public isAllowedTokenOut;
42
+ uint256 public immutable MAX_AMOUNT_IN;
43
+ /// @dev Slippage floor in basis points. 9 900 = allow at most 1% slippage.
44
+ uint256 public immutable MIN_BPS;
45
+
46
+ bytes4 private constant SEL_EXACT_INPUT_SINGLE = 0x04e45aaf;
47
+ bytes4 private constant SEL_APPROVE = 0x095ea7b3;
48
+
49
+ struct ExactInputSingleParams {
50
+ address tokenIn;
51
+ address tokenOut;
52
+ uint24 fee;
53
+ address recipient;
54
+ uint256 amountIn;
55
+ uint256 amountOutMinimum;
56
+ uint160 sqrtPriceLimitX96;
57
+ }
58
+
59
+ /// @param swapRouter SwapRouter02 address (0x2626... on Base)
60
+ /// @param fixedTokenIn The one token the agent is allowed to sell
61
+ /// @param allowedTokensOut Tokens the agent may receive
62
+ /// @param maxAmountIn Per-call spend cap in fixedTokenIn base units
63
+ /// @param minBps Minimum amountOutMinimum as fraction of amountIn ×10 000
64
+ /// e.g. 9900 → require amountOutMinimum ≥ 99% of amountIn
65
+ /// (denominated in fixedTokenIn units, not USD — set per your pair)
66
+ constructor(
67
+ address swapRouter,
68
+ address fixedTokenIn,
69
+ address[] memory allowedTokensOut,
70
+ uint256 maxAmountIn,
71
+ uint256 minBps
72
+ ) {
73
+ require(minBps <= 10_000, "minBps > 10000");
74
+ SWAP_ROUTER = swapRouter;
75
+ FIXED_TOKEN_IN = fixedTokenIn;
76
+ MAX_AMOUNT_IN = maxAmountIn;
77
+ MIN_BPS = minBps;
78
+ for (uint256 i = 0; i < allowedTokensOut.length; i++) {
79
+ isAllowedTokenOut[allowedTokensOut[i]] = true;
80
+ }
81
+ }
82
+
83
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
84
+ if (txData.length < 4) return false;
85
+
86
+ // exactInputSingle: agent swaps FIXED_TOKEN_IN for an allowed output token
87
+ if (ctx.target == SWAP_ROUTER && ctx.selector == SEL_EXACT_INPUT_SINGLE) {
88
+ if (txData.length < 4 + 7 * 32) return false;
89
+ ExactInputSingleParams memory p = abi.decode(txData[4:], (ExactInputSingleParams));
90
+ if (p.tokenIn != FIXED_TOKEN_IN) return false;
91
+ if (!isAllowedTokenOut[p.tokenOut]) return false;
92
+ if (p.amountIn > MAX_AMOUNT_IN) return false;
93
+ // Slippage floor: require amountOutMinimum ≥ amountIn * MIN_BPS / 10 000.
94
+ // This is not a USD check — it's a ratio check in tokenIn units.
95
+ // For a USDC→WETH swap, set MIN_BPS conservatively (e.g. 9 900 for 1% slippage).
96
+ if (p.amountOutMinimum < (p.amountIn * MIN_BPS) / 10_000) return false;
97
+ return true;
98
+ }
99
+
100
+ // approve: agent approves the router to spend FIXED_TOKEN_IN
101
+ if (ctx.target == FIXED_TOKEN_IN && ctx.selector == SEL_APPROVE) {
102
+ if (txData.length < 4 + 2 * 32) return false;
103
+ (address spender, uint256 amount) = abi.decode(txData[4:], (address, uint256));
104
+ if (spender != SWAP_ROUTER) return false;
105
+ if (amount > MAX_AMOUNT_IN) return false;
106
+ return true;
107
+ }
108
+
109
+ return false;
110
+ }
111
+
112
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
113
+ }
@@ -0,0 +1,144 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Protocol : Uniswap V4
6
+ // Version : Universal Router + PoolManager (V4 singleton)
7
+ // NOTE: V4 is NOT the same as V3. Calldata encoding is completely
8
+ // different — do NOT adapt a V3 permission for V4.
9
+ // Chain : Unichain mainnet
10
+ // Target : Universal Router 0xef740bf23acae26f6492b10de645d6b98dc8eaf3
11
+ // (verify on Uniscan before use)
12
+ //
13
+ // ENFORCED ON-CHAIN (via kernel evaluate() on every dispatch):
14
+ // execute(bytes,bytes[]) or execute(bytes,bytes[],uint256):
15
+ // • target must be UNIVERSAL_ROUTER
16
+ // • first command byte (masking the allow-failure MSB) must be V4_SWAP (0x10)
17
+ // • exactly one command (single-swap path — disallow multi-hop command strings)
18
+ // • V4 action inside must be SWAP_EXACT_IN_SINGLE (0x00)
19
+ // • tokenIn (from poolKey, derived by zeroForOne) must be FIXED_CURRENCY_IN
20
+ // • tokenOut must be in ALLOWED_CURRENCIES_OUT
21
+ // • amountIn ≤ MAX_AMOUNT_IN
22
+ // • amountOutMinimum ≥ amountIn × MIN_BPS / 10 000
23
+ //
24
+ // NOT ENFORCED — documented limitations:
25
+ // • hookData is not inspected (hooks can alter swap behavior on-chain; if the
26
+ // pool uses a hook that significantly changes execution, this permission cannot
27
+ // constrain it. Deploy against pools with address(0) hooks or audited hooks only.)
28
+ // • fee tier and tickSpacing within the PoolKey are not constrained here
29
+ // (add pool-key checks if you want to restrict to a specific pool)
30
+ // • The ALL_CURRENCY_PAIR constant (FIXED_CURRENCY_IN, allowedCurrenciesOut) does
31
+ // not constrain which pool is used when multiple pools share the same currency pair
32
+ //
33
+ // VERIFY BEFORE USE:
34
+ // • Confirm Universal Router address on Unichain (shown above; verify on Uniscan).
35
+ // • V4_SWAP command byte = 0x10, SWAP_EXACT_IN_SINGLE action = 0x00 — verify
36
+ // against deployed UniversalRouter and V4Router on Unichain if contract is updated.
37
+ // • PoolKey struct layout (currency0, currency1, fee, tickSpacing, hooks) must
38
+ // match the deployed PoolManager on Unichain. If layout changes, update struct.
39
+ // • hookData is not bounded. Only use with unhookyed pools or audited, bounded hooks.
40
+ // • Calldata revert = false (kernel treats revert as denial) — malformed inputs
41
+ // are safely rejected, but verify with actual calldata samples before deployment.
42
+ // ─────────────────────────────────────────────────────────────────────────────
43
+
44
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
45
+
46
+ contract BoundedSwap_UniswapV4_Unichain is IPermission {
47
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedSwap_UniswapV4_Unichain");
48
+
49
+ address public immutable UNIVERSAL_ROUTER;
50
+ address public immutable FIXED_CURRENCY_IN;
51
+ mapping(address => bool) public isAllowedCurrencyOut;
52
+ uint256 public immutable MAX_AMOUNT_IN;
53
+ uint256 public immutable MIN_BPS;
54
+
55
+ // execute(bytes,bytes[],uint256) — with deadline
56
+ bytes4 private constant SEL_EXECUTE_DEADLINE = 0x3593564c;
57
+ // execute(bytes,bytes[]) — without deadline
58
+ bytes4 private constant SEL_EXECUTE = 0x24856bc3;
59
+ // Universal Router command byte for V4_SWAP
60
+ uint8 private constant CMD_V4_SWAP = 0x10;
61
+ // Bit mask to strip the "allow failure" MSB from a command byte
62
+ uint8 private constant CMD_MASK = 0x3f;
63
+ // V4Router action: SWAP_EXACT_IN_SINGLE
64
+ uint8 private constant ACT_SWAP_EXACT_IN_SINGLE = 0x00;
65
+
66
+ // PoolKey layout must match the deployed V4 PoolManager on Unichain
67
+ struct PoolKey {
68
+ address currency0; // Currency — address type in V4
69
+ address currency1;
70
+ uint24 fee;
71
+ int24 tickSpacing;
72
+ address hooks; // IHooks — address(0) for unhookyed pools
73
+ }
74
+
75
+ struct ExactInputSingleParams {
76
+ PoolKey poolKey;
77
+ bool zeroForOne;
78
+ uint128 amountIn;
79
+ uint128 amountOutMinimum;
80
+ bytes hookData; // not inspected — see limitations header
81
+ }
82
+
83
+ constructor(
84
+ address universalRouter,
85
+ address fixedCurrencyIn,
86
+ address[] memory allowedCurrenciesOut,
87
+ uint256 maxAmountIn,
88
+ uint256 minBps
89
+ ) {
90
+ require(minBps <= 10_000, "minBps > 10000");
91
+ UNIVERSAL_ROUTER = universalRouter;
92
+ FIXED_CURRENCY_IN = fixedCurrencyIn;
93
+ MAX_AMOUNT_IN = maxAmountIn;
94
+ MIN_BPS = minBps;
95
+ for (uint256 i = 0; i < allowedCurrenciesOut.length; i++) {
96
+ isAllowedCurrenciesOut[allowedCurrenciesOut[i]] = true;
97
+ }
98
+ }
99
+
100
+ mapping(address => bool) private isAllowedCurrenciesOut;
101
+
102
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
103
+ if (ctx.target != UNIVERSAL_ROUTER) return false;
104
+ if (ctx.selector != SEL_EXECUTE_DEADLINE && ctx.selector != SEL_EXECUTE) return false;
105
+ if (txData.length < 4) return false;
106
+
107
+ // Decode the execute call. Both overloads start with (bytes commands, bytes[] inputs).
108
+ // abi.decode ignores trailing fields, so decoding as (bytes, bytes[]) works for both.
109
+ (bytes memory commands, bytes[] memory inputs) = abi.decode(txData[4:], (bytes, bytes[]));
110
+
111
+ // Enforce: exactly one command, and it must be V4_SWAP
112
+ if (commands.length != 1) return false;
113
+ if ((uint8(commands[0]) & CMD_MASK) != CMD_V4_SWAP) return false;
114
+ if (inputs.length != 1) return false;
115
+
116
+ // Decode the V4 router call (actions + per-action params)
117
+ (bytes memory v4Actions, bytes[] memory v4Params) =
118
+ abi.decode(inputs[0], (bytes, bytes[]));
119
+
120
+ // Enforce: exactly one V4 action, and it must be SWAP_EXACT_IN_SINGLE
121
+ if (v4Actions.length != 1) return false;
122
+ if (uint8(v4Actions[0]) != ACT_SWAP_EXACT_IN_SINGLE) return false;
123
+ if (v4Params.length != 1) return false;
124
+
125
+ // Decode ExactInputSingleParams from the action param.
126
+ // hookData is a dynamic bytes field — revert here means false (fail closed).
127
+ ExactInputSingleParams memory p = abi.decode(v4Params[0], (ExactInputSingleParams));
128
+
129
+ // Derive tokenIn and tokenOut from the PoolKey and zeroForOne flag.
130
+ // In V4, currency0 < currency1 (sorted by address). zeroForOne = true means
131
+ // trading currency0 for currency1.
132
+ address tokenIn = p.zeroForOne ? p.poolKey.currency0 : p.poolKey.currency1;
133
+ address tokenOut = p.zeroForOne ? p.poolKey.currency1 : p.poolKey.currency0;
134
+
135
+ if (tokenIn != FIXED_CURRENCY_IN) return false;
136
+ if (!isAllowedCurrenciesOut[tokenOut]) return false;
137
+ if (p.amountIn > MAX_AMOUNT_IN) return false;
138
+ if (p.amountOutMinimum < (uint256(p.amountIn) * MIN_BPS) / 10_000) return false;
139
+
140
+ return true;
141
+ }
142
+
143
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
144
+ }
@@ -0,0 +1,73 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Protocol : ERC-20
6
+ // Version : Standard ERC-20 (version-agnostic)
7
+ // Chain : Ethereum mainnet (works on any EVM — the most general example)
8
+ //
9
+ // ENFORCED ON-CHAIN (via kernel evaluate() on every dispatch):
10
+ // transfer(address to, uint256 amount)
11
+ // • target must be in ALLOWED_TOKENS
12
+ // • recipient (to) must be in ALLOWED_RECIPIENTS
13
+ // • amount ≤ MAX_AMOUNT_PER_TRANSFER
14
+ //
15
+ // NOT ENFORCED (agent code — can change without a new contract):
16
+ // • transfer frequency / timing
17
+ // • choice of token within ALLOWED_TOKENS
18
+ // • choice of recipient within ALLOWED_RECIPIENTS
19
+ //
20
+ // VERIFY BEFORE USE:
21
+ // • Selector 0xa9059cbb = transfer(address,uint256) — universally standard.
22
+ // • ALLOWED_TOKENS prevents the agent from transferring tokens not in the set.
23
+ // If a protocol uses non-standard transfer methods (e.g. transferFrom or
24
+ // proprietary hooks), add separate selector entries.
25
+ // • MAX_AMOUNT_PER_TRANSFER is denominated in the token's base units.
26
+ // Different tokens have different decimals (USDC = 6, WETH = 18).
27
+ // Set one permission per token if amounts differ across tokens.
28
+ // ─────────────────────────────────────────────────────────────────────────────
29
+
30
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
31
+
32
+ contract BoundedTransfer_ERC20_Ethereum is IPermission {
33
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedTransfer_ERC20_Ethereum");
34
+
35
+ mapping(address => bool) public isAllowedToken;
36
+ mapping(address => bool) public isAllowedRecipient;
37
+ uint256 public immutable MAX_AMOUNT_PER_TRANSFER;
38
+
39
+ // transfer(address,uint256)
40
+ bytes4 private constant SEL_TRANSFER = 0xa9059cbb;
41
+
42
+ /// @param allowedTokens ERC-20 contracts the agent may transfer from
43
+ /// @param allowedRecipients Addresses the agent may send to
44
+ /// @param maxAmountPerTransfer Per-call amount cap (in token base units)
45
+ constructor(
46
+ address[] memory allowedTokens,
47
+ address[] memory allowedRecipients,
48
+ uint256 maxAmountPerTransfer
49
+ ) {
50
+ MAX_AMOUNT_PER_TRANSFER = maxAmountPerTransfer;
51
+ for (uint256 i = 0; i < allowedTokens.length; i++) {
52
+ isAllowedToken[allowedTokens[i]] = true;
53
+ }
54
+ for (uint256 i = 0; i < allowedRecipients.length; i++) {
55
+ isAllowedRecipient[allowedRecipients[i]] = true;
56
+ }
57
+ }
58
+
59
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
60
+ if (!isAllowedToken[ctx.target]) return false;
61
+ if (ctx.selector != SEL_TRANSFER) return false;
62
+ if (txData.length < 4 + 2 * 32) return false;
63
+
64
+ (address to, uint256 amount) = abi.decode(txData[4:], (address, uint256));
65
+
66
+ if (!isAllowedRecipient[to]) return false;
67
+ if (amount > MAX_AMOUNT_PER_TRANSFER) return false;
68
+
69
+ return true;
70
+ }
71
+
72
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
73
+ }
@@ -0,0 +1,52 @@
1
+ # Permission Examples
2
+
3
+ These are example permission contracts for common DeFi protocols, maintained by Sailor.
4
+
5
+ **They are not part of Sail Protocol. They are not audited by Sail. They are not a supported
6
+ or exhaustive set.** The protocol accepts any contract implementing IPermission — these examples
7
+ teach the bounding pattern for specific protocols so you (and your AI agent) can adapt them or
8
+ write your own.
9
+
10
+ ## Permissions are only as strong as the protocol is on-chain
11
+
12
+ A permission is evaluated by the kernel on every dispatch — but it can only see what happens
13
+ on-chain. For venues with off-chain order matching (e.g. Polymarket, Hyperliquid), a permission
14
+ can constrain deposits, withdrawals, and sub-accounts, but NOT the orders your agent signs
15
+ off-chain. Prefer fully on-chain venues — Uniswap, Aave, GMX, Synthetix, Limitless — where every
16
+ action passes through the kernel and your bounds actually hold.
17
+
18
+ ## Permissions are protocol- and version-specific
19
+
20
+ Calldata differs by protocol and by version. A Uniswap V3 swap is a different decode than a
21
+ Uniswap V4 swap. Use the example closest to YOUR exact protocol+version+chain, verify the decode
22
+ against the protocol's real ABI, and confirm what it enforces before deploying.
23
+
24
+ You own what you deploy.
25
+
26
+ ---
27
+
28
+ ## Examples
29
+
30
+ | File | Protocol | Version | Chain | Status |
31
+ |---|---|---|---|---|
32
+ | `BoundedSwap_UniswapV3_Base.sol` | Uniswap Swap | V3 SwapRouter02 | Base | Full decode |
33
+ | `BoundedSwap_UniswapV4_Unichain.sol` | Uniswap Swap | V4 Universal Router | Unichain | Partial decode — see header |
34
+ | `BoundedBorrow_AaveV3_Arbitrum.sol` | Aave Borrow | V3 Pool | Arbitrum | Full decode — verify selector |
35
+ | `BoundedTransfer_ERC20_Ethereum.sol` | ERC-20 Transfer | — | Ethereum (any EVM) | Full decode |
36
+ | `BoundedPerp_GMXv2_Arbitrum.sol` | GMX Perpetuals | V2 ExchangeRouter | Arbitrum | Partial decode — see header |
37
+ | `BoundedBet_Limitless_Base.sol` | Limitless Prediction | CTF Exchange | Base | UNVERIFIED ABI — see header |
38
+
39
+ ## Using these examples
40
+
41
+ Each file is self-contained and explains in its header exactly what is and is not enforced.
42
+ Read the header before deploying.
43
+
44
+ To compile:
45
+ ```bash
46
+ forge build
47
+ ```
48
+
49
+ To deploy within a Sailor project (copy the .sol file to `mandates/` first):
50
+ ```bash
51
+ sailor mandate deploy --contract <Name> --args '[...]' --attach --sma <SMA>
52
+ ```
@@ -0,0 +1,10 @@
1
+ [profile.default]
2
+ src = "."
3
+ out = "out"
4
+ libs = ["lib"]
5
+ remappings = ["@sail/interfaces/=interfaces/"]
6
+ solc = "0.8.26"
7
+ optimizer = true
8
+ optimizer_runs = 200
9
+ # Examples compile with: forge build (from this directory)
10
+ # Deploy within a Sailor project using: sailor mandate deploy --contract <Name> --args '[...]'
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ struct Context {
5
+ address account;
6
+ address manager;
7
+ address submitter;
8
+ address target;
9
+ bytes4 selector;
10
+ uint256 value;
11
+ uint256 blockTimestamp;
12
+ uint256 blockNumber;
13
+ }
14
+
15
+ interface IPermission {
16
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool);
17
+ function discriminator() external view returns (bytes32);
18
+ }