@dev.sail.money/sailor 0.1.0-local → 1.0.0-39

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 (153) hide show
  1. package/AGENTS.md +139 -140
  2. package/LICENSE +21 -21
  3. package/README.md +428 -430
  4. package/docs/PERMISSION_MODEL.md +93 -93
  5. package/examples/permissions/BoundedApproveAndCallBatch.sol +179 -179
  6. package/examples/permissions/BoundedBet_Limitless_Base.sol +97 -97
  7. package/examples/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +94 -94
  8. package/examples/permissions/BoundedPerp_GMXv2_Arbitrum.sol +154 -154
  9. package/examples/permissions/BoundedStake_Venice_Base.sol +85 -85
  10. package/examples/permissions/BoundedSupply_AaveV3_Arbitrum.sol +82 -82
  11. package/examples/permissions/BoundedSwap_UniswapV3_Base.sol +116 -116
  12. package/examples/permissions/BoundedSwap_UniswapV4_Unichain.sol +150 -150
  13. package/examples/permissions/BoundedTransfer_ERC20_Ethereum.sol +73 -73
  14. package/examples/permissions/BoundedVault_ERC4626_Base.sol +97 -97
  15. package/examples/permissions/README.md +79 -79
  16. package/examples/permissions/SailCalldata.sol +118 -118
  17. package/examples/permissions/foundry.toml +10 -10
  18. package/examples/permissions/interfaces/IBatchPermission.sol +38 -38
  19. package/examples/permissions/interfaces/IPermission.sol +18 -18
  20. package/package.json +44 -45
  21. package/packages/cli/README.md +34 -34
  22. package/packages/cli/dist/index.cjs +734 -705
  23. package/packages/cli/dist/server.cjs +627 -538
  24. package/packages/sdk/README.md +65 -65
  25. package/packages/sdk/dist/intelligence.d.ts +1 -1
  26. package/packages/sdk/dist/intelligence.js +1 -1
  27. package/packages/sdk/package.json +80 -80
  28. package/packages/ui/dist/assets/{add-BxpXfVWe.js → add-Gzf62xlX.js} +1 -1
  29. package/packages/ui/dist/assets/{all-wallets-BKTn_sWK.js → all-wallets-O-pI4o8v.js} +1 -1
  30. package/packages/ui/dist/assets/{app-store-CfuKbwxR.js → app-store-CeSLaOaQ.js} +1 -1
  31. package/packages/ui/dist/assets/{apple-BKSBbNYg.js → apple-FGNyQM-D.js} +1 -1
  32. package/packages/ui/dist/assets/{arrow-bottom-D4bG6gZi.js → arrow-bottom-C1fusORF.js} +1 -1
  33. package/packages/ui/dist/assets/{arrow-bottom-circle-BNTs1p0T.js → arrow-bottom-circle-AvK1VEpN.js} +1 -1
  34. package/packages/ui/dist/assets/{arrow-left-2uee3vYv.js → arrow-left-Bu-hq4Ep.js} +1 -1
  35. package/packages/ui/dist/assets/{arrow-right-BktjMV6h.js → arrow-right-XbZESmct.js} +1 -1
  36. package/packages/ui/dist/assets/{arrow-top-Izu28fX4.js → arrow-top-DvkVHbhX.js} +1 -1
  37. package/packages/ui/dist/assets/{bank-USBaAyFM.js → bank-DTThWRvC.js} +1 -1
  38. package/packages/ui/dist/assets/{basic-C_9KjTEH.js → basic-B9AMgqFE.js} +1 -1
  39. package/packages/ui/dist/assets/{browser-DAEMAKV7.js → browser-Bhnivm4i.js} +1 -1
  40. package/packages/ui/dist/assets/{card-DT8yDkKN.js → card-DjIlyU55.js} +1 -1
  41. package/packages/ui/dist/assets/{ccip-CkqfGSxX.js → ccip-DPAiKntc.js} +1 -1
  42. package/packages/ui/dist/assets/{checkmark-CsgdEXFj.js → checkmark-DSVYfoVl.js} +1 -1
  43. package/packages/ui/dist/assets/{checkmark-bold-D2gjOQo2.js → checkmark-bold-BFkw_Q5g.js} +1 -1
  44. package/packages/ui/dist/assets/{chevron-bottom-tprFynYV.js → chevron-bottom-CyCgyOwY.js} +1 -1
  45. package/packages/ui/dist/assets/{chevron-left-D2Zj1gNB.js → chevron-left-DTuO2WLr.js} +1 -1
  46. package/packages/ui/dist/assets/{chevron-right-D1rRuAVe.js → chevron-right-DwB5FZj8.js} +1 -1
  47. package/packages/ui/dist/assets/{chevron-top-24dL1mbL.js → chevron-top-DKukdWvg.js} +1 -1
  48. package/packages/ui/dist/assets/{chrome-store-Vy-5niYX.js → chrome-store-Csz4L9Ls.js} +1 -1
  49. package/packages/ui/dist/assets/{clock-qBjLnVdJ.js → clock-Bg6488Gw.js} +1 -1
  50. package/packages/ui/dist/assets/{close-DARDwgcu.js → close-BxAJGBxP.js} +1 -1
  51. package/packages/ui/dist/assets/{coinPlaceholder-BvpIbPlD.js → coinPlaceholder-CCJVgW9w.js} +1 -1
  52. package/packages/ui/dist/assets/{compass-BMTO0ayt.js → compass-CSQSZaqJ.js} +1 -1
  53. package/packages/ui/dist/assets/{copy-PaXeRHza.js → copy-CqlzXVB-.js} +1 -1
  54. package/packages/ui/dist/assets/{core-BFnStQd-.js → core-ClvdTrpG.js} +3 -3
  55. package/packages/ui/dist/assets/cursor-CKKwWhGQ.js +3 -0
  56. package/packages/ui/dist/assets/{cursor-transparent-BEMdi-8q.js → cursor-transparent-C1VOGz11.js} +1 -1
  57. package/packages/ui/dist/assets/{desktop-CfuLLThw.js → desktop-QiLednKV.js} +1 -1
  58. package/packages/ui/dist/assets/{disconnect-DhwgJMiR.js → disconnect-Bx2TgkML.js} +1 -1
  59. package/packages/ui/dist/assets/{discord-po8qoN1s.js → discord-6MWX5Rbb.js} +1 -1
  60. package/packages/ui/dist/assets/{etherscan-BEsz0_yx.js → etherscan-CodIrmJK.js} +1 -1
  61. package/packages/ui/dist/assets/{events-Bz33Unzu.js → events-DOEm-LTy.js} +1 -1
  62. package/packages/ui/dist/assets/{exclamation-triangle-7CjTAGOQ.js → exclamation-triangle-Dwr5oCsh.js} +1 -1
  63. package/packages/ui/dist/assets/{extension-CmxjEWEt.js → extension-C-SoZx1s.js} +1 -1
  64. package/packages/ui/dist/assets/{external-link-CmQ--bNS.js → external-link-BiDYH90C.js} +1 -1
  65. package/packages/ui/dist/assets/{facebook-CIBn9b65.js → facebook-Bm27AlfS.js} +1 -1
  66. package/packages/ui/dist/assets/{fallback-DATyrQlb.js → fallback-Bwpmpy13.js} +1 -1
  67. package/packages/ui/dist/assets/{farcaster-OJ3Jasxg.js → farcaster-CSW-SjzS.js} +1 -1
  68. package/packages/ui/dist/assets/{filters-D4x09zeL.js → filters-j3dR7AJK.js} +1 -1
  69. package/packages/ui/dist/assets/{github-ZlIuMArp.js → github-CQMTSSgW.js} +1 -1
  70. package/packages/ui/dist/assets/{google-Gwg85sfv.js → google-BBIVBfAd.js} +1 -1
  71. package/packages/ui/dist/assets/{help-circle-D1uOWYcX.js → help-circle-CEvTLelF.js} +1 -1
  72. package/packages/ui/dist/assets/{id-C0-5UdYk.js → id-CYRVgSgN.js} +1 -1
  73. package/packages/ui/dist/assets/{image-D_DUsv8-.js → image-Cm9Ep5G0.js} +1 -1
  74. package/packages/ui/dist/assets/{index-DdbJhIdl.js → index-4wdo7Ga_.js} +3 -3
  75. package/packages/ui/dist/assets/{index-CrYzBWfD.js → index-BrP8m1ZI.js} +1 -1
  76. package/packages/ui/dist/assets/index-C2PQCECq.css +1 -0
  77. package/packages/ui/dist/assets/{index-DiojfeVM.js → index-DZ07nuwB.js} +1 -1
  78. package/packages/ui/dist/assets/{index-BCzex_R6.js → index-De_P6mNS.js} +1 -1
  79. package/packages/ui/dist/assets/index-DrQ9A8dp.js +1775 -0
  80. package/packages/ui/dist/assets/{index-izd7vu_r.js → index-Z55BVE94.js} +1 -1
  81. package/packages/ui/dist/assets/{index.es-DdkHhQAj.js → index.es-DnT9Uzwt.js} +4 -4
  82. package/packages/ui/dist/assets/{info-CiRd_kEG.js → info-DdYqiFMu.js} +1 -1
  83. package/packages/ui/dist/assets/{info-circle-ypxjqarK.js → info-circle-DkD9oY-S.js} +1 -1
  84. package/packages/ui/dist/assets/{lightbulb-B-pxLxd8.js → lightbulb-7Q3AhpSP.js} +1 -1
  85. package/packages/ui/dist/assets/{mail-BYmicuVZ.js → mail-CPagdnfp.js} +1 -1
  86. package/packages/ui/dist/assets/{metamask-sdk-Ccl6DG7Q.js → metamask-sdk-CQ4tzR6A.js} +1 -1
  87. package/packages/ui/dist/assets/{mobile-CtP5PqVT.js → mobile-01GVSpey.js} +1 -1
  88. package/packages/ui/dist/assets/{more-6C2733we.js → more-BPXPYrvy.js} +1 -1
  89. package/packages/ui/dist/assets/{network-placeholder-CdhxMzqd.js → network-placeholder-CII8WrTF.js} +1 -1
  90. package/packages/ui/dist/assets/{nftPlaceholder-DVmTWEAY.js → nftPlaceholder-DG5rjRzx.js} +1 -1
  91. package/packages/ui/dist/assets/{off-DNYLughs.js → off-eemo7R2q.js} +1 -1
  92. package/packages/ui/dist/assets/{parseSignature-Dq2B5Bu3.js → parseSignature-CaRSntRi.js} +1 -1
  93. package/packages/ui/dist/assets/{play-store-D7Qut5ta.js → play-store-SIqMwLur.js} +1 -1
  94. package/packages/ui/dist/assets/{plus-kqMyjt3q.js → plus-DemTM2Nx.js} +1 -1
  95. package/packages/ui/dist/assets/{qr-code-DiUCWRbz.js → qr-code-BjolKhQv.js} +1 -1
  96. package/packages/ui/dist/assets/{recycle-horizontal-Boe3XiS-.js → recycle-horizontal-BluxSqWj.js} +1 -1
  97. package/packages/ui/dist/assets/{refresh-CrBgBQYO.js → refresh-Cto5auO0.js} +1 -1
  98. package/packages/ui/dist/assets/{reown-logo-CFZCCHSx.js → reown-logo-lrWmaeNj.js} +1 -1
  99. package/packages/ui/dist/assets/{search-ChTDrghU.js → search-SNmrxLL7.js} +1 -1
  100. package/packages/ui/dist/assets/{secp256k1-DAV5Q_FR.js → secp256k1-SI0Bxirn.js} +1 -1
  101. package/packages/ui/dist/assets/{send-DLFbBFe1.js → send-Do8kdKTu.js} +1 -1
  102. package/packages/ui/dist/assets/{swapHorizontal-BEs3emfG.js → swapHorizontal-HBP1koQV.js} +1 -1
  103. package/packages/ui/dist/assets/{swapHorizontalBold-CC-Hfa7W.js → swapHorizontalBold-B9g1LqXn.js} +1 -1
  104. package/packages/ui/dist/assets/{swapHorizontalMedium-BmR0H8DC.js → swapHorizontalMedium-C8JebI_2.js} +1 -1
  105. package/packages/ui/dist/assets/{swapHorizontalRoundedBold-BdP5NGIH.js → swapHorizontalRoundedBold-37eEYoAp.js} +1 -1
  106. package/packages/ui/dist/assets/{swapVertical-CPrGEJPY.js → swapVertical-DmacpIGs.js} +1 -1
  107. package/packages/ui/dist/assets/{telegram-CxNoZ80Q.js → telegram-Dq_CUch4.js} +1 -1
  108. package/packages/ui/dist/assets/{three-dots-BRa6SBpL.js → three-dots-DbkqGUCU.js} +1 -1
  109. package/packages/ui/dist/assets/{twitch-BC338bG5.js → twitch-iG0Ncwwy.js} +1 -1
  110. package/packages/ui/dist/assets/{twitterIcon-BGZmt2i9.js → twitterIcon-CNbKQx87.js} +1 -1
  111. package/packages/ui/dist/assets/{verify-CEstW0zw.js → verify-BfXT7L3L.js} +1 -1
  112. package/packages/ui/dist/assets/{verify-filled-OkZb0weU.js → verify-filled-BxqxA6xc.js} +1 -1
  113. package/packages/ui/dist/assets/{w3m-modal-pS09ECwE.js → w3m-modal-DeDYqwYJ.js} +1 -1
  114. package/packages/ui/dist/assets/{wallet-BXVKCgC9.js → wallet-BXsUR9Tj.js} +1 -1
  115. package/packages/ui/dist/assets/{wallet-placeholder-C_kNhB1c.js → wallet-placeholder-bbWbfkZu.js} +1 -1
  116. package/packages/ui/dist/assets/{walletconnect-CRKIuUHH.js → walletconnect-WsTWE17z.js} +1 -1
  117. package/packages/ui/dist/assets/{warning-circle-DB2NnwlJ.js → warning-circle-cNSUigh6.js} +1 -1
  118. package/packages/ui/dist/assets/{x-DT4RmwL5.js → x-gNtNGE0N.js} +1 -1
  119. package/packages/ui/dist/index.html +14 -14
  120. package/scripts/check-docs.mjs +262 -262
  121. package/scripts/check-init.mjs +108 -108
  122. package/templates/custom-mandate/.sail/contracts/interfaces/IPermission.sol +18 -18
  123. package/templates/custom-mandate/README.md +116 -116
  124. package/templates/custom-mandate/foundry.toml +8 -8
  125. package/templates/custom-mandate/mandates/BoundedCallPermission.sol +41 -41
  126. package/templates/custom-mandate/mandates/README.md +16 -16
  127. package/templates/custom-mandate/mandates/SailCalldata.sol +118 -118
  128. package/templates/default/.cursor/rules +25 -25
  129. package/templates/default/.env.example +20 -20
  130. package/templates/default/.github/workflows/agent-tick.yml +33 -33
  131. package/templates/default/.sail/README.md +13 -13
  132. package/templates/default/.sail/config.json +10 -10
  133. package/templates/default/AGENTS.md +171 -171
  134. package/templates/default/CLAUDE.md +2 -2
  135. package/templates/default/README.md +16 -16
  136. package/templates/default/_gitignore +13 -13
  137. package/templates/default/docs/PERMISSION_MODEL.md +93 -93
  138. package/templates/default/examples/dca/README.md +16 -16
  139. package/templates/default/examples/dca/agent.ts +174 -174
  140. package/templates/default/examples/dca/mandate.ts +45 -45
  141. package/templates/default/package.json +17 -17
  142. package/templates/default/src/agent.ts +37 -37
  143. package/templates/default/src/config.ts +24 -24
  144. package/templates/default/src/mandate.ts +22 -22
  145. package/templates/default/tsconfig.json +17 -17
  146. package/templates/default/ui/README.md +3 -3
  147. package/templates/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +84 -84
  148. package/templates/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +97 -97
  149. package/templates/lifi-permissions/README.md +53 -53
  150. package/packages/ui/dist/assets/cursor-BDvw-B17.js +0 -3
  151. package/packages/ui/dist/assets/index-BUhrHLpY.js +0 -1775
  152. package/packages/ui/dist/assets/index-Cq02kQmy.css +0 -1
  153. package/scripts/postinstall.js +0 -81
