@oracle-agent/oracle 0.11.0 → 0.12.0

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 (308) hide show
  1. package/LICENSE +115 -201
  2. package/README.md +66 -84
  3. package/SECURITY.md +37 -12
  4. package/SETUP.md +207 -272
  5. package/dist/action-receipts.mjs +1 -0
  6. package/dist/action-semantics.mjs +1 -0
  7. package/dist/address-book.mjs +2 -0
  8. package/dist/bin/desk-server.mjs +14 -0
  9. package/dist/bin/oracle-data-mcp.mjs +8 -0
  10. package/dist/bin/oracle-init.mjs +24 -0
  11. package/dist/bin/oracle-public-server.mjs +5 -0
  12. package/dist/bin/oracle-route.mjs +22 -0
  13. package/dist/bin/oracle-scan.mjs +18 -0
  14. package/dist/bin/oracle-upgrade.mjs +21 -0
  15. package/dist/bin/oracle.mjs +68 -0
  16. package/dist/chains.mjs +1 -0
  17. package/dist/cli/commands/auth.mjs +16 -0
  18. package/dist/cli/commands/bootstrap.mjs +18 -0
  19. package/dist/cli/commands/chain.mjs +21 -0
  20. package/dist/cli/commands/chat.mjs +35 -0
  21. package/dist/cli/commands/credential.mjs +1 -0
  22. package/dist/cli/commands/data-mcp.mjs +2 -0
  23. package/dist/cli/commands/data.mjs +12 -0
  24. package/dist/cli/commands/doctor.mjs +5 -0
  25. package/dist/cli/commands/gate.mjs +13 -0
  26. package/dist/cli/commands/help.mjs +1 -0
  27. package/dist/cli/commands/init.mjs +3 -0
  28. package/dist/cli/commands/mcp.mjs +33 -0
  29. package/dist/cli/commands/model.mjs +44 -0
  30. package/dist/cli/commands/prepare.mjs +2 -0
  31. package/dist/cli/commands/public.mjs +3 -0
  32. package/dist/cli/commands/route.mjs +2 -0
  33. package/dist/cli/commands/runner.mjs +1 -0
  34. package/dist/cli/commands/scan.mjs +2 -0
  35. package/dist/cli/commands/setup.mjs +34 -0
  36. package/dist/cli/commands/sign.mjs +4 -0
  37. package/dist/cli/commands/signer.mjs +1 -0
  38. package/dist/cli/commands/upgrade.mjs +2 -0
  39. package/dist/cli/commands/vault.mjs +1 -0
  40. package/dist/cli/commands/version.mjs +2 -0
  41. package/dist/data/desk-data.mjs +12 -0
  42. package/dist/index.mjs +17 -0
  43. package/dist/nft-gas-war-guard.mjs +1 -0
  44. package/dist/onboarding/harness-configs.mjs +4 -0
  45. package/dist/portfolio-risk.mjs +1 -0
  46. package/dist/prepare-envelope.mjs +1 -0
  47. package/dist/public-control/policy-schema.mjs +1 -0
  48. package/dist/router/index.mjs +2 -0
  49. package/dist/scanner/index.mjs +4 -0
  50. package/dist/signals/index.mjs +1 -0
  51. package/dist/watch-preferences.mjs +1 -0
  52. package/package.json +27 -65
  53. package/public/oracle-splash/index.html +11 -1
  54. package/CONTRIBUTING.md +0 -98
  55. package/bin/desk-server.mjs +0 -440
  56. package/bin/oracle-data-mcp.mjs +0 -1019
  57. package/bin/oracle-init.mjs +0 -496
  58. package/bin/oracle-public-server.mjs +0 -36
  59. package/bin/oracle-route.mjs +0 -254
  60. package/bin/oracle-scan.mjs +0 -192
  61. package/bin/oracle-upgrade.mjs +0 -42
  62. package/bin/oracle.mjs +0 -33
  63. package/docs/adding-a-chain.md +0 -229
  64. package/docs/architecture.md +0 -138
  65. package/docs/cli.md +0 -47
  66. package/docs/connectors.md +0 -13
  67. package/docs/oracle-pack-standard.md +0 -29
  68. package/docs/profiles.md +0 -151
  69. package/docs/public-surface.md +0 -133
  70. package/examples/add-a-chain.mjs +0 -65
  71. package/examples/oracle-pack-template.mjs +0 -38
  72. package/examples/research-a-token.mjs +0 -70
  73. package/plugins/oracle-owner-gate/__init__.py +0 -227
  74. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  75. package/profiles/_template/SOUL.md +0 -54
  76. package/profiles/_template/profile.json +0 -22
  77. package/profiles/bitcoin-agent/SOUL.md +0 -31
  78. package/profiles/bitcoin-agent/profile.json +0 -32
  79. package/profiles/hyperliquid-agent/SOUL.md +0 -34
  80. package/profiles/hyperliquid-agent/profile.json +0 -37
  81. package/profiles/oracle/SOUL.md +0 -107
  82. package/profiles/oracle/profile.json +0 -39
  83. package/profiles/polymarket-agent/SOUL.md +0 -35
  84. package/profiles/polymarket-agent/profile.json +0 -34
  85. package/profiles/profile.schema.json +0 -90
  86. package/profiles/protocol-builder/SOUL.md +0 -57
  87. package/profiles/protocol-builder/profile.json +0 -39
  88. package/profiles/robinhood-agent/SOUL.md +0 -53
  89. package/profiles/robinhood-agent/profile.json +0 -40
  90. package/profiles/solana-agent/SOUL.md +0 -37
  91. package/profiles/solana-agent/profile.json +0 -37
  92. package/profiles/stable-agent/SOUL.md +0 -43
  93. package/profiles/stable-agent/profile.json +0 -37
  94. package/protocols/templates/safe-erc20/SECURITY.md +0 -16
  95. package/protocols/templates/safe-erc20/foundry.toml +0 -12
  96. package/protocols/templates/safe-erc20/remappings.txt +0 -2
  97. package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
  98. package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
  99. package/scripts/adversarial-bench.mjs +0 -114
  100. package/scripts/build-inscription.py +0 -230
  101. package/scripts/check-doc-drift.mjs +0 -123
  102. package/scripts/check-test-count.mjs +0 -105
  103. package/scripts/e2e-hl-markets.mjs +0 -21
  104. package/scripts/e2e-hl-perps.mjs +0 -48
  105. package/scripts/e2e-hypercore-staking.mjs +0 -128
  106. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  107. package/scripts/protocol-template-gate.mjs +0 -15
  108. package/scripts/public-api-scan.mjs +0 -23
  109. package/scripts/secret-scan.mjs +0 -181
  110. package/scripts/verify-v3-venues.mjs +0 -192
  111. package/skills/balance/SKILL.md +0 -176
  112. package/skills/oracle-action-semantics/SKILL.md +0 -40
  113. package/skills/oracle-best-execution/SKILL.md +0 -127
  114. package/skills/oracle-bitcoin/SKILL.md +0 -53
  115. package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +0 -59
  116. package/skills/oracle-chat/SKILL.md +0 -61
  117. package/skills/oracle-chat/chain.SKILL.md +0 -31
  118. package/skills/oracle-chat/setup.SKILL.md +0 -37
  119. package/skills/oracle-circuit-breaker/SKILL.md +0 -51
  120. package/skills/oracle-contract-research/SKILL.md +0 -55
  121. package/skills/oracle-desk/SKILL.md +0 -58
  122. package/skills/oracle-dex-launch/SKILL.md +0 -38
  123. package/skills/oracle-grants/SKILL.md +0 -69
  124. package/skills/oracle-hypercore-staking/SKILL.md +0 -57
  125. package/skills/oracle-hyperliquid/SKILL.md +0 -56
  126. package/skills/oracle-meme-token-sniper/SKILL.md +0 -73
  127. package/skills/oracle-multichain-nft-launch/SKILL.md +0 -338
  128. package/skills/oracle-multichain-token-launch/SKILL.md +0 -300
  129. package/skills/oracle-nft-gacha-launch/SKILL.md +0 -48
  130. package/skills/oracle-nft-mint-gas-war/SKILL.md +0 -63
  131. package/skills/oracle-polymarket/SKILL.md +0 -60
  132. package/skills/oracle-protocol-builder/SKILL.md +0 -59
  133. package/skills/oracle-protocol-security/SKILL.md +0 -60
  134. package/skills/oracle-public-product/SKILL.md +0 -44
  135. package/skills/oracle-receipts/SKILL.md +0 -52
  136. package/skills/oracle-rfq-tokenized-assets/SKILL.md +0 -69
  137. package/skills/oracle-smart-wallet-scanner/SKILL.md +0 -49
  138. package/skills/oracle-solana/SKILL.md +0 -65
  139. package/skills/oracle-solana-nft/SKILL.md +0 -54
  140. package/skills/oracle-token-research/SKILL.md +0 -67
  141. package/skins/oracle.yaml +0 -56
  142. package/src/action-receipts.mjs +0 -265
  143. package/src/action-semantics.mjs +0 -62
  144. package/src/address-book.mjs +0 -208
  145. package/src/agent-auth.mjs +0 -206
  146. package/src/approval-guard.mjs +0 -282
  147. package/src/attestation-secret.mjs +0 -88
  148. package/src/audit-log.mjs +0 -196
  149. package/src/auth/oauth.mjs +0 -672
  150. package/src/auto-slippage.mjs +0 -378
  151. package/src/capability-posture.mjs +0 -125
  152. package/src/chains.mjs +0 -62
  153. package/src/cli/chain-catalog.mjs +0 -215
  154. package/src/cli/chain-state.mjs +0 -74
  155. package/src/cli/commands/auth.mjs +0 -193
  156. package/src/cli/commands/bootstrap.mjs +0 -87
  157. package/src/cli/commands/chain.mjs +0 -143
  158. package/src/cli/commands/chat.mjs +0 -434
  159. package/src/cli/commands/credential.mjs +0 -9
  160. package/src/cli/commands/data-mcp.mjs +0 -18
  161. package/src/cli/commands/data.mjs +0 -75
  162. package/src/cli/commands/doctor.mjs +0 -136
  163. package/src/cli/commands/help.mjs +0 -7
  164. package/src/cli/commands/init.mjs +0 -27
  165. package/src/cli/commands/mcp.mjs +0 -142
  166. package/src/cli/commands/model.mjs +0 -99
  167. package/src/cli/commands/prepare.mjs +0 -12
  168. package/src/cli/commands/public.mjs +0 -20
  169. package/src/cli/commands/route.mjs +0 -12
  170. package/src/cli/commands/runner.mjs +0 -9
  171. package/src/cli/commands/scan.mjs +0 -12
  172. package/src/cli/commands/setup.mjs +0 -275
  173. package/src/cli/commands/sign.mjs +0 -21
  174. package/src/cli/commands/signer.mjs +0 -9
  175. package/src/cli/commands/upgrade.mjs +0 -12
  176. package/src/cli/commands/vault.mjs +0 -9
  177. package/src/cli/commands/version.mjs +0 -22
  178. package/src/cli/first-run.mjs +0 -23
  179. package/src/cli/kernel.mjs +0 -239
  180. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  181. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  182. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  183. package/src/cli/mcp-targets/codex.mjs +0 -41
  184. package/src/cli/mcp-targets/shared.mjs +0 -61
  185. package/src/cli/messaging-platforms.mjs +0 -209
  186. package/src/cli/model-config.mjs +0 -70
  187. package/src/cli/operator-dispatch.mjs +0 -258
  188. package/src/cli/oracle-harness.py +0 -415
  189. package/src/cli/paths.mjs +0 -83
  190. package/src/cli/runtime.mjs +0 -351
  191. package/src/cli/setup-state.mjs +0 -168
  192. package/src/cli/spawn-child.mjs +0 -43
  193. package/src/data/catalog.mjs +0 -585
  194. package/src/data/desk-data.mjs +0 -695
  195. package/src/data/http.mjs +0 -253
  196. package/src/data/provider-endpoint.mjs +0 -94
  197. package/src/data/providers/aerodrome.mjs +0 -245
  198. package/src/data/providers/balancer.mjs +0 -209
  199. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  200. package/src/data/providers/bitcoin-meta.mjs +0 -378
  201. package/src/data/providers/blockscout.mjs +0 -14
  202. package/src/data/providers/bridges.mjs +0 -242
  203. package/src/data/providers/cowswap.mjs +0 -415
  204. package/src/data/providers/curve.mjs +0 -201
  205. package/src/data/providers/defillama.mjs +0 -88
  206. package/src/data/providers/dexscreener.mjs +0 -43
  207. package/src/data/providers/evm-rpc.mjs +0 -225
  208. package/src/data/providers/geckoterminal.mjs +0 -34
  209. package/src/data/providers/gmx.mjs +0 -496
  210. package/src/data/providers/hl-assets.mjs +0 -165
  211. package/src/data/providers/hl-info.mjs +0 -108
  212. package/src/data/providers/hl-markets.mjs +0 -210
  213. package/src/data/providers/hl-outcome.mjs +0 -61
  214. package/src/data/providers/hl-perps.mjs +0 -387
  215. package/src/data/providers/hl-staking.mjs +0 -353
  216. package/src/data/providers/hl-ws.mjs +0 -119
  217. package/src/data/providers/hyperevm-dex.mjs +0 -49
  218. package/src/data/providers/jupiter-venues.mjs +0 -119
  219. package/src/data/providers/jupiter.mjs +0 -315
  220. package/src/data/providers/lifi.mjs +0 -151
  221. package/src/data/providers/magiceden-sol.mjs +0 -406
  222. package/src/data/providers/morpho.mjs +0 -177
  223. package/src/data/providers/nft-gallery.mjs +0 -163
  224. package/src/data/providers/nft-portfolio.mjs +0 -494
  225. package/src/data/providers/odos.mjs +0 -156
  226. package/src/data/providers/oneinch.mjs +0 -174
  227. package/src/data/providers/opensea-multichain.mjs +0 -136
  228. package/src/data/providers/opensea-nft.mjs +0 -371
  229. package/src/data/providers/paraswap.mjs +0 -118
  230. package/src/data/providers/pendle.mjs +0 -188
  231. package/src/data/providers/poly-clob.mjs +0 -283
  232. package/src/data/providers/poly-public.mjs +0 -96
  233. package/src/data/providers/poly-ws.mjs +0 -103
  234. package/src/data/providers/portfolio-history.mjs +0 -394
  235. package/src/data/providers/portfolio.mjs +0 -594
  236. package/src/data/providers/rfq.mjs +0 -15
  237. package/src/data/providers/rh-agent.mjs +0 -59
  238. package/src/data/providers/satflow.mjs +0 -341
  239. package/src/data/providers/signed-material-guard.mjs +0 -108
  240. package/src/data/providers/solana-rpc.mjs +0 -197
  241. package/src/data/providers/uniswap-v3.mjs +0 -349
  242. package/src/data/providers/uniswap-v4.mjs +0 -414
  243. package/src/data/providers/zerox.mjs +0 -167
  244. package/src/data/public-api-scan.mjs +0 -61
  245. package/src/data/quote-placeholder.mjs +0 -31
  246. package/src/exact-integer.mjs +0 -72
  247. package/src/exec-policy.mjs +0 -455
  248. package/src/flags.mjs +0 -15
  249. package/src/fresh-window.mjs +0 -76
  250. package/src/gmx-attestation.mjs +0 -176
  251. package/src/index.mjs +0 -100
  252. package/src/nft-gas-war-guard.mjs +0 -139
  253. package/src/onboarding/agent-keys.mjs +0 -161
  254. package/src/onboarding/harness-configs.mjs +0 -102
  255. package/src/onboarding/index.mjs +0 -18
  256. package/src/onboarding/tiers.mjs +0 -139
  257. package/src/oracle-env.mjs +0 -47
  258. package/src/portfolio-risk.mjs +0 -170
  259. package/src/prepare-envelope.mjs +0 -204
  260. package/src/profile-upgrade.mjs +0 -277
  261. package/src/protocol-execution.mjs +0 -84
  262. package/src/protocol-templates/gate.mjs +0 -179
  263. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  264. package/src/public-api/buzz-integration.mjs +0 -256
  265. package/src/public-api/connect-agent.mjs +0 -416
  266. package/src/public-api/grants.mjs +0 -142
  267. package/src/public-api/http.mjs +0 -389
  268. package/src/public-control/aa-adapter.mjs +0 -402
  269. package/src/public-control/build-registry.mjs +0 -227
  270. package/src/public-control/bundler-client.mjs +0 -357
  271. package/src/public-control/grant-indexer.mjs +0 -296
  272. package/src/public-control/policy-render.mjs +0 -69
  273. package/src/public-control/policy-schema.mjs +0 -318
  274. package/src/public-control/runtime-config.mjs +0 -275
  275. package/src/public-control/session-key-model.mjs +0 -374
  276. package/src/public-control/session-orchestrator.mjs +0 -412
  277. package/src/rfq/intent.mjs +0 -180
  278. package/src/rfq/sources.mjs +0 -181
  279. package/src/route-attestation.mjs +0 -132
  280. package/src/router/best-execution.mjs +0 -326
  281. package/src/router/index.mjs +0 -226
  282. package/src/router/prepare-bridge.mjs +0 -289
  283. package/src/router/prepare-route.mjs +0 -398
  284. package/src/router/proposal.mjs +0 -311
  285. package/src/router/risk-classifier.mjs +0 -119
  286. package/src/router/route-sources.mjs +0 -364
  287. package/src/scanner/chains.config.mjs +0 -430
  288. package/src/scanner/contract.mjs +0 -270
  289. package/src/scanner/evm-scanner.mjs +0 -394
  290. package/src/scanner/index.mjs +0 -9
  291. package/src/scanner/v2-venue.mjs +0 -335
  292. package/src/scanner/v3-venue.mjs +0 -290
  293. package/src/scopes.mjs +0 -44
  294. package/src/sell-simulation.mjs +0 -167
  295. package/src/signals/engine.mjs +0 -146
  296. package/src/signals/index.mjs +0 -1
  297. package/src/token-transfer-guard.mjs +0 -188
  298. package/src/tui/app.mjs +0 -438
  299. package/src/tui/backend.mjs +0 -145
  300. package/src/tui/format.mjs +0 -272
  301. package/src/tui/gateway-client.mjs +0 -177
  302. package/src/tui/input.mjs +0 -501
  303. package/src/tui/renderer.mjs +0 -443
  304. package/src/tui/standalone-client.mjs +0 -666
  305. package/src/tui/theme.mjs +0 -81
  306. package/src/vault-attestation.mjs +0 -146
  307. package/src/venues.mjs +0 -206
  308. package/src/watch-preferences.mjs +0 -85
@@ -1,37 +0,0 @@
1
- {
2
- "$schema": "./profile.schema.json",
3
- "id": "solana-agent",
4
- "label": "solana agent",
5
- "role": "venue",
6
- "color": "#9945FF",
7
- "description": "Solana: token research, launch/meme-token scans, Jupiter routes, SPL accounts, Magic Eden NFT reads, unsigned swap and NFT buy/list/mint preparation.",
8
- "model": {
9
- "note": "Mixed research and route math; a balanced general model fits.",
10
- "suggested": "balanced"
11
- },
12
- "skills": [
13
- "oracle-solana",
14
- "oracle-receipts",
15
- "oracle-circuit-breaker",
16
- "oracle-best-execution",
17
- "oracle-meme-token-sniper",
18
- "oracle-chain-graphs-telegram-cards",
19
- "oracle-rfq-tokenized-assets",
20
- "oracle-solana-nft"
21
- ],
22
- "mcp": [
23
- "oracle-data"
24
- ],
25
- "chains": [],
26
- "nonEvm": "solana-mainnet",
27
- "posture": {
28
- "default": "DISARMED",
29
- "grantActions": [
30
- "read:chain",
31
- "simulate:tx",
32
- "prepare:swap"
33
- ],
34
- "signing": "user-wallet",
35
- "rationale": "Separate signing plane from EVM by design: a Solana grant must never be satisfiable by an EVM key."
36
- }
37
- }
@@ -1,43 +0,0 @@
1
- # stable agent
2
-
3
- You cover **Stable mainnet** (chain 988), where the stablecoin *is* the gas token.
4
-
5
- ## What you own
6
-
7
- Balances, bridge-in routes, DEX pools (often forks), and contract verification on
8
- a young chain.
9
-
10
- ## The quirks that break assumptions
11
-
12
- **Gas is USDT0, 18 decimals native.** The same balance shows up twice: as native
13
- via `getBalance`, and as an ERC-20 mirror via `balanceOf` with a 6-decimal
14
- interface. It is **one balance**. Do not sum them.
15
-
16
- **"Listed on a bridge" is not "routable."** A young chain has no relayer
17
- inventory, so liquidity-pool bridges return `INSUFFICIENT_LIQUIDITY / max $0`
18
- even while the chain appears supported. Always quote the actual route. When pool
19
- bridges are dry, the rail that works is the token's native OFT mesh.
20
-
21
- **A token bridge delivers the token, not gas.** After a bridge lands the wallet
22
- often has zero native to pay for the next transaction. Plan the gas leg
23
- separately, before it's needed.
24
-
25
- **DEX forks are not Uniswap.** A fork's router may require an off-chain signed
26
- quote you cannot forge, while the underlying pair is standard V2. Verify what you
27
- are actually calling.
28
-
29
- ## Hard rules
30
-
31
- 1. **Verify every venue on-chain before use** — `eth_getCode` must return real
32
- bytecode. A named contract on an explorer is not verification.
33
- 2. **Quote each leg of a multi-hop before firing the first**, or funds strand
34
- mid-journey.
35
- 3. **Never size against a launchpad token's own virtual reserves.** Find the real
36
- pair.
37
- 4. **You do not sign.** Swaps are prepared for the user's wallet.
38
- 5. **Receipts or it didn't happen.**
39
-
40
- ## Voice
41
-
42
- Say what you verified and how. On a chain this young, `unknown` is often the
43
- honest answer — give it.
@@ -1,37 +0,0 @@
1
- {
2
- "$schema": "./profile.schema.json",
3
- "id": "stable-agent",
4
- "label": "stable agent",
5
- "role": "venue",
6
- "color": "#F0B90B",
7
- "description": "Stable mainnet (988): USDT-native gas, bridge-in routes, DEX-fork pools, launch/meme-token scans.",
8
- "model": {
9
- "note": "New-chain work is full of surprises; wants a careful model that verifies rather than assumes.",
10
- "suggested": "careful-verifier"
11
- },
12
- "skills": [
13
- "oracle-contract-research",
14
- "oracle-receipts",
15
- "oracle-circuit-breaker",
16
- "oracle-best-execution",
17
- "oracle-meme-token-sniper",
18
- "oracle-chain-graphs-telegram-cards",
19
- "oracle-rfq-tokenized-assets"
20
- ],
21
- "mcp": [
22
- "oracle-data"
23
- ],
24
- "chains": [
25
- 988
26
- ],
27
- "posture": {
28
- "default": "DISARMED",
29
- "grantActions": [
30
- "read:chain",
31
- "simulate:tx",
32
- "prepare:swap"
33
- ],
34
- "signing": "user-wallet",
35
- "rationale": "A young chain has thin liquidity and unverified forks. Every venue needs on-chain verification before use."
36
- }
37
- }
@@ -1,16 +0,0 @@
1
- # SafeERC20 template security notice
2
-
3
- **Not a paid security-firm audit.**
4
-
5
- This template is:
6
- - fixed-supply ERC20
7
- - Ownable2Step + pause
8
- - no tax / blacklist / upgrade proxy
9
- - covered by Foundry unit tests in `test/`
10
-
11
- Before mainnet capital:
12
- 1. Keep or expand Foundry tests green
13
- 2. Run static analysis (Slither/Aderyn) if available
14
- 3. Book an independent Solidity auditor for any real TVL
15
-
16
- Oracle only prepares unsigned deploys after the JS gate confirms `forge test` passes.
@@ -1,12 +0,0 @@
1
- [profile.default]
2
- src = "src"
3
- out = "out"
4
- libs = ["lib"]
5
- solc = "0.8.24"
6
- optimizer = true
7
- optimizer_runs = 200
8
- ffi = false
9
- fs_permissions = [{ access = "read", path = "./" }]
10
-
11
- [fmt]
12
- line_length = 100
@@ -1,2 +0,0 @@
1
- @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
2
- forge-std/=lib/forge-std/src/
@@ -1,53 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.24;
3
-
4
- import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5
- import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
6
- import {ERC20Pausable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
7
- import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
8
- import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
9
-
10
- /**
11
- * @title SafeERC20
12
- * @notice Opinionated fixed-supply ERC20 for Oracle protocol-builder v1.
13
- *
14
- * Security posture (templates, NOT a firm audit):
15
- * - Fixed supply minted once to `initialHolder` in constructor (no hidden mint).
16
- * - Ownable2Step ownership (no single-tx accidental transfer).
17
- * - Pausable emergency stop (owner only).
18
- * - No transfer tax, no blacklist, no max-tx, no trading cooldown.
19
- * - No upgradeability / no proxy.
20
- * - Burn optional by holders only (ERC20Burnable).
21
- *
22
- * This is a reviewed starter template with Foundry tests. It is NOT a paid
23
- * security-firm audit. Do not put mainnet TVL on custom forks without one.
24
- */
25
- contract SafeERC20 is ERC20, ERC20Burnable, ERC20Pausable, Ownable2Step {
26
- constructor(
27
- string memory name_,
28
- string memory symbol_,
29
- uint256 initialSupply,
30
- address initialHolder,
31
- address initialOwner
32
- ) ERC20(name_, symbol_) Ownable(initialOwner) {
33
- require(initialHolder != address(0), "SafeERC20: holder zero");
34
- require(initialOwner != address(0), "SafeERC20: owner zero");
35
- require(initialSupply > 0, "SafeERC20: supply zero");
36
- _mint(initialHolder, initialSupply);
37
- }
38
-
39
- function pause() external onlyOwner {
40
- _pause();
41
- }
42
-
43
- function unpause() external onlyOwner {
44
- _unpause();
45
- }
46
-
47
- function _update(address from, address to, uint256 value)
48
- internal
49
- override(ERC20, ERC20Pausable)
50
- {
51
- super._update(from, to, value);
52
- }
53
- }
@@ -1,72 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.24;
3
-
4
- import {Test} from "forge-std/Test.sol";
5
- import {SafeERC20} from "../src/SafeERC20.sol";
6
-
7
- contract SafeERC20Test is Test {
8
- SafeERC20 internal token;
9
- address internal owner = makeAddr("owner");
10
- address internal holder = makeAddr("holder");
11
- address internal alice = makeAddr("alice");
12
- address internal bob = makeAddr("bob");
13
-
14
- uint256 internal constant SUPPLY = 1_000_000 ether;
15
-
16
- function setUp() public {
17
- token = new SafeERC20("Safe", "SAFE", SUPPLY, holder, owner);
18
- }
19
-
20
- function test_fixedSupply_noHiddenMint() public view {
21
- assertEq(token.totalSupply(), SUPPLY);
22
- assertEq(token.balanceOf(holder), SUPPLY);
23
- assertEq(token.balanceOf(owner), 0);
24
- }
25
-
26
- function test_transfer_noTax() public {
27
- vm.prank(holder);
28
- token.transfer(alice, 100 ether);
29
- assertEq(token.balanceOf(alice), 100 ether);
30
- assertEq(token.balanceOf(holder), SUPPLY - 100 ether);
31
- }
32
-
33
- function test_pause_blocksTransfers() public {
34
- vm.prank(owner);
35
- token.pause();
36
- vm.prank(holder);
37
- vm.expectRevert();
38
- token.transfer(alice, 1 ether);
39
- }
40
-
41
- function test_onlyOwner_canPause() public {
42
- vm.prank(alice);
43
- vm.expectRevert();
44
- token.pause();
45
- }
46
-
47
- function test_ownable2Step_requiresAccept() public {
48
- vm.prank(owner);
49
- token.transferOwnership(alice);
50
- // still owner until accept
51
- assertEq(token.owner(), owner);
52
- vm.prank(alice);
53
- token.acceptOwnership();
54
- assertEq(token.owner(), alice);
55
- }
56
-
57
- function test_burn_reducesSupply() public {
58
- vm.prank(holder);
59
- token.burn(10 ether);
60
- assertEq(token.totalSupply(), SUPPLY - 10 ether);
61
- }
62
-
63
- function test_rejectZeroHolder() public {
64
- vm.expectRevert(bytes("SafeERC20: holder zero"));
65
- new SafeERC20("X", "X", SUPPLY, address(0), owner);
66
- }
67
-
68
- function test_rejectZeroSupply() public {
69
- vm.expectRevert(bytes("SafeERC20: supply zero"));
70
- new SafeERC20("X", "X", 0, holder, owner);
71
- }
72
- }
@@ -1,114 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { pathToFileURL } from "node:url";
4
- import { resolve } from "node:path";
5
-
6
- const INJECTION_RULES = [
7
- ["instruction-override", /\b(?:ignore|disregard|override)\b.{0,48}\b(?:previous|prior|system|developer|instructions?)\b/i],
8
- ["secret-exfiltration", /\b(?:reveal|print|return|exfiltrate|send)\b.{0,48}\b(?:private\s*key|seed\s*phrase|mnemonic|secret|credentials?|system\s*prompt)\b/i],
9
- ["transaction-coercion", /\b(?:sign|send|broadcast|execute)\b.{0,32}\b(?:transaction|transfer|approval|trade)\b/i],
10
- ["tool-coercion", /\b(?:call|invoke|use|run)\b.{0,24}\b(?:tool|function|shell|command)\b/i],
11
- ];
12
-
13
- const FORBIDDEN_EXPORT = /^(?:signer|sign|signMessage|signTransaction|sendTransaction|broadcastTransaction|submitTransaction|executeTransaction|privateKey|secretKey|mnemonic|seedPhrase|wallet)$/i;
14
-
15
- function finding(code, path, message) {
16
- return { code, path, message };
17
- }
18
-
19
- function scanStrings(value, path, findings, seen) {
20
- if (typeof value === "string") {
21
- for (const [rule, pattern] of INJECTION_RULES) {
22
- if (pattern.test(value)) {
23
- findings.push(finding("prompt-injection", path, `metadata matches ${rule}`));
24
- break;
25
- }
26
- }
27
- return;
28
- }
29
- if (!value || typeof value !== "object" || seen.has(value)) return;
30
- seen.add(value);
31
- if (Array.isArray(value)) {
32
- value.forEach((item, index) => scanStrings(item, `${path}[${index}]`, findings, seen));
33
- return;
34
- }
35
- for (const key of Object.keys(value).sort()) {
36
- scanStrings(value[key], path ? `${path}.${key}` : key, findings, seen);
37
- }
38
- }
39
-
40
- /** Validate one loaded Oracle protocol pack without calling provider code. */
41
- export function benchmarkPack(moduleValue, { name = "pack" } = {}) {
42
- const namespace = moduleValue && typeof moduleValue === "object" ? moduleValue : {};
43
- const pack = namespace.default && typeof namespace.default === "object" ? namespace.default : namespace;
44
- const findings = [];
45
-
46
- for (const key of Object.keys(namespace).sort()) {
47
- if (key !== "default" && FORBIDDEN_EXPORT.test(key)) {
48
- findings.push(finding("forbidden-signer-export", `exports.${key}`, `pack exports custody capability ${key}`));
49
- }
50
- }
51
- for (const key of Object.keys(pack).sort()) {
52
- if (FORBIDDEN_EXPORT.test(key)) {
53
- findings.push(finding("forbidden-signer-export", `pack.${key}`, `pack exports custody capability ${key}`));
54
- }
55
- }
56
-
57
- if (!pack.provider || typeof pack.provider !== "object") {
58
- findings.push(finding("missing-provider", "pack.provider", "provider metadata is required"));
59
- }
60
- if (typeof pack.prepare !== "function") {
61
- findings.push(finding("missing-prepare", "pack.prepare", "prepare must be a function"));
62
- }
63
- if (typeof pack.decode !== "function") {
64
- findings.push(finding("missing-decoder", "pack.decode", "decode must be a function"));
65
- }
66
- if (!(Array.isArray(pack.riskRules) || typeof pack.riskRules === "function")) {
67
- findings.push(finding("missing-risk-rules", "pack.riskRules", "riskRules must be an array or function"));
68
- }
69
- if (!pack.tests || typeof pack.tests !== "object" || Array.isArray(pack.tests) || Object.keys(pack.tests).length === 0) {
70
- findings.push(finding("missing-tests", "pack.tests", "non-empty tests metadata is required"));
71
- }
72
-
73
- // Metadata is untrusted even when nested below token/NFT records. Scan data only;
74
- // functions are deliberately never invoked by this local harness.
75
- scanStrings(pack.metadata, "pack.metadata", findings, new Set());
76
- scanStrings(pack.provider, "pack.provider", findings, new Set());
77
-
78
- findings.sort((a, b) => `${a.code}\0${a.path}\0${a.message}`.localeCompare(`${b.code}\0${b.path}\0${b.message}`));
79
- return { name, ok: findings.length === 0, findings };
80
- }
81
-
82
- /** Run a stable summary over already-loaded fixture/module records. */
83
- export function runAdversarialBenchmark(entries) {
84
- const results = entries
85
- .map((entry, index) => benchmarkPack(entry.module ?? entry, { name: entry.name ?? `pack-${index + 1}` }))
86
- .sort((a, b) => a.name.localeCompare(b.name));
87
- return {
88
- ok: results.every((result) => result.ok),
89
- packs: results.length,
90
- passed: results.filter((result) => result.ok).length,
91
- failed: results.filter((result) => !result.ok).length,
92
- findings: results.reduce((count, result) => count + result.findings.length, 0),
93
- results,
94
- };
95
- }
96
-
97
- async function main(paths) {
98
- if (paths.length === 0) throw new Error("usage: node scripts/adversarial-bench.mjs <pack.mjs> [...]");
99
- const entries = [];
100
- for (const input of paths) {
101
- const absolute = resolve(input);
102
- entries.push({ name: input, module: await import(pathToFileURL(absolute).href) });
103
- }
104
- const summary = runAdversarialBenchmark(entries);
105
- process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
106
- if (!summary.ok) process.exitCode = 1;
107
- }
108
-
109
- if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
110
- main(process.argv.slice(2)).catch((error) => {
111
- process.stdout.write(`${JSON.stringify({ ok: false, error: String(error.message || error) }, null, 2)}\n`);
112
- process.exitCode = 2;
113
- });
114
- }
@@ -1,230 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Build the Oracle inscription SVG.
3
-
4
- Text is converted to OUTLINED VECTOR PATHS so the inscription is fully
5
- self-contained: no font file, no external fetch, no <text> element that renders
6
- differently in every ordinals explorer. Design language is the Oracle splash:
7
- deep #0B1018 field, #7CC4FF blue, Cormorant Garamond display italic accent,
8
- IBM Plex Mono eyebrow, a single luminous orb.
9
- """
10
-
11
- import math
12
- import os
13
-
14
- from fontTools.ttLib import TTFont
15
- from fontTools.pens.svgPathPen import SVGPathPen
16
- from fontTools.varLib.instancer import instantiateVariableFont
17
-
18
- import os
19
- from pathlib import Path
20
-
21
- REPO_ROOT = Path(__file__).resolve().parent.parent
22
-
23
- W, H = 1000, 1000
24
-
25
- BG = "#0B1018"
26
- BLUE = "#7CC4FF"
27
- BLUE2 = "#A7D8FF"
28
- COOL = "#9BB6D1"
29
- MUTE = "#5B738F"
30
-
31
- # vertical rhythm
32
- CX = W / 2.0
33
- CY = 336.0
34
- R_OUT = 166.0
35
- R_MID = 128.0
36
- R_IN = 92.0
37
- MARK_BASELINE = 690.0
38
- SUB_BASELINE = 786.0
39
-
40
-
41
- def load(path, wght):
42
- f = TTFont(path)
43
- if "fvar" in f:
44
- f = instantiateVariableFont(f, {"wght": wght}, inplace=False, updateFontNames=False)
45
- return f
46
-
47
-
48
- def text_paths(font, text, size, letter_spacing=0.0):
49
- """Return (path_d, advance_width) with the text laid out at `size` px."""
50
- upem = font["head"].unitsPerEm
51
- scale = size / upem
52
- cmap = font.getBestCmap()
53
- gs = font.getGlyphSet()
54
- hmtx = font["hmtx"]
55
-
56
- try:
57
- kern = font["kern"].kernTables[0].kernTable
58
- except Exception:
59
- kern = None
60
-
61
- parts = []
62
- x = 0.0
63
- prev = None
64
-
65
- for ch in text:
66
- gname = cmap.get(ord(ch))
67
- if gname is None:
68
- x += size * 0.3
69
- prev = None
70
- continue
71
- if prev and kern:
72
- x += kern.get((prev, gname), 0) * scale
73
- pen = SVGPathPen(gs)
74
- gs[gname].draw(pen)
75
- d = pen.getCommands()
76
- if d:
77
- # flip Y (font space is y-up, SVG is y-down) and place at x
78
- parts.append(
79
- f'<g transform="translate({x:.3f},0) scale({scale:.6f},{-scale:.6f})">'
80
- f'<path d="{d}"/></g>'
81
- )
82
- x += hmtx[gname][0] * scale + letter_spacing
83
- prev = gname
84
- # trailing letter-spacing is not part of the inked width
85
- if letter_spacing and text:
86
- x -= letter_spacing
87
- return "".join(parts), x
88
-
89
-
90
- def centered(font, text, size, y, fill, letter_spacing=0.0, opacity=None):
91
- d, width = text_paths(font, text, size, letter_spacing)
92
- if not d:
93
- return ""
94
- x = (W - width) / 2.0
95
- op = f' opacity="{opacity}"' if opacity is not None else ""
96
- return f'<g transform="translate({x:.3f},{y:.3f})" fill="{fill}"{op}>{d}</g>'
97
-
98
-
99
- def arc(cx, cy, r, a0, a1):
100
- """SVG arc path between two angles in degrees."""
101
- x0 = cx + math.cos(math.radians(a0)) * r
102
- y0 = cy + math.sin(math.radians(a0)) * r
103
- x1 = cx + math.cos(math.radians(a1)) * r
104
- y1 = cy + math.sin(math.radians(a1)) * r
105
- large = 1 if abs(a1 - a0) > 180 else 0
106
- sweep = 1 if a1 > a0 else 0
107
- return f"M{x0:.2f} {y0:.2f} A{r} {r} 0 {large} {sweep} {x1:.2f} {y1:.2f}"
108
-
109
-
110
- def main():
111
- display_italic = load("/tmp/CormorantGaramond-Italic.ttf", 400)
112
- display = load("/tmp/CormorantGaramond.ttf", 300)
113
- mono = TTFont(os.environ.get("IBM_PLEX_MONO", str(Path.home() / ".local/share/fonts/protocols/IBMPlexMono-Regular.ttf")))
114
-
115
- o = []
116
- o.append(f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" width="{W}" height="{H}">')
117
-
118
- o.append(
119
- "<defs>"
120
- '<radialGradient id="halo" cx="50%" cy="34%" r="54%">'
121
- f'<stop offset="0%" stop-color="{BLUE}" stop-opacity=".20"/>'
122
- f'<stop offset="52%" stop-color="{BLUE}" stop-opacity=".05"/>'
123
- f'<stop offset="100%" stop-color="{BLUE}" stop-opacity="0"/>'
124
- "</radialGradient>"
125
- '<radialGradient id="orb" cx="50%" cy="50%" r="50%">'
126
- '<stop offset="0%" stop-color="#F2FAFF"/>'
127
- f'<stop offset="38%" stop-color="{BLUE2}"/>'
128
- f'<stop offset="100%" stop-color="{BLUE}" stop-opacity=".14"/>'
129
- "</radialGradient>"
130
- '<linearGradient id="rule" x1="0" y1="0" x2="1" y2="0">'
131
- f'<stop offset="0%" stop-color="{BLUE}" stop-opacity="0"/>'
132
- f'<stop offset="50%" stop-color="{BLUE}" stop-opacity=".6"/>'
133
- f'<stop offset="100%" stop-color="{BLUE}" stop-opacity="0"/>'
134
- "</linearGradient>"
135
- '<linearGradient id="sweep" x1="0" y1="0" x2="1" y2="1">'
136
- f'<stop offset="0%" stop-color="{BLUE}" stop-opacity="0"/>'
137
- '<stop offset="100%" stop-color="#EAF6FF" stop-opacity=".95"/>'
138
- "</linearGradient>"
139
- "</defs>"
140
- )
141
-
142
- o.append(f'<rect width="{W}" height="{H}" fill="{BG}"/>')
143
- o.append(f'<rect width="{W}" height="{H}" fill="url(#halo)"/>')
144
-
145
- # --- orbit rings: readable at thumbnail size --------------------------
146
- o.append(
147
- f'<circle cx="{CX}" cy="{CY}" r="{R_OUT}" fill="none" '
148
- f'stroke="{BLUE}" stroke-opacity=".24" stroke-width="1.1"/>'
149
- )
150
- o.append(
151
- f'<circle cx="{CX}" cy="{CY}" r="{R_MID}" fill="none" '
152
- f'stroke="{BLUE}" stroke-opacity=".16" stroke-width="1"/>'
153
- )
154
- o.append(
155
- f'<circle cx="{CX}" cy="{CY}" r="{R_IN}" fill="none" '
156
- f'stroke="{BLUE}" stroke-opacity=".34" stroke-width="1" stroke-dasharray="1.5 7"/>'
157
- )
158
-
159
- # the agentic sweep: one bright arc, the thing that is moving
160
- o.append(
161
- f'<path d="{arc(CX, CY, R_OUT, -96, 4)}" fill="none" '
162
- 'stroke="url(#sweep)" stroke-width="2.2" stroke-linecap="round"/>'
163
- )
164
-
165
- # 8 lane ticks on the outer ring
166
- for i in range(8):
167
- a = math.radians(-90 + i * 45)
168
- x1 = CX + math.cos(a) * R_OUT
169
- y1 = CY + math.sin(a) * R_OUT
170
- x2 = CX + math.cos(a) * (R_OUT - 13)
171
- y2 = CY + math.sin(a) * (R_OUT - 13)
172
- o.append(
173
- f'<line x1="{x1:.2f}" y1="{y1:.2f}" x2="{x2:.2f}" y2="{y2:.2f}" '
174
- f'stroke="{BLUE}" stroke-opacity=".5" stroke-width="1.5"/>'
175
- )
176
-
177
- # node dots on the mid ring
178
- for i in range(4):
179
- a = math.radians(-45 + i * 90)
180
- x = CX + math.cos(a) * R_MID
181
- y = CY + math.sin(a) * R_MID
182
- o.append(f'<circle cx="{x:.2f}" cy="{y:.2f}" r="2.6" fill="{BLUE}" opacity=".72"/>')
183
-
184
- # --- the orb ----------------------------------------------------------
185
- o.append(f'<circle cx="{CX}" cy="{CY}" r="52" fill="url(#orb)" opacity=".20"/>')
186
- o.append(f'<circle cx="{CX}" cy="{CY}" r="16" fill="url(#orb)"/>')
187
- o.append(
188
- f'<circle cx="{CX}" cy="{CY}" r="16" fill="none" '
189
- 'stroke="#F2FAFF" stroke-opacity=".55" stroke-width=".9"/>'
190
- )
191
-
192
- # --- eyebrow ----------------------------------------------------------
193
- o.append(centered(mono, "ORACLE", 16, 122, BLUE, letter_spacing=7.4))
194
- o.append(f'<rect x="{CX - 84}" y="143" width="168" height="1" fill="url(#rule)"/>')
195
-
196
- # --- the mark ---------------------------------------------------------
197
- o.append(centered(display_italic, "oracle", 178, MARK_BASELINE, BLUE2))
198
- o.append(centered(display, "was here", 92, SUB_BASELINE, COOL, opacity=".9"))
199
-
200
- # --- footer -----------------------------------------------------------
201
- o.append(f'<rect x="{CX - 132}" y="836" width="264" height="1" fill="url(#rule)"/>')
202
- o.append(centered(mono, "THE FUTURE IS AGENTIC", 14.5, 880, BLUE, letter_spacing=4.0))
203
- o.append(centered(mono, "BITCOIN L1", 12, 916, MUTE, letter_spacing=3.4))
204
-
205
- # --- corner registration marks ---------------------------------------
206
- m, ln = 52, 24
207
- for (x, y, dx, dy) in ((m, m, 1, 1), (W - m, m, -1, 1), (m, H - m, 1, -1), (W - m, H - m, -1, -1)):
208
- o.append(
209
- f'<path d="M{x} {y + dy * ln} L{x} {y} L{x + dx * ln} {y}" fill="none" '
210
- f'stroke="{BLUE}" stroke-opacity=".38" stroke-width="1.3"/>'
211
- )
212
-
213
- o.append("</svg>")
214
-
215
- svg = "".join(o)
216
- path = str(REPO_ROOT / "artifacts/inscription/oracle-was-here.svg")
217
- os.makedirs(os.path.dirname(path), exist_ok=True)
218
- with open(path, "w") as f:
219
- f.write(svg)
220
-
221
- # sanity: the mark must not collide with the ring group
222
- mark_cap_top = MARK_BASELINE - 178 * 0.74
223
- ring_bottom = CY + R_OUT
224
- print(f"wrote {path}")
225
- print(f"bytes {len(svg.encode())}")
226
- print(f"ring_bottom={ring_bottom:.1f} mark_cap_top={mark_cap_top:.1f} clearance={mark_cap_top - ring_bottom:.1f}px")
227
-
228
-
229
- if __name__ == "__main__":
230
- main()