@@ -1,97 +1,97 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.26;
3
-
4
- // ─────────────────────────────────────────────────────────────────────────────
5
- // Protocol : Limitless
6
- // Version : CTF-based prediction market (on-chain settlement on Base)
7
- // NOT Polymarket (Polymarket's CLOB matches orders off-chain on Polygon —
8
- // a permission cannot bound the orders your agent signs off-chain.
9
- // Limitless settles bets on-chain on Base, so the kernel sees every action.)
10
- // Chain : Base mainnet
11
- //
12
- // ⚠ WARNING — ABI UNVERIFIED ⚠
13
- // The Limitless exchange contract address and bet-placement function signature
14
- // below are based on published CTF exchange patterns and public documentation.
15
- // They have NOT been independently verified against the deployed contracts.
16
- // YOU MUST verify these before deploying with real funds:
17
- // 1. Find the Limitless exchange contract address on Basescan.
18
- // 2. Read its verified ABI and confirm the buy/place function signature.
19
- // 3. Recompute the selector and update SEL_BUY.
20
- // 4. Confirm the parameter layout matches BetParams below.
21
- // Deploying this contract with an unverified ABI may silently PASS or FAIL
22
- // all dispatches depending on whether the selector matches.
23
- //
24
- // ENFORCES ON-CHAIN (kernel calls evaluate() on every dispatch; false ⇒ dispatch blocked)
25
- // — ASSUMING the unverified ABI above is correct:
26
- // buy(bytes32 conditionId,uint256 amount,uint256 outcomeIndex) selector = keccak256(sig)[0:4]
27
- // • target must be LIMITLESS_EXCHANGE
28
- // • conditionId must be in ALLOWED_CONDITIONS
29
- // • amount ≤ MAX_STAKE
30
- // • outcomeIndex must be in ALLOWED_OUTCOMES
31
- //
32
- // AGENT-ENFORCED / NOT BOUNDED HERE (off-chain — can change without redeploying this contract):
33
- // • Market price / odds (on-chain prediction market prices fluctuate)
34
- // • Timing / frequency of bets
35
- //
36
- // VERIFY BEFORE USE:
37
- // • Confirm Limitless exchange address on Base (Basescan).
38
- // • Confirm buy function signature and compute selector:
39
- // keccak256("buy(bytes32,uint256,uint256)")[0:4] == 0x??? — verify on-chain.
40
- // • Confirm conditionId encoding matches the deployed market IDs.
41
- // • Update this contract if the ABI or parameter order differs.
42
- // ─────────────────────────────────────────────────────────────────────────────
43
-
44
- import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
45
-
46
- contract BoundedBet_Limitless_Base is IPermission {
47
- bytes32 private constant DISCRIMINATOR = keccak256("BoundedBet_Limitless_Base");
48
-
49
- /// @dev ⚠ UNVERIFIED — replace with verified Limitless exchange address on Base.
50
- address public immutable LIMITLESS_EXCHANGE;
51
- mapping(bytes32 => bool) public isAllowedCondition;
52
- uint256 public immutable MAX_STAKE;
53
- mapping(uint256 => bool) public isAllowedOutcome;
54
-
55
- /// @dev ⚠ UNVERIFIED selector. Compute keccak256("buy(bytes32,uint256,uint256)")[0:4]
56
- /// and confirm it matches the deployed Limitless exchange contract before use.
57
- bytes4 private constant SEL_BUY = bytes4(keccak256("buy(bytes32,uint256,uint256)"));
58
-
59
- /// @param limitlessExchange ⚠ VERIFY — Limitless CTF exchange address on Base
60
- /// @param allowedConditions conditionIds (bytes32) of markets the agent may bet on
61
- /// @param maxStake Per-bet stake cap in collateral base units
62
- /// @param allowedOutcomes Outcome indices the agent may select (e.g. [0] for YES only)
63
- constructor(
64
- address limitlessExchange,
65
- bytes32[] memory allowedConditions,
66
- uint256 maxStake,
67
- uint256[] memory allowedOutcomes
68
- ) {
69
- LIMITLESS_EXCHANGE = limitlessExchange;
70
- MAX_STAKE = maxStake;
71
- for (uint256 i = 0; i < allowedConditions.length; i++) {
72
- isAllowedCondition[allowedConditions[i]] = true;
73
- }
74
- for (uint256 i = 0; i < allowedOutcomes.length; i++) {
75
- isAllowedOutcome[allowedOutcomes[i]] = true;
76
- }
77
- }
78
-
79
- function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
80
- if (ctx.target != LIMITLESS_EXCHANGE) return false;
81
- if (ctx.selector != SEL_BUY) return false;
82
- if (txData.length < 4 + 3 * 32) return false;
83
-
84
- // ⚠ Assumes: buy(bytes32 conditionId, uint256 amount, uint256 outcomeIndex)
85
- // Verify parameter order against deployed contract ABI before use.
86
- (bytes32 conditionId, uint256 amount, uint256 outcomeIndex) =
87
- abi.decode(txData[4:], (bytes32, uint256, uint256));
88
-
89
- if (!isAllowedCondition[conditionId]) return false;
90
- if (amount > MAX_STAKE) return false;
91
- if (!isAllowedOutcome[outcomeIndex]) return false;
92
-
93
- return true;
94
- }
95
-
96
- function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
97
- }
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Protocol : Limitless
6
+ // Version : CTF-based prediction market (on-chain settlement on Base)
7
+ // NOT Polymarket (Polymarket's CLOB matches orders off-chain on Polygon —
8
+ // a permission cannot bound the orders your agent signs off-chain.
9
+ // Limitless settles bets on-chain on Base, so the kernel sees every action.)
10
+ // Chain : Base mainnet
11
+ //
12
+ // ⚠ WARNING — ABI UNVERIFIED ⚠
13
+ // The Limitless exchange contract address and bet-placement function signature
14
+ // below are based on published CTF exchange patterns and public documentation.
15
+ // They have NOT been independently verified against the deployed contracts.
16
+ // YOU MUST verify these before deploying with real funds:
17
+ // 1. Find the Limitless exchange contract address on Basescan.
18
+ // 2. Read its verified ABI and confirm the buy/place function signature.
19
+ // 3. Recompute the selector and update SEL_BUY.
20
+ // 4. Confirm the parameter layout matches BetParams below.
21
+ // Deploying this contract with an unverified ABI may silently PASS or FAIL
22
+ // all dispatches depending on whether the selector matches.
23
+ //
24
+ // ENFORCES ON-CHAIN (kernel calls evaluate() on every dispatch; false ⇒ dispatch blocked)
25
+ // — ASSUMING the unverified ABI above is correct:
26
+ // buy(bytes32 conditionId,uint256 amount,uint256 outcomeIndex) selector = keccak256(sig)[0:4]
27
+ // • target must be LIMITLESS_EXCHANGE
28
+ // • conditionId must be in ALLOWED_CONDITIONS
29
+ // • amount ≤ MAX_STAKE
30
+ // • outcomeIndex must be in ALLOWED_OUTCOMES
31
+ //
32
+ // AGENT-ENFORCED / NOT BOUNDED HERE (off-chain — can change without redeploying this contract):
33
+ // • Market price / odds (on-chain prediction market prices fluctuate)
34
+ // • Timing / frequency of bets
35
+ //
36
+ // VERIFY BEFORE USE:
37
+ // • Confirm Limitless exchange address on Base (Basescan).
38
+ // • Confirm buy function signature and compute selector:
39
+ // keccak256("buy(bytes32,uint256,uint256)")[0:4] == 0x??? — verify on-chain.
40
+ // • Confirm conditionId encoding matches the deployed market IDs.
41
+ // • Update this contract if the ABI or parameter order differs.
42
+ // ─────────────────────────────────────────────────────────────────────────────
43
+
44
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
45
+
46
+ contract BoundedBet_Limitless_Base is IPermission {
47
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedBet_Limitless_Base");
48
+
49
+ /// @dev ⚠ UNVERIFIED — replace with verified Limitless exchange address on Base.
50
+ address public immutable LIMITLESS_EXCHANGE;
51
+ mapping(bytes32 => bool) public isAllowedCondition;
52
+ uint256 public immutable MAX_STAKE;
53
+ mapping(uint256 => bool) public isAllowedOutcome;
54
+
55
+ /// @dev ⚠ UNVERIFIED selector. Compute keccak256("buy(bytes32,uint256,uint256)")[0:4]
56
+ /// and confirm it matches the deployed Limitless exchange contract before use.
57
+ bytes4 private constant SEL_BUY = bytes4(keccak256("buy(bytes32,uint256,uint256)"));
58
+
59
+ /// @param limitlessExchange ⚠ VERIFY — Limitless CTF exchange address on Base
60
+ /// @param allowedConditions conditionIds (bytes32) of markets the agent may bet on
61
+ /// @param maxStake Per-bet stake cap in collateral base units
62
+ /// @param allowedOutcomes Outcome indices the agent may select (e.g. [0] for YES only)
63
+ constructor(
64
+ address limitlessExchange,
65
+ bytes32[] memory allowedConditions,
66
+ uint256 maxStake,
67
+ uint256[] memory allowedOutcomes
68
+ ) {
69
+ LIMITLESS_EXCHANGE = limitlessExchange;
70
+ MAX_STAKE = maxStake;
71
+ for (uint256 i = 0; i < allowedConditions.length; i++) {
72
+ isAllowedCondition[allowedConditions[i]] = true;
73
+ }
74
+ for (uint256 i = 0; i < allowedOutcomes.length; i++) {
75
+ isAllowedOutcome[allowedOutcomes[i]] = true;
76
+ }
77
+ }
78
+
79
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
80
+ if (ctx.target != LIMITLESS_EXCHANGE) return false;
81
+ if (ctx.selector != SEL_BUY) return false;
82
+ if (txData.length < 4 + 3 * 32) return false;
83
+
84
+ // ⚠ Assumes: buy(bytes32 conditionId, uint256 amount, uint256 outcomeIndex)
85
+ // Verify parameter order against deployed contract ABI before use.
86
+ (bytes32 conditionId, uint256 amount, uint256 outcomeIndex) =
87
+ abi.decode(txData[4:], (bytes32, uint256, uint256));
88
+
89
+ if (!isAllowedCondition[conditionId]) return false;
90
+ if (amount > MAX_STAKE) return false;
91
+ if (!isAllowedOutcome[outcomeIndex]) return false;
92
+
93
+ return true;
94
+ }
95
+
96
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
97
+ }
@@ -1,94 +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 (42161)
8
- // Target : Aave V3 Pool 0x794a61358D6845594F94dc1DB02A252b5b4814aD (verified on Arbiscan)
9
- //
10
- // ENFORCES ON-CHAIN (kernel calls evaluate() on every dispatch; false ⇒ dispatch blocked):
11
- // borrow(address asset,uint256 amount,uint256 interestRateMode,uint16 referralCode,address onBehalfOf)
12
- // selector 0xa415bcad
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
- // AGENT-ENFORCED / NOT BOUNDED HERE (off-chain — can change without redeploying this 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/supply 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
- }
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 (42161)
8
+ // Target : Aave V3 Pool 0x794a61358D6845594F94dc1DB02A252b5b4814aD (verified on Arbiscan)
9
+ //
10
+ // ENFORCES ON-CHAIN (kernel calls evaluate() on every dispatch; false ⇒ dispatch blocked):
11
+ // borrow(address asset,uint256 amount,uint256 interestRateMode,uint16 referralCode,address onBehalfOf)
12
+ // selector 0xa415bcad
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
+ // AGENT-ENFORCED / NOT BOUNDED HERE (off-chain — can change without redeploying this 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/supply 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
+ }